Skip to content

bug(mcp/sse): /messages?sessionId= returns 404 — all MCP tool calls non-functional on pi.ruv.io #312

@RobLe3

Description

@RobLe3

Summary

All MCP tool calls via the SSE transport on pi.ruv.io return HTTP 404. The SSE connection establishes successfully and returns a valid session endpoint, but POSTing to that endpoint fails. The REST API (/v1/...) is unaffected and fully functional.

Environment

  • Endpoint: https://pi.ruv.io/sse (hosted instance)
  • Transport: MCP SSE (as configured in ~/.claude/settings.jsonmcpServers.pi-brain)
  • Client: Claude Code (Sonnet 4.6) — deferred tool schema for all 37 brain_* tools
  • Observed: 2026-03-28 (multiple attempts across several hours)

Steps to Reproduce

# Step 1 — SSE connection: WORKS (returns session endpoint)
curl -s "https://pi.ruv.io/sse" \
  -H "Authorization: Bearer $BRAIN_API_KEY" \
  -H "Accept: text/event-stream" \
  --max-time 3

# Output:
# event: endpoint
# data: /messages?sessionId=ba8abff6-cb7a-4790-9f84-4a14fdeab867

# Step 2 — POST tool call to session endpoint: FAILS with 404
curl -s -w "\nHTTP: %{http_code}" \
  -X POST "https://pi.ruv.io/messages?sessionId=ba8abff6-cb7a-4790-9f84-4a14fdeab867" \
  -H "Authorization: Bearer $BRAIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"brain_status","arguments":{}}}' \
  --max-time 8

# Output: HTTP: 404

# Step 3 — REST API: WORKS fine
curl -s "https://pi.ruv.io/v1/status" \
  -H "Authorization: Bearer $BRAIN_API_KEY"

# Output: {"total_memories":5190,"total_contributors":97,...} HTTP: 200

Observed vs Expected

Endpoint Expected Actual
GET /sse 200, streams endpoint event ✅ 200, event received
POST /messages?sessionId=<id> 200, JSON-RPC response ❌ 404
POST /messages (no session) 405 ✅ 405 (route exists)
GET /v1/status 200 ✅ 200

Suspected Root Cause

Likely a session affinity / distributed state issue introduced during or after the Cloud Run redeployment that fixed issue #305.

The MCP SSE transport works as follows:

  1. Client connects to /sse → server registers an in-memory session, streams endpoint event
  2. Client POSTs JSON-RPC messages to /messages?sessionId=<id>

If Cloud Run routes the SSE connection to Instance A (session registered there) but routes the subsequent POST to Instance B (no knowledge of that session), the POST gets 404.

Issue #305 noted session affinity: enabled — if the recent redeployment (ruvbrain-00159-cjl) reset or misconfigured session affinity, this would explain the symptom exactly.

Alternative: The session TTL may have been shortened to < the roundtrip time for a client to receive the SSE event and send the first POST.

Impact

  • All 37 brain_* MCP tools are non-functional on the hosted pi.ruv.io instance
  • Any Claude Code / MCP client configured to use https://pi.ruv.io/sse cannot call any tools
  • The REST API is a functional workaround but requires direct curl calls — not usable from MCP clients

Collective Stats at Time of Report

The underlying data is healthy and growing:

  • 5,190 memories (up from 3,154 in late March)
  • 8,694,179 graph edges (up from 2,758,924)
  • LoRA epoch 86 (up from 59)
  • avg_quality: 0.754

Suggested Fix

  1. Verify Cloud Run session affinity is still enabled on the current revision (ruvbrain-00159-cjl) — check --session-affinity flag
  2. If affinity is on: Check whether session state is correctly restored after the restart — in-memory sessions would not survive a restart even with affinity
  3. Longer term: Move session state to a persistent store (Redis or the existing ruvector DB) so sessions survive instance restarts and multi-instance routing

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions