SwarmOps
ReferenceMcp toolsMCP tools
View as Markdown

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.

ToolTitleCLI commandChanges the storeNeeds an identity
repo_infoDescribe the storeswarmops infonono
resolve_revResolve a revisionswarmops resolvenono
read_fileRead a fileswarmops catnono
read_treeList a directoryswarmops lsnono
showShow a changesetswarmops shownono
logList historyswarmops lognono
path_historyList a path's historyswarmops historynono
diffDiff two revisionsswarmops diffnono
op_logList operationsswarmops op lognono
ref_listList refsswarmops ref listnono
ref_setMove a refswarmops ref setmoves refsyes
ref_deleteDelete a refswarmops ref deletemoves refsyes
undoUndo an operationswarmops op undomoves refsyes
commitCommit a changesetswarmops commitadds to ityes
landLand a changeswarmops landadds a changeset and moves the targetyes
blob_putStore a blobswarmops blob putadds to ityes
blob_hasFind stored blobsswarmops blob hasnono
verifyVerify the storeswarmops verifynono

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#

VersionHow a client opens it
2026-07-28No handshake: each request names it in params._meta under io.modelcontextprotocol/protocolVersion, with the client's capabilities under io.modelcontextprotocol/clientCapabilities.
2025-11-25initialize; also the version a client gets when it asks for one the handshake does not serve.
2025-06-18initialize.

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, else SWARMOPS_REPO, opened anew for each call, so that a call sees what other processes committed. A store that is not there is each call's E_NOT_A_REPO, and the server serves on.
  • The identity is --as, else SWARMOPS_AGENT, with SWARMOPS_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.

CodeName
-32700Parse error
-32600Invalid Request
-32601Method not found
-32602Invalid params
-32603Internal error
-32022Unsupported protocol version

MCP integration: Protocol errors shows when each is sent.

See also#

Edit on GitHub

On this page