# paulburgess1357/nvim-mcp [Health: Active]

**Category:** 💻 Developer Tools  
**Repository:** https://github.com/paulburgess1357/nvim-mcp  
**GitHub Stars:** 62  
**Views:** 3  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/paulburgess1357-nvim-mcp

## Description
MCP server providing AI assistants with full control of Neovim instances via msgpack-RPC. Read/edit buffers, run commands, send keys, query LSP diagnostics, and annotate code with highlights. No plugin required.

## Tools
Capabilities this server exposes over MCP:

- **connect** — Connect to a running Neovim instance over its Unix socket or TCP address.

    Call this before any other tool if the agent is not yet connected.
    Connection is persistent for the session; you only need to call it once
    unless you want to switch instances.

    Called with no arguments: auto-connects when exactly one instance
    is running; returns a list of instances when multiple are found.

    Optional selection (provide at most one):
    - index: pick from the listed instances (1-based).
    - socket_path: connect directly to a known Unix socket or host:port.
    - terminal_pid: find the Neovim instance whose process tree contains
      this PID (useful when Neovim runs inside a specific terminal).

    Returns {connected, cwd, file} on success, or {error} with details
    on failure (e.g. no instances found, connection timeout, bad index).
    
- **send_command** — Run one or more Vim ex commands in Neovim. This is a mutation tool —
    commands can modify buffers, files on disk, windows, and editor state.

    command: a single command string or a list of strings, without the
      leading ':'. E.g. "w", "e src/main.py", "42", "wincmd v",
      "lua vim.print(...)", or ["wincmd p", "e file.py", "wincmd p"].

    Use this for editor operations that don't have a dedicated tool
    (e.g. saving, opening files, splitting windows, setting options).
    Use `send_keys` instead when you need normal-mode motions or
    operator sequences. Use `find_and_replace_buf` or `write_full_buf`
    for buffer text edits — they are safer and provide undo.

    Returns {output} with the command's captured output, or {error}
    if the command failed. When given a list, returns a list of results
    in the same order; execution stops on the first error.
    
- **send_keys** — Send raw keystrokes to Neovim as if typed by the user. This is a
    mutation tool — keystrokes can modify buffers, change mode, and
    trigger editor actions.

    keys: a string of Vim keystrokes. Esc is prepended automatically, so
      input always begins in normal mode. Multi-mode sequences must be sent
      in a single call (e.g. "17GVG", not "17GV" then "G"). Use Vim
      notation for special keys (e.g. "<CR>", "<C-w>v", "<Tab>").

    Use this for normal-mode motions, visual selections, or operator
    sequences. Use `send_command` for ex commands, and
    `find_and_replace_buf` or `write_full_buf` for text edits — they
    are safer and provide structured results.

    Returns {sent} confirming the keys that were dispatched. Keystrokes
    are fire-and-forget; errors from the resulting Vim actions are not
    captured in the return value.
    
- **send_to_terminal** — Type text into a terminal buffer's running program (usually a shell)
    by writing to its job channel. This is a mutation tool — the text
    reaches the program's stdin as if typed, but is not executed unless
    submit is true.

    text: the text to send, raw. In most shells an embedded newline acts
      like pressing Enter, so multi-line text may execute line by line.
      When submit is false, trailing newlines are stripped so nothing
      runs by accident.
    terminal: which terminal to target — a buffer number or buffer name,
      as listed under `terminals` in `get_state` / `get_state_brief`.
      Names match exactly first, then by unique substring. Omit it when
      exactly one terminal exists; with several open, omitting it
      returns an error listing them.
    submit: false (default) leaves the text at the prompt for the user
      to review and press Enter. true appends a carriage return so the
      program executes it immediately. NEVER pass submit=true unless
      the user has explicitly asked for the command to be run — "put",
      "paste", "type", or "prepare" a command always means
      submit=false. Suggesting a command yourself is not permission to
      run it. When in doubt, use submit=false and let the user press
      Enter.

    Use this whenever text needs to go into a terminal. It works
    regardless of focus, mode, or visibility and never moves the user's
    cursor — unlike `send_keys`, which requires focusing the terminal
    and juggling modes. Terminal buffers cannot be edited with the
    buffer tools.

    Returns {sent, terminal, buf, submitted} on success — sent is the
    byte count actually written. On failure returns {error}, including
    a `terminals` list when the target was missing or ambiguous.
    
