MCP — both directions
ostk speaks MCP in both directions. Inbound: an external client (Claude Code, Cursor, anything) drives ostk as an MCP server. Outbound: ostk-driven agents call external MCP services (linear, github, postgres, etc.) via a userspace proxy.
QUICK_REFERENCE
ostk mcp Run the stdio MCP bridge. Invoked by external MCP clients as a subprocess. Forwards to a running daemon, falls back to in-process serve. ostk mcp diag Reconcile the kernel's MCP tool surface against CORE_SEED_LANGUAGE. Exits 1 on drift. ostk driver list List configured outbound MCP servers from HUMANFILE's mcp: section. ostk driver call <name> <tool> Invoke a tool on a configured outbound MCP server (ephemeral subprocess). ostk driver serve <name> Run an outbound MCP subprocess persistently on a Unix domain socket.
The outbound verbs were renamed from ostk mcp {list,call,serve} to ostk driver {list,call,serve} when ostk mcp (no subcommand) was reclaimed for the inbound bridge. Legacy ostk mcp ... still routes to the new ostk driver ... via McpLegacy dispatch in src/main.rs.
Drive ostk from an external MCP client
Your agent tool (Claude Code, Cursor, your own client) launches ostk mcp as a subprocess and speaks the MCP JSON-RPC protocol over stdio. The bridge translates that into kernel calls. Your agent gets gen-tracked writes, hash-chained audit, and pin-cap enforcement without changing its UI.
Source: src/main.rs (Commands::Mcp { command: None } branch — runs run_mcp_bridge), src/serve/server.rs (run_mcp_bridge, bridge_stdio_to_daemon). The bridge resolved the "two isolated kernels" problem (→1309 Phase 2B) — the Claude Code MCP process and ostk daemon used to have separate ServerStates that couldn't see each other's work.
Configuration
Most MCP clients use the same mcpServers shape. Add this entry to your client's MCP config:
{
"mcpServers": {
"ostk": {
"command": "ostk",
"args": ["mcp"]
}
}
} .mcp.json ~/.claude/settings.json ~/.cursor/mcp.json Verify the surface
Restart the client. Ask the agent to list its tools. You should see ostk-namespaced tools appear:
mcp__ostk__bash — kernel-mediated shell with audit + compressionmcp__ostk__read — file read with gen_table trackingmcp__ostk__fs_ops — file mutation with OCC conflict detectionmcp__ostk__search — unified code/files/needles/decisions searchmcp__ostk__lock, spawn, interact, session, tack, help — coordination primitives
The authoritative list is ostk mcp diag. Tool count varies by kernel version. Names are namespaced as mcp__<server>__<tool> by the MCP client — so mcp__ostk__bash is the bash verb routed through your ostk server entry.
First write — see the audit chain
Have the agent edit a small file. In your terminal:
$ tail -f .ostk/journal.jsonl
{"event":"tool.fs_ops","path":"src/lib.rs","gen_before":4,"gen_after":5,"writer":"claude-code-1","ts":"2026-04-26T19:42:11Z","prev_hash":"...","sig":"..."}
{"event":"tool.bash","cmd":"cargo check","exit_code":0,"duration_ms":2841,...}
Each row is hash-chained against the previous (prev_hash) and Ed25519-signed in-process (sig). Two agents editing the same file get a CAS conflict instead of a silent overwrite. Capability boundaries from .ostk/pins/<name>/pin.caps apply uniformly.
Inbound troubleshooting
DRIVING OSTK FROM CUSTOM TOOLS & SCRIPTS
You don't need Claude Code or Cursor to leverage the ostk kernel. You can drive it directly from custom scripts, CI pipelines, or proprietary editor extensions using two transport methods:
1. Subprocess Pipe Transport (Stdio)
Spawn ostk mcp as a persistent background process. Write JSON-RPC 2.0 messages to its stdin and read structured responses from its stdout.
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "mcp__ostk__read",
"arguments": {
"path": "src/main.rs"
}
},
"id": 1
}
2. UNIX Domain Socket Transport
For maximum performance and zero process-startup overhead, connect directly to the UNIX domain socket located at .ostk/ostk.sock. This bypasses the MCP abstraction layer entirely and invokes System ABI verbs directly.
const net = require('net');
const client = net.createConnection('.ostk/ostk.sock', () => {
client.write(JSON.stringify({
jsonrpc: '2.0',
method: 'read',
params: { path: 'README.md' },
id: 1
}) + '\n');
});
client.on('data', (data) => {
console.log('Kernel Response:', JSON.parse(data.toString()));
client.end();
});
Call external MCP services from ostk-driven agents
Your ostk-driven agent needs to talk to Linear, GitHub, Postgres, or any other MCP-speaking service. ostk's driver subcommand is a userspace proxy — agents invoke ostk driver call <name> <tool> and the proxy connects, sends one JSON-RPC request, prints the response, exits.
Deliberately at arm's length: the kernel never speaks MCP protocol bytes. Output flows through the same compression + audit pipeline as any shell output. Source: src/commands/mcp_proxy.rs (run_list, run_call, run_serve, run_persistent_call, run_ephemeral_call, run_jsonrpc_session).
Configuration
Outbound MCP servers are declared in .ostk/HUMANFILE under an mcp: section (not ostk.toml). Simple key-value: name → command line.
# .ostk/HUMANFILE mcp: linear: npx -y @anthropic/linear-mcp-server github: gh mcp-server postgres: npx -y @modelcontextprotocol/server-postgres
Source: src/commands/mcp_proxy.rs lines 7–11, 53, 134–147 (HUMANFILE parsing).
Execution modes
One subprocess per ostk driver call. Connect, JSON-RPC once, exit.
mcp_proxy.rs run_ephemeral_call.ostk driver serve <name> runs a long-lived subprocess on a Unix domain socket; subsequent calls reuse it.
mcp_proxy.rs run_serve, run_persistent_call.