Repository navigation
Conversation
Connect to one MCP server over stdio or Streamable HTTP through the official SDK. Stdio servers run on the host in their own process group and are stopped with the group; HTTP connects retry transient failures. List pages and tool results are validated by the SDK. The process-group stop sequence moves out of the host shell into a shared Process.terminate helper. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Connections pass the server's notifications/message entries to an onLog handler, and McpLog appends them to a file with one line per entry, rotating it past 5 MB. A result that fails the SDK's schema is reported on one line as `Invalid result for <method>: <path>: <message>` instead of the validator's multi-line issue list, which is still logged at debug level. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Name the MCP entry points with Effect.fn and give each request its own span. A server without resource templates is now recovered from inside the Effect rather than on the SDK promise. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Count stderr as an open pipe, so a descendant holding only stderr is still killed with the server's process group. - Bound the whole connect attempt by the startup timeout; the SDK only times the initialize request, not the initialized notification. - End the HTTP session a failed connect attempt was given, through a fresh transport, since the SDK aborts the failed transport's signal. Tests now cover these, retries of reads but not tool calls, session termination and 400 classification, and register their own teardown for spawned processes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The process spawner kills the group when the connection's scope closes, which hid a missing kill. Assert instead that a grandchild holding only stderr is gone once the connection reports the server's exit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 tasks done
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the low-level MCP client the MCP service will build on: one scoped connection to one server, over stdio or Streamable HTTP, through the official SDK (
@modelcontextprotocol/client2.3.1).src/mcp/client.ts:McpClient.connect(...)returns aConnectionwithtools(),resources(cursor?),resourceTemplates(cursor?),readResource(uri),callTool(...)andonToolsChanged/onResourcesChanged/onSessionExpired/onClosecallbacks.SessionExpiredError, auth failures becomeNeedsAuthError.onClose.src/mcp/stdio.ts: stdio transport. Servers run on the host in their own process group.src/mcp/content.ts: tool results as model text and image content.src/mcp/error.ts: tagged errors.SDK validation: list pages and tool results (against a tool's
outputSchema) are validated by the SDK.Process.terminate: the process-group stop sequence moves out of the host shell intosandbox/utils/process.ts, shared by the host shell and the stdio transport.Server logging:
onLogreceives the server'snotifications/messageentries, andsrc/mcp/log.ts(McpLog) appends them one line per entry, rotating the file past 5 MB.Readable validation errors: the SDK's multi-line issue list becomes one line,
Invalid result for <method>: <path>: <message>; the raw list is logged at debug level.Tracing: entry points use
Effect.fn(McpClient.connect,McpStdio.make,McpLog.make), and each request gets a span namedMcpClient.<method>.No user-facing surface yet: config, the MCP service, scoping and tool wiring come in follow-up PRs stacked on this one.
Test plan
test/mcp.client.test.ts: 29 scenarios against real stdio and Streamable HTTP fixture servers.__artifacts__/mcp.client.json, stable across runs.Process.terminateextractionvp checkandvp run typecheck🤖 Generated with Claude Code