tsafe-mcp 0.1.0

First-party MCP server for tsafe — exposes action-shaped tools to MCP-aware hosts over stdio JSON-RPC.
Documentation

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

cargo install tsafe-mcp

Or get it bundled with the meta-crate:

cargo install tsafe

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.

tsafe-mcp serve \

  --profile work \

  --allowed-keys "demo/*,shared/*" \

  --denied-keys "demo/secret" \

  --audit-source "mcp:claude:1234"

A running tsafe-agent is required by default. Unlock first:

eval $(tsafe agent unlock --ttl 8h)

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:

tsafe mcp install claude --profile work --allowed-keys "demo/*"

tsafe mcp install cursor --profile work --allowed-keys "demo/*" --project .

tsafe mcp install continue --profile work --allowed-keys "demo/*" --project .

tsafe mcp install windsurf --profile work --allowed-keys "demo/*"

tsafe mcp install codex --profile work --allowed-keys "demo/*"

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:

tsafe-mcp serve --profile work --allowed-keys "demo/*" --allow-reveal

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

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_export tools — direct thin-stance violation, not part of the default or opt-in surface.

License

Same as the tsafe workspace — see the repository root.