Add request options bag to high level requests and include Meta (#970)

Co-authored-by: Stephen Toub <stoub@microsoft.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Mike Kistler 2025-12-04 14:32:12 -08:00 • committed by GitHub
commit c447973972
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 882 additions and 164 deletions

View file

@ -100,7 +100,7 @@ public partial class McpServerBuilderExtensionsPromptsTests : ClientServerTestBa
{
await using McpClient client = await CreateMcpClientForServer();
var prompts = await client.ListPromptsAsync(TestContext.Current.CancellationToken);
var prompts = await client.ListPromptsAsync(null, TestContext.Current.CancellationToken);
Assert.Equal(6, prompts.Count);
var prompt = prompts.First(t => t.Name == "returns_chat_messages");
@ -129,7 +129,7 @@ public partial class McpServerBuilderExtensionsPromptsTests : ClientServerTestBa
{
await using McpClient client = await CreateMcpClientForServer();
var prompts = await client.ListPromptsAsync(TestContext.Current.CancellationToken);
var prompts = await client.ListPromptsAsync(null, TestContext.Current.CancellationToken);
Assert.Equal(6, prompts.Count);
Channel<JsonRpcNotification> listChanged = Channel.CreateUnbounded<JsonRpcNotification>();
@ -150,7 +150,7 @@ public partial class McpServerBuilderExtensionsPromptsTests : ClientServerTestBa
serverPrompts.Add(newPrompt);
await notificationRead;
prompts = await client.ListPromptsAsync(TestContext.Current.CancellationToken);
prompts = await client.ListPromptsAsync(null, TestContext.Current.CancellationToken);
Assert.Equal(7, prompts.Count);
Assert.Contains(prompts, t => t.Name == "NewPrompt");
@ -160,7 +160,7 @@ public partial class McpServerBuilderExtensionsPromptsTests : ClientServerTestBa
await notificationRead;
}
prompts = await client.ListPromptsAsync(TestContext.Current.CancellationToken);
prompts = await client.ListPromptsAsync(null, TestContext.Current.CancellationToken);
Assert.Equal(6, prompts.Count);
Assert.DoesNotContain(prompts, t => t.Name == "NewPrompt");
}

View file

@ -129,7 +129,7 @@ public partial class McpServerBuilderExtensionsResourcesTests : ClientServerTest
Assert.NotNull(client.ServerCapabilities.Resources);
var resources = await client.ListResourcesAsync(TestContext.Current.CancellationToken);
var resources = await client.ListResourcesAsync(null, TestContext.Current.CancellationToken);
Assert.Equal(5, resources.Count);
var resource = resources.First(t => t.Name == "some_neat_direct_resource");
@ -146,7 +146,7 @@ public partial class McpServerBuilderExtensionsResourcesTests : ClientServerTest
{
await using McpClient client = await CreateMcpClientForServer();
var resources = await client.ListResourceTemplatesAsync(TestContext.Current.CancellationToken);
var resources = await client.ListResourceTemplatesAsync(null, TestContext.Current.CancellationToken);
Assert.Equal(3, resources.Count);
var resource = resources.First(t => t.Name == "some_neat_templated_resource");
@ -163,7 +163,7 @@ public partial class McpServerBuilderExtensionsResourcesTests : ClientServerTest
{
await using McpClient client = await CreateMcpClientForServer();
var resources = await client.ListResourcesAsync(TestContext.Current.CancellationToken);
var resources = await client.ListResourcesAsync(null, TestContext.Current.CancellationToken);
Assert.Equal(5, resources.Count);
Channel<JsonRpcNotification> listChanged = Channel.CreateUnbounded<JsonRpcNotification>();
@ -184,7 +184,7 @@ public partial class McpServerBuilderExtensionsResourcesTests : ClientServerTest
serverResources.Add(newResource);
await notificationRead;
resources = await client.ListResourcesAsync(TestContext.Current.CancellationToken);
resources = await client.ListResourcesAsync(null, TestContext.Current.CancellationToken);
Assert.Equal(6, resources.Count);
Assert.Contains(resources, t => t.Name == "NewResource");
@ -194,7 +194,7 @@ public partial class McpServerBuilderExtensionsResourcesTests : ClientServerTest
await notificationRead;
}
resources = await client.ListResourcesAsync(TestContext.Current.CancellationToken);
resources = await client.ListResourcesAsync(null, TestContext.Current.CancellationToken);
Assert.Equal(5, resources.Count);
Assert.DoesNotContain(resources, t => t.Name == "NewResource");
}

View file

@ -12,6 +12,7 @@ using System.Collections.Concurrent;
using System.ComponentModel;
using System.IO.Pipelines;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using System.Threading.Channels;
@ -686,7 +687,11 @@ public partial class McpServerBuilderExtensionsToolsTests : ClientServerTestBase
new CallToolRequestParams
{
Name = progressTool.ProtocolTool.Name,
ProgressToken = new("abc123"),
// Set the progress token in Meta
Meta = new JsonObject
{
["progressToken"] = "abc123",
}
},
cancellationToken: TestContext.Current.CancellationToken);

