port-keeper-mcp
以下摘录自该仓库的 README(片段) · 在 GitHub 读完整 README →
**English** | 日本語 | 简体中文
A local ledger for development ports, with an MCP server on top, written in Go.
It gives every parallel coding agent its own set of ports, so each one can run
the whole stack at the same time as the others.
The problem
Coding agents pay off when you run them in parallel: five agents, five
branches, five working copies. git worktree gives each agent its own files.
It does not give each agent its own ports.
For a web service, that is where it stops. Every working copy carries the same
.env, so every copy's dev server, API and database ask for the same numbers.
The first agent to start gets them. The others hit address already in use,
or, worse, quietly run their tests against another agent's server and
database.
An agent that cannot bring up its own stack cannot check its own work. It can
write code, run static analysis, and unit-test the pure functions. It cannot
run an end-to-end test or any test that goes through a database: those need
the application running, which takes one environment per agent, each holding
as many ports as the stack has services. Without that, every agent queues for
the single environment that works. A small CLI tool never notices. A large web
service does: the work is parallel until it has to be verified, then it is
serial, and the reason for running agents in parallel is gone.
Agents run at the same time and do not talk to each other, so a naming
convention or a wiki table of port ranges will not hold. Handing out ports has
to work like a protocol: one place that every agent asks, and that answers
correctly when several ask at once.
What port-keeper does
port-keeper is that place.
- **One environment per agent.** Each working copy gets a *slot*, and each
slot gets its own block of ports. No two leases ever share a port, across
every project on the machine, even when several agents ask at the same
moment.
- **Agents ask instead of guessing.** Over MCP an agent gets the URL of a
service by name, and a hook puts the slot's ports into the agent's shell at
session start. A fresh worktree is refused the main copy's ports until it
has a slot of its own.
- **Nothing to keep running.** No daemon, no proxy, no network listener. Every
command opens the ledger, does its work and exits.
A project declares its services in a small manifest (names and env-var names,
never numbers). port-keeper hands each *slot* (a parallel copy of the project:
one per working copy, whether that is a clone or a git worktree) a block of
ports from a pool, writes them into your .env, and answers "what is the URL
of shop/5/admin?" from the CLI or over MCP. Neither you nor your coding agent
has to remember a port number again. It runs only when called, writes nothing
outside the ledger except the files you point it at inside your project, and
never opens a network listener.
See docs/DESIGN.md for the full design (Japanese).
Small on purpose
Before writing port-keeper we surveyed what already existed. The tools fall
into a few kinds: local proxies that hide ports behind hostnames and have to
stay running; agent-coordination platforms where ports are one feature among
sessions, locks and messaging; wrappers that want to launch your dev server
for you; free-port finders that keep no record of who owns what; and port
registries for agents that know nothing about parallel working copies or
.env files. Several are good at what they do. None of them was a ledger and
nothing but a ledger.
port-keeper is the simplest thing that solves the problem above:
- **One job.** It decides which port belongs to which service of which working
copy, and answers when asked. Starting servers stays with your task runner.
Pretty hostnames stay with a proxy, if you want one. port-keeper can feed
both and replaces neither.
- **Few parts.** One static binary, one SQLite file, one small manifest per
project. No daemon, no proxy, no DNS, no certificates, no account.
- **A small surface for agents.** Eight MCP tools, six of them on by default.
An agent takes in the whole interface at a glance, and it costs almost no
context.
- **Fits what you already run.** It writes plain environment variables into
.env, your shell, direnv or mise. Your dev command does not change.
docs/examples/ shows the wiring for mise, direnv, docker
compose, Vite, Playwright and reverse proxies.
- **Easy to leave.** Remove the MCP entry and the hook, then delete the binary
and the ledger file. The .env.local it wrote is an ordinary file and keeps