@fevernova90/beckon-mcp
v0.3.2
Published
MCP server for beckon — drive local tunnels from an AI coding agent
Downloads
820
Maintainers
Readme
@fevernova90/beckon-mcp
MCP server for beckon — lets an AI coding agent open, list, and tear down local tunnels autonomously, with each git worktree auto-namespaced so parallel agents don't collide.
A local stdio MCP server that shells out to the beckon CLI. (beckon's tunnels are local
processes on your machine, so unlike a cloud MCP this runs locally alongside your dev loop.)
Prerequisites
- The
beckonCLI installed and onPATH(or setBECKON_BINto its path), and logged in once:beckon login. The MCP inherits that session — it never authenticates on its own.
Tools
| Tool | What it does |
|---|---|
| beckon_status | List all live tunnel sessions (dead ones auto-pruned). Call first. Pass repoPath to split the result into mine vs others. |
| beckon_init | Auto-author a tunnel.yaml from detection heuristics (.claude/launch.json, package.json dev scripts, .env.example). Call when beckon_up/beckon_plan report no tunnel.yaml, then call beckon_up. dryRun defaults to false; no --force is exposed (refuses an existing file). |
| beckon_up | Open a repo's tunnels in the background; returns the live, deterministic URLs. |
| beckon_plan | Predict a repo's URLs without opening (dry run) — write them into config first. |
| beckon_down | Tear down a repo/worktree's tunnel session. Refuses the STABLE session without confirmStable: true. |
beckon_status also takes an optional { repoPath, instance? } (same shape as the other tools).
With it, the response is { mine, others } instead of a flat { sessions }: mine is the one
session matching this repo's own app (read from its tunnel.yaml) + branch-derived instance;
others is every other session on the machine — other agents' worktrees, or the human's own
long-running tunnels. Since beckon_up/down are already scoped to one's own app+instance by
construction, this only affects what beckon_status shows, not what other tools can touch.
beckon_up/plan/down take { repoPath, instance? }. repoPath must be absolute — this
server's own working directory is arbitrary (wherever the agent's client launched it from), so a
relative path would resolve against the wrong place. repoPath is the directory containing
tunnel.yaml — usually the repo/worktree root, but in a monorepo it's the specific package
directory, not necessarily the git root. If that directory has no tunnel.yaml yet, beckon_up
fails with the exact format to create one — the agent has file-write access (this MCP doesn't),
so it creates the file itself and retries. The instance namespaces parallel worktrees/agents:
omit it and it's derived from the repo's git branch — main/master → the stable URL, a feature
branch → a per-branch URL ({app}-{service}-{branch}-{slug}). Pass instance to override. URLs are
deterministic, so the same repo+branch always yields the same URL.
Note: the instance is derived from the branch at call time, not pinned to the worktree
directory. Switching branches in place (not via a new worktree) while a tunnel is running leaves
the old branch's tunnel running, untracked by that directory's next beckon_down — tear it down
before switching, or check beckon_status for stragglers.
Two things worth knowing:
- Registration takes a moment.
beckon_upreturns as soon as the tunnel is recorded, but the actual edge registration (SSH handshake + auth) can trail by a second or two. If the URL isn't reachable immediately, wait briefly and retry before concluding it failed. beckon_downonmain/master(no instance) targets the stable URL — which may be a long-running tunnel the human started themselves, not something this agent opened. The CLI kills it unconditionally with no ownership check, sobeckon_downrefuses the stable session unless you passconfirmStable: true— a namespaced (feature-branch) session tears down normally, no flag needed. Checkbeckon_statusfirst if you're not sure you're the one who started it.
Register it with an agent
Build first (pnpm --filter @fevernova90/beckon-mcp build), then point your agent's MCP config at the bundle:
// e.g. .mcp.json (or: claude mcp add beckon -- node <abs>/packages/mcp/dist/server.js)
{
"mcpServers": {
"beckon": {
"command": "node",
"args": ["/abs/path/to/beckon/packages/mcp/dist/server.js"],
"env": { "BECKON_BIN": "beckon" }
}
}
}The server ships a built-in instructions playbook so the agent knows the
list → plan/up → use-URLs → down loop without being told.
Develop
pnpm --filter @fevernova90/beckon-mcp test # vitest (pure seams + injected-runner handlers)
pnpm --filter @fevernova90/beckon-mcp typecheck
pnpm --filter @fevernova90/beckon-mcp build # tsup → dist/server.js (self-contained, SDK bundled)