generated from coulomb/repo-seed
docs(dashboard): add Connecting to the Hub reference page
Covers local setup, remote (COULOMBCORE) one-liner registration, ops-bridge tunnel config, bridge states, MCP transport modes, and adding new remote hosts. Registered in Reference nav + reference.md index. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -43,6 +43,7 @@ export default {
|
||||
collapsible: true,
|
||||
open: false,
|
||||
pages: [
|
||||
{ name: "Connecting to the Hub", path: "/docs/connecting" },
|
||||
{ name: "Contributions", path: "/docs/contributions" },
|
||||
{ name: "Decision Health", path: "/docs/decisions-kpi" },
|
||||
{ name: "Decisions", path: "/docs/decisions" },
|
||||
|
||||
189
dashboard/src/docs/connecting.md
Normal file
189
dashboard/src/docs/connecting.md
Normal file
@@ -0,0 +1,189 @@
|
||||
---
|
||||
title: Connecting to the State Hub — Reference
|
||||
---
|
||||
|
||||
# Connecting to the State Hub — Reference
|
||||
|
||||
How Claude Code agents on local and remote machines connect to the State Hub API
|
||||
and its MCP server.
|
||||
|
||||
---
|
||||
|
||||
## Architecture overview
|
||||
|
||||
The State Hub runs on the **work laptop** only. Remote machines (COULOMBCORE,
|
||||
Railiance nodes) never run their own copy — they connect to the single source
|
||||
of truth via an encrypted SSH reverse tunnel managed by **ops-bridge**.
|
||||
|
||||
```
|
||||
Work laptop Remote machine (e.g. COULOMBCORE)
|
||||
───────────────────── ─────────────────────────────────
|
||||
PostgreSQL :5432 Claude Code session
|
||||
↑ │
|
||||
FastAPI :8000 ←── ops-bridge ────→ :18000 (API health / tools)
|
||||
MCP SSE :8001 ←── ops-bridge ────→ :18001 (MCP for Claude Code)
|
||||
```
|
||||
|
||||
Two services are exposed through the tunnel:
|
||||
|
||||
| Service | Local port | Remote port | Purpose |
|
||||
|---------|-----------|-------------|---------|
|
||||
| State Hub API | `8000` | `18000` | Health checks, direct curl queries |
|
||||
| MCP SSE server | `8001` | `18001` | Claude Code MCP integration |
|
||||
|
||||
---
|
||||
|
||||
## Local setup (work laptop)
|
||||
|
||||
### Start the services
|
||||
|
||||
```bash
|
||||
cd ~/the-custodian/state-hub
|
||||
|
||||
make api # FastAPI on :8000
|
||||
make mcp-http # MCP SSE server on :8001 (separate terminal)
|
||||
```
|
||||
|
||||
`make mcp-http` sets `MCP_TRANSPORT=sse MCP_PORT=8001` and starts the same
|
||||
MCP server that Claude Code uses locally in stdio mode. The SSE mode exposes
|
||||
the identical tool surface over HTTP.
|
||||
|
||||
### Start the tunnels
|
||||
|
||||
```bash
|
||||
bridge up # brings up both tunnels defined in ~/.config/bridge/tunnels.yaml
|
||||
bridge status
|
||||
```
|
||||
|
||||
Both tunnels must show `connected` (or `degraded` — see below) before remote
|
||||
agents can connect.
|
||||
|
||||
### Local Claude Code registration (stdio, default)
|
||||
|
||||
Claude Code on the work laptop uses the stdio MCP server. Registration is in
|
||||
`~/.claude.json` via `.mcp.json` at the repo root. No changes needed for local
|
||||
use.
|
||||
|
||||
---
|
||||
|
||||
## Remote setup (COULOMBCORE or any remote host)
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- ops-bridge tunnels running on the work laptop (`bridge status`)
|
||||
- SSH key `~/.ssh/id_ops` authorised on the remote host for user `tegwick`
|
||||
|
||||
### One-time MCP registration on the remote
|
||||
|
||||
```bash
|
||||
claude mcp add-json -s user state-hub \
|
||||
'{"type":"sse","url":"http://127.0.0.1:18001/sse"}'
|
||||
```
|
||||
|
||||
Restart Claude Code after running this. That's the only setup required — no
|
||||
Python, no repo clone, no local services.
|
||||
|
||||
### Verify connectivity
|
||||
|
||||
```bash
|
||||
# API reachable through tunnel?
|
||||
curl -s http://127.0.0.1:18000/state/health
|
||||
# → {"status":"ok","db":"connected"}
|
||||
|
||||
# MCP SSE endpoint reachable?
|
||||
curl -s --max-time 2 http://127.0.0.1:18001/sse | head -2
|
||||
# → event: endpoint
|
||||
# → data: /messages/?session_id=...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ops-bridge tunnel config
|
||||
|
||||
Tunnels are defined in `~/.config/bridge/tunnels.yaml` on the work laptop:
|
||||
|
||||
```yaml
|
||||
tunnels:
|
||||
state-hub-coulombcore: # API tunnel
|
||||
host: 92.205.130.254
|
||||
remote_port: 18000
|
||||
local_port: 8000
|
||||
ssh_user: tegwick
|
||||
ssh_key: ~/.ssh/id_ops
|
||||
actor: agent.claude-coulombcore
|
||||
health_check:
|
||||
url: http://127.0.0.1:18000/state/health
|
||||
interval_seconds: 30
|
||||
timeout_seconds: 5
|
||||
reconnect:
|
||||
max_attempts: 0 # retry forever
|
||||
backoff_initial: 5
|
||||
backoff_max: 60
|
||||
|
||||
state-hub-mcp-coulombcore: # MCP SSE tunnel
|
||||
host: 92.205.130.254
|
||||
remote_port: 18001
|
||||
local_port: 8001
|
||||
ssh_user: tegwick
|
||||
ssh_key: ~/.ssh/id_ops
|
||||
actor: agent.claude-coulombcore
|
||||
health_check:
|
||||
url: http://127.0.0.1:18001/sse
|
||||
interval_seconds: 30
|
||||
timeout_seconds: 5
|
||||
reconnect:
|
||||
max_attempts: 0
|
||||
backoff_initial: 5
|
||||
backoff_max: 60
|
||||
```
|
||||
|
||||
ops-bridge source: `~/ops-bridge` · SSH key: `~/.ssh/id_ops`
|
||||
|
||||
---
|
||||
|
||||
## Bridge states
|
||||
|
||||
| State | Meaning |
|
||||
|-------|---------|
|
||||
| `connected` | SSH process alive, health check passing |
|
||||
| `degraded` | SSH process alive, health check failing (SSE endpoint streams — not always a real error) |
|
||||
| `reconnecting` | SSH dropped, backoff loop active |
|
||||
| `stopped` | Not started or manually stopped |
|
||||
|
||||
The MCP SSE tunnel often shows `degraded` because the `/sse` health check
|
||||
receives a streaming response rather than a clean 200 — the tunnel is still
|
||||
functional. Confirm with `curl http://127.0.0.1:18001/sse` from the remote.
|
||||
|
||||
---
|
||||
|
||||
## MCP transport modes
|
||||
|
||||
The MCP server (`state-hub/mcp_server/server.py`) supports two transports
|
||||
selected by environment variable:
|
||||
|
||||
| Variable | Default | Effect |
|
||||
|----------|---------|--------|
|
||||
| `MCP_TRANSPORT` | `stdio` | stdio transport (local Claude Code) |
|
||||
| `MCP_TRANSPORT=sse` | — | SSE/HTTP transport for remote clients |
|
||||
| `MCP_PORT` | `8001` | Port for SSE mode |
|
||||
| `API_BASE` | `http://127.0.0.1:8000` | State Hub API URL the MCP server calls |
|
||||
|
||||
On a remote machine the MCP server process runs locally inside Claude Code — it
|
||||
does not run on the remote host. The transport layer (SSE over the tunnel)
|
||||
handles the connection.
|
||||
|
||||
---
|
||||
|
||||
## Adding a new remote host
|
||||
|
||||
1. Generate or reuse an SSH key pair (recommend `~/.ssh/id_ops`)
|
||||
2. Add the public key to the remote host's `~/.ssh/authorized_keys`
|
||||
3. Check port availability on the remote: `ssh user@host "ss -tlnp | grep 18001"`
|
||||
4. Add two tunnel entries to `~/.config/bridge/tunnels.yaml` (API + MCP)
|
||||
5. `bridge up <tunnel-name>` for each
|
||||
6. On the remote: `claude mcp add-json -s user state-hub '{"type":"sse","url":"http://127.0.0.1:18001/sse"}'`
|
||||
|
||||
---
|
||||
|
||||
*The State Hub runs on the work laptop only. Remote machines are read-only
|
||||
consumers connected via tunnel — they never own a copy of the database.*
|
||||
@@ -20,6 +20,7 @@ convention used in the Custodian State Hub.
|
||||
|
||||
| Page | What it covers |
|
||||
|------|---------------|
|
||||
| [Connecting to the Hub](/docs/connecting) | Local and remote connection setup, ops-bridge tunnels, MCP transports |
|
||||
| [Contributions](/docs/contributions) | Contribution types, lifecycle, third-party todo workflow |
|
||||
| [Decision Health](/docs/decisions-kpi) | KPI formula, avg resolve time, open-age colour thresholds |
|
||||
| [Decisions](/docs/decisions) | Decision types, statuses, escalation rules, filter bar |
|
||||
|
||||
Reference in New Issue
Block a user