Matrix logo

MCP Server

The MCP (Model Context Protocol) server exposes tachyon verbs as MCP tools over stdio newline-delimited JSON-RPC. This is the primary transport for LLM agent integration when th...

Source files: pkg/mcp/server.go, pkg/mcp/tools.go

The MCP (Model Context Protocol) server exposes tachyon verbs as MCP tools over stdio newline-delimited JSON-RPC. This is the primary transport for LLM agent integration when the daemon runs as a subprocess.


Design decisions

Stdio NDJSON-RPC

MCP uses stdin/stdout with newline-delimited JSON-RPC 2.0 messages. The server reads one line at a time, parses the request, dispatches to the engine, and writes the response. stdout is flushed after every message so clients block until the response is ready.

scanner := bufio.NewScanner(os.Stdin)
scanner.Buffer(make([]byte, 1024*1024), 1024*1024)
for scanner.Scan() {
    line := scanner.Text()
    resp := handle(eng, req.Method, req.Params, req.ID)
    send(resp)  // marshal + write + sync
}

Log redirection

In MCP mode, logs are written to stderr so they don't corrupt the NDJSON-RPC stream on stdout. The daemon detects MCP mode via the --mcp flag and reconfigures the slog handler accordingly.

Tool registry

The MCP tool list is a static registry in tools.go:

var ToolNames = []string{
    "tachyon_compile",
    "tachyon_test",
    "tachyon_simulate",
    "tachyon_deploy",
    "tachyon_call",
    "tachyon_chain_list",
    "tachyon_chain_register",
    "tachyon_artifact_get",
    "tachyon_registry_lookup",
}

Each tool has a name, description, and input schema. The schema is permissive (additionalProperties: true) because the actual validation happens in the engine.

Selftest

The --selftest flag verifies that the tool registry matches the canonical list:

func Selftest() error {
    tools := Tools()
    if len(tools) != len(ToolNames) { ... }
    // verify every ToolNames entry exists in Tools()
}

This is used in CI to catch tool drift (adding a tool to the engine but not to the MCP registry).

Error formatting

MCP tool errors return isError: true with JSON text content:

{
  "content": [{"type": "text", "text": "{\"ok\":false,\"tool\":\"tachyon_deploy\",\"error\":{...}}"}],
  "isError": true
}

The FormatToolError helper builds this structure from a types.Error.

Method dispatch

MCP MethodHandler
initializeReturn protocol version, server info, capabilities
tools/listReturn tool descriptors
tools/callParse tool name + arguments, dispatch to engine
notifications/initializedNo-op (ack)
pingNo-op (ack)

The tools/call handler routes to the engine via the JSON-RPC dispatcher (pkg/rpc).


Modifying the MCP server

What to changeWhere
Add MCP toolpkg/mcp/tools.go — add to ToolNames and Tools()
Change protocol versionpkg/mcp/server.goinitialize handler
Add MCP capabilitypkg/mcp/server.goinitialize capabilities map
Change error formatpkg/mcp/server.goFormatToolError