How-To · 15 min
Connect MCP servers
MCP runs in both directions here. Inward: connect any MCP server and its tools join Kaptain's catalog like built-ins. Outward: Kaptain itself is an MCP server named kaptain-engine, so your terminal CLIs get Kaptain's whole toolbelt.
Inward: add a server to Kaptain
Kaptain speaks all three MCP transports: stdio (a command it spawns), http (streamable-HTTP URL), and sse. You fill in a command or a URL — the transport follows from which one you filled. Install whatever the server itself needs first (Node/npx, Docker, a binary…) — Kaptain checks the launcher exists and refuses in plain language if it doesn't, before saving anything.
In the UI (Krew tab)
- Open the Krew view ▸ sidebar category MCP Servers.
- Add manually — name (lowercase id), command + arguments or remote URL, and one
KEY=VALUEper line (env vars for a local server, headers for a remote one). - Or + Add from JSON — paste the
{"mcpServers": …}block straight from any vendor README; the format is compatible on purpose. - Add & connect. The row shows live status, tool count, and errors on failure; per-row actions cover Enable/Disable, Reconnect, Remove, and OAuth sign-in where the server uses it.
Connected tools join the catalog under Native Tools, each with its own on/off switch.
The dialog, field by field — one dialog serves both kinds; you never pick a transport, it follows from what you fill in:
| Field | What to put in it |
|---|---|
| Name | a lowercase id, e.g. tavily — its tools appear under this name |
| Local command | the program Kaptain runs (npx, uvx, a binary path); empty for a remote server |
| Arguments | space-separated, e.g. -y some-mcp-server |
| Remote URL | a hosted endpoint, e.g. https://example.com/mcp; empty for a local server |
| Env / headers | one KEY=VALUE per line — env vars for a local server, request headers for a remote one; an API key goes here either way |
Will models call these tools by themselves? Yes — once a server is connected, enabled, and discovered, its tools join the tool set of every tool-capable run; if the active model picks one, Kaptain calls the server. You can also ask outright: "Use the GitHub MCP tool to list open pull requests."
Scoping an agent: a kapsule can be restricted to a subset of tools via the tools list in its kapsule.json (plus use_kapsule_tools to grant everything its own MCP section exposes). That allowlist lives in the file, not the Agents view; an agent with no allowlist uses the globally enabled tools.
From the terminal
kaptain mcp add tavily --env TAVILY_API_KEY=${TAVILY_API_KEY} -- npx -y tavily-mcp
kaptain mcp add linear --url https://mcp.linear.app/mcp
kaptain mcp add-json # paste a {"mcpServers":{…}} block, "-" = stdin
kaptain mcp list | enable | disable | remove <name>
Config lives in mcp_servers.json in the data folder — the same shape those README blocks use, so it's hand-editable too. The CLI updates a running Kaptain live; if none is running, the file takes effect on next start.
Keys and secrets
- Write
${VAR}in env/headers and it's expanded from the environment at connect time — the secret itself is never stored in the config file. - The UI shows key names only after saving; URLs are displayed with their secrets masked.
- OAuth servers use a real OAuth 2.1 + PKCE flow; tokens live in their own file, never in
mcp_servers.json.
Approval gating
External tools get the same human gate as built-ins — Ask blocks on the popup, Read-only denies mutations, Auto/Full run. A kapsule can pre-trust one server with a mcp:<name> trusted scope; everything else still asks. Only connect servers you understand — a tool is as powerful as its server.
Outward: Kaptain as a server for your CLIs
Kaptain's whole toolbelt — KodeGraph, file ops, web research, delegation, skills, agents — is one MCP server named kaptain-engine, started with kaptain mcp. There are two ways your Claude, Codex or Gemini CLI meets it, and they are different:
- Inside Kaptain (a kapsule or the Kaptain chat running on a CLI model): nothing to install. Kaptain starts the CLI and hands it the tool server for that session, wired to the kapsule's grants, its approval mode and its project folder.
- On your own (the CLI in a terminal or in VS Code): the CLI needs a registration — an entry in its own config that says "here is a tool server called kaptain-engine, start it with
kaptain mcp". You add it once per CLI.
Connect a CLI (one action)
Either press Register standalone in the CLI model's ⚙ popover next to the chat composer, or run one command:
kaptain mcp register claude
kaptain mcp register codex
kaptain mcp register gemini
What it writes, and where:
| CLI | How Kaptain registers | Where the entry lives | Check it |
|---|---|---|---|
| Claude Code | the CLI's own command: claude mcp add -s user kaptain-engine -- kaptain mcp | ~/.claude.json → mcpServers.kaptain-engine | claude mcp get kaptain-engine |
| Codex | a config block | ~/.codex/config.toml → [mcp_servers.kaptain-engine] | codex mcp list |
| Gemini CLI | a settings entry | Gemini's settings.json → mcpServers.kaptain-engine | the CLI's /mcp command |
Then, in that CLI on its own, ask for something that needs a Kaptain tool — "search this project with KodeGraph for where sessions are stored" — and watch the mcp__kaptain-engine__… call in its tool list. kaptain mcp install-status claude reports the registration from Kaptain's side; kaptain mcp health proves the server itself answers a tool call.
Updates and old entries
The registration points at your installed kaptain binary. After kaptain update, if a CLI reports the server missing, run kaptain mcp register <cli> again — it is safe to repeat. A refresh that does this for you on every update is in progress.
If you used an earlier Kaptain, your CLI config may still carry an old entry — commonly named kaptain-krew, or a kaptain-engine pointing at a binary that no longer exists. Remove those so the CLI has exactly one Kaptain:
claude mcp remove kaptain-krew # Claude
# Codex: delete the [mcp_servers.kaptain-krew] block from ~/.codex/config.toml
Inside Kaptain you are protected either way: when Kaptain drives a CLI it silences its own duplicate entries for that session and leaves every other server you registered untouched.
Long tool calls: a Kaptain tool that runs for minutes (a build, a test suite, a vision pass) is no longer abandoned by the CLI. The wait is 15 minutes by default, set with KAPTAIN_CLI_TOOL_TIMEOUT_S (seconds).
External tools through Kaptain
Servers you connected to Kaptain (the Inward half above) are re-served to your CLIs as ext__<server>__<tool>, with Kaptain's approval gate in front. The proxy answers only while your Kaptain is running — Kaptain off means those tools vanish rather than fail strangely.
kaptain mcp unregister claude # remove exactly what Kaptain added, nothing else
If it goes wrong
- Server row shows an error — the message is the real launcher/connect error; fix the runtime it names (npx missing, wrong URL…). Reconnect retries.
- Two servers expose a tool with the same name — for native models the first registered wins and the clash is reported on the server's row; CLI harnesses never clash (names are prefixed).
- Self-test:
kaptain mcp health(JSON, non-zero exit when unhealthy) andkaptain mcp smokevalidate the exact installed binary.
Agent-readable version: index.md · Every claim on this page was exercised on a real install before being written. Something missing that cost you time? That is a documentation bug — tell us.