Skip to content

Add HTTP (streamable) transport to MCP client + inline MCP tool rendering - #180

Merged
stippi merged 3 commits into
mainfrom
mcp-http-transport
Aug 16, 2026
Merged

Add HTTP (streamable) transport to MCP client + inline MCP tool rendering#180
stippi merged 3 commits into
mainfrom
mcp-http-transport

Conversation

@stippi

@stippi stippi commented Aug 16, 2026

Copy link
Copy Markdown
Owner

What

Adds an HTTP (streamable) transport to MCP client mode, alongside the existing stdio transport, and reworks how MCP tool blocks render in the gpui UI.

MCP client — HTTP transport

  • McpServerConfig now carries a typed, #[serde(untagged)] McpTransport enum. The JSON shape selects the transport:
    • an object with a url (plus optional headers) → HTTP
    • an object with a command (plus args/env) → stdio
    • Existing mcp-servers.json files stay valid (backward compatible).
  • ${VAR} substitution now applies to HTTP headers values as well as stdio env values.
  • The client builds a reqwest-backed StreamableHttpClientTransport with custom headers (rmcp feature transport-streamable-http-client-reqwest + reqwest).
  • connect_stdio() / connect_http() are symmetric private helpers behind connect().
  • The gpui MCP Servers settings section gained a transport selector (command/args/env vs url/headers).

Example config:

{
  "servers": {
    "jira":   { "command": "npx", "args": ["-y", "some-jira-server"] },
    "remote": { "url": "https://example.com/mcp",
                "headers": { "Authorization": "Bearer ${REMOTE_TOKEN}" } }
  }
}

gpui — MCP tool block rendering

Previously MCP tools (dynamic mcp__<server>__<tool> names) had no registered renderer and fell back to a raw [name] placeholder. Now:

  • New McpToolRenderer (inline/lightweight style), installed as the registry's MCP fallback via ToolBlockRendererRegistry::resolve.
  • Generic MCP icon + bare tool name (get_me); the server name (github_tools_sap) shows as a right-aligned pill via a new ToolBlockRenderer::header_tag() hook.
  • Tool JSON output is pretty-printed and rendered in a monospace font; non-JSON output is shown verbatim.

Tests

  • Config: round-trip + ${VAR} substitution for both transports.
  • New in-process axum HTTP server integration test (connects_and_calls_over_http) exercising the full HTTP path: connect, tools/list, tools/call.
  • pretty_json / parse_mcp_name unit tests.
  • cargo fmt, clippy -D warnings, and the touched crates' tests are green; validated end-to-end against a real HTTP MCP server.

Note

This branch also contains the pre-existing, unrelated commit 26875a47 ("Fix previous_response_not_found after WebSocket reconnect"), which was already on the branch before this work.

stippi added 3 commits August 14, 2026 17:12
The incremental-input delta (previous_response_id + delta items) was
computed before ensure_connection() ran. When the server had closed the
socket in the meantime, ensure_connection() correctly dropped the stale
connection and cleared the delta state - but the request had already
been built against the dead connection's response id, which the fresh
connection does not know (store: false keeps response state only for
the lifetime of one connection). The server then rejected the request
with 400 previous_response_not_found.

Ensure the connection is live before computing the delta, so a
reconnect automatically falls back to sending the full transcript.
Extend MCP client mode with an HTTP streamable transport alongside stdio.
McpServerConfig now carries a typed, untagged McpTransport enum: an object
with a "url" is HTTP (with optional "headers"), one with a "command" is
stdio -- so existing mcp-servers.json files stay valid. ${VAR} substitution
now covers HTTP header values as well as stdio env values.

The client builds a reqwest-backed StreamableHttpClientTransport with custom
headers (rmcp feature transport-streamable-http-client-reqwest). Added an
in-process axum HTTP server integration test. The gpui MCP settings section
gains a transport selector (command/args/env vs url/headers).
MCP tools have dynamic mcp__<server>__<tool> names, so no renderer was
registered for them and they fell back to a raw "[name]" placeholder.

Add a McpToolRenderer (inline style) installed as the registry's MCP
fallback (ToolBlockRendererRegistry::resolve). It shows a generic MCP icon,
the bare tool name, and the server name as a right-aligned pill via a new
ToolBlockRenderer::header_tag() hook. JSON output is pretty-printed and
rendered in a monospace font; non-JSON output is shown verbatim.
@stippi
stippi merged commit 4211212 into main Aug 16, 2026
5 checks passed
@stippi
stippi deleted the mcp-http-transport branch August 16, 2026 07:10
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