Implementation for SEP-2243 Http Standardization (#1553)

Co-authored-by: Tarek Mahmoud Sayed <tarekms@microsoft.com>
Co-authored-by: Tarek Mahmoud Sayed <tarekms@ntdev.microsoft.com>
Co-authored-by: Tarek Mahmoud Sayed <10833894+tarekgh@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Mike Kistler 2026-05-14 17:39:37 -05:00 • committed by GitHub
commit b8c4d951ec
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -179,6 +179,136 @@ try
}
break;
}
case "http-standard-headers":
{
// List and call tools to test Mcp-Method and Mcp-Name headers
var tools = await mcpClient.ListToolsAsync();
Console.WriteLine($"Available tools: {string.Join(", ", tools.Select(t => t.Name))}");
var tool = tools.FirstOrDefault(t => t.Name == "test_headers");
if (tool is not null)
{
Console.WriteLine("Calling tool: test_headers");
var result = await mcpClient.CallToolAsync(toolName: "test_headers", arguments: new Dictionary<string, object?>());
success &= !(result.IsError == true);
}
// List and get prompts to test Mcp-Method and Mcp-Name headers
var prompts = await mcpClient.ListPromptsAsync();
Console.WriteLine($"Available prompts: {string.Join(", ", prompts.Select(p => p.Name))}");
foreach (var prompt in prompts)
{
Console.WriteLine($"Getting prompt: {prompt.Name}");
try
{
await mcpClient.GetPromptAsync(prompt.Name);
}
catch (Exception ex)
{
Console.WriteLine($"Prompt get error (expected for test): {ex.Message}");
}
}
// List and read resources to test Mcp-Name with params.uri
var resources = await mcpClient.ListResourcesAsync();
Console.WriteLine($"Available resources: {string.Join(", ", resources.Select(r => r.Uri))}");
foreach (var resource in resources)
{
Console.WriteLine($"Reading resource: {resource.Uri}");
try
{
await mcpClient.ReadResourceAsync(resource.Uri);
}
catch (Exception ex)
{
Console.WriteLine($"Resource read error (expected for test): {ex.Message}");
}
}
break;
}
case "http-custom-headers":
{
// List tools to discover x-mcp-header annotations (populates tool cache)
var tools = await mcpClient.ListToolsAsync();
Console.WriteLine($"Available tools: {string.Join(", ", tools.Select(t => t.Name))}");
// Parse conformance context for tool calls
if (!string.IsNullOrEmpty(conformanceContext))
{
using var contextDoc = JsonDocument.Parse(conformanceContext);
// Support both "toolCalls" (array) and legacy "toolCall" (single object)
var toolCallElements = new List<JsonElement>();
if (contextDoc.RootElement.TryGetProperty("toolCalls", out var toolCallsArray) &&
toolCallsArray.ValueKind == JsonValueKind.Array)
{
foreach (var item in toolCallsArray.EnumerateArray())
{
toolCallElements.Add(item);
}
}
else if (contextDoc.RootElement.TryGetProperty("toolCall", out var toolCallEl))
{
toolCallElements.Add(toolCallEl);
}
foreach (var toolCallEl in toolCallElements)
{
var toolName = toolCallEl.TryGetProperty("name", out var nameEl)
? nameEl.GetString() ?? "test_custom_headers"
: "test_custom_headers";
Dictionary<string, object?> toolCallArgs = new();
if (toolCallEl.TryGetProperty("arguments", out var argsEl))
{
foreach (var prop in argsEl.EnumerateObject())
{
object? value = prop.Value.ValueKind switch
{
JsonValueKind.String => prop.Value.GetString(),
JsonValueKind.Number => prop.Value.TryGetInt64(out var l) ? l : prop.Value.GetDouble(),
JsonValueKind.True => true,
JsonValueKind.False => false,
JsonValueKind.Null => null,
_ => prop.Value.GetRawText(),
};
toolCallArgs[prop.Name] = value;
}
}
Console.WriteLine($"Calling tool: {toolName} with {toolCallArgs.Count} arguments");
var result = await mcpClient.CallToolAsync(toolName: toolName, arguments: toolCallArgs);
success &= !(result.IsError == true);
}
}
break;
}
case "http-invalid-tool-headers":
{
// List tools — the client should filter out tools with invalid x-mcp-header annotations
var tools = await mcpClient.ListToolsAsync();
Console.WriteLine($"Available tools after filtering: {string.Join(", ", tools.Select(t => t.Name))}");
// Only call valid_tool — invalid tools should have been excluded
var validTool = tools.FirstOrDefault(t => t.Name == "valid_tool");
if (validTool is not null)
{
Console.WriteLine("Calling valid_tool");
var result = await mcpClient.CallToolAsync(toolName: "valid_tool", arguments: new Dictionary<string, object?>
{
{ "region", "us-east1" }
});
success &= !(result.IsError == true);
}
else
{
Console.WriteLine("ERROR: valid_tool was not found in the filtered tool list");
success = false;
}
break;
}
default:
// No extra processing for other scenarios
break;