Run the MCP server¶
The MCP server is the front door for agents. It speaks the Model Context Protocol, validates an agent's capability token on every call, and exposes exactly the version-control tools an agent is allowed to use — and not one it isn't. This page is a how-to: start the server, see its tools, and understand the validation it runs.
Phase 2 edge is implemented
The workspace package tovio-mcp-server is built on tovio-node-bindings and the Node SDK.
It revalidates the capability token on every call and exposes scoped reads, semantic context,
clear and protected writes, delete/move, commit, narrower sub-token delegation, rationale, and
clear/protected whole-side and region-level conflict resolution. tovio mcp serve launches it over
stdio or Streamable HTTP. Delegated sessions persist and reconstruct the signed root-to-leaf chain,
revalidate every ancestor, and bind commits to the chain and canonical tool-manifest hash. The npm
packages are publish-ready but have not been published.
Start the server¶
Build the workspace package once, ensure its tovio-mcp-server executable is on PATH (or point
TOVIO_MCP_SERVER_BIN at it), then launch it from inside a repository:
tovio mcp serve resolves the repository, passes the token (from --token or TOVIO_TOKEN; without
one it refuses with TVO-MCP-001 rather than falling back to your human identity), and runs the package.
Stdio is the default. For Streamable HTTP, pass --transport http, or simply --port / --bind, which
imply it; the listener defaults to 127.0.0.1:7744 and serves MCP at /mcp. Every HTTP listener is
bearer-authenticated: a non-loopback --bind requires the shared secret in TOVIO_MCP_BEARER, and when
that variable is unset on a loopback bind the server mints a random bearer for the run and prints it on
stderr for the client that started it — the endpoint is never unauthenticated. All tool I/O is UTF-8
JSON. Most editor integrations spawn the server over stdio for you; see
write an integration. You can also run the package directly with TOVIO_REPO
and TOVIO_TOKEN in its environment (on PowerShell, $env:TOVIO_REPO and $env:TOVIO_TOKEN).
The server is a gateway, not a trust boundary
The MCP server owns no version-control logic and no cryptography of its own. Every operation is delegated to the Rust core. A compromised or buggy server cannot grant access the core would deny — read access is cryptographic and write access is proof-gated regardless of which edge made the request. The server's jobs are narrow: present the token on every call, refuse to even offer forbidden operations, and marshal results as clean JSON.
Why agents use MCP, not the raw CLI¶
An agent should never shell out to the tovio CLI. The MCP server exists because it makes four
guarantees the CLI cannot:
- Token scope is enforced at the protocol level. Every tool call carries the session's token and is validated before any work happens. The CLI assumes an ambient human identity; the MCP server has none — it acts only as the bound agent.
- The forbidden surface is structurally absent. The catalog contains no tool for obliterate, policy modification, key management, or unconstrained token issuance. An agent cannot call what is not exposed — a stronger guarantee than denying it after the fact.
- Provenance is injected automatically. Every commit records the model, task, prompt hash, delegation chain, server-generated session ID, and canonical tool-manifest hash without the agent supplying them.
- Output is structured by construction. Tools return parsed JSON, never prose to scrape. Errors use
the machine contract so agents branch on a
code.
Connecting: token validation up front¶
An agent authenticates by presenting its capability token at connection time. The server hands it to
the core, which runs the full validity check before any session exists: the version is
tovio-capability-v1, the signature verifies, authorized_by is a human (or the delegation chain ends
at one), and the token is unexpired and unrevoked. A token that fails any of these yields no
session — the client gets the corresponding TVO-TOKEN-* error.
The Node SDK's internal connect handshake returns the effective scope to the server. The current stdio entry point binds the token before MCP initialization and prints a short, content-free summary to stderr:
The connection exposes the effective scope, and status includes in-session staged paths. The core still re-checks the bound token, every delegation ancestor, and scope on every call.
Token validation on every call¶
This is the heart of the MCP contract: every tool call — read or write — re-presents the session token to the core and re-runs the full enforcement order, in this exact order:
- Token validity — still unexpired, still not revoked, chain still valid.
- Path scope — target paths within scope — checked before any policy is read.
- Operation allow/deny — op allowed, not denied, capability flags satisfied.
- Policy / clearance / key availability — for paths touching protected content.
The server holds no authorization state of its own, so a token that expires or is revoked mid-session causes the next call to fail. There is no caching that could outlive a revocation the core has learned about, and no grace period on expiry.
agent ──tool call (+token)──▶ MCP server ──delegates──▶ tovio-core
├─ 1. valid?
├─ 2. in scope?
├─ 3. op allowed?
└─ 4. policy / key / proof?
agent ◀────── result or structured error ────────────────┘
The tools it exposes¶
Every tool takes and returns JSON. Errors use the machine contract envelope.
Read tools¶
Read tools require read in the token's allowed ops and are path-scoped — any path argument is checked
against scope before policy.
| Tool | Returns |
|---|---|
effective_scope |
A read-only echo of the session's path, lane, operation, and clearance scope — informational; the core re-checks scope on every call. |
status |
The current lane, the most recent change visible to the token, in-session staged paths as modified, and open conflicts filtered to the token's path scope — an out-of-scope tip or conflict is omitted, never leaked. |
log |
Change history from HEAD (first-parent, default 20 entries): change id, author, message, timestamp, and agent provenance — metadata only, no file content or paths. |
diff |
The current change's per-file diff, filtered to scope. Protected sides are returned only after the read gate and signed audit; otherwise only a redaction marker appears. |
read_file |
The content of an in-scope committed file (the canonical path-scoped tool). |
list_conflicts |
Conflicts whose path is in scope. |
symbol_context |
A semantic graph for in-scope symbols (truncated when results were limited to scope). |
search_symbols |
Ranked symbol definitions matching a name — the way to turn a half-remembered name into a moniker. |
symbol_relations |
One-hop relations of a symbol: callers, tested_by, or supertypes. |
change_impact |
The transitive dependents of one or more symbols plus the tests covering them (advisory). |
project_context |
Scope-gated symbols, overlapping peer intents, readable rationale, and matching repository conventions. |
provenance_graph |
The derivation graph for a target — human → token → agent → change → rationale — over already-signed data. |
read_file shows the enforcement order most clearly: a path outside scope is rejected with
TVO-TOKEN-001 before any policy is consulted; a path in scope but guarded by a policy the agent
cannot satisfy returns TVO-PERM-001; and if secret_clearance is false against a clearance-gated
policy, the key is simply unobtainable. On success the tool returns the file's bytes as text when they
are valid UTF-8, or base64 with _meta["tovio/encoding"] = "base64" for a binary file.
// → read_file { "path": "src/integrations/cgm/dexcom.ts" }
// ← text content
"export class DexcomSyncHandler { /* … */ }"
Write tools¶
Write tools require the matching operation and pass the full enforcement order. Protected content is sealed at commit. Provenance is auto-recorded on every successful commit — the agent never supplies it.
| Tool | Does |
|---|---|
write_file |
Stages clear or protected bytes; protected content stays in zeroizing memory and is sealed at commit. |
delete_file |
Stages deletion of a staged or committed in-scope path. |
move_file |
Stages a move. Protected sources require an audited read and may move only under the same effective policy. |
resolve_conflict |
Keeps ours/theirs for a whole conflict or one zero-based region; protected sides are audited and resealed. |
commit |
Seals protected edits, advances the agent lane, and injects provenance plus an optional clear or sealed rationale. |
// → commit
{ "message": "Add Dexcom G7 reconnect backoff", "reasoning_summary": "Stabilize CGM WebSocket under flaky network" }
// ← CommitResult
{
"change_id": "chg:a3f7b2",
"commit": "blake3:91be07…",
"branch": "agent/cgm-sync",
"verified": true
}
Delegation¶
The only delegation surface is issue_sub_token. The tool is always registered, but the core refuses it
with TVO-TOKEN-004 unless the session token allows delegation (can_issue_sub_tokens and
sub-token:issue, both granted by tovio agent new … --can-delegate). It enforces monotonic narrowing
and returns the signed leaf as hex — the sub-agent's own TOVIO_TOKEN — see
delegation in capability tokens.
Tools deliberately absent¶
The catalog has no tool for obliterate, policy modification, key management, tag-force, or
unconstrained token issuance — and amend, direct lane creation, and sync are likewise outside the
registered surface today. This is a structural property, not a runtime check — an agent cannot name what
does not exist. A client that requests such a name gets the MCP protocol's own unknown-tool error, not a
TOVIO envelope; the human-only path stays the CLI (tovio obliterate <hash> --confirm "obliterate <hash>").
TVO-TOKEN-004 is what a registered tool returns when the token does not permit its operation — for
example issue_sub_token under a token issued without --can-delegate, or commit under a token whose
allowed_ops lacks commit. A denial is the catalog envelope itself, returned as the tool result's text
and flagged isError:
{
"code": "TVO-TOKEN-004",
"title": "Agent token does not permit this operation",
"cause": "Operation `SubTokenIssue` is not in the token's allowed_ops, is denied, or a required capability flag is unset (§7 step 3).",
"context": { "op": "SubTokenIssue" },
"exit_code": 13
}
Expiry and revocation, surfaced cleanly¶
When a token expires or is revoked mid-session, the next call fails with TVO-TOKEN-002 (expired)
or TVO-TOKEN-003 (revoked), verbatim in the structured envelope, and the server closes the session.
The server never silently degrades, retries, or re-authorizes on the agent's behalf — the
orchestrator is expected to request a fresh token and reconnect. Parent revocation cascades to every
sub-token because the complete persisted chain is revalidated.
The server does not yet attach an approaching-expiry signal to tool responses. An orchestrator
should read expires_at from the token (tovio agent show --json) and renew
proactively rather than discover the deadline through a TVO-TOKEN-002 failure.
Protocol versioning¶
The server's protocol generation is tovio-mcp-v1.3, and tool schemas are versioned with it: every
tool's name, version, and input schema is part of the canonical tovio-tool-manifest-v3 manifest whose
BLAKE3 hash is recorded in each commit's provenance. Today the version is carried in that manifest and
the connect handshake echoes the effective scope; the spec's single combined handshake object (protocol,
version, expiry, coordination warnings) is not yet returned. The handshake can also echo a prompt_hash,
but tovio mcp serve passes no prompt bytes, so that field is absent on a server-launched session. Backward compatibility is
guaranteed for one minor generation back: a newer server keeps every prior tool name, input, and output
working with unchanged meaning. Within a generation the server may add tools and optional fields but
never remove or repurpose one without a major-version bump. These rules mirror the --json stability
guarantees so the CLI, --json, and MCP surfaces never drift — see
the machine contract.
Where this connects¶
- The token the server enforces: capability tokens.
- Wiring a specific client to it: write an integration.
- The output and error shapes it returns: the machine contract.
- The session it opens: agent sessions.
Last reviewed September 9, 2026
Suggest an improvement to this page Not for security reports — see disclosure