mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
215a0ad473
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.
70 lines
2.5 KiB
C#
70 lines
2.5 KiB
C#
// Copyright (c) Microsoft. All rights reserved.
|
|
|
|
using System;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Azure.Core;
|
|
using Microsoft.Agents.AI.Foundry.Hosting;
|
|
using Microsoft.Extensions.Options;
|
|
using Moq;
|
|
|
|
namespace Microsoft.Agents.AI.Foundry.UnitTests.Hosting;
|
|
|
|
public class FoundryToolboxServiceTests
|
|
{
|
|
[Fact]
|
|
public async Task GetToolboxToolsAsync_StrictMode_ThrowsForUnknownToolboxAsync()
|
|
{
|
|
var options = new FoundryToolboxOptions { StrictMode = true };
|
|
var service = new FoundryToolboxService(
|
|
Options.Create(options),
|
|
Mock.Of<TokenCredential>());
|
|
|
|
// Act + Assert: no StartAsync so Tools is empty; unknown name in strict mode throws.
|
|
var ex = await Assert.ThrowsAsync<InvalidOperationException>(
|
|
async () => await service.GetToolboxToolsAsync("missing", version: null, CancellationToken.None));
|
|
|
|
Assert.Contains("missing", ex.Message, StringComparison.Ordinal);
|
|
Assert.Contains("StrictMode", ex.Message, StringComparison.Ordinal);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetToolboxToolsAsync_NonStrictMode_RequiresEndpointAsync()
|
|
{
|
|
var options = new FoundryToolboxOptions { StrictMode = false };
|
|
var service = new FoundryToolboxService(
|
|
Options.Create(options),
|
|
Mock.Of<TokenCredential>());
|
|
|
|
// Without calling StartAsync, endpoint is not resolved so lazy-open fails clearly.
|
|
var ex = await Assert.ThrowsAsync<InvalidOperationException>(
|
|
async () => await service.GetToolboxToolsAsync("missing", version: null, CancellationToken.None));
|
|
|
|
Assert.Contains("FOUNDRY_AGENT_TOOLSET_ENDPOINT", ex.Message, StringComparison.Ordinal);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task StartAsync_WithoutEndpoint_LeavesToolsEmptyAsync()
|
|
{
|
|
// Ensure env var is not set (tests may run in any CI environment)
|
|
var saved = Environment.GetEnvironmentVariable("FOUNDRY_AGENT_TOOLSET_ENDPOINT");
|
|
Environment.SetEnvironmentVariable("FOUNDRY_AGENT_TOOLSET_ENDPOINT", null);
|
|
try
|
|
{
|
|
var options = new FoundryToolboxOptions();
|
|
options.ToolboxNames.Add("any");
|
|
var service = new FoundryToolboxService(
|
|
Options.Create(options),
|
|
Mock.Of<TokenCredential>());
|
|
|
|
await service.StartAsync(CancellationToken.None);
|
|
|
|
Assert.Empty(service.Tools);
|
|
}
|
|
finally
|
|
{
|
|
Environment.SetEnvironmentVariable("FOUNDRY_AGENT_TOOLSET_ENDPOINT", saved);
|
|
}
|
|
}
|
|
}
|