Skip to content

feat: SSE MCP transport — shared state with proxy on :9090#14

Merged
alderpath merged 1 commit into
masterfrom
mcp-sse-shared-state
Jun 16, 2026
Merged

feat: SSE MCP transport — shared state with proxy on :9090#14
alderpath merged 1 commit into
masterfrom
mcp-sse-shared-state

Conversation

@alderpath

Copy link
Copy Markdown
Contributor

Problem

The MCP server was stdio-only — a separate subprocess with its own memory. No shared state with the proxy (anti-decision, session hashes, response cache). Each agent needed its own subprocess.

Solution

SSE MCP runs on the same axum server as the proxy (port :9090), sharing the same process memory.

Architecture

Agent → GET /mcp/sse → SSE connection established
Agent ← event: endpoint /mcp/messages?sessionId=xxx
Agent → POST /mcp/messages?sessionId=xxx (JSON-RPC)
Agent ← event: message (JSON-RPC response via SSE)

Shared State

SSE MCP tools and proxy share the same memory space:

  • Anti-decision DB — heal tool knows past failure patterns
  • Session hashes — search ranked by session co-occurrence
  • Response cache — MCP tool results cached alongside proxy responses
  • Single port (:9090) for everything

Transport Options

| Transport | Config | When |
|---|---|---|
| SSE | url: http://127.0.0.1:9090/mcp/sse | init default (shared state) |
| Stdio | command: reliary-agent mcp | Always-available fallback |

Safety

  • Sessions auto-expire after 5 min idle
  • SSE disconnect cleans up immediately
  • tokio mpsc channels: no blocking, no deadlocks
  • Stdio stays forever as fallback

Code Changes

  • mcp.rs: refactored — extracted pure dispatch_tool_call() + tool_definitions() for reuse
  • mcp_sse.rs: new (~170 lines) — SSE handler + messages handler
  • proxy.rs: 2 new routes wired (/mcp/sse, /mcp/messages)
  • init.rs: inject_sse_mcp_server() — URL-based MCP config

Tests

86 tests pass (0 regressions). Zero build warnings.

mcp.rs: refactored — extracted pure dispatch_tool_call() + pub tool_definitions()
for shared use by stdio and SSE transports. Stdio is always-available fallback.

mcp_sse.rs: new module (~170 lines)
- GET  /mcp/sse — SSE connection with session ID + endpoint event
- POST /mcp/messages?sessionId=xxx — JSON-RPC dispatch, response via SSE
- tokio mpsc channel for async response delivery
- Auto-cleanup on SSE disconnect + 5-min idle TTL
- Inline UUID generation (zero external deps)

proxy.rs: wired SSE MCP routes into axum router alongside existing routes
- /mcp/sse (GET) and /mcp/messages (POST) coexist with daemon + proxy routes

init.rs: inject_sse_mcp_server() — configures agents with url-based MCP entry
('url': 'http://127.0.0.1:9090/mcp/sse') instead of subprocess. Falls back
to stdio injection if SSE fails.

Shared state with proxy: anti-decision DB, session hashes, response cache —
all accessible from SSE MCP tool dispatch (same process, same memory space).

86 tests pass (0 regressions). Zero build warnings.
@alderpath alderpath merged commit 955a366 into master Jun 16, 2026
4 checks passed
@alderpath alderpath deleted the mcp-sse-shared-state branch June 16, 2026 21:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant