feat(server): server extensions and Protocol.overrideRequestHandler - #2820
Draft
mattzcarey wants to merge 1 commit into
Draft
mattzcarey wants to merge 1 commit into
mattzcarey wants to merge 1 commit into
Conversation
ServerOptions.extensions takes ServerExtension objects ({ id, capability?,
install(server) }). Each is advertised under capabilities.extensions[id]
and installed at construction, after the built-in handlers exist.
Extensions register custom methods with the explicit-schema
setRequestHandler and intercept spec methods with the new
Protocol.overrideRequestHandler(method, (request, ctx, next) => ...).
Overrides compose around the registered handler at dispatch time, so an
override on tools/call applies even though McpServer registers that
handler lazily; the returned function removes the override.
McpServer tool dispatch re-throws MissingRequiredClientCapabilityError
(-32021) as a JSON-RPC error instead of an isError tool result, matching
the UrlElicitationRequiredError passthrough.
🦋 Changeset detectedLatest commit: f195b40 The changes in this PR will be included in the next version bump. This PR includes changesets to release 6 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@modelcontextprotocol/client
@modelcontextprotocol/codemod
@modelcontextprotocol/core
@modelcontextprotocol/server
@modelcontextprotocol/server-legacy
@modelcontextprotocol/express
@modelcontextprotocol/fastify
@modelcontextprotocol/hono
@modelcontextprotocol/node
commit: |
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.
What this adds
A way to package protocol behaviour outside the core spec — an MCP extension such as
io.modelcontextprotocol/tasks, or a vendor feature — as one object the server installs:ServerOptions.extensionstakesServerExtensionobjects:{ id, capability?, install(server) }. Each is advertised undercapabilities.extensions[id]({}by default) and installed at construction, in order, after the built-in handlers exist. Same option on the low-levelServer.Protocol.overrideRequestHandler(method, (request, ctx, next) => …)is the new seam an extension uses to intercept a spec method. Overrides compose around the registered handler at dispatch time, so an override ontools/callinstalled at construction still applies even thoughMcpServerregisters that handler on the first tool registration. With no underlying handler,nextthrowsMethodNotFound. Later overrides nest outside earlier ones; the returned function removes the override. A thrownProtocolErrorbecomes the JSON-RPC error response.setRequestHandler(method, { params, result }, handler); nothing new there.McpServertool dispatch re-throwsMissingRequiredClientCapabilityError(-32021) as a JSON-RPC error instead of converting it into anisErrortool result, the same passthroughUrlElicitationRequiredErroralready has. Extensions that gatetools/callon a client capability need the client to see the error as an error.The SDK owns the seams and the capability advertisement. How an extension stores state or where its work runs is the extension's own.
Tests
packages/core-internal/test/shared/overrideRequestHandler.test.ts— wraps and transforms, answers withoutnext, throws become JSON-RPC errors, applies to a later-registered handler,MethodNotFoundwith nothing underneath, nesting order, removal.packages/server/test/server/extensions.test.ts— advertised capability and install order,{}default throughMcpServer, extension custom method served,tools/calloverride refusing with-32021and passing through with the capability,-32021from inside a tool handler is a JSON-RPC error.Docs
docs/advanced/extensions.md, linked from the Advanced nav next to Custom methods.Not in this PR