Skip to main content
MCP (Model Context Protocol) is an open protocol for tool interoperability with AI models. ChatCLI integrates with MCP servers, allowing the AI to access external tools such as file systems, web searches, databases, and any compatible service.

Overview

ChatCLI <-> MCP Manager <-> MCP Server (stdio | sse | http)
                              |
                         External tools
                         (filesystem, search, DB, ...)
1

Load configuration

The MCP Manager loads the MCP server configuration.
2

Start servers

Starts the configured servers (stdio, SSE or Streamable HTTP).
3

Discover tools

Discovers the available tools on each server.
4

Expose to the model

Exposes the tools to the AI model as ToolDefinition.
5

Route calls

Routes tool calls to the correct server.

Configuration

Configuration File

Create ~/.chatcli/mcp_servers.json:
{
  "mcpServers": [
    {
      "name": "filesystem",
      "transport": "stdio",
      "command": "npx",
      "args": ["-y", "@anthropic/mcp-server-filesystem", "/workspace"],
      "enabled": true
    },
    {
      "name": "web-search",
      "transport": "sse",
      "url": "http://localhost:8080/sse",
      "enabled": true,
      "overrides": ["@webfetch", "@websearch"]
    },
    {
      "name": "database",
      "transport": "stdio",
      "command": "/usr/local/bin/mcp-postgres",
      "args": ["--connection-string", "postgresql://localhost/mydb"],
      "env": {
        "PGPASSWORD": "secret"
      },
      "enabled": true
    }
  ]
}

Extended server capabilities

Beyond the minimum (name, command, args, env, transport, enabled, overrides), each server entry accepts an opt-in set of fields covering the same cases Claude Code, Cline, Cursor, and the AWS EKS MCP server support β€” tool auto-approval, enabledTools/disabledTools filtering, per-server timeouts, working directory, custom HTTP headers, and HTTP authentication (bearer/basic/header, shared by sse and http), plus metadata (description, tags, category) shown in /mcp status. Any key outside the typed schema is preserved verbatim across save/load (the Extensions catch-all), so a config copied from another client works without losing vendor-specific annotations. Full reference with semantics, examples and troubleshooting: MCP Servers Configuration.

Environment Variables

CHATCLI_MCP_ENABLED=true
CHATCLI_MCP_CONFIG=~/.chatcli/mcp_servers.json

Via Server Flag

chatcli server --mcp-config ~/.chatcli/mcp_servers.json

Transports

The stdio transport starts a local process and communicates via stdin/stdout using JSON-RPC 2.0:
{
  "name": "filesystem",
  "transport": "stdio",
  "command": "npx",
  "args": ["-y", "@anthropic/mcp-server-filesystem", "/workspace"]
}
Use case: Local servers distributed as npm packages, standalone binaries, or scripts.

Tool Naming

MCP tools are automatically prefixed with mcp_ and receive a description from the source server:
Original name: read_file
Name in ChatCLI: mcp_read_file
Description: [MCP:filesystem] Reads a file from the filesystem
The mcp_ prefix prevents collisions with ChatCLI’s native tools.

Built-in Overrides (Shadow + Fallback)

When an MCP server provides a tool that replaces a native plugin (e.g., @webfetch, @websearch), use the overrides field to declare which built-ins it replaces. ChatCLI automatically hides the listed built-ins while the MCP server is connected. If the server disconnects, the built-ins are immediately restored β€” the user never loses the capability.

Why use overrides?

Without overrides, the LLM sees two tools that do the same thing (e.g., @webfetch and mcp_web_fetch) and picks randomly. With overrides, the behavior is deterministic: the LLM only sees the MCP tool, with no ambiguity.

Configuration

Add overrides to the MCP server configuration:
{
  "mcpServers": [
    {
      "name": "web-tools",
      "transport": "sse",
      "url": "http://mcp-web:8080/sse",
      "enabled": true,
      "overrides": ["@webfetch", "@websearch"]
    }
  ]
}

How it works

MCP server "web-tools" CONNECTED + overrides: ["@webfetch", "@websearch"]
  LLM sees:       mcp_web_fetch, mcp_web_search, @coder, ...
  LLM does NOT see: @webfetch, @websearch  (hidden)

MCP server "web-tools" DISCONNECTED (crash, network, etc.)
  LLM sees:       @webfetch, @websearch, @coder, ...  (automatically restored)
  Log:            "MCP server 'web-tools' disconnected, restoring built-in overrides"
Shadow sync happens on every conversation turn, not just at startup. This means if the MCP server crashes mid-conversation, the built-ins return on the very next message β€” no restart needed.

Important rules

RuleDetail
Exact namesUse the full built-in name including @ (e.g., "@webfetch", not "webfetch")
Multiple serversDifferent servers can declare different overrides. If two servers override the same built-in, only one needs to be connected to maintain the shadow
Disabled server"enabled": false on the server = overrides do not apply (server never connects)
Partial overrideYou can override just one built-in (e.g., only @websearch) and keep the others visible
No effect on @coder@coder cannot be overridden via MCP β€” its subcommands are native tools of /coder mode
The overrides field does not uninstall or modify the built-in plugin. It only hides it from the LLM prompt. The plugin remains available internally and returns automatically when needed. This is shadow, not delete.

Deploy via Helm

# values.yaml
mcp:
  enabled: true
  servers:
    - name: filesystem
      transport: stdio
      command: npx
      args: ["-y", "@anthropic/mcp-server-filesystem", "/workspace"]
      enabled: true
    - name: web-tools
      transport: sse
      url: "http://mcp-web:8080/sse"
      enabled: true
      overrides: ["@webfetch", "@websearch"]  # hides built-ins when connected
The Helm chart automatically creates a ConfigMap with the mcp_servers.json and mounts it at /etc/chatcli/mcp/.

Deploy via Operator (Instance CRD)

When using the ChatCLI Operator, configure MCP directly in the Instance resource:
apiVersion: platform.chatcli.dev/v1alpha1
kind: Instance
metadata:
  name: my-chatcli
spec:
  provider: CLAUDEAI
  model: claude-sonnet-4-20250514
  mcp:
    enabled: true
    servers:
      - name: filesystem
        transport: stdio
        command: npx
        args: ["-y", "@anthropic/mcp-server-filesystem", "/workspace"]
        enabled: true
      - name: github
        transport: stdio
        command: npx
        args: ["-y", "@anthropic/mcp-server-github"]
        env:
          GITHUB_TOKEN: "ghp_xxxxx"
        enabled: true
      - name: remote-search
        transport: sse
        url: "http://mcp-search:8080/sse"
        enabled: true
        overrides: ["@webfetch", "@websearch"]  # hides built-ins when connected
Or reference an existing ConfigMap:
spec:
  mcp:
    enabled: true
    existingConfigMap: "my-mcp-servers"
The controller automatically:
  1. Generates a ConfigMap <instance>-mcp with mcp_servers.json
  2. Mounts at /etc/chatcli/mcp/ (read-only)
  3. Passes --mcp-config /etc/chatcli/mcp/mcp_servers.json to the container
The MCPSpec CRD mirrors the mcp_servers.json format exactly. Each MCPServerSpec field maps to a JSON field β€” including overrides for built-in shadowing.

Checking Status

The MCP Manager exposes the status of each server:
statuses := mcpMgr.GetServerStatus()
for _, s := range statuses {
    fmt.Printf("Server: %s, Connected: %v, Tools: %d\n",
        s.Name, s.Connected, s.ToolCount)
}
To check if a tool is MCP:
if mcpMgr.IsMCPTool("mcp_read_file") {
    result, err := mcpMgr.ExecuteTool(ctx, "read_file", args)
}

ServerDescriptionInstallation
@anthropic/mcp-server-filesystemFile system accessnpx -y @anthropic/mcp-server-filesystem /path
@anthropic/mcp-server-githubGitHub integrationnpx -y @anthropic/mcp-server-github
@anthropic/mcp-server-postgresPostgreSQL queriesnpx -y @anthropic/mcp-server-postgres
@anthropic/mcp-server-slackSlack integrationnpx -y @anthropic/mcp-server-slack
Check modelcontextprotocol.io for the complete list of available MCP servers.

MCP in Client Mode (TTY)

MCP now works directly in interactive mode (TTY), not just server mode. ChatCLI auto-detects ~/.chatcli/mcp_servers.json and initializes servers automatically on startup.
MCP tools are exposed across all 3 modes:
ModeHow it works
ChatTools listed in system prompt as informational context
AgentTools invocable via <tool_call name="mcp_<tool>" args='...' />
CoderSame mechanism as Agent mode

Deferred Schemas (Token Savings)

To save tokens in the system prompt, ChatCLI uses deferred schemas:
  1. Only name + description are sent in the prompt (lightweight)
  2. When the model invokes a tool without arguments, the full schema is returned as feedback
  3. The model then re-invokes with the correct arguments
This can save hundreds of tokens per turn when many MCP tools are connected.

/mcp Command

Manage MCP servers directly from the interactive terminal. Every subcommand that takes a server name has autocomplete β€” press Tab after /mcp <subcommand> to list the configured servers.
SubcommandArgumentDescription
/mcp or /mcp status [name]OptionalStatus of all servers (no name) or a specific one
/mcp tools [name]OptionalAll tools (no name) or only those of <name>
/mcp start <name>RequiredStart a stopped server (or one that failed to start)
/mcp stop <name>RequiredStop a server without removing it from config β€” start revives it later
/mcp restart [name]OptionalRestart one server (with name) or all (no name)
/mcp reloadβ€”Re-read mcp_servers.json and reconcile (same logic as hot-reload, on demand)
/mcp logs <name>RequiredLast 200 stderr lines from the server (in-memory ring buffer)

