StreamableHTTPSessionManager is an ASGI app — it sends its own
http.response.start and http.response.body messages via the scope/receive/send
triple. Wrapping it inside a @app.api_route FastAPI handler causes FastAPI
to try to finalize the response after the handler returns, emitting a
second http.response.start. uvicorn rejects this with:
RuntimeError: Unexpected ASGI message 'http.response.start' sent,
after response already completed.
Every POST /mcp raises, making the server unreachable from any MCP client
(tested with Claude Code 2.x against mcp==1.27.0).
Fix: mount the session manager as a Starlette Mount so it owns the
response cycle directly. Auth middleware still applies because
add_middleware attaches at the app level, wrapping all mounted sub-apps.
- Add parent_id to NodeUpdate schema in backend so PATCH /nodes/{id}
accepts it (was silently ignored before)
- Expose parent_id in update_node MCP tool schema so the MCP SDK
forwards it to the backend instead of stripping it
- Add regression tests in both backend and MCP layers
- Replace BaseHTTPMiddleware with pure ASGI middleware in auth.py to fix
the "Unexpected message: http.response.start" crash on SSE streams
- Migrate from SseServerTransport to StreamableHTTPSessionManager in main.py
- Add _slim_canvas() in tools.py to strip React Flow layout fields from
get_canvas responses (60-80% payload reduction)
- Update tests: assert canvas slimming, mock session_manager.handle_request
in auth tests to avoid uninitialized task group errors
Exposes homelab topology to MCP-compatible AI clients (Claude Code, etc.)
over LAN via HTTP/SSE on port 8001.
- New mcp/ service: FastAPI + mcp SDK, SSE transport
- Auth: X-API-Key for AI clients, X-MCP-Service-Key for backend (Docker-internal)
- Resources: canvas, nodes, edges, scan/pending, scan/runs
- Tools: create/update/delete nodes+edges, trigger scan, approve/hide devices
- Backend deps.py: accepts JWT or MCP service key (no plain-text password)
- 40 tests (auth, resources, tools) across asyncio + trio
- docker-compose.yml: mcp service on port 8001
- README: MCP setup section with Claude Code/Desktop config examples