{"record":{"id":"96d1ce2eca078471","repo":"microsoft/aspire","slug":"the-toolbox-mcp-response-did-not-contain-json-rpc-response","errorCode":null,"errorMessage":"The Toolbox MCP response did not contain JSON-RPC response ID {expectedId}.","messagePattern":"The Toolbox MCP response did not contain JSON-RPC response ID (.+?)\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxReadinessProbe.cs","lineNumber":216,"sourceCode":"            : responsePayload.Split('\\n', StringSplitOptions.TrimEntries)\n                .Where(line => line.StartsWith(\"data:\", StringComparison.Ordinal))\n                .Select(line => line[\"data:\".Length..].Trim());\n        JsonElement? matchingResponse = null;\n        foreach (var responseMessage in responseMessages)\n        {\n            using var candidate = JsonDocument.Parse(responseMessage);\n            if (candidate.RootElement.TryGetProperty(\"id\", out var responseId) &&\n                responseId.ValueKind == JsonValueKind.Number &&\n                responseId.GetInt32() == expectedId)\n            {\n                matchingResponse = candidate.RootElement.Clone();\n                break;\n            }\n        }\n\n        if (matchingResponse is null)\n        {\n            throw new InvalidOperationException(\n                $\"The Toolbox MCP response did not contain JSON-RPC response ID {expectedId}.\");\n        }\n\n        if (matchingResponse.Value.TryGetProperty(\"error\", out var error))\n        {\n            throw new InvalidOperationException($\"Toolbox MCP request failed: {error.GetRawText()}\");\n        }\n\n        var result = matchingResponse.Value.TryGetProperty(\"result\", out var resultElement)\n            ? resultElement.Clone()\n            : default;\n        return new(result, responseSessionId);\n    }\n\n    private sealed record McpResponse(\n        JsonElement Result,\n        string? SessionId,\n        bool IsRetryableFailure = false);","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxReadinessProbe.cs#L198-L234","documentation":"Thrown by SendRequestAsync when, after reading all pending JSON-RPC responses for a request, none carries the expected response ID. The probe correlates JSON-RPC request IDs to responses; a missing ID means the reply stream ended or returned responses for other requests without answering this one.","triggerScenarios":"The Toolbox MCP stream closed before the response for expectedId arrived; the server dropped or never processed the request; responses arrive on a different connection than the probe is reading; the request was rejected before an ID-correlated response was emitted.","commonSituations":"SSE/streaming connection interrupted by a proxy or idle timeout; server crash mid-request; auth token expired mid-session causing the server to silently drop requests; mismatch between the probe's JSON-RPC framing and the server version.","solutions":["Retry the readiness check — transient stream drops are the most common cause.","Verify network path (proxies, gateways) between the probe and the Toolbox doesn't terminate SSE/WebSocket streams early.","Ensure the access token is valid for the whole probe duration; refresh if the session outlives token expiry.","Check Toolbox service logs for dropped or unhandled JSON-RPC requests."],"exampleFix":"// before\n// long-lived probe session with token expiring mid-handshake\ncancellationToken = CancellationToken.None;\n// after\n// bound probe lifetime to a fresh, valid token and explicit timeout\ncancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(30)).Token;","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try\n{\n    await probe.WaitForToolsAsync(accessToken, ct);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"did not contain JSON-RPC response ID\"))\n{\n    logger.LogWarning(ex, \"MCP response stream dropped the reply; retrying readiness check.\");\n    await probe.WaitForToolsAsync(accessToken, ct);\n}","preventionTips":["Avoid proxies that terminate SSE/WebSocket streams between the probe and Toolbox.","Bind the probe session to a token with lifetime longer than the probe duration.","Retry readiness checks on transient stream drops."],"tags":["mcp","json-rpc","streaming","foundry-toolbox"],"backgroundTag":"unexpected-response-shape","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}