Tool search: how AI harnesses load tools on demand

Published

Connecting another MCP server should not require the model to read another hundred function definitions before answering a question. Deferred tool discovery keeps the full catalog available to the harness and brings individual tools into the model's context when they become relevant.

There are two useful approaches. Native loading makes a discovered tool directly callable by the model. Documentation retrieval returns its signature as ordinary tool output; the model then invokes it through code or a generic dispatcher. Both spend context on discovered definitions. They differ in how those definitions become usable.

The idea predates the recent MCP ecosystem. July 2023's ToolLLM already included a retriever that selected APIs for an instruction. Anthropic introduced MCP in November 2024, making integrations easier to connect. Deciding how much of their catalog to show the model remained a separate problem.

The public milestones reach well before summer 2026. Cloudflare described Code Mode on September 26, 2025: present APIs as TypeScript and let the model compose calls in code. Anthropic's November 4 post explicitly described reading tool definitions on demand or finding them with search_tools. Its November 24 release added API-level tool search and defer_loading.

Claude Code 2.1.7, released January 14, 2026, enabled automatic MCP tool search when definitions exceeded 10% of the context window. Its current documentation describes deferral by default on supported configurations, with that threshold available as an optional mode. These are concrete release milestones, rather than a claim that the whole ecosystem switched at once.

The implementations now make different choices:

Harness Initially visible Discovery and invocation
Codex Core tools and bounded summaries of deferred namespaces. Local BM25 search supports both paths: native tool_search_output loads schemas; code-mode search returns callable names and TypeScript declarations.
Claude Code In the inspected mirror, deferred tools are announced by name; their parameter schemas stay deferred. The mirrored implementation uses weighted keyword matching or exact select: queries. Results contain tool_reference blocks that load definitions for direct calls.
Grok Build Local mode exposes built-in tools and MCP server summaries; individual integration schemas stay in the host catalog. search_tool returns matching names, descriptions and input schemas as JSON tool output, with five results by default. The index tries exact tool names before BM25. use_tool dispatches calls by qualified name; search leaves the native tool list unchanged.
OpenCode A partial code-mode catalog, plus namespace summaries. search returns descriptions and typed signatures, with namespace filtering and pagination. Calls run through code mode.
Pi Supports direct, code-mode, and deferred exposure; code-mode declarations have an inline budget. Code mode provides discovery helpers and ALL_TOOLS. A separate BM25 tool search activates native tools for subsequent model calls.
eve Eager tools, fixed catalog tools, and a bounded namespace/connection listing. eve__search returns names and TypeScript signatures. eve__tool({name,input}) invokes them through one fixed schema, without promoting each result into the native tool list.
DeepSeek Harness Native execution exposes all currently visible schemas. Programmatic calling exposes run_code plus an SDK for those tools. The inspected programmatic executor renders the whole visible SDK. It changes execution style, but does not itself defer definitions until search.
Happen A small core interface and bounded namespace summaries; external schemas remain in the host registry. Shared BM25 discovery returns declarations inside code mode or selectively loads schemas for direct calls. Compaction restores only explicitly loaded native tools.

The Claude Code source above comes from codeaashu's leaked-source mirror, at revision b983a3b. It is a community-maintained snapshot, not an official source release or proof of the exact implementation shipping today. The other implementation links also pin the revisions inspected for this comparison.

DeepSeek Harness illustrates an easy mistake: one execution tool can still come with a huge description of every function behind it. Code execution and deferred tool discovery solve different parts of context growth.

In Happen, I use code mode as the primary path. Searching with tools.tool_search({query, limit}) returns declarations without changing the native tool list. ALL_TOOLS remains available for exact lookup and filtering. Direct discovery loads only its matches. After compaction, namespace summaries and explicitly loaded native schemas return; ordinary discovery output follows the rest of conversation history. The same policy serves GPT and DeepSeek.

Prompt caching makes placement matter too. OpenAI's tool-search API appends loaded definitions at the end of context, preserving the earlier prefix.

With around 20 installed plugins, several integrations might expose tools for searching documents, creating issues or inspecting a page. The model needs enough source identity and capability metadata to formulate a useful query. Composer selections and server summaries supply that context before retrieval.

