Skip to content
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

Add subscribe to resource functionality #170

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

Conversation

cliffhall
Copy link
Contributor

@cliffhall cliffhall commented Mar 8, 2025

When the connected MCP server's capabilities include resource subscriptions:

  • Show a Subscribe or Unsubscribe button at the top of the selected resource panel of the Resources tab.
  • Send subscribe/unsubscribe requests to the server according to the protocol spec.
  • Track and manage subscribed resource URIs so that the UI knows which button to display for the selected resource.
  • Allow ServerNotificationSchema messages to be handled.

Incidental out-of band update: Jetbrains IDE falls into a loop prompting for npm install to be run because these versions were not up to date.

  • In package.json, package.lock.json, updated client and server versions to match inspector
    • "@modelcontextprotocol/inspector-client": "^0.5.1"
    • "@modelcontextprotocol/inspector-server": "^0.5.1"

This fixes #166

Motivation and Context

Dynamic resources can change over time and the protocol specifies a way for clients to subscribe to individual resources so they can be updated when those resources change.

However the existing reference client - the MCP Inspector - does not provide any affordance for the user to subscribe to a resource. It provides a way to list resources and read resources.

Implementation

There is a panel for displaying the selected resource, and that panel's header already contained a Refresh button. This PR adds a Subscribe or Unsubscribe button there, but only if the server supports resource subscriptions.

When clicked, it passes the selected resource's URI to the subscribe or unsubscribe handler, which in turn sends the appropriate message to the server.

A slight modification was made to useConnection and notificationTypes to support handling ServerNotificationSchema messages, a union of which ResourceUpdatedNotificationSchema is a member.

How Has This Been Tested?

Button placement

The buttons are in a right justified div that is 2/5 wide in the panel header. Just large enough to contain the buttons, leaving 3/5 width to the heading without overlap.

Button positioning

Server capabilities

I have an SSE-based MCP server called puzzlebox. It hosts finite state machines (called puzzles) and allows clients to perform actions on them to change their states. The puzzles are exposed as dynamic resources with a resource template. They could already be listed and read, but there was no way to test that clients could subscribe to individual puzzles for updates. Puzzlebox provided the perfect test server for this functionality, since I had handy local access to both projects for troubleshooting.

Test 1 - Check for no subscription support on server

1A) Turn OFF subscriptions on the server

Screenshot 2025-03-08 at 12 38 46 PM

1B) Observe NO subscription button on selected resource

Screenshot 2025-03-08 at 12 38 04 PM

Test 2 - Check for subscription support on server

2A) Turn ON subscriptions on the server

Screenshot 2025-03-08 at 12 40 29 PM

2B) Observe subscription button on selected resource

Screenshot 2025-03-08 at 12 40 06 PM

Test 3 - Test outgoing requests and appropriate button display

3A) Click Subscribe button, observe Unsubscribe button

subscribe-clicked

3B) Observe subscribe request

resource-subscribed

3C) Click Unsubscribe button, observe Subscribe button again

unsub-clicked

3D) Observe unsubscribe request

resource-unsubbed

Test 4 - Check notifications when subscribed resource changes

4A) Use perform_action_on_puzzle tool to change subscribed puzzle's state

perform-action

4B) Observe resource updated notification from server

resource-updated

Test 5 - Check notifications no longer sent when unsubscribed resource changes

5A) Click Unsubscribe button on same puzzle,

unsubscribed

5B) Use perform_action_on_puzzle tool to change unsubscribed puzzle's state, observe NO new server notification

not-notified

Breaking Changes

Nope.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

* In App.tsx
  - added subscribeToResource()
    - takes a uri
    - sends a `resources/subscribe` message with the uri
  - added unsubscribeFromResource()
    - takes a uri
    - sends a `resources/unsubscribe` message with the uri
  - in ResourcesTab element,
    - pass subscribeToResource and subscribeToResource invokers to component
* In notificationTypes.ts
  - add ServerNotificationSchema to NotificationSchema to permit server update messages.

* In ResourcesTab.tsx
  - deconstruct subscribeToResource and unsubscribeFromResource and add prop types
  - Add Subscribe and Unsubscribe buttons to selected resource panel, left of the refresh button. They call the sub and unsub functions that came in on props, passing the selected resource URI.
  - [WIP]: Will show the appropriate button in a follow up commit.
* In useConnection.ts
  - import ResourceUpdatedNotificationSchema
  - in the connect function,
    - set onNotification as the handler for ResourceUpdatedNotificationSchema
…bscribe button on selected resource panel.

If the server does not support resource subscriptions, do not show any subscription buttons.

* In App.tsx
  - useState for resourceSubscriptions, setResourceSubscriptions a Set of type string.
  - in subscribeToResource()
    - only make the request to subscribe if the uri is not in the resourceSubscriptions set
  - in unsubscribeFromResource()
    - only make the request to unsubscribe if the uri is in the resourceSubscriptions set
  - in ResourceTab element,
    - pass a boolean resourceSubscriptionsSupported as serverCapabilities.resources.subscribe
    - pass resourceSubscriptions as a prop
* In ResourcesTab.tsx
  - deconstruct resourceSubscriptions and resourceSubscriptionsSupported from props and add prop type
  - in selected resource panel
    - don't show subscribe or unsubscribe buttons unless resourceSubscriptionsSupported is true
    - only show subscribe button if selected resource uri is not in resourceSubscriptions set
    - only show unsubscribe button if selected resource uri is in resourceSubscriptions set
    - wrap buttons in a flex div that is
      - justified right
      - has a minimal gap between
      - 2/5 wide (just big enough to contain two buttons and leave the h3 text 3/5 of the row to render and not overflow.
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.

Add ability to control and test resource subscription in MCP Inspector
1 participant