SwarmOps
ReferenceCommandsswarmops mcp
View as Markdown

swarmops mcp#

Serve the store's operations to an agent as an MCP server on stdin and stdout.

One tool per operation (repo_info, resolve_rev, read_file, read_tree, show, log, path_history, diff, op_log, ref_list, ref_set, ref_delete, undo, commit, land, blob_put, blob_has, verify), each taking the operation's request as its arguments and returning the envelope the other commands print. The store and the identity are the server's, --repo and --as or their variables, never a call's. Speaks MCP 2026-07-28, and 2025-11-25 and 2025-06-18 to clients that open with initialize. Prints no envelope: stdout carries the protocol until stdin ends, and a command line it refuses has its envelope on stderr. The derive command has no tool: it is maintenance, no agent's work.

Metadata
Group
server
Since
0.1.0
Mutates
yes
Identity required
no
MCP tool
none
Envelope op
mcp
Exit codes
0
Errors
none

Syntax#

swarmops mcp [OPTIONS]

Required arguments#

None.

Optional arguments#

The command also takes the global options.

Examples#

No recorded example yet.

Details#

What the server does#

swarmops mcp is the command an agent harness starts, not one a person types: it turns the store's operations into MCP tools on stdin and stdout. The transport is JSON-RPC 2.0, one message per line. The server reads a message, answers it on stdout if it is a request, and reads the next: one at a time, in order, so a notifications/cancelled finds nothing to cancel. Notifications get no answer.

  • stdout carries nothing but answers.
  • stderr gets a line, starting swarmops mcp:, for a message that is a response from the client, and for the I/O error that stops the server; a bug's panic report; and the reason before one of the store's four documented aborts.
  • The exit code is 0 when stdin ends, 1 when reading stdin or writing stdout fails. On one of the store's aborts the process ends by SIGABRT, and the client has to start it again.

Options#

mcp takes no options of its own; the global options set the server for its whole life:

OptionEffect
--repo, else SWARMOPS_REPOThe store every call uses. It is opened anew for each call, so a call sees what other processes committed meanwhile. A store that is not there fails each call with E_NOT_A_REPO, and the server serves on.
--as, else SWARMOPS_AGENTThe identity every write is recorded for, with SWARMOPS_RUN_ID when it is set. It is checked when a call needs it: reads work without one, a write without one is E_IDENTITY_REQUIRED, and a write with a name that is no agent name is E_INVALID_ARG.
--json, --human, --prettyNo effect: a tool result always holds the JSON envelope.

No tool argument names another store or identity. A command line that parses as swarmops mcp but is refused (an unknown flag after mcp, a SWARMOPS_FORMAT that is neither json nor human) starts no server: its envelope goes to stderr, stdout stays empty, and the process exits with the envelope's code. A flag refused before the word mcp (swarmops --frob mcp) is an ordinary usage error, printed on stdout with exit code 2.

Protocol versions#

VersionHow a client opens it
2026-07-28No handshake: each request names the version in params._meta (io.modelcontextprotocol/protocolVersion) with the client's capabilities. Methods server/discover, tools/list, tools/call.
2025-11-25initialize. Also the version a client gets that asks initialize for one the server does not serve.
2025-06-18initialize.

A handshake opens a session that lasts as long as the process; ping is answered in it, and also before initialize. Both handshake versions get the same tools and results. 2025-03-26 and older are not served. The results of server/discover and tools/list may be kept for an hour (ttlMs), since they change only with the binary.

Tools#

tools/list gives 18 tools, one per operation, named as the envelope's op is: repo_info, resolve_rev, read_file, read_tree, show, log, path_history, diff, op_log, ref_list, ref_set, ref_delete, undo, commit, land, blob_put, blob_has and verify. A tool's input schema is its request type's JSON Schema (swarmops schema <Req>), with every reference inlined so that it stands alone. Its annotations say what it does to the store:

ToolsreadOnlyHintdestructiveHintidempotentHint
The 12 reads, blob_has and verify among themtruefalsetrue
commit, blob_putfalsefalsefalse
ref_set, ref_delete, undofalsetruetrue
landfalsefalsetrue

