refactor(core): extract Dispatcher; Protocol composes it#2130
Draft
felixweinberger wants to merge 1 commit into
Draft
refactor(core): extract Dispatcher; Protocol composes it#2130felixweinberger wants to merge 1 commit into
felixweinberger wants to merge 1 commit into
Conversation
|
@modelcontextprotocol/client
@modelcontextprotocol/server
@modelcontextprotocol/express
@modelcontextprotocol/fastify
@modelcontextprotocol/hono
@modelcontextprotocol/node
commit: |
This was referenced May 20, 2026
…or change)
Introduce `Dispatcher<ContextT>` (`packages/core/src/shared/dispatcher.ts`)
holding the request-handler registry, middleware chain, and `dispatch()`
entry point. `Protocol` now composes a `protected readonly dispatcher`
and delegates:
- `setRequestHandler` / `removeRequestHandler` / `assertCanSetRequestHandler`
- `fallbackRequestHandler` (now `dispatcher.fallbackHandler`)
- `_onrequest` invokes `dispatcher.dispatch(request, ctx)` for lookup,
middleware onion, and JSON-RPC response wrapping
The previous `_wrapHandler` override hook is replaced by `dispatcher.use()`:
- `Server` registers `_callToolResultMiddleware` (was `_wrapHandler` for tools/call)
- `Client` registers `_validationMiddleware` (was `_wrapHandler` for
elicitation/create + sampling/createMessage)
Same validation runs on the same paths; the observation point moves from
per-registration wrapping to per-dispatch middleware.
`dispatch()`'s catch block preserves `_onrequest`'s error behavior verbatim:
thrown errors surface their `code` (if a safe integer), `message`, and `data`.
No sanitization is introduced.
Tests:
- `dispatcher.test.ts` added (11 tests for setHandler/dispatch/middleware/error)
- `wrapHandler.test.ts` deleted (covered by rewritten customMethods test)
- `customMethods.test.ts` adapts one test from spying on `_wrapHandler` to
spying via middleware; same assertion (both 2-arg and 3-arg routes through)
No existing test assertions changed.
5b5c538 to
09fc142
Compare
6 tasks
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.
Extracts
Dispatcher<Ctx>(handler map + middleware chain +dispatch()) fromProtocol.Protocolnow composes one;setRequestHandler/_onrequest/fallbackRequestHandlerdelegate. The_wrapHandleroverride hook becomesdispatcher.use(middleware).Zero behavior change.
dispatch()'s catch block preserves_onrequest's error mapping verbatim. No existing test assertions changed.Motivation and Context
Enabling refactor for SEP-2575:
_dispatchStateless(next PR) needs to invoke the same handler map + middleware that legacy_onrequestuses, without going through Protocol's session machinery.How Has This Been Tested?
pnpm test:all— count delta isdispatcher.test.ts(+11) andwrapHandler.test.ts(−1, redundant). No existing assertion changed.Breaking Changes
Protocol._wrapHandleroverride hook removed (was protected). Subclasses usethis.dispatcher.use(mw)instead.Types of changes
Checklist