Skip to content

MCP Broker spike#2034

Draft
sathvikkumar-octo wants to merge 4 commits into
mainfrom
sk/mcp-broker-spike
Draft

MCP Broker spike#2034
sathvikkumar-octo wants to merge 4 commits into
mainfrom
sk/mcp-broker-spike

Conversation

@sathvikkumar-octo

@sathvikkumar-octo sathvikkumar-octo commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Ref MD-2096

Every MCP server is spawned by Calamari as its own stdio child, and the secret lives only in that child's environment. Calamari fronts each child with a loopback HTTP MCP server and forwards MCP calls.
This is done using https://github.com/modelcontextprotocol/csharp-sdk

Claude Code is pointed at those loopback URLs via an mcp-config.json that contains no MCP tokens on disk or in environment variables.

The loopback server has no auth as part of this spike and we should add auth to this before merging

Broker approach

flowchart TB
    subgraph calamari["Calamari process"]
        direction TB
        orch["AI Agent step"]
        broker["MCP broker host<br/>loopback 127.0.0.1:&lt;port&gt; — no secret"]
    end

    orch -. spawns .-> claude
    broker -. spawns .-> child

    claude["Claude Code<br/>child process — no OCTOPUS_API_KEY"]
    child["MCP server / npx<br/>child process — env: OCTOPUS_API_KEY"]

    claude -->|HTTP — no secret| broker
    broker <-->|stdio| child
    child --> octopus[(Octopus Server)]

    classDef safe fill:#e0ffe0,stroke:#3a3,color:#000;
    classDef secret fill:#fff3bf,stroke:#e8a200,color:#000;
    class calamari,orch,broker,claude safe;
    class child secret;
Loading

Route every MCP server (Octopus + custom) through an in-process broker:
Calamari spawns each as its own stdio child that holds the secrets and
re-exposes it to Claude Code over a secret-free loopback HTTP endpoint.
No MCP secret is written to mcp-config.json or inherited by the agent's
environment or descendants. Drops --bare so HTTP MCP tools load.
Collapse the near-duplicate McpServerEntry/McpServerSpec into a single
McpServerSpec (the broker's input contract). The JSON parse shape and the
mcp-config.json entry shape are now file-private records in McpWriter
rather than public types in ClaudeCodeCliRunner, so there is one public
'MCP server' concept end-to-end and parsing/file-format are local details.
Remove the near-identical CustomMcpServerJson parse type: the McpServers
variable is just a list of server specs, so deserialize directly into
McpServerSpec and validate. Leaves one 'MCP server' type end-to-end;
McpConfigEntry stays separate as it is the distinct (type+url) shape the
agent reads.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant