Skip to content

mcp: add resource subscriptions #138

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

samthanawalla
Copy link
Contributor

This CL adds the ability for clients to subscribe and receive updates for resources as described in https://modelcontextprotocol.io/specification/2025-06-18/server/resources#subscriptions

Fixes: #23

This CL adds the ability for clients to subscribe and receive updates
for resources as described in https://modelcontextprotocol.io/specification/2025-06-18/server/resources#subscriptions
@samthanawalla samthanawalla requested review from Copilot and jba July 15, 2025 19:32
@samthanawalla samthanawalla marked this pull request as ready for review July 15, 2025 19:32
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements resource subscriptions for the MCP (Model Context Protocol), allowing clients to subscribe to and receive notifications when specific resources change. The implementation follows the MCP specification for resource subscriptions.

Key changes:

  • Added server-side subscription management with handlers for subscribe/unsubscribe operations
  • Implemented client-side subscription methods and notification handling
  • Added comprehensive test coverage for the subscription workflow

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
mcp/protocol.go Defines subscription-related protocol structures (SubscribeParams, UnsubscribeParams, ResourceUpdatedNotificationParams)
mcp/server.go Implements server-side subscription tracking, handlers, and notification routing
mcp/client.go Adds client-side subscription methods and notification handler registration
mcp/server_test.go Tests server capability reporting for resource subscriptions
mcp/mcp_test.go End-to-end integration tests for the complete subscription workflow
design/design.md Documentation updates explaining subscription usage patterns

Copy link
Contributor

@jba jba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice.

@@ -224,6 +236,12 @@ func (s *Server) capabilities() *serverCapabilities {
if s.resources.len() > 0 || s.resourceTemplates.len() > 0 {
caps.Resources = &resourceCapabilities{ListChanged: true}
}
if s.opts.SubscribeHandler != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm.
I think that if there are no resources, it doesn't matter if there's a subscribe handler. There is no resource capability.
It's OK to provide a handler, it just doesn't do anything.

defer s.mu.Unlock()

uri := params.URI
if sessions, ok := s.resourceSubscriptions[uri]; ok {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might as well skip the check and just call DeleteFunc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(If you prefer to use a slice.)

@@ -97,6 +108,7 @@ func NewServer(impl *Implementation, opts *ServerOptions) *Server {
resourceTemplates: newFeatureSet(func(t *serverResourceTemplate) string { return t.resourceTemplate.URITemplate }),
sendingMethodHandler_: defaultSendingMethodHandler[*ServerSession],
receivingMethodHandler_: defaultReceivingMethodHandler[*ServerSession],
resourceSubscriptions: make(map[string][]*ServerSession),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would be a little nicer if it was a map[string]map[string]bool. Adding and deleting would be trivial.

@@ -614,6 +686,8 @@ var serverMethodInfos = map[string]methodInfo{
methodListResourceTemplates: newMethodInfo(serverMethod((*Server).listResourceTemplates)),
methodReadResource: newMethodInfo(serverMethod((*Server).readResource)),
methodSetLevel: newMethodInfo(sessionMethod((*ServerSession).setLevel)),
methodSubscribe: newMethodInfo(serverMethod((*Server).subscribe)),
methodUnsubscribe: newMethodInfo(serverMethod((*Server).unsubscribe)),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this ever be run in reality?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Resource subscriptions support
3 participants