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 with 21st_….
- 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. prefix m_ for leading
digits, replace invalid chars with _), keeping a bidirectional map for the
response path.
- Recursively coerce schemas: force root
type: "object" when properties is
present; when anyOf/oneOf appears 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.
Environment: kimi-cli 1.49.0 · macOS (arm64) · Model: K3 via Moonshot API
The API rejects such requests with:
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 toolsnamed:
MCP places no constraint on the leading character of tool names. The Moonshot API,
however, rejects any request whose
tools[].function.namebegins with a digit:the names start with
21st_….m_21st_magic_*(letter first) makes theexact 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 rewritenon-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), toolapi_impact, declares thisinputSchema — 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
anyOfwith per-branchrequired, combined with the empty sibling"required": [].Rewriting the schema to drop the empty
requiredand resolve theanyOf(movingthe constraint into the description) makes the identical tool call succeed.
Related: some servers omit the root
"type": "object"entirely; coercing itclient-side is trivial and harmless.
(For completeness: GitNexus fixed the
anyOfpart upstream in 1.6.10-rc viaPR #2489 — verified by auditing all 17 tool schemas on
gitnexus@rc. Theclient-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
toolsto the API, kimi-cli could:^[A-Za-z][A-Za-z0-9_-]*$(e.g. prefixm_for leadingdigits, replace invalid chars with
_), keeping a bidirectional map for theresponse path.
type: "object"whenpropertiesispresent; when
anyOf/oneOfappears alongside sibling keywords, either inlinethe 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
Happy to provide the proxy source or test a fix.