v0.5.0: route the neovim MCP through MetaMCP
mcp-neovim-server no longer runs as a per-session npx stdio child.
It is now a MetaMCP namespace upstream on emmett (one persistent
process), reached over Streamable-HTTP via the mcp-session-pool:
Claude Code -> pool.localhost:12010/p/neovim/mcp
-> MetaMCP neovim namespace -> mcp-neovim-server -> nvim socket
- .mcp.json: stdio npx server -> streamable-http pool endpoint
- agents/companion.md + skills: tool names are now 3-segment
(mcp__neovim__neovim__vim_*) — the MetaMCP aggregation shape; the
surface description and unavailability runbook updated for the
three-link path (nvim socket / MetaMCP / session)
- README: connection-path diagram
Host side (servers/emmett, deployed separately): neovim added to
services.mcp-session-pool.upstreams; metamcp.nix seeds the neovim
mcp_servers row + mapping and adds nodejs to the unit PATH.
This commit is contained in:
@@ -1,17 +1,43 @@
|
||||
# nvim-agentic-companion
|
||||
|
||||
A Claude Code plugin that turns the user's running Neovim into a first-class collaborator.
|
||||
A Claude Code plugin that turns the user's running Neovim into a first-class
|
||||
collaborator.
|
||||
|
||||
It assumes two things are already wired up:
|
||||
|
||||
1. **`mcp-neovim-server`** registered as an MCP server in Claude Code, pointed at the nvim RPC socket (default `/run/user/1000/nvim.sock`). NixVim's `extraConfigLuaPre` starts the server on that socket at editor startup.
|
||||
2. **`coder/claudecode.nvim`** loaded inside nvim, with `<leader>a*` keymaps wired (toggle, focus, send, accept/deny diff).
|
||||
1. **`mcp-neovim-server`** reaching the running nvim's RPC socket (default
|
||||
`/run/user/1000/nvim.sock`, created by NixVim's `extraConfigLuaPre`
|
||||
`serverstart` at editor startup). The plugin ships a `.mcp.json` that points
|
||||
the `neovim` MCP server at a **MetaMCP namespace** over Streamable-HTTP
|
||||
(`pool.localhost:12010/p/neovim/mcp`) rather than spawning a per-session
|
||||
`npx` stdio child — one persistent server, shared across sessions. Because of
|
||||
MetaMCP's aggregation, the tools surface as `mcp__neovim__neovim__vim_*`.
|
||||
2. **`coder/claudecode.nvim`** loaded inside nvim, with `<leader>a*` keymaps
|
||||
wired (toggle, focus, send, accept/deny diff).
|
||||
|
||||
This plugin doesn't ship those — it depends on them and ties them together with one agent and three skills.
|
||||
This plugin doesn't ship those — it depends on them and ties them together with
|
||||
one agent and three skills.
|
||||
|
||||
## Connection path
|
||||
|
||||
```text
|
||||
Claude Code session
|
||||
└─ .mcp.json → http://pool.localhost:12010/p/neovim/mcp (Streamable-HTTP)
|
||||
└─ mcp-session-pool (:12010, M=1 session pooler)
|
||||
└─ MetaMCP `neovim` namespace upstream
|
||||
└─ mcp-neovim-server (one persistent stdio child on emmett)
|
||||
└─ /run/user/1000/nvim.sock (nvim msgpack-RPC)
|
||||
└─ the running Neovim
|
||||
```
|
||||
|
||||
MetaMCP and the pool both run on emmett as systemd services under user `oleks`,
|
||||
so the per-user socket is directly reachable. If `mcp__neovim__neovim__*` tools
|
||||
are missing, walk the chain top-down: socket exists? `systemctl status metamcp`?
|
||||
session restarted since the wiring landed?
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
```text
|
||||
nvim-agentic-companion/
|
||||
├── .claude-plugin/plugin.json # manifest + userConfig (socket, config path)
|
||||
├── agents/
|
||||
@@ -24,13 +50,21 @@ nvim-agentic-companion/
|
||||
|
||||
## Agent
|
||||
|
||||
`companion` — answers questions about the *running* nvim ("what's bound to `<leader>ff`?", "is lualine actually using catppuccin-mocha?") and acts on it ("open neovim.nix at the lualine block"). It reads the declarative NixVim config as the source-of-truth for *why* things are set up the way they are, and the live editor for *what is actually loaded right now*.
|
||||
`companion` — answers questions about the *running* nvim ("what's bound to
|
||||
`<leader>ff`?", "is lualine actually using catppuccin-mocha?") and acts on it
|
||||
("open neovim.nix at the lualine block"). It reads the declarative NixVim config
|
||||
as the source-of-truth for *why* things are set up the way they are, and the
|
||||
live editor for *what is actually loaded right now*.
|
||||
|
||||
## Skills
|
||||
|
||||
- **`editor-introspect`** — read-only queries against the live nvim (keymaps, buffers, options, diagnostics, plugins, messages, cursor, selection).
|
||||
- **`editor-act`** — safe driving: open files, jump to definitions, trigger user keymaps, toggle UI. Does **not** edit buffer contents.
|
||||
- **`claude-code-handoff`** — when the work is "change code in this buffer," hand it to the in-editor Claude Code session so the user gets a diff to accept or reject inline.
|
||||
- **`editor-introspect`** — read-only queries against the live nvim (keymaps,
|
||||
buffers, options, diagnostics, plugins, messages, cursor, selection).
|
||||
- **`editor-act`** — safe driving: open files, jump to definitions, trigger user
|
||||
keymaps, toggle UI. Does **not** edit buffer contents.
|
||||
- **`claude-code-handoff`** — when the work is "change code in this buffer,"
|
||||
hand it to the in-editor Claude Code session so the user gets a diff to accept
|
||||
or reject inline.
|
||||
|
||||
## Why split it three ways
|
||||
|
||||
@@ -38,16 +72,20 @@ The companion's three jobs have different blast radii:
|
||||
|
||||
- *Reads* are free; do them eagerly.
|
||||
- *Edits to navigation/UI* are cheap to undo; do them when asked.
|
||||
- *Edits to code* deserve a diff and human review; route them through the inner Claude that already has the right UX for that.
|
||||
- *Edits to code* deserve a diff and human review; route them through the inner
|
||||
Claude that already has the right UX for that.
|
||||
|
||||
The skills enforce that separation so the agent doesn't drift into running `nvim_buf_set_text` directly when it should be sending to the Claude Code split.
|
||||
The skills enforce that separation so the agent doesn't drift into running
|
||||
`nvim_buf_set_text` directly when it should be sending to the Claude Code split.
|
||||
|
||||
## Configuration
|
||||
|
||||
| Key | Default | Purpose |
|
||||
| --------------- | ------------------------------------------------------ | ----------------------------------------------------------- |
|
||||
| `nvim_socket` | `/run/user/1000/nvim.sock` | Where the running nvim listens (must match the MCP server). |
|
||||
| `config_path` | `/home/oleks/projects/servers/emmett/nixos/neovim.nix` | The declarative NixVim source the companion cites from. |
|
||||
- **`nvim_socket`** — default `/run/user/1000/nvim.sock`. Where the
|
||||
running nvim listens; must match the socket `mcp-neovim-server`
|
||||
connects to (`NVIM_SOCKET_PATH` in the MetaMCP `neovim` upstream).
|
||||
- **`config_path`** — default
|
||||
`/home/oleks/projects/servers/emmett/nixos/neovim.nix`. The
|
||||
declarative NixVim source the companion cites from.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
Reference in New Issue
Block a user