From 148998b1dbe42ac75702bd50645c365d981f4c04 Mon Sep 17 00:00:00 2001 From: Adrian Cole <64215+codefromthecrypt@users.noreply.github.com> Date: Mon, 29 Dec 2025 17:50:24 +0800 Subject: [PATCH] feat(acp): support mcp_servers in acp_providers config (#2883) Allow acp_providers to specify an mcp_servers array that gets passed to create_session. This enables agents to connect to HTTP MCP servers configured by the client. - Read mcp_servers from Config.acp_providers[provider] - Pass to acp_client:create_session for MCP tool support - Add mock transport tests verifying mcpServers propagation --- lua/avante/llm.lua | 4 +- tests/libs/acp_client_spec.lua | 133 +++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 1 deletion(-) diff --git a/lua/avante/llm.lua b/lua/avante/llm.lua index 440f9f5..6b7be79 100644 --- a/lua/avante/llm.lua +++ b/lua/avante/llm.lua @@ -1338,7 +1338,9 @@ end ---@param acp_client avante.acp.ACPClient function M._create_acp_session_and_continue(opts, acp_client) local project_root = Utils.root.get() - acp_client:create_session(project_root, {}, function(session_id_, err) + local acp_provider = Config.acp_providers[Config.provider] or {} + local mcp_servers = acp_provider.mcp_servers or {} + acp_client:create_session(project_root, mcp_servers, function(session_id_, err) if err then opts.on_stop({ reason = "error", error = err }) return diff --git a/tests/libs/acp_client_spec.lua b/tests/libs/acp_client_spec.lua index 9f8030d..4f42cd2 100644 --- a/tests/libs/acp_client_spec.lua +++ b/tests/libs/acp_client_spec.lua @@ -237,4 +237,137 @@ describe("ACPClient", function() assert.equals(ACPClient.ERROR_CODES.METHOD_NOT_FOUND, sent_error.code) end) end) + + describe("MCP tool flow", function() + local MCP_TOOL_UUID = "mcp-test-uuid-12345-67890" + + it("receives MCP tool result via session/update when mcp_servers configured", function() + local sent_request = nil + local session_updates = {} + local client + + local mock_transport = { + send = function(self, data) + local decoded = vim.json.decode(data) + + if decoded.method == "session/new" then + sent_request = decoded.params + + vim.schedule( + function() + client:_handle_message({ + jsonrpc = "2.0", + id = decoded.id, + result = { sessionId = "test-session-mcp" }, + }) + end + ) + elseif decoded.method == "session/prompt" then + vim.schedule( + function() + client:_handle_message({ + jsonrpc = "2.0", + method = "session/update", + params = { + sessionId = "test-session-mcp", + update = { + sessionUpdate = "tool_call", + toolCallId = "mcp-tool-1", + title = "lookup__get_code", + kind = "other", + status = "completed", + content = { + { + type = "content", + content = { type = "text", text = MCP_TOOL_UUID }, + }, + }, + }, + }, + }) + end + ) + + vim.schedule( + function() + client:_handle_message({ + jsonrpc = "2.0", + id = decoded.id, + result = { stopReason = "end_turn" }, + }) + end + ) + end + end, + start = function(self, on_message) end, + stop = function(self) end, + } + + local mock_config = { + transport_type = "stdio", + handlers = { + on_session_update = function(update) table.insert(session_updates, update) end, + }, + } + + client = ACPClient:new(mock_config) + client.transport = mock_transport + client.state = "ready" + + local mcp_servers = { + { type = "http", name = "lookup", url = "http://localhost:8080/mcp" }, + } + local session_id = nil + client:create_session("/tmp/test", mcp_servers, function(sid, err) session_id = sid end) + + assert.is_not_nil(sent_request) + assert.equals("/tmp/test", sent_request.cwd) + assert.same(mcp_servers, sent_request.mcpServers) + assert.equals("test-session-mcp", session_id) + + client:send_prompt("test-session-mcp", { { type = "text", text = "Use the get_code tool" } }, function() end) + + assert.equals(1, #session_updates) + assert.equals("tool_call", session_updates[1].sessionUpdate) + assert.equals("lookup__get_code", session_updates[1].title) + assert.equals("completed", session_updates[1].status) + + local tool_content = session_updates[1].content[1].content.text + assert.equals(MCP_TOOL_UUID, tool_content) + end) + + it("should default mcp_servers to empty array", function() + local sent_params = nil + local client + + local mock_transport = { + send = function(self, data) + local decoded = vim.json.decode(data) + if decoded.method == "session/new" then + sent_params = decoded.params + vim.schedule( + function() + client:_handle_message({ + jsonrpc = "2.0", + id = decoded.id, + result = { sessionId = "test-session" }, + }) + end + ) + end + end, + start = function(self, on_message) end, + stop = function(self) end, + } + + client = ACPClient:new({ transport_type = "stdio", handlers = {} }) + client.transport = mock_transport + client.state = "ready" + + client:create_session("/tmp/test", nil, function() end) + + assert.is_not_nil(sent_params) + assert.same({}, sent_params.mcpServers) + end) + end) end)