Skip to content

Configuring MCP Servers

In #2549, CodeCompanion added support for the Model Context Protocol (MCP), an open-source standard for connecting AI applications to external systems.

You can find out which parts of the protocol CodeCompanion has implemented on the MCP page. Currently, you can leverage MCP servers with chat interactions.

Configuring MCP Servers

You can give CodeCompanion knowledge of MCP servers via the mcp.servers configuration option. This is a list of server definitions, each specifying how to connect to an MCP server

Basic Configuration

lua
require("codecompanion").setup({
  mcp = {
    ["tavily-mcp"] = {
      cmd = { "npx", "-y", "tavily-mcp@latest" },
    },
  },
})
lua
require("codecompanion").setup({
  mcp = {
    ["tavily-mcp"] = {
      cmd = { "npx", "-y", "tavily-mcp@latest" },
      env = {
        TAVILY_API_KEY = "cmd:op read op://personal/Tavily_API/credential --no-newline",
      },
    },
  },
})

In the example above, we're using 1Password CLI tool to fetch the API key. However, you can leverage CodeCompanion's built-in environment variable capabilities to fetch the value from any source you like.

Roots

IMPORTANT

The roots feature is a hint to MCP servers. Compliant servers use it to limit file system access, but CodeCompanion cannot enforce this. For untrusted servers, use isolation mechanisms like containers.

Roots allow you to specify directories that the MCP server can access. By default, roots are disabled for security reasons. You can enable them by adding a roots field to your server configuration:

lua
require("codecompanion").setup({
  mcp = {
    filesystem = {
      cmd = { "npx", "-y", "@modelcontextprotocol/server-filesystem" },
      roots = function()
        -- Return a list of names and directories as per:
        -- https://modelcontextprotocol.io/specification/2025-11-25/client/roots#listing-roots
      end,
    },
  },
})
lua
require("codecompanion").setup({
  mcp = {
    filesystem = {
      cmd = { "npx", "-y", "@modelcontextprotocol/server-filesystem" },
      ---@param notify fun()
      register_roots_list_changes = function(notify)
        -- Call `notify()` whenever the list of roots changes.
      end,
    },
  },
})

Enabling Servers

By default, all MCP servers are enabled in CodeCompanion. This results in servers being started when a chat buffer is opened for the first time - remaining active until Neovim is closed. This behaviour can be changed by setting mcp.enabled = false. You can also change this at an individual server level:

lua
require("codecompanion").setup({
  mcp = {
    enabled = false,
    ["tavily-mcp"] = {
      cmd = { "npx", "-y", "tavily-mcp@latest" },
    },
  },
})
lua
require("codecompanion").setup({
  mcp = {
    enabled = true,
    ["tavily-mcp"] = {
      cmd = { "npx", "-y", "tavily-mcp@latest" },
      opts = {
        enabled = false,
      },
    },
  },
})

Overriding Tool Behaviour

An MCP server can expose multiple tools. For example, a "math" server might provide add, subtract, multiply, and divide tools. You can override the behaviour of individual tools using the tool_overrides configuration, allowing you to customise options, output handling, system prompts, and timeouts on a per-tool basis.

The tool_overrides field is a table where keys are the MCP tool names (not the prefixed names used internally by CodeCompanion):

lua
require("codecompanion").setup({
  mcp = {
    ["math-server"] = {
      cmd = { "npx", "-y", "math-mcp-server" },
      tool_overrides = {
        divide = {
          opts = {
            require_approval_before = true,
          },
        },
      },
    },
  },
})
lua
require("codecompanion").setup({
  mcp = {
    ["math-server"] = {
      cmd = { "npx", "-y", "math-mcp-server" },
      tool_overrides = {
        add = {
          output = {
            success = function(self, tools, cmd, stdout)
              local tool_bridge = require("codecompanion.mcp.tool_bridge")
              local content = stdout and stdout[#stdout]
              local output = tool_bridge.format_tool_result_content(content)
              local msg = string.format("%d + %d = %s", self.args.a, self.args.b, output)
              tools.chat:add_tool_output(self, output, msg)
            end,
          },
        },
      },
    },
  },
})
lua
require("codecompanion").setup({
  mcp = {
    ["math-server"] = {
      cmd = { "npx", "-y", "math-mcp-server" },
      tool_overrides = {
        multiply = {
          system_prompt = "When using the multiply tool, always show your working.",
        },
      },
    },
  },
})

Tool Defaults

You can set default options for all tools by setting the tool_defaults option. However, note that tool_overrides take precedence over them:

lua
require("codecompanion").setup({
  mcp = {
    ["math-server"] = {
      cmd = { "npx", "-y", "math-mcp-server" },
      tool_defaults = {
        require_approval_before = true,
      },
      -- Per-tool overrides take precedence over tool_defaults
      tool_overrides = {
        add = {
          opts = {
            require_approval_before = false,
          },
        },
      },
    },
  },
})

Override Options

Each tool override can include:

OptionTypeDescription
optstableTool options like require_approval_before, require_approval_after
outputtableCustom output handlers (success, error, prompt, rejected, cancelled)
system_promptstringAdditional system prompt text for this tool
timeoutnumberCustom timeout in milliseconds for this tool
enabledbooleanWhether the tool is enabled

Released under the MIT License.