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(); } [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("client", () => new McpClientPrompt(null!, promptDefinition)); } [Fact] public async Task Constructor_WithNullPrompt_ThrowsArgumentNullException() { await using McpClient client = await CreateMcpClientForServer(); Assert.Throws("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 { ["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 { ["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); } }