- **get_all_diagnostics** — Get LSP diagnostics from all open buffers in Neovim. Read-only.

    Use this for a project-wide overview of errors and warnings. Use
    `get_buf_diagnostics` instead when you only need diagnostics for a
    specific file — it is more focused and returns less data.

    Returns a list of {file, line, col, severity, message, source}.
    severity is one of "error", "warning", "info", "hint". Returns an
    empty list when there are no diagnostics. Results depend on which
    LSP servers are attached and which buffers are loaded in Neovim.
    
- **get_buf_diagnostics** — Get LSP diagnostics for a single Neovim buffer. Read-only.

    file: path relative to Neovim's cwd (as shown in `get_state` buffers).
      The buffer must already be open in Neovim; returns an error otherwise.

    Use this when you need diagnostics for one specific file. Use
    `get_all_diagnostics` instead for a project-wide overview.

    Returns a list of {file, line, col, severity, message, source}.
    severity is one of "error", "warning", "info", "hint". Returns an
    empty list when the buffer has no diagnostics.
    
- **find_and_replace_buf** — Find and replace text in a Neovim buffer. The edit happens in-memory
    and is fully undoable — nothing is written to disk until the user saves.

    file: path relative to Neovim's cwd (as shown in `get_state` buffers).
    old_string: the exact text to find. Must match exactly once in the
      buffer; returns an error if not found or if it matches multiple
      locations. Include surrounding lines to disambiguate.
    new_string: the replacement text.

    Creates the buffer if it doesn't already exist. Use this for targeted
    edits. Use `write_full_buf` instead when replacing the entire buffer
    content. Use `read_full_buf` or `read_buf_range` first if you need
    to see the current content before editing.

    Returns {start_line, lines_removed, lines_added, total_lines} on
    success, or {error} with a message on failure.
    
- **write_full_buf** — Replace the entire content of a Neovim buffer. The edit happens
    in-memory and is fully undoable — nothing is written to disk until
    the user saves.

    file: path relative to Neovim's cwd (as shown in `get_state` buffers).
    content: the full new text for the buffer.

    Creates the buffer if it doesn't already exist. Use this when you
    need to rewrite the whole file. Use `find_and_replace_buf` instead
    for targeted edits that preserve surrounding content.

    Returns {total_lines} with the new line count.
    
- **read_full_buf** — Read the full content of a Neovim buffer. Read-only; reads from
    Neovim's in-memory buffer, which may differ from the file on disk
    if there are unsaved changes.

    file: path relative to Neovim's cwd (as shown in `get_state` buffers).
      The buffer must already be open in Neovim; returns an error otherwise.

    Use this when you need to see the entire file. Use `read_buf_range`
    instead when you only need a specific section — it returns less data.

    Returns {lines, total_lines}. lines is a list of strings, each
    prefixed with its 1-based line number (e.g. "1: first line").
    
- **read_buf_range** — Read a specific line range from a Neovim buffer. Read-only; reads
    from Neovim's in-memory buffer, which may differ from the file on
    disk if there are unsaved changes.

    file: path relative to Neovim's cwd (as shown in `get_state` buffers).
      The buffer must already be open in Neovim; returns an error otherwise.
    start_line: first line to read (1-indexed, inclusive).
    end_line: last line to read (1-indexed, inclusive). Out-of-range
      values are clamped to the buffer bounds. If start_line > end_line
      they are swapped automatically.

    Use this when you only need a section of a file. Use `read_full_buf`
    instead when you need the entire buffer.

    Returns {lines, total_lines}. lines is a list of strings, each
    prefixed with its 1-based line number (e.g. "10: some code").
    
