Getting started Community Training Tutorials Documentation APIs, AI & Tools
Search Result Limit
Policy Name |
MCP Tools Progressive Disclosure |
Summary |
Reduces context window token cost by exposing tools on-demand through search |
Category |
MCP |
First Omni Gateway version available |
v1.13.0 |
Release Notes |
|
Returned Status Codes |
No return codes exist for this policy. |
| This policy supports Model Context Protocol (MCP) version 2025-06-18 and earlier. To learn more about MCP, see MCP Specification. |
The MCP Tools Progressive Disclosure policy reduces an MCP client’s context-window token cost by hiding the tools/list catalog behind these tools:
search_tools: Finds relevant tools on demand by matching a query against tool names and descriptions.
invoke_tool: Calls a tool discovered via search_tools.
With this policy, you can:
Reduce token consumption by exposing tools on-demand rather than listing all tools up front.
Keep frequently-used tools immediately available through hotTools configuration.
Support paginated search results for large tool catalogs.
Preserve normal tool invocation semantics for upstream policies.
| This policy must be positioned after the MCP Support Policy but before any other MCP authorization policies, such as access control, tool mapping, or schema validation policies. To learn more about MCP authorization policies, see Configuring MCP Access Control Policies. |
The policy performs no tool caching. Every tools/list, search_tools, and invoke_tool request is resolved against the live upstream, so the client always sees the real, per-caller-filtered upstream state.
When you apply the policy from the UI, the following parameters are displayed:
| Element | Description | Default |
|---|---|---|
Search Result Limit |
The maximum number of matches a |
|
Hot Tools |
Tool names or patterns that bypass disclosure. Matched tools appear in the client-facing |
|
Meta Tool Prefix |
A prefix prepended to the |
|
- policyRef:
name: mcp-tools-progressive-disclosure-policy-flex
config:
searchResultLimit: 20
hotTools:
- "get_weather"
- "list_*"
metaToolPrefix: "mcp_"
The metaToolPrefix value "mcp_" produces mcp_search_tools and mcp_invoke_tool. The underscore is part of the configured prefix, not added automatically.
|
When a client requests tools/list, the policy:
Forwards the request upstream to get the live, per-caller-filtered tool catalog.
Replaces the full catalog with the two meta-tools (search_tools and invoke_tool).
Includes any tools matching the configured hotTools patterns with their original schemas.
When a client calls search_tools:
The policy forwards a synthesized tools/list request upstream.
The upstream access control policy filters the list per caller.
The policy runs the search query against the filtered list.
Matching tools are returned with their full schemas, sufficient to construct an invoke_tool call.
When a client calls invoke_tool:
The policy rewrites the request as a native tools/call with the wrapped tool name.
All upstream policies see the real tool name (not invoke_tool).
The response is returned to the caller unchanged.
This normalization ensures that access control, tool mapping, and other policies operate on the real tool name without progressive-disclosure awareness.
The hotTools configuration enables you to keep frequently-used tools immediately visible without requiring a search. Tools matching the patterns appear in tools/list alongside search_tools and invoke_tool.
Use exact names: "get_weather".
Use glob patterns: "list_*", "*_info".
Matches are evaluated against the live upstream tools/list response on every request.
Only tools the caller is authorized to see (per the chain’s access control policy) will match.
The search_tools meta-tool accepts a JSON object with the following parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
|
string |
Yes |
A case-insensitive regular expression to match against tool names and descriptions. Separate alternative keywords with |
|
integer |
No |
Maximum number of results to return per page. If omitted, uses the configured |
|
string |
No |
Opaque pagination cursor from a prior search’s |
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "search_tools",
"arguments": {
"query": "weather",
"limit": 3
}
}
}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "Found 1 matching tool(s)."
}
],
"structuredContent": {
"matches": [
{
"name": "get_weather",
"description": "Return the current weather for a city",
"inputSchema": {
"type": "object",
"required": ["city"],
"properties": {
"city": {
"type": "string"
}
}
}
}
]
}
}
}
When more tools match than fit on a page, the response includes a nextCursor field under structuredContent:
{
"structuredContent": {
"matches": [...],
"nextCursor": "eyJxIjoid2VhdGhlciIsIm8iOjIwfQ=="
}
}
To fetch the next page, pass the cursor back in the arguments:
{
"method": "tools/call",
"params": {
"name": "search_tools",
"arguments": {
"cursor": "eyJxIjoid2VhdGhlciIsIm8iOjIwfQ=="
}
}
}
Each page resolves against a fresh upstream tools/list, ensuring the correct authorization. The query parameter may be omitted when using a cursor (the cursor carries it).
The invoke_tool meta-tool wraps a call to a discovered tool. It accepts:
| Parameter | Type | Required | Description |
|---|---|---|---|
|
string |
Yes |
The tool name returned from |
|
object |
Yes |
The tool’s input parameters as returned in the |
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "invoke_tool",
"arguments": {
"name": "get_weather",
"arguments": {
"city": "San Francisco"
}
}
}
}
The policy rewrites this as a native tools/call:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": {
"city": "San Francisco"
}
}
}
All upstream policies see get_weather (not invoke_tool), ensuring access control, tool mapping, and other policies operate correctly.
The MCP Tools Progressive Disclosure policy must be positioned after the MCP Support Policy but before any other MCP policies in the filter chain, particularly before any policy that reads tool names (access control, tool mapping, schema validation).
If positioned after an access control policy, that policy would see invoke_tool (the meta-tool) in the request and gate the envelope—not the real tool inside—creating an authorization bypass.
The policy maintains per-caller authorization parity by delegating to the chain:
A search_tools call triggers a synthesized tools/list request upstream.
The upstream access control policy filters the list per caller.
The policy runs the query against the filtered list.
Only tools the caller is authorized to see are included in results.
This ensures:
Callers don’t see tools they cannot invoke.
Results reflect live authorization state.
No caching of authorization decisions.
If no access control policy is present, search_tools returns the full unfiltered catalog—the same as a direct tools/list would in that chain.
The policy returns JSON-RPC error objects with a stable data.reason field for machine-checkable error handling.
| Case | Code | data.reason |
Description |
|---|---|---|---|
Malformed |
|
|
Missing or invalid |
Malformed |
|
|
Empty/missing/non-string query, exceeds 256 characters, invalid regex, bad |
Errors produced upstream (access control denials, upstream tool errors) pass through unchanged.