Skip to content

Commit 210fd29

Browse files
committed
merge main
1 parent b719e1c commit 210fd29

17 files changed

Lines changed: 1141 additions & 764 deletions

File tree

CHANGELOG.md

Lines changed: 136 additions & 59 deletions
Large diffs are not rendered by default.

doc/configuration.md

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,79 @@ By default when the LLM calls a tool or resource on a MCP server, we show a conf
141141

142142
![Image](https://github.com/user-attachments/assets/201a5804-99b6-4284-9351-348899e62467)
143143

144-
Set it to `true` to automatically approve all MCP tool calls without user confirmation. This also sets `vim.g.mcphub_auto_approve` variable to `true`. You can toggle this option in the MCP Hub UI with `ga` keymap. You can see the current auto approval status in the Hub UI.
144+
#### Boolean Auto-Approval
145+
146+
Set it to `true` to automatically approve all MCP tool calls without user confirmation:
147+
148+
```lua
149+
require("mcphub").setup({
150+
auto_approve = true, -- Auto approve all MCP tool calls
151+
})
152+
```
153+
154+
This also sets `vim.g.mcphub_auto_approve` variable to `true`. You can toggle this option in the MCP Hub UI with `ga` keymap. You can see the current auto approval status in the Hub UI.
145155

146156
![Image](https://github.com/user-attachments/assets/64708065-3428-4eb3-82a5-e32d2d1f98c6)
147157

148-
**Fine-Grained Auto-Approval**: For more granular control, configure auto-approval per server or per tool using the `autoApprove` field in your `servers.json`. You can also toggle auto-approval from the Hub UI using the `a` keymap on individual servers or tools. See [servers.json configuration](/mcp/servers_json#auto-approval-configuration) for detailed examples and configuration options.
158+
#### Function-Based Auto-Approval
159+
160+
For maximum control, provide a function that decides approval based on the specific tool call:
161+
162+
```lua
163+
require("mcphub").setup({
164+
auto_approve = function(params)
165+
-- Auto-approve GitHub issue reading
166+
if params.server_name == "github" and params.tool_name == "get_issue" then
167+
return true -- Auto approve
168+
end
169+
170+
-- Block access to private repos
171+
if params.arguments.repo == "private" then
172+
return "You can't access my private repo" -- Error message
173+
end
174+
175+
-- Auto-approve safe file operations in current project
176+
if params.tool_name == "read_file" then
177+
local path = params.arguments.path or ""
178+
if path:match("^" .. vim.fn.getcwd()) then
179+
return true -- Auto approve
180+
end
181+
end
182+
183+
-- Check if tool is configured for auto-approval in servers.json
184+
if params.is_auto_approved_in_server then
185+
return true -- Respect servers.json configuration
186+
end
187+
188+
return false -- Show confirmation prompt
189+
end,
190+
})
191+
```
192+
193+
**Parameters available in the function:**
194+
- `params.server_name` - Name of the MCP server
195+
- `params.tool_name` - Name of the tool being called (nil for resources)
196+
- `params.arguments` - Table of arguments passed to the tool
197+
- `params.action` - Either "use_mcp_tool" or "access_mcp_resource"
198+
- `params.uri` - Resource URI (for resource access)
199+
- `params.is_auto_approved_in_server` - Boolean indicating if tool is configured for auto-approval in servers.json
200+
201+
**Return values:**
202+
- `true` - Auto-approve the call
203+
- `false` - Show confirmation prompt
204+
- `string` - Deny with error message
205+
- `nil` - Show confirmation prompt (same as false)
206+
207+
#### Server-Level Auto-Approval
208+
209+
For fine-grained control per server or tool, configure auto-approval using the `autoApprove` field in your `servers.json`. You can also toggle auto-approval from the Hub UI using the `a` keymap on individual servers or tools. See [servers.json configuration](/mcp/servers_json#auto-approval-configuration) for detailed examples and configuration options.
210+
211+
#### Auto-Approval Priority
212+
213+
The system checks auto-approval in this order:
214+
1. **Function**: Custom `auto_approve` function (if provided)
215+
2. **Server-specific**: `autoApprove` field in server config
216+
3. **Default**: Show confirmation dialog
149217

150218
### auto_toggle_mcp_servers
151219

@@ -259,3 +327,4 @@ Logging configuration options:
259327

260328

261329

330+

doc/extensions/avante.md

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,59 @@ You can also toggle auto-approval from the Hub UI:
120120
- Press `a` on an individual tool to toggle auto-approval for just that tool
121121
- Resources are always auto-approved (no configuration needed)
122122

123+
### Function-Based Auto-Approval
124+
125+
For maximum control, provide a function that decides approval based on the specific tool call:
126+
127+
```lua
128+
require("mcphub").setup({
129+
auto_approve = function(params)
130+
-- Auto-approve GitHub issue reading
131+
if params.server_name == "github" and params.tool_name == "get_issue" then
132+
return true -- Auto approve
133+
end
134+
135+
-- Block access to private repos
136+
if params.arguments.repo == "private" then
137+
return "You can't access my private repo" -- Error message
138+
end
139+
140+
-- Auto-approve safe file operations in current project
141+
if params.tool_name == "read_file" then
142+
local path = params.arguments.path or ""
143+
if path:match("^" .. vim.fn.getcwd()) then
144+
return true -- Auto approve
145+
end
146+
end
147+
148+
-- Check if tool is configured for auto-approval in servers.json
149+
if params.is_auto_approved_in_server then
150+
return true -- Respect servers.json configuration
151+
end
152+
153+
return false -- Show confirmation prompt
154+
end,
155+
})
156+
```
157+
158+
**Parameters available in the function:**
159+
- `params.server_name` - Name of the MCP server
160+
- `params.tool_name` - Name of the tool being called (nil for resources)
161+
- `params.arguments` - Table of arguments passed to the tool
162+
- `params.action` - Either "use_mcp_tool" or "access_mcp_resource"
163+
- `params.uri` - Resource URI (for resource access)
164+
- `params.is_auto_approved_in_server` - Boolean indicating if tool is configured for auto-approval in servers.json
165+
166+
**Return values:**
167+
- `true` - Auto-approve the call
168+
- `false` - Show confirmation prompt
169+
- `string` - Deny with error message
170+
- `nil` - Show confirmation prompt (same as false)
171+
123172
### Auto-Approval Priority
124173

125174
The system checks auto-approval in this order:
126-
1. **Global**: `vim.g.mcphub_auto_approve = true` (approves everything)
175+
1. **Function**: Custom `auto_approve` function (if provided)
127176
2. **Server-specific**: `autoApprove` field in server config
128177
3. **Default**: Show confirmation dialog
129178

@@ -136,3 +185,4 @@ The system checks auto-approval in this order:
136185

137186

138187

188+

doc/extensions/codecompanion.md

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -198,10 +198,67 @@ You can also toggle auto-approval from the Hub UI:
198198
- Press `a` on an individual tool to toggle auto-approval for just that tool
199199
- Resources are always auto-approved (no configuration needed)
200200

201-
#### Auto-Approval Priority
201+
### Function-Based Auto-Approval
202+
203+
For maximum control, provide a function that decides approval based on the specific tool call:
204+
205+
```lua
206+
require("mcphub").setup({
207+
auto_approve = function(params)
208+
-- Respect CodeCompanion's auto tool mode when enabled
209+
if vim.g.codecompanion_auto_tool_mode == true then
210+
return true -- Auto approve when CodeCompanion auto-tool mode is on
211+
end
212+
213+
-- Auto-approve GitHub issue reading
214+
if params.server_name == "github" and params.tool_name == "get_issue" then
215+
return true -- Auto approve
216+
end
217+
218+
-- Block access to private repos
219+
if params.arguments.repo == "private" then
220+
return "You can't access my private repo" -- Error message
221+
end
222+
223+
-- Auto-approve safe file operations in current project
224+
if params.tool_name == "read_file" then
225+
local path = params.arguments.path or ""
226+
if path:match("^" .. vim.fn.getcwd()) then
227+
return true -- Auto approve
228+
end
229+
end
230+
231+
-- Check if tool is configured for auto-approval in servers.json
232+
if params.is_auto_approved_in_server then
233+
return true -- Respect servers.json configuration
234+
end
235+
236+
return false -- Show confirmation prompt
237+
end,
238+
})
239+
```
240+
241+
**Parameters available in the function:**
242+
- `params.server_name` - Name of the MCP server
243+
- `params.tool_name` - Name of the tool being called (nil for resources)
244+
- `params.arguments` - Table of arguments passed to the tool
245+
- `params.action` - Either "use_mcp_tool" or "access_mcp_resource"
246+
- `params.uri` - Resource URI (for resource access)
247+
- `params.is_auto_approved_in_server` - Boolean indicating if tool is configured for auto-approval in servers.json
248+
249+
**Return values:**
250+
- `true` - Auto-approve the call
251+
- `false` - Show confirmation prompt
252+
- `string` - Deny with error message
253+
- `nil` - Show confirmation prompt (same as false)
254+
255+
### Auto-Approval Priority
202256

203257
The system checks auto-approval in this order:
204-
1. **Global**: `vim.g.mcphub_auto_approve = true` (approves everything)
205-
2. **CodeCompanion**: `vim.g.codecompanion_auto_tool_mode = true` (toggled via `gta` in chat buffer)
206-
3. **Server-specific**: `autoApprove` field in server config
207-
4. **Default**: Show confirmation dialog
258+
1. **Function**: Custom `auto_approve` function (if provided)
259+
2. **Server-specific**: `autoApprove` field in server config
260+
3. **Default**: Show confirmation dialog
261+
262+
263+
264+

lua/mcphub/config.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ local defaults = {
1919
},
2020
},
2121
},
22+
---@type boolean | fun(parsed_params: MCPHub.ParsedParams): boolean | nil | string Function to determine if a call should be auto-approved
2223
auto_approve = false,
2324
auto_toggle_mcp_servers = true, -- Let LLMs start and stop MCP servers automatically
2425
use_bundled_binary = false, -- Whether to use bundled mcp-hub binary
@@ -38,8 +39,8 @@ local defaults = {
3839
window = {},
3940
wo = {},
4041
},
42+
---@type MCPHub.Extensions.Config
4143
extensions = {
42-
---@type MCPHubAvanteConfig
4344
avante = {
4445
enabled = true,
4546
make_slash_commands = true,
Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
---@module "avante"
12
--[[
23
*MCP Servers Tool*
34
This tool can be used to call tools and resources from the MCP Servers.
@@ -6,10 +7,17 @@ M.mcp_tool() will return a use_mcp_tool and access_mcp_resource function schemas
67
M.use_mcp_tool() will return schema for calling tools on MCP servers.
78
M.access_mcp_resource() will return schema for accessing resources on MCP servers.
89
--]]
10+
11+
---@class MCPHub.Extensions.Avante
12+
---@field setup function(config: MCPHub.Extensions.AvanteConfig) Setup slash commands and other configurations for Avante extension
13+
---@field mcp_tool fun(): AvanteLLMTool,AvanteLLMTool
14+
---@field use_mcp_tool AvanteLLMTool
15+
---@field access_mcp_resource AvanteLLMTool
16+
17+
---@class MCPHub.Extensions.Avante
918
local M = {}
10-
local async = require("plenary.async")
11-
local shared = require("mcphub.extensions.shared")
1219

20+
---@type table<MCPHub.ActionType, AvanteLLMTool>
1321
local tool_schemas = {
1422
use_mcp_tool = {
1523
name = "use_mcp_tool",
@@ -34,6 +42,7 @@ local tool_schemas = {
3442
},
3543
},
3644
},
45+
returns = {}, -- Will be added dynamically in mcp_tool()
3746
},
3847

3948
access_mcp_resource = {
@@ -54,11 +63,16 @@ local tool_schemas = {
5463
},
5564
},
5665
},
66+
returns = {}, -- Will be added dynamically in mcp_tool()
5767
},
5868
}
5969