- **get_state** — Full snapshot of the current Neovim session. Read-only — does not
    modify any editor state.

    Use `get_state_brief` for quick orientation at the start of a turn.
    Use this when you need the complete picture: all window details,
    folds, marks, diagnostics summaries, highlights, virtual text, and
    indent settings.

    Returns: mode (normal/insert/visual/etc.), cwd, buffers (relative
    paths of all listed buffers), modified_buffers, current_tab, tab_count,
    and terminals — a list of open terminal buffers as {buf, name,
    visible}, present only when at least one exists (targets for
    `send_to_terminal`).

    windows — list of visible windows (current tab only). The active
    window is always first, the alternate window (previous) is second.
    Each window entry contains:
      file (path relative to cwd), filetype, total_lines, modified,
      buftype ("file" for normal buffers, "terminal", etc.),
      line, col, indent: {expandtab, shiftwidth, tabstop}.
      Optional per-window fields (present when applicable):
      - role: "active" or "alternate".
      - context: numbered lines surrounding the cursor.
      - selection: {start_line, start_col, end_line, end_col} in visual modes.
      - folds: list of [start, end] closed fold ranges.
      - diagnostics_summary: {error, warning, info, hint} counts.
      - marks: list of {mark, line, col} for lowercase (a-z) buffer marks.
      - mcp_highlights: list of {start_line, end_line, color} for active highlights.
      - mcp_virtual_text: list of {line, position, lines, color} for active virtual text.
    
- **get_state_brief** — Lightweight snapshot of the Neovim session for quick orientation.
    Read-only — does not modify any editor state.

    Use this at the start of each turn to see what the user is working
    on. Use `get_state` instead when you need the full picture: all
    windows, folds, marks, diagnostics summaries, highlights, virtual
    text, and indent settings.

    Returns: mode (normal/insert/visual/etc.), cwd, buffers (relative
    paths of all listed buffers), modified_buffers, and active_window:
    {file, filetype, total_lines, modified, buftype, line, col, context}.
    context is a short list of numbered lines around the cursor.

    If an alternate window exists, also returns alternate_window with
    the same fields. When terminal buffers exist, returns terminals — a
    list of {buf, name, visible} (targets for `send_to_terminal`).
    
- **highlight_range** — Add a colored line highlight to a Neovim buffer. This is a visual
    annotation only — it does not modify buffer content and is not
    persisted to disk. Highlights stack; calling this multiple times adds
    more highlights without removing previous ones.

    file: path relative to Neovim's cwd (as shown in `get_state` buffers).
      The buffer must already be open in Neovim; returns an error otherwise.
    start_line: first line to highlight (1-indexed, inclusive).
    end_line: last line to highlight (1-indexed, inclusive). Out-of-range
      values are clamped. If start_line > end_line they are swapped.
    color: a hex color (e.g. "#3b4048") or a Neovim highlight group name
      (e.g. "Comment", "DiagnosticError"). For groups, the resolved
      foreground color becomes the line background — so highlights adapt
      to the user's colorscheme. Defaults to "Comment". Unknown names
      (including bare color literals like "Red") return an error.

    Use this for a single highlight. Use `highlight_ranges` to apply
    multiple highlights in one call. Use `clear_highlights` to remove
    all highlights from a buffer.

    Returns {highlighted} with the number of lines highlighted, or
    {error} with a message on failure.
    
- **highlight_ranges** — Add colored line highlights to one or more Neovim buffers in a single
    call. This is a visual annotation only — it does not modify buffer
    content and is not persisted to disk. Highlights stack; calling this
    adds more highlights without removing previous ones.

    highlights: a list of dicts. Each dict requires:
      - file: path relative to Neovim's cwd (as shown in `get_state`).
        The buffer must be open in Neovim.
      - start_line: first line (1-indexed, inclusive).
      - end_line: last line (1-indexed, inclusive).
      - color (optional): hex color (e.g. "#5f3a3a") or Neovim highlight
        group name (e.g. "Comment", "DiagnosticError"). For groups, the
        resolved foreground color becomes the line background. Defaults
        to "Comment". Unknown names (including bare color literals like
        "Red") return an error. Out-of-range lines are clamped.

    Use this when you need to highlight several ranges at once (possibly
    across different files). Use `highlight_range` for a single range.
    Use `clear_highlights` to remove all highlights from a buffer.

    Returns a list of {highlighted} results in the same order as the
    input. Raises an error if any item is missing required keys.

    Example: [{"file": "foo.py", "start_line": 1, "end_line": 3,
               "color": "DiagnosticError"},
              {"file": "foo.py", "start_line": 10, "end_line": 12}]
    
