关于 overseer-nvim-mcp
overseer-nvim-mcp 是供 Neovim 内编码 Agent 使用的 MCP 服务,可管理 overseer.nvim 任务,让 Agent 与用户共用任务列表来运行和监控长时命令。
主要功能
- 01列出任务和模板
- 02运行长时命令
- 03查看输出并等待匹配文本
- 04重启、停止和移除任务
- 05保护用户启动的运行中任务
适用场景
- 01将 Agent 启动的开发服务器纳入 Neovim 任务列表
- 02查看测试或文件监视器输出,避免轮询 Shell
- 03通过 MCP 客户端停止或重启 Agent 创建的任务
MCP 相关
该服务通过 stdio 向 MCP 客户端提供七种 overseer.nvim 任务管理工具。它经由 Neovim 的 `$NVIM` RPC 套接字连接,客户端必须运行在 Neovim 终端缓冲区内。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
overseer-nvim-mcp
一个 MCP 服务,让编码 Agent 能像你一样控制 overseer.nvim 任务:列出、查看输出、运行、重启、停止和释放。

为什么
Agent 的 shell 工具和你的 overseer 任务列表属于彼此独立的执行环境。Agent 在自己的 shell 中启动的开发服务器不会显示在任务列表中,无法从任务列表中停止,而且会在会话结束时遗留进程树。你 启动的任务则能正常清理。这个项目弥合了这一差距:Agent 的长时间运行命令会成为真正的 overseer 任务。
要求
- 安装了 overseer.nvim 的 Neovim
(已针对
v2.1.0测试) - Node >= 22
- 在 Neovim 终端缓冲区内运行的 MCP 客户端
安装
该服务使用 stdio 通信,并由 MCP 客户端启动。命令始终相同:
npx -y overseer-nvim-mcp
客户端必须在 Neovim 终端缓冲区内运行;它继承的 $NVIM 套接字来自那里。工具会在下次会话启动时出现,因为 MCP 服务会在启动时连接。如果工具始终没有出现,通常是因为 $NVIM 没有传递到服务的环境中:没有它,服务不会注册任何工具,而且有些客户端会清除传递给服务的环境变量。
Claude Code
claude mcp add overseer -- npx -y overseer-nvim-mcp
Codex CLI
codex mcp add overseer -- npx -y overseer-nvim-mcp
然后在生成的 ~/.codex/config.toml 配置块中添加一行:
[mcp_servers.overseer]
command = "npx"
args = ["-y", "overseer-nvim-mcp"]
env_vars = ["NVIM"]
env_vars 行是必需的。Codex 只会向 stdio 服务传递固定白名单中的变量(HOME、PATH、TERM 等),而 $NVIM 不在其中;没有这一行,服务就不会注册任何工具。
Codex 也不会主动使用该服务;请参阅让 Agent 真正使用它。
Antigravity CLI
在 ~/.gemini/config/mcp_config.json 中:
{
"mcpServers": {
"overseer": {
"command": "npx",
"args": ["-y", "overseer-nvim-mcp"]
}
}
}
应使用这个用户级全局文件:CLI 的非交互式打印模式(agy -p)只会从该文件加载 MCP 服务;工作区级别的 .agents/mcp_config.json 会被静默忽略。
Antigravity 也不会主动使用该服务;请参阅让 Agent 真正使用它。
Gemini CLI
gemini mcp add overseer npx -y overseer-nvim-mcp
或者在 settings.json 中:
{
"mcpServers": {
"overseer": {
"command": "npx",
"args": ["-y", "overseer-nvim-mcp"]
}
}
}
opencode
在 opencode.json 中:
{
"mcp": {
"overseer": {
"type": "local",
"command": ["npx", "-y", "overseer-nvim-mcp"]
}
}
}
mcphub.nvim (codecompanion.nvim, avante.nvim)
在 mcphub 的服务配置中:
{
"mcpServers": {
"overseer": {
"command": "npx",
"args": ["-y", "overseer-nvim-mcp"],
"env": { "NVIM": "${NVIM}" }
}
}
}
env 块是必需的:mcp-hub 不会将自身的环境传递给它启动的服务,因此没有这一块,服务就看不到 $NVIM,也不会注册任何工具。该服务会操作启动 hub 的 Neovim 实例。在 Neovim 外部启动的 hub 没有 $NVIM 可供传递,mcp-hub 会将此服务报告为已断开连接,并显示 Variable 'NVIM' not found。
LazyVim 自带 overseer.nvim 扩展。
使用 :LazyExtras 启用它(选择 editor.overseer),重启 Neovim,然后像上文一样将服务添加到 MCP 客户端即可。无需进行其他设置;该服务会使用你已有的 overseer 配置。
工具
| 工具 | 用途 |
|---|---|
overseer_list_tasks | 列出任务及其 id、名称、状态、exit_code、cmd、cwd、耗时和 origin |
overseer_list_templates | 列出目录中的模板(npm、go-task、make、just、VS Code),包含 provider、desc、params |
overseer_tail | 查看任务输出及其状态;可阻塞等待某个模式出现 |
overseer_run | 启动长时间运行的命令:可使用原始 cmd 数组,或使用带 params 的 template |
overseer_restart | 根据 id 或名称子字符串重启任务 |
overseer_stop | 停止正在运行的任务 |
overseer_dispose | 停止任务并将其从列表中移除 |
最后三个工具接受 force;如果要停止的是你启动且仍在运行的任务,则必须提供该参数。
可使用数字 id 或不区分大小写的名称子字符串来指定任务,因此 Agent 可以说 "dev",而不必跟踪 id。
工作原理
传输通道是 $NVIM,这是 Neovim 导出的 RPC 套接字,会传递给它在终端缓冲区中启动的每个进程。MCP 客户端会继承该变量,而作为客户端子进程的此服务也会继承该变量。
其他一切都由此决定:
- 设置了
$NVIM时,服务会注册七个工具,每个工具都会通过 msgpack-RPC 对 overseer 执行一次nvim_exec_lua。 - 未设置
$NVIM时,服务不会注册任何工具,也不会干扰运行。它在 Neovim 外部运行时不会执行任何操作,而不会报错。
此处不会查找套接字:不会对 cwd 进行哈希处理,不会使用 lsof 或
pgrep。这些方法从根本上就有缺陷(cwd 哈希方案无法区分崩溃实例留下的过期套接字和仍在运行的套接字,还会取消链接正常工作的套接字;在 macOS 上,pgrep 不会搜索调用者自身的祖先进程,而这正是相关的 Neovim 实例)。$NVIM 从设计上避开了这两个问题。
所有用户输入(任务名称、命令、工作目录)都会作为 msgpack 参数传递,并在 Lua 中以 ... 的形式接收。任何内容都不会被插入 Lua 源代码,因此任务名称无法被转化为代码执行。
它与您共享任务列表,因此不会干扰您的任务
现在有两个写入者会操作任务列表,但只有一个写入者能看到它。以下两点可以避免出现问题:
- 子字符串匹配到多个任务时会报错,并列出候选项,要求使用数字 id。在单体仓库中,
"dev"可能匹配十几个名称;静默选择第一个,可能导致停止错误的任务。 - 任务会标记启动者。
overseer_list_tasks会将origin报告为agent或user;除非传入force,否则overseer_stop、overseer_restart和overseer_dispose会拒绝操作你自己启动且仍在运行的任务。已完成的任务不受限制,因为移除一行失效记录毫无代价。
这种不对称是有意为之。错误地拒绝操作只会多花一次调用。错误地停止任务会杀掉你的开发服务器,丢失它持有的状态,而且你本来也没有理由把它连接到 Agent。
overseer_run 用于启动不会自行退出的命令:开发服务器、文件监视器、带 --watch 的测试运行。自行结束的短命令应继续使用 Agent 的常规 shell 工具,这样输出就能直接返回。通过“启动后轮询”的方式执行耗时两秒的构建,反而更糟。
模板列表为空是正常的
overseer_list_templates 会原样返回 overseer 的各个 provider 发现的内容。
大多数仓库都没有声明可运行的内容,因此返回空列表。这是合理的结果,不是错误。这也是为什么 overseer_run 将原始 cmd 作为主要路径:在常见情况下,仅支持模板的设计将无法使用。
此服务不包含任何特定于 provider 的知识。它不会过滤或改写结果,包括一些任务运行器公开的仅用于帮助的条目,因为这样做就意味着要将某个 provider 的约定编码进服务,而该服务在从未听说过它的仓库中也必须表现一致。
每个条目包含的内容:
{
"name": "just fixture-just-generate",
"provider": "just",
"desc": "Generate output for a language",
"params": [{ "name": "lang", "type": "string", "required": true }],
"running_task_id": 128
}
- 当 provider 未提供描述时,
desc会显式设为null。 npm 和 make 从不提供描述;go-task 和 just 通常会提供。显式的 null 表示没有可读内容,而不是让你猜测某个字段是否在某处被丢弃了。 - 带描述的条目会排在前面。 这不代表任何 provider 的特性,只反映信息量。否则,同时有 Taskfile 和 package.json 的仓库会把有文档说明的部分埋在数十个没有描述的 npm 脚本名称之下。
params是模板接受的参数;required用于标记overseer_run在调用时不接受缺少的参数。将它们作为params传入。缺少参数时会报错并指出所需参数,而不是在你的编辑器中打开提示词。running_task_id会在同名任务已在运行时出现。这是按名称匹配的,因此可能会漏掉某些情况(带参数调用的模板会生成一个以解析后的命令命名的任务);但如果出现了它,就表示不要在现有开发服务器之上再启动一个。filter会将子字符串与名称和描述进行匹配。值得一用:包含三个任务运行器的单体仓库可能会返回远超 80 个条目。
让 Agent 真正使用它
在某些客户端上,这个过程是自动的。服务会在 initialize 结果中返回 MCP instructions,而会展示这些内容的客户端会将其放入 Agent 的系统提示词中,让 Agent 在真正会查看的地方看到,而不是埋在几十条工具描述里。它会说明生命周期边界(在这里运行长期任务,在 shell 中运行短命令),并告诉 Agent:重建命令前先检查模板,使用 wait_for 而不是轮询,只清理自己的任务。
当 $NVIM 未设置时,服务会隐藏这些 instructions,原因与不注册任何工具相同:没有收到工具的会话不应被告知如何使用它们。
instructions 能否传达到模型,决定了整个体验,而不同客户端的行为各异:
- Claude Code 会注入这些内容。Copilot CLI 会为你允许其 instructions 的服务注入内容(在脚本运行中使用
--allow-all-mcp-server-instructions)。 - Codex CLI 会向模型展示工具定义,但不会展示 instructions;在收到提示前不处理服务是一个已知的未解决问题。当被要求“启动开发服务器”时,它会在自己的 shell 中运行
npm run dev,而服务已连接且正常工作。 - Antigravity CLI 完全不会注入任何内容:它会将 instructions 和每个工具的 schema 写入
~/.gemini/antigravity-cli/mcp/overseer/下的文件,只有在有内容指向这些文件时,模型才会读取它们。同样的提示词,会得到同样的结果:在自己的 shell 中运行。
对于这两种客户端,你可以在提示词中点名 overseer(两者都能响应“在 overseer 中启动开发服务器”),或者在客户端实际读取的位置说一次:它的上下文文件。在 AGENTS.md(Codex)或 GEMINI.md(Antigravity)中添加一行,就能让同一个提示词改为完整地路由到 overseer:先检查模板,按名称运行任务,然后跟踪输出。
下面的 Markdown 就是这条一次性指令,应放入每个客户端的项目上下文文件中(CLAUDE.md、AGENTS.md、GEMINI.md,或你的客户端会读取的文件)。客户端会不断重新读取项目指令,因此其优先级高于服务能发送的任何内容:
## Long-running commands
Start dev servers, file watchers and `--watch` test runs with `overseer_run`,
not the shell. They then appear in my task list, I can stop them myself, and
their process trees get torn down properly instead of being orphaned.
Short commands that exit on their own stay on the shell: their output is
in-band there, which is what you want.
Check `overseer_list_templates` first. If the repo declares one that matches, run
it by name rather than reconstructing the command.
如果这样仍然不够,PreToolUse 钩子可以让行为变得确定。这个钩子会针对几种明确的情况阻止 shell,并告知 Agent 应改为怎么做。从小范围开始,只添加你实际遇到的模式,因为钩子误触发比没有钩子更糟:
#!/usr/bin/env bash
# ~/.claude/hooks/prefer-overseer.sh: exit 2 blocks the call and shows stderr
# to the agent. Receives the tool call as JSON on stdin.
cmd=$(jq -r '.tool_input.command // ""')
case "$cmd" in
*"vitest run"*) ;; # one-shot, stays on the shell
*" --watch"*|*"vitest"*|*"npm run dev"*|*"pnpm dev"*|*"yarn dev"*)
echo "This looks long-running. Use overseer_run so it lands in the task list and can be stopped." >&2
exit 2
;;
esac
exit 0
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [{ "type": "command", "command": "~/.claude/hooks/prefer-overseer.sh" }]
}
]
}
}
等待,而不忙等
手动驱动任务的 Agent 最后只能靠猜:启动任务、跟踪输出、什么也没看到,再跟踪一次,还是没有结果。它无法休眠,所以每次猜测都要经过一轮往返,你只能看着它们不断滚过。
overseer_tail 改为接受一个 wait_for 正则表达式。出现匹配的行、任务退出或达到 timeout_ms 时,它会立即返回,并说明发生了哪一种情况,因此不会把超时误认为成功:
overseer_tail { task: 48, wait_for: "ready - listening" }
status=RUNNING total=5 from=1 waited=matched
compiling... 0
compiling... 1
compiling... 2
ready - listening on http://localhost:3000
GET /route-4 200
total 是一个游标。将它作为 since 传回,就只会得到新增内容,而不是每次轮询都重新读取同一屏输出:
overseer_tail { task: 48, since: 5 }
status=RUNNING total=9 from=6
GET /route-5 200
GET /route-6 200
GET /route-7 200
GET /route-8 200
from 是输出块实际开始的索引。如果它大于 since + 1,说明两次调用之间有输出被滚过,因此你看到的是一个间隔,而不是连续的内容。
overseer_run 也会短暂等待,最多等待 settle_ms(默认值为 1500,设为 0 可禁用),并在任务产生输出或退出时立即返回。启动时就失败的命令会在这里报告失败,而不会像正常运行的开发服务器那样只返回一个简单的 ID。
**等待发生在 Node 中。**这个服务运行在你的编辑器内部,而 vim.wait 不会处理输入,因此在 Lua 中等待十五秒会让会话冻结十五秒。通过本地 socket 轮询可以让 Neovim 保持响应,你也不会看到这些往返过程。
斜杠命令和可附加资源
工具是 Agent 调用的内容。服务器还会发布两种由你驱动的内容。
提示词会显示为斜杠命令(在 Claude Code 中为 /mcp__overseer__...)。服务器会根据每次调用动态生成提示词,因此它们检查的是你当前的编辑器状态,而不是复述通用答案:
-
directory_local_task使用 overseer 自带的.nvim.lua中的register_template,为没有 npm 脚本、Makefile 或 Taskfile 的项目定义任务。它会检查exrc是否确实已启用,以及是否已存在.nvim.lua,并说明两件容易让正确配置看起来像是出了问题的事:重启 Neovim 后配置才会生效,而且 Neovim 会要求你对文件执行:trust。 -
diagnose解释为何 overseer 没有显示你预期的任务。Overseer 会记录每个提供程序为何没有贡献任何内容,而这个原因通常不可见:- `npm`: 11/11 available - `make`: 0/0 available - No Makefile found - `mise`: 0/0 available - Command "mise" not found这样便能区分“这里没有可读取的内容”和“未安装该运行器”,而空列表无法做到这一点。
资源可供附加,而非调用:
overseer://tasks:完整任务列表,格式为 JSONoverseer://task/{id}/output:某个任务的输出,包含状态行
服务器会枚举带有实时 ID 的各任务 URI,并支持补全,因此客户端可以直接提供现有任务,而不必让你自行查找。
注意事项
- 通过 RPC 启动的任务,其输出会保存在策略的待处理缓冲区中,而非终端缓冲区,直到你打开 overseer 面板。
overseer_tail会读取这两个缓冲区、去除 ANSI 颜色代码和回车符,并裁掉 PTY 的空白填充,让你看到整洁的日志行,而不是空白网格的底部。 - 任务运行时不会显示
exit_code;退出后才会显示。Agent 可据此区分任务是正常结束还是崩溃。
参与贡献
请参阅 CONTRIBUTING.md。发布流程通过 release-please 自动化,因此提交必须遵循 Conventional Commits。
许可证
MIT © Miguel Angelo Sepulveda
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。