tsafe-mcp
First-party MCP server for tsafe — speaks
MCP over stdio (JSON-RPC 2.0, protocol version 2025-06-18) to MCP-aware hosts
(Claude Desktop, Cursor, Continue, Windsurf, Codex).
Companion binary published alongside tsafe-agent. Per
ADR-006, this binary supersedes
the Node starter under examples/mcp/ on v1 GA.
Install
Or get it bundled with the meta-crate:
The meta-crate enables the mcp feature on its embedded tsafe-cli dep so
tsafe mcp install <host> works out of the box.
Bind one profile per server
Each tsafe-mcp process is bound to exactly one tsafe profile at startup.
Request-time profile switching is rejected as JSON-RPC error -32008
(thin-stance "one profile per server"). Run multiple processes if you need
multiple profiles.
A running tsafe-agent is required by default. Unlock first:
If the agent is not reachable, every tool call returns -32001 AgentNotRunning
with a directive to run tsafe agent unlock.
Per-host install
tsafe mcp install <host> writes a server entry to the host's MCP config:
The writer merges into existing host configs (other entries are preserved) and
refuses to write without an explicit --allowed-keys or --contract. Use
--dry-run to preview the file change without touching disk.
Default tool surface (6 tools)
| Tool | Purpose |
|---|---|
tsafe_run |
Exec a command with explicitly-allowed keys injected as env. |
tsafe_list_keys |
List scope-filtered key names. Values are never returned. |
tsafe_search_keys |
Case-insensitive substring match across scope-filtered keys. |
tsafe_has_key |
Boolean presence check that honors scope. |
tsafe_audit_tail |
Recent audit entries, redacted to 6 fields. |
tsafe_status |
Agent/vault/scope shape per ADR-029 schema v1. |
tsafe_run accepts only literal key names in its allowed_keys request
field — globs at request time are rejected with -32602 InvalidParams. Globs
apply only at the startup scope level.
Opt-in 7th tool: tsafe_reveal
Off by default. Enable with --allow-reveal to expose the explicit escape
hatch:
Every tsafe_reveal call writes an audit row with operation=mcp.reveal
before the value is retrieved, so a panic or biometric denial still leaves
a record of the attempt. When the OS keychain has an entry for the bound
profile, biometric consent is implicit via keyring_store::retrieve_password.
Audit
Every tool call appends a row to the profile's .audit.jsonl:
operation: mcp.run | mcp.list_keys | mcp.search_keys | mcp.has_key
| mcp.audit_tail | mcp.status | mcp.reveal | mcp.shutdown
source: the --audit-source value (default: mcp:unknown:<pid>)
Audit rows reuse the existing tsafe-core::audit::AuditLog chain, so they
appear in the same operator narrative as tsafe exec.
Doctrine pointers
docs/architecture/ADR-006-mcp-server.md— decision record.docs/architecture/mcp-server-design.md— concrete shape (crate layout, tool schemas, error codes, host configs, test posture).docs/research/thin-mcp-stance-2026-05.md— thin-stance, one-profile-per-server.docs/decisions/agent-publish-topology.md— companion-binary publish model.
Out of scope for v1
- HTTP/SSE transport — stdio only.
- Multi-profile per process — refused at startup; run one process per profile.
tsafe_get/tsafe_set/tsafe_delete/tsafe_exporttools — direct thin-stance violation, not part of the default or opt-in surface.
License
Same as the tsafe workspace — see the repository root.