diff --git a/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step25_FoundryToolboxMcp/Program.cs b/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step25_FoundryToolboxMcp/Program.cs index 023fc31b988..3dc6267106f 100644 --- a/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step25_FoundryToolboxMcp/Program.cs +++ b/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step25_FoundryToolboxMcp/Program.cs @@ -5,7 +5,6 @@ // Point an `McpClient` at a Foundry Toolbox's MCP endpoint. The agent // discovers the toolbox's tools at runtime and invokes them locally. -using System.ClientModel; using System.Net.Http.Headers; using Azure.AI.Projects; using Azure.AI.Projects.Agents; @@ -21,7 +20,7 @@ // Name of the toolbox to create and connect to. const string ToolboxName = "research_toolbox"; -const string Query = "What tools do you have access to?"; +const string Query = "Find the REST API documentation for Azure Container Apps session pools."; string endpoint = Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("FOUNDRY_PROJECT_ENDPOINT is not set."); @@ -29,7 +28,7 @@ TokenCredential credential = new DefaultAzureCredential(); -// Comment out if the toolbox already exists in your Foundry project. +// Connect to the new version so the tool-search configuration is unambiguous. var toolboxEndpoint = await CreateSampleToolboxAsync(ToolboxName, endpoint, credential); // Inject a fresh Azure AI bearer token on every MCP request. @@ -72,7 +71,7 @@ Console.WriteLine($"Assistant: {await agent.RunAsync(Query)}"); // --------------------------------------------------------------------------- -// Helper: create (or replace) a sample toolbox so the sample runs end-to-end +// Helper: create a sample toolbox version so the sample runs end-to-end // --------------------------------------------------------------------------- static async Task CreateSampleToolboxAsync(string name, string endpoint, TokenCredential credential) { @@ -83,18 +82,8 @@ static async Task CreateSampleToolboxAsync(string name, string endpoint, var adminClient = new AgentAdministrationClient(new Uri(endpoint), credential); var toolboxClient = adminClient.GetAgentToolboxes(); - // Delete existing toolbox if present (ignore 404). - try - { - await toolboxClient.DeleteAsync(name); - Console.WriteLine($"Deleted existing toolbox '{name}'"); - } - catch (ClientResultException ex) when (ex.Status == 404) - { - // Toolbox does not exist — nothing to delete. - } - - // Create a fresh version with a single MCP tool. + // Enable discovery through tool_search and invocation through call_tool. + // The underlying MCP tools are not all placed in the model's initial context. MCPToolboxTool mcpTool = new("api-specs") { ServerUri = new Uri("https://gitmcp.io/Azure/azure-rest-api-specs"), @@ -103,11 +92,11 @@ static async Task CreateSampleToolboxAsync(string name, string endpoint, ToolboxVersion created = (await toolboxClient.CreateVersionAsync( name: name, - tools: [mcpTool], - description: "Sample toolbox with an MCP tool — created by Agent_Step25 sample.")).Value; + tools: [mcpTool, new ToolSearchToolboxTool()], + description: "Sample toolbox with tool search — created by Agent_Step25 sample.")).Value; Console.WriteLine($"Created toolbox '{created.Name}' v{created.Version} ({created.Tools.Count} tool(s))"); - return $"{endpoint}/toolboxes/{created.Name}/mcp?api-version=v{created.Version}"; + return $"{endpoint.TrimEnd('/')}/toolboxes/{created.Name}/versions/{created.Version}/mcp?api-version=v1"; } // --------------------------------------------------------------------------- diff --git a/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step25_FoundryToolboxMcp/README.md b/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step25_FoundryToolboxMcp/README.md index 31206477780..7290b0c166f 100644 --- a/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step25_FoundryToolboxMcp/README.md +++ b/dotnet/samples/02-agents/AgentProviders/foundry/Agent_Step25_FoundryToolboxMcp/README.md @@ -7,7 +7,7 @@ This sample shows how to use a Foundry Toolbox by pointing an `McpClient` at the - Connecting to a Foundry toolbox's MCP endpoint via Streamable HTTP transport - Injecting a fresh Azure AI bearer token (`https://ai.azure.com/.default`) on every MCP request - Passing the discovered MCP tools to `AIProjectClient.AsAIAgent(...)` -- Optional helper to create (or replace) a sample toolbox in the project so the sample is runnable end-to-end +- Creating a toolbox version with tool search enabled and connecting to that version ## Prerequisites @@ -21,9 +21,24 @@ $env:FOUNDRY_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.co $env:FOUNDRY_MODEL="gpt-5.4-mini" ``` -The sample creates a toolbox named `research_toolbox` in your Foundry project on -startup, then connects to its MCP endpoint at -`{FOUNDRY_PROJECT_ENDPOINT}/toolboxes/research_toolbox/mcp?api-version=v{version}`. +The sample creates a version of `research_toolbox` on startup, then connects to +`{FOUNDRY_PROJECT_ENDPOINT}/toolboxes/research_toolbox/versions/{version}/mcp?api-version=v1`. +Existing versions are not deleted. Review and remove sample versions in your +Foundry project when you no longer need them. + +## Tool search + +`ToolSearchToolboxTool` enables the toolbox's `tool_search` and `call_tool` +meta-tools. The agent searches for relevant capabilities before invoking a +discovered tool, rather than receiving all underlying tool definitions initially. +The sample prints the initial MCP tool names; expect those two meta-tools. +Remove `new ToolSearchToolboxTool()` from the creation helper to compare ordinary +toolbox discovery. + +This demonstrates [Foundry toolbox tool search](https://learn.microsoft.com/azure/foundry/agents/how-to/tools/tool-search), +not the separate request-scoped deferred-tool feature of the OpenAI Responses API. +The existing MCP integration handles discovery and invocation without adding an +Agent Framework tool-search API. ## Run the sample