Skip to content

.Net: [WIP] Add Foundry Toolbox Support to Hosted Agents#5318

Open
rogerbarreto wants to merge 4 commits intomicrosoft:feature/responses-hostingfrom
rogerbarreto:hosted-agents-toolbox-support
Open

.Net: [WIP] Add Foundry Toolbox Support to Hosted Agents#5318
rogerbarreto wants to merge 4 commits intomicrosoft:feature/responses-hostingfrom
rogerbarreto:hosted-agents-toolbox-support

Conversation

@rogerbarreto
Copy link
Copy Markdown
Member

@rogerbarreto rogerbarreto commented Apr 16, 2026

Summary

Adds Foundry Toolbox (MCP proxy) integration to AgentFrameworkResponseHandler in Microsoft.Agents.AI.Foundry, supporting both host-configured (eager, startup) and client-selectable (per-request, lazy) toolbox injection.

What this adds

Phase 1 — Host-configured toolboxes (eager)

  • Eager initialization via IHostedService — MCP clients connect and discover tools at startup, gating the readiness probe (spec §3.1)
  • Tool injection — discovered MCP tools are added to ChatOptions.Tools on every request
  • OAuth consent interception — JSON-RPC error -32006 returned by the Foundry proxy is caught by a per-tool AIFunction wrapper, stored in AsyncLocal shared state, and propagated back to the handler which emits mcp_approval_request + incomplete SSE events
  • Retry/backoffFoundryToolboxBearerTokenHandler retries up to 3x with exponential backoff on 429/5xx (spec §7)
  • Graceful degradation — when FOUNDRY_AGENT_TOOLSET_ENDPOINT is absent the container starts healthy with no tools (spec §2)

Phase 2 — Client-selectable toolboxes (per-request)

  • HostedMcpToolboxAITool — new public (experimental) marker type subclassing HostedMcpServerTool. Rides the OpenAI Responses mcp wire format using a synthetic foundry-toolbox://<name>?version=<v> URI so toolbox selection survives client → server serialization without a new wire type.
  • FoundryAITool.CreateHostedMcpToolbox(...) — factory overloads so consumers can attach a toolbox marker from (a) a plain name [+ version], (b) a ToolboxRecord (uses Name + DefaultVersion), or (c) a specific ToolboxVersion (uses Name + Version) retrieved from AIProjectClient.
  • Per-request parsing & merge — handler parses marker tools from the incoming request, resolves them via FoundryToolboxService, and merges with any host-configured toolbox tools. Markers are deduped by name per request.
  • Lazy toolbox open — toolboxes requested by the client that weren't pre-registered are opened on demand and cached (double-checked SemaphoreSlim). Cached toolboxes are reused across requests.
  • StrictMode option (default true) — when a client-requested toolbox fails to resolve, the handler emits a failed response with a clear error. Set StrictMode = false to silently skip unresolvable toolboxes.

Files changed

New

  • HostedMcpToolboxAITool.cs — marker tool, UriScheme = "foundry-toolbox", BuildAddress/TryParseToolboxAddress
  • FoundryToolboxOptions.cs — toolbox name list, API version, StrictMode
  • FoundryToolboxBearerTokenHandler.csDelegatingHandler: Bearer token, Foundry-Features header, 3x backoff
  • McpConsentContext.csAsyncLocal per-request consent state
  • ConsentAwareMcpClientAIFunction.csAIFunction wrapper catching -32006, cancels linked CTS to escape FunctionInvokingChatClient tool loop
  • FoundryToolboxService.csIHostedService + IAsyncDisposable: eager MCP client per toolbox at startup, plus GetToolboxToolsAsync(name, version?, ct) for lazy open
  • InputConverter.ReadMcpToolboxMarkers — parses MCPTool entries with the foundry-toolbox:// scheme
  • Unit tests: HostedMcpToolboxAIToolTests, Hosting/FoundryToolboxServiceTests
  • Hosted-Toolbox/ sample — minimal hosted agent using AddFoundryToolboxes

Modified

  • AgentFrameworkResponseHandler.cs — per-request marker parse + merge, linked CTS consent path, mcp_approval_request emission, EmitFailed on strict-mode resolution failures
  • FoundryAITool.csCreateHostedMcpToolbox(string, string?), CreateHostedMcpToolbox(ToolboxRecord), CreateHostedMcpToolbox(ToolboxVersion) factories
  • ServiceCollectionExtensions.csAddFoundryToolboxes(params string[]) and AddFoundryToolboxes(configureOptions, params string[]) overloads
  • Microsoft.Agents.AI.Foundry.csprojModelContextProtocol + Azure.Identity under .NETCoreApp condition

Usage

Host configured (eager at startup):

builder.Services.AddFoundryResponses(agent);
builder.Services.AddFoundryToolboxes("my-toolbox", "another-toolbox");

Client selected (per request) — discover via AIProjectClient:

// Discover a toolbox via the Foundry project
var project = new AIProjectClient(endpoint, credential);
ToolboxRecord toolbox = await project.GetAgentToolboxesClient().GetToolboxAsync("calendar-tools");

// Attach as a per-request tool (uses record.Name + record.DefaultVersion)
var response = await agent.RunAsync(
    "Book a meeting with the team next Tuesday.",
    new ChatClientAgentRunOptions
    {
        ChatOptions = new() { Tools = [FoundryAITool.CreateHostedMcpToolbox(toolbox)] }
    });

// Or pin a specific version
ToolboxVersion version = await project.GetAgentToolboxesClient().GetToolboxVersionAsync("calendar-tools", "v2");
var toolWithVersion = FoundryAITool.CreateHostedMcpToolbox(version);

// Or pass the name/version explicitly
var toolByName = FoundryAITool.CreateHostedMcpToolbox("calendar-tools", version: "v2");

Combined — host-configured toolboxes are always injected; client markers additionally lazy-open any toolbox the server hasn't pre-registered.

Environment variables

Variable Required Description
FOUNDRY_AGENT_TOOLSET_ENDPOINT No (absent = healthy, no tools) Foundry Toolsets proxy base URL
FOUNDRY_AGENT_TOOLSET_FEATURES No Feature flags sent via Foundry-Features header
FOUNDRY_AGENT_NAME No MCP client info name (default: hosted-agent)
FOUNDRY_AGENT_VERSION No MCP client info version (default: 1.0.0)

WIP — needs integration testing against a live Foundry Toolsets proxy.

@moonbox3 moonbox3 added the .NET label Apr 16, 2026
@github-actions github-actions bot changed the title feat: Add Foundry Toolbox (MCP) support to hosted agent responses handler .NET: feat: Add Foundry Toolbox (MCP) support to hosted agent responses handler Apr 16, 2026
@rogerbarreto rogerbarreto changed the title .NET: feat: Add Foundry Toolbox (MCP) support to hosted agent responses handler .Net: Add Foundry Toolbox (MCP) support to hosted agent responses handler Apr 16, 2026
@rogerbarreto rogerbarreto changed the title .Net: Add Foundry Toolbox (MCP) support to hosted agent responses handler .Net: [WIP] Add Foundry Toolbox (MCP) support to hosted agent responses handler Apr 16, 2026
@rogerbarreto rogerbarreto changed the title .Net: [WIP] Add Foundry Toolbox (MCP) support to hosted agent responses handler .Net: [WIP] Add Foundry Toolbox Support to Hosted Agents Apr 16, 2026
@rogerbarreto rogerbarreto self-assigned this Apr 16, 2026
@rogerbarreto rogerbarreto moved this to In Progress in Agent Framework Apr 16, 2026
@rogerbarreto rogerbarreto force-pushed the hosted-agents-toolbox-support branch from 01a730b to e665172 Compare April 17, 2026 18:45
Adds support for Foundry Toolsets MCP proxy integration in the hosted agent
response handler. Toolsets connect at startup via IHostedService, gating the
readiness probe per spec §3.1. MCP tools are injected into every request's
ChatOptions and OAuth consent errors (-32006) are intercepted and surfaced as
mcp_approval_request + incomplete SSE events.

New files:
- FoundryToolboxOptions.cs: configuration POCO for toolset names and API version
- FoundryToolboxBearerTokenHandler.cs: DelegatingHandler with Azure Bearer token
  auth, Foundry-Features header injection, and 3x exponential backoff on 429/5xx
- McpConsentContext.cs: AsyncLocal-based per-request consent state shared between
  the tool wrapper and the response handler
- ConsentAwareMcpClientTool.cs: AIFunction wrapper that catches -32006 errors and
  signals consent via shared state and linked CancellationTokenSource
- FoundryToolboxService.cs: IHostedService that creates McpClient per toolset at
  startup and exposes cached tools

Modified files:
- AgentFrameworkResponseHandler.cs: injects toolbox tools into ChatOptions, sets
  up linked CTS consent interception, emits mcp_approval_request on -32006
- ServiceCollectionExtensions.cs: adds AddFoundryToolboxes(params string[]) extension
- Microsoft.Agents.AI.Foundry.csproj: adds ModelContextProtocol and Azure.Identity
  dependencies under NETCoreApp condition

Sample:
- Hosted-Toolbox: minimal hosted agent sample using AddFoundryToolboxes
…lientTool to ConsentAwareMcpClientAIFunction
Introduces HostedMcpToolboxAITool, a marker tool subclassing HostedMcpServerTool that rides the OpenAI Responses 'mcp' wire format to let clients request a specific Foundry toolbox per request.

- New FoundryAITool.CreateHostedMcpToolbox(name, version?) factory.

- FoundryToolboxOptions.StrictMode (default true) rejects unregistered toolboxes; set to false to allow lazy-open on first use.

- FoundryToolboxService.GetToolboxToolsAsync(name, version?) resolves cached or lazy-opened MCP tools.

- AgentFrameworkResponseHandler parses request.Tools for foundry-toolbox://name[?version=v] markers and injects resolved tools per request, merging with pre-registered ones.

- Unit tests for marker parsing and strict-mode resolution.
@rogerbarreto rogerbarreto force-pushed the hosted-agents-toolbox-support branch from e665172 to 215a0ad Compare April 17, 2026 22:22
@rogerbarreto rogerbarreto marked this pull request as ready for review April 17, 2026 22:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

3 participants