Codex: explicit plugin selection

In Codex 0.166.0, collect_explicit_plugin_mentions resolves structured or Markdown-linked plugin:// references by exact plugin ID. The turn builder adds those plugins' MCP servers to its startup requirements before capturing the first request's tool catalog. A selection therefore affects server readiness as well as prompt content.

build_plugin_injections then maps each explicitly mentioned plugin to its available MCP server names, enabled app labels and skill namespace. It wraps the resulting text in PluginInstructions, with role: "developer". When the plugin has available apps, the full hint explicitly tells the model to search their tools before falling back to unrelated or built-in tools.

The renderer caps each plugin hint at 4 KiB. With SimplifiedSelectionHints enabled, it replaces the capability mapping with a shorter instruction naming the selected plugin and asking the model to use its skills and tools. That retains the user's selection but supplies fewer concrete names for query construction.

The tool_search input schema still contains only query and limit. ToolSearchHandler ranks deferred registry entries using BM25; the hint adds no plugin filter or ranking weight. Its retrieval effect depends on the model using the supplied identity in its query. Server startup can also make previously unavailable tools discoverable.

Schema loading follows that search. For a native call, ToolSearchOutput::to_response_item returns tool_search_output with execution: "client", the search call_id and the selected schemas in tools. A code-mode search returns callable names and TypeScript declarations as tool output. The plugin hint itself carries neither form of tool declaration.

Grok Build: hints from connected servers

Grok Build's local MCP path derives its hints from a shared ToolMetadataSnapshot. It contains tool metadata, server metadata and an initialization flag. Server descriptions can come from the MCP initialize response's instructions field. The reminder renderer emits each server's name, tool count and description, with descriptions sanitized and capped at 2,048 characters. Individual tool names and schemas stay out of this listing.

The session injector tracks fingerprints containing the tool count and hashes of the description and tool names. Its default delta mode announces added, changed or removed servers. It appends a usage instruction requiring search_tool to retrieve the input schema before use_tool. The model gets both integration names and an explicit rule to discover schemas before dispatch.

Those names participate directly in retrieval. The index builds each BM25 document from the server name, tool name, description and parameter names. It also appends identifier components split at __, _, - and camelCase boundaries, and normalizes queries similarly. A query such as linear create issue can therefore match the server identity as well as the operation. The server name is a ranking term, not a mandatory filter.

Before BM25, the index tries a case-insensitive exact match on the qualified or bare tool name. A collision between bare names returns the first matching entry; using server__tool disambiguates tools from different servers. Otherwise, the index ranks the current snapshot and returns up to limit matches, five by default. The handler groups results by server and returns tool_name, description, score and input_schema as JSON tool output. It reports status: "partial" while the snapshot is still initializing. Calls continue through use_tool; discovery leaves the native tool list unchanged.

Grok's composer also exposes plugin skills through ACP slash commands. Their metadata includes pluginName, and invocation passes /name args to the shell for skill expansion. The server hint above is generated from the session's MCP catalog and does not require that selection.

Context cost and retrieval behavior

Selecting one Codex plugin out of 20 adds at most one hint, bounded at 4 KiB. That is separate from advertising the available search sources: when enabled, the source listing in tool_search has its own 512 KiB aggregate budget and reserves room for source names before descriptions. A hint for the selected plugin does not remove that baseline catalog cost.

Grok bounds each server description, but the reminder renderer has no aggregate budget for the server list. Its initial listing grows with the number of servers; delta announcements limit repeated listings when the catalog changes. The default of five search results bounds the number of retrieved schemas, not their total size. Installed plugins, connected servers and searchable tools are different counts: one plugin can supply several servers or only skills.

Hints provide concrete input for query generation, while exact lookup, ranking and schema exposure remain separate mechanisms. To measure their benefit with those 20 plugins, compare the same tasks and catalog with and without the hints: retrieval recall at the chosen result limit, search retries, context tokens and latency for completed tasks. The source establishes how hints can affect discovery; it does not establish the size of that improvement.