csharp-sdk/tests/ModelContextProtocol.Tests/Client/McpClientPromptTests.cs
Copilot b90f17bccb
Add public constructors to McpClient types for reusing cached definitions (#938)
* Initial plan

* Add public constructor to McpClientTool for reusing tool definitions

Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>

* Fix McpClientTool constructor per review feedback

Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>

* Add public constructors for McpClientPrompt, McpClientResource, and McpClientResourceTemplate

Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
2025-11-06 13:59:17 -05:00

137 lines
4.9 KiB
C#

using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
using ModelContextProtocol.Client;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
using System.ComponentModel;
namespace ModelContextProtocol.Tests.Client;
public class McpClientPromptTests : ClientServerTestBase
{
public McpClientPromptTests(ITestOutputHelper outputHelper)
: base(outputHelper)
{
}
protected override void ConfigureServices(ServiceCollection services, IMcpServerBuilder mcpServerBuilder)
{
mcpServerBuilder.WithPrompts<GreetingPrompts>();
}
[McpServerPromptType]
private sealed class GreetingPrompts
{
[McpServerPrompt, Description("Generates a greeting prompt")]
public static ChatMessage Greeting([Description("The name to greet")] string name) =>
new(ChatRole.User, $"Hello, {name}!");
}
[Fact]
public async Task Constructor_WithValidParameters_CreatesInstance()
{
await using McpClient client = await CreateMcpClientForServer();
var prompts = await client.ListPromptsAsync(cancellationToken: TestContext.Current.CancellationToken);
var originalPrompt = prompts.First();
var promptDefinition = originalPrompt.ProtocolPrompt;
var newPrompt = new McpClientPrompt(client, promptDefinition);
Assert.NotNull(newPrompt);
Assert.Equal("greeting", newPrompt.Name);
Assert.Equal("Generates a greeting prompt", newPrompt.Description);
Assert.Same(promptDefinition, newPrompt.ProtocolPrompt);
}
[Fact]
public void Constructor_WithNullClient_ThrowsArgumentNullException()
{
var promptDefinition = new Prompt
{
Name = "test",
Description = "Test prompt"
};
Assert.Throws<ArgumentNullException>("client", () => new McpClientPrompt(null!, promptDefinition));
}
[Fact]
public async Task Constructor_WithNullPrompt_ThrowsArgumentNullException()
{
await using McpClient client = await CreateMcpClientForServer();
Assert.Throws<ArgumentNullException>("prompt", () => new McpClientPrompt(client, null!));
}
[Fact]
public async Task ReusePromptDefinition_AcrossDifferentClients_InvokesSuccessfully()
{
Prompt promptDefinition;
{
await using McpClient client1 = await CreateMcpClientForServer();
var prompts = await client1.ListPromptsAsync(cancellationToken: TestContext.Current.CancellationToken);
var greetingPrompt = prompts.First(p => p.Name == "greeting");
promptDefinition = greetingPrompt.ProtocolPrompt;
}
await using McpClient client2 = await CreateMcpClientForServer();
var reusedPrompt = new McpClientPrompt(client2, promptDefinition);
var result = await reusedPrompt.GetAsync(
new Dictionary<string, object?> { ["name"] = "World" },
cancellationToken: TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.NotNull(result.Messages);
var message = result.Messages.First();
Assert.NotNull(message.Content);
var textContent = message.Content as TextContentBlock;
Assert.NotNull(textContent);
Assert.Equal("Hello, World!", textContent.Text);
}
[Fact]
public async Task ReusePromptDefinition_PreservesPromptMetadata()
{
await using McpClient client = await CreateMcpClientForServer();
var prompts = await client.ListPromptsAsync(cancellationToken: TestContext.Current.CancellationToken);
var originalPrompt = prompts.First();
var promptDefinition = originalPrompt.ProtocolPrompt;
var reusedPrompt = new McpClientPrompt(client, promptDefinition);
Assert.Equal(originalPrompt.Name, reusedPrompt.Name);
Assert.Equal(originalPrompt.Description, reusedPrompt.Description);
Assert.Equal(originalPrompt.ProtocolPrompt.Name, reusedPrompt.ProtocolPrompt.Name);
Assert.Equal(originalPrompt.ProtocolPrompt.Description, reusedPrompt.ProtocolPrompt.Description);
}
[Fact]
public async Task ManuallyConstructedPrompt_CanBeInvoked()
{
await using McpClient client = await CreateMcpClientForServer();
var manualPrompt = new Prompt
{
Name = "greeting",
Description = "Generates a greeting prompt"
};
var clientPrompt = new McpClientPrompt(client, manualPrompt);
var result = await clientPrompt.GetAsync(
new Dictionary<string, object?> { ["name"] = "Test" },
cancellationToken: TestContext.Current.CancellationToken);
Assert.NotNull(result);
Assert.NotNull(result.Messages);
var message = result.Messages.First();
Assert.NotNull(message.Content);
var textContent = message.Content as TextContentBlock;
Assert.NotNull(textContent);
Assert.Equal("Hello, Test!", textContent.Text);
}
}