Skip to content

feat(core): concrete Protocol with custom-method overloads + deprecated v1 schema-arg shims#1891

Draft
felixweinberger wants to merge 5 commits intomainfrom
fweinberger/protocol-concrete
Draft

feat(core): concrete Protocol with custom-method overloads + deprecated v1 schema-arg shims#1891
felixweinberger wants to merge 5 commits intomainfrom
fweinberger/protocol-concrete

Conversation

@felixweinberger
Copy link
Copy Markdown
Contributor

@felixweinberger felixweinberger commented Apr 14, 2026

Part of the v2 backwards-compatibility series — see reviewer guide.

Makes Protocol concrete and exported; adds 3-arg setRequestHandler(method, paramsSchema, handler) overload for custom (non-spec) methods; method-keyed request() return type; restores @deprecated v1 schema-argument overloads; adds notifyCustom() so notification() stays single-signature (mock-assignable).

Motivation and Context

v2's setRequestHandler<M extends RequestMethod> is a closed union — custom (vendor-prefixed) methods crash at runtime. This restores extensibility via a 3-arg overload, makes request() method-keyed so request({method:'tools/list'}) returns ListToolsResult, and brings back setRequestHandler(ZodSchema, h) as a @deprecated overload so v1 code keeps compiling.

v1 vs v2 patterns

v1:

server.setRequestHandler(ListToolsRequestSchema, async () => ({tools: []}));
const r = await client.request({method:'tools/call', params}, CallToolResultSchema);
client.setNotificationHandler(CustomSchema, h);  // custom method

v2-native:

server.setRequestHandler('tools/list', async () => ({tools: []}));
const r = await client.request({method:'tools/call', params});  // typed return
client.setNotificationHandler('vendor/custom', paramsSchema, h);  // 3-arg form

How Has This Been Tested?

  • Unit: customMethods.test.ts, protocol.compat.test.ts — 3-arg overload, schema-arg dispatch, mock-assignment, notifyCustom validation
  • Integration: validated bump-only against 5 OSS repos via the v2-bc-integration validation branch
  • pnpm typecheck:all && pnpm lint:all && pnpm test:all green (core 507/507)

Breaking Changes

None vs current main — additive. Supersedes the closed #1846/#1868 approach.

Types of changes

  • New feature (non-breaking change which adds functionality)

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added or updated documentation as needed

Additional context

Stacks on: C1 (deprecate() helper). This is the largest PR in the series (~+1000 LOC) — could split into "concrete Protocol + overloads" / "deprecated schema-arg shims" if preferred, but they touch the same protocol.ts.

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 14, 2026

🦋 Changeset detected

Latest commit: 070a9cd

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 7 packages
Name Type
@modelcontextprotocol/core Patch
@modelcontextprotocol/client Minor
@modelcontextprotocol/server Minor
@modelcontextprotocol/node Major
@modelcontextprotocol/express Major
@modelcontextprotocol/fastify Major
@modelcontextprotocol/hono Major

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

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 14, 2026

Open in StackBlitz

@modelcontextprotocol/client

npm i https://pkg.pr.new/@modelcontextprotocol/client@1891

@modelcontextprotocol/server

npm i https://pkg.pr.new/@modelcontextprotocol/server@1891

@modelcontextprotocol/express

npm i https://pkg.pr.new/@modelcontextprotocol/express@1891

@modelcontextprotocol/fastify

npm i https://pkg.pr.new/@modelcontextprotocol/fastify@1891

@modelcontextprotocol/hono

npm i https://pkg.pr.new/@modelcontextprotocol/hono@1891

@modelcontextprotocol/node

npm i https://pkg.pr.new/@modelcontextprotocol/node@1891

commit: 070a9cd

…erloads

- Protocol becomes concrete: 5 assert*Capability abstracts → no-op virtuals,
  buildContext → virtual with default. Client/Server override to enforce.
- setRequestHandler/setNotificationHandler gain a 3-arg
  (method: string, paramsSchema, handler) overload alongside the existing
  2-arg spec-typed form. One method, any method name.
- request() gains string-form (method, params, resultSchema) overload for
  custom methods (object-form already returns method-keyed ResultTypeMap[M]).
- notification() gains (method, params, paramsSchema?) overload.
- removeRequestHandler/removeNotificationHandler accept string.
- isRequestMethod/isNotificationMethod predicates added.
- Protocol and mergeCapabilities exported from public surface.

Enables vendor-prefixed extension methods (which the MCP spec permits) without
a separate setCustom* API.
…ient (C3/C6 in core)

- setRequestHandler/setNotificationHandler: accept Zod schema (extracts method literal, warns once)
- request(): accept (req, ResultSchema, opts?) deprecated form (schema ignored)
- callTool(): accept (params, ResultSchema, opts?) deprecated form
- sendNotification(): non-overloaded alias for notification() (test-mock friendly)
- Export AnySchema/SchemaOutput/ZodLikeRequestSchema from core/public
…m() for string-form custom methods

notification() reverts to a single (Notification, opts?) signature so test
code can do client.notification = mockFn without TS rejecting the mock for
not matching the intersection of all overloads (the fastmcp regression).
The typed string-form sender moves to a new notifyCustom(method, params,
{paramsSchema?}). Removes the sendNotification() workaround alias.
@felixweinberger felixweinberger force-pushed the fweinberger/protocol-concrete branch from db49955 to 070a9cd Compare April 15, 2026 19:38
@felixweinberger felixweinberger added the v2-bc v2 backwards-compatibility series label Apr 15, 2026
@felixweinberger felixweinberger changed the title feat(core): make Protocol concrete and exported (alternative to #1846) feat(core): concrete Protocol with custom-method overloads + deprecated v1 schema-arg shims Apr 15, 2026
@felixweinberger felixweinberger added this to the v2.0.0-bc milestone Apr 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v2-bc v2 backwards-compatibility series

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant