docs(mcp): switch MCP transport stdio → SSE, update all references

MCP server is now a persistent SSE service on :8001 (make mcp-http),
independent of the Claude Code session. Re-registration is a single
claude mcp add-json command; no patch_mcp_cwd.py needed.

- Makefile: mcp-http is primary transport, add fuser restart + updated comment
- state-hub/README.md: stack table, MCP section, troubleshooting note updated
- CLAUDE.md (project): registration instructions rewritten for SSE

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-19 00:05:56 +01:00
parent a9ba6ffd42
commit 7c81f4fba0
3 changed files with 23 additions and 16 deletions

View File

@@ -64,7 +64,7 @@ make dashboard # Observable preview on :3000
make check # curl /state/health
```
The MCP server is registered in `.mcp.json` at the repo root. After `make install` creates `.venv`, restart Claude Code for `/mcp` to show `state-hub`.
The MCP server runs as a persistent SSE service (`make mcp-http`, port 8001). Registered at user scope via `claude mcp add-json -s user state-hub '{"type":"sse","url":"http://127.0.0.1:8001/sse"}'`. Restart the MCP server independently — no Claude Code restart needed.
### Docker Setup (WSL2, one-time)

View File

@@ -25,11 +25,11 @@ migrate:
seed:
uv run python scripts/seed.py
## MCP server in SSE/HTTP mode for remote Claude Code sessions (e.g. COULOMBCORE).
## Exposes the same tools as the stdio server over HTTP at http://127.0.0.1:8001/sse
## Remote clients connect via the ops-bridge tunnel (port 18001 on the remote host).
## Registration on the remote: claude mcp add-json -s user state-hub '{"type":"sse","url":"http://127.0.0.1:18001/sse"}'
## Start (or restart) the MCP SSE server on :8001 — primary transport for Claude Code.
## Remote clients (e.g. COULOMBCORE) connect via the ops-bridge tunnel (port 18001).
## Registration: claude mcp add-json -s user state-hub '{"type":"sse","url":"http://127.0.0.1:8001/sse"}'
mcp-http:
@fuser -k 8001/tcp 2>/dev/null && echo "Stopped running MCP server" || true
MCP_TRANSPORT=sse MCP_PORT=8001 uv run python mcp_server/server.py
dashboard:

View File

@@ -1,6 +1,6 @@
# State Hub v0.1
The operational brain of the Custodian: a local PostgreSQL database, FastAPI REST service, FastMCP stdio server for Claude Code, Observable Framework dashboard, and a `custodian` CLI.
The operational brain of the Custodian: a local PostgreSQL database, FastAPI REST service, FastMCP SSE server for Claude Code, Observable Framework dashboard, and a `custodian` CLI.
---
@@ -10,7 +10,7 @@ The operational brain of the Custodian: a local PostgreSQL database, FastAPI RES
|-------|-----------|------|
| Database | PostgreSQL 16-alpine (Docker) | `127.0.0.1:5432` |
| API | FastAPI + SQLAlchemy 2.0 async + asyncpg | `127.0.0.1:8000` |
| MCP server | FastMCP stdio (Claude Code native) | stdio |
| MCP server | FastMCP SSE | `127.0.0.1:8001` |
| Dashboard | Observable Framework | `127.0.0.1:3000` |
| CLI | `custodian` (Python, uv entry point) | — |
@@ -147,15 +147,22 @@ Returns a full snapshot in one call — used by both the MCP server and dashboar
## MCP Server
Registered in `~/.claude.json` at user scope. Config in `.mcp.json` (repo root).
Runs as a persistent SSE service on `:8001`, independent of the Claude Code session.
Restart it anytime without restarting Claude Code.
Uses absolute path + `PYTHONPATH` so `cwd` is not required:
```bash
make mcp-http # start (or restart) the MCP SSE server on :8001
```
Registered at user scope in `~/.claude.json`:
```json
{
"command": "/home/worsch/the-custodian/state-hub/.venv/bin/python",
"args": ["/home/worsch/the-custodian/state-hub/mcp_server/server.py"],
"env": { "PYTHONPATH": "/home/worsch/the-custodian/state-hub", "API_BASE": "http://127.0.0.1:8000" }
}
{ "type": "sse", "url": "http://127.0.0.1:8001/sse" }
```
To re-register from scratch:
```bash
claude mcp remove state-hub -s user 2>/dev/null || true
claude mcp add-json -s user state-hub '{"type":"sse","url":"http://127.0.0.1:8001/sse"}'
```
See `mcp_server/TOOLS.md` for the full tool reference card (30 lines, faster than reading `server.py`).
@@ -202,7 +209,7 @@ Prints API health, totals, and any blocking decisions.
| Script | Purpose |
|--------|---------|
| `scripts/register_project.sh` | Shell version of `custodian register-project` |
| `scripts/patch_mcp_cwd.py` | Patches `cwd` into `~/.claude.json` after `claude mcp add-json` drops it |
| `scripts/patch_mcp_cwd.py` | Legacy: patched `cwd` for the old stdio registration (no longer needed) |
| `scripts/project_claude_md.template` | CLAUDE.md template with `{PROJECT_NAME}`, `{DOMAIN}`, `{TOPIC_ID}` |
| `scripts/seed.py` | Insert the 6 canonical topics into a fresh database |
| `scripts/pull_image.py` | WSL2 workaround: pull Docker images via Python urllib with Range-request chunking |
@@ -231,5 +238,5 @@ rm -rf dashboard/src/.observablehq/cache/
## Known Issues / WSL2 Notes
- **TLS bad record MAC on large downloads**: WSL2 corrupts packets on big TCP transfers. Use `scripts/pull_image.py` instead of `docker pull` for future image pulls.
- **`claude mcp add-json` drops `cwd`**: Known Claude Code bug. Run `python3 scripts/patch_mcp_cwd.py` after any re-registration. The current `.mcp.json` uses absolute path + `PYTHONPATH` so `cwd` is not strictly needed.
- **MCP server is now SSE, not stdio**: Re-registration is `claude mcp add-json -s user state-hub '{"type":"sse","url":"http://127.0.0.1:8001/sse"}'`. The `patch_mcp_cwd.py` script and `.mcp.json` config are legacy artifacts from the old stdio setup.
- **AsyncSession concurrency**: SQLAlchemy 2.0 async sessions don't support concurrent operations. All queries in `/state/summary` run sequentially on a single session.