mcpField
O
overseer-nvim-mcp

overseer-nvim-mcp

本地服务
github.com开发工具012 周前更新

关于 overseer-nvim-mcp

overseer-nvim-mcp 是供 Neovim 内编码 Agent 使用的 MCP 服务,可管理 overseer.nvim 任务,让 Agent 与用户共用任务列表来运行和监控长时命令。

主要功能

  1. 01列出任务和模板
  2. 02运行长时命令
  3. 03查看输出并等待匹配文本
  4. 04重启、停止和移除任务
  5. 05保护用户启动的运行中任务

适用场景

  1. 01将 Agent 启动的开发服务器纳入 Neovim 任务列表
  2. 02查看测试或文件监视器输出,避免轮询 Shell
  3. 03通过 MCP 客户端停止或重启 Agent 创建的任务

MCP 相关

该服务通过 stdio 向 MCP 客户端提供七种 overseer.nvim 任务管理工具。它经由 Neovim 的 `$NVIM` RPC 套接字连接,客户端必须运行在 Neovim 终端缓冲区内。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"impossiblecode-overseer-nvim": {
"command": "npx",
"args": [
"-y",
"overseer-nvim-mcp"
]
}
}
}
启动命令npx -y overseer-nvim-mcp

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npmoverseer-nvim-mcp0.2.3

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

overseer-nvim-mcp

一个 MCP 服务,让编码 Agent 能像你一样控制 overseer.nvim 任务:列出、查看输出、运行、重启、停止和释放。

Agent 将开发服务器作为 overseer 任务启动;用户在任务列表中查看其输出,并自行停止任务

npm CI license Glama score

为什么

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 配合使用

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:完整任务列表,格式为 JSON
  • overseer://task/{id}/output:某个任务的输出,包含状态行

服务器会枚举带有实时 ID 的各任务 URI,并支持补全,因此客户端可以直接提供现有任务,而不必让你自行查找。

注意事项

  • 通过 RPC 启动的任务,其输出会保存在策略的待处理缓冲区中,而非终端缓冲区,直到你打开 overseer 面板。overseer_tail 会读取这两个缓冲区、去除 ANSI 颜色代码和回车符,并裁掉 PTY 的空白填充,让你看到整洁的日志行,而不是空白网格的底部。
  • 任务运行时不会显示 exit_code;退出后才会显示。Agent 可据此区分任务是正常结束还是崩溃。

参与贡献

请参阅 CONTRIBUTING.md。发布流程通过 release-please 自动化,因此提交必须遵循 Conventional Commits。

许可证

MIT © Miguel Angelo Sepulveda

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。