Skip to main content
Glama
byyshka

kimi-bridge

by byyshka

kimi-bridge

An MCP server that makes a locally installed Kimi Code CLI available inside Claude Code as a second agent.

This bridge is aimed at 1C:Enterprise development, and it is worth being precise about where that shows. The machinery — spawning the CLI, parsing its stream, sessions, timeouts, the summary of tools actually called — is general. The 1C part is one tool: kimi_review casts Kimi as a BSL reviewer and tells it to verify metadata through its graph servers.

That tool is registered only in the default profile. The neutral profile exposes kimi_ask alone, so nothing 1C-flavoured reaches a general-purpose setup. If you do not work with 1C you get a solid second-agent bridge without a review tool; if you do, you get a reviewer that checks attributes against real metadata instead of recalling them.

Set up the Kimi CLI first

This bridge is a thin adapter: it spawns the Kimi CLI and parses its output. It installs nothing and authenticates nothing.

  1. Install the CLI — through npm, and pinned.

    npm i -g @moonshot-ai/kimi-code@0.31.1
    kimi login

    Two things are deliberate here.

    The version is pinned because that is the one this bridge's stream parsing was written against and tested on. @latest currently resolves to the 2.x line, which is untested here — see the version note above before reaching for it.

    Install through npm, not the one-line installer. Moonshot also publishes irm https://code.kimi.com/kimi-code/install.ps1 | iex, which drops a kimi binary on PATH. This bridge does not use that binary: it spawns dist/main.mjs through node directly, because the kimi shim is a .cmd wrapper and would force shell: true, breaking argv escaping for prompts with quotes or non-ASCII text. If you already installed that way, point KIMI_BRIDGE_ENTRY at a dist/main.mjs you do have — otherwise the bridge will list the paths it tried and stop.

    Login is a device-code OAuth flow against a Kimi subscription; an API key works too. Confirm the CLI works on its own before wiring up the bridge:

    kimi -p "reply with one word: ok" --output-format stream-json
  2. Give Kimi its own MCP servers — this is the part that takes real time, and the part that makes the bridge worth having. Kimi reads its own mcp.json (on Windows, %USERPROFILE%\.kimi-code\mcp.json; $KIMI_CODE_HOME moves it), entirely separate from your Claude configuration. Nothing here configures those servers and nothing is inherited from Claude's set — consult Kimi's own documentation for the file's schema.

    The file is a map of server names to launch configs:

    {
      "mcpServers": {
        "some-stdio-server": {
          "type": "stdio",
          "command": "npx",
          "args": ["-y", "some-mcp-package"],
          "env": { "SOME_TOKEN": "..." }
        },
        "some-http-server": {
          "type": "http",
          "url": "http://localhost:8080/mcp"
        }
      }
    }

    Without them you get a second opinion from memory. With them you get an agent that checks a claim before answering — and the footer on every reply tells you which of the two you got.

  3. Know which instruction files Kimi actually reads. Measured, not assumed: Kimi picks up AGENTS.md and the skill list under .agents/skills/. It does not read CLAUDE.md, RULES.md or anything in .claude/rules/. Any convention you expect the delegated agent to honour has to live in AGENTS.md — a rule kept only in CLAUDE.md never reaches it, silently.

Related MCP server: Kimi MCP Server

Why a second agent at all

Kimi runs with its own MCP servers, configured in its own home directory, independent of Claude's. In the setup this was built for those are 1C metadata graphs, code embeddings, a syntax checker and standards lookups. That makes the difference between "a second model that agrees with you" and a reviewer that can check whether an attribute actually exists before answering.

Kimi also has a 1M-token context and opens files itself, so a 70 KB module passed by path costs the caller nothing.

Requirements

  • Node.js ≥ 20.11 for this bridge — but see the version note below, the CLI wants more

  • Kimi Code CLI, installed so that its dist/main.mjs exists on disk: npm i -g @moonshot-ai/kimi-code@0.31.1, then kimi login — pinned deliberately, see below

  • Optionally, MCP servers configured in Kimi's own mcp.json — that is where the value comes from