Example: status and logs

> /mcp status

╭── πŸ”Œ MCP SERVERS
β”‚  ● filesystem    connected     3 tools  (2m 15s)
β”‚  ● web-search    connected     2 tools  (2m 15s)
β”‚  β—‹ database      disconnected
β”‚    ↳ start MCP server "mcp-postgres": exec: not found
β”‚
β”‚  Total: 3 servers, 5 tools available
╰──────────────────────────────────────────────────────

> /mcp logs filesystem

╭── πŸ“œ MCP LOGS β€” filesystem
β”‚  Server starting on /workspace
β”‚  Loaded 12 file watchers
β”‚  Tool list: read_file, write_file, list_dir
╰──────────────────────────────────────────────────────

Start/stop semantics

ScenarioBehavior
/mcp stop foo on a running serverKills the process, drops its tools; keeps the entry in the manager
/mcp start foo after stopRevives using the in-memory config; tools come back
Hot-reload (JSON edit) while foo is user-stoppedReload respects the manual stop; restarts only if foo’s config changed
/mcp restart (no name)Stop all + start all with a new mcpCtx β€” equivalent to a full reset
/mcp restart fooStop + start of foo only, preserving the global ctx and the other servers
Server that failed at startup (LastError set)/mcp start foo clears LastError and retries β€” useful after fixing command/env
Difference between /mcp restart and /mcp reload:
  • /mcp restart forces a restart even if the config didn’t change (useful for β€œreload credentials” after editing shell env).
  • /mcp reload is a diff-and-apply against mcp_servers.json β€” nothing that hasn’t changed gets restarted.

Per-server log buffer

Each stdio server keeps a 200-line ring buffer fed from the child process’s stderr. That means:
  • /mcp logs <name> shows the last 200 lines without enabling --debug;
  • Chatty servers don’t grow memory unboundedly β€” old lines drop off the front;
  • Captures like npm 404, panic stacks and startup messages stay available even after startup ends.
Useful combo for diagnosing connection issues: /mcp status (state), then /mcp logs <name> (the why). No need to restart with CHATCLI_LOG_LEVEL=debug.

Push notifications β€” MCP Channels

Beyond tools (request/response), ChatCLI accepts push notifications from any MCP server across all three transports. Notifications are JSON-RPC messages without id (the spec form for β€œthe server wants to tell me something, it isn’t asking for anything back”). ChatCLI captures, persists, and automatically injects them into the next conversations, and β€” optionally β€” fires the agent via trigger rules.

The essentials

  • Works on stdio, sse, and http β€” each transport has its own listener:
    • sse: the GET /sse that already carries tool responses receives notifications on the same stream.
    • http: a separate GET on the endpoint (opt-in by the client, optional by the spec) pulls notifications. Servers that don’t support it respond with 405/404/501 and the listener stops cleanly, no retries.
    • stdio: JSON-RPC lines on stdout without id are treated as notifications.
  • Durable persistence at ~/.chatcli/mcp/channels.jsonl (up to 10 MiB, rotates, replays on boot).
  • Auto-injection of the 5 most recent in the system prompt of chat/agent/coder (uncached so cache isn’t trashed).
  • Per-server filter: channels field in mcp_servers.json accepts a literal allow-list.
  • Optional rules engine in ~/.chatcli/mcp/triggers.json with 3 modes: notify (discreet banner, default), confirm (manual yes/no), auto (runs the agent β€” requires tool whitelist).
  • Slash commands: /channel list, /channel ack, /channel pause, /channel rules, /channel confirm <id>, /channel run <seq>, /channel inject.

Minimal example β€” server with channels

{
  "name": "prom-alerts",
  "transport": "sse",
  "url": "https://prom-alerts.internal/sse",
  "enabled": true,
  "channels": ["alerts/critical", "alerts/error"]
}
With that, alerts land in /channel list, show up in the next prompt banner, and are auto-injected into the agent context.

Example β€” trigger that investigates CI failures

~/.chatcli/mcp/triggers.json:
{
  "rules": [
    {
      "name": "ci-investigator",
      "server": "ci-monitor",
      "channel": "ci-pipeline",
      "contentRegex": "(?i)fail|broken",
      "mode": "confirm",
      "prompt": "Investigate this CI failure: {{content}}",
      "rateLimit": "5m"
    }
  ]
}
Every CI failure asks the user with a prompt in the banner; /channel confirm <id> accepts and the agent starts investigating.
Full channels, rules, and troubleshooting docs: MCP Channels. Complete channels schema and triggers.json reference: MCP Config.

Next steps

MCP Channels

Push messages across all three transports (stdio, sse, http) with durable persistence, per-server filter, and a rules engine (notify/confirm/auto).

Agentic plugins

ChatCLI’s plugin system β€” compared with MCP.

Native Tool Use

Native Anthropic/OpenAI APIs that power MCP under the hood.

MCP Config

Full mcp_servers.json format and examples.