{"record":{"id":"63bb336725fd55ac","repo":"koala73/worldmonitor","slug":"initialize-error-mcp-server-rejected-request","errorCode":null,"errorMessage":"Initialize error: MCP server rejected request","messagePattern":"Initialize error: MCP server rejected request","errorType":"exception","errorClass":"McpProxyUpstreamError","httpStatus":null,"severity":"error","filePath":"api/mcp-proxy.ts","lineNumber":581,"sourceCode":"      jsonrpc: '2.0',\n      method: 'notifications/initialized',\n      params: {},\n    }, headers, sessionId);\n    await cancelResponseBody(response);\n  } catch (error) {\n    if (error instanceof McpProxySsrfError) throw error;\n    /* non-fatal */\n  }\n}\n\nasync function mcpListTools(serverUrl, customHeaders) {\n  const { response: initResp, url: sessionUrl, headers } = await postJson(\n    serverUrl, buildInitPayload(), buildHeaders(customHeaders), null,\n  );\n  if (!initResp.ok) throw new McpProxyUpstreamError(`Initialize failed: HTTP ${initResp.status}`);\n  const sessionId = initResp.headers.get('Mcp-Session-Id') || initResp.headers.get('mcp-session-id');\n  const initData = await parseJsonRpcResponse(initResp);\n  if (initData.error) throw new McpProxyUpstreamError('Initialize error: MCP server rejected request');\n  await sendInitialized(sessionUrl, headers, sessionId);\n  const { response: listResp } = await postJson(sessionUrl, {\n    jsonrpc: '2.0', id: 2, method: 'tools/list', params: {},\n  }, headers, sessionId);\n  if (!listResp.ok) throw new McpProxyUpstreamError(`tools/list failed: HTTP ${listResp.status}`);\n  const listData = await parseJsonRpcResponse(listResp);\n  if (listData.error) throw new McpProxyUpstreamError('tools/list error: MCP server rejected request');\n  return listData.result?.tools || [];\n}\n\nasync function mcpCallTool(serverUrl, toolName, toolArgs, customHeaders) {\n  const { response: initResp, url: sessionUrl, headers } = await postJson(\n    serverUrl, buildInitPayload(), buildHeaders(customHeaders), null,\n  );\n  if (!initResp.ok) throw new McpProxyUpstreamError(`Initialize failed: HTTP ${initResp.status}`);\n  const sessionId = initResp.headers.get('Mcp-Session-Id') || initResp.headers.get('mcp-session-id');\n  const initData = await parseJsonRpcResponse(initResp);\n  if (initData.error) throw new McpProxyUpstreamError('Initialize error: MCP server rejected request');","sourceCodeStart":563,"sourceCodeEnd":599,"githubUrl":"https://github.com/koala73/worldmonitor/blob/7d06c8633d256c18e38133030bc3613976a96ec9/api/mcp-proxy.ts#L563-L599","documentation":"During the MCP streamable-HTTP handshake, the server accepted the initialize request at the HTTP level (2xx) but answered with a JSON-RPC error object instead of a result. The proxy treats this as the upstream rejecting the initialization itself, so the session can never be established, and throws McpProxyUpstreamError('Initialize error: MCP server rejected request') in mcpListTools.","triggerScenarios":"Thrown from mcpListTools (called by the tools handler) when initData = await parseJsonRpcResponse(initResp) returns { error: ... } — i.e. HTTP 200 but a JSON-RPC error for the initialize request.","commonSituations":"The upstream MCP server does not support the protocol version the proxy sends in buildInitPayload (spec version mismatch); the server requires authentication and returns a JSON-RPC auth error instead of HTTP 401; the URL targets a transport the server doesn't speak at that path (e.g. POSTing to an SSE-only endpoint); the server is a different MCP spec revision that rejects the payload shape.","solutions":["Inspect the JSON-RPC error object (code/message) returned by the server — it states why initialize was rejected (version, auth, or protocol).","Align the protocolVersion sent in buildInitPayload with what the upstream server supports (check its advertised version in the error data).","Verify required auth: pass the needed custom headers (API key / bearer token) to the proxy request if the server expects them at initialize.","Confirm the server URL/transport: a path ending in /sse must use the SSE transport, not the streamable-HTTP POST flow.","Update the upstream MCP server to a spec revision compatible with the proxy's initialize payload."],"exampleFix":"// before: proxy advertises a newer spec version than the server accepts\n{ jsonrpc: '2.0', id: 1, method: 'initialize', params: { protocolVersion: '2025-06-18', ... } }\n// after: negotiate the version the server supports\n{ jsonrpc: '2.0', id: 1, method: 'initialize', params: { protocolVersion: '2024-11-05', ... } }","handlingStrategy":"try-catch","validationCode":"if (!serverUrl || !/^https:\\/\\//.test(serverUrl)) throw new Error('A valid https MCP server URL is required');\nif (requiredAuthHeaders && !Object.keys(customHeaders || {}).length) throw new Error('This MCP server requires auth headers at initialize');","typeGuard":"function isJsonRpcError(msg) {\n  return typeof msg === 'object' && msg !== null && 'error' in msg && msg.error !== undefined;\n}","tryCatchPattern":"try {\n  const tools = await mcpProxy.tools(serverUrl, headers);\n} catch (error) {\n  if (error instanceof McpProxyUpstreamError && error.message.startsWith('Initialize error')) {\n    // protocol-version or auth rejection: surface a config hint to the operator\n    return { error: 'MCP server rejected initialize — check protocol version and auth headers' };\n  }\n  throw error;\n}","preventionTips":["Pin and document the MCP protocol version each upstream server supports.","Store and pass auth headers via environment configuration before first use.","Test the handshake with the official MCP inspector against each registered server.","Keep upstream servers on a spec revision compatible with the proxy's initialize payload."],"tags":["mcp","json-rpc","initialize","handshake","upstream"],"backgroundTag":"upstream-api-error","analyzedSha":"7d06c8633d256c18e38133030bc3613976a96ec9","analyzedAt":"2026-09-15T16:44:39.439Z","contentChangedAt":"2026-09-15T16:44:39.439Z","schemaVersion":2},"datasetVersion":"2026-09-15T18:17:12.389Z"}