Metadata-Version: 2.4
Name: mpac-mcp
Version: 0.2.6
Summary: MCP bridge for MPAC: coordinate coding agents working on the same repository
Author-email: Kaiyang Qian <kaiyang.2.qian@ucdenver.edu>
License: Apache-2.0
Project-URL: Homepage, https://github.com/KaiyangQ/mpac-mcp
Project-URL: Repository, https://github.com/KaiyangQ/mpac-mcp
Project-URL: Paper, https://arxiv.org/abs/2604.09744
Project-URL: MPAC Protocol, https://github.com/KaiyangQ/mpac-protocol
Project-URL: Issues, https://github.com/KaiyangQ/mpac-mcp/issues
Keywords: mpac,mcp,multi-agent,agent-coordination,claude-code,cursor,ai-agents,coordination
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: websockets>=12.0
Requires-Dist: mcp>=1.0.0
Requires-Dist: mpac>=0.2.2
Requires-Dist: httpx>=0.27

# mpac-mcp

[![arXiv](https://img.shields.io/badge/arXiv-2604.09744-b31b1b.svg)](https://arxiv.org/abs/2604.09744)
[![PyPI](https://img.shields.io/pypi/v/mpac-mcp.svg)](https://pypi.org/project/mpac-mcp/)

📄 **Paper:** [MPAC: A Multi-Principal Agent Coordination Protocol for Interoperable Multi-Agent Collaboration](https://arxiv.org/abs/2604.09744) (arXiv:2604.09744)

`mpac-mcp` is the MCP-facing bridge for MPAC — it lets MCP-aware coding
clients (Claude Code, Cursor, any MCP host) participate in an MPAC
coordination session without re-implementing the protocol themselves.
The underlying protocol and reference runtime live in
[`mpac-protocol`](https://github.com/KaiyangQ/mpac-protocol) / the
[`mpac`](https://pypi.org/project/mpac/) package.

It does not re-implement the coordination protocol. Instead it:

- detects the current repository context
- ensures a local MPAC sidecar is running
- queries the sidecar for shared coordination state
- exposes high-level tools to MCP-compatible coding clients

All bundled smoke scripts now run against an isolated scratch workspace copied
from the requested repo path, so repeated runs do not inherit stale conflicts
or frozen scope from a long-lived sidecar session.

## Current scope

This initial scaffold focuses on the shortest end-to-end path:

- local sidecar auto-discovery / auto-start
- repository-root detection
- session summary query
- first MCP tools:
  - `who_is_working`
  - `begin_task`
  - `check_overlap`
  - `get_file_state`
  - `ack_conflict`
  - `submit_change`
  - `yield_task`
  - `escalate_conflict`
  - `resolve_conflict`
  - `take_over_task`
- a Milestone 0 validation script for "two processes share one local coordinator"
- an end-to-end smoke script for "one external client + one MCP-owned task"
- an end-to-end smoke script for "begin task -> submit change -> yield task"
- an end-to-end smoke script for "ack -> escalate -> resolve"
- an end-to-end smoke script for "suspend -> claim -> take over"

## Multi-tenant Hosted Mode (Authenticated Profile)

When deploying a hosted coordinator for multiple projects/teams:

1. Set `MPAC_TOKEN_TABLE` as a JSON env var mapping bearer tokens to allowed sessions:
   ```json
   {
     "<token-for-alice>": {"allowed_sessions": ["proj-alpha"], "roles": ["contributor"]},
     "<token-for-bob>":   {"allowed_sessions": ["proj-beta"],  "roles": ["contributor"]}
   }
   ```

2. Start the sidecar in multi-session mode:
   ```bash
   mpac-mcp-sidecar --multi-session --host 0.0.0.0 --port 8766 --tls
   ```
   The sidecar auto-detects `MPAC_TOKEN_TABLE` and switches to `security_profile=authenticated`.

3. Clients connect with their token in the HELLO credential field:
   ```
   wss://your-host/session/proj-alpha
   ```
   Tokens bound to `proj-alpha` can only join `proj-alpha` — cross-session access returns `CREDENTIAL_REJECTED`.

See `deploy/fly-coordinator/` for a complete Docker + Caddy + fly.io deployment recipe.

## Development status

This directory is the start of the `mpac-mcp` product entry point. It is
intentionally thin: MPAC remains the runtime and coordination engine;
`mpac-mcp` is the integration layer.

## Running the Milestone 0 smoke check

From this repository root:

```bash
python3 mpac-mcp/src/mpac_mcp/milestone0.py --workspace .
```

This will:

- derive a deterministic local sidecar port from the repo path
- start the local sidecar if it is not already running
- launch two independent demo clients
- announce two overlapping intents
- query the sidecar summary and print the result

## Running the tool smoke check

From this repository root:

```bash
python3 mpac-mcp/src/mpac_mcp/smoke_tools.py --workspace .
```

This will:

- ensure the local sidecar is running
- launch one independent demo client
- call `begin_task(...)` through the bridge
- call `check_overlap(...)`
- confirm that overlap is visible through shared sidecar state

## Running the commit smoke check

From this repository root:

```bash
python3 mpac-mcp/src/mpac_mcp/smoke_commit.py --workspace .
```

This will:

- ensure the local sidecar is running
- call `begin_task(...)`
- call `submit_change(...)` once with a derived `state_ref_before`
- verify the sidecar state changed
- call `yield_task(...)`

## Running the governance smoke check

From this repository root:

```bash
python3 mpac-mcp/src/mpac_mcp/smoke_governance.py --workspace .
```

This will:

- ensure the local sidecar is running
- launch one contributor client and one arbiter client
- call `begin_task(...)` to create a real overlap
- call `ack_conflict(...)`
- call `escalate_conflict(...)`
- call `resolve_conflict(...)`

## Running the takeover smoke check

From this repository root:

```bash
python3 mpac-mcp/src/mpac_mcp/smoke_takeover.py --workspace .
```

This will:

- ensure the local sidecar is running
- launch one client that leaves with `GOODBYE(intent_disposition="transfer")`
- verify the sidecar exposes a suspended intent
- call `take_over_task(...)`
- verify the replacement intent becomes active
