Gemini Flash: one malformed MCP array enum breaks all prompts with HTTP 400
還沒有人認領這個 Issue。
- 主要語言
- Shell
- 星號
- 11.2k
- 分支
- 1.9k
- 平均合併
- 14 小時 16 分鐘
- 30 天內合併 PR
- 6
描述
Type: Bug
Copilot CLI Version: 1.0.84-5
OS Version: Windows 11 x64
Model: gemini-3.7-flash
Summary
Having a single MCP tool whose schema contains an integer enum directly on an array property causes all requests to Gemini Flash to fail with an opaque HTTP 400 Bad Request error.
The error does not identify which MCP server, tool, or schema property caused the failure.
Steps to Reproduce
- Save
schema-repro.mjs,gemini-bad.json, andgemini-fixed.jsonfrom the Reproducer files section below in the same directory. Node.js must be available. - From that directory, run these native Copilot commands:
copilot --model gemini-3.7-flash --no-custom-instructions --additional-mcp-config "@gemini-bad.json" --available-tools schema_repro-probe_000 --allow-all-tools -p "Reply with exactly OK. Do not call tools."
copilot --model gemini-3.7-flash --no-custom-instructions --additional-mcp-config "@gemini-fixed.json" --available-tools schema_repro-probe_000 --allow-all-tools -p "Reply with exactly OK. Do not call tools."
Both commands advertise exactly one inert tool. There is no SDK dependency or shell helper.
The bad fixture defines:
{
"type": "object",
"properties": {
"levels": {
"type": ["array", "null"],
"items": { "type": "integer" },
"enum": [0, 1, 2, 3, 4, 25]
}
}
}
Actual Behaviour
The request immediately fails with:
Execution failed: 400 Bad Request (Request ID: ...)
Moving enum under items:
{
"type": ["array", "null"],
"items": {
"type": "integer",
"enum": [0, 1, 2, 3, 4, 25]
}
}
completely resolves the issue and the request succeeds.
Native CLI results:
| Input Schema | Advertised tools | Result |
|---|---|---|
enum on array level |
1 | HTTP 400 |
enum under items |
1 | OK |
Expected Behaviour
Copilot CLI should validate tool schemas client-side before sending them to the provider API, and report actionable errors identifying:
- Server name
- Tool name
- Schema property path
For this fixture: schema_repro, probe_000, and /properties/levels/enum.
Failing that, the error message should include the provider's validation details instead of a generic 400 error.
Notes
- Other schema constructs like plain integer enums (
{"type": "integer", "enum": [0, 1]}) and nullable objects work fine. - Related to #4623, but specifically caused by array-level enums rather than nullable object unions.
Impact
A single malformed tool schema from any active MCP server silently breaks all model calls to Gemini without any indication of which server or tool is at fault.
Reproducer files
schema-repro.mjs
import { createInterface } from 'node:readline';
const mode = process.argv[2];
const count = Number(process.argv[3] ?? 1);
const allowedModes = ['array-enum-bad', 'array-enum-fixed', 'count'];
if (!allowedModes.includes(mode) ||
!Number.isInteger(count) ||
count < 1 ||
count > 400) {
throw new Error('Usage: node schema-repro.mjs array-enum-bad|array-enum-fixed|count [1..400]');
}
const levels = { type: ['array', 'null'], items: { type: 'integer' } };
if (mode === 'array-enum-bad') {
levels.enum = [0, 1, 2, 3, 4, 25];
} else {
levels.items.enum = [0, 1, 2, 3, 4, 25];
}
const tools = Array.from({ length: mode === 'count' ? count : 1 }, (_, index) => ({
name: `probe_${String(index).padStart(3, '0')}`,
description: 'Schema diagnostic only; performs no operation.',
inputSchema: {
type: 'object',
properties: mode === 'count' ? { value: { type: 'string' } } : { levels },
},
}));
for await (const line of createInterface({ input: process.stdin, crlfDelay: Infinity })) {
if (!line.trim()) {
continue;
}
const request = JSON.parse(line);
if (request.id === undefined) {
continue;
}
let result;
if (request.method === 'initialize') {
result = {
protocolVersion: request.params.protocolVersion,
capabilities: { tools: {} },
serverInfo: { name: 'schema-repro', version: '1.0.0' },
};
} else if (request.method === 'tools/list') {
result = { tools };
} else if (request.method === 'tools/call') {
result = {
isError: true,
content: [{ type: 'text', text: 'This diagnostic never executes an operation.' }],
};
} else if (request.method === 'ping') {
result = {};
} else {
process.stdout.write(`${JSON.stringify({
jsonrpc: '2.0',
id: request.id,
error: { code: -32601, message: 'Method not found' },
})}\n`);
continue;
}
process.stdout.write(`${JSON.stringify({ jsonrpc: '2.0', id: request.id, result })}\n`);
}
gemini-bad.json
{
"mcpServers": {
"schema_repro": {
"type": "stdio",
"command": "node",
"args": ["schema-repro.mjs", "array-enum-bad"],
"tools": ["*"]
}
}
}
gemini-fixed.json
{
"mcpServers": {
"schema_repro": {
"type": "stdio",
"command": "node",
"args": ["schema-repro.mjs", "array-enum-fixed"],
"tools": ["*"]
}
}
}
貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
研究方向
從 schema-repro.mjs、gemini-bad.json 和 gemini-fixed.json 開始,接著執行重現步驟中的兩個原生 Copilot 命令,以確認失敗和成功的情況。追蹤在送出 Gemini 請求之前 MCP 工具 schema 的處理位置。完成的標準是:陣列層級的格式錯誤 enum 產生一個可採取行動的錯誤,其中指出 schema_repro、probe_000 和 /properties/levels/enum;或者公開 provider 的驗證詳細資訊,而不是通用的 400。
由索引模型根據 Issue 內容生成。
評估
- 技術堆疊
- javascript, node.js
- 領域
- api, cli
- Issue 類型
- 缺陷
- 難度
- 4/5
- 預估耗時
- 3-5 天
- 活躍度
- 活躍
- 描述清晰度
- 基本清楚
- 新手友好度
- 50/100