From 3f971550bda0ef7e322b32d5817578fc0d35e8cd Mon Sep 17 00:00:00 2001 From: Peter Ibekwe Date: Wed, 13 May 2026 15:34:27 -0700 Subject: [PATCH] Addressed initial PR comments. --- .../InvokeFoundryToolboxMcp.yaml | 6 +++--- .../InvokeFoundryToolboxMcp/Program.cs | 18 ++++++++++++------ .../DefaultMcpToolHandler.cs | 11 ++++------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/dotnet/samples/03-workflows/Declarative/InvokeFoundryToolboxMcp/InvokeFoundryToolboxMcp.yaml b/dotnet/samples/03-workflows/Declarative/InvokeFoundryToolboxMcp/InvokeFoundryToolboxMcp.yaml index d7941a51ac..b5f6f39316 100644 --- a/dotnet/samples/03-workflows/Declarative/InvokeFoundryToolboxMcp/InvokeFoundryToolboxMcp.yaml +++ b/dotnet/samples/03-workflows/Declarative/InvokeFoundryToolboxMcp/InvokeFoundryToolboxMcp.yaml @@ -37,7 +37,7 @@ trigger: toolName: tools/list conversationId: =System.ConversationId headers: - Foundry-Features: Toolboxes=V1Preview + Foundry-Features: Toolboxes=V1Preview output: autoSend: true result: Local.ToolboxTools @@ -50,7 +50,7 @@ trigger: toolName: =Env.FOUNDRY_TOOLBOX_DOCS_SERVER_LABEL & "___microsoft_docs_search" conversationId: =System.ConversationId headers: - Foundry-Features: Toolboxes=V1Preview + Foundry-Features: Toolboxes=V1Preview arguments: query: =Local.SearchQuery output: @@ -67,7 +67,7 @@ trigger: toolName: =Env.FOUNDRY_TOOLBOX_WEB_SEARCH_TOOL_NAME conversationId: =System.ConversationId headers: - Foundry-Features: Toolboxes=V1Preview + Foundry-Features: Toolboxes=V1Preview arguments: search_query: =Local.SearchQuery output: diff --git a/dotnet/samples/03-workflows/Declarative/InvokeFoundryToolboxMcp/Program.cs b/dotnet/samples/03-workflows/Declarative/InvokeFoundryToolboxMcp/Program.cs index 5f577052b6..6636cb13a7 100644 --- a/dotnet/samples/03-workflows/Declarative/InvokeFoundryToolboxMcp/Program.cs +++ b/dotnet/samples/03-workflows/Declarative/InvokeFoundryToolboxMcp/Program.cs @@ -6,6 +6,7 @@ using System.ClientModel; using System.ClientModel.Primitives; +using System.Collections.Concurrent; using System.Net.Http.Headers; using Azure.AI.Projects; using Azure.AI.Projects.Agents; @@ -60,11 +61,15 @@ internal sealed class Program // Ensure sample toolbox and agent exist in Foundry string toolboxEndpoint = await CreateSampleToolboxAsync(toolboxName, docsServerLabel, foundryEndpoint, credential); string toolboxMcpServerUrl = BuildToolboxMcpServerUrl(toolboxEndpoint, toolboxName, toolboxApiVersion); - Environment.SetEnvironmentVariable(ToolboxMcpServerUrlSetting, toolboxMcpServerUrl); - // Expose the server label to the workflow so the YAML can build prefixed MCP tool names dynamically. - Environment.SetEnvironmentVariable(DocsServerLabelSetting, docsServerLabel); - // Expose the web search tool name so the YAML can reference it without hard-coding. - Environment.SetEnvironmentVariable(WebSearchToolNameSetting, webSearchToolName); + IConfiguration workflowConfiguration = new ConfigurationBuilder() + .AddConfiguration(configuration) + .AddInMemoryCollection(new Dictionary + { + [ToolboxMcpServerUrlSetting] = toolboxMcpServerUrl, + [DocsServerLabelSetting] = docsServerLabel, + [WebSearchToolNameSetting] = webSearchToolName, + }) + .Build(); await CreateAgentAsync(foundryEndpoint, configuration, credential); @@ -72,7 +77,7 @@ internal sealed class Program string workflowInput = Application.GetInput(args); // Create the MCP tool handler for invoking the Foundry toolbox MCP proxy. - List createdHttpClients = []; + ConcurrentBag createdHttpClients = []; DefaultMcpToolHandler mcpToolHandler = new( httpClientProvider: async (serverUrl, _) => { @@ -97,6 +102,7 @@ internal sealed class Program // Create the workflow factory with MCP tool provider WorkflowFactory workflowFactory = new("InvokeFoundryToolboxMcp.yaml", foundryEndpoint) { + Configuration = workflowConfiguration, McpToolHandler = mcpToolHandler }; diff --git a/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative.Mcp/DefaultMcpToolHandler.cs b/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative.Mcp/DefaultMcpToolHandler.cs index 34d914589e..66da428cf6 100644 --- a/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative.Mcp/DefaultMcpToolHandler.cs +++ b/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative.Mcp/DefaultMcpToolHandler.cs @@ -67,16 +67,13 @@ public sealed class DefaultMcpToolHandler : IMcpToolHandler, IAsyncDisposable if (IsListToolsToolName(toolName)) { ThrowIfListToolsArgumentsSpecified(arguments); + McpClient listToolsClient = await this.GetOrCreateClientAsync(serverUrl, serverLabel, headers, cancellationToken).ConfigureAwait(false); + IList tools = await listToolsClient.ListToolsAsync(cancellationToken: cancellationToken).ConfigureAwait(false); + return CreateListToolsResultContent(tools.Select(tool => tool.ProtocolTool)); } McpClient client = await this.GetOrCreateClientAsync(serverUrl, serverLabel, headers, cancellationToken).ConfigureAwait(false); - if (IsListToolsToolName(toolName)) - { - IList tools = await client.ListToolsAsync(cancellationToken: cancellationToken).ConfigureAwait(false); - return CreateListToolsResultContent(tools.Select(tool => tool.ProtocolTool)); - } - McpServerToolResultContent resultContent = new(Guid.NewGuid().ToString()); // Convert IDictionary to IReadOnlyDictionary for CallToolAsync @@ -349,6 +346,6 @@ public sealed class DefaultMcpToolHandler : IMcpToolHandler, IAsyncDisposable writer.WriteEndObject(); } - return Encoding.UTF8.GetString(stream.ToArray()); + return Encoding.UTF8.GetString(stream.GetBuffer(), 0, (int)stream.Length); } }