bytedance/deer-flow · error · MCPConfigRequestError

Failed to load MCP configuration

Error message

Failed to load MCP configuration

What it means

Thrown when GET /api/mcp/config fails. This endpoint reads the Gateway-side MCP server registry (extensions_config.json plus runtime state); any non-2xx aborts loading of the MCP configuration UI. The error class MCPConfigRequestError carries the HTTP status and the backend 'detail' text.

Source

Thrown at frontend/src/core/mcp/api.ts:31

  get isAdminRequired(): boolean {
    return this.status === 403;
  }
}

async function readErrorDetail(
  response: Response,
  fallback: string,
): Promise<string> {
  const error = (await response.json().catch(() => ({}))) as {
    detail?: unknown;
  };
  return typeof error.detail === "string" ? error.detail : fallback;
}

export async function loadMCPConfig() {
  const response = await fetch(`${getBackendBaseURL()}/api/mcp/config`);
  if (!response.ok) {
    throw new MCPConfigRequestError(
      response.status,
      await readErrorDetail(response, "Failed to load MCP configuration"),
    );
  }
  return response.json() as Promise<MCPConfig>;
}

export async function updateMCPConfig(config: MCPConfig) {
  const response = await fetch(`${getBackendBaseURL()}/api/mcp/config`, {
    method: "PUT",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify(config),
  });
  if (!response.ok) {
    throw new MCPConfigRequestError(
      response.status,

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. curl http://127.0.0.1:8001/api/mcp/config directly to see the real status and 'detail' body
  2. Validate extensions_config.json with a JSON linter and fix syntax errors
  3. Remove or migrate MCP server entries that use fields removed in the current backend version (compare against extensions_config.example.json)
  4. If a 502/503 came from nginx, wait for or restart the Gateway and retry

Example fix

// before
const config = await loadMCPConfig();

// after
const config = await loadMCPConfig().catch((e) => {
  if (e instanceof MCPConfigRequestError && e.status >= 500) {
    toast.error('MCP config unavailable on the server; retry after Gateway restart');
  }
  throw e;
});
Defensive patterns

Strategy: retry

Validate before calling

async function gatewayHealthy(baseURL: string): Promise<boolean> {
  try {
    const r = await fetch(`${baseURL}/health`);
    return r.ok;
  } catch {
    return false;
  }
}

Type guard

export function isMCPConfigRequestError(e: unknown): e is MCPConfigRequestError {
  return e instanceof MCPConfigRequestError;
}

Try / catch

try {
  return await loadMCPConfig();
} catch (e) {
  if (isMCPConfigRequestError(e) && e.status >= 502) {
    return retryWithBackoff(loadMCPConfig, {tries: 2});
  }
  throw e;
}

Prevention

When it happens

Trigger: Gateway not fully started when the settings page fetches config; extensions_config.json corrupted or unreadable (500); an MCP server entry whose schema the backend rejects at load; nginx proxy returning 502 while the Gateway restarts.

Common situations: Opening the MCP settings panel right after `make dev` before the Gateway is listening; hand-editing extensions_config.json and introducing JSON syntax errors; upgrading the backend to a version with a stricter MCP config schema while stale entries remain.

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/636e679172b04ce6. Report an issue: GitHub.