mcpr (CLI binary)
mcpr is a sidecar primitive in the envoy / pgbouncer mold. The launched PID
is the proxy itself — your host process supervisor (systemd, Docker,
Node child_process.spawn, terminal) owns the lifecycle.
- proxy:
mcpr proxy run <config>— runs the MCP gateway in the foreground. SIGTERM drains gracefully. - relay:
mcpr relay run <config>— tunnel relay server that accepts WebSocket connections and assigns subdomains. One per machine.
All state (lockfiles, config snapshots, sqlite store) lives under ~/.mcpr/.
Module Structure
Three-layer architecture: render (terminal output), logic (data operations), cmd (thin command dispatch).
mcpr-cli/src/
+-- main.rs # Entry point, gateway runtime
+-- state.rs # AppState (axum host container wrapping ProxyState)
+-- proxy.rs # Axum fallback handler → mcpr_core pipeline
+-- config.rs # CLI args (clap), TOML config, subcommands
+-- render.rs # All terminal output — tables, colors, formatting
+-- admin.rs # Health/readiness admin server
+-- proxy_lock.rs # Per-proxy lockfiles under ~/.mcpr/proxies/
+-- relay_lock.rs # Singleton relay lockfile under ~/.mcpr/relay/
+-- logic/ # Core business logic (no printing)
| +-- proxy.rs # Proxy lifecycle (stop, reload, list, delete)
| +-- relay.rs # Relay lifecycle (stop, status)
| +-- query.rs # DB engine, time parsing, threshold parsing
+-- cmd/ # Thin command handlers (logic → render)
+-- proxy.rs # Proxy lifecycle commands
+-- relay.rs # Relay lifecycle commands
+-- observe.rs # Observability commands (logs, stats, sessions, …)
+-- store.rs # Store maintenance commands
+-- setup.rs # Interactive setup flow (mcpr proxy setup)
The proxy engine (pipeline, middleware, ProxyState, forwarding,
rewrite, SSE, health) lives in mcpr_core::proxy. This binary
assembles a ProxyState + ProxyPipeline at boot, wires them into
axum via AppState, and drives every request through
AppState::pipeline.run.
The event bus (routes ProxyEvent to sinks) lives in mcpr_core::event;
sink implementations (stderr, sqlite, cloud) live in mcpr_integrations.
This binary just registers them via EventManager.