Tighten draft protocol negotiation boundaries (#1692)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Co-authored-by: Tarek Mahmoud Sayed <tarekms@ntdev.microsoft.com>
This commit is contained in:
parent
a8d374b280
commit
fd38f51e27
1 changed files with 1755 additions and 589 deletions
|
|
@ -147,7 +147,7 @@ public class MrtrProtocolTests(ITestOutputHelper outputHelper) : KestrelInMemory
|
|||
// headers. No initialize handshake and no Mcp-Session-Id.
|
||||
HttpClient.DefaultRequestHeaders.Accept.Add(new("application/json"));
|
||||
HttpClient.DefaultRequestHeaders.Accept.Add(new("text/event-stream"));
|
||||
HttpClient.DefaultRequestHeaders.Add("MCP-Protocol-Version", McpHttpHeaders.July2026ProtocolVersion);
|
||||
HttpClient.DefaultRequestHeaders.Add("MCP-Protocol-Version", McpProtocolVersions.July2026ProtocolVersion);
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
|
|
@ -261,7 +261,7 @@ public class MrtrProtocolTests(ITestOutputHelper outputHelper) : KestrelInMemory
|
|||
public async Task BackcompatResolver_SendsServerRequestOverPostStream_WithoutGetStream()
|
||||
{
|
||||
// Configure a server that does NOT pin 2026-07-28 so it can negotiate the current
|
||||
// protocol with a legacy client. The backcompat resolver path only runs when the
|
||||
// initialize-handshake protocol. The backcompat resolver path only runs when the
|
||||
// negotiated version is not 2026-07-28.
|
||||
Builder.Services.AddMcpServer(options =>
|
||||
{
|
||||
|
|
@ -302,7 +302,7 @@ public class MrtrProtocolTests(ITestOutputHelper outputHelper) : KestrelInMemory
|
|||
HttpClient.DefaultRequestHeaders.Accept.Add(new("application/json"));
|
||||
HttpClient.DefaultRequestHeaders.Accept.Add(new("text/event-stream"));
|
||||
|
||||
// Initialize with the current legacy protocol so the server's backcompat resolver runs.
|
||||
// Initialize with the current initialize-handshake protocol so the server's backcompat resolver runs.
|
||||
var initJson = """
|
||||
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{"roots":{}},"clientInfo":{"name":"BackcompatTestClient","version":"1.0.0"}}}
|
||||
""";
|
||||
|
|
@ -337,7 +337,7 @@ public class MrtrProtocolTests(ITestOutputHelper outputHelper) : KestrelInMemory
|
|||
// the response headers arrive instead of waiting for the SSE stream to close.
|
||||
var callRequest = new HttpRequestMessage(HttpMethod.Post, (string?)null)
|
||||
{
|
||||
Content = JsonContent(CallTool("backcompat-roots-tool")),
|
||||
Content = JsonContent(CallTool("backcompat-roots-tool", includePerRequestMetadata: false)),
|
||||
};
|
||||
callRequest.Content.Headers.Add("Mcp-Method", "tools/call");
|
||||
callRequest.Content.Headers.Add("Mcp-Name", "backcompat-roots-tool");
|
||||
|
|
@ -456,16 +456,49 @@ public class MrtrProtocolTests(ITestOutputHelper outputHelper) : KestrelInMemory
|
|||
|
||||
private long _lastRequestId = 1;
|
||||
|
||||
private string Request(string method, string parameters = "{}")
|
||||
private string Request(string method, string parameters = "{}", bool includePerRequestMetadata = true)
|
||||
{
|
||||
var id = Interlocked.Increment(ref _lastRequestId);
|
||||
return $$"""
|
||||
{"jsonrpc":"2.0","id":{{id}},"method":"{{method}}","params":{{parameters}}}
|
||||
""";
|
||||
var paramsObj = JsonNode.Parse(parameters) as JsonObject ?? new JsonObject();
|
||||
if (includePerRequestMetadata)
|
||||
{
|
||||
AddJuly2026ProtocolMeta(paramsObj);
|
||||
}
|
||||
|
||||
var request = new JsonObject
|
||||
{
|
||||
["jsonrpc"] = "2.0",
|
||||
["id"] = id,
|
||||
["method"] = method,
|
||||
["params"] = paramsObj,
|
||||
};
|
||||
|
||||
return request.ToJsonString();
|
||||
}
|
||||
|
||||
private string CallTool(string toolName, string arguments = "{}") =>
|
||||
private static void AddJuly2026ProtocolMeta(JsonObject paramsObj)
|
||||
{
|
||||
if (paramsObj["_meta"] is not JsonObject meta)
|
||||
{
|
||||
meta = [];
|
||||
paramsObj["_meta"] = meta;
|
||||
}
|
||||
|
||||
meta[MetaKeys.ProtocolVersion] = McpProtocolVersions.July2026ProtocolVersion;
|
||||
meta[MetaKeys.ClientInfo] = new JsonObject
|
||||
{
|
||||
["name"] = "MrtrTestClient",
|
||||
["version"] = "1.0",
|
||||
};
|
||||
|
||||
if (meta[MetaKeys.ClientCapabilities] is not JsonObject)
|
||||
{
|
||||
meta[MetaKeys.ClientCapabilities] = new JsonObject();
|
||||
}
|
||||
}
|
||||
|
||||
private string CallTool(string toolName, string arguments = "{}", bool includePerRequestMetadata = true) =>
|
||||
Request("tools/call", $$"""
|
||||
{"name":"{{toolName}}","arguments":{{arguments}}}
|
||||
""");
|
||||
""", includePerRequestMetadata);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue