Skip to content

Enhancing ACP Support #266

Description

@cenk1cenk2

Hello again ravitemer,

I would like to enquire whether it would be a good addition to improve the ACP configuration a bit more by having a proxy server in between for clients to proxy the calls through a socket to given neovim instance and call the MCPHub commands like MCPHub:call_tool() via lua itself.

So the idea goes something like this, where you would have an additional config property called proxy, which in turn runs a nodejs server that will just create an in-between server with vim.v.servername passed in to it.

This proxy server will call the lua functions directly through the MCPHub:get_hub_instance() and replicate the endpoints to list tools, prompts, resources, and such.

This would enable it to make the ACP servers as interactive as the HTTP servers, where every command actually goes through the approval process and its default configuration, as well as being able to use the native servers.

So currently I have something like the following for code-companion.nvim.

claude_code = function()
  ---@type MCPHub.Hub
  local instance
  local ok = vim.wait(5000, function()
    instance = require("mcphub").get_hub_instance()

    return instance and instance:ensure_ready()
  end, 100)
  if not ok then
    error("MCPHub instance not ready in time")
  end
  log:info("Connected to MCPHub instance: :%d", instance.port)

  return require("codecompanion.adapters").extend(
    "claude_code",
    ---@type CodeCompanion.ACPAdapter
    {
      env = {
        CLAUDE_CODE_OAUTH_TOKEN = vim.env["CLAUDE_CODE_OAUTH_TOKEN"],
      },
      defaults = {
        mcpServers = {
          {
            name = "mcphub",
            type = "sse",
            url = ("http://localhost:%d/mcp"):format(instance.port),
            args = {},
            command = "",
            headers = {},
            env = {},
          },
        },
      },
      commands = {
        default = { "bunx", "@zed-industries/claude-code-acp" },
      },
    }
  )
end,

Which will turn into the latter.

claude_code = function()
  ---@type MCPHub.Hub
  local instance
  local ok = vim.wait(5000, function()
    instance = require("mcphub").get_hub_instance()

    return instance and instance:ensure_ready()
  end, 100)
  if not ok then
    error("MCPHub instance not ready in time")
  end
  log:info("Connected to MCPHub instance: :%d", instance.port)

  return require("codecompanion.adapters").extend(
    "claude_code",
    ---@type CodeCompanion.ACPAdapter
    {
      env = {
        CLAUDE_CODE_OAUTH_TOKEN = vim.env["CLAUDE_CODE_OAUTH_TOKEN"],
      },
      defaults = {
        mcpServers = {
          {
            name = "mcphub",
            type = "stdio",
            url = ("unix://%s"):format(instance.proxy),
            args = {},
            command = "",
            headers = {},
            env = {},
          },
        },
      },
      commands = {
        default = { "bunx", "@zed-industries/claude-code-acp" },
      },
    }
  )
end,

I have been fiddling with the idea for a bit, but I am not sure if it would be a worthwhile PR or something you want to include because of the additional replication.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions