Skip to content

SEP-1821: Dynamic Tool Discovery #1821

@truehazker

Description

@truehazker

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.

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" }

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

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

#1822

Metadata

Metadata

Assignees

No one assigned

    Labels

    SEPproposalSEP proposal without a sponsor.

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions