MoonshotAI / MoonshotAI/kimi-cli
MCP tool names & schemas rejected by Moonshot API (HTTP 400) — sanitize client-side before sending
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 11.4k
- Forks
- 1.3k
- Avg merge
- 9h 47m
- Merged PRs (30d)
- 2
Description
Environment: kimi-cli 1.49.0 · macOS (arm64) · Model: K3 via Moonshot API
The API rejects such requests with:
Error: [provider.api_error] 400 tools.function.parameters is not a valid
moonshot flavored json schema, details: <At path 'root': when using anyOf,
type should be defined in anyOf items instead of the parent schema>
Summary
Several spec-valid MCP servers cannot be used with kimi-cli, because the Moonshot
chat-completions endpoint rejects their tool definitions with HTTP 400. The MCP
spec itself allows these names/schemas — other API consumers handle them fine.
kimi-cli (or the API) should normalize tool definitions before the request.
Problem 1: Tool names starting with a digit → HTTP 400
The MCP server @21st-dev/magic (a popular UI-component generator) exposes tools
named:
21st_magic_component_builder
21st_magic_component_inspiration
21st_magic_component_refiner
...
MCP places no constraint on the leading character of tool names. The Moonshot API,
however, rejects any request whose tools[].function.name begins with a digit:
- Same session, same prompt, same tools — the call fails with HTTP 400 as long as
the names start with21st_…. - Renaming the identical tools to
m_21st_magic_*(letter first) makes the
exact same calls succeed. No other change.
Ask: Either relax the API-side pattern (e.g. OpenAI-compatible
^[a-zA-Z0-9_-]{1,64}$, which permits leading digits), or have kimi-cli rewrite
non-conforming tool names client-side (with a stable mapping so results route back
to the correct MCP tool).
Problem 2: Strict JSON-Schema subset rejects valid MCP schemas
Example: gitnexus@1.6.9 (npx gitnexus mcp), tool api_impact, declares this
inputSchema — valid JSON Schema (2020-12):
{
"type": "object",
"properties": {
"route": { "type": "string", "description": "Route path (e.g., \"/api/grants\")" },
"file": { "type": "string", "description": "Handler file path (alternative to route)" },
"method": { "type": "string" },
"repo": { "type": "string" },
"branch": { "type": "string" }
},
"required": [],
"anyOf": [
{ "required": ["route"] },
{ "required": ["file"] }
]
}
The API rejects it (HTTP 400). The offending constructs appear to be the root-level
anyOf with per-branch required, combined with the empty sibling "required": [].
Rewriting the schema to drop the empty required and resolve the anyOf (moving
the constraint into the description) makes the identical tool call succeed.
Related: some servers omit the root "type": "object" entirely; coercing it
client-side is trivial and harmless.
(For completeness: GitNexus fixed the anyOf part upstream in 1.6.10-rc via
PR #2489 — verified by auditing all 17 tool schemas on gitnexus@rc. The
client-side problem for kimi-cli remains: any spec-valid server can still hit
these rejections, e.g. digit-led tool names or other combinator patterns.)
Suggested fix (client-side, minimal)
Before sending tools to the API, kimi-cli could:
- Rewrite names to
^[A-Za-z][A-Za-z0-9_-]*$(e.g. prefixm_for leading
digits, replace invalid chars with_), keeping a bidirectional map for the
response path. - Recursively coerce schemas: force root
type: "object"whenpropertiesis
present; whenanyOf/oneOfappears alongside sibling keywords, either inline
the siblings into each branch or drop the conflicting sibling with a note in
description.
This is exactly what our local workaround does (a FastMCP stdio proxy between
kimi-cli and the upstream server). It works, but every user of these servers
shouldn't need to build their own proxy — the sanitization belongs in the client
(or the API validation should be relaxed).
Repro
# 1. magic (name problem)
kimi mcp add magic -- npx -y @21st-dev/magic@latest
# ask anything that loads tools -> HTTP 400
# 2. gitnexus (schema problem)
kimi mcp add gitnexus -- npx -y gitnexus@latest mcp
# ask anything that loads tools -> HTTP 400
Happy to provide the proxy source or test a fix.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the kimi-cli MCP tool serialization path before requests are sent to the Moonshot API, using the two kimi mcp add reproductions in the issue. Trace how tool names and schemas are forwarded and how tool results are routed back. Done means digit-led names and the shown schema forms no longer produce HTTP 400, while responses still reach the original MCP tools.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api, cli
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100