None reaches beyond the store (openWorldHint: false). init, whoami, schema, git import, git export, derive and mcp have no tool: a call to one is the protocol error -32602 (Unknown tool). The git commands and init read or write paths on the operator's host, and derive is maintenance, no agent's work.

Tool results#

A call runs as one command of the CLI does, and its result holds the envelope the CLI prints for the same request, twice: as structuredContent and as the text of its one content block. isError is true exactly when the envelope's ok is false. An operation that fails is such a result, not a protocol error: its error has the code, retryable, exit, details and a hint that is often the next command, whose tool has the matching name (ref list is ref_list, cat is read_file). A verify that finds problems is E_STORE_CORRUPT, as swarmops verify is.

The server adds its own rules to the request types, each refused with E_INVALID_ARG:

  • Full ids for compare-and-swap. ref_set's and ref_delete's expected_old, a commit's parent with advance, and land's resolutions.against must be the full 64-hex changeset id read before. A ref name always matches, a relative revision such as main~1 never does, and an id prefix stops resolving once another changeset shares it.
  • Absolute, regular files. A {"file": <path>} content in commit, blob_put or land's resolutions is read by the server, as the user it runs as. A relative path, the server's own stdin or stdout, and anything that is not a regular file are refused, since the server would read from a working directory the agent cannot see, or block.
  • Arguments that fit the type. A field the type does not know is ignored; a field named twice, or a value of the wrong type, is refused.

Sizes#

A message line holds at most 64 MiB; a longer one is -32600, read no further, and the server reads on from the next line. Send larger content as {"file": <path>}, or store it with blob_put first and name it by id.

Clients limit long tool results, and each result holds its envelope twice. The tools' descriptions and the server's instructions ask for small reads: max_bytes of 32 KiB or less, limit and max_changes of 100 or less, an op_log limit of 20 or less, and paging on. read_file alone declares a larger result for Claude Code (_meta: {"anthropic/maxResultSizeChars": 200000}).

Patterns#

One server per agent identity. A harness starts one server per session, and everything the session's subagents write is recorded for that server's identity. An agent that needs an identity of its own runs as its own process, with its own SWARMOPS_AGENT:

claude mcp add swarmops -e SWARMOPS_AGENT=agent/worker-1 -- swarmops mcp --repo ~/.local/state/swarmops/repos/acme

Give the store by its absolute path. The server runs in a working directory the agent cannot see, so a relative --repo is read from wherever the harness started it.

Let agents publish, keep git with the operator. Agents read, commit and land through the tools; the operator runs git import and git export beside them as commands.

Keep a copy of the answers. The server keeps none. swarmops op log lists the writes that succeeded; a wrapper that copies stdout keeps every envelope (Keep a copy of every envelope).

Performance#

The server opens the store for each call and takes its snapshots as a CLI command does, without a process start per call. It keeps no cache between calls: the performance ledger measures a snapshot, and names swarmops mcp as the long-lived process where caching would pay (what would change the picture).

Failure cases#

WhereWhatWhat to do
StartA refused command line: envelope on stderr, its exit code, no server.Fix the flags or SWARMOPS_FORMAT.
A message-32700 (not JSON or not UTF-8), -32600 (not one request object, or over 64 MiB), -32601 (a method the version lacks), -32602 (bad params, an unknown tool, no version before initialize), -32022 (a version not served; data.supported lists the served ones), -32603 (a bug).Fix the message; the server reads on.
A callisError: true and the envelope's error.As at the CLI: Scripting the CLI gives the retry rules.
The processExit 1 on an I/O failure of stdin or stdout; SIGABRT on a store abort, with the reason on stderr.Start the server again.

Go further#

Return information#

swarmops mcp prints no envelope: stdout carries the MCP protocol until stdin ends, and a command line it refuses has its envelope on stderr.

Envelope op: mcp.

Exit codes:

  • 0: Success.

Errors#

No golden step shows this command failing yet.

Any command that opens a store may also fail with a store error, such as E_NOT_A_REPO, E_IO or E_STORE_CORRUPT; a command line the grammar refuses is E_INVALID_ARG (exit 2).

See also#

Edit on GitHub

On this page