Skip to content

SEP-1821: Dynamic Tool Discovery #1821

Description

@truehazker

SEP-1821: Dynamic Tool Discovery

Abstract

This proposal extends tools/list to support tool search via an optional query parameter. Adds ServerCapabilities.tools.filtering to indicate support, enabling agents to know when they can request filtered tool subsets.

Motivation

Current MCP implementations return all tools on every tools/list request. For servers with large or context-dependent tool sets:

  1. Scale: Servers with hundreds of tools waste bandwidth returning all tools
  2. Discovery: No mechanism for searching tools by name or description
  3. UX: Users cannot easily find relevant tools in large catalogs

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 PaginatedRequestParams with optional search:

interface ListToolsRequestParams extends PaginatedRequestParams {
  query?: string; // Search string
}

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:

  • Single words: "database", "filesystem", "network"
  • Short phrases: "read files", "http requests"
  • Use case scenarios: "tools for data analysis", "database operations"

Examples:

// Category-based
{ "query": "database" }

// Semantic/use-case
{ "query": "tools for reading files" }

// Tag-like
{ "query": "filesystem" }

2. ServerCapabilities.tools.filtering

Signals server support for filtered tool discovery:

interface ServerCapabilities {
  tools?: {
    filtering?: boolean;
  };
}

Behavior:

  • Present: Server supports and will process the query parameter
  • Absent: Server returns all tools (query parameter ignored)

3. Server Behavior

Servers supporting tool search:

  1. Declare tools.filtering: true in ServerCapabilities during initialization
  2. When query provided, return filtered tool subset based on search
  3. When query absent, return all tools
  4. Server implements simple search strategies optimized for LLM/agent usage (substring matching, semantic search, tag matching, category filtering)
  5. Server MUST NOT expect complex JSON, structured queries, or query languages in the query field
  6. Server MUST document expected query format and examples in the instructions field

Instructions 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 instructions document feature usage and expected query format.

5. Interaction with List Change Notifications

Search works seamlessly with notifications/tools/list_changed:

// Client stores search query
const searchQuery = "database operations";

// Initial fetch
const tools = await client.request("tools/list", { query: searchQuery });

// On notification, re-fetch with same query
client.on("notifications/tools/list_changed", async () => {
  const updated = await client.request("tools/list", { query: searchQuery });
  // Client only receives updated matching tools, not full catalog
});

Benefits:

  • Reduces bandwidth on re-fetches
  • Client maintains search result consistency
  • Server only sends matching tools, even after changes

Server behavior when tools change:

  1. Send notifications/tools/list_changed (if tools.listChanged: true)
  2. Next tools/list request applies same search logic
  3. Returns current matching subset

Rationale

Design principles:

  • Simple, universal query string parameter (every search API has a query string)
  • LLM/agent-friendly: easy to generate simple text queries
  • Flexible interpretation (substring, semantic, tag matching, category filtering)
  • Doesn't conflict with future proposals for tags, categories, or structured filters
  • Covers most use cases: "find tools related to X"

Why capability flag is needed:

  • Agents need to know if filtering is supported (to avoid wasting tokens)
  • Clear signal: filtering: true = "you can use query parameter"
  • Simple boolean, no complex structure

Relationship to other filtering proposals:

  • This SEP focuses solely on text search via query
  • Future SEPs can add structured filtering (tags, categories, metadata)
  • Both can coexist: { query: "database", tags: ["sql"], category: "storage" }

Backward Compatibility

Fully backward compatible:

  • All parameters are optional
  • Servers ignore unknown parameters
  • Clients without filtering support work unchanged

Security Implications

  • Servers MUST sanitize query input (prevent injection attacks)
  • MUST treat query as plain text, never as code or structured query language
  • MUST NOT expose sensitive tool information through search results
  • SHOULD implement rate limiting to prevent search abuse
  • SHOULD validate query length

Reference Implementation

The reference implementation is available as a pull request against the specification repository:

The PR includes schema changes to ListToolsRequestParams adding the optional query field and the ServerCapabilities.tools.filtering capability flag.

Activity

  1. added
    proposalSEP proposal without a sponsor.
    and removed
    enhancementNew feature or request
    on Nov 17, 2025
  2. simonrussell commented on Nov 20, 2025

    @simonrussell
    Contributor

    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/list request?

  3. truehazker commented on Nov 20, 2025

    @truehazker
    Author

    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/list request?

    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.

  4. truehazker commented on Nov 20, 2025

    @truehazker
    Author

    @simonrussell FYI. I've updated my PR and SEP description. Now it features a simpler approach.

  5. simonrussell commented on Nov 20, 2025

    @simonrussell
    Contributor

    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/list request 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?

  6. chrisvoncsefalvay commented on Nov 20, 2025

    @chrisvoncsefalvay
    • 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/list request 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.

  7. truehazker commented on Nov 20, 2025

    @truehazker
    Author

    What 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.

  8. simonrussell commented on Nov 20, 2025

    @simonrussell
    Contributor

    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)?

  9. truehazker commented on Nov 21, 2025

    @truehazker
    Author

    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_k parameter, 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.

  10. Dazfl commented on Jan 5, 2026

    @Dazfl

    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.

  11. onmete commented on Jan 5, 2026

    @onmete

    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.

  12. sep-automation-bot commented on Feb 23, 2026

    @sep-automation-bot

    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.

  13. localden commented on Apr 8, 2026

    @localden
    Contributor

    @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).

  14. heiwen commented on Apr 9, 2026

    @heiwen

    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-practices

  15. truehazker commented on Apr 9, 2026

    @truehazker
    Author

    MHO, 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")

  16. truehazker commented on Apr 9, 2026

    @truehazker
    Author

    @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

  17. truehazker commented on Apr 9, 2026

    @truehazker
    Author

    For everyone interested, join the conversation about this proposal in discord: https://discord.com/channels/1358869848138059966/1425903819186770064/1491737396230881371

  18. aak204 commented on Apr 13, 2026

    @aak204
  19. localden commented on Jun 24, 2026

    @localden
    Contributor

    @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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    SEPproposalSEP proposal without a sponsor.

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions