neovim-use-mcp
An MCP server that edits files through a real Neovim instance, giving agents access to LSP diagnostics, formatting, code actions, and plugin commands.
README
neovim-use-mcp
An MCP server that edits files through a real Neovim instance. Your agent gets your language servers, your formatters and your plugins, not a plain text writer.
- Real LSP — diagnostics after every edit, rename, code actions, hover, references, document and workspace symbols.
- Format on save — edits write the buffer, so
BufWritePreruns and your formatter fires. - Plugin access —
nvim_commandandnvim_exec_luareach anything else. - stdio transport — the server starts with the agent and stops with it. It also stops the Neovim child process.
Requirements
| Item | Version | Note |
|---|---|---|
| Node.js | 18 or later | The server runs on Node. |
| Neovim | 0.10 or later | The server calls vim.lsp.get_clients. |
| A Neovim config | optional | Without one, you get edits but no LSP. |
Check your Neovim first:
nvim --version
nvim --headless --embed # must start and stay quiet; press Ctrl-C to stop
If that command prints errors, a plugin breaks headless start. Use
--config-mode minimal until you fix the plugin.
Install
From npm (recommended)
npm install -g neovim-use-mcp
Or use npx without a global install:
npx neovim-use-mcp
From source
git clone https://github.com/santanusinha/neovim-use-mcp.git
cd neovim-use-mcp
npm install
npm run build
The build writes dist/index.js. That file is the server.
Connect an agent
Add the server to your MCP client config.
With npx (no install needed):
{
"mcpServers": {
"neovim": {
"command": "npx",
"args": ["neovim-use-mcp"],
"env": {
"NVIM_MCP_CWD": "/absolute/path/to/your/project"
}
}
}
}
With a global install:
{
"mcpServers": {
"neovim": {
"command": "neovim-use-mcp",
"env": {
"NVIM_MCP_CWD": "/absolute/path/to/your/project"
}
}
}
}
From a local build:
{
"mcpServers": {
"neovim": {
"command": "node",
"args": ["/absolute/path/to/neovim-use-mcp/dist/index.js"],
"env": {
"NVIM_MCP_CWD": "/absolute/path/to/your/project"
}
}
}
}
[!TIP]
NVIM_MCP_CWDsets the project root. The language server uses that root to findtsconfig.json,go.mod,Cargo.tomland so on. If you leave it out, the server uses the directory that the agent starts it in.
The server needs no start or stop command. The agent starts it over stdio and stops it on exit. The server then stops its Neovim child process.
First run
Ask your agent to open a file:
Open
src/util/format.tswith the Neovim tools.
A correct answer looks like this:
Opened src/util/format.ts (buffer 1, 59 lines, filetype typescript).
LSP clients: null-ls, quick_lint_js, ts_ls
If you see No LSP client attached, read
When no LSP attaches.
How an agent should work
The tools follow one simple order.
- Open the file with
nvim_open_file. This starts the language server. Every LSP tool needs an open buffer. - Read with
nvim_read_fileto get numbered lines. - Edit with
nvim_edit_text,nvim_edit_linesornvim_insert_lines. Each edit saves the file and returns fresh diagnostics. - Fix any new diagnostic with
nvim_code_actions.
Three rules make the results much better:
- Use
nvim_rename_symbolfor a rename. Do not use a text replace. The LSP changes every file, and a text replace does not. - Use
nvim_edit_textwhen you know the exact text. It fails if the text is not unique, which stops a wrong edit. - Stage a multi-file change with
save: false, then callnvim_save_bufferonce per file.
Tools
Buffer and file
| Tool | Arguments | Purpose |
|---|---|---|
nvim_open_file |
path, wait_ms? |
Open a file and start its LSP client |
nvim_read_file |
path, start_line?, end_line? |
Read numbered lines |
nvim_edit_lines |
path, start_line, end_line, text, save? |
Replace a line range |
nvim_edit_text |
path, old_text, new_text, replace_all?, save? |
Replace exact text |
nvim_insert_lines |
path, line, text, save? |
Insert text before a line |
nvim_save_buffer |
path |
Write a buffer and run format on save |
nvim_list_buffers |
— | List open buffers |
LSP
| Tool | Arguments | Purpose |
|---|---|---|
nvim_diagnostics |
path?, severity?, wait_ms? |
Errors and warnings |
nvim_goto_definition |
path, line, column, wait_ms? |
Find a definition |
nvim_references |
path, line, column, wait_ms? |
Find every reference |
nvim_hover |
path, line, column, wait_ms? |
Type and documentation |
nvim_rename_symbol |
path, line, column, new_name |
Rename across the workspace |
nvim_code_actions |
path, line, column, apply_index? |
List or apply a quick fix |
nvim_format |
path, start_line?, end_line? |
Format a file or a range |
nvim_document_symbols |
path, wait_ms? |
Outline a file |
nvim_workspace_symbols |
query, wait_ms? |
Search symbols in the project |
Lines and columns start at 1.
Escape hatches
| Tool | Arguments | Purpose |
|---|---|---|
nvim_exec_lua |
code, args? |
Run Lua inside Neovim |
nvim_command |
command |
Run an Ex command, for example a plugin command |
These two tools run any code. Turn them off with --no-exec if the agent is
not trusted.
Recipes
Fix every error in a file
nvim_open_file path=src/app.ts
nvim_diagnostics path=src/app.ts severity=error
nvim_code_actions path=src/app.ts line=42 column=9 # list
nvim_code_actions path=src/app.ts line=42 column=9 apply_index=1
Rename a symbol everywhere
nvim_open_file path=src/util/format.ts
nvim_document_symbols path=src/util/format.ts # find the line
nvim_rename_symbol path=src/util/format.ts line=28 column=17 new_name=renderIssues
The tool returns the list of files that it changed and saved.
Change several places, then save once
nvim_edit_text path=src/a.ts old_text="foo(" new_text="bar(" save=false
nvim_edit_text path=src/a.ts old_text="= foo" new_text="= bar" save=false
nvim_save_buffer path=src/a.ts
Run a plugin command
nvim_command command="Telescope find_files"
nvim_exec_lua code="return vim.fn.getcwd()"
Options
Command line flags win over environment variables.
| Flag | Environment | Default | Meaning |
|---|---|---|---|
--mode |
NVIM_MCP_MODE |
embedded |
embedded spawns its own nvim; attach connects to a socket |
--socket |
NVIM_MCP_SOCKET |
— | Socket for attach mode |
--nvim |
NVIM_MCP_BIN |
nvim |
Path to the nvim binary |
--config-mode |
NVIM_MCP_CONFIG_MODE |
user |
user loads your config; minimal runs nvim --clean |
--no-exec |
NVIM_MCP_ALLOW_EXEC=0 |
exec on | Turn off nvim_exec_lua and nvim_command |
--cwd |
NVIM_MCP_CWD |
process cwd | Project root for the LSP |
--lsp-wait-ms |
NVIM_MCP_LSP_WAIT_MS |
3000 |
Default LSP wait |
--max-lines |
NVIM_MCP_MAX_LINES |
2000 |
Line cap for a read |
--debug |
NVIM_MCP_DEBUG |
off | Debug lines on stderr |
Watch the agent work
Attach mode shows you every edit in your own window, live.
# terminal 1
nvim --listen /tmp/nvim.sock
# agent config
node dist/index.js --socket /tmp/nvim.sock
In attach mode the server does not stop your Neovim on exit.
The default is embedded, always. The server spawns its own headless Neovim
and owns it. A socket in the environment does not change the mode, so the
server does not take over your editor when the agent runs in a Neovim
terminal. Ask for attach mode with --socket or --mode attach.
How lazy plugins load
Headless Neovim never fires UIEnter or VeryLazy, so a lazy.nvim setup keeps
nvim-lspconfig and mason asleep, and no language server attaches. On start
the server fires the VeryLazy event and forces those plugins to load. It then
waits for the client count to stay stable, so a slow real language server is not
missed behind a fast linter bridge.
Troubleshooting
When no LSP attaches
nvim_open_file reports No LSP client attached. Try these steps in order.
- Confirm the file type is correct. The tool prints it. An empty file type means Neovim did not detect the language.
- Raise the wait:
nvim_open_file path=... wait_ms=10000. A cold TypeScript or Rust server needs more than 3 seconds. - Check that
NVIM_MCP_CWDpoints at the project root. A server that cannot findtsconfig.jsondoes not start. - Start the server with
--debugand read stderr. It prints which plugins the warm-up loaded. - Confirm the server starts in your own Neovim for the same file.
The server does not start
Run it by hand and read stderr:
NVIM_MCP_DEBUG=1 node dist/index.js
A healthy start prints:
[nvim-mcp] ready (mode=embedded, exec=true, cwd=/your/project)
A plugin breaks headless Neovim
Use --config-mode minimal. The server then runs nvim --clean. You keep the
edit tools, but you lose your plugins and your LSP setup.
Diagnostics look wrong or stale
A linter bridge, for example null-ls with eslint_d, reports an error when
the project has no lint config. Add the config, or make the null-ls source
conditional on a config file. This is an editor setup problem, not a server
problem.
A tool says the text is not unique
nvim_edit_text refuses an ambiguous match on purpose. Add more context lines
to old_text, or set replace_all: true if you truly want every match.
Development
npm run dev # tsc --watch
npm test # vitest, uses a real headless nvim
npm run typecheck # tsc --noEmit
npm run inspect # MCP Inspector UI
Docker
A Dockerfile is included for isolated or CI usage. The image bundles Node and Neovim, but has no user Neovim config. Mount your config if you need LSP:
docker build -t neovim-use-mcp .
docker run --rm neovim-use-mcp
Releasing
Releases publish to npm through GitHub Actions with OIDC trusted publishing. No npm token is stored.
- Bump the version in
package.json. - Tag and push:
git tag v0.x.0 && git push origin v0.x.0. - Create a GitHub Release from the tag.
- The
Publish to npmworkflow builds, tests, and publishes automatically.
Licence
MIT
[!CAUTION] This is completely vibe coded. I guarantee absolutely nothing!!
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。