Skip to content

[Feature] First-class notification subscription support via a notifications/ directory convention #525

Description

@everm1nd

Motivation

xmcp has a great file-system-based convention for tools (tools/ directory, each file exports a tool(...) definition). There is currently no equivalent for MCP client notifications — there is no way to subscribe to events like roots/list_changed, $/cancelRequest, or any other notification the client may send.

The only workaround today is to reach for the underlying McpServer instance, which xmcp does not expose. This forces implementors to resort to per-call polling instead of event-driven logic.

Proposed API

Introduce a notifications/ directory (parallel to tools/) where each file exports a subscribe call:

// notifications/roots-changed.ts
import { subscribe } from 'xmcp';

export default subscribe('roots/list_changed', async () => {
  // update workspace context here
});

subscribe(notificationName, handler) mirrors the ergonomics of tool(name, schema, handler) — the framework handles all the plumbing (registering setNotificationHandler on the underlying McpServer) and the engineer just writes the handler.

Why this fits xmcp's design philosophy

Concern Tools Notifications (proposed)
Declaration tools/my-tool.ts exports tool(...) notifications/roots-changed.ts exports subscribe(...)
Discovery Framework scans tools/ at startup Framework scans notifications/ at startup
Plumbing Framework registers tool on McpServer Framework calls setNotificationHandler on McpServer
Engineer writes Input schema + handler function Notification name + handler function

Alternatives considered

  • Expose McpServer directly (e.g. via extra.server or a lifecycle hook) — lower-level, still requires engineers to know about the SDK internals (setNotificationHandler, schema objects, etc.). The subscribe() abstraction is more in the spirit of xmcp.

Environment

  • xmcp: 0.6.5

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions