microsoft/aspire · error · InvalidOperationException
Foundry Toolbox MCP initialization did not negotiate a…
Error message
Foundry Toolbox MCP initialization did not negotiate a protocol version.
What it means
Thrown by FoundryToolboxReadinessProbe.WaitForToolsAsync when the MCP initialize handshake response contains no non-empty 'protocolVersion' property. The probe performs a full JSON-RPC MCP handshake to confirm the Toolbox is live before declaring readiness; a successful initialize must always negotiate a protocol version.
Solutions
- Verify the MCP endpoint URL is the correct Toolbox endpoint that speaks the MCP JSON-RPC protocol.
- Check authentication — an auth redirect or error page returned with 200 would lack protocolVersion; ensure the access token is valid and scoped.
- Confirm the Toolbox service version supports the MCP initialize handshake expected by the probe.
- Retry after the service deploys/updates, since a mid-deploy endpoint can return malformed responses.
Example fix
// before probe endpoint: https://my-app.example.com/ (not the MCP route) // after probe endpoint: https://my-app.example.com/mcp (the actual JSON-RPC MCP endpoint)
Defensive patterns
Strategy: retry
Validate before calling
// Pre-check: verify the endpoint speaks MCP by expecting a JSON object with protocolVersion in the initialize reply before relying on the probe.
Try / catch
try
{
await probe.WaitForToolsAsync(accessToken, ct);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("did not negotiate a protocol version"))
{
logger.LogError(ex, "Toolbox endpoint did not complete MCP handshake; verify URL and auth.");
throw;
} Prevention
- Point the probe at the actual JSON-RPC MCP route, not the app root.
- Use a fresh, correctly-scoped access token so auth gateways don't intercept the handshake.
- Keep the Foundry Toolbox service and Aspire.Hosting.Foundry package versions compatible.
When it happens
Trigger: The Toolbox MCP endpoint responds to 'initialize' with a JSON body lacking protocolVersion or with an empty string — e.g. the endpoint is not actually an MCP server, an auth gateway returns a 200 with an HTML/JSON error body, or a protocol-incompatible server version.
Common situations: Pointing the probe at a wrong or deprecated Toolbox URL; an API management layer intercepting the request and returning an unexpected payload; the Foundry Toolbox service deployed an incompatible MCP protocol revision.
Related errors
- A discovered Toolbox tool did not have a name.
- Foundry Toolbox did not discover the required tools within
- The Toolbox MCP response did not contain JSON-RPC response…
- Toolbox MCP request failed
- -32602
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/61ea15f85c10b68b.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxReadinessProbe.cs:48
using var discoveryCancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
discoveryCancellation.CancelAfter(_timeout);
try
{
var initialize = await SendRequestAsync(
endpoint,
accessToken,
sessionId: null,
protocolVersion: null,
"""
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"Aspire.Hosting.Foundry","version":"1.0"}}}
""",
discoveryCancellation.Token).ConfigureAwait(false);
var negotiatedProtocol = initialize.Result
.GetProperty("protocolVersion")
.GetString();
if (string.IsNullOrEmpty(negotiatedProtocol))
{
throw new InvalidOperationException("Foundry Toolbox MCP initialization did not negotiate a protocol version.");
}
await SendRequestAsync(
endpoint,
accessToken,
initialize.SessionId,
negotiatedProtocol,
"""{"jsonrpc":"2.0","method":"notifications/initialized","params":{}}""",
discoveryCancellation.Token).ConfigureAwait(false);
var requestId = 2;
while (true)
{
var discoveredToolNames = new HashSet<string>(StringComparer.Ordinal);
string? cursor = null;
var retryDiscovery = false;
do
{View on GitHub (pinned to 25830f84bd)