Capture MCP Tools Changed notifications - notifications/prompts/list_changed notifications
Resolved 💬 28 comments Opened Jul 22, 2025 by AchintyaAshok Closed May 23, 2026
💡 Likely answer: A maintainer (localden, collaborator)
responded on this thread — see the highlighted reply below.
Requesting to add support for https://modelcontextprotocol.io/specification/2024-11-05/server/tools#list-changed-notification.
Goal: when the MCP server emits a notification that its tools have changed, I would like Claude to refresh the tool list from the server and reflect the change in the /mcp menu for that server.
29 Comments
Hey there,
This is a great suggestion. It would be a huge quality-of-life improvement for anyone using MCP servers that have dynamic tools.
I took a look through the latest documentation you provided to see if there was a manual workaround. From what I can tell, the current implementation seems to discover tools when the server is first connected.
The
/mcpslash command lets you manage the connection and view the server's tools, but the docs don't mention a way to manually trigger a refresh of the tool list after the initial connection.The MCP documentation page (
en/docs/claude-code/mcp) mentions:And:
This seems to confirm that the tool/prompt discovery happens at connection time. I couldn't find any mention of the
notifications/tools/list_changedevent specifically.For now, I guess the only way to force a refresh would be to remove and re-add the server with
claude mcp remove <server-name>andclaude mcp add .... Not ideal, but it might get the job done if you know the tool list has changed.Having Claude Code listen for that
list_changednotification and automatically refresh would be the perfect solution. It would make integrations feel much more seamless.Fingers crossed the dev team sees this and adds it to the roadmap
I would like to see this as well. Currently there is support for dynamic tools in Cursor and VSCode but not in Claude Code.
It would be amazing to use this feature 👍
Expert Implementation Approach for Dynamic MCP Tool Management
TL;DR
We've successfully implemented a comprehensive solution for this exact problem in our GODA MCP server (Go-based). Here's what we learned and recommend for Claude Code implementation.
Current Problem Analysis
Based on our research and implementation experience:
mcp_list_toolsitems persist for entire conversationsnotifications/tools/list_changedare sent but ignored by Claude Desktop/Code/mcpreconnection or app restartOur Working Solution
We implemented a server-side intelligent categorization system that works around Claude Code's limitations:
Architecture Overview
Key Technical Insights
1. Handler Persistence vs Tool Discovery
2. Conversation-Level Cache Compatibility
3. Token Optimization By Design
Recommended Implementation for Claude Code
Phase 1: Basic Notification Support
Phase 2: Advanced Cache Strategy
Phase 3: Smart Tool Management
Real-World Performance Impact
Our implementation achieves:
Testing Strategy
We verified handler deregistration works correctly:
Migration Path for Existing Servers
set_tool_categoriescommand for dynamic switchingCommunity Impact
This approach solves the broader MCP ecosystem problem:
Code References
Full implementation available in our GODA project (Go):
internal/mcp/categories.gointernal/mcp/server.gonotifyToolsListChanged()method---
Would be happy to share more implementation details or collaborate on getting this into Claude Code core!
Quick Demo
If anyone wants to test this approach:
Option 1: Binary Download
Option 2: Build from Source
Configuration Example:
Try Dynamic Categorization:
The key insight: fix the problem at the server level while Claude Code catches up architecturally.
@kolkov This requires a reconnect after modifying the categories, right?
It's incredibly sad and confusing that Anthropic's own MCP clients don't support the basic discovery features of the protocol they created. Especially when those clients are proprietary so even if the community wanted to contribute that support, they can't.
How could MCP ever be taken seriously when only a fraction of the spec is supported even by its own authors?
It's not like this is a new feature. It was in the very first MCP spec version, front and center under the Tools documentation.
Just to bump this, this is something me and my colleagues working on the GitHub MCP Server would find very useful as, In our deployments, we occasionally change the tools list (eg. during tool consolidation.) At the moment Claude Code does not support this, but this would be a really useful addition to make the experience smoother for users with long running sessions so the LLM doesn't attempt to call non-existent/changed tools.
The LLM tool landscape truly is a developing wild west at this point.
Even the best tools available each have their own shortcomings of failures to implement basic standards.
I hope next year I can look back and laugh at this. I probably will.
Independently discovered this, and offered similar suggestions for fix. Here's hoping the extra noise increases the chances.
It'd be really great to see this part of the spec implemented by Claude Code because there are solutions out there (including my own) where descriptions of tools do change fairly regularly -- part of the problem is that they're called descriptions but they're tool spec PROMPTS and as such are subject to prompt engineering lifecycles rather than some static guidance that no one reads or pays attention to.
Combined with the fact that people tend to sit on Claude Code sessions for days if not weeks, well, lots of confused debugging can result (like today when I couldn't figure out why CC was using an old version of a description; I thought it was a caching bug, didn't expect it to be a CC caching bug!)
Hi, are there any updates on this issue? This limitation is a significant blocker for enabling dynamic tool discovery. It also poses a major challenge in preventing context pollution when MCP Servers manage a large number of tools.
Updated claude-code and now it seems to be working.
Also version 2.1.0 changelog notes support for list_changed notifications.
It just works for the following prompt, if during the current prompt iteration the LLM needs to call a tool that was updated, Claude is not being able to see that tool and returns an error:
Error: No such tool available: <YOUR_NEW_TOOL>If I try to interact again with Claude, now it is able to see the tool and call it.
Adding another real-world use case to support this request.
Scenario: MCP gateway that dynamically discovers agents from a message broker. Agents register via heartbeats after the gateway connects to the broker.
Problem: By the time agent discovery callbacks fire (milliseconds after init), Claude Code has already cached an empty tool list and ignores the tools/list_changed notification. Users see zero tools.
Current workaround: MCP server authors must implement polling/delay logic to wait for agents before completing initialization. This adds 10-15+ seconds of latency to every connection and is fragile.
Key point: Users who don't control the MCP server source code have NO workaround. They're stuck with broken tool discovery.
This is a fundamental MCP protocol feature - would be great to see it supported.
Real-world impact: MCP proxy/multiplexer rendered unable to dynamically manage servers
I built mcp-proxy — a Rust-based MCP multiplexer that sits between Claude Code and multiple downstream MCP servers. It aggregates tools from all servers with namespace prefixes, handles crash recovery, binary hot-reload, and graceful shutdown.
The original design included on-demand server loading: a catalogue of configured servers where Claude could start/stop individual servers mid-session via IPC. This was fully implemented and tested — the IPC works, servers spawn correctly,
tools/list_changedis sent — but the new tools never appear in the session because of this exact bug.What happens:
tools/list_changednotification sent on stdoutResult: The entire catalogue/on-demand architecture had to be scrapped. All servers must now be loaded at startup, defeating the purpose of dynamic management. With the 128-tool hard cap and growing MCP ecosystems, this is a significant limitation.
A working
tools/list_changedhandler would unlock MCP multiplexers, lazy-loading proxies, and any server that dynamically registers new tools at runtime.Confirming this is still an issue as of today. I maintain an MCP server that uses dynamic tool promotion — tools start deferred and are surfaced on demand via
tools/list_changed. Server-side everything works correctly (tool list updates, notification fires, tools are callable viacall_tool), but ToolSearch never picks up the newly promoted tools. The only workaround is bypassinglist_tools()entirely.The partial fix in 2.1.0 doesn't help this case. The ToolSearch index appears to be a static snapshot from conversation start that's never refreshed.
My workaround is to Piggyback on all of my tool calls I message to the user
to say “tools have changed if you want to see them, restart Claude.
One more example of how young Claude is really. So many laughable
inadequacies.
to MCP Conte
anthropic yourself
will find it
On Fri, 20 Mar 2026 at 05:30, Grant Sparks @.***> wrote:
Test results:
notifications/tools/list_changedin VS Code extension v2.1.86I tested this end-to-end with a C# MCP stdio server (ModelContextProtocol SDK 1.1.0) on Windows.
Setup
listChanged: truecapabilitynotifications/tools/list_changedviaMcpServer.SendNotificationAsync()after startupResults
| Scenario | Tool visible? |
|---|---|
| New tool added → rebuild → same chat ToolSearch | No |
| New tool added → rebuild → new chat ToolSearch | Yes |
| New tool added → rebuild →
/mcp→ Reconnect → same chat | Yes |Analysis of extension.js (v2.1.86)
The MCP SDK layer does handle the notification correctly:
_setupListChangedHandlerregisters a debounced handler (300ms)tools/list→ updatescacheToolMetadataonChangedcallbackHowever, the application layer does not propagate the updated tool list into the active agent conversation's deferred tools. The tools are refreshed at the SDK/connection level but the running chat session retains its stale tool cache.
Conclusion
The CHANGELOG for v2.1.0 says "Added support for MCP
list_changednotifications" — this is true at the SDK level. But the active conversation does not see newly added tools until the user opens a new chat or manually reconnects via/mcp.This makes the feature effectively incomplete for the main use case: iterating on MCP server development while keeping the same chat open.
Environment: VS Code extension
anthropic.claude-code@2.1.86-win32-x64, Windows 10, C# MCP server via stdio.A
PostToolUsehook can detect when MCP tool usage patterns change:For monitoring MCP server health:
Note: Hooks can't currently trigger an MCP tool list refresh — that requires a native implementation of the
notifications/tools/list_changedprotocol handler. The hooks above provide visibility into MCP tool state changes as a partial workaround.found this issue also with Claude Desktop via claude.ai and Claude Code #41123
Workaround that actually reconnects — patch
extension.jsdirectlySince the conversation-level tool cache isn't refreshed on
list_changed, I patchedextension.jsto watch a flag file and callreconnectMcpServerautomatically. Build script touches the flag → all open chats reconnect, no manual/mcpneeded.apply_patch.py(tested on v2.1.87, Windows):How it works:
setInterval(2000ms)watchesFLAG_FILEmtimeZ.allComms(Set of active chats) → callsreconnectMcpServer(channelId, serverName)for each channeltouch .mcp-reconnectafter successful rebuild → all open chats reconnect automaticallyStable identifiers (not minified, survive extension updates):
allComms(17 occurrences in v2.1.87),reconnectMcpServer(5 occurrences)What breaks on extension update: the injection anchor uses minified variable names (
K,Z,O6). The script prints a clear error when the anchor isn't found and tells you where to look. Adapting to a new version takes a few minutes.Works on Windows. The flag file approach is build-tool agnostic — any script can trigger reconnect with a simple
touch.---
Detecting extension updates
The patch breaks silently when Claude Code auto-updates. Simple check:
Add this to your build script — if it prints
NEEDS PATCH, runapply_patch.py+ reload VSCode.---
Update: tested on v2.1.88
Extension updated silently overnight — the anchor broke as expected. Adapted in a few minutes:
O6→M6(one minified variable renamed)allComms,reconnectMcpServer,Z,K— unchangedNew anchor for v2.1.88:
The detection script above caught the update immediately on the next build. Patch reapplied, working.
---
Update: tested on v2.1.89
Same anchor as v2.1.88 — no changes needed.
allComms,reconnectMcpServer,Z,K,M6all unchanged. Patch applied cleanly.Also worth checking before each re-patch: scan the changelog for a native fix (
gh api repos/anthropics/claude-code/releases/latest --jq '.body' | grep -i mcp). v2.1.89 has no mention ofnotifications/tools/list_changed— patch still required.---
Repository: https://github.com/Serg2000Mr/claude-code-mcp-reconnect — generic version of the script (configurable
SERVER_NAME/FLAG_FILE).@ollie-anthropic In the labels it says "enhancement" but this is more of type "bug" .. Its been open für almost a year... Would it be possible to get some kind of feedback or an ETA.. This would open up many many doors..
The bug is still there on claude desktop. Say I am developing a MCP tool. I have dynamic discovery with a tool I named
discover_tools. It works by registering newly enabled tools at runtime and emitting the MCP protocol'snotifications/tools/list_changedevent. The protocol defines this event ( https://modelcontextprotocol.io/specification/2024-11-05/server/tools#list-changed-notification ) and Anthropic's own TypeScript SDK providessendToolsListChanged()for emitting it.However Claude Code itself does not honor it. The Zod schema for the notification is defined in cli.js, but no handler is registered, so the dynamically-enabled tool never reaches the model's tool surface. It's baffling that this has been open nearly for a year.
Adding a real-world cost data point in case it helps weigh the not-planned ruling on #46426.
I run ~30 MCP connectors against my single-operator business stack (Shopify, Xero, Klaviyo, GA4, GSC, Google Ads, Pinterest, Bluesky, LinkedIn, Home Assistant, etc.). Iterating on a connector — adding a tool, fixing a schema, renaming an action — is a tight loop: edit, rebuild container, redeploy. Every iteration currently costs a full Claude Code restart, which means losing the conversation, the loaded context, and any in-progress investigation.
The MCP server already sends
notifications/tools/list_changedafter the rebuild. Claude Code receives the notification (per #13646) but discards it because no handler is registered. The protocol-level work is done on both sides; only the client handler is missing./mcpreconnect re-establishes transport without re-pullingtools/list, which is arguably worse than no reconnect at all — it gives the appearance of a refresh without performing one.The stated efficiency argument (tool schemas baked into the cached system prompt) is real, but
ENABLE_TOOL_SEARCH=truealready breaks the "all tools at session start" model — deferred tools are loaded on demand and injected into the conversation, not the prompt. The same mechanism could deliver atools/list_changedrefresh without invalidating the prompt cache.A
/mcp refresh <server>slash command that re-fetches a single server's tool list and surfaces the diff would solve 95% of the iteration pain even without automatic handling of the notification.The bug is still there on Claude Desktop, I keep seeing this when building my own MCP server for an app!
+1 — Minsky (https://github.com/edobry/minsky), a multi-agent task system, ships infrastructure that depends on this. Our architecture: a stdio supervisor (
minsky mcp proxy) sits between Claude Code and the inner MCP server, transparently respawns the inner when source updates, and emitsnotifications/tools/list_changedupstream after each respawn so Claude Code can refresh its tool cache without a/mcpreconnect step.End-to-end test (Claude Code 2.1.146):
debug.listMethodson the inner returns 210 tools (e.g.,git.branch,ai.chat,session.inspect).ToolSearch select:mcp__minsky__git_branchreturns empty (the deferred-tools surface doesn't have it).__proxy_restart_server→ emits a spec-conformantnotifications/tools/list_changed(advertised capability, valid JSON-RPC, ping-gated readiness probe).ToolSearch select:mcp__minsky__git_branchstill returns empty./mcpreconnect →ToolSearchimmediately finds it.Interestingly, the binary at 2.1.146 contains both
"Received tools/list_changed notification, refreshing tools"and atengu_mcp_list_changedtelemetry event — so a handler DOES exist (vs the 2.0.65 reported in #13646). But the deferred-tools surface that powersToolSearchdoesn't reflect any refresh — only manual/mcpreconnect closes the gap. The handler may update the SDK-internal tools list without propagating to the higher-level deferred-tools cache.Anything that closes this gap would be appreciated. Happy to share repro details.
(Had Claude help draft this comment.)
@edobry Thanks for jumping on this guys! Just wanted to point out that I'm seeing this issue on claude desktop, so if that too could be taken care of - that would be amazing!
Thanks for the report. Handling for
notifications/tools/list_changedshipped in 2.1.0 and is active in current versions. If you are still seeing the tool list not refresh on a current version (especially in print mode or with deferred tool search), please open a new issue with the version and a repro.Built MCP Salad on top of this — a CLI + gateway that uses
notifications/tools/list_changedto hot-swap servers into a running Claude Code session without restart.The implementation: gateway listens on a Unix socket for
salad enable <server>, updates the server pool, fires the notification. On Claude Code ≥2.1.0 the tool list updates instantly — no restart, no new chat.One gap we noticed: the notification works cleanly, but the UX problem is discovery — knowing which server to enable mid-session. We added
salad suggest "<description>"which keyword-searches the 14k official MCP registry and returns ranked suggestions, so you can go from "I need a patent search tool" to live tools in a running session in a few commands.Might be useful context for anyone building on this notification.