Compare commits
2
Commits
03f8786d24
...
7fed3a2e77
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7fed3a2e77 | ||
|
|
bce9b82b66 |
No files matched your search
@@ -1,6 +1,6 @@
|
||||
# Neovim UX Protocol & Live Editing
|
||||
|
||||
Whenever you need to actively interact with the user's Neovim UI or dynamically inject code edits into their live buffers, use the nvim_execute_lua tool (the "God Mode" escape hatch).
|
||||
Whenever you need to actively interact with the user's Neovim UI or dynamically inject code edits into their live buffers, use the nvim_exec tool (with action 'lua') (the "God Mode" escape hatch).
|
||||
|
||||
## 1. Showing UI Feedback (Agent Notifications)
|
||||
The user has a global Lua table _G.gemini loaded in their Neovim environment. You can use it to pop up a floating notification window when you are starting a background task.
|
||||
|
||||
@@ -21,7 +21,7 @@ The Antigravity CLI (`agy`) acts as the MCP Client and automatically manages the
|
||||
When `agy` starts up, it reads `mcp_config.json`. If it finds `"win-nvim": { "command": "C:\\Users\\reazul.ashraf\\.local\\bin\\mcp-memory-nvim.exe" }`, it will spawn that binary as a background subprocess using standard `stdio`.
|
||||
|
||||
3. **Communication:**
|
||||
- The LLM requests to use a consolidated tool (e.g., `nvim_view` with action `goto_line`, or `nvim_execute_lua`).
|
||||
- The LLM requests to use a consolidated tool (e.g., `nvim_workspace` with action `focus`, or `nvim_exec`).
|
||||
- The `agy` CLI sends a JSON-RPC request to the `mcp-memory-nvim` subprocess via its `stdin`.
|
||||
- The Rust MCP Server receives the request, connects to the Neovim active socket/pipe (`~/.gemini/active_nvim.txt` or `\\.\pipe\nvim.*`), sends the Msgpack-RPC command, and writes the JSON-RPC response back to `stdout`.
|
||||
- The `agy` CLI reads the response from `stdout` and returns it to the LLM context.
|
||||
@@ -29,12 +29,10 @@ The Antigravity CLI (`agy`) acts as the MCP Client and automatically manages the
|
||||
## Capabilities & Requirements
|
||||
To use this architecture, Neovim must run the `gemini-integration.lua` script to broadcast its active socket to `~/.gemini/active_nvim.txt`.
|
||||
|
||||
The MCP server provides 7 cohesive domain tools:
|
||||
1. **`nvim_buffer`** (actions: `get_active`, `read`, `open`, `create_scratch`, `save`, `reload`, `close`, `list`, `search`)
|
||||
2. **`nvim_window`** (actions: `list`, `get_active`, `focus`, `split`, `close`)
|
||||
3. **`nvim_view`** (actions: `goto_line`, `get_cursor`, `get_viewport`, `get_selection`)
|
||||
4. **`nvim_diagnostics`** (actions: `get`, `set`, `set_quickfix`)
|
||||
5. **`nvim_visual`** (actions: `preview`, `extmark`, `highlight`, `clear_highlight`)
|
||||
6. **`nvim_execute_lua`** (direct Lua execution escape hatch)
|
||||
7. **`nvim_system`** (actions: `get_info`, `get_messages`, `send_to_terminal`)
|
||||
The MCP server provides 5 cohesive mega-tools:
|
||||
1. **`nvim_buffer`** (actions: `read`, `replace`, `save`, `undo`, `redo`, `create_scratch`)
|
||||
2. **`nvim_workspace`** (actions: `list_buffers`, `list_windows`, `focus`, `split`, `cwd`)
|
||||
3. **`nvim_intelligence`** (actions: `hover`, `definition`, `references`, `outline`, `query`, `diagnostics`, `rename`, `code_action`)
|
||||
4. **`nvim_ui`** (actions: `highlight`, `ghost_text`, `clear`)
|
||||
5. **`nvim_exec`** (actions: `lua`, `vimscript`, `terminal`)
|
||||
|
||||
@@ -16,9 +16,9 @@ File edits must use EXACTLY one of two paths:
|
||||
## 2. Strict Tool Adherence (No Raw Lua RCE)
|
||||
You must strictly use the specialized, sandboxed Neovim MCP tools:
|
||||
- `nvim_buffer`: For reading, writing, saving, and creating scratch buffers.
|
||||
- `nvim_window`: For creating splits and focusing panes.
|
||||
- `nvim_visual`: For highlighting diffs, adding ghost text, and showing previews.
|
||||
**DO NOT** use `nvim_execute_lua` to mutate editor state. It is restricted to **READ-ONLY** queries.
|
||||
- `nvim_workspace`: For creating splits and focusing panes.
|
||||
- `nvim_ui`: For highlighting diffs, adding ghost text, and showing previews.
|
||||
**DO NOT** use `nvim_exec` (action `lua`) to mutate editor state. It is restricted to **READ-ONLY** queries.
|
||||
|
||||
## 3. Headless Quarantine
|
||||
Headless mode (`nvim --headless`) is strictly banned for interactive edits.
|
||||
@@ -26,7 +26,7 @@ Headless mode (`nvim --headless`) is strictly banned for interactive edits.
|
||||
Headless instances are allowed ONLY for non-interactive background batch processing (e.g., project-wide formatting or linting).
|
||||
|
||||
## 4. UI Presentation & Chat Console Minimization
|
||||
Never output large plans, context blocks, or architectural discussions to the chat console if Neovim is running. You MUST use the `nvim_buffer` and `nvim_window` tools to open a vertical split (e.g., `Antigravity_Plan.md` scratch buffer) and present the markdown natively. Reserve the chat console strictly for brief confirmations.
|
||||
Never output large plans, context blocks, or architectural discussions to the chat console if Neovim is running. You MUST use the `nvim_buffer` and `nvim_workspace` tools to open a vertical split (e.g., `Antigravity_Plan.md` scratch buffer) and present the markdown natively. Reserve the chat console strictly for brief confirmations.
|
||||
|
||||
## 5. Visual Cues & Auto-Save
|
||||
When manipulating buffers via MCP:
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
When interacting with the user's Neovim editor (e.g., opening a file, moving the cursor, reading the active buffer, setting diagnostics), you MUST ALWAYS use the MCP tools provided by the `win-nvim` (Neovim) MCP server.
|
||||
|
||||
- You are strictly forbidden from using bash scripts, `nvim --server`, or other raw terminal/shell hacks to remote-control Neovim.
|
||||
- You must rely entirely on the consolidated MCP tool registry (`nvim_buffer`, `nvim_window`, `nvim_view`, `nvim_diagnostics`, `nvim_visual`, `nvim_execute_lua`, `nvim_system`).
|
||||
- You must rely entirely on the consolidated MCP tool registry (`nvim_buffer`, `nvim_workspace`, `nvim_intelligence`, `nvim_ui`, `nvim_exec`).
|
||||
- If the tool is eagerly loaded, use it natively as an agent tool. If lazy-loaded, invoke it via the `call_mcp_tool` mechanism.
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ Our current MCP ecosystem is highly advanced, utilizing a **Dual-Transport Leade
|
||||
* `process_logs`: Direct file seeking and daemon log management (`watch`, `get`, `clear`). Prevents LLMs from reading multi-megabyte log files. **Score: A**
|
||||
|
||||
### 2. Neovim IDE Integration (nvim-core)
|
||||
* `nvim_buffer`, `nvim_window`, `nvim_view`, `nvim_diagnostics`, `nvim_visual`, `nvim_execute_lua`, `nvim_system`.
|
||||
* `nvim_buffer`, `nvim_workspace`, `nvim_intelligence`, `nvim_ui`, `nvim_exec`.
|
||||
* **Review:** Exceptional human QoL. The agent interacts with the code where the human's eyes actually are. Ghost text and diagnostic extmarks provide an IDE-like experience usually reserved for closed-source tools like Cursor. **Score: S-Tier**
|
||||
|
||||
### 3. Clipboard & Workflow
|
||||
@@ -37,7 +37,7 @@ To push the system to the absolute bleeding edge of autonomous coding, I propose
|
||||
* **The Solution:** Using Tantivy and BERT embeddings in our backend. We index the AST blocks of the codebase in the background. The LLM can query *"Where is the auth token validated?"* and get the exact 3 relevant functions instantly.
|
||||
* **Impact:** Massive token cost reduction (no blind file reading). Instant T2R for codebase exploration.
|
||||
|
||||
### 3. `nvim_system` terminal execution (Interactive Execution QoL)
|
||||
### 3. `nvim_exec` terminal execution (Interactive Execution QoL)
|
||||
* **The Problem:** When the agent runs a background terminal command (`cargo build`, `npm run dev`), the output is hidden from the human, and interactive prompts cause the background task to hang indefinitely.
|
||||
* **The Solution:** Dispatch to Neovim terminal splits where the human can watch the tests run natively, interact with prompts, see ANSI colors, and interact seamlessly.
|
||||
* **Impact:** Massive Human QoL.
|
||||
|
||||
@@ -2,48 +2,22 @@
|
||||
|
||||
When connected to this Neovim MCP server (`win-nvim`), you have powerful tools to interact directly with the active Neovim editor.
|
||||
|
||||
## The Consolidated Tool Arsenal (v2)
|
||||
The server consolidates granular Neovim operations into 7 smart domain tools:
|
||||
- **`nvim_buffer`**: Buffer and file management.
|
||||
- `action: "open_file"`: Open file in buffer (args: `file`, `line`, `col`).
|
||||
- `action: "open"`: Open buffer (args: `bufnr`).
|
||||
- `action: "close"`: Close buffer (args: `bufnr`, `force`).
|
||||
- `action: "reload"`: Reload buffer from disk (args: `bufnr`).
|
||||
- `action: "save"`: Save buffer to disk (args: `bufnr`).
|
||||
- `action: "list"`: List all loaded buffers.
|
||||
- **`nvim_window`**: Window split and focus management.
|
||||
- `action: "split"`: Split window (args: `direction: "horizontal" | "vertical"`, `file`).
|
||||
- `action: "close"`: Close window (args: `winnr`).
|
||||
- `action: "list"`: List open windows.
|
||||
- `action: "get_active"`: Get active window details.
|
||||
- `action: "set_active"`: Set active window focus (args: `winnr`).
|
||||
- **`nvim_view`**: Editor viewport and navigation.
|
||||
- `action: "get_active_buffer"`: Get active buffer details.
|
||||
- `action: "get_cursor"`: Get current cursor line/col.
|
||||
- `action: "goto_line"`: Jump cursor to line (args: `line`, `col`).
|
||||
- `action: "get_viewport"`: Get visible line range in viewport.
|
||||
- `action: "get_messages"`: Get Neovim command-line messages.
|
||||
- **`nvim_diagnostics`**: LSP diagnostics querying and publishing.
|
||||
- `action: "get"`: Get diagnostics (args: `bufnr`, `severity`).
|
||||
- `action: "set"`: Set buffer diagnostics (args: `bufnr`, `diagnostics`).
|
||||
- **`nvim_visual`**: Visual highlighting, extmarks, and quickfix.
|
||||
- `action: "get_selection"`: Get current visual selection text and range.
|
||||
- `action: "highlight_lines"`: Highlight line ranges (args: `bufnr`, `hl_group`, `start_line`, `end_line`).
|
||||
- `action: "set_extmark"`: Place virtual text or sign extmarks (args: `bufnr`, `ns_id`, `line`, `col`, `opts`).
|
||||
- `action: "set_quickfix"`: Populate quickfix list (args: `items`, `title`).
|
||||
- **`nvim_execute_lua`**: God Mode arbitrary Lua evaluation.
|
||||
- Arguments: `code: String`.
|
||||
- **`nvim_system`**: System diagnostics and connection heartbeat.
|
||||
- `action: "ping"`: Heartbeat test.
|
||||
- `action: "status"`: Server and socket bridge health status.
|
||||
## The Consolidated Tool Arsenal (v3)
|
||||
The server consolidates granular Neovim operations into 5 smart mega-tools:
|
||||
- **`nvim_buffer`**: Buffer and file management. Actions: `read`, `replace`, `save`, `undo`, `redo`, `create_scratch`.
|
||||
- **`nvim_workspace`**: Window split and focus management. Actions: `list_buffers`, `list_windows`, `focus`, `split`, `cwd`.
|
||||
- **`nvim_intelligence`**: Code intelligence and LSP. Actions: `hover`, `definition`, `references`, `outline`, `query`, `diagnostics`, `rename`, `code_action`.
|
||||
- **`nvim_ui`**: Visual highlighting, diff previews, and ghost text. Actions: `highlight`, `ghost_text`, `clear`.
|
||||
- **`nvim_exec`**: Escape hatch for raw evaluation. Actions: `lua`, `vimscript`, `terminal`.
|
||||
|
||||
## 1. Using Consolidated Domain Tools First
|
||||
Always prefer the specific consolidated tools (like `nvim_buffer`, `nvim_window`, `nvim_visual`, etc.) over writing raw Lua scripts. These tools are strongly typed, tested, and safe.
|
||||
Always prefer the specific consolidated tools (like `nvim_buffer`, `nvim_workspace`, `nvim_ui`, etc.) over writing raw Lua scripts. These tools are strongly typed, tested, and safe.
|
||||
|
||||
## 2. Lua God Mode (`nvim_execute_lua`)
|
||||
If you need to access *any* Neovim API that does not have a dedicated tool (e.g., complex buffer edits, changing options, custom LSP interactions), you MUST use `nvim_execute_lua` as your escape hatch.
|
||||
## 2. Lua God Mode (`nvim_exec` with action `lua`)
|
||||
If you need to access *any* Neovim API that does not have a dedicated tool (e.g., changing options, setting autocmds), you MUST use `nvim_exec` with action `lua` as your escape hatch.
|
||||
**CRITICAL**: `nvim_exec` is restricted to **READ-ONLY** queries. Do NOT use it to mutate editor state.
|
||||
|
||||
### CRITICAL RULES for `nvim_execute_lua`:
|
||||
### CRITICAL RULES for `nvim_exec` (`lua`):
|
||||
1. **Never Block:** Never use interactive prompt functions or interactive confirmation flags in substitutions (e.g., `%s/old/new/gc`). This will cause the headless MCP bridge to deadlock forever.
|
||||
2. **Visual Feedback:** Always trigger a notification using `require("notify")("Antigravity: [Action]", "info", { title = "Antigravity" })`.
|
||||
3. **Auto-Save:** If you modify a file buffer, always save it using `vim.cmd('write')` within the same Lua script so external tools can see the changes, unless you explicitly want to pause for manual human review.
|
||||
@@ -57,4 +31,3 @@ While the headless background instance is great for autonomous, routine tasks, i
|
||||
|
||||
## 4. Tool Schema Discovery
|
||||
Do **NOT** grep or search the Rust source code to find tool schemas or arguments. All lazy-loaded MCP tool schemas are automatically cached as JSON files on your disk. To understand a tool's arguments, directly read `~/.gemini/antigravity-cli/mcp/win-nvim/<tool_name>.json` (or linux-nvim).
|
||||
|
||||
+176
-204
@@ -1083,208 +1083,125 @@ pub async fn run_mcp_loop(app_name: &str, app_version: &str) {
|
||||
jsonrpc: "2.0".to_string(),
|
||||
id,
|
||||
result: Some(json!({
|
||||
"tools": [
|
||||
{
|
||||
"name": "nvim_buffer",
|
||||
"description": "Unified buffer management: inspect, open, read, search, save, reload, or close Neovim buffers.",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": ["get_active", "read", "open", "create_scratch", "save", "reload", "close", "list", "search", "edit", "undo", "redo"],
|
||||
"description": "Action to perform on the buffer"
|
||||
},
|
||||
"file": { "type": "string", "description": "Target file path (for open, read, search)" },
|
||||
"buf_id": { "type": "integer", "description": "Buffer ID (for close, reload, or split)" },
|
||||
"steps": { "type": "integer", "description": "Number of undo/redo steps to apply (default: 1)" },
|
||||
"content": { "type": "string", "description": "Initial text content (for create_scratch)" },
|
||||
"name": { "type": "string", "description": "Buffer display name (for create_scratch)" },
|
||||
"filetype": { "type": "string", "description": "Filetype syntax (for open, create_scratch)" },
|
||||
"start_line": { "type": "integer", "description": "1-indexed start line (for read)" },
|
||||
"end_line": { "type": "integer", "description": "1-indexed end line (for read)" },
|
||||
"pattern": { "type": "string", "description": "Regex or substring pattern to search for (for search)" },
|
||||
"force": { "type": "boolean", "description": "Force reload or close (for reload, close)" },
|
||||
"edits": {
|
||||
"type": "array",
|
||||
"description": "Array of edits to apply sequentially (for edit). Grouped by file, applied in descending order.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file": { "type": "string", "description": "Target file path" },
|
||||
"start_line": { "type": "integer", "description": "1-indexed start line" },
|
||||
"end_line": { "type": "integer", "description": "1-indexed end line" },
|
||||
"replacement_content": { "type": "string", "description": "New content" },
|
||||
"expected_content": { "type": "string", "description": "Optional: exact content expected in the replacement range to prevent line drift corruption" }
|
||||
},
|
||||
"required": ["file", "start_line", "end_line", "replacement_content"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["action"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nvim_window",
|
||||
"description": "Manage Neovim windows and splits: list open windows, query or focus active window, create splits, or close windows.",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": ["list", "get_active", "focus", "split", "close"],
|
||||
"description": "Window operation to perform"
|
||||
},
|
||||
"win_id": { "type": "integer", "description": "Window ID to focus or close" },
|
||||
"file": { "type": "string", "description": "File to open in split" },
|
||||
"buf_id": { "type": "integer", "description": "Buffer ID to attach to split" },
|
||||
"direction": { "type": "string", "enum": ["vertical", "horizontal"], "description": "Split orientation (default: vertical)" },
|
||||
"force": { "type": "boolean", "description": "Force close window" }
|
||||
},
|
||||
"required": ["action"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nvim_view",
|
||||
"description": "Editor navigation and viewport introspection: jump to line, query cursor position, get visible viewport lines, or get visual selection.",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": ["goto_line", "get_cursor", "get_viewport", "get_selection"],
|
||||
"description": "Navigation/inspection action to perform"
|
||||
},
|
||||
"file": { "type": "string", "description": "File path (for goto_line)" },
|
||||
"line": { "type": "integer", "description": "Target line number (1-indexed, for goto_line)" }
|
||||
},
|
||||
"required": ["action"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nvim_diagnostics",
|
||||
"description": "LSP diagnostics and quickfix integration: fetch current diagnostics, inject LSP diagnostic markers, or populate the quickfix list.",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": ["get", "set", "set_quickfix"],
|
||||
"description": "Diagnostic action to perform"
|
||||
},
|
||||
"line": { "type": "integer", "description": "Line number (1-indexed, for set)" },
|
||||
"message": { "type": "string", "description": "Diagnostic warning/error message (for set)" },
|
||||
"items": {
|
||||
"type": "array",
|
||||
"description": "Quickfix entries (for set_quickfix)",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"filename": { "type": "string" },
|
||||
"lnum": { "type": "integer" },
|
||||
"text": { "type": "string" }
|
||||
},
|
||||
"required": ["filename", "lnum", "text"]
|
||||
}
|
||||
},
|
||||
"qf_action": { "type": "string", "enum": ["replace", "append", "prepend"], "description": "Quickfix list modification action (for set_quickfix)" }
|
||||
},
|
||||
"required": ["action"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nvim_visual",
|
||||
"description": "Visual feedback, syntax highlighting, ghost text extmarks, and diff preview overlays.",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": ["preview", "extmark", "highlight", "clear_highlight"],
|
||||
"description": "Visual feedback action"
|
||||
},
|
||||
"file_path": { "type": "string", "description": "File path (for preview)" },
|
||||
"start_line": { "type": "integer", "description": "Start line (1-indexed, for preview, highlight)" },
|
||||
"end_line": { "type": "integer", "description": "End line (1-indexed, for preview, highlight)" },
|
||||
"preview_content": { "type": "string", "description": "Proposed replacement code (for preview)" },
|
||||
"line": { "type": "integer", "description": "Line number (1-indexed, for extmark)" },
|
||||
"text": { "type": "string", "description": "Virtual ghost text to display (for extmark)" },
|
||||
"highlight_group": { "type": "string", "description": "Highlight group (for extmark, highlight, e.g. 'Comment', 'IncSearch')" },
|
||||
"buf_id": { "type": "integer", "description": "Buffer ID (for highlight, clear_highlight)" },
|
||||
"duration_ms": { "type": "integer", "description": "Auto-clear duration in ms (for highlight, default: 5000)" }
|
||||
},
|
||||
"required": ["action"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nvim_execute_lua",
|
||||
"description": "Execute arbitrary Lua code directly in the active Neovim session. Primary tool for editing files via vim.api.nvim_buf_set_lines, querying editor state, and triggering notifications.",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "string",
|
||||
"description": "The Lua code string to execute in Neovim"
|
||||
}
|
||||
},
|
||||
"required": ["code"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nvim_system",
|
||||
"description": "System diagnostics, terminal interaction, and editor notification messages.",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": ["get_info", "get_messages", "send_to_terminal"],
|
||||
"description": "System action to perform"
|
||||
},
|
||||
"command": { "type": "string", "description": "Shell command to send (for send_to_terminal)" },
|
||||
"tail": { "type": "integer", "description": "Number of message lines to return (for get_messages)" }
|
||||
},
|
||||
"required": ["action"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nvim_lsp",
|
||||
"description": "Language Server Protocol integration for semantic queries and safe workspace-wide refactoring.",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": ["rename", "definition", "references", "hover", "code_action"],
|
||||
"description": "LSP action to perform"
|
||||
},
|
||||
"file": { "type": "string", "description": "Target file path" },
|
||||
"line": { "type": "integer", "description": "1-indexed line number" },
|
||||
"col": { "type": "integer", "description": "0-indexed column number" },
|
||||
"new_name": { "type": "string", "description": "New name for rename action" }
|
||||
},
|
||||
"required": ["action"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nvim_ast",
|
||||
"description": "Tree-sitter AST queries for semantic code exploration and outlining.",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": ["query", "outline"],
|
||||
"description": "AST action to perform"
|
||||
},
|
||||
"file": { "type": "string", "description": "Target file path" },
|
||||
"query": { "type": "string", "description": "Tree-sitter query string" },
|
||||
"preset": { "type": "string", "description": "Query preset (e.g., 'functions', 'classes')" }
|
||||
},
|
||||
"required": ["action"]
|
||||
}
|
||||
}
|
||||
]
|
||||
"tools":
|
||||
[
|
||||
{
|
||||
"name": "nvim_buffer",
|
||||
"description": "Core Text Editing: read, replace, save, and manipulate Neovim buffers in memory.",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": ["read", "replace", "save", "undo", "redo", "create_scratch"],
|
||||
"description": "Action to perform on the buffer"
|
||||
},
|
||||
"file": { "type": "string", "description": "Target file path (for read, replace, save)" },
|
||||
"start_line": { "type": "integer", "description": "1-indexed start line (for read)" },
|
||||
"end_line": { "type": "integer", "description": "1-indexed end line (for read)" },
|
||||
"content": { "type": "string", "description": "Initial text content (for create_scratch)" },
|
||||
"name": { "type": "string", "description": "Buffer display name (for create_scratch)" },
|
||||
"steps": { "type": "integer", "description": "Number of undo/redo steps to apply (default: 1)" },
|
||||
"edits": {
|
||||
"type": "array",
|
||||
"description": "Array of edits to apply sequentially (for replace). Grouped by file, applied in descending order.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"file": { "type": "string" },
|
||||
"start_line": { "type": "integer" },
|
||||
"end_line": { "type": "integer" },
|
||||
"replacement_content": { "type": "string" },
|
||||
"expected_content": { "type": "string" }
|
||||
},
|
||||
"required": ["file", "start_line", "end_line", "replacement_content"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["action"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nvim_workspace",
|
||||
"description": "Window & Editor State: list buffers, windows, focus splits, and manage cwd.",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": ["list_buffers", "list_windows", "focus", "split", "cwd"],
|
||||
"description": "Workspace operation to perform"
|
||||
},
|
||||
"win_id": { "type": "integer", "description": "Window ID to focus" },
|
||||
"file": { "type": "string", "description": "File to open in split" },
|
||||
"direction": { "type": "string", "enum": ["vertical", "horizontal"], "description": "Split orientation (default: vertical)" },
|
||||
"path": { "type": "string", "description": "Target directory (for cwd action)" }
|
||||
},
|
||||
"required": ["action"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nvim_intelligence",
|
||||
"description": "Code Semantics: LSP queries (hover, definition, references, code_action, rename, diagnostics) and AST outlining/queries.",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": ["hover", "definition", "references", "outline", "query", "diagnostics", "rename", "code_action"],
|
||||
"description": "Intelligence action to perform"
|
||||
},
|
||||
"file": { "type": "string", "description": "Target file path" },
|
||||
"line": { "type": "integer", "description": "1-indexed line number (for LSP)" },
|
||||
"col": { "type": "integer", "description": "0-indexed column number (for LSP)" },
|
||||
"new_name": { "type": "string", "description": "New name (for rename action)" },
|
||||
"query": { "type": "string", "description": "Tree-sitter query string (for AST query)" },
|
||||
"preset": { "type": "string", "description": "Query preset (e.g., 'functions', 'classes' for AST query)" }
|
||||
},
|
||||
"required": ["action"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nvim_ui",
|
||||
"description": "Visual Feedback: communicating visually with the human user via highlights and ghost text.",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": ["highlight", "ghost_text", "clear"],
|
||||
"description": "UI action"
|
||||
},
|
||||
"buf_id": { "type": "integer", "description": "Buffer ID to apply to" },
|
||||
"start_line": { "type": "integer", "description": "1-indexed start line (for highlight)" },
|
||||
"end_line": { "type": "integer", "description": "1-indexed end line (for highlight)" },
|
||||
"line": { "type": "integer", "description": "1-indexed line number (for ghost_text)" },
|
||||
"text": { "type": "string", "description": "Virtual text to display (for ghost_text)" },
|
||||
"highlight_group": { "type": "string", "description": "Highlight group (e.g. 'Comment', 'IncSearch')" },
|
||||
"duration_ms": { "type": "integer", "description": "Auto-clear duration in ms (for highlight, default: 5000)" }
|
||||
},
|
||||
"required": ["action"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nvim_exec",
|
||||
"description": "The Escape Hatch: execute lua read-only queries, run vimscript commands, or send commands to the terminal.",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"action": {
|
||||
"type": "string",
|
||||
"enum": ["lua", "vimscript", "terminal"],
|
||||
"description": "Execution action"
|
||||
},
|
||||
"code": { "type": "string", "description": "Lua code or Vimscript command to execute" },
|
||||
"command": { "type": "string", "description": "Shell command to send (for terminal)" }
|
||||
},
|
||||
"required": ["action"]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
})),
|
||||
error: None,
|
||||
}).await;
|
||||
@@ -1297,8 +1214,42 @@ pub async fn run_mcp_loop(app_name: &str, app_version: &str) {
|
||||
|
||||
let action = args.get("action").and_then(|v| v.as_str()).unwrap_or("");
|
||||
|
||||
match name {
|
||||
"nvim_buffer" => match action {
|
||||
let (mapped_name, mapped_action) = match (name, action) {
|
||||
("nvim_buffer", "read") => ("nvim_buffer", "read"),
|
||||
("nvim_buffer", "replace") => ("nvim_buffer", "edit"),
|
||||
("nvim_buffer", "save") => ("nvim_buffer", "save"),
|
||||
("nvim_buffer", "undo") => ("nvim_buffer", "undo"),
|
||||
("nvim_buffer", "redo") => ("nvim_buffer", "redo"),
|
||||
("nvim_buffer", "create_scratch") => ("nvim_buffer", "create_scratch"),
|
||||
|
||||
("nvim_workspace", "list_buffers") => ("nvim_buffer", "list"),
|
||||
("nvim_workspace", "list_windows") => ("nvim_window", "list"),
|
||||
("nvim_workspace", "focus") => ("nvim_window", "focus"),
|
||||
("nvim_workspace", "split") => ("nvim_window", "split"),
|
||||
("nvim_workspace", "cwd") => ("nvim_system", "cwd"),
|
||||
|
||||
("nvim_intelligence", "hover") => ("nvim_lsp", "hover"),
|
||||
("nvim_intelligence", "definition") => ("nvim_lsp", "definition"),
|
||||
("nvim_intelligence", "references") => ("nvim_lsp", "references"),
|
||||
("nvim_intelligence", "rename") => ("nvim_lsp", "rename"),
|
||||
("nvim_intelligence", "code_action") => ("nvim_lsp", "code_action"),
|
||||
("nvim_intelligence", "outline") => ("nvim_ast", "outline"),
|
||||
("nvim_intelligence", "query") => ("nvim_ast", "query"),
|
||||
("nvim_intelligence", "diagnostics") => ("nvim_diagnostics", "get"),
|
||||
|
||||
("nvim_ui", "highlight") => ("nvim_visual", "highlight"),
|
||||
("nvim_ui", "ghost_text") => ("nvim_visual", "extmark"),
|
||||
("nvim_ui", "clear") => ("nvim_visual", "clear_highlight"),
|
||||
|
||||
("nvim_exec", "lua") => ("nvim_execute_lua", ""),
|
||||
("nvim_exec", "vimscript") => ("nvim_system", "vimscript"),
|
||||
("nvim_exec", "terminal") => ("nvim_system", "send_to_terminal"),
|
||||
|
||||
(n, a) => (n, a),
|
||||
};
|
||||
|
||||
match mapped_name {
|
||||
"nvim_buffer" => match mapped_action {
|
||||
"get_active" => match get_nvim_active_buffer().await {
|
||||
Ok(content) => {
|
||||
send_text_result!(id.clone(), content);
|
||||
@@ -2147,6 +2098,27 @@ pub async fn run_mcp_loop(app_name: &str, app_version: &str) {
|
||||
send_error(id, -32602, "Missing 'command'").await;
|
||||
}
|
||||
}
|
||||
"cwd" => {
|
||||
let lua_code =
|
||||
if let Some(path) = args.get("path").and_then(|v| v.as_str()) {
|
||||
format!(
|
||||
"vim.cmd('cd {}'); return vim.fn.getcwd()",
|
||||
path.replace("\\", "\\\\").replace("'", "\\'")
|
||||
)
|
||||
} else {
|
||||
"return vim.fn.getcwd()".to_string()
|
||||
};
|
||||
handle_lua_result!(id, execute_nvim_lua(&lua_code));
|
||||
}
|
||||
"vimscript" => {
|
||||
if let Some(code) = args.get("code").and_then(|v| v.as_str()) {
|
||||
let lua_code =
|
||||
format!("vim.cmd([=[{}]=]); return 'Success'", code);
|
||||
handle_lua_result!(id, execute_nvim_lua(&lua_code));
|
||||
} else {
|
||||
send_error(id, -32602, "Missing 'code'").await;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
send_error(
|
||||
id,
|
||||
|
||||
Reference in new issue
Block a user