@@ -12,7 +12,7 @@ various aspects of the server behavior.
1212- [ Session Management] ( #session-management )
1313- [ Manual Capability Registration] ( #manual-capability-registration )
1414- [ Service Dependencies] ( #service-dependencies )
15- - [ Custom Method Handlers] ( #custom-method -handlers )
15+ - [ Custom Message Handlers] ( #custom-message -handlers )
1616- [ Complete Example] ( #complete-example )
1717- [ Method Reference] ( #method-reference )
1818
@@ -344,50 +344,101 @@ $server = Server::builder()
344344 ->setEventDispatcher($eventDispatcher);
345345```
346346
347- ## Custom Method Handlers
347+ ## Custom Message Handlers
348348
349- ** Low-level escape hatch.** Custom method handlers run before the SDK’ s built-in handlers and give you total control over
350- individual JSON-RPC methods . They do not receive the builder’ s registry, container, or discovery output unless you pass
349+ ** Low-level escape hatch.** Custom message handlers run before the SDK' s built-in handlers and give you total control over
350+ individual JSON-RPC messages . They do not receive the builder' s registry, container, or discovery output unless you pass
351351those dependencies in yourself.
352352
353- Attach handlers with ` addMethodHandler() ` (single) or ` addMethodHandlers() ` (multiple). You can call these methods as
354- many times as needed; each call prepends the handlers so they execute before the defaults:
353+ > ** Warning** : Custom message handlers bypass discovery, manual capability registration, and container lookups (unless
354+ > you explicitly pass them). Tools, resources, and prompts you register elsewhere will not show up unless your handler
355+ > loads and executes them manually. Reach for this API only when you need that level of control and are comfortable
356+ > taking on the additional plumbing.
357+
358+ ### Request Handlers
359+
360+ Handle JSON-RPC requests (messages with an ` id ` that expect a response). Request handlers ** must** return either a
361+ ` Response ` or an ` Error ` object.
362+
363+ Attach request handlers with ` addRequestHandler() ` (single) or ` addRequestHandlers() ` (multiple). You can call these
364+ methods as many times as needed; each call prepends the handlers so they execute before the defaults:
355365
356366``` php
357367$server = Server::builder()
358- ->addMethodHandler(new AuditHandler())
359- ->addMethodHandlers([
360- new CustomListToolsHandler(),
368+ ->addRequestHandler(new CustomListToolsHandler())
369+ ->addRequestHandlers([
361370 new CustomCallToolHandler(),
371+ new CustomGetPromptHandler(),
362372 ])
363373 ->build();
364374```
365375
366- Custom handlers implement ` MethodHandlerInterface ` :
376+ Request handlers implement ` RequestHandlerInterface ` :
367377
368378``` php
369- use Mcp\Schema\JsonRpc\HasMethodInterface;
370- use Mcp\Server\Handler\MethodHandlerInterface;
379+ use Mcp\Schema\JsonRpc\Error;
380+ use Mcp\Schema\JsonRpc\Request;
381+ use Mcp\Schema\JsonRpc\Response;
382+ use Mcp\Server\Handler\Request\RequestHandlerInterface;
371383use Mcp\Server\Session\SessionInterface;
372384
373- interface MethodHandlerInterface
385+ interface RequestHandlerInterface
374386{
375- public function supports(HasMethodInterface $message ): bool;
387+ public function supports(Request $request ): bool;
376388
377- public function handle(HasMethodInterface $message , SessionInterface $session);
389+ public function handle(Request $request , SessionInterface $session): Response|Error ;
378390}
379391```
380392
381- - ` supports() ` decides if the handler should look at the incoming message.
382- - ` handle() ` must return a JSON-RPC ` Response ` , an ` Error ` , or ` null ` .
393+ - ` supports() ` decides if the handler should process the incoming request
394+ - ` handle() ` ** must** return a ` Response ` (on success) or an ` Error ` (on failure)
383395
384- Check out ` examples/custom-method-handlers/server.php ` for a complete example showing how to implement
385- custom ` tool/list ` and ` tool/call ` methods independently of the registry.
396+ ### Notification Handlers
386397
387- > ** Warning** : Custom method handlers bypass discovery, manual capability registration, and container lookups (unlesss
388- > you explicitly pass them). Tools, resources, and prompts you register elsewhere will not show up unless your handler
389- > loads and executes them manually.
390- > Reach for this API only when you need that level of control and are comfortable taking on the additional plumbing.
398+ Handle JSON-RPC notifications (messages without an ` id ` that don't expect a response). Notification handlers ** do not**
399+ return anything - they perform side effects only.
400+
401+ Attach notification handlers with ` addNotificationHandler() ` (single) or ` addNotificationHandlers() ` (multiple):
402+
403+ ``` php
404+ $server = Server::builder()
405+ ->addNotificationHandler(new LoggingNotificationHandler())
406+ ->addNotificationHandlers([
407+ new InitializedNotificationHandler(),
408+ new ProgressNotificationHandler(),
409+ ])
410+ ->build();
411+ ```
412+
413+ Notification handlers implement ` NotificationHandlerInterface ` :
414+
415+ ``` php
416+ use Mcp\Schema\JsonRpc\Notification;
417+ use Mcp\Server\Handler\Notification\NotificationHandlerInterface;
418+ use Mcp\Server\Session\SessionInterface;
419+
420+ interface NotificationHandlerInterface
421+ {
422+ public function supports(Notification $notification): bool;
423+
424+ public function handle(Notification $notification, SessionInterface $session): void;
425+ }
426+ ```
427+
428+ - ` supports() ` decides if the handler should process the incoming notification
429+ - ` handle() ` performs side effects but ** does not** return a value (notifications have no response)
430+
431+ ### Key Differences
432+
433+ | Handler Type | Interface | Returns | Use Case |
434+ | -------------| -----------| ---------| ----------|
435+ | Request Handler | ` RequestHandlerInterface ` | ` Response\|Error ` | Handle requests that need responses (e.g., ` tools/list ` , ` tools/call ` ) |
436+ | Notification Handler | ` NotificationHandlerInterface ` | ` void ` | Handle fire-and-forget notifications (e.g., ` notifications/initialized ` , ` notifications/progress ` ) |
437+
438+ ### Example
439+
440+ Check out ` examples/custom-method-handlers/server.php ` for a complete example showing how to implement
441+ custom ` tools/list ` and ` tools/call ` request handlers independently of the registry.
391442
392443## Complete Example
393444
@@ -453,8 +504,10 @@ $server = Server::builder()
453504| ` setLogger() ` | logger | Set PSR-3 logger |
454505| ` setContainer() ` | container | Set PSR-11 container |
455506| ` setEventDispatcher() ` | dispatcher | Set PSR-14 event dispatcher |
456- | ` addMethodHandler() ` | handler | Prepend a single custom method handler |
457- | ` addMethodHandlers() ` | handlers | Prepend multiple custom method handlers |
507+ | ` addRequestHandler() ` | handler | Prepend a single custom request handler |
508+ | ` addRequestHandlers() ` | handlers | Prepend multiple custom request handlers |
509+ | ` addNotificationHandler() ` | handler | Prepend a single custom notification handler |
510+ | ` addNotificationHandlers() ` | handlers | Prepend multiple custom notification handlers |
458511| ` addTool() ` | handler, name?, description?, annotations?, inputSchema? | Register tool |
459512| ` addResource() ` | handler, uri, name?, description?, mimeType?, size?, annotations? | Register resource |
460513| ` addResourceTemplate() ` | handler, uriTemplate, name?, description?, mimeType?, annotations? | Register resource template |
0 commit comments