View file

@ -41,7 +41,7 @@ public class McpServerResourceCapabilityIntegrationTests : ClientServerTestBase
Assert.True(client.ServerCapabilities.Resources.Subscribe, "Server should advertise Subscribe capability when manually set");
// The resources should be exposed and listable
var resources = await client.ListResourcesAsync(TestContext.Current.CancellationToken);
var resources = await client.ListResourcesAsync(null, TestContext.Current.CancellationToken);
Assert.NotEmpty(resources);
Assert.Contains(resources, r => r.Name == "test_resource");
}
@ -56,7 +56,7 @@ public class McpServerResourceCapabilityIntegrationTests : ClientServerTestBase
Assert.NotNull(client.ServerCapabilities.Resources);
// The resources should be exposed and listable
var resources = await client.ListResourcesAsync(TestContext.Current.CancellationToken);
var resources = await client.ListResourcesAsync(null, TestContext.Current.CancellationToken);
Assert.NotEmpty(resources);
}

View file

@ -23,19 +23,19 @@ public sealed class McpServerResourceRoutingTests(ITestOutputHelper testOutputHe
// Regression test for https://github.com/modelcontextprotocol/csharp-sdk/issues/821.
await using McpClient client = await CreateMcpClientForServer();
var nonTemplatedResult = await client.ReadResourceAsync("test://resource/non-templated", TestContext.Current.CancellationToken);
var nonTemplatedResult = await client.ReadResourceAsync("test://resource/non-templated", null, TestContext.Current.CancellationToken);
Assert.Equal("static", ((TextResourceContents)nonTemplatedResult.Contents[0]).Text);
var templatedResult = await client.ReadResourceAsync("test://resource/12345", TestContext.Current.CancellationToken);
var templatedResult = await client.ReadResourceAsync("test://resource/12345", null, TestContext.Current.CancellationToken);
Assert.Equal("template: 12345", ((TextResourceContents)templatedResult.Contents[0]).Text);
var exactTemplatedResult = await client.ReadResourceAsync("test://resource/{id}", TestContext.Current.CancellationToken);
var exactTemplatedResult = await client.ReadResourceAsync("test://resource/{id}", null, TestContext.Current.CancellationToken);
Assert.Equal("template: {id}", ((TextResourceContents)exactTemplatedResult.Contents[0]).Text);
var paramsResult = await client.ReadResourceAsync("test://params?a1=a&a2=b&a3=c", TestContext.Current.CancellationToken);
var paramsResult = await client.ReadResourceAsync("test://params?a1=a&a2=b&a3=c", null, TestContext.Current.CancellationToken);
Assert.Equal("params: a, b, c", ((TextResourceContents)paramsResult.Contents[0]).Text);
var mcpEx = await Assert.ThrowsAsync<McpProtocolException>(async () => await client.ReadResourceAsync("test://params{?a1,a2,a3}", TestContext.Current.CancellationToken));
var mcpEx = await Assert.ThrowsAsync<McpProtocolException>(async () => await client.ReadResourceAsync("test://params{?a1,a2,a3}", null, TestContext.Current.CancellationToken));
Assert.Equal(McpErrorCode.InvalidParams, mcpEx.ErrorCode);
Assert.Equal("Request failed (remote): Unknown resource URI: 'test://params{?a1,a2,a3}'", mcpEx.Message);
}

View file

@ -24,7 +24,7 @@ public partial class McpServerScopedTests : ClientServerTestBase
{
await using McpClient client = await CreateMcpClientForServer();
var tools = await client.ListToolsAsync(McpServerScopedTestsJsonContext.Default.Options, TestContext.Current.CancellationToken);
var tools = await client.ListToolsAsync(new RequestOptions { JsonSerializerOptions = McpServerScopedTestsJsonContext.Default.Options }, TestContext.Current.CancellationToken);
var tool = tools.First(t => t.Name == "echo_complex");
Assert.DoesNotContain("\"complex\"", JsonSerializer.Serialize(tool.JsonSchema, McpJsonUtilities.DefaultOptions));