You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 52edb18
Browse filesBrowse the repository at this point in the historyBrowse files
Consult the resources_subscribe_handler for listen resource URIs
## Motivation and Context
In the 2026-07-28 lifecycle `subscriptions/listen` takes the place of `resources/subscribe`,
but the URIs it names in `resourceSubscriptions` were honored on the `subscribe` capability alone.
The `resources_subscribe_handler`, the hook an application uses to decide which resources
a client may follow, was never called for them, so a decision it made for `resources/subscribe`
did not carry over to a modern client.
Each distinct URI is now passed to that handler with the params a `resources/subscribe` request
for it would carry, together with the listen request's envelope and `auth_info` when the handler declares
`server_context:`. A URI the handler raises for is reported to the exception reporter
and left out of the acknowledgement, and the stream receives no `notifications/resources/updated` for it.
The spec lets the acknowledgement honor a subset of the requested filter, so this needs no new error on the wire,
and the field is omitted when no URI remains. The decision is made once when the stream opens,
before it is registered; the stream already closes when its token expires.
The params also carry the listen request's `_meta`, as those of a `resources/subscribe` request would,
while the `server_context` has no session, so session-scoped helpers do nothing there. Any value
the handler returns accepts the URI.
The TypeScript and Python SDKs copy the requested URIs into the acknowledgement as well;
the TypeScript SDK leaves authorization to the middleware layer. In the Ruby SDK the handler was already
the documented place for this decision, so it is reused instead of adding a second hook that
existing applications would have to discover.
`resources_unsubscribe_handler` is not called when a listen stream ends: the subscription lasts
as long as the stream.
`Server#subscribable_resource_uris` is public only so that the transport can call it;
it is marked `@api private` and is not part of the published API.
## How Has This Been Tested?
- test/mcp/server/transports/streamable_http_transport_test.rb
- test/mcp/server/transports/streamable_http_transport_oauth_test.rb
- test/mcp/server_test.rb
The two transport tests and the OAuth test fail against the previous `lib`, which acknowledged every requested URI.
The `_meta` transport test fails against it too.
## Breaking Changes
A `resources_subscribe_handler` that raises for a URI now narrows the listen acknowledgement for that URI,
and a handler that records subscriptions is now also called for listen streams, without a matching
`resources_unsubscribe_handler` call. Servers without a custom handler are unaffected.
0 commit comments