Repository navigation
SEP-1821: Dynamic Tool Discovery #1821
Description
Activity
- addedproposalSEP proposal without a sponsor.SEP proposal without a sponsor.and removedenhancementNew feature or requestNew feature or request
on Nov 17, 2025 If the server defines what the filtering means, how does a client know what to send? And why does the client capability need to be exposed -- isn't all the information in the
tools/listrequest?If the server defines what the filtering means, how does a client know what to send? And why does the client capability need to be exposed -- isn't all the information in the
tools/listrequest?Good point. There’s no need for a server to know if the client supports tool filtering, as it's purely a server-side thing.
Regarding custom filtering, it’s the aspect I'm struggling with. I've seen some great proposals that feature filtering with tags and groups, and I wanted to make my semantic search compatible with them.
I think I'll simplify my proposal with the next commit. I'll remove custom metadata and filtering to avoid interfering with other filtering proposals and will only retain using a query parameter without any metadata.
@simonrussell FYI. I've updated my PR and SEP description. Now it features a simpler approach.
Definitely looks simpler 👍
What drove you to write this SEP -- did it come out of discussions on the discord somewhere?
Now I'm thinking about it more, I guess I'm wondering how many clients will use this, for a few reasons:
- a lot of clients just fetch the tools once when they connect
- a lot of servers don't have that many tools
- you can only figure out you need to use this feature by doing a full
tools/listrequest to see how many tools there are (and then you've already got the full list and can filter it client side) - for a lot of LLM-based clients, the tool list goes into the context at the start -- what criteria would the client use to filter the list? (How would it know the other tools won't be required?)
Is there a client that's needing this feature?
- a lot of servers don't have that many tools
- you can only figure out you need to use this feature by doing a full
tools/listrequest to see how many tools there are (and then you've already got the full list and can filter it client side)
I see your point. That said, consider something like the AWS Cloud Control API MCP, which wraps around north of a thousand resources that might from time to time change. More importantly, we know from practical experience that it takes much less than that to start degrading performance. MCP servers with tools in the mid to high double digits are frequent enough that I can see the point to this.
Reacted by Egor Orlov and John WangWhat drove you to write this SEP -- did it come out of discussions on the discord somewhere?
I bumped into this while looking for an MCP gateway that can filter tools dynamically instead of using a static list. Right now we can filter only during initialization by passing an authorization header, which gives access to a limited set of tools tied to the authenticated user and offers no dynamic tool search.
It's a good idea to move this discussion to Discord, maybe it will get more comments and ideas.
- a lot of clients just fetch the tools once when they connect
That's true, but asking the client to refetch tools is still simpler than spinning up virtual MCP servers on every request to filter out tools by some traits. On mobile devices this becomes especially painful for DX.
- a lot of servers don't have that many tools
There are many MCP gateways appearing now, but none of them support proper filtering, especially semantic filtering.
- you can only figure out you need to use this feature by doing a full tools/list request to see how many tools there are (and then you've already got the full list and can filter it client side)
LLMs work noticeably better when they get a tighter set of tools. The tradeoff is that the LLM won't see the full set of abilities based on existing tools, but this can be corrected with clearer prompt instructions.
Also, it will make the context window drastically smaller in size, so we can achieve much better results with this filtering approach.
- for a lot of LLM-based clients, the tool list goes into the context at the start -- what criteria would the client use to filter the list? (How would it know the other tools won't be required?)
This is also part of the tradeoff. Clients would need to adopt a pattern of refetching tools when needed. My use case is more agent driven. With a Mastra sdk agent this filtering would be very easy to support with minimal code changes. I believe this will simplify things rather than complicate them.
It's a good idea to move this discussion to Discord, maybe it will get more comments and ideas.
Yeah I think this sort of change is best started there -- I think this does relate to what primitive-grouping-wg is doing, but TBH I haven't really been tracking much of the tool discovery stuff, so there may be other places to discuss it.
LLMs work noticeably better when they get a tighter set of tools. The tradeoff is that the LLM won't see the full set of abilities based on existing tools, but this can be corrected with clearer prompt instructions.
Also, it will make the context window drastically smaller in size, so we can achieve much better results with this filtering approach.
This is true, but there's nothing that says that the list of tools returned from an MCP server has to go directly to the LLM -- it can be filtered in the client. (Which is what some of the tool grouping stuff is about I think.)
This is also part of the tradeoff. Clients would need to adopt a pattern of refetching tools when needed. My use case is more agent driven. With a Mastra sdk agent this filtering would be very easy to support with minimal code changes. I believe this will simplify things rather than complicate them.
For an agent with a specific task I can see how you could hard-code a filter; but for a more generic approach -- what would the first filter be (for the first tool list)?
To solve the cold start problem, we can rely on the grouping feature from #1300. If the server supports grouping, an initial tools/list call with no query can return lightweight groups instead of the full tool list. This immediately gives the client a high-level view of available domains.
Once the client/LLM knows the domain, it can send a simple query inside that domain to get a filtered list of relevant tools. The server can return multiple candidates together with a similarity score, letting the client/LLM choose the best match based on name, description, and ranking.
We can also support an optional
top_kparameter, so the client can limit how many tools are returned. This will allow getting less data, but more relevant.Overall, this approach stays cheap, avoids full tools dumps on startup, and works without requiring any changes in the client implementation (e.g. client-side filtering, assembling virtual MCP servers) which is the main obstacle.
I support this feature. I have a need for this feature right now as I'm trying to get a subset of tools from an MCP server so as to keep the tool list tight for my AI agent, and also so I stay under the 128-tool limitation for some models.
While this proposal sounds intuitive and addresses a real problem (tool discovery at scale), I have concerns about whether tool filtering belongs in the MCP protocol specification at all.
The proposal explicitly states:
Servers SHOULD support simple queries that LLMs can generate
This creates unpredictable behavior for clients and agents. An agent that works well with one MCP server may fail with another, despite both advertising
tools.filtering: true.Tool selection is a research problem, not a protocol feature.
Filtering tools reliably is an active area of ML/AI research. Simple keyword matching is known to be weak and unreliable due to:
- Semantic gaps: Query "save data" won't match persist_object or write_file
- Ambiguity: "read" could mean file I/O, database queries, or parsing
- Context blindness: No understanding of the user's actual task context
- No ranking: All matches treated equally, no relevance scoring
Research has shown more effective approaches:
- RAG-based tool retrieval: Embedding tool descriptions and using semantic similarity for retrieval
- Dedicated tool-selection agents: Using a separate LLM to reason about which tools match a task
and many more (I'm far from being an expert here).
These are sophisticated ML techniques that shouldn't be expected of every MCP server implementer.The current approach of "each server implements whatever filtering it wants" will lead to fragmented, unreliable behavior that hurts the ecosystem more than it helps.
Friendly Reminder
Hi @truehazker!
This SEP proposal has been inactive for 93 days.
We wanted to check in:
- Are you still working on this proposal?
- Is there anything blocking progress?
- Do you need help finding a sponsor?
If this proposal is no longer being pursued, please let us know and we can close it. Otherwise, any update on the current status would be appreciated!
This is an automated message from the SEP lifecycle bot.
@truehazker wanted to check in if you're still interested in pushing this proposal forward? If so, it would need to be transformed into a SEP following the updated guidelines (Claude or an AI agent can help with that, if so).
IMHO, without dynamic tool discovery in MCP, the ecosystem will likely default to SKILLS.md. They provide hierarchical discovery out-of-the-box: Skills can be namespaced, nested, and conditionally loaded, letting agents navigate large capability trees without blowing up the context window or degrading selection accuracy (more tools = more noise = worse tool choice).
If MCP can't do filtered tools/list, it's viability will probably be limited only for small static tool sets. Everything else moves to skill manifests outside the protocol. The query parameter here feels like a minimal fix that keeps MCP relevant for real-scale deployments.
https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview
https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practicesMHO, without dynamic tool discovery in MCP, the ecosystem will likely default to SKILLS.md. They provide hierarchical discovery out-of-the-box: Skills can be namespaced, nested, and conditionally loaded, letting agents navigate large capability trees without blowing up the context window or degrading selection accuracy (more tools = more noise = worse tool choice).
If MCP can't do filtered tools/list, it's viability will probably be limited only for small static tool sets. Everything else moves to skill manifests outside the protocol. The query parameter here feels like a minimal fix that keeps MCP relevant for real-scale deployments.
https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices
I agree, the real thing is that during the discovery stage skills only share their title + description, but as for MCP we share list of tools bloated with I/O schema. But this proposal is actually not about it.
I think that agent should be perceived like a user. When we go to google and search for something, google does not show every single website it has discovered. It shows only portion that's semantically relevant and aligns with the user problem or request.
Right now I see that every discovery mechanism offloads search to the agent. While the agent should only do selection from the subset of tools. That's how I see it.
As for token consumption, having a deterministic and working search on the server side will eliminate wasting thousands of tokens just to browse through some tools that may not be relevant at all.
And as for problems with this proposal. Essentially there are two:
- How the agent can know the capabilities of the server, so it has an idea of what to search for.
- How the search should work and how to make it deterministic.
While the second question is solved by creating some sort of a standard/default search provided in the MCP framework, the first one is not very trivial.
But to make it work, we still don't need to give every single tool info to the agent, we just need to give enough context to perform the search, and experiment a bit to find the optimal selection window for such searches (like k coefficient in vector based search, under which we consider an item as a "match")
@truehazker wanted to check in if you're still interested in pushing this proposal forward? If so, it would need to be transformed into a SEP following the updated guidelines (Claude or an AI agent can help with that, if so).
Done, thanks for letting me know
For everyone interested, join the conversation about this proposal in discord: https://discord.com/channels/1358869848138059966/1425903819186770064/1491737396230881371
@truehazker closing this as SEPs have since moved to pull requests. If this is still a relevant project to pursue, feel free to create a new SEP PR and build support in our contributor Discord.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsNo status
SEP-1821: Dynamic Tool Discovery
Abstract
This proposal extends
tools/listto support tool search via an optionalqueryparameter. AddsServerCapabilities.tools.filteringto indicate support, enabling agents to know when they can request filtered tool subsets.Motivation
Current MCP implementations return all tools on every
tools/listrequest. For servers with large or context-dependent tool sets:This proposal provides schema support for tool search, letting servers implement text-based filtering (substring matching, semantic search, fuzzy search, etc.).
Specification
1. ListToolsRequestParams
Extends
PaginatedRequestParamswith optional search:Parameter:
query: Optional search string. Server interprets as simple text (category, tag, semantic description, or use case scenario). NOT for complex JSON or structured queries.Design for LLM/Agent usage:
Servers SHOULD support simple queries that LLMs can generate:
"database","filesystem","network""read files","http requests""tools for data analysis","database operations"Examples:
2. ServerCapabilities.tools.filtering
Signals server support for filtered tool discovery:
Behavior:
queryparameterqueryparameter ignored)3. Server Behavior
Servers supporting tool search:
tools.filtering: truein ServerCapabilities during initializationqueryprovided, return filtered tool subset based on searchqueryabsent, return all toolsqueryfieldinstructionsfieldInstructions field examples:
{ "instructions": "Tool search: Use simple keywords or categories. Examples: 'database', 'filesystem', 'tools for data analysis'" }{ "instructions": "Tool search: Supports semantic search. Describe what you want to do: 'read configuration files', 'query databases', 'send HTTP requests'" }4. Discovery Pattern
Clients discover filtering support through:
Capability Check:
{ "capabilities": { "tools": { "filtering": true } } }Documentation via Instructions:
{ "instructions": "Tool search: Use categories or short descriptions. Examples: 'filesystem', 'database', 'tools for API calls'" }{ "instructions": "Tool search: Semantic search on tool descriptions. Try: 'read files', 'http requests', 'data analysis'" }This follows MCP's existing pattern where capabilities signal feature availability, and
instructionsdocument feature usage and expected query format.5. Interaction with List Change Notifications
Search works seamlessly with
notifications/tools/list_changed:Benefits:
Server behavior when tools change:
notifications/tools/list_changed(iftools.listChanged: true)tools/listrequest applies same search logicRationale
Design principles:
Why capability flag is needed:
filtering: true= "you can use query parameter"Relationship to other filtering proposals:
query{ query: "database", tags: ["sql"], category: "storage" }Backward Compatibility
Fully backward compatible:
Security Implications
queryinput (prevent injection attacks)queryas plain text, never as code or structured query languageReference Implementation
The reference implementation is available as a pull request against the specification repository:
The PR includes schema changes to
ListToolsRequestParamsadding the optionalqueryfield and theServerCapabilities.tools.filteringcapability flag.