- **clear_highlights** — Remove all MCP highlights from a Neovim buffer. Only removes
    highlights added by `highlight_range` or `highlight_ranges` — does
    not affect syntax highlighting, LSP highlights, or other plugins.
    Does not modify buffer content. Safe to call even if no highlights
    are present (returns {cleared: true} either way).

    file: path relative to Neovim's cwd (as shown in `get_state` buffers).
      The buffer must already be open in Neovim; returns an error otherwise.

    Use this to clean up highlights after an annotation workflow.
    Use `highlight_range` or `highlight_ranges` to add highlights.
    
- **add_virtual_text** — Add a virtual text annotation to a Neovim buffer. Visual only —
    the buffer's actual content is unchanged and nothing is written to
    disk. Annotations stack; multiple calls accumulate.

    file: path relative to Neovim's cwd (as shown in `get_state` buffers).
      The buffer must already be open in Neovim; returns an error otherwise.
    line: 1-indexed anchor line. Out-of-range values are clamped.
    text: list of strings, one per virtual line. Must be non-empty.
      When position is "eol", exactly one item is allowed.
    position: where the annotation appears relative to the anchor line.
      One of "eol" (after end of line), "above" (between previous and
      anchor lines), or "below" (between anchor and next lines).
      Defaults to "eol".
    color: a Neovim highlight group name (e.g. "Comment",
      "DiagnosticError") or a hex color (e.g. "#7a9ad4"). Defaults to
      "Comment", which adapts to the user's colorscheme. Unknown names
      (including bare color literals like "Red") return an error.

    Use this for a single annotation. Use `add_virtual_texts` for
    multiple annotations in one call. Use `clear_virtual_texts` to
    remove all MCP virtual text from a buffer.

    Returns {added: 1} on success, or {error} with a message on failure.
    
- **add_virtual_texts** — Add multiple virtual text annotations to Neovim buffers in a
    single call. Visual only — buffer content is unchanged. Annotations
    stack; calling this adds more without removing previous ones.

    items: a list of dicts. Each dict requires:
      - file: path relative to Neovim's cwd. Buffer must be open.
      - line: 1-indexed anchor line. Out-of-range values are clamped.
      - text: list of strings, one per virtual line. Non-empty.
        EOL position requires exactly one item.
      And optionally:
      - position: "eol" (default), "above", or "below".
      - color: hex color (e.g. "#7a9ad4") or Neovim highlight group
        name (e.g. "Comment", "DiagnosticError"). Defaults to "Comment".
        Unknown names (including bare color literals like "Red") return
        an error.

    Use this when you need to add several annotations at once (possibly
    across different files). Use `add_virtual_text` for a single
    annotation. Use `clear_virtual_texts` to remove all MCP virtual
    text from a buffer.

    Returns a list of {added: 1} results in input order. Raises a
    ValueError if any item is missing a required key. Iteration is
    sequential: if item N fails validation or the manager raises,
    items 0..N-1 have already been applied (call `clear_virtual_texts`
    to roll back).

    Example: [{"file": "foo.py", "line": 10, "text": ["this is the bug"]},
              {"file": "foo.py", "line": 20, "text": ["note one", "note two"],
               "position": "above", "color": "DiagnosticInfo"}]
    
- **clear_virtual_texts** — Remove all MCP virtual text annotations from a Neovim buffer.
    Only removes annotations added by `add_virtual_text` or
    `add_virtual_texts` — does not affect highlights, LSP virtual
    text, inlay hints, or other plugins. Does not modify buffer
    content. Safe to call even if no annotations are present
    (returns {cleared: true} either way).

    file: path relative to Neovim's cwd (as shown in `get_state` buffers).
      The buffer must already be open in Neovim; returns an error otherwise.

    Use this to clean up after an annotation workflow. Use
    `add_virtual_text` or `add_virtual_texts` to add annotations.
    

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `uvx` (confidence: high):

