mcp://¶
Call a tool on an external MCP (Model Context Protocol) server from inside a Helix route. The producer opens a single MCP session per endpoint (lazy sync.Once), packs the exchange body into the tool's argument shape, invokes CallTool, and writes the text response back onto the exchange. Reach for mcp:// when an existing MCP server (Claude desktop tools, third-party MCP integrations, another Helix node running mcp-server://) exposes a tool you want to call from a workflow.
For the other half of the integration — exposing Helix routes as MCP tools — see mcp-server://.
URI shape¶
<server-addr>is the host:port (HTTP/SSE) or executable path (stdio) of the MCP server. The path is split at the last/: everything before is the address, the last segment is the tool name.<tool-name>is the MCP tool to call. Can be overridden per exchange via theHelixMcpToolNameheader.- Producer-only —
CreateConsumerreturns an error.
Parameters¶
| Param | Type | Default | Producer/Consumer/Both | Description |
|---|---|---|---|---|
(path) server-addr |
string | — | Producer | Host:port of the MCP server, or the binary path for stdio. |
(path) tool-name |
string | — | Producer | Tool to invoke. Required unless overridden by HelixMcpToolName. |
transport |
enum | http |
Producer | http (Streamable HTTP — the default), sse (SSE), or stdio (subprocess). |
The component uses the official Anthropic SDK github.com/modelcontextprotocol/go-sdk v1.4.0+. Identity is hard-coded to helix-mcp-client/1.0.0.
Headers¶
Read by the producer¶
| Header | Description |
|---|---|
HelixMcpToolName |
Per-exchange override of the tool to call (wins over the URI path). Use this when the same connection invokes different tools depending on the exchange. |
Written by the producer¶
| Header | Description |
|---|---|
HelixMcpToolName |
The tool name actually invoked. |
HelixMcpIsError |
Boolean — true if the MCP tool returned IsError=true. |
When IsError=true, the producer also calls ex.SetException(...) so the route's error handler kicks in; the response body still contains the tool's text content (or "mcp tool returned error with no message").
Body shaping¶
The body is converted to MCP Arguments (map[string]any) by:
map[string]any→ used as-is.string,[]byte,json.RawMessage→ JSON-decoded into a map; on parse failure wrapped as{"input": <raw>}.nil→{}.- anything else →
{"input": fmt.Sprintf("%v", body)}.
The response is unpacked in this order:
1. concatenated TextContent from result.Content,
2. fallback to JSON-marshalled result.StructuredContent,
3. empty string.
Examples¶
Call an HTTP MCP server tool:
workflows:
- id: ask-search
trigger: { uri: direct://ask }
steps:
- set-body:
starlang: '{ "query": payload, "limit": 5 }'
- target: mcp://localhost:8181/search
Stdio transport (subprocess MCP server):
workflows:
- id: filesystem-lookup
trigger: { uri: direct://lookup }
steps:
- target: mcp:///usr/local/bin/mcp-fs/read_file?transport=stdio
Per-exchange tool selection:
workflows:
- id: dispatch
trigger: { uri: direct://dispatch }
steps:
- set-header:
name: HelixMcpToolName
starlang: header("X-Intent")
- target: mcp://localhost:8181/_unused
End-to-end: read a payload, ask a remote MCP search tool, then summarize with a local agent:
workflows:
- id: research
trigger:
uri: http-server://0.0.0.0:8080/research
steps:
- set-body:
starlang: '{ "query": payload }'
- target: mcp://kb-server.internal:8181/search
- set-body:
starlang: '"Summarize: " ++ payload'
- target: agent://summarizer
Behavior notes¶
- Lazy connect — the first
Processcall opens the session; subsequent calls reuse it. The init error is sticky (subsequent calls fail without retrying). Restart the route to retry. - Transport differences —
httpuses the SDK'sStreamableClientTransportagainsthttp://<addr>.sseusesSSEClientTransportagainsthttp://<addr>.stdioexecs<addr>as a subprocess (the address is the binary path).- No reconnect — if the server drops the session, the next call returns an error from the SDK; there is no automatic reconnect loop.
- No streaming back — MCP tool calls are RPC-style: the producer waits for the full result. If you need streaming, expose the tool via a different protocol (A2A, AG-UI).
Source¶
pkg/component/mcp/client.go, pkg/component/mcp/tools.go
See also¶
- mcp-server — the inverse: expose Helix routes as MCP tools.
- a2a, a2a-server — A2A protocol equivalent.
- tool — Helix-native tool primitive.