Windows only. Built and tested on Windows 11. There are POSIX branches in the code, but they are neither tested nor supported.

Version note — read this before installing

Verified against kimi-code 0.31.1. The stream parsing here is written to that version's NDJSON records. The published CLI has since moved to the 2.x line, and this bridge has not been tested against it; if the record shapes changed, the bridge will return "no answer" while the CLI itself works fine. Pin the CLI or expect to adjust parseStreamJson.

The CLI needs Node ≥ 22.19, even though the bridge itself runs on 20.11. Installing it under Node 20 fails on the engines check. If you are on 20.x, the bridge will run but you will have no CLI to drive.

Install it through npm, pinned to that version — the setup section below gives the command and explains why the one-line Windows installer is the wrong route here.

Install

git clone https://github.com/byyshka/kimi-bridge.git
cd kimi-bridge
npm install
npm test          # optional: runs offline, needs neither the Kimi CLI nor a login

claude mcp add kimi-bridge --scope user -- node C:\path\to\kimi-bridge\index.mjs

Restart the client afterwards. The claude CLI has to be installed already.

Tools

kimi_ask(prompt, files?, cwd?, session_id?, model?, timeout_sec?)

An open question or a delegated analysis. Pass files as paths for Kimi to open itself rather than pasting their contents.

session_id continues a previous thread — right for iterating on one artifact, wrong for a second opinion, where carrying context over means inheriting the first answer's assumptions.

kimi_review(subject, target, focus?, files?, known_good?, budget_tool_calls?, cwd?, model?, timeout_sec?)

A review with a fixed output contract: verdict, findings, confirmed by tools, could not check. The last section is mandatory — "nothing" is an answer, silence is not.

It takes no session_id on purpose: a review always starts a fresh session, because a reviewer holding the author's context inherits the author's blind spots.

Every answer says what it was based on

Each reply ends with the tools Kimi actually called. When there were none, it says so outright:

Kimi called NO tools — this answer is from the model's own knowledge, not verified against anything.

That line is the whole point. Without it, an answer recalled from training data is indistinguishable from one checked against your metadata.

Two profiles from one binary

Register the same file twice under different names to have both: a tooled agent for questions about your codebase, and an isolated one for everything else, where an answer from the model's own knowledge is the honest form.

Two variables, and both are needed. KIMI_BRIDGE_PROFILE=neutral changes only what this server advertises — its name, its tool descriptions, and the fact that kimi_review is not registered. Which MCP servers Kimi actually has is decided by KIMI_CODE_HOME, which the child process inherits. Setting the profile alone gives you a tooled Kimi wearing a description that says it has no tools, which is worse than either honest state.

{
  "mcpServers": {
    "kimi-bridge": {
      "type": "stdio",
      "command": "node",
      "args": ["C:\\path\\to\\kimi-bridge\\index.mjs"]
    },
    "kimi-clean": {
      "type": "stdio",
      "command": "node",
      "args": ["C:\\path\\to\\kimi-bridge\\index.mjs"],
      "env": {
        "KIMI_BRIDGE_PROFILE": "neutral",
        "KIMI_CODE_HOME": "C:\\path\\to\\a\\kimi-home-with-empty-mcp-json",
        "KIMI_BRIDGE_LOG_DIR": "C:\\path\\to\\kimi-bridge\\logs-clean"
      }
    }
  }
}

The two register different tool descriptions on purpose. A description promising metadata verification, sitting in front of a profile with no tools, is exactly how an unverified answer gets read as a checked one.

What it looks like in use

Pass files by path — Kimi opens them itself, so their text never enters the calling agent's context:

