@mrrlin-dev/mcp
v0.3.10
Published
CLI that runs the local Director bridge under PM2 and forwards chat turns to a locally-spawned Codex `app-server`. Installed globally on operator boxes via `npm install -g @mrrlin-dev/mcp` (the official install path; `pnpm install -g` also works if the op
Readme
@mrrlin-dev/mcp — Mrrlin Director Bridge
CLI that runs the local Director bridge under PM2 and forwards chat turns to a locally-spawned Codex app-server. Installed globally on operator boxes via npm install -g @mrrlin-dev/mcp (the official install path; pnpm install -g also works if the operator has pnpm setup configured).
Self-update & process hygiene
The bridge auto-picks up new @mrrlin-dev/mcp versions after npm install -g. No manual pm2 restart is required.
How it works
- L1 (self-update loop): every 15 minutes (env-tunable) the bridge hashes its own
bin.cjsand, on change, drains the current Codex turn cleanly and exits viabridgeShutdown. PM2 restarts. New code loads. - L2 (postinstall nudge):
npm install -g @mrrlin-dev/mcp@latesttriggers aSIGUSR2to every running PM2 bridge, collapsing the L1 wait to seconds. - L3 (in-chat update offer): every 6 hours the bridge checks
https://registry.npmjs.org/@mrrlin-dev/mcp/latest. When a newer version is published, on your next chat turn the Director asks: "Бачу що bridge на X, на npm уже Y — оновити зараз?". Say "yes" → Director runsnpm install -g @mrrlin-dev/mcp@latestitself. 48h cooldown if you decline. - L4 (process hygiene): the bridge refuses to start a second instance on the same port and warns about orphan
mrrlin-mcp director-bridgeprocesses at startup.
Env tuning
| Env var | Default | Purpose |
|---|---|---|
| MRRLIN_DIRECTOR_BRIDGE_SELF_UPDATE | (unset = on) | Set 0 to disable L1 (and silence L2 SIGUSR2 effect). |
| MRRLIN_DIRECTOR_BRIDGE_SELF_UPDATE_INTERVAL_MS | 900000 (15 min) | L1 hash-check interval. |
| MRRLIN_DIRECTOR_BRIDGE_REGISTRY_POLL_INTERVAL_MS | 21600000 (6 h) | L3.1 npm registry poll interval. |
| MRRLIN_DIRECTOR_BRIDGE_UPDATE_COOLDOWN_MS | 172800000 (48 h) | L3.2 in-chat update-offer cooldown. |
| MRRLIN_MCP_POSTINSTALL_SKIP | unset | Set 1 to skip the postinstall SIGUSR2 nudge. |
| CI | unset | Set 1 to skip the postinstall nudge in CI. |
PM2 ecosystem (automatic via mrrlin-mcp install-service)
mrrlin-mcp install-service writes ~/.mrrlin/ecosystem.config.cjs automatically. The generated config already includes kill_timeout: 10000 so the bridge has 10s to drain cleanly before PM2 SIGKILLs. Reference shape:
module.exports = {
apps: [{
name: "mrrlin-bridge",
script: "mrrlin-mcp",
args: "director-bridge",
interpreter: "none",
cwd: "<repo cwd>",
autorestart: true,
max_restarts: 10,
restart_delay: 3000,
kill_timeout: 10000,
env: { /* ... */ },
}],
};Verifying the self-update path is wired
Tail the bridge logs after a fresh start:
pm2 logs mrrlin-bridge --lines 50 | grep "bridge.self_update.startup"Expect a JSON-fielded line including version, binSha, selfUpdateEnabled, intervalMs. Any non-default tuning shows up here.
One-time cleanup for zombie processes
If you see multiple mrrlin-mcp director-bridge processes accumulating (pgrep -f "mrrlin-mcp director-bridge" returns > 1 PID), run once:
pm2 stop mrrlin-bridge
pkill -f "mrrlin-mcp director-bridge" || true
sleep 2
pm2 start ~/.mrrlin/ecosystem.config.cjsThis is only needed for the legacy population (bridges started before this self-update mechanism shipped). New installs won't produce zombies thanks to L1's bridgeShutdown exit path.
Update offer UX (L3) — what the operator sees
When a newer @mrrlin-dev/mcp is published and your bridge polls (within 6h):
- On your next chat turn, the Director weaves a yes/no question in: "Бачу що bridge на X, на npm уже Y — оновити зараз? (запущу
npm install -g @mrrlin-dev/mcp@latest)" - You reply "yes" / "так" / "ага" → Director runs the install via its shell tool, reports stdout + exit code in chat.
- L1 picks up the new
bin.cjs(or L2 SIGUSR2 nudges it sooner) → drain-on-quiet → PM2 restart → web reconnects. - You reply "later" → Director acknowledges and drops it for 48h.
- If the install fails (sudo, registry pin, network) → Director shows the error verbatim plus the manual command.
The Director never installs without explicit confirmation.
