buddy.nvim
Lua工具既可以作为键映射,也可以作为MCP工具。
______________________________________________________________________
我想在Neovim中使用AI工具,而不用去找另一个编辑器。所以我建造了这个。
buddy.nvim经营着一家 MCP服务器 Neovim内部。Claude、OpenCode或任何MCP客户端都可以连接并实际控制您的编辑器:读取缓冲区、编辑文件、运行命令、导航。不只是聊天。
你用Lua编写工具。它们充当MCP工具(AI称之为MCP工具) *和* 作为常规的Neovim插件(键盘映射、命令、autocmds)。相同的代码,两个接口。
______________________________________________________________________
安装
lazy.nvim
{
"arismoko/buddy.nvim",
dependencies = {
"nvim-mini/mini.nvim",
"nvim-neotest/nvim-nio",
},
lazy = false,
config = function()
require("buddy").setup({
auto_start = true,
port = 7234,
})
end,
}包装商nvim
use {
"arismoko/buddy.nvim",
requires = {
"nvim-mini/mini.nvim",
"nvim-neotest/nvim-nio",
},
config = function()
require("buddy").setup({
auto_start = true,
port = 7234,
})
end,
}手册
克隆到您的Neovim包目录:
git clone https://github.com/arismoko/buddy.nvim ~/.local/share/nvim/site/pack/plugins/start/buddy.nvim______________________________________________________________________
连接MCP客户端
buddy.nvim使用 HTTP+服务器发送事件(SSE) 与现代MCP客户端兼容。
有两种连接方式:
选项A:通过代理(推荐)
这 buddy-mcp-proxy 自动发现正在运行的Neovim会话,为您转发身份验证令牌,并支持在多个实例之间切换。不需要端口配置。需要 20+.
npm install -g buddy-mcp-proxyOpenCode
添加 ~/.config/opencode/opencode.jsonc:
{
"mcp": {
"vim": {
"type": "local",
"command": ["npx", "buddy-mcp-proxy"]
}
}
}克劳德桌面版
添加到您的Claude Desktop配置中:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - 视窗:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"vim": {
"command": "npx",
"args": ["buddy-mcp-proxy"]
}
}
}选项B:直接SSE连接
通过URL直接连接到特定的Neovim实例。更简单,但您必须知道端口,并且只能连接到一个会话。
备注:启用身份验证(默认)后,客户端必须发送 Authorization: Bearer 头球代理自动处理此问题;对于直接连接,可以配置客户端的auth标头,也可以在受信任的本地设置中禁用auth。小贴士:buddy.nvim工具仅在启用好友的Neovim会话实际运行时显示。如果您的客户端在Neovim之前启动,请先启动Neovim或使用 buddy-mcp-proxy,当会话联机时,它将自动连接。OpenCode
{
"mcp": {
"vim": {
"type": "remote",
"url": "http://127.0.0.1:7234/sse"
}
}
}克劳德桌面版
{
"mcpServers": {
"vim": {
"url": "http://127.0.0.1:7234/sse"
}
}
}______________________________________________________________________
安全
默认情况下,buddy.nvim绑定到 127.0.0.1 (仅限本地主机)。这意味着只有本地进程可以连接。
在局域网上曝光 (例如,对于远程AI客户端):
require("buddy").setup({
host = "0.0.0.0", -- Listen on all interfaces
})备注:默认情况下启用承载令牌身份验证(auth = true)但是没有TLS。如果你绑定到0.0.0.0,令牌以明文形式发送。考虑: - 使用防火墙限制访问 - 用于远程访问的SSH隧道 - 仅在受信任的网络上启用
______________________________________________________________________
内置工具
| 工具 | 说明 |
|---|---|
buffer | 读取、列出和获取缓冲区信息 |
edit | 插入、替换、删除缓冲区中的文本 |
command | 执行Ex命令 |
navigation | 跳转到文件、行、标记 |
search | 在当前缓冲区中查找并替换 |
grep | 使用vimgrep进行项目范围内的搜索 |
diagnostics | 从Neovim获取LSP诊断 |
window | 管理拆分和窗口布局 |
tab | 管理选项卡 |
fold | 控制码折叠 |
visual | 创建视觉选择 |
macro | 录制和播放宏 |
register | 访问Neovim注册表 |
status | 获取光标、模式、标记、寄存器 |
init | 脚手架新用户工具 |
看 docs/tools.md 有关MCP JSON示例的完整参考。
______________________________________________________________________
创建工具
工具已上线 lua/{plugin}/buddy.lua 文件夹。buddy.nvim会自动从运行时路径中发现它们。
格式1:工具列表
对于具有一个或多个独立工具的插件:
-- lua/my-plugin/buddy.lua
return {
tools = {
{
name = "greet",
description = "Say hello",
input_schema = {
type = "object",
properties = {
name = { type = "string", description = "Name to greet" },
},
required = { "name" },
},
run = function(args)
return "Hello, " .. args.name
end,
},
{
name = "farewell",
description = "Say goodbye",
input_schema = {
type = "object",
properties = {
name = { type = "string", description = "Name to farewell" },
},
required = { "name" },
},
run = function(args)
return "Goodbye, " .. args.name
end,
},
}
}格式2:单工具
对于只公开一个工具的插件:
-- lua/my-plugin/buddy.lua
return {
name = "my_tool",
description = "Does a thing",
input_schema = {
type = "object",
properties = {
message = { type = "string", description = "Message to show" },
},
required = {},
},
run = function(args)
vim.notify("Did the thing with: " .. (args.message or "nothing"))
return { success = true }
end,
}返回结果
工具归还 原始Lua值.buddy.nvim会自动将它们包装成MCP响应:
-- String → text content block
return "Hello, world!"
-- Table → JSON-encoded text content block
return { success = true, data = "result" }
-- nil → text content block with "nil"
return nil常见错误:不要像这样退回MCP信封 { content = { { type = "text", text = "..." } } } 从你的工具。只需返回原始值。buddy.nvim为你包装好了。添加关键点映射、命令、Autocmd
添加一个 setup block,你的工具就变成了一个合适的Neovim插件:
local function do_thing(args)
vim.notify("Did the thing with: " .. (args.message or "nothing"))
return { success = true }
end
return {
name = "my_tool",
description = "Does a thing",
input_schema = {
type = "object",
properties = {
message = { type = "string", description = "Message to show" },
},
required = {},
},
run = do_thing,
setup = {
keymaps = {
{ "n", "mt", function() do_thing({}) end, { desc = "My Tool" } },
},
commands = {
{ "MyTool", function(opts) do_thing({ message = opts.args }) end, nargs = "?" },
},
autocmds = {
{ "BufEnter", pattern = "*.md", callback = function() print("Markdown!") end },
},
},
}现在你的工具:
- AI呼叫时通过MCP工作
my_tool - 作品通过
mt键位映射 - 作品通过
:MyTool命令 - 运行于
BufEnter用于markdown文件
编辑文件时,关键帧映射和命令会自动更新。无需重新启动。
看 docs/creating-tools.md 完整的指南。
______________________________________________________________________
配置
require("buddy").setup({
host = "127.0.0.1", -- Bind address (default: "127.0.0.1" for security)
port = 7234, -- Server port (default: 7234)
auto_start = false, -- Start on VimEnter (default: false)
auth = true, -- Bearer token auth on HTTP endpoints (default: true)
watch = true, -- Hot reload file watching (default: true)
log_level = "info", -- Log level: "debug", "info", "warn", "error"
tools = {
disabled = {}, -- Disable specific tools: {"grep", "diagnostics", ...}
},
buffer = {
ignored_filetypes = {}, -- Hide filetypes from buffer listings
},
})看 docs/configuration.md 以获取完整的配置参考。
______________________________________________________________________
API
local buddy = require("buddy")
-- Start the MCP server
buddy.start()
-- Stop the server
buddy.stop()
-- Restart (stop + start)
buddy.restart()
-- Check status
local status = buddy.status()
-- { running = true, port = 7234 }
-- Call a tool programmatically
local result = buddy.call("buffer", { action = "list" })
-- Register a tool programmatically
buddy.register_tool({
name = "my_tool",
description = "Does something",
args = {
param = { type = "string", description = "A parameter" },
},
required = { "param" },
run = function(args) return { success = true, param = args.param } end,
})______________________________________________________________________
需求
- 新 0.10+
- mini.nvim (依赖性)
- 尼翁 (依赖关系--异步操作)
______________________________________________________________________
故障排除
端口已在使用中
Failed to bind to 127.0.0.1:7234 - address already in use另一个实例正在运行,或者另一个应用程序正在使用端口7234。停止其他进程或更改端口:
require("buddy").setup({ port = 7235 })工具未加载
检查 :messages 对于错误。常见问题:
- 工具文件中存在语法错误
- 缺失
name,description,或run领域 - 无效
input_schema
SSE连接失败
确保:
- buddy.nvim正在运行:
:lua print(require('buddy').status().running) - URL与您的配置匹配(默认值:
http://127.0.0.1:7234/sse) - 没有防火墙阻止连接
______________________________________________________________________
许可证
麻省理工学院
