Skip to content

Conversation

@chipgpt
Copy link
Contributor

@chipgpt chipgpt commented Nov 1, 2025

This PR iterates on #239 which seems to have stalled. It adds a new, optional field to the ClientOptions that enables a tool list changed notification handler.

const client = new Client({
    name: 'test-client',
    version: '1.0.0',
}, {
    toolListChangedOptions: {
        autoRefresh: true,
        debounceMs: 300,
        onToolListChanged: (error, tools) => {
            if (err) {
                console.error('Unable to fetch tools:', error);
                return;
            }
            console.log('Updated tools:', tools);
        }
    }
});
  • If autoRefresh is true, then it will reload the tools first and pass them into the callback. If reload fails then error will be set and tools will be null.
  • If autoRefresh is false, then error and tools will always be null.

Motivation and Context

This update will allow clients to utilize the dynamic aspect of MCP by reloading tools when the server sends change notifications. Addresses issue #205

How Has This Been Tested?

I have added tests for the new behavior. It has not been tested in a real application.

Breaking Changes

No breaking changes. The new field is optional.

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

  • Should I add similar for resources?

@chipgpt chipgpt requested a review from a team as a code owner November 1, 2025 19:49
// Reset tool list changed options and remove notification handler
else {
this._toolListChangedOptions = null;
this.removeNotificationHandler(ToolListChangedNotificationSchema.shape.method.value);
Copy link
Member

@cliffhall cliffhall Nov 4, 2025

Choose a reason for hiding this comment

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

In this section, we should probably clearTimeout on any existing _toolListChangedDebounceTimer and set it to undefined

Copy link
Member

@cliffhall cliffhall Nov 4, 2025

Choose a reason for hiding this comment

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

Suggested change
this.removeNotificationHandler(ToolListChangedNotificationSchema.shape.method.value);
this.removeNotificationHandler(ToolListChangedNotificationSchema.shape.method.value);
if (this._toolListChangedDebounceTimer) {
clearTimeout(this._toolListChangedDebounceTimer);
this._toolListChangedDebounceTimer) = undefined;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated

@sandros06
Copy link

sandros06 commented Nov 8, 2025

Great work, @chipgpt!

I've tested our branch on the Inspector, but I need to adapt the Inspector client code to work with our changes. I also tested it with the dynamic MCP tool.

See the changes here: https://github.com/sandros06/inspector/pull/1/files

This is still experimental code. What are your thoughts on it?

This opens the door to a whole new class of dynamic MCP servers!

See on gif:

mcpdynamic

@cliffhall
Copy link
Member

I've tested our branch on the Inspector, but I need to adapt the Inspector client code to work with our changes.

@sandros06 I see the pull request in your repo, but can you please summarize what you needed to change and speak to whether this PR should include such changes and why?

@sandros06
Copy link

sandros06 commented Nov 9, 2025

I've tested our branch on the Inspector, but I need to adapt the Inspector client code to work with our changes.

@sandros06 I see the pull request in your repo, but can you please summarize what you needed to change and speak to whether this PR should include such changes and why?

I wanted to integrate it into the “inspector”, and after setting up the options for toolListChangedOptions, I ran into an issue with the setNotificationHandler logic from src/shared/protocol.ts . This function ultimately only accepts a single event handler, when the client registers a new handler, it overrides any existing ones.

However, this same handler is used both to display messages in the message list on the inspector and for the tool list_changed event. So, there might be a need for a getNotificationHandler, or some other mechanism, to let the client access the previous handler (though I’m not sure if that’s the best approach).

@chipgpt
Copy link
Contributor Author

chipgpt commented Nov 11, 2025

Very cool to see it in action in the inspector! I would definitely like to see this implemented in the official MCP inspector (probably needs to be an optional setting in case some people prefer the current behavior where you manually relist the tools). It would be great if you could create a PR for the modelcontextprotocol/inspector repo that implements this SDK update.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 11, 2025

Open in StackBlitz

npm i https://pkg.pr.new/modelcontextprotocol/typescript-sdk/@modelcontextprotocol/sdk@1068

commit: 3928c76

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.

3 participants