forked from admin/VolcanicAgenticCore
- redact /mcp output, and stderr lines as they arrive (log, errors, tail)
- take host servers by name: configuration binding sorts keys anyway
- dispose kills the tree only without an exit code and only if the pid's
start time matches the spawn (no kill of a reused pid)
- idle timer generation guards stale callbacks; catalogue check runs in
the background with a 10 s cap; shutdown stops servers concurrently
- stop resets a failed status; /mcp shows an exited process; ordinal names
- spec: ${workspace} in command, ordering, dispose and /mcp wording
71 lines
3.1 KiB
C#
71 lines
3.1 KiB
C#
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.Logging;
|
|
using Volcanic.AgenticCore.Extensions.Mcp;
|
|
|
|
namespace Volcanic.AgenticCore.Telegram.Tests;
|
|
|
|
public class McpConfigurationTests
|
|
{
|
|
[Fact]
|
|
public void Mcp_section_binds_servers_and_the_playwright_preset()
|
|
{
|
|
var config = new ConfigurationBuilder().AddInMemoryCollection(new Dictionary<string, string?>
|
|
{
|
|
["Mcp:Servers:github:Command"] = "npx",
|
|
["Mcp:Servers:github:Args:0"] = "-y",
|
|
["Mcp:Servers:github:Args:1"] = "@modelcontextprotocol/server-github@2025.9.1",
|
|
["Mcp:Servers:github:Env:GITHUB_TOKEN"] = "${env:GITHUB_TOKEN}",
|
|
["Mcp:Servers:github:ToolPrefix"] = "gh_",
|
|
["Mcp:Servers:github:IdleTimeoutSeconds"] = "0",
|
|
["Mcp:Servers:github:StderrLevel"] = "Information",
|
|
["Mcp:Playwright:Enabled"] = "true",
|
|
["Mcp:Playwright:Headless"] = "false",
|
|
["Mcp:Playwright:ExtraArgs:0"] = "--isolated",
|
|
}).Build();
|
|
|
|
var mcp = config.GetSection(McpOptions.SectionName).Get<McpOptions>()!;
|
|
|
|
var github = mcp.Servers["github"];
|
|
Assert.Equal("npx", github.Command);
|
|
Assert.Equal(["-y", "@modelcontextprotocol/server-github@2025.9.1"], github.Args);
|
|
Assert.Equal("${env:GITHUB_TOKEN}", github.Env["GITHUB_TOKEN"]);
|
|
Assert.Equal("gh_", github.ToolPrefix);
|
|
Assert.Equal(0, github.IdleTimeoutSeconds);
|
|
Assert.Equal(LogLevel.Information, github.StderrLevel);
|
|
Assert.Equal(120, github.CallTimeoutSeconds);
|
|
Assert.True(mcp.Playwright.IsEnabled);
|
|
Assert.False(mcp.Playwright.IsHeadless);
|
|
Assert.Equal(["--isolated"], mcp.Playwright.ExtraArgs!);
|
|
Assert.Empty(mcp.Validate());
|
|
Assert.Equal("MCP: playwright enabled (headed, chromium)", mcp.DescribePlaywright());
|
|
}
|
|
|
|
[Fact]
|
|
public void Bound_servers_arrive_in_name_order_whatever_the_file_order()
|
|
{
|
|
// Microsoft.Extensions.Configuration sorts child keys, so the file order is lost; McpServerSet.Resolve then
|
|
// takes host servers by name and the first by name wins a tool name.
|
|
var config = new ConfigurationBuilder().AddInMemoryCollection(new Dictionary<string, string?>
|
|
{
|
|
["Mcp:Servers:zeta:Command"] = "zeta-mcp",
|
|
["Mcp:Servers:alpha:Command"] = "alpha-mcp",
|
|
}).Build();
|
|
|
|
var mcp = config.GetSection(McpOptions.SectionName).Get<McpOptions>()!;
|
|
|
|
Assert.Equal(["alpha", "zeta"], mcp.Servers.Keys);
|
|
}
|
|
|
|
[Fact]
|
|
public void Configured_values_win_over_PLAYWRIGHT_variables()
|
|
{
|
|
var config = new ConfigurationBuilder().AddInMemoryCollection(new Dictionary<string, string?> { ["Mcp:Playwright:Enabled"] = "false" }).Build();
|
|
var mcp = config.GetSection(McpOptions.SectionName).Get<McpOptions>()!;
|
|
|
|
mcp.ApplyEnvironment(name => name == "PLAYWRIGHT_ENABLED" ? "true" : null);
|
|
|
|
Assert.False(mcp.Playwright.IsEnabled);
|
|
Assert.Equal("MCP: playwright disabled (set PLAYWRIGHT_ENABLED=true)", mcp.DescribePlaywright());
|
|
}
|
|
}
|