koala73/worldmonitor · error · McpProxyUpstreamError
tools/call failed: HTTP
Error message
tools/call failed: HTTP ${callResp.status} What it means
Thrown by mcpCallTool when any request in the tools/call flow — initialize, the call itself, or session setup — received a non-2xx HTTP status from the MCP server. The remote endpoint answered but refused the request at the HTTP layer, so the tool call could not complete.
Solutions
- Inspect the HTTP status in the message to distinguish auth (401/403), routing (404), and upstream (5xx) causes
- Verify serverUrl and any required custom headers for the MCP server
- Retry transient 5xx statuses once; restart the session for 404 caused by an expired session id
Defensive patterns
Strategy: retry
When it happens
Trigger: Thrown at api/mcp-proxy.ts:338 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of koala73/worldmonitor@e586b8b4b8 (2026-09-15).
Data as JSON: /api/errors/b1a98fa04d37c686.
Report an issue: GitHub.
Appendix: source
Thrown at api/mcp-proxy.ts:606
const listData = await parseJsonRpcResponse(listResp);
if (listData.error) throw new McpProxyUpstreamError('tools/list error: MCP server rejected request');
return listData.result?.tools || [];
}
async function mcpCallTool(serverUrl, toolName, toolArgs, customHeaders) {
const { response: initResp, url: sessionUrl, headers } = await postJson(
serverUrl, buildInitPayload(), buildHeaders(customHeaders), null,
);
if (!initResp.ok) throw new McpProxyUpstreamError(`Initialize failed: HTTP ${initResp.status}`);
const sessionId = initResp.headers.get('Mcp-Session-Id') || initResp.headers.get('mcp-session-id');
const initData = await parseJsonRpcResponse(initResp);
if (initData.error) throw new McpProxyUpstreamError('Initialize error: MCP server rejected request');
await sendInitialized(sessionUrl, headers, sessionId);
const { response: callResp } = await postJson(sessionUrl, {
jsonrpc: '2.0', id: 3, method: 'tools/call',
params: { name: toolName, arguments: toolArgs || {} },
}, headers, sessionId);
if (!callResp.ok) throw new McpProxyUpstreamError(`tools/call failed: HTTP ${callResp.status}`);
const callData = await parseJsonRpcResponse(callResp);
if (callData.error) throw new McpProxyUpstreamError('tools/call error: MCP server rejected request');
return callData.result;
}
// --- SSE transport (HTTP+SSE, older MCP spec) ---
// Servers whose URL path ends with /sse use this protocol:
// 1. Client GETs the SSE URL — server opens a stream and emits an `endpoint` event
// containing the URL where the client should POST JSON-RPC messages.
// 2. Client POSTs JSON-RPC to that endpoint URL.
// 3. Server sends responses on the same SSE stream as `data:` lines.
function isSseTransport(url) {
const p = url.pathname;
return p === '/sse' || p.endsWith('/sse');
}
function makeDeferred() {View on GitHub (pinned to e586b8b4b8)