Co-authored-by: Tarek Mahmoud Sayed <tarekms@microsoft.com> Co-authored-by: Tarek Mahmoud Sayed <tarekms@ntdev.microsoft.com> Co-authored-by: Tarek Mahmoud Sayed <10833894+tarekgh@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
67 lines
2.5 KiB
C#
67 lines
2.5 KiB
C#
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging;
|
|
using ModelContextProtocol.Client;
|
|
using ModelContextProtocol.Protocol;
|
|
using ModelContextProtocol.Server;
|
|
using System.Text.Json;
|
|
|
|
namespace ModelContextProtocol.Tests.Client;
|
|
|
|
public class McpClientToolRejectionTests : ClientServerTestBase
|
|
{
|
|
private const string InvalidToolName = "InvalidHeaderTool";
|
|
private const string ValidToolName = "ValidTool";
|
|
|
|
public McpClientToolRejectionTests(ITestOutputHelper outputHelper)
|
|
: base(outputHelper)
|
|
{
|
|
}
|
|
|
|
protected override void ConfigureServices(ServiceCollection services, IMcpServerBuilder mcpServerBuilder)
|
|
{
|
|
// Register a valid tool.
|
|
mcpServerBuilder.WithTools([McpServerTool.Create(
|
|
(string input) => $"echo {input}",
|
|
new() { Name = ValidToolName })]);
|
|
|
|
// Register a tool whose InputSchema has an invalid x-mcp-header (colon in header name).
|
|
var invalidTool = McpServerTool.Create(
|
|
(string region) => $"result for {region}",
|
|
new() { Name = InvalidToolName });
|
|
|
|
// Manually inject an invalid x-mcp-header annotation into the schema.
|
|
// The header name "Invalid:Header" contains a colon, which is prohibited.
|
|
var schemaJson = """
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"region": {
|
|
"type": "string",
|
|
"x-mcp-header": "Invalid:Header"
|
|
}
|
|
}
|
|
}
|
|
""";
|
|
invalidTool.ProtocolTool.InputSchema = JsonDocument.Parse(schemaJson).RootElement.Clone();
|
|
|
|
mcpServerBuilder.WithTools([invalidTool]);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ListToolsAsync_ExcludesToolWithInvalidXMcpHeader_AndLogsWarning()
|
|
{
|
|
// Act
|
|
await using var client = await CreateMcpClientForServer();
|
|
var tools = await client.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken);
|
|
|
|
// Assert: the valid tool is returned, the invalid one is excluded.
|
|
Assert.Contains(tools, t => t.Name == ValidToolName);
|
|
Assert.DoesNotContain(tools, t => t.Name == InvalidToolName);
|
|
|
|
// Assert: a warning was logged about the rejected tool.
|
|
Assert.Contains(MockLoggerProvider.LogMessages, log =>
|
|
log.LogLevel == LogLevel.Warning &&
|
|
log.Message.Contains(InvalidToolName) &&
|
|
log.Message.Contains("excluded"));
|
|
}
|
|
}
|