```json
"mcpServers": {
  "nvim-mcp": {
    "command": "uvx",
    "args": ["nvim-mcp"]
  }
}
```

## Documentation

## What paulburgess1357/nvim-mcp MCP server does

The paulburgess1357/nvim-mcp MCP server exposes a running Neovim session to an MCP-compatible AI client. It communicates through Neovim's native msgpack-RPC socket and does not require a Neovim plugin. The server can inspect the current editor context, change buffers, run editor commands, send input to terminal buffers, read LSP diagnostics, and place temporary annotations over code.

Use it when the agent needs awareness of the user's active editor state, including the current file, cursor context, mode, working directory, open buffers, windows, folds, selections, marks, modified buffers, and terminal buffers. It is also suitable for workflows where edits should remain in Neovim's undo history and stay unsaved until the user chooses to write them.

## How it works

The agent first calls `connect`. With no arguments, the server discovers running Neovim instances when exactly one is available; when several are found, it returns a list for selection. A client can also choose an instance by list index, Unix socket path, TCP address, or a terminal process ID. The connection remains active for the session unless the agent switches instances.

Read operations include lightweight and full state snapshots, complete buffer reads, line-range reads, and diagnostics for one buffer or all open buffers. Buffer paths are interpreted relative to Neovim's current working directory, and buffer-reading tools require the target buffer to already be open.

Mutating operations include Ex commands, raw Vim keystrokes, targeted replacement, and full-buffer replacement. The structured buffer-edit tools operate in memory and support undo; saving still requires an editor command or another user action. Keystrokes are dispatched without capturing errors produced by the resulting Vim actions, so structured tools are preferable when available.

## Setup and configuration

The README documents `uv` as the recommended launcher and provides this MCP registration command:

```json
{
  "command": "uvx",
  "args": ["nvim-mcp"]
}
```

The project also documents a Nix-based configuration using the repository's flake. Client-specific configuration guidance is provided for Cursor, Claude Code, Codex, Claude Desktop, OpenCode, and other MCP clients. Agent rules are recommended because they explain when and how the tools should be used.

The stated requirements are Linux, Python 3.10 or newer, and Neovim 0.11 or newer. Older Neovim versions can work with `--listen` and an address configuration, according to the project documentation. On many Linux systems, Neovim's Unix socket is discovered automatically.

## Tools and capabilities

The paulburgess1357/nvim-mcp MCP server provides tools for:

- Connecting to and selecting running Neovim instances.
- Reading full buffers or bounded line ranges from Neovim memory.
- Replacing one exact text match or rewriting an entire buffer with undo support.
- Running one or more Ex commands and sending normal-mode or multi-mode keystrokes.
- Sending text to a Neovim terminal buffer, either for review or immediate execution when explicitly requested.
- Retrieving diagnostics from a specific buffer or across all open buffers.
- Inspecting brief or complete session state, including windows, cursor context, folds, marks, and terminal targets.
- Adding and clearing line highlights and virtual text annotations without changing buffer contents.

Highlights and virtual text are visual-only, accumulate across calls, and are removed with their corresponding clear tools. They are not written to disk.

## Limitations and notes

The server controls a live editor session, so commands and keystrokes can change buffers, files, windows, and editor state. The project advises using it in a version-controlled directory because agents have broad Neovim access and can make mistakes. Terminal input is especially sensitive: text normally remains for review unless submission is explicitly enabled.

Diagnostics depend on the LSP servers attached to Neovim and the buffers currently loaded. Buffer tools address open Neovim buffers rather than arbitrary files on disk. Terminal buffers cannot be edited with the regular buffer-edit tools, and visual annotations do not persist after the relevant Neovim state is cleared or changed.

_Full upstream README: https://allmcps.com/mcp/paulburgess1357-nvim-mcp/readme_