kimi_ask({
  prompt: "Does ПолучитьЦенуНоменклатуры handle an empty price type? Answer yes or no with " +
          "the line number, and say so plainly if you could not check.",
  files: ["src/CommonModules/Ценообразование/Module.bsl"]
})
Нет. Строка 47: при пустом виде цены запрос вернёт пустую выборку, и функция вернёт 0
вместо ошибки — вызывающий код не отличит «цена нулевая» от «цена не найдена».

---
Kimi called 2 tool(s):
  Read(path=src/CommonModules/Ценообразование/Module.bsl)
  search_metadata(operation=list_attributes, object=Справочник.ВидыЦен)
Took 24.1s.
session_id: session_0bd086c7 (pass it back as session_id to continue this thread)

The footer is the part to read first — but read which tools, not how many. The count includes plain file reads, so two calls can mean "it opened the module" rather than "it checked the metadata". Kimi called NO tools is the only unambiguous signal, and it means the answer came from the model's own knowledge.

When it does not work

Kimi Code CLI entrypoint not found The error lists every path that was tried. Under nvm, fnm or volta the global root moves with the active Node version — if none of the listed paths is right, set KIMI_BRIDGE_ENTRY to your dist/main.mjs directly.

Kimi answers, but the reply ends with Kimi called NO tools The answer came from the model's own knowledge. For a question of fact about your codebase that is not a verified answer — name the files in files, or check whether Kimi's own mcp.json actually has the servers you expect.

The server starts and nothing happens: exit 0, no output, no error The entry-point check. Reached through a symlink or junction, Node resolves import.meta.url to the link target while argv[1] keeps the path as spawned, so a naive comparison concludes the file was imported rather than run and never calls main(). This bridge compares resolved real paths (case-insensitively on Windows) for exactly that reason.

A run ends with a libuv assertion on Windows Expected, and handled: kimi-code trips it while tearing down handles, after the answer is already on stdout. The bridge trusts the parsed answer over the exit code.

Environment variables

Variable

Default

Meaning

KIMI_BRIDGE_ENTRY

auto-detected

Absolute path to dist/main.mjs. Wins over detection.

KIMI_BRIDGE_PROFILE

default

neutral registers kimi_ask only.

KIMI_CODE_HOME

Kimi's default

Which Kimi home (and thus which MCP set) to use.

KIMI_BRIDGE_LOG

off

Set to 1 to enable the call log.

KIMI_BRIDGE_LOG_DIR

logs/ next to index.mjs

Where the log is written. Not relative to the working directory.

If the CLI cannot be found, the error lists every path that was tried.

Logging is off by default

With KIMI_BRIDGE_LOG=1 every call is appended to logs/YYYY-MM-DD.jsonl — prompt, answer, tools called, timings. Useful for working out why Kimi got something wrong, and nobody's business by default, so it stays off until you ask.

Behaviour worth knowing

  • Exit codes are not trusted. kimi-code trips a libuv assertion on Windows while tearing down handles, after the answer is already on stdout. A parsed answer therefore wins over exit status.

  • The CLI is spawned as node dist/main.mjs, not through the kimi shim. The shim is a .cmd/.ps1 wrapper, which would force shell: true and break argv escaping for prompts holding quotes, newlines or non-ASCII text.

  • A timeout fails the call. A truncated answer is never returned as though it were complete.

  • Kimi narrates while it works, and each narration line is an assistant record shaped exactly like the real answer. The bridge takes the text after the last tool call as the answer.

  • No background job layer, deliberately. An earlier version grew one; the premise was false, since killing the bridge kills the child anyway. Claude Code already backgrounds any call running past two minutes.

  • No sandbox. Kimi runs with permission to write in its working directory. Pass cwd deliberately.

License

MIT

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    F
    maintenance
    The self-hosted MCP bridge between Claude Chat and Claude Code.
    46
    AGPL 3.0
  • A
    license
    Not graded
    quality
    D
    maintenance
    An MCP bridge that enables Claude Code to consult the Kimi AI model in a structured challenge-loop for code review, debugging, and architecture evaluation.
    18 npm
    2
    MIT