{"record":{"id":"4bc0bb3ccba093a5","repo":"microsoft/aspire","slug":"foundry-toolbox-did-not-discover-the-required-tools-within","errorCode":null,"errorMessage":"Foundry Toolbox did not discover the required tools within {_timeout}: {expected}.","messagePattern":"Foundry Toolbox did not discover the required tools within (.+?): (.+?)\\.","errorType":"exception","errorClass":"TimeoutException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxReadinessProbe.cs","lineNumber":122,"sourceCode":"                    (hasConfiguredExpectations || discoveredToolNames.Count > 0))\n                {\n                    return discoveredToolNames.ToArray();\n                }\n\n                // Toolbox tool discovery is eventually consistent immediately after reconciliation.\n                await Task.Delay(_retryDelay, discoveryCancellation.Token).ConfigureAwait(false);\n            }\n        }\n        catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested)\n        {\n            var expectedTools = requiredToolNames\n                .Concat(requiredMcpServerLabels.Select(label => $\"{label}.*\"))\n                .Order(StringComparer.Ordinal)\n                .ToArray();\n            var expected = expectedTools.Length == 0\n                ? \"any tool\"\n                : string.Join(\", \", expectedTools);\n            throw new TimeoutException(\n                $\"Foundry Toolbox did not discover the required tools within {_timeout}: {expected}.\");\n        }\n    }\n\n    private static string CreateToolsListPayload(int requestId, string? cursor)\n    {\n        using var stream = new MemoryStream();\n        using (var writer = new Utf8JsonWriter(stream))\n        {\n            writer.WriteStartObject();\n            writer.WriteString(\"jsonrpc\", \"2.0\");\n            writer.WriteNumber(\"id\", requestId);\n            writer.WriteString(\"method\", \"tools/list\");\n            writer.WriteStartObject(\"params\");\n            if (cursor is not null)\n            {\n                writer.WriteString(\"cursor\", cursor);\n            }","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Foundry/Toolbox/FoundryToolboxReadinessProbe.cs#L104-L140","documentation":"Thrown as a TimeoutException by WaitForToolsAsync when the required tools (tool names plus '{label}.*' patterns for MCP server labels) were not all discovered on the Toolbox within the probe timeout. The probe pages through tools/list until the expected set is complete; on expiry it reports what was still missing.","triggerScenarios":"Calling .WaitForTools(...) where the Toolbox never exposes one or more of the required tool names or MCP-server-label tools before the timeout elapses — e.g. the backing MCP server is slow to start, not registered, or the tool name/label in code does not match what the server advertises.","commonSituations":"Typo in the expected tool name or McpServerLabel; the downstream MCP server crashed or is unreachable from Foundry; network latency or cold start exceeding the configured timeout; the tool list paginates slowly and the timeout is too short.","solutions":["Compare the expected tool names/labels in code against the actual tools listed by the Toolbox (via the dashboard or a manual tools/list call) and fix mismatches.","Increase the readiness probe timeout to accommodate slow starts.","Verify the backing MCP server is running, healthy, and reachable by the Foundry Toolbox.","Re-register the missing tool in the Toolbox configuration and redeploy."],"exampleFix":"// before\n.WithTools(\"search-tool\") // server actually exposes 'web-search'\n// after\n.WithTools(\"web-search\") // matches the tool name advertised by the MCP server","handlingStrategy":"retry","validationCode":"// Compare expected names against the live Toolbox before waiting:\n// var listed = await CallToolsListAsync(endpoint, token); // assert expected ⊆ listed","typeGuard":null,"tryCatchPattern":"try\n{\n    await probe.WaitForToolsAsync(accessToken, ct);\n}\ncatch (TimeoutException ex)\n{\n    logger.LogWarning(ex, \"Tools not discovered in time; retrying once.\");\n    await probe.WaitForToolsAsync(accessToken, ct);\n}","preventionTips":["Verify expected tool names and MCP server labels match exactly what the server advertises.","Size the probe timeout for cold starts and network latency.","Ensure the backing MCP server is healthy and reachable before waiting on tools."],"tags":["timeout","mcp","readiness","foundry-toolbox"],"backgroundTag":"request-timeout","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"}