# XMesh over MCP

Any MCP client (Claude Code, Codex, Cursor or your own agent) can hand XMesh work and read what
the mesh knows. `xmesh` is the runtime; `xmesh-mcp` is the bridge between your agent and it.

## Connect

With the runtime running (`xmesh`), from your project directory:

```bash
xmesh mcp install
```

That writes the `xmesh` server into the project's `.mcp.json` and prints what it wrote: the file, the bridge
and the `XMESH_URL` it pins, which is the runtime the CLI would reach from that directory (with `XMESH_TEAM_ROOT`
set, that root's live runtime). The file is replaced whole, never half-written. A `.mcp.json` that git tracks is
left alone unless you add `--force`. Plain `xmesh`, run in a project directory, wires it the same way as it starts
the runtime; no other `xmesh` command writes configuration. Restart Claude Code there (or run `/mcp`) and approve
the server. For Codex:

```bash
codex mcp add xmesh --env XMESH_URL=http://localhost:8787 --env XMESH_SEAT=your-name -- xmesh-mcp
```

Restart the client fully after adding or changing the server: an MCP client loads the tool list
when the connection opens.

## The tool: `mesh_mission`

There is one tool. Its `action` says what it does:

| Action | Use it to |
|---|---|
| `create` | hand the mesh a mission of any kind: `focus`, `criteria` with `CHECK:` clauses, and `kind` for anything but work |
| `read` | follow a mission by its `id`, or read one part of it (`part`: outputs, diff, artifact, root-cause) |
| `list` | list your missions, filtered by `kind`, `status` or `query` |
| `operate` | act on a mission: `id` and `op`, for example `{op: "verdict", verdict: "validated"}` |
| `abandon` | stop a mission (`id`); files it already wrote stay where they are |
| `view` | read what the mesh holds: `view` is `board`, `recall` (with `query`), `canon` or `capabilities` |

The kinds of mission are `work` (the default), `question`, `review`, `research`, `assessment` and
`task`. `simulation` answers `kind_unavailable` until the runtime has a simulation host;
`{action: "view", view: "capabilities"}` says which kinds a deployment runs, and why not where not.

Because reading and starting missions share one tool, a client that allows it without asking also
lets it start missions. Leave it on "ask" if you want to approve each mission.

The tool calls the runtime's one public resource, `/api/v1/mission`
([the contract](../docs/api/mission-v1.md)).

## Settings

| Variable | Default | What it sets |
|---|---|---|
| `XMESH_URL` | `http://localhost:8787` | where the runtime listens |
| `XMESH_PASSCODE` | read from the state directory | the runtime's passcode |
| `XMESH_STATE_DIR` or `XMESH_TEAM_ROOT` | `~/.xmesh` | where the passcode is read from when it is not given |
| `XMESH_SEAT` | see below | who your missions are recorded as asked by, and where completion notices go. With no seat, missions are recorded anonymous and no notice is sent. |

The seat is the first of these that names one:

1. `XMESH_SEAT`, then `SYM_NODE_NAME`, from the bridge's environment.
2. `node_name` in the project's `.sym/node.json`: the name `sym-mesh-channel start` gave the folder's mesh node. The file is
   read from `CLAUDE_PROJECT_DIR`, or the directory the bridge runs in, where the SYM mesh channel reads it, and a name the
   channel would refuse is skipped. It is the project's configuration and travels with the folder, so a repository that
   carries one names the asker for anyone who runs a client in it.
3. Inside a Claude Code session, `claude-<project>-<session>`: the name the SYM mesh plugin gives its node there.

When the file or the session names the seat, the bridge says so in its log as it starts, so the log shows which one chose
who asks.

## `camel-dryrun` — an integration capability as a tool (`skills/camel-dryrun/mcp-server.mjs`)

| Tool | What it does |
|---|---|
| `dryrun` | Execute an Apache Camel route in a secretless sandbox against mock endpoints; return a REAL pass/fail. Proves wiring+syntax+the transform; NOT idempotency/ordering/exactly-once. |

Prereq: `brew install openjdk jbang; jbang trust add https://github.com/apache/camel/; jbang app install camel@apache/camel`.

## Wiring

**Claude Code** (`.mcp.json` / `--mcp-config`):
```json
{ "mcpServers": {
  "xmesh":        { "command": "node", "args": ["<repo>/mcp/xmesh-mcp-server.mjs"] },
  "camel-dryrun": { "command": "node", "args": ["<repo>/skills/camel-dryrun/mcp-server.mjs"] }
} }
```

**Codex** (`config.toml`):
```
codex mcp add xmesh        --command "node <repo>/mcp/xmesh-mcp-server.mjs"
codex mcp add camel-dryrun --command "node <repo>/skills/camel-dryrun/mcp-server.mjs"
```

The mesh's own workers already get `camel-dryrun` as a sibling MCP server (opt-in via
`XMESH_CAMEL_TOOL=1`) — so a mission's critic invokes the dry-run through MCP, not raw Bash.
Both servers are stdio, which Claude Code and Codex both support.
