Skip to content

fix(ai): add types to untyped enums in Moonshot tool schemas - #50961

Merged
rekram1-node merged 1 commit into
v2from
moonshot-enum-types
Sep 23, 2026
Merged

rekram1-node merged 1 commit into
v2from
moonshot-enum-types

Conversation

@rekram1-node

@rekram1-node rekram1-node commented Sep 23, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Moonshot's Chat Completions API rejects any tool schema node that has an enum but no type:

Invalid request: tools.function.parameters is not a valid moonshot flavored json schema,
details: <At path 'properties.requestBody.properties.kind': type is not defined>

The whole request fails, not just the tool. OpenAPI-derived MCP tools often omit the type. For example, Vercel's MCP create_flag tool has kind: {"description": "The kind of flag", "enum": ["boolean", "string", "number", "json"]}, so enabling that server breaks every Kimi request on the Moonshot chat route, which is the default route for moonshotai. Found while surveying provider schema limits for #50297.

Verified live against kimi-k3 and kimi-k2.6:

  • The rule applies wherever the node appears: properties, anyOf branches, items, additionalProperties, and $defs.
  • const without a type, {}, $ref, and typed anyOf branches are accepted.
  • type may be one type, or a pair with "null" (["string", "null"]). Other type arrays such as ["string", "number"] are rejected.

Change

packages/ai/src/protocols/utils/tool-schema.ts: the moonshot projection adds a type derived from the enum values to any node that has an enum and no type:

  • one JSON type → that type (all numbers become "number")
  • one type plus null → [type, "null"]
  • mixed non-null types → left unchanged, since Moonshot has no valid type for them

The added type matches every enum value, so the schema still accepts the same values.

Verification

  • test/tool-schema-projection.test.ts: untyped enums under properties, anyOf, items, additionalProperties, and $defs; numeric, boolean, and nullable enums; typed and mixed enums left unchanged. Fails without the change.
  • Live through the V2 client (Moonshot.chat("kimi-k3")), each of the 21 Vercel MCP request bodies that contain an untyped enum as a tool: 11/21 rejected before, 21/21 accepted after.
  • Live tool use on kimi-k3 and kimi-k2.6 (3 trials each): the models called the projected tools, and every call validated against the original schema. create_flag for an on/off flag picked kind: "boolean" in 6/6. A synthetic tool with untyped integer, nullable, anyOf, items, additionalProperties, and boolean enums produced exactly the expected arguments in 12/12, including 3 (not "3"), null (not "null"), and false (not "false").
  • bun test in packages/ai: 1497 pass. bun run check: 35/35.

Moonshot's Chat Completions API rejects any tool schema node with an
`enum` but no `type` ("type is not defined"), wherever it appears:
properties, anyOf branches, items, additionalProperties, and $defs.
OpenAPI-derived MCP tools often omit the type, so one such tool fails
every Kimi request.

The Moonshot projection now derives the type from the enum values. Moonshot
accepts one type or one type plus "null", so enums mixing other types are
left unchanged.
@rekram1-node
rekram1-node merged commit fb4422e into v2 Sep 23, 2026
11 of 12 checks passed
@rekram1-node
rekram1-node deleted the moonshot-enum-types branch September 23, 2026 20:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant