Skip to main content
Glama
README.md
# kimi-cli-mcp

MCP server that delegates coding tasks to your **locally installed**
[Kimi Code](https://github.com/MoonshotAI/kimi-code) CLI (`kimi`).

It wraps the real `kimi` binary instead of bundling its own copy of the agent, so every call
inherits your kimi auth, models and `~/.kimi-code` config. Nothing about your model stack is
duplicated here, and the server does not drift when you upgrade kimi.

Sibling of [pi-cli-mcp](https://github.com/minmax/pi-cli-mcp), [qwen-cli-mcp](https://github.com/minmax/qwen-cli-mcp) and
[grok-cli-mcp](https://github.com/minmax/grok-cli-mcp) — same architecture, same principles, kimi behind the wheel.

Use it when your primary agent should hand work to native Kimi as it already does to pi / qwen / grok.

Verified against kimi **0.41.0** (`~/.kimi-code/bin/kimi`) and native source
`kimi-code@aad4a7df2`.

## Install

Requires Node ≥ 22 and a working `kimi` on `PATH`.

This package is **not** activated automatically. Add it only when you want a
separate MCP named `kimi`.

### Claude Code (example — do not run unless you intend to activate)

Clone and build from source (not yet published to npm):

```bash
git clone https://github.com/minmax/kimi-cli-mcp.git
cd kimi-cli-mcp
npm ci
npm run build

claude mcp add-json kimi -s user "{
  \"type\": \"stdio\",
  \"command\": \"node\",
  \"args\": [\"$(pwd)/dist/index.js\"],
  \"timeout\": 3600000
}"
```

Or with an explicit binary:

```json
{
  "mcpServers": {
    "kimi": {
      "command": "node",
      "args": ["/absolute/path/to/kimi-cli-mcp/dist/index.js"],
      "env": { "KIMI_MCP_BIN": "/absolute/path/to/kimi" }
    }
  }
}
```

Keep the server name short (`kimi`): it becomes part of the tool names your model sees.

> **⚠️ Default ACP approval mode is `yolo`.** Delegation is only useful when the
> delegate can act. Print mode (`transport: "print"`) already executes tools
> without confirmation; combining `-p` with `-y` is a CLI error and this adapter
> never does that.

## Tools

| Tool | Purpose |
|---|---|
| `kimi` | Start a session. Returns `[session: <id>]`, the result, and stats. |
| `kimi_reply` | Continue a finished or interrupted session — including one killed by a timeout. |
| `kimi_models` | List models this install has configured (`kimi provider list --json`). |
| `kimi_send` | Deliver into a turn executing right now (`abort` / `steer` / `follow_up`). ACP only. |
| `kimi_running` | List turns executing right now that `kimi_send` can reach. |
| `kimi_sessions` | List known sessions started through this server, newest first. |
| `kimi_history` | Read visible user/assistant/tool history from native `wire.jsonl` (bounded cursor). |

### `kimi`

| Argument | Notes |
|---|---|
| `prompt` | Required. Must be self-contained — kimi cannot see your conversation. |
| `cwd` | Absolute path; defaults to this server's cwd. |
| `model` | `-m` / ACP `session/set_config_option` model id. `kimi_models` lists values. |
| `approval_mode` | `yolo` \| `default` \| `auto` \| `plan`. ACP `session/set_mode`. Print cannot take `plan`. |
| `thinking` | ACP-only: `off` \| `on` \| `low` \| `medium` \| `high` \| `max`. |
| `add_dirs` | Comma-separated extra absolute dirs (`--add-dir` / ACP `additionalDirectories`). |
| `transport` | `acp` (default) or `print`. Usually omit. |
| `timeout_ms` | Wall clock for this run. Off unless you set it. |

**Not supported (honest error, not a fake flag):** `effort`, `allowed_tools`, `system_prompt_append`.
Kimi has no `--effort`; pick a model alias such as `stepfun-high/step-3.7-flash`. Prompt mode
already runs tools; `-y` with `-p` is rejected by the CLI.

```js
kimi({
  prompt: "Read and execute the prompt: /abs/path/prompt.md",
  cwd: "/abs/path/to/repo",
  model: "kimi-code/k3"
})

// later:
kimi_reply({
  session: "<id from the prefix>",
  prompt: "Now check the error paths of those call sites."
})
```

## What comes back

Only kimi's final result plus aggregate stats — never the transcript, thinking, tool arguments or raw stdout:

```
[session: session_0927adc5-a840-4b68-93ca-5ca344c9fafb]

Refactored retry() in src/http.rs; all 12 tests pass.

---
kimi: kimi-code/k3 · 1 turn · 5 tool calls: Read×2, Bash×2, Edit · 12s
kimi wrote: src/http.rs
```

On `acp` the text is assembled from `agent_message_chunk` updates (thought chunks dropped).
On `print` it is the last `role: assistant` `content` from `--output-format stream-json`
(thinking is not on that stream). Session identity comes from ACP `session/new` or print
`session.resume_hint`.

## Sessions

`kimi` returns a session id; `kimi_reply` resumes it with `session/load` (acp) or `-S` (print).
The conversation lives in kimi's own store (`~/.kimi-code/sessions/...`), so follow-ups keep
working across restarts of this server — the session → directory map is persisted in
`~/.local/state/kimi-mcp/sessions.json`.

Concurrent replies to one session are serialized per server process.

## Transports

| | `acp` (default) | `print` |
|---|---|---|
| command | `kimi acp` | `kimi -m … --output-format stream-json -S … -p …` |
| process | stays up, speaks ACP JSON-RPC | one process per turn, exits when done |
| mid-run delivery | `kimi_send` (interrupt / steer / follow_up) | impossible |
| follow-up | `session/load` then `session/prompt` | `-S <id>` |
| deadline / cancel | kimi's `session/cancel` first, signals as fallback | SIGTERM, then SIGKILL |

**This server never sends anything into kimi on its own.** `kimi_send` fires only when the caller calls it.

## History

`kimi_history` reads `$KIMI_CODE_HOME/sessions/<workspace>/<id>/agents/main/wire.jsonl`
without taking the session lock and without talking to a live process. Visible items are
user / assistant / tool / gap. Thought, encrypted blobs and reasoning are omitted. State is
`active` if this process is running the turn, otherwise `unknown` — a missing registry row
is not treated as completed. The cursor is always returned, including at EOF, so a later
append can be read; a partial trailing JSONL line is `truncated_tail`. Paths outside the
session store are rejected.

## Environment

| Variable | Default | Meaning |
|---|---|---|
| `KIMI_MCP_BIN` | `kimi` | Path to the kimi binary. |
| `KIMI_MCP_APPROVAL_MODE` | `yolo` | Default ACP mode for every call. |
| `KIMI_MCP_MODEL` | unset | Default model for every call. |
| `KIMI_MCP_TRANSPORT` | `acp` | Default transport: `acp` or `print`. |
| `KIMI_MCP_TIMEOUT_MS` | unset | Server-wide default wall clock; unset means no deadline. |
| `KIMI_MCP_MAX_TIMEOUT_MS` | `86400000` | Ceiling on what `timeout_ms` may ask for. |
| `KIMI_MCP_MAX_CONCURRENT` | `100` | Concurrent kimi processes. |
| `KIMI_MCP_MAX_OUTPUT` | unset | Cap on the answer. Unset means no truncation. |
| `KIMI_MCP_STDERR_LIMIT` | `1500` | stderr tail included in the response. |
| `KIMI_MCP_STDERR_KEEP_EVENTS` | unset | `1` forwards stderr verbatim, protocol lines included. |
| `KIMI_MCP_MAX_CAPTURE` | `16000000` | Read-buffer guard against a runaway stream. |
| `KIMI_MCP_MAX_LINE` | `8000000` | Longest single message line from kimi before it is dropped. |
| `KIMI_MCP_MAX_FRAME` | `8000000` | Longest single JSON-RPC frame from the client. |
| `KIMI_MCP_MAX_SESSIONS` | `200` | Remembered sessions before the oldest is dropped. |
| `KIMI_MCP_KILL_GRACE_MS` | `5000` | SIGTERM → SIGKILL grace period. |
| `KIMI_MCP_INTERRUPT_GRACE_MS` | `5000` | How long `session/cancel` gets before signals (acp only). |
| `KIMI_MCP_INIT_TIMEOUT_MS` | `15000` | Initialize-handshake timeout (acp only). |
| `KIMI_MCP_MODELS_TIMEOUT_MS` | `60000` | Whole-run budget for the `kimi_models` probe. |
| `KIMI_MCP_STATE` | `~/.local/state/kimi-mcp/sessions.json` | Session → cwd map. |
| `KIMI_MCP_WRAP` | unset | Command prefix, e.g. a sandbox wrapper around kimi. |
| `KIMI_CODE_HOME` | `~/.kimi-code` | Native kimi data root (forwarded to the child). |

## Development

TypeScript (native `tsc`), Biome, Vitest. Tests drive the real server binary over stdio against a
fixture that speaks kimi's protocol; live tests against the installed `kimi` are opt-in.

```bash
npm run hooks          # once per clone: git hooks from .githooks/
npm run build          # tsc -> dist/
npm test               # unit + type tests, no API access, no tokens
npm run test:live      # live tests against the real kimi binary (spends tokens)
npm run check          # format + types + tests
npm run fix            # biome --write
```

Verification: the deterministic suite passes; two opt-in live prompt tests are skipped.
The recorded live check covers model discovery only, not a real prompt/reply run.

## License

MIT

TDQS

A4.5/5.0

Scored across 7 tools

Disambiguation5/5

Each tool targets a distinct phase of the Kimi session lifecycle: start (kimi), resume (kimi_reply), message a running turn (kimi_send), list running (kimi_running), list all (kimi_sessions), read history (kimi_history), and list models (kimi_models). The overlapping pairs (reply/send, running/sessions) are explicitly differentiated by execution state.

Naming Consistency5/5

All tools share the kimi_ prefix with lowercase snake_case names. The only deviation is the root verb `kimi` itself for starting a new session, which is a natural base command; the pattern is otherwise uniform (kimi_ + verb/noun).

Tool Count5/5

Seven tools cover the full lifecycle of orchestrating a Kimi CLI agent: start, resume, send, list running/all, history, and models. This is well-scoped for the server's stated purpose without redundancy.

Completeness4/5

Core session lifecycle is well covered: start, reply, send while running, list running/all, read history, and list models. Missing an explicit cancel/stop operation for running turns, which is a minor gap but likely handled outside the tool surface.

Maintenance

ActivityMaintained
ResponsivenessNo issues