Skip to content

v2: setRequestHandler/setNotificationHandler require a method-string literal — re-accept the schema object (or export typed method tokens) #2505

Description

@cliffhall

Summary

In v2, Protocol.setRequestHandler / setNotificationHandler require a method-string literal as the first argument and no longer accept the request/notification Zod schema object (the v1 API). Two consequences motivated this request while migrating a client:

  1. v1-peer libraries break at runtime with a confusing error. Any library still on the v1 peer that calls client.setNotificationHandler(SomeNotificationSchema, handler) now throws:

    '[object Object]' is not a spec notification method; pass schemas as the second argument to setNotificationHandler()
    

    The schema stringifies to [object Object], so the message is hard to act on, and it fails at connect time rather than at build time.

  2. Callers must hardcode magic string literals. setRequestHandler('tools/list', …) / setNotificationHandler('notifications/tools/list_changed', …) scatter bare method strings through app code instead of referencing a typed value.

Context

Found migrating the MCP Inspector to @modelcontextprotocol/client@2.0.0-beta.4. The Inspector renders MCP Apps via @modelcontextprotocol/ext-apps, which still peers on the v1 SDK and subscribes to tools/resources/prompts *_changed notifications with the schema-first API. Under v2 that throws the error above during the AppBridge connect handshake, so apps fail to load. We worked around it with a client-side proxy that reads the method literal off the schema's shape.method.value and forwards the method string — but that's exactly the translation the SDK is well-positioned to provide.

The *RequestSchema / *NotificationSchema objects still exist and still carry the method literal, so the method is derivable from the schema.

Proposals (either would help)

A. Re-accept the schema object as an overload, deriving the method from schema.shape.method:

setNotificationHandler(ToolListChangedNotificationSchema, handler) // v1-style, typed, no magic string
setNotificationHandler('notifications/tools/list_changed', handler) // still supported

This also restores backward-compat for v1-peer libraries, so nothing breaks at runtime.

B. Export typed method tokens/constants (e.g. a RequestMethods / NotificationMethods map) so callers reference a named value instead of a bare literal, keeping the method-string design but removing hardcoded strings.

At minimum, if the schema-first form stays unsupported, the thrown error could name the received schema's method (from shape.method.value) and suggest the string to pass — it would have turned a head-scratch into a one-line fix.

Versions

  • @modelcontextprotocol/client / core: 2.0.0-beta.4

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions