different-ai/openwork · error · ProbeFailure
MCP_INITIALIZED
MCP_INITIALIZED
Error message
Initialized notification returned HTTP ${initializedResponse.status} What it means
Thrown when the notifications/initialized request returns any status other than the expected 202 (and not 404, which is classified as session expiry instead). MCP streamable-HTTP servers must acknowledge notifications with 202 Accepted; any other status means the lifecycle step did not complete as required.
Source
Thrown at packages/enterprise-mcp-mock-server/src/testing/probe.ts:789
recordPassed(phases, "MCP_INITIALIZE", startedAt, "MCP version, capabilities, and session negotiated")
const sessionHeaders = {
...rpcHeaders,
"mcp-session-id": sessionId,
"mcp-protocol-version": initialize.protocolVersion,
}
startedAt = Date.now()
const initializedResponse = await fetchStep(mcpUrl, {
method: "POST",
headers: sessionHeaders,
body: JSON.stringify({ jsonrpc: "2.0", method: "notifications/initialized" }),
}, "MCP_INITIALIZED", overallDeadline)
await discardResponseBody(initializedResponse, "MCP_INITIALIZED", "mcp_lifecycle")
if (initializedResponse.status === 404) {
throw new ProbeFailure("CONTINUITY_SESSION", "mcp_session_expired", "MCP session expired after initialize")
}
if (initializedResponse.status !== 202) {
throw new ProbeFailure("MCP_INITIALIZED", "mcp_lifecycle", `Initialized notification returned HTTP ${initializedResponse.status}`)
}
recordPassed(phases, "MCP_INITIALIZED", startedAt, "Initialized notification received HTTP 202")
startedAt = Date.now()
const toolNames = new Set<string>()
const discoveredTools: MockTool[] = []
const cursors = new Set<string>()
let cursor: string | undefined
let catalogComplete = false
for (let page = 0; page < 25; page += 1) {
if (cursor) {
if (cursors.has(cursor)) throw new ProbeFailure("MCP_TOOL_DISCOVERY", "mcp_pagination_loop", "Tool catalog repeated a cursor")
cursors.add(cursor)
}
const listRawResponse = await fetchStep(mcpUrl, {
method: "POST",
headers: sessionHeaders,
body: JSON.stringify({ jsonrpc: "2.0", id: 10 + page, method: "tools/list", params: cursor ? { cursor } : {} }),View on GitHub (pinned to 2b7df46e8a)
Solutions
- Update the server to return 202 Accepted for JSON-RPC notifications (no id)
- Check gateway/proxy rules that may reject id-less POST bodies
- Inspect the response body/status server-side for an internal error and fix it
- Confirm the server implements the streamable-HTTP transport, not an older one
Example fix
// before (server)
handleJsonRpc(body); res.status(200).json(result)
// after (server)
if (!("id" in body)) { handleNotification(body); res.status(202).end() } Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
null
Try / catch
try {
await probeEnterpriseMcpMockServer(scenario)
} catch (e) {
if (e instanceof ProbeFailure && e.code === "MCP_INITIALIZED") {
console.error("Initialized notification rejected:", e.message)
}
} Prevention
- Return 202 Accepted for JSON-RPC notifications (requests without id)
- Test the full initialize → notifications/initialized lifecycle
- Check gateways accept id-less POST bodies
When it happens
Trigger: The initialized notification POST returns 200, 400, 405, 500, etc. — e.g. the server treats notifications as regular JSON-RPC requests, rejects the body, or errors internally.
Common situations: Server implemented against an older HTTP transport that replies 200 to notifications; a gateway that rejects POSTs without an id field (notifications have no id); server bug returning 500 on notification handling; wrong content-type negotiation causing 415.
Related errors
- invalid_mcp_token_payload
- invalid_mcp_connection_payload
- t("providers.not_connected")
- OpenWork server cannot read MCP config for this workspace.
- OpenWork Connect MCP metadata is invalid.
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/103f29873e188d08.
Report an issue: GitHub.