Change default name casing of McpServerXx.Create tools/prompts/resources (#568)
This commit is contained in:
parent
4e290f8de9
commit
4411f1ce5e
10 changed files with 104 additions and 49 deletions
|
|
@ -68,7 +68,7 @@ internal sealed class AIFunctionMcpServerPrompt : McpServerPrompt
|
|||
MethodInfo method, McpServerPromptCreateOptions? options) =>
|
||||
new()
|
||||
{
|
||||
Name = options?.Name ?? method.GetCustomAttribute<McpServerPromptAttribute>()?.Name,
|
||||
Name = options?.Name ?? method.GetCustomAttribute<McpServerPromptAttribute>()?.Name ?? AIFunctionMcpServerTool.DeriveName(method),
|
||||
Description = options?.Description,
|
||||
MarshalResult = static (result, _, cancellationToken) => new ValueTask<object?>(result),
|
||||
SerializerOptions = options?.SerializerOptions ?? McpJsonUtilities.DefaultOptions,
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ internal sealed class AIFunctionMcpServerResource : McpServerResource
|
|||
MethodInfo method, McpServerResourceCreateOptions? options) =>
|
||||
new()
|
||||
{
|
||||
Name = options?.Name ?? method.GetCustomAttribute<McpServerResourceAttribute>()?.Name,
|
||||
Name = options?.Name ?? method.GetCustomAttribute<McpServerResourceAttribute>()?.Name ?? AIFunctionMcpServerTool.DeriveName(method),
|
||||
Description = options?.Description,
|
||||
MarshalResult = static (result, _, cancellationToken) => new ValueTask<object?>(result),
|
||||
SerializerOptions = options?.SerializerOptions ?? McpJsonUtilities.DefaultOptions,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using System.Diagnostics;
|
|||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace ModelContextProtocol.Server;
|
||||
|
||||
|
|
@ -74,7 +75,7 @@ internal sealed partial class AIFunctionMcpServerTool : McpServerTool
|
|||
MethodInfo method, McpServerToolCreateOptions? options) =>
|
||||
new()
|
||||
{
|
||||
Name = options?.Name ?? method.GetCustomAttribute<McpServerToolAttribute>()?.Name,
|
||||
Name = options?.Name ?? method.GetCustomAttribute<McpServerToolAttribute>()?.Name ?? DeriveName(method),
|
||||
Description = options?.Description,
|
||||
MarshalResult = static (result, _, cancellationToken) => new ValueTask<object?>(result),
|
||||
SerializerOptions = options?.SerializerOptions ?? McpJsonUtilities.DefaultOptions,
|
||||
|
|
@ -293,6 +294,63 @@ internal sealed partial class AIFunctionMcpServerTool : McpServerTool
|
|||
};
|
||||
}
|
||||
|
||||
/// <summary>Creates a name to use based on the supplied method and naming policy.</summary>
|
||||
internal static string DeriveName(MethodInfo method, JsonNamingPolicy? policy = null)
|
||||
{
|
||||
string name = method.Name;
|
||||
|
||||
// Remove any "Async" suffix if the method is an async method and if the method name isn't just "Async".
|
||||
const string AsyncSuffix = "Async";
|
||||
if (IsAsyncMethod(method) &&
|
||||
name.EndsWith(AsyncSuffix, StringComparison.Ordinal) &&
|
||||
name.Length > AsyncSuffix.Length)
|
||||
{
|
||||
name = name.Substring(0, name.Length - AsyncSuffix.Length);
|
||||
}
|
||||
|
||||
// Replace anything other than ASCII letters or digits with underscores, trim off any leading or trailing underscores.
|
||||
name = NonAsciiLetterDigitsRegex().Replace(name, "_").Trim('_');
|
||||
|
||||
// If after all our transformations the name is empty, just use the original method name.
|
||||
if (name.Length == 0)
|
||||
{
|
||||
name = method.Name;
|
||||
}
|
||||
|
||||
// Case the name based on the provided naming policy.
|
||||
return (policy ?? JsonNamingPolicy.SnakeCaseLower).ConvertName(name) ?? name;
|
||||
|
||||
static bool IsAsyncMethod(MethodInfo method)
|
||||
{
|
||||
Type t = method.ReturnType;
|
||||
|
||||
if (t == typeof(Task) || t == typeof(ValueTask))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (t.IsGenericType)
|
||||
{
|
||||
t = t.GetGenericTypeDefinition();
|
||||
if (t == typeof(Task<>) || t == typeof(ValueTask<>) || t == typeof(IAsyncEnumerable<>))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Regex that flags runs of characters other than ASCII digits or letters.</summary>
|
||||
#if NET
|
||||
[GeneratedRegex("[^0-9A-Za-z]+")]
|
||||
private static partial Regex NonAsciiLetterDigitsRegex();
|
||||
#else
|
||||
private static Regex NonAsciiLetterDigitsRegex() => _nonAsciiLetterDigits;
|
||||
private static readonly Regex _nonAsciiLetterDigits = new("[^0-9A-Za-z]+", RegexOptions.Compiled);
|
||||
#endif
|
||||
|
||||
private static JsonElement? CreateOutputSchema(AIFunction function, McpServerToolCreateOptions? toolCreateOptions, out bool structuredOutputRequiresWrapping)
|
||||
{
|
||||
structuredOutputRequiresWrapping = false;
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ public abstract class MapMcpTests(ITestOutputHelper testOutputHelper) : KestrelI
|
|||
await using var mcpClient = await ConnectAsync();
|
||||
|
||||
var response = await mcpClient.CallToolAsync(
|
||||
"EchoWithUserName",
|
||||
"echo_with_user_name",
|
||||
new Dictionary<string, object?>() { ["message"] = "Hello world!" },
|
||||
cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
|
|
|
|||
|
|
@ -149,11 +149,11 @@ public partial class SseIntegrationTests(ITestOutputHelper outputHelper) : Kestr
|
|||
var tools = await mcpClient.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal(2, tools.Count);
|
||||
Assert.Contains(tools, tools => tools.Name == "Echo");
|
||||
Assert.Contains(tools, tools => tools.Name == "echo");
|
||||
Assert.Contains(tools, tools => tools.Name == "sampleLLM");
|
||||
|
||||
var echoResponse = await mcpClient.CallToolAsync(
|
||||
"Echo",
|
||||
"echo",
|
||||
new Dictionary<string, object?>
|
||||
{
|
||||
["message"] = "from client!"
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ public partial class McpServerBuilderExtensionsPromptsTests : ClientServerTestBa
|
|||
var prompts = await client.ListPromptsAsync(TestContext.Current.CancellationToken);
|
||||
Assert.Equal(6, prompts.Count);
|
||||
|
||||
var prompt = prompts.First(t => t.Name == nameof(SimplePrompts.ReturnsChatMessages));
|
||||
var prompt = prompts.First(t => t.Name == "returns_chat_messages");
|
||||
Assert.Equal("Returns chat messages", prompt.Description);
|
||||
|
||||
var result = await prompt.GetAsync(new Dictionary<string, object?>() { ["message"] = "hello" }, cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
|
@ -171,7 +171,7 @@ public partial class McpServerBuilderExtensionsPromptsTests : ClientServerTestBa
|
|||
Assert.NotNull(prompts);
|
||||
Assert.NotEmpty(prompts);
|
||||
|
||||
McpClientPrompt prompt = prompts.First(t => t.Name == nameof(SimplePrompts.ReturnsString));
|
||||
McpClientPrompt prompt = prompts.First(t => t.Name == "returns_string");
|
||||
|
||||
Assert.Equal("This is a title", prompt.Title);
|
||||
}
|
||||
|
|
@ -204,7 +204,7 @@ public partial class McpServerBuilderExtensionsPromptsTests : ClientServerTestBa
|
|||
await using IMcpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var e = await Assert.ThrowsAsync<McpException>(async () => await client.GetPromptAsync(
|
||||
nameof(SimplePrompts.ReturnsChatMessages),
|
||||
"returns_chat_messages",
|
||||
cancellationToken: TestContext.Current.CancellationToken));
|
||||
|
||||
Assert.Equal(McpErrorCode.InternalError, e.ErrorCode);
|
||||
|
|
@ -242,7 +242,7 @@ public partial class McpServerBuilderExtensionsPromptsTests : ClientServerTestBa
|
|||
sc.AddMcpServer().WithPromptsFromAssembly();
|
||||
IServiceProvider services = sc.BuildServiceProvider();
|
||||
|
||||
Assert.Contains(services.GetServices<McpServerPrompt>(), t => t.ProtocolPrompt.Name == nameof(SimplePrompts.ReturnsChatMessages));
|
||||
Assert.Contains(services.GetServices<McpServerPrompt>(), t => t.ProtocolPrompt.Name == "returns_chat_messages");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -255,10 +255,10 @@ public partial class McpServerBuilderExtensionsPromptsTests : ClientServerTestBa
|
|||
.WithPrompts([McpServerPrompt.Create(() => "42", new() { Name = "Returns42" })]);
|
||||
IServiceProvider services = sc.BuildServiceProvider();
|
||||
|
||||
Assert.Contains(services.GetServices<McpServerPrompt>(), t => t.ProtocolPrompt.Name == nameof(SimplePrompts.ReturnsChatMessages));
|
||||
Assert.Contains(services.GetServices<McpServerPrompt>(), t => t.ProtocolPrompt.Name == nameof(SimplePrompts.ThrowsException));
|
||||
Assert.Contains(services.GetServices<McpServerPrompt>(), t => t.ProtocolPrompt.Name == nameof(SimplePrompts.ReturnsString));
|
||||
Assert.Contains(services.GetServices<McpServerPrompt>(), t => t.ProtocolPrompt.Name == nameof(MorePrompts.AnotherPrompt));
|
||||
Assert.Contains(services.GetServices<McpServerPrompt>(), t => t.ProtocolPrompt.Name == "returns_chat_messages");
|
||||
Assert.Contains(services.GetServices<McpServerPrompt>(), t => t.ProtocolPrompt.Name == "throws_exception");
|
||||
Assert.Contains(services.GetServices<McpServerPrompt>(), t => t.ProtocolPrompt.Name == "returns_string");
|
||||
Assert.Contains(services.GetServices<McpServerPrompt>(), t => t.ProtocolPrompt.Name == "another_prompt");
|
||||
Assert.Contains(services.GetServices<McpServerPrompt>(), t => t.ProtocolPrompt.Name == "Returns42");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ public partial class McpServerBuilderExtensionsResourcesTests : ClientServerTest
|
|||
var resources = await client.ListResourcesAsync(TestContext.Current.CancellationToken);
|
||||
Assert.Equal(5, resources.Count);
|
||||
|
||||
var resource = resources.First(t => t.Name == nameof(SimpleResources.SomeNeatDirectResource));
|
||||
var resource = resources.First(t => t.Name == "some_neat_direct_resource");
|
||||
Assert.Equal("Some neat direct resource", resource.Description);
|
||||
|
||||
var result = await resource.ReadAsync(cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
|
@ -146,7 +146,7 @@ public partial class McpServerBuilderExtensionsResourcesTests : ClientServerTest
|
|||
var resources = await client.ListResourceTemplatesAsync(TestContext.Current.CancellationToken);
|
||||
Assert.Equal(3, resources.Count);
|
||||
|
||||
var resource = resources.First(t => t.Name == nameof(SimpleResources.SomeNeatTemplatedResource));
|
||||
var resource = resources.First(t => t.Name == "some_neat_templated_resource");
|
||||
Assert.Equal("Some neat resource with parameters", resource.Description);
|
||||
|
||||
var result = await resource.ReadAsync(new Dictionary<string, object?>() { ["name"] = "hello" }, cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
|
@ -204,13 +204,13 @@ public partial class McpServerBuilderExtensionsResourcesTests : ClientServerTest
|
|||
var resources = await client.ListResourcesAsync(cancellationToken: TestContext.Current.CancellationToken);
|
||||
Assert.NotNull(resources);
|
||||
Assert.NotEmpty(resources);
|
||||
McpClientResource resource = resources.First(t => t.Name == nameof(SimpleResources.SomeNeatDirectResource));
|
||||
McpClientResource resource = resources.First(t => t.Name == "some_neat_direct_resource");
|
||||
Assert.Equal("This is a title", resource.Title);
|
||||
|
||||
var resourceTemplates = await client.ListResourceTemplatesAsync(cancellationToken: TestContext.Current.CancellationToken);
|
||||
Assert.NotNull(resourceTemplates);
|
||||
Assert.NotEmpty(resourceTemplates);
|
||||
McpClientResourceTemplate resourceTemplate = resourceTemplates.First(t => t.Name == nameof(SimpleResources.SomeNeatTemplatedResource));
|
||||
McpClientResourceTemplate resourceTemplate = resourceTemplates.First(t => t.Name == "some_neat_templated_resource");
|
||||
Assert.Equal("This is another title", resourceTemplate.Title);
|
||||
}
|
||||
|
||||
|
|
@ -268,8 +268,8 @@ public partial class McpServerBuilderExtensionsResourcesTests : ClientServerTest
|
|||
sc.AddMcpServer().WithResourcesFromAssembly();
|
||||
IServiceProvider services = sc.BuildServiceProvider();
|
||||
|
||||
Assert.Contains(services.GetServices<McpServerResource>(), t => t.ProtocolResource?.Uri == $"resource://mcp/{nameof(SimpleResources.SomeNeatDirectResource)}");
|
||||
Assert.Contains(services.GetServices<McpServerResource>(), t => t.ProtocolResourceTemplate?.UriTemplate == $"resource://mcp/{nameof(SimpleResources.SomeNeatTemplatedResource)}{{?name}}");
|
||||
Assert.Contains(services.GetServices<McpServerResource>(), t => t.ProtocolResource?.Uri == $"resource://mcp/some_neat_direct_resource");
|
||||
Assert.Contains(services.GetServices<McpServerResource>(), t => t.ProtocolResourceTemplate?.UriTemplate == $"resource://mcp/some_neat_templated_resource{{?name}}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -282,9 +282,9 @@ public partial class McpServerBuilderExtensionsResourcesTests : ClientServerTest
|
|||
.WithResources([McpServerResource.Create(() => "42", new() { UriTemplate = "myResources:///returns42/{something}" })]);
|
||||
IServiceProvider services = sc.BuildServiceProvider();
|
||||
|
||||
Assert.Contains(services.GetServices<McpServerResource>(), t => t.ProtocolResource?.Uri == $"resource://mcp/{nameof(SimpleResources.SomeNeatDirectResource)}");
|
||||
Assert.Contains(services.GetServices<McpServerResource>(), t => t.ProtocolResourceTemplate?.UriTemplate == $"resource://mcp/{nameof(SimpleResources.SomeNeatTemplatedResource)}{{?name}}");
|
||||
Assert.Contains(services.GetServices<McpServerResource>(), t => t.ProtocolResourceTemplate?.UriTemplate == $"resource://mcp/{nameof(MoreResources.AnotherNeatDirectResource)}");
|
||||
Assert.Contains(services.GetServices<McpServerResource>(), t => t.ProtocolResource?.Uri == $"resource://mcp/some_neat_direct_resource");
|
||||
Assert.Contains(services.GetServices<McpServerResource>(), t => t.ProtocolResourceTemplate?.UriTemplate == $"resource://mcp/some_neat_templated_resource{{?name}}");
|
||||
Assert.Contains(services.GetServices<McpServerResource>(), t => t.ProtocolResourceTemplate?.UriTemplate == $"resource://mcp/another_neat_direct_resource");
|
||||
Assert.Contains(services.GetServices<McpServerResource>(), t => t.ProtocolResourceTemplate.UriTemplate == "myResources:///returns42/{something}");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -126,8 +126,7 @@ public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
var tools = await client.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken);
|
||||
Assert.Equal(16, tools.Count);
|
||||
|
||||
McpClientTool echoTool = tools.First(t => t.Name == "Echo");
|
||||
Assert.Equal("Echo", echoTool.Name);
|
||||
McpClientTool echoTool = tools.First(t => t.Name == "echo");
|
||||
Assert.Equal("Echoes the input back to the client.", echoTool.Description);
|
||||
Assert.Equal("object", echoTool.JsonSchema.GetProperty("type").GetString());
|
||||
Assert.Equal(JsonValueKind.Object, echoTool.JsonSchema.GetProperty("properties").GetProperty("message").ValueKind);
|
||||
|
|
@ -165,8 +164,7 @@ public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
var tools = await client.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken);
|
||||
Assert.Equal(16, tools.Count);
|
||||
|
||||
McpClientTool echoTool = tools.First(t => t.Name == "Echo");
|
||||
Assert.Equal("Echo", echoTool.Name);
|
||||
McpClientTool echoTool = tools.First(t => t.Name == "echo");
|
||||
Assert.Equal("Echoes the input back to the client.", echoTool.Description);
|
||||
Assert.Equal("object", echoTool.JsonSchema.GetProperty("type").GetString());
|
||||
Assert.Equal(JsonValueKind.Object, echoTool.JsonSchema.GetProperty("properties").GetProperty("message").ValueKind);
|
||||
|
|
@ -231,7 +229,7 @@ public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
await using IMcpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var result = await client.CallToolAsync(
|
||||
"Echo",
|
||||
"echo",
|
||||
new Dictionary<string, object?>() { ["message"] = "Peter" },
|
||||
cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
|
|
@ -250,7 +248,7 @@ public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
await using IMcpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var result = await client.CallToolAsync(
|
||||
"EchoArray",
|
||||
"echo_array",
|
||||
new Dictionary<string, object?>() { ["message"] = "Peter" },
|
||||
cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
|
|
@ -274,7 +272,7 @@ public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
await using IMcpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var result = await client.CallToolAsync(
|
||||
"ReturnNull",
|
||||
"return_null",
|
||||
cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.NotNull(result);
|
||||
|
|
@ -288,7 +286,7 @@ public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
await using IMcpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var result = await client.CallToolAsync(
|
||||
"ReturnJson",
|
||||
"return_json",
|
||||
cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.NotNull(result);
|
||||
|
|
@ -305,7 +303,7 @@ public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
await using IMcpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var result = await client.CallToolAsync(
|
||||
"ReturnInteger",
|
||||
"return_integer",
|
||||
cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.NotNull(result.Content);
|
||||
|
|
@ -320,7 +318,7 @@ public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
await using IMcpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var result = await client.CallToolAsync(
|
||||
"EchoComplex",
|
||||
"echo_complex",
|
||||
new Dictionary<string, object?>() { ["complex"] = JsonDocument.Parse("""{"Name": "Peter", "Age": 25}""").RootElement },
|
||||
cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
|
|
@ -340,7 +338,7 @@ public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
var result = await client.CallToolAsync(
|
||||
nameof(EchoTool.GetCtorParameter),
|
||||
"get_ctor_parameter",
|
||||
cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.NotNull(result);
|
||||
|
|
@ -366,7 +364,7 @@ public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
await using IMcpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var result = await client.CallToolAsync(
|
||||
"ThrowException",
|
||||
"throw_exception",
|
||||
cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.True(result.IsError);
|
||||
|
|
@ -393,7 +391,7 @@ public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
await using IMcpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var result = await client.CallToolAsync(
|
||||
"Echo",
|
||||
"echo",
|
||||
cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.True(result.IsError);
|
||||
|
|
@ -436,7 +434,7 @@ public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
sc.AddMcpServer().WithToolsFromAssembly();
|
||||
IServiceProvider services = sc.BuildServiceProvider();
|
||||
|
||||
Assert.Contains(services.GetServices<McpServerTool>(), t => t.ProtocolTool.Name == "Echo");
|
||||
Assert.Contains(services.GetServices<McpServerTool>(), t => t.ProtocolTool.Name == "echo");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -452,7 +450,7 @@ public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
sc.AddMcpServer().WithTools([typeof(EchoTool)], BuilderToolsJsonContext.Default.Options);
|
||||
IServiceProvider services = sc.BuildServiceProvider();
|
||||
|
||||
McpServerTool tool = services.GetServices<McpServerTool>().First(t => t.ProtocolTool.Name == "EchoComplex");
|
||||
McpServerTool tool = services.GetServices<McpServerTool>().First(t => t.ProtocolTool.Name == "echo_complex");
|
||||
if (parameterInServices)
|
||||
{
|
||||
Assert.DoesNotContain("\"complex\"", JsonSerializer.Serialize(tool.ProtocolTool.InputSchema, AIJsonUtilities.DefaultOptions));
|
||||
|
|
@ -495,7 +493,7 @@ public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
sc.AddMcpServer().WithToolsFromAssembly();
|
||||
IServiceProvider services = sc.BuildServiceProvider();
|
||||
|
||||
McpServerTool tool = services.GetServices<McpServerTool>().First(t => t.ProtocolTool.Name == "EchoComplex");
|
||||
McpServerTool tool = services.GetServices<McpServerTool>().First(t => t.ProtocolTool.Name == "echo_complex");
|
||||
if (lifetime is not null)
|
||||
{
|
||||
Assert.DoesNotContain("\"complex\"", JsonSerializer.Serialize(tool.ProtocolTool.InputSchema, AIJsonUtilities.DefaultOptions));
|
||||
|
|
@ -516,8 +514,7 @@ public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
Assert.NotNull(tools);
|
||||
Assert.NotEmpty(tools);
|
||||
|
||||
var tool = tools.First(t => t.Name == "TestTool");
|
||||
Assert.Equal("TestTool", tool.Name);
|
||||
var tool = tools.First(t => t.Name == "test_tool");
|
||||
Assert.Empty(tool.Description!);
|
||||
Assert.Equal("object", tool.JsonSchema.GetProperty("type").GetString());
|
||||
|
||||
|
|
@ -543,9 +540,9 @@ public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
|
||||
Assert.Contains(services.GetServices<McpServerTool>(), t => t.ProtocolTool.Name == "double_echo");
|
||||
Assert.Contains(services.GetServices<McpServerTool>(), t => t.ProtocolTool.Name == "DifferentName");
|
||||
Assert.Contains(services.GetServices<McpServerTool>(), t => t.ProtocolTool.Name == "MethodB");
|
||||
Assert.Contains(services.GetServices<McpServerTool>(), t => t.ProtocolTool.Name == "MethodC");
|
||||
Assert.Contains(services.GetServices<McpServerTool>(), t => t.ProtocolTool.Name == "MethodD");
|
||||
Assert.Contains(services.GetServices<McpServerTool>(), t => t.ProtocolTool.Name == "method_b");
|
||||
Assert.Contains(services.GetServices<McpServerTool>(), t => t.ProtocolTool.Name == "method_c");
|
||||
Assert.Contains(services.GetServices<McpServerTool>(), t => t.ProtocolTool.Name == "method_d");
|
||||
Assert.Contains(services.GetServices<McpServerTool>(), t => t.ProtocolTool.Name == "Returns42");
|
||||
}
|
||||
|
||||
|
|
@ -591,7 +588,7 @@ public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
Assert.NotNull(tools);
|
||||
Assert.NotEmpty(tools);
|
||||
|
||||
McpClientTool tool = tools.First(t => t.Name == nameof(EchoTool.EchoComplex));
|
||||
McpClientTool tool = tools.First(t => t.Name == "echo_complex");
|
||||
|
||||
Assert.Equal("This is a title", tool.Title);
|
||||
Assert.Equal("This is a title", tool.ProtocolTool.Title);
|
||||
|
|
@ -607,7 +604,7 @@ public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
Assert.NotNull(tools);
|
||||
Assert.NotEmpty(tools);
|
||||
|
||||
McpClientTool progressTool = tools.First(t => t.Name == nameof(EchoTool.SendsProgressNotifications));
|
||||
McpClientTool progressTool = tools.First(t => t.Name == "sends_progress_notifications");
|
||||
|
||||
TaskCompletionSource tcs = new(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
int remainingNotifications = 10;
|
||||
|
|
@ -660,7 +657,7 @@ public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
|
|||
var tools = await client.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken);
|
||||
Assert.NotNull(tools);
|
||||
Assert.NotEmpty(tools);
|
||||
McpClientTool cancelableTool = tools.First(t => t.Name == nameof(EchoTool.InfiniteCancelableOperation));
|
||||
McpClientTool cancelableTool = tools.First(t => t.Name == "infinite_cancelable_operation");
|
||||
|
||||
var requestId = new RequestId(Guid.NewGuid().ToString());
|
||||
var invokeTask = client.SendRequestAsync<CallToolRequestParams, CallToolResult>(
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ public partial class McpServerScopedTests : ClientServerTestBase
|
|||
await using IMcpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var tools = await client.ListToolsAsync(McpServerScopedTestsJsonContext.Default.Options, TestContext.Current.CancellationToken);
|
||||
var tool = tools.First(t => t.Name == nameof(EchoTool.EchoComplex));
|
||||
var tool = tools.First(t => t.Name == "echo_complex");
|
||||
Assert.DoesNotContain("\"complex\"", JsonSerializer.Serialize(tool.JsonSchema, McpJsonUtilities.DefaultOptions));
|
||||
|
||||
int startingConstructed = ComplexObject.Constructed;
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ public class CancellationTests : ClientServerTestBase
|
|||
await using var client = await CreateMcpClientForServer();
|
||||
|
||||
var tools = await client.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken);
|
||||
var waitTool = tools.First(t => t.Name == nameof(WaitForCancellation));
|
||||
var waitTool = tools.First(t => t.Name == "wait_for_cancellation");
|
||||
|
||||
CancellationTokenSource cts = new();
|
||||
var waitTask = waitTool.InvokeAsync(cancellationToken: cts.Token);
|
||||
|
|
|
|||
Loading…
Reference in a new issue