mcphub.nvim
repository·main·Indexed 23 days ago
https://github.com/ravitemer/mcphub.nvimA Neovim client for the Model Context Protocol (MCP) that integrates MCP servers (tools, resources, and prompts) into AI-powered chat workflows. It supports transports like Streamable-HTTP, SSE, and STDIO, and integrates with chat plugins such as Avante.nvim, CodeCompanion.nvim, and CopilotChat.nvim. The plugin allows for native Lua MCP server implementation, workspace-local configurations, and VS Code compatible server settings.
What's inside mcphub.nvim
- MCP Hub is a Model Context Protocol (MCP) client for Neovim. It integrates MCP servers into your Neovim editing workflow, allowing you to manage, test, and use MCP servers with popular chat plugins. It supports tools, resources, and prompts, providing real-time updates when server capabilities change.
How MCPHub.nvim manages the server lifecycle
mainMCPHub.nvim operates using an Express server that manages MCP servers and handles client requests. The lifecycle is designed for multi-instance support, allowing multiple Neovim instances to connect to a single shared hub.
Initialization Sequence
When
setup()is called, the following occurs:- Pre-flight checks: The plugin checks for the
mcp-hubcommand installation, verifies version compatibility, and checks if a server is already running. - Server Startup: If no server is running, it starts
mcp-hubwith config file watching enabled. - Server Binding: An Express server is created at
http://localhost:[config.port]or the specifiedconfig.server_url. - Ready Callback: Once setup is successful, the
on_readycallback is triggered, providing access to the hub instance and its REST API.
Multi-instance and Shutdown Behavior
- Shared State: Multiple Neovim instances can connect to the same running server. New instances register as clients.
- Automatic Cleanup: When a Neovim instance closes, it unregisters as a client. The server remains active as long as there is at least one client connected. When the last client unregisters, a shutdown timer is triggered. If a new client connects before the timer expires, the shutdown is canceled.
- Pre-flight checks: The plugin checks for the
Implement a Tool Handler
mainTool handlers are functions that receive a
ToolRequestand aToolResponsebuilder.ToolRequest contains:
params: Validated tool arguments.tool: The completeMCPTooldefinition.server: TheNativeServerinstance.caller: Context about the caller (e.g., which LLM plugin is calling the tool).editor_info: Current Neovim editor state (e.g., active buffer info).
ToolResponse (Chainable Builder):
text(string): Add text content.image(data, mime): Add image data.audio(data, mime): Add audio data.resource(MCPResourceContent): Add a resource.error(message, details?): Send an error response.send(result?): Finalize and send the response.
Compare Plugin-Specific Tools vs Native MCP Servers
mainWhen building tools for AI chat plugins in Neovim, you can either use plugin-specific tool implementations (like those provided by
AvanteorCodeCompanion) or use MCPHub's Native MCP Servers.Native MCP Servers offer several advantages:
- Write Once, Use Everywhere: Tools are written once using the standard MCP protocol and work across all compatible chat plugins.
- Rich Response Types: Supports text, images, and blobs, whereas plugin-specific tools are often limited to text.
- Resource System: Provides a URI-based system for accessing data.
- Deep Editor Integration: Direct access to Neovim APIs and editor state.
- Plugin-Aware Context: The ability to detect which plugin is calling the tool and adapt behavior accordingly.
- Standard Protocol: Ensures consistent behavior and future compatibility.
Chat Plugin Integrations
mainMCP Hub integrates with several Neovim chat plugins to expose MCP capabilities:
- Avante.nvim: Supports Tools, resources, resourceTemplates, and prompts (exposed as
slash_commands). - CodeCompanion.nvim: Supports Tools, resources, templates, prompts (exposed as
slash_commands), and image responses. - CopilotChat.nvim: Supports Tools, resources, and function calling.
- Avante.nvim: Supports Tools, resources, resourceTemplates, and prompts (exposed as
Access Editor State via EditorInfo
mainThe
req.editor_infofield provides a consistent view of the current Neovim editor state, including thelast_activebuffer and a list of all openbuffers. This allows tools to interact with the user's workspace regardless of which plugin triggered the tool.---@class EditorInfo ---@field last_active BufferInfo # Currently active buffer ---@field buffers BufferInfo[] # List of all buffers ---@class BufferInfo ---@field name string # Buffer name ---@field filename string # Full file path ---@field windows number[] # Window IDs showing this buffer ---@field winnr number # Primary window number ---@field cursor_pos number[] # Cursor position [row, col] ---@field filetype string # Buffer filetype ---@field line_count number # Total lines ---@field is_visible boolean # Whether buffer is visible ---@field is_modified boolean # Whether buffer is modified ---@field is_loaded boolean # Whether buffer is loaded ---@field lastused number # Last used timestamp ---@field bufnr number # Buffer number -- Example usage: mcphub.add_tool("buffer", { name = "get_info", description = "Get buffer information", handler = function(req, res) local info = req.editor_info local active = info.last_active -- Access current buffer state local details = { name = active.filename, type = active.filetype, lines = active.line_count, cursor = active.cursor_pos, modified = active.is_modified, visible = active.is_visible } -- List all open buffers local buffers = {} for _, buf in ipairs(info.buffers) do table.insert(buffers, buf.filename) end return res:text(vim.inspect({ active = details, open_buffers = buffers })):send() end })How MCP Hub works
mainMCP Hub acts as a central manager for Model Context Protocol (MCP) servers. When Neovim starts and
setup()is called, it launches a backgroundmcp-hubnodejs binary that reads your configuration file and manages the lifecycle of your MCP servers.It provides two primary interfaces:
- Management API (default:
http://localhost:37373/api): Used by the Neovim plugin to start/stop servers, execute tools, access resources, and handle real-time events. - Unified MCP Endpoint (
http://localhost:37373/mcp): A single MCP server that aggregates the capabilities of ALL managed servers. You can point other MCP clients (like Claude Desktop or Cursor) to this single endpoint to gain access to all your configured tools and resources without individual configuration.
- Management API (default:
What are Native MCP Servers in MCPHub.nvim
mainNative MCP Servers implement the Model Context Protocol (MCP) directly within Neovim using Lua. Unlike external MCP servers that run as separate processes, Native Servers run within Neovim's runtime, providing direct access to Neovim APIs, buffer/window management, and editor state.
Key benefits include:
- Full MCP Support: Implements tools, resources, and prompts using standard request/response formats.
- Write Once, Run Anywhere: A single Lua implementation works across all chat plugins compatible with MCPHub.
- Rich Response System: Supports standard response types like text, images, and blobs with MIME type support.
- Deep Integration: Native Lua performance and direct access to Neovim's internal APIs.
Define an MCP Tool
mainAn
MCPToolis a function that an LLM can call. You register tools usingmcphub.add_tool(namespace, tool_definition).A tool definition requires a
name, adescription(or a function returning a string), and ahandlerfunction. You can optionally provide aninputSchema(JSON Schema) to validate the arguments passed by the LLM.---@class MCPTool ---@field name string Required: Tool identifier ---@field description string|fun():string Optional: Tool description ---@field inputSchema? table|fun():table Optional: JSON Schema for validation ---@field handler fun(req: ToolRequest, res: ToolResponse): nil|table Required: ImplementationAccess Neovim context via URI resources
mainYou can retrieve structured context about your environment using specific URI patterns:
neovim://buffer: Provides metadata (name, bufnr, line count), full buffer content with line numbers, cursor position, marks, and quickfix entries.neovim://workspace: Provides system info (OS, hostname, memory), workspace details (current directory, git status), file structure, and lists of visible/loaded files.neovim://diagnostics/buffer: Provides LSP diagnostics (error, warning, info, hint) for the active buffer, including line/column and source info.neovim://diagnostics/workspace: Provides LSP diagnostics across all open buffers, grouped by file.
Access Caller Context in Handlers
mainWhen a tool or resource is called from a chat plugin, the
req.callerfield provides context about the calling system. You can use this to adapt behavior (e.g., retrieving the correct buffer fromavanteorcodecompanion).Supported
typevalues:avantecodecompanionhubui
mcphub.add_tool("workspace", { name = "analyze_buffer", description = "Analyze current buffer", handler = function(req, res) -- Get correct buffer based on caller local bufnr if req.caller.type == "codecompanion" then -- Get buffer from CodeCompanion chat context local chat = req.caller.codecompanion.chat bufnr = chat.context.bufnr local is_var = req.caller.meta.is_within_variable -- true if called from #variable elseif req.caller.type == "avante" then -- Get buffer from Avante code context bufnr = req.caller.avante.code.bufnr elseif req.caller.type == "hubui" then -- Using hub UI context bufnr = req.caller.hubui.context.bufnr or 0 end -- Use the buffer number local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) return res:text(#lines .. " lines found"):send() end })How Workspaces work in MCP Hub
mainWorkspaces allow for isolated MCP server setups per project by using project-local configuration files. This enables different server configurations (like filesystem access or LSP settings) for different projects without manually editing a global configuration.
Project Detection
When you open Neovim, MCP Hub searches upward from the current directory for the first available configuration file:
.mcphub/servers.json(MCP Hub specific).vscode/mcp.json(VS Code compatibility).cursor/mcp.json(Cursor compatibility)
Hub Instance Lifecycle
Each detected workspace triggers the creation of a unique hub instance with:
- Unique port: Generated from a hash of the project path.
- Isolated processes: A separate
mcp-hubinstance running its own servers. - Merged configuration: Project-specific configurations override the global configuration.
- Project context: The hub starts with its
cwdset to the project directory.
Automatic Switching
If
reload_on_dir_changedis enabled, MCP Hub automatically detects new workspaces and switches to the appropriate hub instance when you change directories using:cd.