Skip to content

feat(mcp): support http and sse MCP server transports#2208

Open
cfis wants to merge 1 commit intoqwibitai:mainfrom
cfis:feat/mcp-http-sse-transport
Open

feat(mcp): support http and sse MCP server transports#2208
cfis wants to merge 1 commit intoqwibitai:mainfrom
cfis:feat/mcp-http-sse-transport

Conversation

@cfis
Copy link
Copy Markdown
Contributor

@cfis cfis commented May 3, 2026

Type of Change

  • Feature skill - adds a channel or integration (source code changes + SKILL.md)
  • Utility skill - adds a standalone tool (code files in .claude/skills/<name>/, no source changes)
  • Operational/container skill - adds a workflow or agent skill (SKILL.md only, no source changes)
  • Fix - bug fix or security fix to source code
  • Simplification - reduces or simplifies source code
  • Documentation - docs, README, or CONTRIBUTING changes only

None of the checkbox categories fit cleanly. This is a small source-only change that adds capability (HTTP/SSE MCP transports), not a bug fix and not a skill. CONTRIBUTING.md says features should be skills — but this isn't skill-able, since the type definition lives in the agent-runner and gates what every skill can configure. Happy to discuss whether this belongs in source or whether you'd prefer a different shape; in the meantime, no box ticked since none apply.

Description

Widens McpServerConfig from a stdio-only shape to a discriminated union that mirrors the transports the Claude Agent SDK already supports:

  • type: 'stdio' (default) — { command, args?, env? } (existing behavior, unchanged)
  • type: 'http'{ url, headers? } (Streamable HTTP)
  • type: 'sse'{ url, headers? } (Server-Sent Events)

Stdio entries without an explicit type continue to work — no existing container.json files need to change.

For HTTP and SSE the agent-runner hands the config straight through to the SDK; the SDK handles the transport. No host-orchestrator change, no Dockerfile change, no new dependencies.

Motivation

Today every MCP server is a subprocess of the agent container. That's fine for servers whose runtime fits cleanly in-container, but it ties some configurations to the agent's namespace that don't need to be there. The HTTP/SSE transports let an MCP server live outside the agent container — on the host, in a sidecar container, or as a hosted service — addressed by URL.

The concrete near-term use case is MCP servers that talk raw TCP+TLS protocols (IMAP, SMTP, Postgres, Redis, etc.) where credentials must be injected at the protocol layer (HTTPS-proxy approaches like OneCLI don't help). Running such a server out-of-container keeps the credentials out of the agent's environment without requiring NanoClaw to grow protocol-specific proxying.

Files

  • src/container-config.ts — host type widened. instructions? kept on every variant; claude-md-compose.ts already reads it from any MCP entry.
  • container/agent-runner/src/providers/types.ts — provider-side type widened to match.
  • container/agent-runner/src/config.tsRunnerConfig.mcpServers references the union type instead of an inline stdio shape.
  • container/agent-runner/src/index.ts — startup log line handles all three variants (stdio prints command, http/sse print URL).

Possible follow-up

This PR only widens the type so externally-hosted MCP servers can be addressed. If there's interest, I can follow up with a separate PR that also lets container.json declare how a sidecar MCP server is launched and managed (a sidecars block: image, env, lifecycle, networking) so NanoClaw can spawn and reap them alongside the agent container, instead of leaving that to the operator.

Note on CI failure

The two failing tests in src/host-sweep.test.ts (resetStuckProcessingRows — orphan claim cleanup) are not caused by this PR. Verified by running them against pristine upstream/main code with none of this PR's changes applied — both fail identically. They're a regression from #2183 (the openOutboundDbRw reopen path doesn't match the in-memory test DB) that I will fix in a different PR.

@cfis cfis requested review from gabi-simons and gavrielc as code owners May 3, 2026 05:31
@github-actions github-actions Bot added follows-guidelines PR was created using the current contributing template PR: Fix Bug fix labels May 3, 2026
@cfis
Copy link
Copy Markdown
Contributor Author

cfis commented May 3, 2026

Note for maintainer: PR: Fix was auto-added when I (incorrectly) checked the Fix box in an earlier edit. I've since unchecked it because this is adding capability, not fixing a bug, and none of the template's category boxes cleanly applies. I don't have permissions to remove the label myself — please relabel as appropriate (or remove if it doesn't fit any existing category).

Widens McpServerConfig to a discriminated union that mirrors the four
transports the Claude Agent SDK already supports:

  type: 'stdio' (default) — { command, args?, env? }
  type: 'http'            — { url, headers? }    (Streamable HTTP)
  type: 'sse'             — { url, headers? }    (Server-Sent Events)

Stdio entries without an explicit `type` continue to work as before, so
no existing `container.json` files need to change.

For HTTP and SSE the agent-runner just hands the config through to the
SDK as-is; the SDK does the actual transport setup. No change to host
orchestration, no Dockerfile change, no new dependencies.

Touches:
  - src/container-config.ts (host) — type widened, instructions? kept
    on every variant (claude-md-compose reads it from any MCP entry).
  - container/agent-runner/src/providers/types.ts — provider-side type
    widened to match.
  - container/agent-runner/src/config.ts — RunnerConfig.mcpServers now
    references the union type instead of an inline stdio shape.
  - container/agent-runner/src/index.ts — startup log handles all three
    variants (stdio prints command, http/sse print URL).

Why: this lets an MCP server live outside the agent container — on the
host, in a sidecar container, or as a hosted service — addressed by URL
instead of as a subprocess. Useful for any MCP server whose runtime
needs aren't a fit for the agent container (e.g. credentials that the
agent shouldn't see, OS-specific dependencies, processes that should
outlive a single agent session). Concrete near-term motivation:
servers that talk raw TCP+TLS protocols (IMAP, SMTP, Postgres, Redis)
where credential injection has to happen at the protocol layer rather
than at the HTTPS proxy OneCLI provides; running those out-of-container
keeps the secrets out of the agent's namespace.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

follows-guidelines PR was created using the current contributing template PR: Fix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant