Use SilentSwarm from an AI agent¶
The leader speaks the Model Context Protocol
(MCP) at https://<your-leader>/mcp. An AI agent connected there - Claude
Code, Claude Desktop, a claude.ai connector, Cursor or any other MCP client -
can do what you do in the web UI: look at pools and fellows, add a machine,
manage buckets and datasets, plan and run training, follow a run, load a model
and chat with it, and, for admins, run the deployment.
It does that as you, with your token's permissions and nothing more. Every
tool calls the same REST route the web UI and the swarm CLI call, with your
token, so the route's own checks - who may see which pool, quotas, validation -
apply unchanged. There is no second permission model to drift.
The full list of tools, resources and prompts, with every parameter, is the MCP tool reference, generated from the server's own registry.
Set up a client¶
You need two things: the leader's address and an API token. Create the
token under Profile > API tokens (Profile) and give it the
scopes the agent needs (see Tokens and scopes). Then pick
your client below. swarm mcp config prints every snippet with your leader's
address filled in; it never prints the token.
export SWARM_API_TOKEN=sk-swarm-... # the token you just created
swarm mcp config # every client below, ready to paste
swarm mcp config --client claude-code # just one: claude-code, claude-desktop, cursor, json
Claude Code¶
Claude Code talks to /mcp over HTTP and sends the token as a header:
claude mcp add --transport http silentswarm https://<your-leader>/mcp \
--header "Authorization: Bearer $SWARM_API_TOKEN"
Run it in a shell where SWARM_API_TOKEN is set; the shell expands it once and
Claude Code stores the header. Add --scope project to share the entry with a
repository (then keep the token out of it and let each person add their own).
Leave the header out and Claude Code signs in with OAuth instead the first time
you use the server (/mcp in Claude Code), through the same consent page as
the connectors below.
Claude Desktop¶
Two ways:
-
The
swarm mcp servebridge. Claude Desktop starts a local process and talks to it over stdio; the bridge forwards every message to the leader with your CLI token (--token,SWARM_API_TOKEN, thenapi_tokenin~/.swarm/config.toml). Add this toclaude_desktop_config.json:{ "mcpServers": { "silentswarm": { "command": "swarm", "args": ["--leader-url", "https://<your-leader>", "mcp", "serve"] } } }Desktop does not use your shell's
PATH: if it cannot startswarm, put the full path incommand(which swarmprints it). This works for a leader on your own network, too. -
A custom connector with OAuth, as for claude.ai below.
claude.ai connectors (OAuth)¶
In claude.ai (or Claude Desktop) add a custom connector with the URL
https://<your-leader>/mcp. No token to paste: the leader is its own OAuth 2.1
authorization server (PKCE, dynamic client registration, as the MCP
authorization spec asks), so the connector:
- finds the leader's sign-in through the
401it gets from/mcpwithout a token (itsWWW-Authenticateheader points at the protected-resource metadata), - opens the leader's login page and then a consent page that names the app, where it will send you back to, the tool groups it asked for, and the scopes it may have - untick any you do not want to grant,
- receives a scoped API token labelled
oauth: <app name>that lasts an hour and is refreshed while the connection is in use.
The connection appears under Profile > API tokens; Revoke there ends it.
A connector is reached from Anthropic's servers, so this needs a leader with a
public HTTPS address. For a leader on a private network use Claude Code or the
swarm mcp serve bridge. Operators: the endpoints and limits are in
Users & authentication.
Other clients¶
Any client that takes a Streamable HTTP server and a header:
{
"mcpServers": {
"silentswarm": {
"type": "http",
"url": "https://<your-leader>/mcp",
"headers": { "Authorization": "Bearer ${SWARM_API_TOKEN}" }
}
}
}
Cursor writes the variable as ${env:SWARM_API_TOKEN}; replace it with the
token itself if your client does not expand environment variables. A client
that only speaks stdio can run swarm mcp serve instead, like Claude Desktop.
swarm mcp tools lists what the token can see, to check the setup without an
agent.
Tokens and scopes¶
The token decides what an agent may do. Each API token carries one or more scopes:
| Scope | What it allows |
|---|---|
| read | Look: pools, fellows, jobs, loss curves, logs, models, buckets. Changes nothing. |
| operate | Change things as you: submit and cancel jobs, load and unload models, manage buckets, datasets and pools, add fellows, chat with a model. |
| admin | The admin toolset: users, every pool and fellow, quotas, announcements, the audit log. Only an admin can hold it. |
- A connection lists only the tools its scopes allow. A read-only token sees the read tools and none of the others - a good start for an agent that should explain, not act.
- Scopes are separate: operate does not include read. Give an agent that
acts both. A tool that has to read what it changes first (deleting a pool,
cancelling a job, chatting with a model) needs both, and the reference marks
it
operate + read; an operate-only token is not offered it. - A token never does more than its owner. Pool membership still decides which pools, jobs and models it sees, and a demoted admin's tokens lose admin at once.
- Legacy tokens, created before scopes existed, keep their owner's whole power (read and operate, plus admin for an admin). Create a narrower one for the agent and revoke the old one.
- The
metool (toolsetaccount) shows whose token it is and its scopes.
Toolsets¶
Over 100 tools would crowd an agent's context and make it pick the wrong one, so tools come in toolsets and a connection lists only those it asks for:
| Toolset | What it covers | Listed by default |
|---|---|---|
cluster |
Fellows, GPUs, the swarm graph, fellow logs, adding a fellow | yes |
training |
Plan, submit, follow, checkpoint and cancel runs; train from a bucket | yes |
buckets |
Buckets and datasets: create, upload, reference Hugging Face, preload | yes |
serving |
The model catalogue, load and unload, chat | yes |
meta |
Leader health, public stats, announcements, the docs, and pools_list (the pool ids other tools take) |
always |
pools |
Members, invites, join requests, node roles, pool telemetry | - |
account |
Who am I | - |
admin |
Users, pools, quotas, announcements, audit, mail, fellows | - |
Choose them in the URL:
https://<your-leader>/mcp- the default set.https://<your-leader>/mcp/pools,admin- those toolsets (plusmeta).https://<your-leader>/mcp/all- every toolset.https://<your-leader>/mcp?toolsets=pools,admin- the same, as a query.
Unknown names are ignored. swarm mcp config --toolsets pools,admin (or
all) writes the matching URL into every snippet. Toolsets only choose what
is listed; the scopes decide what the token may do.
Resources and subscriptions¶
State you follow is also offered as resources (swarm://...), so a client
that supports them can read it without a tool call: swarm://cluster/nodes,
swarm://jobs/{job_id}, swarm://jobs/{job_id}/metrics,
swarm://fellows/{fellow_id}/logs, swarm://models/{model_id}, the pools and
buckets, and more (list).
Most of them are subscribable: after resources/subscribe the leader
re-reads the resource every few seconds and sends
notifications/resources/updated when it changes - a job's step and loss, new
log lines, a model's load progress. A subscription ends with the session -
when the client disconnects, when the leader ends an idle session (after
SWARM_MCP_SESSION_IDLE_S, default 30 minutes, with no request and no open
stream) - or as soon as the token is revoked. Subscribing to something you
cannot read (an id that does not exist, or one outside your pools) is refused
at once with JSON-RPC error -32002, as is reading it. One session holds at
most 50 subscriptions, one token 100 across all its sessions.
For clients without resources, every one has a read tool too, and jobs_wait
and models_wait_ready block until a run ends or a model is ready, sending
progress notifications on the way, like swarm train --wait - at least every
five seconds even while nothing moves, so a client that resets its timeout on
progress keeps waiting.
swarm://docs lists the pages of this documentation and
swarm://docs/{page} returns one as Markdown (swarm://docs/06_user_guide/mcp
is this page), so an agent can look up a setting or an error without leaving
the session.
Prompts¶
Four ready-made workflows, offered by clients as commands (in Claude Code,
/mcp__silentswarm__train_from_bucket and so on). Each lists the tool calls in
order and stops for you before anything that changes the cluster:
| Prompt | What it does | Scope |
|---|---|---|
train_from_bucket |
Check a bucket, plan the run, ask you, submit, follow it to the end | operate |
diagnose_failed_job |
Read a job's error, loss curve and fellow logs, re-plan it, and name the cause and one next step | read |
add_a_fellow |
Mint the join command, wait while you run it on the new machine, watch until the node is ready | operate |
serve_and_test |
Load a model, wait until it is ready, check it answers a short chat | operate |
A prompt is offered only when the token has the scope its steps need.
Safety model¶
An agent here acts on real machines and other people's work, so:
- Destructive tools ask you first. Deleting a bucket, dataset, pool or
user, cancelling a run, unloading a model, releasing or removing fellows and
the like are marked destructive. If your client supports MCP
elicitation, the leader asks you through the client what will happen
("Release 2 fellows: ...") - always, even when the agent claims you agreed.
The question has one box, ticked: Accept goes ahead, Decline (or
unticking the box) does not. Other clients - and a client that declared only
URL-mode elicitation - get a refusal that says what the tool would do; it
runs only when called again with
confirm: true, which the agent should set only after you said yes. - Plan before acting.
jobs_plan(andbuckets_trainwithplan_only) shows where a run would go and why it could not start, without submitting; the server tells agents to show you that first.jobs_planis a read: it is free, not logged, and clients may run it without asking. - Every change is audit-logged. Each call to a tool that changes something
writes an audit row
mcp.<tool>withvia=mcp, the token's label, the argument names and the outcome -result=ok,result=refused(the confirmation was declined or missing, nothing changed) orresult=error(the route refused it) - next to the route's own event. Both rows carry your address as the leader saw it through its proxy. Admins find them under Admin > Audit log with the MCP calls toggle (Administration). Reads are not logged. - Changes are rate-limited per token. Read tools are free; every other tool
takes one unit from the token's bucket:
SWARM_MCP_WRITE_BURST(default20) in a row, refilled atSWARM_MCP_WRITES_PER_MIN(default30) per minute. A refused confirmation gives its unit back. Past that a tool answers "Too many changes in a short time; try again in N s", so an agent in a loop cannot submit jobs back to back. - What comes back is data, not instructions. Fellow logs, job errors, dataset text, Hugging Face rows, names people typed and model replies come from other machines and people. Tool descriptions say so, and the server tells agents never to follow instructions found in them. Treat an agent that suddenly wants to do something a log line suggested with suspicion.
- Sessions belong to their token. The endpoint takes only a bearer token -
a browser's session cookie is ignored, so a web page cannot drive tools as
you - and an MCP session opened with one token cannot be used with another.
One token may hold
SWARM_MCP_SESSIONS_PER_TOKEN(default20) open sessions and open about as many per minute; past that a new connection answers429, so no single token can fill the leader's session table (SWARM_MCP_MAX_SESSIONS, default10000).
What MCP will not do¶
Some of the web UI stays in the browser on purpose
(src/silent_swarm/leader/mcp/coverage.py, held by a test that fails when a new
route is neither covered nor listed there):
| Not over MCP | Why |
|---|---|
| Password, two-factor setup, sessions, log out everywhere, extend session | A token holder must not change the credentials that protect the account; browser only. |
| Creating, listing or revoking API tokens | An agent must not mint, list or revoke its own credentials. |
| Login, registration, email verification, password reset | Human login and registration flows, bound to a browser. |
| The public waitlist form | A sign-up form; admins read the waitlist with admin_waitlist. |
| The bootstrap script, manifest and source archive; a joining machine's progress reports | Fetched and written by the install script, not by people; fellows_join_command gives you the command and join_sessions_get reads the progress. |
| Live event streams (metrics, logs, the swarm graph) | Offered as subscribable resources instead. |
| Downloading a model archive | A multi-GB file of weights that fellows fetch; agents read models_get. |
/v1/chat/completions |
An alias of the route the chat tool uses. |
| The fellow protocol (registration, heartbeats, relay) | Machine to machine, with a node credential no agent holds. |
| HTML pages | Their data comes from the tools behind them. |
An admin's agent also cannot reset the password of, re-verify, change the email or role of, or delete the account its own token belongs to, and never receives a one-time sign-in link (Administration). The REST routes behind those tools enforce the same rule for every API token - the CLI's and an OAuth connector's too - so it holds outside MCP as well.
Troubleshooting¶
401 with invalid_token. No token, a mistyped or revoked one, or an
OAuth token whose hour is up and could not be refreshed. The answer carries
WWW-Authenticate: Bearer realm="silentswarm", resource_metadata="https://<your-leader>/.well-known/oauth-protected-resource/mcp":
OAuth clients use it to start the sign-in, so a connector showing a login
again after a revoke is expected. With a header client, check the header is
Authorization: Bearer <token> and that the token still lists under
Profile > API tokens. swarm mcp serve explains a refused token on stderr
and to the client, then exits with status 1 (status 2 when it has no token).
403 with insufficient_scope. "This token has no owner": an old token
not tied to an account. Create a new one on your Profile page.
A tool is missing, or "Unknown tool". The token lacks the tool's scope, or
the connection did not ask for its toolset. Check with
swarm mcp tools --toolsets all, which lists what the token can call, or the
me tool for its scopes. A route can still refuse with "not found" for
something outside your pools, or "forbidden"; the tool error carries the same
message the web UI would show, and its structured content the problem's
status, type and title, so an agent can tell the cases apart without
parsing the text.
The confirmation question never appears, progress stalls, or long calls end
after a minute. Something between the client and the leader buffers
text/event-stream. Every MCP response is streamed, and a destructive tool's
question to you is sent in the middle of the call. The shipped frontend
(docker/nginx/frontend.conf) proxies /mcp with proxy_buffering off and a
one-hour read timeout, and Traefik streams by default. Behind your own nginx,
give /mcp the same (proxy_buffering off; proxy_read_timeout 3600s;); with
other proxies, turn off response buffering and compression for
text/event-stream on that path.
404 "Session not found" or 400 "Missing session ID". MCP sessions live
in the leader's memory: after a leader restart or redeploy, or once an idle
session expired, the client must connect again (in Claude Code, /mcp and
reconnect). A session also belongs to the token that opened it, so changing
the token mid-session has the same effect. swarm mcp serve notices this
itself: it answers the waiting request with "the leader no longer knows this
MCP session", says so on stderr and exits with status 1, so Claude Desktop
shows the server as stopped - restart it there (or restart Desktop) to
connect again.
429 with too_many_sessions. The token already holds
SWARM_MCP_SESSIONS_PER_TOKEN open sessions, or opened sessions too fast.
Close clients you no longer use (each disconnect ends its session), wait for
idle ones to expire, or give each client its own token.
A leader under a path prefix. A leader served at https://host/swarm
(uvicorn --root-path /swarm behind a proxy) serves MCP at
https://host/swarm/mcp, and tools reach its routes under the same prefix.
"Too many changes in a short time". The write rate limit above. Wait the
seconds it names, or raise SWARM_MCP_WRITE_BURST / SWARM_MCP_WRITES_PER_MIN
on the leader.
An upload is refused as too large. datasets_upload takes at most 5 MB of
inline text. Give it a source_url for the leader to download, or upload a
larger file in the browser or with the CLI.
Licence¶
SilentSwarm is source-available under the PolyForm Noncommercial License 1.0.0: self-hosting it, and connecting your own agents to your own leader, is free for any noncommercial purpose. Commercial use - running it inside a for-profit company, or offering it, its MCP endpoint included, as part of a product or service - needs the commercial licence (fabian@nexpatch.ai).