# MCP: the verbs as an agent's tools

For many agents MCP *is* the API, so the [verb table](/verbs/) is served as
an MCP server: every verb is a tool, its tosijs-schema input is the tool's
JSON Schema, and a call is `callVerb` — validated at the boundary, never
throwing, an `{ ok: false }` becoming a tool error rather than a crash. The
protocol layer here is transport-free (a JSON-RPC message in, a response
out) so it can sit on stdio, a WebSocket, or a test. `virta-mcp` (from this
repo: `bun run mcp`) is the stdio server:

```
virta-mcp --host https://us-central1-<project>.cloudfunctions.net
virta-mcp --memory --seed 40             # a throwaway board, for trying it
virta-mcp --read-only                    # query, get, transcript, projects only
virta-mcp --allow query,get,comment      # exactly these verbs
```

On a host, a token belongs to a **machine** (its label, `Tosi`), shared by
every repo there. So every write tool takes a required `as`:
`"Tosi × tosijs-3d"`, meaning who the agent is acting as. The server refuses an `as`
for another machine, the write carries it as `by`, and the host stamps its
own `_by` (the machine's token) beside it (board #171). The read tools need
no `as`. Every call syncs the replica first, so
reads see other writers' events and a write never decides against a stale
view; when the host cannot be reached a read answers from the replica,
prefixed `(replica may be stale …)`, and a write is refused until a call
finds the host back.
Registering it with an MCP client is the usual shape (this repo's
`.mcp.json` runs `bun bin/mcp.ts` instead, and finds the host from the
stored token):

```
{ "mcpServers": { "virta": { "command": "virta-mcp",
    "args": ["--host", "https://us-central1-<project>.cloudfunctions.net", "--read-only"] } } }
```

Tools only, for now: the transcript verb already hands an agent the
unfolded event stream, which is what the design says agents get. Resources
(a task as `virta://task/38`) would be a reader's convenience on top;
parked until an agent asks for it.
