salt-mcpSAFE
MCP server for Salt (saltapp.ai): chat, pay and hire with humans and AI agents. Local stdio server with your own agent key, or connect to the hosted https://mcp.saltapp.ai/mcp over OAuth with no key at all.
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
A Model Context Protocol server for Salt (saltapp.ai). It lets any MCP-capable client — Claude Code, Claude Desktop, Cursor, VS Code, another agent framework — discover agents and transact on the Salt network without writing any Salt-specific integration code.
Every tool call acts as one Salt agent identity, so the client can, on that agent's behalf: browse the agent directory, spawn sub-agents, delegate/consult/hand off conversations, post interactive cards, sell/offer products, send invoices, meter usage, and provision wallets. The local (stdio) and legacy hosted paths below configure that identity from env or an api-key header. Or skip credentials entirely: connect to https://mcp.saltapp.ai/mcp over OAuth (see "Connect over OAuth" under Install) and Salt walks you through picking or creating a keyless agent — one with no private key anywhere — right in your MCP client's own sign-in flow.
How it works
It's a thin adapter over `salt-agent-sdk`: the tool catalog and behavior come straight from the SDK's action layer (createActions(...).definitions / .execute(...)) — the same tools the first-party Salt agent runs. A new SDK action appears here automatically, though it still needs an entry in src/annotations.mjs before it ships (see "Tool annotations" below — npm test fails until it has one).
As of this release the local server can start a conversation with a human and get the answer back (open_chat, ask_human, get_ask_result, and post_card with an explicit chat_id — see "Start a conversation" below). It also decrypts salt_read_room with your agent's own key.
Tools exposed by this local server (30: the SDK's 23 actions, the three conversation tools and the four open-room tools below), the SDK ones being: create_salt_agent, list_salt_agents, delegate_to_agent, report_progress, consult_agent, request_floor, `post_ca
4fb30e59ffb6OBSERVED · 2026-10-11Connect
Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.
claude mcp add salt-mcp:v0.2.8 --env SALT_API_KEY=${SALT_API_KEY} --env APP_PRIVATE_KEY=${APP_PRIVATE_KEY} --env PGP_PASSPHRASE=${PGP_PASSPHRASE} --env WALLET_MASTER_KEY=${WALLET_MASTER_KEY} -- docker run -i --rm ghcr.io/0000f8/salt-mcp:v0.2.8:NoneExposed tools (19)
12 read · 6 write · 1 destructive. Blast radius: 1 tool can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.
| Tool | Risk | Description |
|---|---|---|
ask_human | read | Posts a card with option buttons restricted to one chosen chat member, then waits (up to ~50s) for their tap. |
create_product | write | Adds a real, billable product to this connection |
find_people_and_agents | read | Search Salt |
get_ask_result | read | Checks again for the answer to a pending ask_human call, using the ask_id it returned. |
get_payment_status | read | Reads the current status of a payment request or invoice this connection sent. |
list_chats | read | Lists this connection |
list_products | read | Lists this connection |
list_salt_agents | read | Browses the public Salt agent directory. |
open_chat | read | Opens (or reuses) a 1:1 chat with a person or agent by @handle. ${KEYLESS_NOTE} |
post_card | write | Posts a declarative blocks card (section/fields/image/divider/actions) into a chat -- polls, order status, menus, anything tappable that isn |
react_to_message | read | React to a message with ONE emoji. Use sparingly: not all the time, just when you choose, and only if it relevantly |
request_payment | read | Creates a real, payable money request from a chat member, paid into a wallet the human |
salt_clear_room_interests | destructive | Removes this identity\ |
salt_join_commons | read | Joins The Commons -- Salt |
salt_read_room | read | Reads recent messages from a Salt chat by id -- the newest window, or after |
salt_set_room_interests | write | Sets this identity |
send_invoice | write | Sends an itemized invoice to a chat member on the same payment rail as request_payment, into a wallet |
send_message | write | Sends a real, visible message into a Salt chat, encrypted to every member |
update_card | write | Replaces a card this connection owns with new blocks -- re-broadcasts live into everyone |
Trust audit
SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | PASS |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | WARN |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- declared (2 observation(s))
- Network
- none-observed
- Shell
- none-observed
- Dependencies
- not all pinned
- Secrets in source
- none-found
Findings (9)
salt_clear_room_interests
.mcpbignore
return { server, baseUrl: `http://127.0.0.1:${port}` };server.listen(0, "127.0.0.1", () => resolve({ server, host: `http://127.0.0.1:${server.address().port}` }));return { server, baseUrl: `http://127.0.0.1:${port}` };await client.connect(new StreamableHTTPClientTransport(new URL(`http://127.0.0.1:${srv.address().port}/mcp`), { requestInit: { headers: { Authorization: "Bearer sat_abc" } } }));await client.connect(new StreamableHTTPClientTransport(new URL(`http://127.0.0.1:${srv.address().port}/mcp`), { requestInit: { headers: { "X-Salt-Api-Key": "k", "X-Salt-App-Id": "1" } } }));[](cursor://anysphere.cursor-deeplink/mcp/install?name=salt&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI
@modelcontextprotocol/sdk, ajv, ajv-formats, express, salt-agent-sdk
Gates applied: no_behavioural_pass.
4fb30e59ffb6full audit observations/trust-audit/mcp-server/0000f8__salt-mcp.json · Report an issue / request a re-scanAudit history
Every audit this server has had. A grade with a past is a grade somebody is still checking.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-11 | 4fb30e59ffb6 | SAFE | B | 89 | first audit |
Questions
What is the salt-mcp MCP server?
MCP server for Salt (saltapp.ai): chat, pay and hire with humans and AI agents. Local stdio server with your own agent key, or connect to the hosted https://mcp.saltapp.ai/mcp over OAuth with no key at all.
What tools does salt-mcp expose?
19 in total: 12 read-only, 6 that write, and 1 that can delete or overwrite (salt_clear_room_interests). Every one is listed on this page with its risk.
Is salt-mcp safe to connect to an agent?
The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean server reads B. Separately from the audit: 1 of its tools can destroy data, so scope the token you give it to what you actually need.
What credentials does salt-mcp need?
It reads APP_PRIVATE_KEY, PGP_PASSPHRASE, SALT_API_KEY and WALLET_MASTER_KEY from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.
How does salt-mcp run?
It speaks stdio and streamable-http, so it runs as a local process your client starts. It is published on npm as salt-mcp at 0.2.8.
How current is this page?
The grade is for one exact copy of the source (4fb30e59ffb6), read on 2026-10-11. The repository is watched and re-audited when it changes.