The official TypeScript SDK for Model Context Protocol servers and clients
by modelcontextprotocolTypeScript
Last 12 weeks · 112 commits
5 of 6 standards met
Description When a stdio pipe is backed up, write() returns false and every concurrent send() registered its own once('drain') listener. Once 11+ messages were in flight, Node and Bun emitted \MaxListenersExceededWarning\ and dumped the whole stream object to the console. Two real-world triggers: a client talking to a slow-starting child process (e.g. a Python MCP server booting under uv) that isn't reading stdin yet - every request during startup queues up bulk \sendToolListChanged()\ notifications on the server side (#842) This adds a small \DrainWait\ helper in core-internal: all sends that overlap on a backed-up stream share one listener and one promise (max 1 \drain\ listener at any time). Both \StdioClientTransport\ and \StdioServerTransport\ now use it. As a side effect the client's \send()\ now rejects on stdin errors instead of waiting forever - previously a pending send could hang indefinitely if the child died mid-write. Test plan New client tests: 15 concurrent sends against a mocked stdin that always reports backpressure -> exactly 1 \drain\ listener at peak, all sends resolve on drain; pending sends reject on stdin \error\ instead of hanging New server test: same scenario through a backed-up Writable Verified the new tests fail against the old implementation (client 2/2 fail, server 1/1 fail) Full client (794 passed) and server (466 passed) suites show no new failures; typecheck and prettier clean on all touched packages Fixes #842
Summary preserve the originating client request ID across a Streamable HTTP POST SSE response stream expose it through the existing callback carrier for server-initiated JSON-RPC requests keep standalone GET messages and normal responses backward-compatible add a client patch changeset and transport regression test Verification Regression proof: before the source change, the focused test received no attributed server request. After the fix: passes 70/70. typecheck passes. typecheck passes. Prettier and pass. Fixes #2659
Problem validates against the raw shape only; / / constraints never run. A payload rejected by passes the server gate — a fail-open validation gap for tools whose security-critical constraints are expressed via refine/superRefine. Suggestion 1. Run the full ZodObject parse (the authoritative ) in the tool wrapper, or 2. Document the limitation loudly in the signature so integrators know refine-level constraints require their own wrapper. Context Observed on 1.30.0. Our mitigation: the tool wrapper runs an authoritative itself before delegating (regression-tested).
I've updated to 1.25.1, and I get ../../node_modules/@modelcontextprotocol/sdk/dist/esm/server/streamableHttp.d.ts:58:22 - error TS2420: Class 'StreamableHTTPServerTransport' incorrectly implements interface 'Transport'. Types of property 'onclose' are incompatible. Type '(() => void) | undefined' is not assignable to type '() => void'. Type 'undefined' is not assignable to type '() => void'. 58 export declare class StreamableHTTPServerTransport implements Transport { ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Found 1 error. I suspect this is due to "exactOptionalPropertyTypes": true in my tsconfig.json.
Motivation and Context Tools, prompts, resources and resource templates registered on can all be toggled with /. A disabled one drops out of its list verb and is rejected when invoked. #247 added this for all four primitives at once. Resource templates are the exception.** has the field and does flip it, but none of these four handlers read it. As a result, a disabled resource template is still exposed in the four responses above. In order to fix, the missing check at all four sites, in two shapes: and filter disabled templates out. Nothing was addressed specifically, so there is nobody to report a failure to. and throw , since the client named a specific resource template. How Has This Been Tested? Four tests in , one per request path, each committed ahead of its fix so it can be checked red → green. : a disabled static resource and a disabled template drop out, the enabled template stays : the disabled template's URI pattern is gone : a URI matching a disabled template is rejected with + : a completion aimed at a disabled template is rejected the same way The first testcase() also covers the static-resource filtering. That already worked, but it sits in the same handler as the template path, so pinning it down keeps a fix on one side from breaking the other. Breaking Changes No API change. Types of changes [x] Bug fix (non-breaking change which fixes an issue) [ ] New feature (non-breaking change which adds functionality) [ ] Breaking change (fix or feature that would cause existing functionality to change) [ ] Documentation update Checklist [x] I have read the MCP Documentation [x] My code follows the repository's style guidelines [x] New and existing tests pass locally [x] I have added appropriate error handling [ ] I have added or updated documentation as needed Additional context For I went with throwing, following the disabled prompt case. The branch below in the same handler returns for static resources. If that's the better fit here, I'm happy to change it. Let me know. fixes: #2696
Repository: modelcontextprotocol/typescript-sdk. Description: The official TypeScript SDK for Model Context Protocol servers and clients Stars: 13236, Forks: 2113. Primary language: TypeScript. Languages: TypeScript (97.3%), JavaScript (2.6%), Shell (0.1%). Homepage: https://ts.sdk.modelcontextprotocol.io/v2 Topics: mcp, mcp-client, mcp-server, typescript. Latest release: @modelcontextprotocol/fastify@2.0.0 (3w ago). Open PRs: 100, open issues: 473. Last activity: 21h ago. Community health: 87%. Top contributors: jspahrsummers, ihrpr, felixweinberger, ochafik, KKonstantinov, bhosmer-ant, mattzcarey, jerome3o-anthropic, cliffhall, allenzhou101 and others.