Fix McpClientPrompt/Resource types to use RequestOptions like McpClientTool does (#1370)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
This commit is contained in:
parent
1446cd738c
commit
8c46411f82
3 changed files with 115 additions and 12 deletions
|
|
@ -4,6 +4,7 @@ using ModelContextProtocol.Client;
|
|||
using ModelContextProtocol.Protocol;
|
||||
using ModelContextProtocol.Server;
|
||||
using System.ComponentModel;
|
||||
using System.Text.Json.Nodes;
|
||||
|
||||
namespace ModelContextProtocol.Tests.Client;
|
||||
|
||||
|
|
@ -25,6 +26,10 @@ public class McpClientPromptTests : ClientServerTestBase
|
|||
[McpServerPrompt, Description("Generates a greeting prompt")]
|
||||
public static ChatMessage Greeting([Description("The name to greet")] string name) =>
|
||||
new(ChatRole.User, $"Hello, {name}!");
|
||||
|
||||
[McpServerPrompt, Description("Echoes back the metadata it receives")]
|
||||
public static ChatMessage MetadataEcho(RequestContext<GetPromptRequestParams> context) =>
|
||||
new(ChatRole.User, context.Params?.Meta?.ToJsonString() ?? "{}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -33,7 +38,7 @@ public class McpClientPromptTests : ClientServerTestBase
|
|||
await using McpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var prompts = await client.ListPromptsAsync(cancellationToken: TestContext.Current.CancellationToken);
|
||||
var originalPrompt = prompts.First();
|
||||
var originalPrompt = prompts.First(p => p.Name == "greeting");
|
||||
var promptDefinition = originalPrompt.ProtocolPrompt;
|
||||
|
||||
var newPrompt = new McpClientPrompt(client, promptDefinition);
|
||||
|
|
@ -98,7 +103,7 @@ public class McpClientPromptTests : ClientServerTestBase
|
|||
await using McpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var prompts = await client.ListPromptsAsync(cancellationToken: TestContext.Current.CancellationToken);
|
||||
var originalPrompt = prompts.First();
|
||||
var originalPrompt = prompts.First(p => p.Name == "greeting");
|
||||
var promptDefinition = originalPrompt.ProtocolPrompt;
|
||||
|
||||
var reusedPrompt = new McpClientPrompt(client, promptDefinition);
|
||||
|
|
@ -134,4 +139,32 @@ public class McpClientPromptTests : ClientServerTestBase
|
|||
Assert.NotNull(textContent);
|
||||
Assert.Equal("Hello, Test!", textContent.Text);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetAsync_WithRequestOptions_PassesMetaToServer()
|
||||
{
|
||||
await using McpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var prompts = await client.ListPromptsAsync(cancellationToken: TestContext.Current.CancellationToken);
|
||||
var prompt = prompts.Single(p => p.Name == "metadata_echo");
|
||||
|
||||
RequestOptions requestOptions = new()
|
||||
{
|
||||
Meta = new JsonObject
|
||||
{
|
||||
["traceId"] = "test-trace-123",
|
||||
["customKey"] = "customValue"
|
||||
}
|
||||
};
|
||||
|
||||
var result = await prompt.GetAsync(options: requestOptions, cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.NotNull(result);
|
||||
var message = result.Messages.First();
|
||||
var textContent = Assert.IsType<TextContentBlock>(message.Content);
|
||||
var receivedMetadata = JsonNode.Parse(textContent.Text)?.AsObject();
|
||||
Assert.NotNull(receivedMetadata);
|
||||
Assert.Equal("test-trace-123", receivedMetadata["traceId"]?.GetValue<string>());
|
||||
Assert.Equal("customValue", receivedMetadata["customKey"]?.GetValue<string>());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using ModelContextProtocol.Client;
|
|||
using ModelContextProtocol.Protocol;
|
||||
using ModelContextProtocol.Server;
|
||||
using System.ComponentModel;
|
||||
using System.Text.Json.Nodes;
|
||||
|
||||
namespace ModelContextProtocol.Tests.Client;
|
||||
|
||||
|
|
@ -23,6 +24,10 @@ public class McpClientResourceTemplateConstructorTests : ClientServerTestBase
|
|||
{
|
||||
[McpServerResource, Description("A file template")]
|
||||
public static string FileTemplate([Description("The file path")] string path) => $"Content for {path}";
|
||||
|
||||
[McpServerResource, Description("Echoes back the metadata it receives")]
|
||||
public static string MetadataEcho(RequestContext<ReadResourceRequestParams> context, [Description("An ID")] string id) =>
|
||||
context.Params?.Meta?.ToJsonString() ?? "{}";
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -31,7 +36,7 @@ public class McpClientResourceTemplateConstructorTests : ClientServerTestBase
|
|||
await using McpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var templates = await client.ListResourceTemplatesAsync(cancellationToken: TestContext.Current.CancellationToken);
|
||||
var originalTemplate = templates.First();
|
||||
var originalTemplate = templates.First(t => t.Name == "file_template");
|
||||
var templateDefinition = originalTemplate.ProtocolResourceTemplate;
|
||||
|
||||
var newTemplate = new McpClientResourceTemplate(client, templateDefinition);
|
||||
|
|
@ -69,7 +74,7 @@ public class McpClientResourceTemplateConstructorTests : ClientServerTestBase
|
|||
await using McpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var templates = await client.ListResourceTemplatesAsync(cancellationToken: TestContext.Current.CancellationToken);
|
||||
var originalTemplate = templates.First();
|
||||
var originalTemplate = templates.First(t => t.Name == "file_template");
|
||||
var templateDefinition = originalTemplate.ProtocolResourceTemplate;
|
||||
|
||||
var reusedTemplate = new McpClientResourceTemplate(client, templateDefinition);
|
||||
|
|
@ -100,4 +105,34 @@ public class McpClientResourceTemplateConstructorTests : ClientServerTestBase
|
|||
Assert.Equal("A file template", clientTemplate.Description);
|
||||
Assert.Equal("file:///{path}", clientTemplate.UriTemplate);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadAsync_WithRequestOptions_PassesMetaToServer()
|
||||
{
|
||||
await using McpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var templates = await client.ListResourceTemplatesAsync(cancellationToken: TestContext.Current.CancellationToken);
|
||||
var template = templates.Single(t => t.Name == "metadata_echo");
|
||||
|
||||
RequestOptions requestOptions = new()
|
||||
{
|
||||
Meta = new JsonObject
|
||||
{
|
||||
["traceId"] = "test-trace-123",
|
||||
["customKey"] = "customValue"
|
||||
}
|
||||
};
|
||||
|
||||
var result = await template.ReadAsync(
|
||||
new Dictionary<string, object?> { ["id"] = "test-id" },
|
||||
options: requestOptions,
|
||||
cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.NotNull(result);
|
||||
var content = Assert.IsType<TextResourceContents>(result.Contents.First());
|
||||
var receivedMetadata = JsonNode.Parse(content.Text)?.AsObject();
|
||||
Assert.NotNull(receivedMetadata);
|
||||
Assert.Equal("test-trace-123", receivedMetadata["traceId"]?.GetValue<string>());
|
||||
Assert.Equal("customValue", receivedMetadata["customKey"]?.GetValue<string>());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using ModelContextProtocol.Client;
|
|||
using ModelContextProtocol.Protocol;
|
||||
using ModelContextProtocol.Server;
|
||||
using System.ComponentModel;
|
||||
using System.Text.Json.Nodes;
|
||||
|
||||
namespace ModelContextProtocol.Tests.Client;
|
||||
|
||||
|
|
@ -23,6 +24,10 @@ public class McpClientResourceTests : ClientServerTestBase
|
|||
{
|
||||
[McpServerResource, Description("A sample resource")]
|
||||
public static string Sample() => "Sample content";
|
||||
|
||||
[McpServerResource, Description("Echoes back the metadata it receives")]
|
||||
public static string MetadataEcho(RequestContext<ReadResourceRequestParams> context) =>
|
||||
context.Params?.Meta?.ToJsonString() ?? "{}";
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -31,7 +36,7 @@ public class McpClientResourceTests : ClientServerTestBase
|
|||
await using McpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var resources = await client.ListResourcesAsync(cancellationToken: TestContext.Current.CancellationToken);
|
||||
var originalResource = resources.First();
|
||||
var originalResource = resources.First(r => r.Name == "sample");
|
||||
var resourceDefinition = originalResource.ProtocolResource;
|
||||
|
||||
var newResource = new McpClientResource(client, resourceDefinition);
|
||||
|
|
@ -94,7 +99,7 @@ public class McpClientResourceTests : ClientServerTestBase
|
|||
await using McpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var resources = await client.ListResourcesAsync(cancellationToken: TestContext.Current.CancellationToken);
|
||||
var originalResource = resources.First();
|
||||
var originalResource = resources.First(r => r.Name == "sample");
|
||||
var resourceDefinition = originalResource.ProtocolResource;
|
||||
|
||||
var reusedResource = new McpClientResource(client, resourceDefinition);
|
||||
|
|
@ -125,4 +130,31 @@ public class McpClientResourceTests : ClientServerTestBase
|
|||
Assert.Equal("A sample resource", clientResource.Description);
|
||||
Assert.Equal("file:///sample.txt", clientResource.Uri);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadAsync_WithRequestOptions_PassesMetaToServer()
|
||||
{
|
||||
await using McpClient client = await CreateMcpClientForServer();
|
||||
|
||||
var resources = await client.ListResourcesAsync(cancellationToken: TestContext.Current.CancellationToken);
|
||||
var resource = resources.Single(r => r.Name == "metadata_echo");
|
||||
|
||||
RequestOptions requestOptions = new()
|
||||
{
|
||||
Meta = new JsonObject
|
||||
{
|
||||
["traceId"] = "test-trace-123",
|
||||
["customKey"] = "customValue"
|
||||
}
|
||||
};
|
||||
|
||||
var result = await resource.ReadAsync(options: requestOptions, cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.NotNull(result);
|
||||
var content = Assert.IsType<TextResourceContents>(result.Contents.First());
|
||||
var receivedMetadata = JsonNode.Parse(content.Text)?.AsObject();
|
||||
Assert.NotNull(receivedMetadata);
|
||||
Assert.Equal("test-trace-123", receivedMetadata["traceId"]?.GetValue<string>());
|
||||
Assert.Equal("customValue", receivedMetadata["customKey"]?.GetValue<string>());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue