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](https://crates.io/crates/tsafe-cli) — 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](../../docs/architecture/ADR-006-mcp-server.md), this binary supersedes
the Node starter under `examples/mcp/` on v1 GA.

## Install


```sh
cargo install tsafe-mcp
```

Or get it bundled with the meta-crate:

```sh
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.

```sh
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:

```sh
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:

```sh
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:

```sh
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


- [`docs/architecture/ADR-006-mcp-server.md`]../../docs/architecture/ADR-006-mcp-server.md — decision record.
- [`docs/architecture/mcp-server-design.md`]../../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`]../../docs/research/thin-mcp-stance-2026-05.md — thin-stance, one-profile-per-server.
- [`docs/decisions/agent-publish-topology.md`]../../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_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.