[{'Text': '{"url":"https://gofastmcp.com/servers/tools","title":"Tools - FastMCP","description":"New in version 2.9.1 <strong>FastMCP automatically sends notifications/tools/list_changed notifications to connected clients when tools are added, removed, enabled, or disabled</strong>.","extra_snippets":["New in version 2.9.1 FastMCP automatically sends notifications/tools/list_changed notifications to connected clients when tools are added, removed, enabled, or disabled.","Clients can handle these notifications using a message handler to automatically refresh their tool lists or update their interfaces. Tools can access MCP features like logging, reading resources, or reporting progress through the Context object. To use it, add a parameter to your tool function with the type hint Context. from fastmcp import FastMCP, Context mcp = FastMCP(name=\\"ContextDemo\\") @mcp.tool async def process_data(data_uri: str, ctx: Context) -> dict: \\"\\"\\"Process data from a resource with progress reporting.\\"\\"\\" await ctx.info(f\\"Processing data from {data_uri}\\") # Read a resource resour","The most commonly used hint is readOnlyHint, which signals that a tool only reads data without making changes. Read-only tools improve user experience by: ... Enabling more aggressive batching and caching Mark a tool as read-only when it retrieves data, performs calculations, or checks status without modifying state: from fastmcp import FastMCP from mcp.types import ToolAnnotations mcp = FastMCP(\\"Data Server\\") @mcp.tool(annotations={\\"readOnlyHint\\": True}) def get_user(user_id: str) -> dict: \\"\\"\\"Retrieve user information by ID.\\"\\"\\" return {\\"id\\": user_id, \\"name\\": \\"Alice\\"} @mcp.tool( annotations=To","Functions with *args or **kwargs are not supported as tools. This restriction exists because FastMCP needs to generate a complete parameter schema for the MCP protocol, which isn’t possible with variable argument lists."]}{"url":"https://github.com/google-gemini/gemini-cli/issues/19509","title":"notifications/tools/list_changed support not working · Issue #19509 · google-gemini/gemini-cli","description":"Server starts with one initial tool: &quot;unlock_secret_tool&quot; <strong>When a client calls &quot;unlock_secret_tool&quot;, the server dynamically registers a new tool called &quot;secret_calculator&quot; and sends a notifications/tools/list_changed notification</strong>.","extra_snippets":["Server starts with one initial tool: \\"unlock_secret_tool\\" When a client calls \\"unlock_secret_tool\\", the server dynamically registers a new tool called \\"secret_calculator\\" and sends a notifications/tools/list_changed notification. The client (e.g., Gemini CLI) picks up the notification and re-fetches the tool list, making \\"secret_calculator\\" available for use. \\"\\"\\" import asyncio import logging from mcp.server.fastmcp import FastMCP, Context","What happened? I tried running gemini-cli at latest version 0.29.2 as well as nightly build and I can see the merged code in pull request #14375 exists in that tag and as well as in nightly build. I am using below code to add a dynamic t...","I tried running gemini-cli at latest version 0.29.2 as well as nightly build and I can see the merged code in pull request #14375 exists in that tag and as well as in nightly build. I am using below code to add a dynamic tool via python `\\"\\"\\" MCP Server that demonstrates dynamic tool registration with notifications/tools/list_changed.","A new tool \'secret_calculator\' is now available.\\\\n\\" \\"It supports operations: add, subtract, multiply, divide.\\\\n\\" \\"Example: secret_calculator(a=10, b=5, operation=\'add\')\\\\n\\" \\"The client has been notified about the new tool via notifications/tools/list_changed.\\" ) @mcp.tool() async def list_available_info(ctx: Context) -> str: \\"\\"\\"List information about currently available tools and whether the secret tool has been unlocked. Returns: Status information about the server and available tools. \\"\\"\\" global _secret_tool_added · status = \\"🔓 UNLOCKED\\" if _secret_tool_added else \\"🔒 LOCKED\\" return ( f\\"Dynamic Tools Server Status:\\\\n\\" f\\"----------------------------\\\\n\\" f\\"Secret Calculator: {status}\\\\n\\" f\\"\\\\n\\" f\\"Available tools:\\\\n\\" f\\" 1."]}{"url":"https://www.speakeasy.com/mcp/tool-design/dynamic-tool-discovery","title":"Dynamic tool discovery in MCP | Speakeasy","description":"<strong>When the MCP server detects that the authentication has expired, it can send a notifications/tools/list_changed message to notify the MCP client that the list of tools has changed</strong>.","extra_snippets":["We want to hide the getWhatsAppChatById tool until the user re-authenticates. MCP allows you to dynamically change the list of available tools at runtime. When the MCP server detects that the authentication has expired, it can send a notifications/tools/list_changed message to notify the MCP client that the list of tools has changed.","MCP allows you to send a notifications/tools/list_changed message from the MCP server to the MCP client to notify it that the list of available tools has changed. This is useful for dynamic tool discovery, where the MCP server can add or remove tools at runtime.","The MCP client can then call tools/list to get the updated list of tools. This allows the MCP server to dynamically change its capabilities without requiring the MCP client to reconnect or reinitialize. Here’s what that would look like in our WhatsApp MCP server: // When the MCP server detects that the authentication has expired, it can send a notification const authenticationExpiredListener = () => { getWhatsAppChatById.disable(); // Disable the tool };","Resource availability changes: Hide tools that depend on external services when those services are unavailable · Context-dependent tools: Show tools that are only relevant in certain contexts (e.g., only show file operations when a project is open) By dynamically adjusting the available tools, you can provide a cleaner, more intuitive experience for users without cluttering their tool list with unavailable options."]}{"url":"https://github.com/google-gemini/gemini-cli/issues/13850","title":"Add support for MCP dynamic tool update by `notifications/tools/list_changed` · Issue #13850 · google-gemini/gemini-cli","description":"he MCP specification defines tools.listChanged as a server capability and <strong>notifications/tools/list_changed as the notification method for signaling tool updates</strong>.","extra_snippets":["What would you like to be added? Support for MCP server dynamic tool updates via the notifications/tools/list_changed notification mechanism. When an MCP server sends a notifications/tools/list_changed notification (as defined in the MCP...","When an MCP server sends a notifications/tools/list_changed notification (as defined in the MCP specification), the Gemini CLI should automatically: Remove the old tool list from the affected MCP server ... ManySome MCP servers dynamically update their available tools based on runtime conditions (e.g., authentication state changes, resource availability, or configuration updates).","Supporting the notifications/tools/list_changed notification would: ... Allow MCP servers to add or remove tools in response to runtime changes (such as credential refresh, resource state changes, etc.)","he MCP specification defines tools.listChanged as a server capability and notifications/tools/list_changed as the notification method for signaling tool updates."]}{"url":"https://github.com/Fnctn-Inc/mcp-toolbox","title":"GitHub - Fnctn-Inc/mcp-toolbox: Toolbox for MCP tools to overcome the tool limit set","description":"FastMCP Integration: Built on FastMCP v2 for robust server runtime and client capabilities · Persistent Indexing: SQLite + Faiss storage for fast tool lookup and change detection · MCP Spec Compliant: Emits proper notifications/tools/list_changed events","extra_snippets":["mcpproxy/ ├── models/ │ └── schemas.py # Pydantic models and schemas ├── persistence/ │ ├── db.py # SQLite operations │ ├── faiss_store.py # Faiss vector storage │ └── facade.py # Unified persistence interface ├── indexer/ │ ├── base.py # Base embedder interface │ ├── bm25.py # BM25 implementation │ ├── huggingface.py # HuggingFace embeddings │ ├── openai.py # OpenAI embeddings │ └── facade.py # Search and indexing interface ├── server/ │ ├── config.py # Configuration management │ └──","Start MCP server, by default transport is stdio, you can use MCPPROXY_TRANSPORT to change it to streamable-http or sse ... Behavior: AI agent calls retrieve_tools, which searches and dynamically registers the most relevant tools as MCP tools · Tool Registration: Tools become available in the MCP protocol after retrieve_tools call","FastMCP Integration: Built on FastMCP v2 for robust server runtime and client capabilities · Persistent Indexing: SQLite + Faiss storage for fast tool lookup and change detection · MCP Spec Compliant: Emits proper notifications/tools/list_changed events","When you see a tool named `retrieval_tools` in the MCP tool list, call it first. It returns the most relevant tools for the user’s request, helping you answer more accurately and concisely. A federating gateway that sits between AI agents and multiple Model Context Protocol (MCP) servers, providing intelligent tool discovery and dynamic registration."]}{"url":"https://github.com/anthropics/claude-code/issues/13646","title":"[Bug] MCP tool list not refreshed on notifications/tools/list_changed event · Issue #13646 · anthropics/claude-code","description":"<strong>The listTools method exists but is only called once during initial connection setup. This prevents dynamic tool loading scenarios where an MCP server adds or removes tools during a session</strong>.","extra_snippets":["Bug Description Claude Code does not refresh its tool list when receiving the MCP notifications/tools/list_changed notification from servers. Investigation of the minified cli.js source confirms that while Claude Code defines the Zod sch...","Investigation of the minified cli.js source confirms that while Claude Code defines the Zod schema for this notification and includes it in the server-to-client notification types, no handler is registered via setNotificationHandler for notifications/tools/list_changed. When the notification arrives, the _onnotification method finds no matching handler and no fallbackNotificationHandler, so it returns early without action. The listTools method exists but is only called once during initial connection setup. This prevents dynamic tool loading scenarios where an MCP server adds or removes tools during a session.","Suggested solution: Register a notification handler for notifications/tools/list_changed that calls listTools on the affected server connection and updates the internal tool cache.","[{\\"error\\":\\"Error: Plugin hook \\\\\\"cat | curl -sf -X POST -H \\\\\\"X-Wrapper-PID: $MAITRED_WRAPPER_PID\\\\\\" -d @- http://localhost:9100/hook\\\\\\" failed with exit code 7\\\\n at Object.callback (file:///home/temujin9/.claude/local/node_modules/@anthropic-ai/claude-code/cli.js:1860:13)\\\\n at async K35 (file:///home/temujin9/.claude/local/node_modules/@anthropic-ai/claude-code/cli.js:2993:1190)\\\\n at async file:///home/temujin9/.claude/local/node_modules/@anthropic-ai/claude-code/cli.js:2986:912\\\\n at async vZA (file:///home/temujin9/.claude/local/node_modules/@anthropic-ai/claude-code/cli.js:1878:5591)\\\\n at async"]}{"url":"https://pypi.org/project/fastmcp/2.2.6/","title":"fastmcp · PyPI","description":"Decorate synchronous or asynchronous functions with @mcp.tool(). FastMCP automatically generates the necessary MCP schema based on type hints and docstrings. Pydantic models can be used for complex inputs. import httpx from pydantic import BaseModel class UserInfo(BaseModel): user_id: int notify: bool = False @mcp.tool() async def send_notification(user: UserInfo, message: str) -&gt; dict: &quot;&quot;&quot;Sends a notification to a user if requested.&quot;&quot;&quot; if user.notify: # Simulate sending notification print(f&quot;Notifying user {user.user_id}: {message}&quot;) return {&quot;status&quot;: &quot;sent&quot;, &quot;user_id&quot;: user.user_id} return {&quot;status&quot;: &quot;skipped&quot;, &quot;user_id&quot;: user.user_id} @mcp.tool() def get_stock_price(ticker: str) -&gt; float: &quot;&quot;&quot;Gets the current price for a stock ticker.&quot;&quot;&quot; # Replace with actual API call prices = {&quot;AAPL&quot;: 180.50, &quot;GOOG&quot;: 140.20} return prices.get(ticker.upper(), 0.0)","extra_snippets":["FastMCP.from_client is a class method that connects to the target, discovers its capabilities, and dynamically builds the proxy server instance. Structure larger MCP applications by creating modular FastMCP servers and \\"mounting\\" them onto a parent server. This automatically handles prefixing for tool names and resource URIs, preventing conflicts.","Decorate synchronous or asynchronous functions with @mcp.tool(). FastMCP automatically generates the necessary MCP schema based on type hints and docstrings. Pydantic models can be used for complex inputs. import httpx from pydantic import BaseModel class UserInfo(BaseModel): user_id: int notify: bool = False @mcp.tool() async def send_notification(user: UserInfo, message: str) -> dict: \\"\\"\\"Sends a notification to a user if requested.\\"\\"\\" if user.notify: # Simulate sending notification print(f\\"Notifying user {user.user_id}: {message}\\") return {\\"status\\": \\"sent\\", \\"user_id\\": user.user_id} return {\\"status\\": \\"skipped\\", \\"user_id\\": user.user_id} @mcp.tool() def get_stock_price(ticker: str) -> float: \\"\\"\\"Gets the current price for a stock ticker.\\"\\"\\" # Replace with actual API call prices = {\\"AAPL\\": 180.50, \\"GOOG\\": 140.20} return prices.get(ticker.upper(), 0.0)","You can connect to servers using any supported transport protocol (Stdio, SSE, FastMCP, etc.). If you don\'t specify a transport, the Client class automatically attempts to detect an appropriate one from your connection string or server object. The Client class exposes several methods for interacting with MCP servers. async with Client(\\"path/to/server\\") as client: # List available tools tools = await client.list_tools() # List available resources resources = await client.list_resources() # Call a tool with arguments result = await client.call_tool(\\"generate_report\\", {\\"user_id\\": 123}) # Read a resource user_data = await client.read_resource(\\"db://users/123/profile\\") # Get a prompt greeting = await client.get_prompt(\\"welcome\\", {\\"name\\": \\"Alice\\"}) # Send progress updates await client.progress(\\"task-123\\", 50, 100) # 50% complete # Basic connectivity testing await client.ping()","Provide functionality through Tools (think POST/PUT endpoints; execute actions) Define interaction patterns through Prompts (reusable templates) ... FastMCP provides a high-level, Pythonic interface for building and interacting with these servers."]}{"url":"https://www.npmjs.com/package/fastmcp","title":"fastmcp - npm","description":"Both approaches are fully compatible with all MCP clients, including Cursor. FastMCP automatically generates the proper schema in both cases. You can control which tools are available to authenticated users by adding an optional canAccess function to a tool&#x27;s definition.","extra_snippets":["The auth option uses FastMCP\'s built-in OAuth Proxy that acts as a secure intermediary between MCP clients and upstream OAuth providers. The proxy handles the complete OAuth 2.1 authorization flow, including Dynamic Client Registration (DCR), PKCE, consent management, and token management with encryption and token swap patterns enabled by default.","Both approaches are fully compatible with all MCP clients, including Cursor. FastMCP automatically generates the proper schema in both cases. You can control which tools are available to authenticated users by adding an optional canAccess function to a tool\'s definition.","FastMCP supports Roots - Feature that allows clients to provide a set of filesystem-like root locations that can be listed and dynamically updated. The Roots feature can be configured or disabled in server options: const server = new FastMCP({ name: \\"My Server\\", version: \\"1.0.0\\", roots: { // Set to false to explicitly disable roots support enabled: false, // By default, roots support is enabled (true) }, }); ... server.on(\\"connect\\", (event) => { const session = event.session; // Access the current roots console.log(\\"Initial roots:\\", session.roots); // Listen for changes to the roots session.on(\\"rootsChanged\\", (event) => { console.log(\\"Roots changed:\\", event.roots); }); });","FastMCP uses the Standard Schema specification for defining tool parameters."]}{"url":"https://github.com/danny-avila/LibreChat/issues/7117","title":"[Enhancement]: Respond to the notifications/tools/list_changed MCP message · Issue #7117 · danny-avila/LibreChat","description":"The MCP client should respond by requesting the tool list as described in the MCP List Changed Notification Specification · My MCP server is dynamically creating new tools and sending list_changed notifications, but LibreChat is not requesting a new tool list, so the tool list remains static until a restart is done.","extra_snippets":["What features would you like to see added? Respond to notifications/tools/list_changed notification MCP message More details It appears that Librechat is not responding to the notifications/tools/list_changed notification message sent fr...","The MCP client should respond by requesting the tool list as described in the MCP List Changed Notification Specification · My MCP server is dynamically creating new tools and sending list_changed notifications, but LibreChat is not requesting a new tool list, so the tool list remains static until a restart is done."]}{"url":"https://github.com/jlowin/fastmcp/issues/2521","title":"FastMCP Proxy causes \\"listChanged\\" and other tool-list properties to flip to \\"true\\" unexpectedly · Issue #2521 · jlowin/fastmcp","description":"Hi, I noticed an unexpected behavior when using FastMCP Proxy in front of my MCP server. ... When a client connects directly to my MCP server, the response to tools/list contains the correct metadata — specifically, all of the listChanged, resourceChanged, and promptTemplateChanged flags are &quot;false&quot; (as expected), because my server is extremely simple and does not implement tool-list change tracking.","extra_snippets":["Description Hi, I noticed an unexpected behavior when using FastMCP Proxy in front of my MCP server. Problem Summary When a client connects directly to my MCP server, the response to tools/list contains the correct metadata — specificall...","My server is extremely simple — no resources, no prompt templates, no dynamic tool changes. ... Does FastMCP Proxy intentionally rebuild or wrap the tools/list response?","Hi, I noticed an unexpected behavior when using FastMCP Proxy in front of my MCP server. ... When a client connects directly to my MCP server, the response to tools/list contains the correct metadata — specifically, all of the listChanged, resourceChanged, and promptTemplateChanged flags are \\"false\\" (as expected), because my server is extremely simple and does not implement tool-list change tracking.","FastMCP Proxy causes \\"listChanged\\" and other tool-list properties to flip to \\"true\\" unexpectedly#2521"]}'}]