MCP tools#
swarmops mcp serves the store's operations as an MCP server on stdin and stdout: JSON-RPC 2.0, one message per line. Each tool is one operation, named as the envelope's op is, and its result holds the envelope the CLI prints for the same request. These pages are generated from the server's own tool table, so they say what tools/list says. MCP integration shows how to register the server and use it.
Tools#
In tools/list's order.
| Tool | Title | CLI command | Changes the store | Needs an identity |
|---|---|---|---|---|
repo_info | Describe the store | swarmops info | no | no |
resolve_rev | Resolve a revision | swarmops resolve | no | no |
read_file | Read a file | swarmops cat | no | no |
read_tree | List a directory | swarmops ls | no | no |
show | Show a changeset | swarmops show | no | no |
log | List history | swarmops log | no | no |
path_history | List a path's history | swarmops history | no | no |
diff | Diff two revisions | swarmops diff | no | no |
op_log | List operations | swarmops op log | no | no |
ref_list | List refs | swarmops ref list | no | no |
ref_set | Move a ref | swarmops ref set | moves refs | yes |
ref_delete | Delete a ref | swarmops ref delete | moves refs | yes |
undo | Undo an operation | swarmops op undo | moves refs | yes |
commit | Commit a changeset | swarmops commit | adds to it | yes |
land | Land a change | swarmops land | adds a changeset and moves the target | yes |
blob_put | Store a blob | swarmops blob put | adds to it | yes |
blob_has | Find stored blobs | swarmops blob has | no | no |
verify | Verify the store | swarmops verify | no | no |
These commands have no tool: swarmops init, swarmops whoami, swarmops schema, swarmops git import, swarmops git export, swarmops mcp, swarmops derive. An operator or a script runs them as commands; derive runs beside the store as maintenance, deriving values ahead of readers.
Protocol versions#
| Version | How a client opens it |
|---|---|
| 2026-07-28 | No handshake: each request names it in params._meta under io.modelcontextprotocol/protocolVersion, with the client's capabilities under io.modelcontextprotocol/clientCapabilities. |
| 2025-11-25 | initialize; also the version a client gets when it asks for one the handshake does not serve. |
| 2025-06-18 | initialize. |
The handshake revisions get the same tools and results. Revisions older than 2025-06-18 are not served. In 2026-07-28, a result has resultType: "complete" and the server's identity in _meta, and the results of server/discover and tools/list say a client may keep them for ttlMs 3600000 (an hour) with cacheScope: "public": they change only with the binary. MCP integration: Protocol versions shows a session of each.
Server instructions#
initialize and server/discover return this text as instructions, for the client's model: 2005 characters on one line.
SwarmOps is source control for coding-agent swarms: many agents commit to one store at once. Each tool is one store operation, and its result is the SwarmOps envelope {ok, op, api, result | error, meta}, as structuredContent and again as JSON text. A failed operation sets isError and gives error {code, message, retryable, exit, details, hint}: retryable says whether the operation can succeed when it is run again, as it is or after re-reading what the hint names, and a hint is often a swarmops command, whose operation is the tool of the same name (ref list is ref_list, cat read_file, ls read_tree, info repo_info). commit records a changeset; with advance it also moves that ref to it in the same transaction, if the ref still names parent: check result.advanced. ref_set and ref_delete change a ref by compare-and-swap, so their expected_old, like commit's parent with advance, is the full 64-hex changeset id the ref held when you read it (from ref_list, show, log or a commit's result). A ref name or a relative revision is read when the call runs instead of pinning the id you read: the ref's own name always matches, so the compare-and-swap protects nothing, and main~1 on ref main never matches; an id prefix stops resolving once another changeset shares it; the server refuses all three. To publish a changeset, land it: land merges it three-way onto main and moves main in one step, and on E_CONFLICT details.report says what to resolve. A read may show a commit that a failed sync then takes back; a mutation that names it fails under the lock instead of building on it. op_log lists the store's transactions, newest first; undo restores the refs one moved while they still hold what it set. Clients limit long tool results: ask for little, as each tool's description says. A {"file": path} content is read by this server, not by your client: give an absolute path (a relative one, or the server's own stdin or stdout, is refused). Every change is recorded for the agent the server runs as.Example: initialize#
{
"id": 1,
"jsonrpc": "2.0",
"method": "initialize",
"params": {
"capabilities": {},
"clientInfo": {
"name": "swarmops-tests",
"version": "0"
},
"protocolVersion": "2025-11-25"
}
}{
"id": 1,
"jsonrpc": "2.0",
"result": {
"capabilities": {
"tools": {}
},
"instructions": "SwarmOps is source control for coding-agent swarms: many agents commit to one store at once. Each tool is one store operation, and its result is the SwarmOps envelope {ok, op, api, result | error, meta}, as structuredContent and again as JSON text. A failed operation sets isError and gives error {code, message, retryable, exit, details, hint}: retryable says whether the operation can succeed when it is run again, as it is or after re-reading what the hint names, and a hint is often a swarmops command, whose operation is the tool of the same name (ref list is ref_list, cat read_file, ls read_tree, info repo_info). commit records a changeset; with advance it also moves that ref to it in the same transaction, if the ref still names parent: check result.advanced. ref_set and ref_delete change a ref by compare-and-swap, so their expected_old, like commit's parent with advance, is the full 64-hex changeset id the ref held when you read it (from ref_list, show, log or a commit's result). A ref name or a relative revision is read when the call runs instead of pinning the id you read: the ref's own name always matches, so the compare-and-swap protects nothing, and main~1 on ref main never matches; an id prefix stops resolving once another changeset shares it; the server refuses all three. To publish a changeset, land it: land merges it three-way onto main and moves main in one step, and on E_CONFLICT details.report says what to resolve. A read may show a commit that a failed sync then takes back; a mutation that names it fails under the lock instead of building on it. op_log lists the store's transactions, newest first; undo restores the refs one moved while they still hold what it set. Clients limit long tool results: ask for little, as each tool's description says. A {\"file\": path} content is read by this server, not by your client: give an absolute path (a relative one, or the server's own stdin or stdout, is refused). Every change is recorded for the agent the server runs as.",
"protocolVersion": "2025-11-25",
"serverInfo": {
"name": "swarmops",
"title": "SwarmOps",
"version": "[version]"
}
}
}Recorded by the MCP tests. A name in square brackets, such as [tmp] or [c1], stands for what differs from run to run: the test's temporary directory, an id, a time, the version.
The store and the identity#
Both are the server's, never a call's; no tool argument names either.
- The store is
--repo, elseSWARMOPS_REPO, opened anew for each call, so that a call sees what other processes committed. A store that is not there is each call'sE_NOT_A_REPO, and the server serves on. - The identity is
--as, elseSWARMOPS_AGENT, withSWARMOPS_RUN_ID, as for the CLI. Every change is recorded for it. - These tools need it, and without one fail with
E_IDENTITY_REQUIRED:ref_set,ref_delete,undo,commit,land,blob_put. - These need none:
repo_info,resolve_rev,read_file,read_tree,show,log,path_history,diff,op_log,ref_list,blob_has,verify. - The output flags (
--json,--human,--pretty) do not apply.
Result size limits#
A result holds its envelope twice, so the descriptions of the tools that read much ask the model for small reads and pages. In tools/list, read_file carries _meta: {"anthropic/maxResultSizeChars": 200000}: Claude Code keeps a result of up to that many characters in the conversation instead of saving it to a file. The other tools carry no _meta. MCP integration: Result size limits gives the sizes each tool asks for.
A message line longer than 64 MiB is an Invalid Request (-32600) without an id, read no further than one byte past the limit.
Protocol errors#
A message the server cannot serve gets a JSON-RPC error. An operation that fails is not one: its tool result has isError: true and the envelope's error, with an error code.
| Code | Name |
|---|---|
-32700 | Parse error |
-32600 | Invalid Request |
-32601 | Method not found |
-32602 | Invalid params |
-32603 | Internal error |
-32022 | Unsupported protocol version |
MCP integration: Protocol errors shows when each is sent.
See also#
read_tree
Lists one directory at a revision, without a checkout, a page of entries at a time, each file with its size, and with depth the directories below it too; pass…
ref_delete
Removes a ref by compare-and-swap, if it still holds expected\_old, the full 64-hex changeset id it held when you read it; a ref name or a relative revision…