Repository navigation
build: update dependency @modelcontextprotocol/server to v2.3.1 (22.2.x) - #34266
Merged
alan-agius4 merged 1 commit intoOct 7, 2026
Conversation
See associated pull request for more information.
alan-agius4
approved these changes
Oct 7, 2026
alan-agius4
deleted the
ng-renovate/22.2.x-modelcontextprotocol-server-2-x
branch
October 7, 2026 06:36
Collaborator
|
This PR was merged into the repository. The changes were merged into the following branches:
|
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.
This PR contains the following updates:
2.0.0→2.3.1Release Notes
modelcontextprotocol/typescript-sdk (@modelcontextprotocol/server)
v2.3.1Compare Source
Patch Changes
v2.3.0Compare Source
Minor Changes
#2929
40f8f4eThanks @claude! -requireBearerAuthandverifyBearerTokentake a new optionalexpectedResource, which makes them accept only tokens issued for this resource (the token's audience). Set it to the value your authorization server puts into tokens meant for this server, usually the server's URL. When it is set, a token is accepted only if the verifier reports that value inAuthInfo.resource; the two are compared as strings, ignoring a fragment and one trailing slash. A token reported for another value, or for none, is answered401 invalid_tokenwith the usualWWW-Authenticatechallenge. When it is not set, nothing changes. To use it, passexpectedResourceand haveverifyAccessTokenfillAuthInfo.resource, for example from theaudclaim. The option is declared on a new exported type,VerifyBearerTokenOptions, which extendsBearerAuthOptions;BearerAuthOptionsitself is unchanged. The ExpressrequireBearerAuthpasses the option through. With Express,@modelcontextprotocol/expresshas to be upgraded to this release as well: 2.0.1 does not pass the option on, so nothing is compared. Its options type does not have the option, so TypeScript reports anexpectedResourcewritten in a call to the 2.0.1requireBearerAuthas an error.#2926
6d8dbc6Thanks @claude! -McpServernow accepts amaxToolInputElementsoption that limits the number of elements in tool-call arguments: the largest combined number of array elements and object members a singletools/callargumentspayload may contain. It is off by default, so behavior is unchanged unless you set it. When it is set and a call exceeds it, that call is answered with anisError: truetool result that names the limit, before the input schema runs, and the server keeps serving. Set it above the largest arguments your tools legitimately accept;maxRequestBodySizeremains the primary limit on request size. The value must be a number of at least 1, orInfinityfor no limit; any other value is rejected at construction. The options type is exported asMcpServerOptions.#2918
84804c2Thanks @claude! - AServerorMcpServernow serves one connection at a time, and a Streamable HTTP server transport without sessions (sessionIdGenerator: undefined) serves one request. An app that uses one server object, or one stateless transport, for every HTTP request fails on the second request after this upgrade. Build the server and the transport per request instead.What keeps working without a change:
createMcpHandler(buildServer)andserveStdio(buildServer), wherebuildServerreturns a new server on every call.sessionIdGenerator).close().Client.What fails now, how it shows, and what to change:
const server = new McpServer(...)outside the handler,await server.connect(transport)inside it): the second HTTP request the process receives fails, and so does every later one.connect()rejects with anSdkErrorof codeALREADY_CONNECTED. If the handler closes the transport when the response ends, requests that arrive one after the other still work and a request that overlaps another one fails. Change: movenew McpServer(...)and its registrations into the handler.sessionIdGenerator: undefined): the second HTTP request fails.WebStandardStreamableHTTPServerTransport.handleRequest()rejects withStateless transport cannot be reused across requests. Create a new transport per request., andNodeStreamableHTTPServerTransport.handleRequest()answers500. Change: build the server and the transport inside the handler and connect them there.createMcpHandler(() => server)with a server built once: a request that arrives after the previous response has been read to its end still works. A request that arrives while another one is being served is answered500with the JSON-RPC error-32603(Internal server error); the reason is reported only through theonerroroption. Change: pass a function that builds the server, as increateMcpHandler(buildServer).initializerequest of the second session fails withALREADY_CONNECTED. Change: build a server per session.What the caller sees when
connect()orhandleRequest()rejects depends on the host. Express 5, Fastify and Hono answer500. A plainnode:httplistener without its own error handling gets an unhandled rejection, which ends the process.The README examples of
@modelcontextprotocol/express,@modelcontextprotocol/fastify,@modelcontextprotocol/honoand@modelcontextprotocol/node, and the handler examples in the JSDoc ofWebStandardStreamableHTTPServerTransportandNodeStreamableHTTPServerTransport, now build a server and a transport per request.#2907
e55f9acThanks @claude! -allowedOriginsandvalidateOriginHeaderaccept lowercase entries of the form<scheme>://*, such asmoz-extension://*orchrome-extension://*, which admit every origin of that scheme. This lets a server admit MCP clients that run as a browser extension when the extension ID cannot be listed, as on Firefox, where it differs on every install.http://*andhttps://*are not honoured, and the defaults are unchanged.Patch Changes
#2599
5238fbaThanks @freya0926! - A server can now serve, and a client can now call,tasks/getandtasks/cancelof the Tasks extension (SEP-2663) on a 2026-07-28 connection, when the handler is registered and the request is sent with an explicit schema. Every other method that a protocol revision removed is still refused. If one server factory serves both eras and such a handler is meant for 2025-era clients only, register it only whenctx.era === 'legacy'.#2107
2fc49eaThanks @pragnyanramtha! -prompts/getwithoutargumentsno longer fails with "Invalid arguments" when every argument of the prompt is optional. A missingargumentsis now validated as{}, as it already is fortools/call, so a top-level.optional()or.default(...)onargsSchemano longer seesundefined.#2889
4d94e7bThanks @claude! -registerToolno longer converts tool schemas up front, so a server built per request stops converting every tool on every request. The warning about an invalidx-mcp-headerdeclaration now appears each time tools are listed, not when the tool is registered.#2908
633dd3eThanks @claude! - Thelicensefield of the package manifests is nowApache-2.0; theLICENSEfile shipped in each package carries the full terms, including the MIT text for earlier contributions. No code change.#2841
2237555Thanks @sharziki! -McpServer.registerPrompt()now types the callback correctly when noargsSchemais given: its one parameter is the server context. Before, readingctx.mcpReqthere was a type error although it worked at runtime. Prompts registered with anargsSchemaare unchanged.Updated dependencies [
633dd3e]:v2.2.0Compare Source
Patch Changes
#2885
9dd722fThanks @claude! - Sending a notification on a closed connection no longer produces a briefly unhandled promise rejection (seen asunhandledrejectionon Cloudflare Workers) in addition to the returned rejection.#2778
e3fb9edThanks @vjymisal0! - Fix a stack overflow increateMcpHandlerwhen the factory returns the same server instance for more than one request. Returning a fresh instance per request is still required.#2651
c55efa6Thanks @sushantkumar23! -createMcpHandlernow ends asubscriptions/listenstream right after the acknowledgement when it honored none of the requested notification types, instead of holding the stream open with nothing to deliver. The client receives the acknowledgement and then theresultType: "complete"result. Streams that honor at least one type are unchanged.Updated dependencies [
edd12e2]:v2.1.0Compare Source
Minor Changes
#1624
6032170Thanks @SamMorrowDrums! - Add request-time OAuth scope challenges for tools, resources, resource templates,and prompts. Each primitive's
scopeChallengecallback receives the parsedrequest and verified authentication info, then either continues or returns the
exact scope set for an
insufficient_scoperesponse.requireScopesprovides asmall helper for static all-of checks.
createMcpHandlerand Streamable HTTP transports return HTTP 403 with aninsufficient_scopechallenge before handler execution or SSE setup. Thepreflight is active whenever a registered primitive carries a
scopeChallengecallback — there is no handler- or transport-level configuration. The
challenge's
WWW-Authenticateheader is built by the same formatter as thebearer-auth 401/403 answers, and its
resource_metadataparameter is derivedfrom the verified
AuthInfo:requireBearerAuth/verifyBearerTokennowstamp their configured
resourceMetadataUrlonto theAuthInfothey return(new optional
AuthInfo.resourceMetadataUrlfield), with a fallback to thewell-known location for an HTTP(S) RFC 8707
resourceidentifier; theparameter is omitted when neither is available.
Patch Changes
#2726
6fa4227Thanks @LuckTerence! -SdkErrorandSdkHttpErroraccept standardErrorOptionsas an optional fourth constructor argument and forward it toError, so a wrapped error is reachable through the standardError.causechain. Version-negotiation probe failures (SdkErrorCode.EraNegotiationFailed) now use it: the underlyingTypeError: fetch failedand the DNS or socket error beneath it surface viaerror.cause, so pino, Sentry, andutil.inspectrenderENOTFOUND/ECONNREFUSED/ETIMEDOUTinstead of stopping at theSdkError(#2657). The previouserror.data.causeslot is still populated for compatibility but is deprecated and slated for removal; readerror.causeinstead.#2654
03842cdThanks @pshah19! - Treat request id0as a real id. Two guards tested aRequestIdfor truthiness, so the legal JSON-RPC ids0and''were read as absent. Id0is not a corner case: the outbound request counter is zero-based, so it is the first id every peer assigns, which on the server→client leg is the firstsampling/createMessage,elicitation/create, orroots/lista server sends.notifications/cancelledcarrying id0was ignored, and the in-flight handler ran to completion with itsAbortSignalnever fired.relatedRequestId: 0wrongly passed the debounce gate (for methods opted intodebouncedNotificationMethods). Because the pending set is keyed by method alone, a second such notification in the same tick was silently dropped rather than sent.Absent is now the only value that means "no id".
#2668
3e90449Thanks @KKonstantinov! - Stop sendingnotifications/cancelledfor theinitializehandshake. The spec is explicit that a client MUST NOT attempt to cancel itsinitializerequest, but the outbound cancel path fired for any in-flight request: aborting theAbortSignalpassed toconnect(), or letting the handshake hit its timeout, put a forbidden cancellation on the wire naming the initialize request id.The local behaviour is unchanged — the caller's promise still rejects with the same abort/timeout error, and
connect()still tears the connection down. Only the wire notification is suppressed. Every other method keeps the existing cancellation path.#2698
7b781edThanks @maxisbey! - Read Streamable HTTP request bodies with a size limit. Every SDK-owned body read —WebStandardStreamableHTTPServerTransport(and the Node transport built on it),createMcpHandler,toNodeHandler, andcreateMcpHonoApp's JSON pre-parse — now stops at4 MiB by default (the limit the legacy SSE transport already uses; the Express adapter and stdio
bound their reads too) and answers
413 Payload Too Largebefore anything is parsed.toWebRequest(when it reads the Node stream itself) now rejects once the body exceeds thelimit with an error whose
nameis'RequestBodyTooLargeError'andstatusis413, andtoNodeHandleranswers that with413; hand-wired callers oftoWebRequestshould handle therejection or pass a pre-parsed body, and
isLegacyRequestreports such a request as non-legacyso the modern handler answers it. JSON-RPC batch arrays are limited to 100 messages; a longer
batch is answered
400/-32600and none of it is dispatched.The limit is configurable with a new
maxRequestBodySizeoption (bytes, defaultDEFAULT_MAX_REQUEST_BODY_SIZE= 4 MiB, exported from@modelcontextprotocol/server) onWebStandardStreamableHTTPServerTransportOptions,CreateMcpHandlerOptions(forwarded to itsstateless legacy leg;
isLegacyRequestandlegacyStatelessFallbacktake the same option),CreateMcpHonoAppOptions, andToNodeHandlerOptions/ToWebRequestOptions(the adapter'sbound applies before the handler's, so raise both). The bounded reader is exported as
readRequestBodyfor adapter authors. Hosts that pre-parse the body and pass it asparsedBodyskip the SDK's read and its size limit entirely; the batch bound applies either way.createMcpHonoAppandcreateMcpExpressAppnow run their Host/Origin validation before theJSON body parser, so a request from a disallowed Host or Origin with an invalid JSON body is
answered
403rather than400, and its body is not read.#2590
75dc7eaThanks @davidpavlovschi! - Reject a modern (2026-07-28) POST that omits the requiredMCP-Protocol-Versionheader.createMcpHandleraccepted a request whose body carried a valid per-request_metaenvelope but whose
MCP-Protocol-Versionheader was absent: the request was classifiedmodern, dispatched, and answered
200— tool handlers ran. Only the mismatch case(header present, disagreeing with the body) was rejected, so of the standard headers
SEP-2243 requires on a modern POST, presence was enforced for
Mcp-Method(and forMcp-Nameon the methods that mirrorparams.name/params.uri) but not forMCP-Protocol-Version.Such a request is now refused with
400 Bad Requestand JSON-RPC-32020(
HeaderMismatch), matching the shape the sibling missing-header cells already emit andechoing the request id — per the Streamable HTTP spec, which requires the header on every
POST and lists a missing required standard header as a
HeaderMismatchfailure. Thespec's allowance to treat a header-less request as
2025-03-26is available only to aserver that also serves pre-2025-06-18 clients, and permits routing it to legacy
handling — never serving it as 2026-07-28; under
legacy: 'reject'the requirement isunconditional.
Era classification is deliberately unchanged and stays body-primary: a proxy that strips
the header still must not change the era, so such a request is still classified modern
and is refused one rung later, at
standard-header-validation— the same rung thatalready answers a missing
Mcp-Method. Legacy-era traffic is untouched, notificationsare unaffected, body-less
GET/DELETEsession operations are method-routed beforeany header validation, and stdio serving (which has no HTTP headers) is not involved.
Clients built with this SDK always send the header, so no first-party client is affected;
hand-rolled clients that omitted it must add it.
#2494
6a05402Thanks @claude! -StdioServerTransportnow closes itself and firesonclosewhen its stdin ends or closes. The stdio binding says servers "SHOULD exit promptly when their standard input is closed" — stdin EOF is the primary graceful-shutdown signal, and on some platforms (notably Windows, where no signal is delivered when the parent goes away) the only reliable one. Previously the transport listened only fordataanderror, so when an MCP client hung up its end of the pipe (window closed, session restarted, host crashed) the server never noticed:onclosenever fired, nothing tore down, and server processes accumulated as zombies until killed by hand. The transport now attachesend/closelisteners on stdin that close the transport (idempotently —onclosestill fires exactly once ifclose()is also called), soServer/McpServerandserveStdiotear down through the existingonclosechain and a well-behaved server process exits naturally. Requests still in flight when stdin ends are aborted (their handlers observesignal.aborted) and their responses are not written: EOF means the client has hung up and is no longer waiting. A client that wants answers keeps stdin open until it has read them.#2613
70de0c8Thanks @jwcarman! - Emit and validate theMcp-Nameheader for tasks requests per SEP-2663's Streamable HTTP binding: the client transport now mirrorsparams.taskIdintoMcp-Nameontasks/get/tasks/update/tasks/cancel(previously omitted, causing conforming servers to reject every task poll with-32020 HeaderMismatch), and the server-side standard-header validation cross-checks it via the same sharedMCP_NAME_HEADER_SOURCEtable.On the server,
createMcpHandlernow answers a modern (2026-07-28)tasks/get/tasks/update/tasks/cancelPOST that omitsMcp-Name, or whose header disagrees withparams.taskId, with400/-32020(HeaderMismatch) at thestandard-header-validationrung, the same treatmenttools/call/prompts/get/resources/readalready get. Legacy-era (2025-11-25) tasks traffic is unaffected. Clients built with this SDK release send the header; hand-rolled clients that omitted it must add it.Updated dependencies [
dcc0102]: