github / github/copilot-cli

Gemini Flash: one malformed MCP array enum breaks all prompts with HTTP 400

オープン
#4,835 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

triage
主要言語
Shell
スター
11.2k
フォーク
1.9k
平均マージ
14時間 16分
マージ済み PR(30日)
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
  1. Save schema-repro.mjs, gemini-bad.json, and gemini-fixed.json from the Reproducer files section below in the same directory. Node.js must be available.
  2. 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": ["*"]
    }
  }
}

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

schema-repro.mjs、gemini-bad.json、gemini-fixed.json から始め、次に再現手順にある 2 つのネイティブな Copilot コマンドを実行して、失敗するケースと成功するケースを確認します。Gemini リクエストが送信される前に、MCP ツールスキーマがどこで処理されるかを追跡します。完了条件は、配列レベルの不正な enum が schema_repro、probe_000、/properties/levels/enum を示す実用的なエラーを生成するか、汎用的な 400 の代わりにプロバイダーの検証詳細を公開することです。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
javascript, node.js
領域
api, cli
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
活発
明瞭さ
おおむね明確
初心者へのやさしさ
50/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。