SuperAPI AI 工具集

port-keeper-mcp

port-keeper-mcp 是一个用 Go 编写的本地开发端口账本工具,并在此基础上提供 MCP 服务器。它能为每个并行编码代理(如克隆或 git worktree 工作副本)分配独立的端口块,把端口写入 .env 文件,并把服务名解析为 URL。该工具没有常驻守护进程、不监听网络、不保存密钥。当多个代理同时运行同一项目的多份工作副本时,它们会争夺相同的端口号,导致“地址已被占用”或测试连到别人的服务上。port-keeper 通过集中式账本来分配端口,确保机器上任何项目、任何槽位的租约都不会共享端口。代理可以通过 MCP 按名称获取服务 URL,也可通过命令行查询。项目通过小型清单声明服务(只写名称和环境变量名,不写端口号)。安装方式为单个静态二进制文件,支持自动脚本安装或手动安装,需要 Go 1.25 或更高版本构建。它只负责决定端口归属,不启动服务器、不提供反向代理和主机名。

访问官网

工具介绍

用途

port-keeper-mcp 解决的是并行编码代理场景下的开发端口冲突问题。当同时运行多个代理(例如五个代理、五个分支、五份工作副本)时,git worktree 能为每个代理提供独立的文件,但不会给它们独立的端口。每份工作副本携带相同的 .env,因此开发服务器、API 和数据库都会请求相同的端口号,先启动的代理获得端口,其他代理就会遇到“地址已被占用”,或者更糟——测试悄悄地在其他代理的服务器和数据库上运行。一个无法启动自身技术栈的代理无法验证自己的端到端测试或任何经过数据库的测试。工具的核心目标是:让每个代理拥有自己的一套端口,能够同时运行整个技术栈。

主要能力

  • 按槽位分配端口:每份工作副本获得一个槽位,每个槽位获得自己的端口块。机器上每个项目的任意两个租约都不会共享端口,即使多个代理同时请求也是如此。
  • 代理通过 MCP 询问而非猜测:代理可通过 MCP 按服务名称获取 URL,钩子可在会话启动时将槽位端口导出到代理的 shell 中。没有自己槽位的新工作副本会被拒绝使用主副本的端口。
  • 无需常驻进程:没有守护进程、没有代理、没有网络监听器。每条命令打开账本、执行操作并退出。
  • 项目清单声明服务:项目通过一个小型清单声明服务(只有名称和环境变量名,没有端口号)。port-keeper 为每个槽位从池中分配端口块,写入 .env,并能从 CLI 或 MCP 回答“shop/5/admin 的 URL 是什么”。
  • 代理接口精简:提供八个 MCP 工具,其中六个默认启用,代理可以快速理解整个接口,几乎不占用上下文。
  • 融入现有工具链:将普通环境变量写入 .env、shell、direnv 或 mise,开发命令无需改变。文档示例展示了与 mise、direnv、docker compose、Vite、Playwright 和反向代理的接线方式。
  • 易于移除:删除 MCP 条目和钩子,然后删除二进制文件和账本文件即可。它写入的 .env.local 是普通文件,仍可继续使用。

使用方式

port-keeper 是一个静态二进制文件,没有运行时依赖。把它放到 PATH 中,shell、代理钩子和 MCP 客户端都调用同一个 port-keeper 命令,因此一次安装即可服务三者,且机器上只有一个版本。

安装脚本会从最新的 GitHub Release 中选择适合操作系统和 CPU 的归档文件,除非其 SHA-256 与发布版的 checksums.txt 匹配,否则拒绝安装,并将 port-keeper 放入 ~/.local/bin。它从不请求 sudo。可设置 PORT_KEEPER_INSTALL_DIR 安装到其他地方,设置 PORT_KEEPER_VERSION 固定版本。再次运行即可更新;它会替换二进制文件,但不动账本和配置。

使用 Go 工具链(1.25 或更高版本)构建:

go install github.com/gridhra/port-keeper-mcp@latest

同一个项目的第二份工作副本获得自己的槽位:

port-keeper slot new

让编码代理拥有相同的视角:

# 注册 MCP 服务器(用户级,配置中没有端口号,只有命令)
claude mcp add port-keeper port-keeper mcp

然后在 ~/.claude/settings.json 中添加钩子。在 SessionStart 时,它会将当前槽位的端口导出到代理的 shell 中,并将项目和槽位添加到 Claude 的上下文中;在 CwdChanged(Claude cd 到另一个工作副本)时,它会将该工作副本的槽位端口替换导出的端口。在项目之外该命令不打印任何内容并退出 0,因此钩子永远不会让会话失败。

告诉代理工具的存在:代理只有知道工具存在才会使用它。在用户级指令文件中添加两行(对于 Claude Code,是 ~/.claude/CLAUDE.md;其他代理有等价文件),因为这两行适用于机器上的每个项目。如果运行多个代理(Claude Code、Codex、Cursor 等),在每个代理的全局指令中放入相同的块。MCP 注册是按客户端进行的,账本是共享的。

适用场景与限制

适用场景:需要同时运行多个代理、多个分支、多份工作副本的大型 Web 服务项目,尤其是需要运行端到端测试或经过数据库的测试时。典型用例包括:第五份工作副本的排班(port-keeper slot new hotfix)、无需记住端口即可打开正确的管理界面(port-keeper url shop/3/admin --open)、在两个应用环境之间共享数据库(port-keeper slot new 2 --infra-from 1)、找出谁占用了端口(port-keeper status 对比账本与实际监听并列出 PID)、在不破坏书签的情况下迁移现有项目(port-keeper pin web=3000 admin=3001 api=8080 --reason "docs and bookmarks")。

保证特性:任意两个租约不共享端口(由账本中的 UNIQUE 约束和每次分配周围的写事务保证);仅使用配置的池(默认 20000–31999),避免常规端口、macOS 服务占用的端口和操作系统临时端口范围,唯一离开池的方式是显式的、有理由的固定;槽位保留端口块直到释放,重启后依然如此;不会在背后回收端口(port-keeper gc 列出看起来被遗弃的槽位,仅在加 --yes 时释放);每份工作副本一个槽位;没有监听器、没有守护进程;不保存秘密(账本中没有密码、令牌或连接字符串列,.env 渲染永远不会写入被跟踪的文件)。

明确不支持的功能(Non-goals):不提供反向代理或命名主机(如 http://admin.shop.localhost),因为代理会引入常驻进程,当它停止时所有环境同时不可达,且浏览器按源(包括端口)隔离 cookie 和本地存储,不同端口恰好保持了槽位会话的隔离;没有容器镜像;没有 npx 启动器。port-keeper 只负责决定哪个端口属于哪个工作副本的哪个服务,启动服务器留给任务运行器。

限制:资料中未提供关于收费、价格、平台支持范围、性能指标或具体用户案例的更多细节。完整设计见 docs/DESIGN.md(日语)。