MCP: the verbs as an agent's tools
For many agents MCP is the API, so the verb table 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.