microsoft/autogen · error · Error
Failed to list MCP tools
Error message
Failed to list MCP tools
What it means
Thrown by McpAPI.listTools when the POST to /mcp/tools/list returns a non-2xx status. The server response body is parsed as JSON and its message field is surfaced; the literal string 'Failed to list MCP tools' only appears when the body has no message field (e.g. empty or HTML error body). This is a plain fetch wrapper with no timeout, no retry, and no check for network-vs-HTTP failure.
Source
Thrown at python/packages/autogen-studio/frontend/src/components/views/mcp/api.ts:209
const data = await response.json();
if (!response.ok) {
throw new Error(data.message || "Failed to get MCP capabilities");
}
return data;
}
async listTools(serverParams: McpServerParams): Promise<ListToolsResponse> {
const response = await fetch(`${this.getBaseUrl()}/mcp/tools/list`, {
method: "POST",
headers: this.getHeaders(),
body: JSON.stringify({ server_params: serverParams }),
});
const data = await response.json();
if (!response.ok) {
throw new Error(data.message || "Failed to list MCP tools");
}
return data;
}
async callTool(
serverParams: McpServerParams,
toolName: string,
toolArguments: Record<string, any>
): Promise<CallToolResponse> {
const response = await fetch(`${this.getBaseUrl()}/mcp/tools/call`, {
method: "POST",
headers: this.getHeaders(),
body: JSON.stringify({
server_params: serverParams,
tool_name: toolName,
arguments: toolArguments,
}),View on GitHub (pinned to 027ecf0a37)
Solutions
- Check the browser Network tab for the actual status code and response body of the POST to /mcp/tools/list — the body's message field names the real cause
- Validate server_params before calling: for stdio ensure command is on the backend PATH; for SSE/HTTP ensure the URL is reachable from the backend process, not the browser
- Verify the Authorization header is present and the token valid (clear localStorage auth_token and re-login if 401)
- Confirm the backend actually mounts the /mcp/tools/list route (curl POST it directly against the backend port)
- If data.message is empty because the body is HTML, log await response.text() instead of relying on response.json()
Example fix
// before
const data = await response.json();
if (!response.ok) {
throw new Error(data.message || "Failed to list MCP tools");
}
// after
const text = await response.text();
let data: any = {};
try { data = JSON.parse(text); } catch { /* HTML/plain error body */ }
if (!response.ok) {
throw new Error(data.message || `Failed to list MCP tools (HTTP ${response.status}): ${text.slice(0, 200)}`);
} Defensive patterns
Strategy: validation
Validate before calling
function hasValidServerParams(p: McpServerParams): boolean {
if (!p || typeof p !== "object") return false;
if ((p as any).command != null) {
return typeof (p as any).command === "string" && (p as any).command.length > 0;
}
if ((p as any).url != null) {
try { new URL((p as any).url); return true; } catch { return false; }
}
return false;
} Type guard
function isStdioParams(p: McpServerParams): p is McpServerParams & { command: string; args?: string[] } {
return typeof (p as any).command === "string";
} Try / catch
try {
const res = await mcpAPI.listTools(serverParams);
return res.data?.tools ?? [];
} catch (e) {
reportError(e instanceof Error ? e.message : String(e), { scope: "mcp.listTools" });
return []; // treat as no tools; never surface raw error to render tree
} Prevention
- Run healthCheck() once before listTools to fail fast with a clearer message
- Validate server_params shape (stdio command / SSE url) in the UI form before submit
- Cache the last working server_params per server entry and offer rollback
When it happens
Trigger: POST {base}/mcp/tools/list with {server_params} returning 4xx/5xx: invalid server_params (bad command, missing env vars for a stdio server), unreachable SSE/HTTP MCP server URL, unauthenticated request (missing/expired Bearer token so the backend returns 401/403), or the backend MCP route not mounted.
Common situations: Misconfigured stdio server_params (wrong command path), MCP server URL not reachable from the backend container, running frontend against a backend on a different port without the /api proxy forwarding /mcp, expired auth_token in localStorage, backend version where the /mcp route is not registered.
Related errors
- Failed to call MCP tool
- MCP health check failed
- HTTP ${response.status}: ${errorText || "Failed to create We
- Failed to fetch sessions
- Failed to delete team
AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15).
Data as JSON: /api/errors/7042bb0c3770eeab.
Report an issue: GitHub.