McpTestExtensions.cs 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. using System.Text.Json;
  2. using System.Text.Json.Serialization;
  3. using ModelContextProtocol.Client;
  4. using ModelContextProtocol.Protocol;
  5. namespace Tests.Mcp;
  6. internal static class McpTestExtensions {
  7. /// <summary>Mirrors the server's tool serialization: web defaults plus enums as strings.</summary>
  8. public static readonly JsonSerializerOptions Json = new(JsonSerializerDefaults.Web) {
  9. Converters = { new JsonStringEnumConverter() }
  10. };
  11. /// <summary>Calls a tool that must succeed and deserializes its structured content.</summary>
  12. public static async Task<T> CallOkAsync<T>(
  13. this McpClient client,
  14. string tool,
  15. Dictionary<string, object?>? args = null) {
  16. CallToolResult result = await client.CallToolAsync(tool, args);
  17. AssertOk(tool, result);
  18. Assert.NotNull(result.StructuredContent);
  19. return result.StructuredContent.Value.Deserialize<T>(Json)
  20. ?? throw new InvalidOperationException($"'{tool}' returned unusable structured content.");
  21. }
  22. /// <summary>Calls a tool that must succeed and returns its text content.</summary>
  23. public static async Task<string> CallTextAsync(
  24. this McpClient client,
  25. string tool,
  26. Dictionary<string, object?>? args = null) {
  27. CallToolResult result = await client.CallToolAsync(tool, args);
  28. AssertOk(tool, result);
  29. return Text(result);
  30. }
  31. /// <summary>Calls a tool that must fail and returns the error text the agent would see.</summary>
  32. public static async Task<string> CallErrorAsync(
  33. this McpClient client,
  34. string tool,
  35. Dictionary<string, object?>? args = null) {
  36. CallToolResult result = await client.CallToolAsync(tool, args);
  37. Assert.True(result.IsError == true, $"Expected '{tool}' to fail, but it succeeded: {Text(result)}");
  38. return Text(result);
  39. }
  40. public static string Text(CallToolResult result) =>
  41. string.Join(Environment.NewLine, result.Content.OfType<TextContentBlock>().Select(t => t.Text));
  42. private static void AssertOk(string tool, CallToolResult result) =>
  43. Assert.False(result.IsError == true, $"'{tool}' failed: {Text(result)}");
  44. }