* bots, nodejs: document chat, connection, member contact and network commands, typed commands in library * bots, nodejs: restore apiConnect, wrap domain once, test all connect responses * nodejs: JSDoc for new methods * docs: plan for bot API commands and typed Node library methods * tests: channel prepared with a domain has a verified SimpleX name * docs: apply review fixes to the plan for bot API commands * docs: apply second review pass to the plan for bot API commands * docs: refer the bot API plan to the rewritten test commit * docs: record decisions in the plan for bot API commands * docs: plan tests of the generated Python command strings * python: test the generated strings of the documented commands * docs: plan for files, /leave and library methods in the MCP server * docs: wait at stop in the MCP plan * docs: library methods and /leave mechanics in the MCP plan * mcp: typed library methods for chat commands * docs: plan the message information command for bots * mcp: /leave CHAT owner command to leave a chat at once * docs: file servers, GIF and video choices decided in the MCP plan * docs: file mechanics in the MCP plan * mcp: files of received messages * bots, nodejs: message information with the file servers for bots * docs: plan the relay approval option of receiving files in Node * mcp: download of received files with owner approval * docs: name the xftp-server test helper in the files plan * nodejs: receive files without approving unknown relays * docs: plan the user servers command for bots * bots, nodejs: user servers and relays by operator for bots * nodejs: document the message information method * docs: plan the file upload progress event for bots * mcp: send files with owner approval, refusing private keys * bots: file upload progress event for bots * mcp: /leave template in the agent control chat menu * docs: sent copies are deleted for contacts too, at sndFileCompleteXFTP * bots: drop the file upload progress event * docs: drop the upload progress event plan * nodejs: document user servers and relay approval of received files * mcp: download cards name unknown file servers after the upload * docs: record the wait for the file description in the files plan * mcp: fixed wait at stop for cancelled cards, without /sql * docs: record decision C4, a fixed wait at stop, in the files plan * ci: test the MCP server package on pull requests * ci: state when the MCP workflow can be dispatched * ci: run the MCP server tests when its libraries change * mcp: log the errors of image previews and resizing * mcp: keep files in transfer in the data folder * mcp: restrict sent files by the real paths of refused folders * mcp: validate the file at the send by its inode and change time * mcp: limit ffmpeg and ffprobe to local files and no input commands * mcp: ask the owner for unknown file servers; read approvals at creation * mcp: name downloaded files by their ID; return paths of downloads only * mcp: end each download with a result for the agent and the card * mcp: show files above their sender's size limit as failed * mcp: refuse empty files, as without file and captions too long to send * mcp: tell the owner about failed uploads and unposted received files * mcp: delete resized copies left by the last run at start * mcp: name downloads and leaving in the help and greeting, align docs * mcp: compute the download path for received files only * mcp: send a /receive file to the owner under its name * mcp: keep files received without a download in the chat's folder * mcp: keep a left chat's files and delete them with /delete CHAT files * mcp: test that sent images are resized by the core * mcp: wait 30 minutes for a download's progress before cancelling it * mcp: end a download as deleted only when its message is not found * mcp: delete the copy of a /receive file whose post fails * mcp: count the quoted content in a message's length, as the core sends it * mcp: name received bytes, unknown-server downloads and left chat files plainly * mcp: test refused folders, file changes and download approvals * docs: align MCP server docs with refused folders, leaves and download waits * mcp: move received files only in full, delete partials only of downloads * mcp: report a received file missing from its folder as failed * mcp: move received files of a group's member chats into its folder * mcp: read a video's preview and duration as an MP4 or QuickTime file * mcp: 0.2.0 on simplex-chat 7.1.0-beta.10.1 * mcp: file folders by chat type, /delete cancels downloads, files reply * docs: MCP server specs and plan for 0.2.0 * mcp: /receive gives the agent a file, /forward sends it to the owner * docs: MCP server specs for /receive and /forward of download cards * docs: MCP plan records the temp folder command as a library exception * mcp: /delete cancels resumed downloads; /forward quote fits the limit * docs: MCP specs and plans for /forward quotes and resumed downloads * docs: MCP specs name the source commit they are checked against * docs: MCP PLAN states the /forward quote and move rules * mcp: a download moves its completed file whatever its size * mcp: /receive N all covers its card and later files, not pending ones * docs: MCP files approval scope, reply text and README server wording * mcp: a download approves relays only for a card naming unknown servers * mcp: files in member chats of a group are tracked as in the main chat * docs: MCP relay approval of downloads and files in member chats * mcp: a rejected file gets a card again under the files approval * docs: MCP rejected files under the files approval, README scope * mcp: an offered file without a description gets no card or action * docs: MCP a file without a description is not downloaded * mcp: 0.2.0 on simplex-chat 7.1.0-beta.10.2 * ci: test the MCP server as a scope of build-linux
33 KiB
SimpleX MCP server: reference
README has the short version.
@simplex-chat/mcp is a local server that gives an AI agent its own presence on the SimpleX network. The agent connects to people, bots, groups, channels and directories, as itself or incognito, sends messages and files, and receives all the responses, with the files people send it. Bots tell it which commands they understand, so every bot on the network becomes a service the agent can use. You supervise the agent from its control chat in SimpleX: it asks there before it connects, sends, downloads a file or leaves, and you approve or reject from your phone with one tap, or approve all its messages to a chat you trust, or all files from it. Six tools cover it: connect, send, receive, download, list, leave. Setup is one command to start the agent, a scan to join its control chat, and one command to add it to Claude Code.
What it isn't:
- Not a directory or a search service. The agent reaches chats through links, SimpleX names and the directories it connects to.
- Not a push channel into the agent. An MCP server can't start a turn of the agent, so news reaches it only as results of calls it makes: waits inside
sendandreceive, or polling. - Not an always-on service. The agent acts while its session runs; services that must always be up should be bots.
- Not hosted. It runs on your machine, one process per agent.
- Not in v0.2:
- an address for the agent: nobody can contact it first;
- your approval of incoming messages;
- a Claude Code plugin or channel;
- registration in other hosts.
Status: v0.2. TESTING.md describes a local build and test. The design, the tools and the scenarios are in PLAN.md.
- Requirements
- Quick start
- Owner approval
- Add the agent to Claude Code
- Approval modes
- Expiry
- What the owner sees
- What the agent sees
- Waiting for approval in Claude Code
- Several agents
- Other MCP hosts
- Recovery
- Command reference
- Data folder
- Security
Requirements
- Node.js 22.
- One of the platforms of the
simplex-chatpackage: Linux x86-64 or arm64, macOS x86-64 or arm64, Windows x86-64. - On Linux x86-64: glibc 2.34 or later, and the system libraries
libcrypto.so.3,libgmp.so.10andlibz.so.1. - The SimpleX Chat app on a phone or computer, for the owner.
- Claude Code; other MCP hosts with Streamable HTTP and custom headers can be configured by hand.
At its first start the server downloads the SimpleX core library, 29 to 50 MB depending on the platform, into ~/.cache/simplex-chat (macOS: ~/Library/Caches/simplex-chat, Windows: %LOCALAPPDATA%\simplex-chat). Unpacked on Linux, it takes about 240 MB.
Quick start
-
Start the agent's server in a terminal and keep it running. NAME, here
my-agent, names the agent's data folder and its entry in Claude Code;--display-nameis the name people see in SimpleX, NAME by default:npx -y @simplex-chat/mcp serve my-agent --display-name "My Agent"The first start prints, after two lines about downloading the SimpleX core library and the Node.js add-on:
SimpleX MCP server 0.2.0, agent "my-agent" Data folder: /home/alice/.simplex-mcp/my-agent Approval mode: requests Agent control chat "My Agent" created. Join the agent control chat in the SimpleX app. The link works once: <QR code> https://smp4.simplex.im/g#... If the QR code does not scan, restart with --qr-code large, or paste the link into the app. Whoever joins by this link becomes an owner of "My Agent" and approves its actions. To approve owners yourself, start with --owners. Listening on http://127.0.0.1:5226/mcp-yanswers npm's prompt to install the package. The server asks no questions: every choice is an option. The QR code of such a link is 37 columns wide and 19 lines high;--qr-code largedraws it twice as wide and twice as high. -
In the SimpleX app, scan the QR code or open the link, and tap Join. The chat "My Agent" appears in the chat list, and the agent writes:
I'm your agent. I ask here before I connect, send, download a file or leave a chat.The terminal prints:Alice joined (member 3) and is now an owner. The link is deleted. Add the agent to Claude Code: npx -y @simplex-chat/mcp register my-agent -
In another terminal, add the agent to Claude Code:
$ npx -y @simplex-chat/mcp register my-agent Added to Claude Code: scope user, server simplex-my-agent. -
Add
"mcp__simplex-my-agent"topermissions.allowin~/.claude/settings.json, so Claude Code does not prompt for each call; approval happens in the SimpleX app. -
Start Claude Code and ask it, for example:
Connect to the SimpleX Directory at https://smp4.simplex.im/a#lXUjJW5vHYQzoLYgmi8GbxkGP41_kjefFvBrdwg-0Ok and search it for trail running shoes.In the chat "My Agent", the agent writes:I want to connect to bot SimpleX Directory, as myself. `Find groups, channels, businesses and bots.` /approve 1 or /reject 1Tap
/approve 1. The agent then asks to send its search, and you approve that too, or tap the card'sallcommand to approve all its messages to the directory. Once the name@directory.simplexis registered, it works as the target too, and the card shows(@directory.simplex).
Without --owners:
- whoever joins by the link becomes an owner of the agent control chat;
- every owner approves actions, including owners added later in the app;
- the link is deleted when the first person joins.
Owner approval
With --owners, only the owners listed in it approve actions. An owner added later in the app approves actions only after the server is restarted with that owner in the list.
-
Start the server with
--ownersand no list:npx -y @simplex-chat/mcp serve my-agent --ownersThe output is the same as in the quick start, with the line
The link adds an observer. Its ID and name are printed when it joins.in place ofWhoever joins by this link .... -
Join the agent control chat in the SimpleX app with the link. The link is deleted. The terminal prints, and the agent posts in the chat:
Alice joined (member 3). Restart the server with --owners 3:AliceUntil the restart, the agent's
connect,send,downloadandleavefail. -
Stop the server with Ctrl-C and start it with the list:
$ npx -y @simplex-chat/mcp serve my-agent --owners 3:Alice Owners: 3:Alice. Add the agent to Claude Code: npx -y @simplex-chat/mcp register my-agent -
To add an owner, add the person to the agent control chat in the app and make them an owner there. The terminal prints, and the agent posts in the chat:
Bob (member 7) is now an owner and can't approve actions yet. Restart the server with --owners 3:Alice,7:BobWhen an owner leaves or is removed, the agent lists the human owners who remain:
Alice (member 3) is no longer an owner. Restart the server with --owners 7:BobWhen none remains:
No owners remain: restart the server with --reset-owners --owners.
In the chat, the --owners ... part of these lines is shown as code, so a member's name in it cannot form a tappable command.
At every start with a list, the server removes the connected members of the agent control chat other than the listed owners.
Add the agent to Claude Code
npx -y @simplex-chat/mcp register my-agent # all Claude Code projects
npx -y @simplex-chat/mcp register my-agent --scope local # the current project only
register NAME reads the agent's port from its data folder, runs claude mcp remove --scope SCOPE simplex-NAME (SCOPE: user, or the --scope value), ignoring a missing entry, and then, for register my-agent:
claude mcp add-json --scope user simplex-my-agent '{"type":"http","url":"http://127.0.0.1:5226/mcp","headersHelper":"cat /home/alice/.simplex-mcp/my-agent/headers.json","timeout":169800000}'
- NAME: 1 to 32 lowercase letters, digits and single hyphens, starting with a letter or digit.
- The entry has no token. At every connection Claude Code runs the
headersHelpercommand and sends the header it prints fromheaders.jsonin the data folder; on Windows the command istype "<folder>\headers.json". With--scope local, Claude Code runs it only in a folder whose trust dialog was accepted. - The agent's tools in Claude Code are
mcp__simplex-my-agent__connectand the rest. timeoutis the expiry plus 24 hours and 10 minutes, in milliseconds: the longest wait for a decision plus the longest wait for responses. After a change of--expireor--port, register the agent again; an agent on another port needs the same--portat every start.- The server must be running when Claude Code starts a session. If a session started before the server, run
/mcp reconnect allin it (Claude Code 2.1.284 or later; earlier, reconnectsimplex-my-agentin/mcp).
Errors:
situation message
never started Agent "my-agent" was never started. Start it with: npx -y @simplex-chat/mcp serve my-agent
claude not on PATH Add this entry under "mcpServers" in ~/.claude.json: {"simplex-my-agent": {...}}
(--scope local: under "projects" > "<project folder>" > "mcpServers")
The token is created at the agent's first start and saved in its data folder; every start writes it to headers.json. serve my-agent --new-token replaces it, and Claude Code sends the new token from its next connection, without a new register.
Approval modes
--approve MODE sets what the owner approves. It is set only by this option.
| Mode | The agent's actions: connect, send, download, leave | Messages to the agent |
|---|---|---|
requests (default) |
Performed after /approve N, or /receive N for a download; a send to a chat approved for all messages at once, with a copy posted in the agent control chat; a download from a chat approved for all files at once, with no post, when the file is on the agent's XFTP servers. |
Passed to the agent. |
host |
Performed at once; a copy is posted in the agent control chat, except for downloads. A download of a file on other servers fails. | Passed to the agent. |
Claude Code's own permission check applies to every tool call too. In mode requests, add the agent's server, for example "mcp__simplex-my-agent", to permissions.allow in ~/.claude/settings.json; otherwise Claude Code prompts for each call, or in auto mode its classifier decides it.
In host mode, approval is left to the MCP host. The server marks connect, send, download and leave with _meta["anthropic/requiresUserInteraction"]: true, so Claude Code shows its permission prompt on every call, in acceptEdits, auto and bypassPermissions modes as well, and allow rules do not skip it. In dontAsk mode and in claude -p runs Claude Code denies these calls.
Expiry
A pending action expires after --expire HOURS, 23 by default and at most: SimpleX allows edits of a message for 24 hours, and the outcome of a pending action is an edit of its card. Cards don't show the time; /pending does. The last line of its card is edited to Expired., and the agent's call returns {"action": N, "status": "expired"}. For the same reason, a connect waits for the other side at most until 23 hours 50 minutes after the action was created.
A result that no call has returned is dropped after the action's expiry time; a repeated call after that creates a new action. At most 20 actions are pending at once; a further connect, send, download or leave fails until the owner decides.
Actions last only while the server runs. When the server stops, the last line of each pending card is edited to Cancelled: the server stopped., and the server waits up to 10 seconds, --stop-wait, for these edits to be sent: it prints Stopping: sending 2 cancelled cards, up to 10 s. Ctrl-C to stop now., and a second Ctrl-C ends the wait. After a restart, /approve of an earlier number replies Action N is not pending., and the agent's repeated call posts a new card. Action numbers continue across restarts.
What the owner sees
All of it is in the agent control chat, posted by the agent's profile. The chat has the agent's display name; to see it under another name in your chat list, set an alias for the chat in the app. Names that are valid display names are shown plain. All other text written by the agent or by peers, other names included, is shown as code, line by line; names and errors take one line. Commands and SimpleX links inside it cannot be tapped: a valid display name cannot contain /, and the app parses each line of a message separately.
My Agent: I want to connect to bot SimpleX Directory (@directory.simplex), as myself.
`Find groups, channels, businesses and bots.`
/approve 1 or /reject 1
My Agent: I want to send a message to business Ridgeline, where I am incognito:
`Is the Talus Trail waterproof?`
/approve #9 4, /approve #9 all or /reject #9 4
My Agent: I want to leave business Ridgeline (#9).
/approve #9 12 or /reject #9 12
My Agent: I want to download a file from Alice in group Builders (#3):
`report.pdf`, 2.4 MB
Servers: `xftp.example.com`, unknown: downloading shows it this computer's IP address.
/receive #3 7, /forward #3 7 or /reject #3 7
The download card of an image or a video shows the sender's preview. Its servers line says Servers: known. when the file is on the agent's XFTP servers; otherwise it names the other servers, which see this computer's IP address during the download, and the card leaves out /receive #3 7 all. The agent waits until the sender finishes the upload before it asks, because the file's servers are known only then. A file without a file description is not downloaded: no card appears, and the agent's call ends with an error. A send with a file names the file's type, full path and size after the text, and shows an image's or video's preview:
My Agent: I want to send a message to group Builders:
`The trail map.`
attaching image `/home/alice/trail.jpg`, 3.1 MB
/approve #3 8, /approve #3 all or /reject #3 8
When the agent asks to send a private key or a file of the server's data folder, the server refuses it and posts Refused to send `/home/alice/.ssh/id_ed25519` to group Builders (#3): private keys and the server's own files are not sent. When the upload of a sent file fails, the agent posts, for example, The file `trail.jpg` was not sent to group Builders (#3): `File server error: Server address is incompatible with network settings.`.; both lines are logged too.
After the decision the card is edited, and its commands removed:
My Agent: I sent a message to business Ridgeline, where I am incognito:
`Is the Talus Trail waterproof?`
Approved by Alice.
Commands:
| Command | Effect |
|---|---|
/approve N, /approve #9 N |
Performs a connect, send or leave action N; the cards of sends and leaves name the chat. |
/reject N, /reject #9 N |
Rejects action N. |
/approve #9 all |
Approves all the agent's messages to chat #9: the pending ones and later ones. |
/revoke #9 |
Ends that approval: each message to #9 needs approval again. |
/receive #3 7 |
The agent receives the file of download 7: the server downloads it, and the agent's call returns its path. |
/receive #3 7 all |
The same, and the agent receives its later downloads from chat #3 of files on its XFTP servers without asking. Other pending downloads of #3 stay pending. |
/receive #3 off |
Ends that: each download from #3 needs approval again. |
/forward #3 7 |
Downloads the file of action 7 and sends it to you in the agent control chat, as a reply to the card when the file's preview and the card fit in one message. The card stays pending, and the agent gets nothing: its messages show the file as offered, without a path. The server keeps the file outside the chat's folder until /receive #3 7, which then uses it. |
/leave #9, /leave @4 |
Makes the agent leave group #9, or delete contact @4, at once, in both approval modes, and rejects the agent's pending actions for that chat. The reply, for example Left business Ridgeline (#9), requested by Alice., is logged too. |
/delete #9 files |
Cancels the running downloads from chat #9, which then fail, also those the core continues after a restart, and deletes the chat's files in the data folder, forwarded ones included, for a current or a left chat: Deleted 3 files from #9, 2.1 MB. or No files from #9. |
/pending |
Lists pending actions. |
/list |
Lists the agent's 100 most recent chats, one line each, and which of them are approved for all messages or all files: , approved for this chat by NAME and , files approved by NAME; a last line counts the older chats. |
After /leave #9, or after the agent's leave of #9 is performed in either mode, when the chat's folder has files, the agent posts Files from business Ridgeline (#9) are kept in `/home/alice/.simplex-mcp/my-agent/files/group-9`: 3 files, 2.1 MB. /delete #9 files. The files forwarded from #9 are deleted when the agent leaves it.
/pending, /list and /leave are in the chat's command menu, and the cards carry the others. Tapping /leave in the menu puts /leave <chat ID> into the entry field: replace <chat ID> with the chat's ID from /list, such as #9, and send it. Each command includes its number, because the app sends a tapped command as a new message, without a quote. Every card form and reply is listed in PLAN.md, section "What the owner sees: the agent control chat".
Approval of all messages to a chat
After /approve #9 all, the agent's messages to #9 are sent at once, and each one is posted in the agent control chat after it is sent:
My Agent: I sent a message to business Ridgeline, where I am incognito:
`Thanks, I'll order.`
Approved for this chat by Alice. /revoke #9
- It covers messages only: connecting and leaving are approved one by one.
- It lasts until
/revoke, until the chat is deleted, or until the approving owner is no longer an approver. It survives restarts: it is kept in the agent's database, as custom data of that chat. - With it, the agent can send anything it can read, without asking, to everyone in that chat.
- It applies in mode
requestsonly: in modehost,listand/listshow no approvals.
Receiving all files from a chat
After /receive #3 7 all, the agent's later downloads from #3 are performed at once, and nothing is posted in the agent control chat.
- It covers files on the agent's XFTP servers. A download of a file on other servers gets a card, as without it.
- Cards already pending in #3, other than card 7, stay pending. A file you rejected, or whose card expired, gets a card again.
- It covers downloads only, and the approval of messages covers no downloads: each is given and ended by its own command.
- It lasts as the approval of messages does, until
/receive #3 off, and is kept next to it in the chat's custom data. /listshows it as, files approved by Alice.
What the agent sees
Six tools:
| Tool | What it does |
|---|---|
connect |
Joins a contact, bot, business, group or channel by a link or a SimpleX name, as the agent's profile or incognito. Returns the chat, its profile, welcome message, the commands a bot advertises, and the messages so far. |
send |
Sends a message, with a file of this computer when asked, and returns every message received in that chat after it, until none arrives for idle seconds (30 by default). A directory bot's search results arrive this way. |
receive |
Returns the chat's unread messages and those that arrive while it waits, waiting for one when asked. |
download |
Downloads the file of a received message to the data folder and returns its full path. |
list |
Lists the agent's chats with unread counts and approved: true for chats approved for all messages, and its actions without a result. |
leave |
Deletes a contact, or leaves a group, business chat or channel, and deletes the chat; the contact or the members are notified. |
A send to a chat that list shows with connected: false is refused before any card. A send is refused with text: too long for its approval card; shorten it. when its card, in its longest outcome form, would exceed 15000 bytes in the SimpleX message, which holds at most 15602; a text of many lines or multi-byte characters reaches it below 12000 characters.
A received message with a file has a file field: its name, size, type (image, video, voice or file) and status. Status offered means download can fetch it; received comes with the path of the file that download downloaded; a file /forward sent to you stays offered; rejected means you rejected its download, or it expired; failed comes with the error, also for a file above the size its sender may send, and for a received file that is not in the chat's folder, for example after /delete #3 files. A downloaded file is named by its file ID and the extension of its name, when the extension has only letters and digits: the name the sender gave stays in the name field. download first waits, up to wait seconds, for the sender to finish the upload; when it has not finished by then, the call returns an error that asks to call again later. A download that runs past its wait after the approval returns status performing, and the same call again picks it up. A download fails when the sender cancels the file, when the message or its chat is deleted, or when no part of the file arrives for 30 minutes; the server then cancels it.
A short voice message can arrive with its file already received. The server moves such a file into the chat's folder under the same naming when it is received in full, and its message shows it as offered; download returns its path there after the approval. A partial file of a download, or of a short voice message that arrives while the server runs, is deleted when its transfer fails or is cancelled.
send with file, an absolute path, sends that file with text as its caption:
.jpg,.jpegand.pngas an image, resized by the SimpleX core to the size the apps send, with a preview the core makes;.gifand.webpas an image, unchanged, with a gray preview;.mp4and.movas a video, unchanged, with the first frame as its preview and its duration whenffmpegandffprobeare installed, otherwise a gray preview;- other files as a file, unchanged;
as: "file"sends an image or video this way too.
An empty file is refused, and so is as without file. A message holds at most 15602 bytes with its text, the file's name and preview, the message reply_to quotes and the mentioned names. The quote is the quoted text when the message is an image or video; otherwise it is the quoted content, an image's preview included. A send over it is refused with text: too long for a message with this image; shorten it., or without a file text: too long for the message with its quote; shorten it. An image's preview takes up to 14000 bytes, so its text has about 1 KB.
The server checks the file by its real path, after symbolic links, and refuses files under ~/.ssh and ~/.gnupg, files named id_*, *.pem, *.key, *.p12 and *.pfx, and the files under its data folder and under ~/.simplex-mcp, except those under files/ of its own data folder; each folder is taken by its real path too. The card shows the real path. A file whose real path, size, inode or change time differs at the send from the request is not sent: the action fails.
Incognito: the core creates a random profile for that one chat, so peers of different chats can't link them. The tools' inputs, results and errors are in PLAN.md, section "What the agent sees: tools", and the call sequences of the scenarios in section "Sequence diagrams".
Waiting for approval in Claude Code
An MCP server cannot start a turn of the agent: what the agent reads from the server are the results of its own tool calls. A call that waits for the owner, or for responses, stays open, and Claude Code turns it into a background task:
- A tool call in the main conversation that runs past two minutes moves to a background task. Claude continues working, and the result arrives as a task notification. When it arrives while the session is idle, Claude responds to it without a prompt (checked with Claude Code 2.1.300).
- To move calls to the background sooner, set
CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS, for example to10000, in theenvblock of~/.claude/settings.json. This applies to every MCP server. - Calls from subagents, and calls in
claude -pruns unlessCLAUDE_AUTO_BACKGROUND_TASKS=1, stay in the foreground: the subagent or the run waits. - A background task ends with the session. The action stays in the server while it runs;
listshows it, and the same call again picks it up.
Several agents
Each agent is its own process, with its own data folder, port, agent control chat and Claude Code server:
npx -y @simplex-chat/mcp serve my-agent-2 --port 5227
npx -y @simplex-chat/mcp register my-agent-2
Other MCP hosts
Add an entry with the URL http://127.0.0.1:5226/mcp and the header Authorization: Bearer <token>, as in headers.json of the data folder; after --new-token, update the entry. A host that ends a tool call early returns a timeout to the agent; the agent repeats the call with the same arguments, which picks up the same action. Hosts with a fixed tool-call limit, between 60 and 300 seconds in several hosts, need wait below it.
Recovery
| Situation | What to do |
|---|---|
| The server was not running when Claude Code started | Start the server, then run /mcp reconnect all in Claude Code (2.1.284 or later). |
| The server restarted while Claude Code was running | Claude Code reconnects up to five times within about 30 seconds. After that, in an interactive session, run /mcp reconnect all; claude -p runs and Agent SDK sessions keep retrying for about half an hour. Open calls fail, and pending actions are cancelled; the agent's repeated call creates a new request. |
| A second server was started on the same data folder | It exits with Another server uses <folder> (PID N). If no server runs, remove <folder>/lock. |
| Every owner left the agent control chat or was removed | connect, send, download and leave fail. Without --owners, the server logs No owners in the agent control chat. and prints a new link; join with it. With an --owners list, the agent posts and the server logs No owners remain: restart the server with --reset-owners --owners. |
| The agent was removed from the agent control chat, the chat was deleted, or the agent lost its owner role | connect, send, download and leave fail, and the server logs The agent lost its control chat. Restart the server with --reset-owners. |
| The QR code does not scan | Start with --qr-code large, or paste the link into the app. |
| The wrong person joined by the link | Start with --reset-owners. |
| The token leaked | Start with --new-token; Claude Code reads the new token at its next connection. |
--reset-owners deletes the agent control chat for all its members, creates a new one and prints a new link. Member IDs change in the new chat, so --reset-owners takes --owners without a list.
Command reference
npx -y @simplex-chat/mcp --help prints:
Usage:
simplex-mcp serve NAME [options] run agent NAME
simplex-mcp register NAME [options] add agent NAME to Claude Code
serve options:
--data DIR data folder (default: ~/.simplex-mcp/NAME)
--display-name TEXT the agent's name in SimpleX (default at the first start: NAME)
--approve MODE what the owner approves in the agent control chat:
requests the agent's connections, messages, downloads
and leaving chats (default)
host nothing; the MCP host asks
--owners [ID:NAME,...] only these owners approve; without a list, the link
adds an observer and its ID is printed at the join.
Without --owners, whoever joins becomes an owner and
every owner approves.
--expire HOURS pending actions expire after HOURS, 1 to 23 (default: 23)
--stop-wait SECONDS at stop, wait SECONDS for cancelled cards to be sent,
0 to 60 (default: 10)
--reset-owners replace the owners: a new agent control chat and link
--new-token replace the access token
--port N HTTP port on 127.0.0.1 (default: 5226)
--qr-code SIZE QR code of the link: small (default) or large
register options:
--scope SCOPE user (default) or local
--data DIR data folder (default: ~/.simplex-mcp/NAME)
--reset-owners takes --owners without a list.
Data folder
~/.simplex-mcp/my-agent/
simplex_chat.db SimpleX chat database: the agent's profile and chats
simplex_agent.db SimpleX agent database: connections and keys
token access token, readable only by the user
headers.json the token as the Authorization header for Claude Code, readable only by the user
server.json name, port and expiry of the server, read by register
lock PID of the running server
tmp/ the SimpleX core's work folder for files in transfer
files/group-3/ files downloaded from chat #3, and files received there without a download, each named by its file ID
and the extension of its name, such as 12.pdf; files/contact-4/ for contact @4
files/sent/ resized copies of the images the agent sends, and copies of the files /forward sends you under their names;
each is deleted when its upload completes or fails, and all at start
forwarded/group-3/ files /forward downloaded from chat #3, until /receive moves them into files/group-3/; deleted when the agent
leaves the chat, and by /delete #3 files
The folder is readable only by the user: every start sets its mode to 0700, except on Windows.
The server keeps its action counter in the chat database, as custom data of the agent control chat, the approvals of all messages to a chat and of all files from it as custom data of that chat, and its actions in memory.
The server keeps no log file: it writes its log to the terminal where serve runs, events to stdout and errors to stderr.
One server runs per data folder: a second one exits, because two processes on one database break each other's connections (a SimpleX server delivers a queue's messages only to the last process that subscribed to it).
Security
- The server listens only on 127.0.0.1. Every request needs the token. Requests from web pages on other hosts, and requests with another
Host, are refused (the SDK's localhost Origin and Host checks). - Any process with the token can act as the agent. The token is stored only in the data folder, in
tokenandheaders.json; Claude Code's config and theclaude mcp add-jsoncommand line contain the command that printsheaders.json, not the token. - Names written by peers are folded to one line, with control and format characters replaced by spaces, in the terminal and in the agent control chat; there, a name that is not a valid display name is shown as code.
- Without
--owners, whoever opens the link first becomes an owner. The link works once. - With
--owners, only the listed owners approve. - After
/approve #N all, the agent sends to that chat without asking, files included;/revoke #Nends it. - The server refuses to send private keys, its own files and the files under
~/.simplex-mcp, where agents keep their data, except the files underfiles/of its own data folder; other files the agent can read are sent after approval. - After
/receive #N 7 all, the agent's later downloads from that chat, of files on its XFTP servers, run without asking;/receive #N offends it. A file on other servers is downloaded only by/receiveor/forwardof the card that names them; any other download of it fails, unless the IP address is protected. - Peers of a chat connected as the agent see its profile; peers of an incognito chat see a random profile made for that chat only.
- The agent has no address, so nobody can contact it first.
- The agent uses private message routing: the SMP server that holds a contact's queue does not see the agent's IP address.