Custom request and notification handlers¶
For vendor-extension methods, those outside the MCP spec, registration names the envelope class that parses the
method and the handler that serves it. The class is what makes the method parseable at all, and its getMethod()
is the method registered. The message parser only recognises methods it has a class for, and answers -32601
for the rest.
->addRequestHandler(AcmeLookupRequest::class, new MyLookupHandler())
->addNotificationHandler(AcmeHeartbeatNotification::class, new MyHeartbeatHandler())
The envelope class¶
AcmeLookupRequest extends JsonRpcRequest, returns 'acme/lookup' from getMethod(), and implements the
ClientRequest marker. Registration rejects a class that lacks the marker, since the dispatcher only serves
ClientRequest requests.
Its params must be RequestParams-typed. They carry the lifecycle _meta every request is gated on. Otherwise
the dispatcher answers -32600. Notification classes extend JsonRpcNotification the same way, without the
marker.
Overriding a spec method¶
Both methods reject spec-reserved methods. To override the SDK's built-in handler for a spec method, for example
to take over tools/list, use the replace* variants:
->replaceRequestHandler('tools/list', new MyListToolsHandler())
->replaceNotificationHandler('notifications/cancelled', new MyCancelledHandler())
The replace* variants in turn reject non-spec methods, so each entry point steers vendor extensions and spec
overrides to the correct place. A replaced spec method keeps its registry envelope class, which is why replace*
takes no class argument.