|
1 | 1 | using System.Net; |
2 | 2 | using System.Net.Sockets; |
3 | | -using System.Text; |
| 3 | +using System.Text.Json; |
4 | 4 | using System.Web; |
5 | 5 | using Microsoft.Extensions.Logging; |
6 | 6 | using ModelContextProtocol.Client; |
| 7 | +using ModelContextProtocol.Protocol; |
7 | 8 |
|
8 | 9 | // This program expects the following command-line arguments: |
9 | 10 | // 1. The client conformance test scenario to run (e.g., "tools_call") |
|
18 | 19 | var scenario = args[0]; |
19 | 20 | var endpoint = args[1]; |
20 | 21 |
|
21 | | -McpClientOptions options = new() |
22 | | -{ |
23 | | - ClientInfo = new() |
24 | | - { |
25 | | - Name = "ConformanceClient", |
26 | | - Version = "1.0.0" |
27 | | - } |
28 | | -}; |
29 | | - |
30 | 22 | var consoleLoggerFactory = LoggerFactory.Create(builder => |
31 | 23 | { |
32 | 24 | builder.AddConsole(); |
|
67 | 59 | } |
68 | 60 | }, loggerFactory: consoleLoggerFactory); |
69 | 61 |
|
| 62 | +// Wrapper delegate pattern: allows setting elicitation handler after client creation |
| 63 | +// This allows the actual handler to be set dynamically based on scenario |
| 64 | +Func<ElicitRequestParams?, CancellationToken, ValueTask<ElicitResult>>? elicitationHandler = null; |
| 65 | + |
| 66 | +McpClientOptions options = new() |
| 67 | +{ |
| 68 | + ClientInfo = new() |
| 69 | + { |
| 70 | + Name = "ConformanceClient", |
| 71 | + Version = "1.0.0" |
| 72 | + }, |
| 73 | + Handlers = new() |
| 74 | + { |
| 75 | + ElicitationHandler = (request, cancellationToken) => |
| 76 | + { |
| 77 | + if (elicitationHandler is not null) |
| 78 | + { |
| 79 | + return elicitationHandler(request, cancellationToken); |
| 80 | + } |
| 81 | + Console.WriteLine("No elicitation handler set, rejecting by default"); |
| 82 | + return ValueTask.FromResult(new ElicitResult()); // default - reject |
| 83 | + } |
| 84 | + } |
| 85 | +}; |
| 86 | + |
70 | 87 | await using var mcpClient = await McpClient.CreateAsync(clientTransport, options, loggerFactory: consoleLoggerFactory); |
71 | 88 |
|
72 | 89 | bool success = true; |
|
105 | 122 | success &= !(result.IsError == true); |
106 | 123 | break; |
107 | 124 | } |
| 125 | + case "elicitation-sep1034-client-defaults": |
| 126 | + { |
| 127 | + // In this test scenario, an elicitation request will be made that includes default values in the schema. |
| 128 | + // The client should apply these defaults to demonstrate that it received and processed them correctly. |
| 129 | + |
| 130 | + // Set the elicitation handler dynamically for this scenario |
| 131 | + elicitationHandler = (request, cancellationToken) => |
| 132 | + { |
| 133 | + Console.WriteLine($"Received elicitation request: {request?.Message}"); |
| 134 | + |
| 135 | + // Apply default values from the schema |
| 136 | + var content = new Dictionary<string, JsonElement>(); |
| 137 | + |
| 138 | + if (request?.RequestedSchema?.Properties is not null) |
| 139 | + { |
| 140 | + foreach (var (key, schema) in request.RequestedSchema.Properties) |
| 141 | + { |
| 142 | + switch (schema) |
| 143 | + { |
| 144 | + case ElicitRequestParams.StringSchema stringSchema when stringSchema.Default is not null: |
| 145 | + content[key] = JsonSerializer.SerializeToElement(stringSchema.Default); |
| 146 | + break; |
| 147 | + case ElicitRequestParams.NumberSchema numberSchema when numberSchema.Default.HasValue: |
| 148 | + content[key] = JsonSerializer.SerializeToElement(numberSchema.Default.Value); |
| 149 | + break; |
| 150 | + case ElicitRequestParams.BooleanSchema booleanSchema when booleanSchema.Default.HasValue: |
| 151 | + content[key] = JsonSerializer.SerializeToElement(booleanSchema.Default.Value); |
| 152 | + break; |
| 153 | + case ElicitRequestParams.UntitledSingleSelectEnumSchema enumSchema when enumSchema.Default is not null: |
| 154 | + content[key] = JsonSerializer.SerializeToElement(enumSchema.Default); |
| 155 | + break; |
| 156 | + case ElicitRequestParams.TitledSingleSelectEnumSchema titledEnumSchema when titledEnumSchema.Default is not null: |
| 157 | + content[key] = JsonSerializer.SerializeToElement(titledEnumSchema.Default); |
| 158 | + break; |
| 159 | + } |
| 160 | + } |
| 161 | + } |
| 162 | + |
| 163 | + return new ValueTask<ElicitResult>(new ElicitResult { Action = "accept", Content = content }); |
| 164 | + }; |
| 165 | + |
| 166 | + // Call the test_client_elicitation_defaults tool |
| 167 | + var testToolName = "test_client_elicitation_defaults"; |
| 168 | + Console.WriteLine($"Calling tool: {testToolName}"); |
| 169 | + var result = await mcpClient.CallToolAsync(toolName: testToolName, arguments: new Dictionary<string, object?>()); |
| 170 | + Console.WriteLine($"Tool result: {result}"); |
| 171 | + success &= !(result.IsError == true); |
| 172 | + |
| 173 | + break; |
| 174 | + } |
108 | 175 | default: |
109 | 176 | // No extra processing for other scenarios |
110 | 177 | break; |
|
0 commit comments