Give an agent five tools and it picks the right one almost every time. Give it two hundred and three things go wrong together. Every turn costs more tokens, the context fills with tool definitions the task never needs, and the model starts choosing the wrong tool. Microsoft Foundry has a built-in answer to this: tool search in Toolboxes.
What a toolbox is
A toolbox is a named, versioned bundle of tools that your agents reach through one endpoint. The tools can be remote MCP servers or built-in Foundry tools. You curate the toolbox once, publish a version, and any agent that needs those capabilities can use it. As of Microsoft's September 2026 update, toolboxes are generally available for hosted agents and in public preview for prompt agents.
How tool search works
You turn tool search on by adding one entry, {"type": "toolbox_search"}, to the toolbox version. After that, the toolbox no longer lists its tools to the model. The model sees two meta-tools instead:
tool_search, which the model calls with a plain-language description of what it needs, such as "look up calendar events".call_tool, which the model uses to run any tool that the search returned.
Foundry ranks the toolbox's tools against the query using BM25, a standard text-ranking method that scores each tool's name, description, and parameter information. It returns the best matches, five by default and ten at most. Tools that come back stay callable for the rest of the turn, and the model can search again if a later step needs something else.
Microsoft reports that in an internal evaluation on a public benchmark of more than 44,000 tools, tool search cut input tokens by more than 60% for a 50-tool toolbox and by over 97% for a 1,000-tool toolbox. Those numbers compare against a prompt-cached baseline that loads the whole catalog up front. They are Microsoft's results, so measure your own agent before you quote them.
Create a toolbox with tool search
You need a Foundry project, the Foundry User role on that project, and a project connection for any MCP server that requires credentials. Here is the Python version:
import os
from azure.identity import DefaultAzureCredential
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import MCPToolboxTool, ToolSearchToolboxTool
project = AIProjectClient(
endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
credential=DefaultAzureCredential(),
)
github_tools = MCPToolboxTool(
server_label="github",
server_url="https://api.githubcopilot.com/mcp",
require_approval="never", # use "always" for tools that change data
project_connection_id="your-connection-id",
)
version = project.toolboxes.create_version(
name="my-toolbox",
description="Large toolbox with tool search enabled",
tools=[github_tools, ToolSearchToolboxTool()],
)
print(f"Created toolbox {version.name}, version {version.version}")
The same thing in C#:
using Azure.AI.Projects;
using Azure.AI.Projects.Agents;
using Azure.Identity;
var endpoint = Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT");
AIProjectClient projectClient = new(endpoint: new Uri(endpoint), tokenProvider: new DefaultAzureCredential());
AgentToolboxes toolboxClient = projectClient.AgentAdministrationClient.GetAgentToolboxes();
MCPToolboxTool githubTools = new(serverLabel: "github")
{
ServerUri = new Uri("https://api.githubcopilot.com/mcp"),
ToolCallApprovalPolicy = new McpToolCallApprovalPolicy(
GlobalMcpToolCallApprovalPolicy.NeverRequireApproval),
};
ToolSearchToolboxTool searchTool = new()
{
Name = "ToolBoxSearch",
Description = "Search for tools by capability"
};
ToolboxVersion version = toolboxClient.CreateVersion(
name: "my-toolbox",
tools: [githubTools, searchTool],
description: "Large toolbox with tool search enabled");
Console.WriteLine($"Created toolbox {version.Name}, version {version.Version}");
Publishing creates the first version, and it becomes the default automatically. These APIs are still in preview, so pin your package version and check the docs if a type has moved.
Check that it is working
Every toolbox version has its own MCP endpoint, so you can inspect it with any MCP client before you promote the version. If tool search is on, the tool list should contain tool_search and call_tool and nothing else, apart from tools you pinned.
import asyncio
from azure.identity import DefaultAzureCredential
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
url = ("https://<account>.services.ai.azure.com/api/projects/<project>"
"/toolboxes/my-toolbox/versions/<version>/mcp?api-version=v1")
token = DefaultAzureCredential().get_token("https://ai.azure.com/.default").token
async def main():
async with streamablehttp_client(url, headers={"Authorization": f"Bearer {token}"}) as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
print([t.name for t in tools.tools])
asyncio.run(main())
Tune what the model finds
Search works without extra settings, but two options help when you know your usage. pin keeps a tool permanently visible, so the model can call it without a search round trip. additional_search_text adds keywords to a tool's search entry when the server's own description uses different words than your users do. The extra text is used only for ranking and is never shown to the model.
{
"type": "mcp",
"server_label": "analytics",
"server_url": "https://db-mcp.internal/sse",
"tool_configs": {
"execute_query": {
"pin": True,
"additional_search_text": "SQL database analytics reporting dashboard queries",
},
"list_tables": {
"additional_search_text": "schema columns metadata table structure discover",
},
},
}
Foundry also tracks which tools each user calls most and surfaces them automatically after a short warmup, so the most-used tools skip the search step without any configuration.
Practical tips
- Write a clear description for every tool. A tool with no description, or a vague one, will rarely be returned.
- Tell the agent about the search in its instructions, for example: if you need a capability that is not in your tool list, call
tool_searchbefore saying you cannot help. - Use tool search once a toolbox passes roughly 10 to 15 tools. Below that, the extra search step is not worth it.
- Test each new version on its version-specific endpoint before you make it the default.
- If a tool sits behind OAuth, the first call returns a consent-required error with a URL. Open it, complete the sign-in, and retry.
Resources
- Enable tool search in a toolbox: learn.microsoft.com
- Curate an intent-based toolbox: learn.microsoft.com
- Foundry September 2026 update: azure.microsoft.com
Join the conversation! Your thoughts help the community grow.