60-
---@return table,table
70+
---@return AvanteLLMTool use_mcp_tool
71+
---@return AvanteLLMTool access_mcp_resource
6172
function M.mcp_tool()
73+
---@param str string
74+
---@param max_length number
75+
---@return string
6276
local function truncate_utf8(str, max_length)
6377
if type(str) ~= "string" or #str <= max_length then
6478
return str
@@ -80,7 +94,10 @@ function M.mcp_tool()
8094
return str:sub(1, i - 1) .. "... (truncated)"
8195
end
8296

97+
local async = require("plenary.async")
98+
local shared = require("mcphub.extensions.shared")
8399
for action_name, schema in pairs(tool_schemas) do
100+
---@type AvanteLLMToolFunc<MCPHub.ToolCallArgs | MCPHub.ResourceAccessArgs>
84101
schema.func = function(args, on_log, on_complete)
85102
---@diagnostic disable-next-line: missing-parameter
86103
async.run(function()
@@ -92,13 +109,10 @@ function M.mcp_tool()
92109
if #params.errors > 0 then
93110
return on_complete(nil, table.concat(params.errors, "\n"))
94111
end
95-
-- Check both global and server-specific auto-approval
96-
local auto_approve = vim.g.mcphub_auto_approve == true or params.should_auto_approve
97-
if not auto_approve then
98-
local confirmed = shared.show_mcp_tool_prompt(params)
99-
if not confirmed then
100-
return on_complete(nil, "User cancelled the operation")
101-
end
112+
113+
local result = shared.handle_auto_approval_decision(params)
114+
if result.error then
115+
return on_complete(nil, result.error)
102116
end
103117
local sidebar = require("avante").get()
104118
if params.action == "access_mcp_resource" then
@@ -154,6 +168,8 @@ function M.mcp_tool()
154168
end
155169
end)
156170
end
171+
172+
---@type AvanteLLMToolReturn[]
157173
schema.returns = {
158174
{
159175
name = "result",
@@ -173,4 +189,11 @@ function M.mcp_tool()
173189
return unpack(vim.tbl_values(tool_schemas))
174190
end
175191

192+
---@param config MCPHub.Extensions.AvanteConfig
193+
function M.setup(config)
194+
if config.make_slash_commands then
195+
require("mcphub.extensions.avante.slash_commands").setup()
196+
end
197+
end
198+
176199
return M

0 commit comments

Comments
 (0)