Striatum MCP
June 29, 2026 ยท View on GitHub
Status: native Go daemon HTTP MCP is the production tool surface Updated: 2026-05-21
Overview
Striatum's MCP surface is served by the local Go striatumd daemon. The
primary transport endpoint is Streamable-HTTP-style POST /mcp on loopback
only, with GET /mcp and the legacy /mcp/sse alias available for SSE
clients. Tool discovery comes from the daemon method registry, is filtered by
the caller's capability token, and every tools/call re-enters daemon RPC with
normal authorization, request logging, and audit behavior.
The retired Python striatum.mcp stdio wrapper is no longer part of the
product surface. Agents should connect to the running daemon instead of
spawning a proxy process.
Endpoint
striatumd starts the MCP HTTP listener by default on an ephemeral loopback
port. The daemon writes the active SSE endpoint to the owner-only runtime file:
$STRIATUM_DAEMON_RUNTIME_DIR/mcp-http-endpoint
If STRIATUM_DAEMON_RUNTIME_DIR is unset, the runtime directory follows the
same daemon token/socket rules documented in docs/how-to/postgres-transition.md.
The file contains a single URL such as:
http://127.0.0.1:43127/mcp
The listener can be configured with:
striatumd --mcp-http-addr 127.0.0.1:8765
STRIATUM_DAEMON_MCP_HTTP_ADDR=127.0.0.1:8765 striatumd
Use --mcp-http-addr off to disable the listener. Non-loopback bind addresses
are refused.
Protocol
Diagnostic and Streamable HTTP clients can send JSON-RPC requests directly to:
POST /mcp
Authorization: Bearer <capability-token>
Content-Type: application/json
The response is returned as one JSON-RPC response body. The supported JSON-RPC methods are:
initializenotifications/initializedtools/listtools/call
SSE clients can open a stream at either endpoint:
GET /mcp
Authorization: Bearer <capability-token>
or the compatibility alias:
GET /mcp/sse
Authorization: Bearer <capability-token>
The first event is endpoint; its data is a relative message URL:
event: endpoint
data: /mcp/messages?session_id=<session>
Clients then send JSON-RPC requests to that URL:
POST /mcp/messages?session_id=<session>
Authorization: Bearer <capability-token>
Content-Type: application/json
Responses are delivered on the SSE stream as message events. The
compatibility alias also accepts direct diagnostic POST /mcp/sse, but new
clients should use POST /mcp.
Authentication
Use a daemon capability token in the HTTP Authorization header:
Authorization: Bearer dtok_...
Tokens are the same daemon tokens used by Unix-socket RPC. The daemon runtime
client-token is not automatically applied to arbitrary clients; a supervisor
or operator must pass token material explicitly. Tokens in query strings or
JSON-RPC params are not accepted by the daemon HTTP transport.
tools/list accepts an optional repository_id. Single-repository tools are
listed only when the token is authorized for that repository. tools/call
also accepts repository_id at the method params level and copies it into the
tool arguments object when the caller did not already provide one.
Tool Calls
tools/list returns daemon methods that are all of:
- present in
contracts/daemon_methods.json, - non-deprecated,
- not internal
daemon.*handshake methods, - not hidden local workflow-authoring methods,
- authorized by the supplied token and repository scope.
Example direct diagnostic request:
{"jsonrpc":"2.0","id":"tools","method":"tools/list","params":{"repository_id":"repo_123"}}
tools/call dispatches through daemon RPC only for production-supported MCP
tools. Hidden local workflow-authoring methods fail closed at the MCP layer
with structuredContent.error == "tool_hidden" even when the caller has a
write-capable token. Production-supported calls use MCP tool result shape with
Striatum details in structuredContent:
{
"content": [{"type": "text", "text": "status"}],
"structuredContent": {
"ok": true,
"method": "status",
"audit_id": "audit_..."
},
"isError": false
}
Denied calls fail closed. Calls that reach daemon RPC audit under
transport = "mcp"; hidden local workflow-authoring methods are refused by
MCP before daemon dispatch. Missing bearer auth, malformed JSON, bad local
browser Origin/Host checks, and unknown JSON-RPC methods return stable
JSON-RPC error objects with error.data.code. Hidden-tool, daemon-method, and
authorization denials through tools/call return MCP tool results with
isError: true and the denial code in structuredContent.error. Common
denial codes include tool_hidden, token_missing, token_malformed,
token_invalid, token_revoked, token_expired, capability_missing,
capability_scope_mismatch, capability_expired, repo_not_registered, and
method_unknown.
The HTTP listener refuses non-loopback bind addresses at startup. Requests must
also carry a loopback Host, and any Origin header must be loopback
(http://localhost, http://127.0.0.1, or equivalent loopback IP forms).
Agent Loop
The Go --agent-loop mode is a PTY supervisor only. It starts the configured
agent command, exports the daemon MCP endpoint in STRIATUM_MCP_URL, passes
token material through STRIATUM_MCP_TOKEN or STRIATUM_MCP_TOKEN_FILE, and
injects a bootstrap prompt.
The supervisor does not call work.await_packet, claim work, complete work,
release work, or write packet JSON. The agent is responsible for using MCP:
- call
tools/list, - call
work.await_packetwithrepository_id,session_id, andlease_seconds, - use the packet's identifiers, expected artifacts, and write scope,
- report state with MCP tools such as
work.ack,artifact.publish,review.verdict,work.complete, orwork.release.
Before a packet exists, agents use session.report for structured
ready, heartbeat, question, or escalate reports. This is the
pre-work path for startup blockers; terminal text and pane contents remain
observability only.
Boundary
The MCP server is local-only and daemon-owned. It does not introduce hosted services, telemetry, transcript capture, external persistence, direct database writes outside daemon RPC, marker-file state, or terminal-output state.
Repository files remain provenance; PostgreSQL remains live workflow state.
.striatum/ beside a target repository is operational scratch, not an MCP
message bus.