Skip to content

Commit adb158e

Browse files
committed
Tighten MCP tool contracts (#1778 #1723 #1696)
1 parent 0a803d7 commit adb158e

9 files changed

Lines changed: 225 additions & 52 deletions

File tree

DEVELOPER_GUIDE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,8 @@ Process exit codes are coarse (`0` success including valid zero-row queries, `1`
978978
- **Structured MCP responses** — MCP tool calls return typed JSON in `structuredContent` and keep `content` concise for compatibility.
979979
- **MCP `batch_query` response cap**`batch_query` estimates the UTF-8 JSON size of aggregate slot results and stops appending once the response would exceed `CDIDX_MCP_BATCH_RESPONSE_MAX_BYTES` (default: 1,000,000 bytes, aligned with the JSON-RPC line cap). Truncated responses include `truncated: true`, `truncated_queries`, and byte-limit metadata so clients can split the batch or lower per-slot limits without parsing prose (#1416).
980980
- **MCP array argument bounds** — MCP string-array filters such as `path`, `project`, `excludePaths`, and mixed `names` arrays reject invalid entries instead of silently dropping them. Arrays are capped at 100 entries and each entry is capped at 4096 characters; `batch_query` reports these validation failures per slot with `request_index` and `ok: false`.
981+
- **MCP schema lock-down** — Every tool `inputSchema` includes `additionalProperties: false`, and `tools/call` mirrors that contract by rejecting unknown argument names with `-32602` / `invalid_argument` instead of silently defaulting misspelled fields.
982+
- **MCP stability markers and naming** — Every tool advertises `x-stability` (`stable`, `experimental`, or `deprecated`). MCP structured payload keys use snake_case, matching the CLI JSON contract; do not add camelCase aliases for new fields.
981983
- **MCP language-support clauses** — Every advertised MCP tool description ends with a `Language support:` clause generated through `McpServer.CreateToolDefinition`. Graph tools enumerate `ReferenceExtractor.GetSupportedLanguages()`, symbol tools enumerate `SymbolExtractor.GetSupportedLanguages()`, and file/content tools point at the detected-language catalog used by `cdidx languages`, so `tools/list` stays aligned with the runtime registries instead of carrying hand-maintained prose.
982984
- **MCP tool annotations** — All tools emit `annotations` with `readOnlyHint`, `destructiveHint`, `idempotentHint`, and `openWorldHint` per the MCP spec, so AI clients can auto-approve safe read-only queries.
983985
- **MCP server instructions** — The `initialize` response includes an `instructions` string with tool-selection guidance so AI clients can choose the right tool on first connection.
@@ -2550,6 +2552,8 @@ USER_GUIDEの[終了コード](USER_GUIDE.md#終了コード)セクションを
25502552
- **構造化MCPレスポンス** — MCPツール呼び出しは `structuredContent` に型付きJSONを返し、`content` は互換性のため簡潔に保つ。
25512553
- **MCP `batch_query` レスポンス上限**`batch_query` は集約した slot 結果の UTF-8 JSON サイズを見積もり、`CDIDX_MCP_BATCH_RESPONSE_MAX_BYTES`(既定: JSON-RPC 行上限と揃えた 1,000,000 bytes)を超える場合は追加を止める。切り詰めたレスポンスには `truncated: true``truncated_queries`、byte limit メタデータを含めるため、クライアントは prose を parsing せず batch 分割や slot limit 縮小を判断できる (#1416)。
25522554
- **MCP 配列引数の上限**`path` / `project` / `excludePaths` / mixed `names` などの string-array filter は、不正要素を暗黙に落とさず拒否する。配列は 100 件、各要素は 4096 文字を上限とし、`batch_query` では `request_index``ok: false` 付きの slot 失敗として報告する。
2555+
- **MCP schema のロックダウン** — すべての tool `inputSchema``additionalProperties: false` を含み、`tools/call` も同じ契約として未知の引数名を黙って既定値にせず `-32602` / `invalid_argument` で拒否する。
2556+
- **MCP stability marker と命名** — すべての tool は `x-stability``stable``experimental``deprecated`)を公開する。MCP の構造化 payload key は CLI JSON 契約に合わせて snake_case を使う。新規 field に camelCase alias を追加しないこと。
25532557
- **MCP の言語サポート句** — 公開されるすべての MCP ツール説明は、`McpServer.CreateToolDefinition` で生成される `Language support:` 句で終わる。Graph 系ツールは `ReferenceExtractor.GetSupportedLanguages()`、symbol 系ツールは `SymbolExtractor.GetSupportedLanguages()`、file/content 系ツールは `cdidx languages` と同じ検出言語カタログを参照するため、`tools/list` は手書き説明ではなく実行時レジストリと同期する。
25542558
- **MCPツールアノテーション** — 全ツールが MCP 仕様に沿った `annotations``readOnlyHint``destructiveHint``idempotentHint``openWorldHint`)を返し、AIクライアントが安全な読み取り専用クエリを自動承認できるようにする。
25552559
- **MCPサーバー instructions**`initialize` レスポンスにツール選択ガイダンスの `instructions` 文字列を含め、AIクライアントが初回接続時に適切なツールを選べるようにする。

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ file completion.
108108
| Search surfaces | CLI-first output for humans and machines; full-text, symbol, reference, caller/callee, dependency, map, inspect, and excerpt commands. |
109109
| Ranking and filters | Public/exported symbol matches rank ahead of protected, internal, and private matches. Use `--no-visibility-rank` for legacy order, and `--visibility` / `--exclude-visibility` with `symbols`, `definition`, `unused`, and `hotspots`. Query defaults can be adjusted with `CDIDX_DEFAULT_LIMIT`, `CDIDX_DEFAULT_SNIPPET_LINES`, and `CDIDX_DEFAULT_MAX_LINE_WIDTH`; explicit CLI flags still win. |
110110
| Project scoping | `.sln` / `.csproj`-aware <code>--project &lt;name&#124;path&gt;</code> filters for indexing and queries, plus `--solution <path>` when a workspace has multiple solution files. |
111-
| MCP integration | MCP server support for AI clients such as Claude Code, Cursor, and Windsurf, including tools, indexed-file resources, starter prompts, schema constraints for local argument validation, `mimeType` on text content blocks, logging, a compatibility server-side `notifications/initialized` ready signal on stdio or HTTP `/events` streams, and `Language support:` descriptions sourced from the same registries as `cdidx languages`. |
111+
| MCP integration | MCP server support for AI clients such as Claude Code, Cursor, and Windsurf, including tools, indexed-file resources, starter prompts, schema constraints for local argument validation, `mimeType` on text content blocks, logging, a compatibility server-side `notifications/initialized` ready signal on stdio or HTTP `/events` streams, and `Language support:` descriptions sourced from the same registries as `cdidx languages`. Tool schemas reject unknown arguments with `-32602`, advertise `x-stability`, and use snake_case structured JSON keys to match the CLI JSON contract. |
112112
| Freshness | Parallel full-scan extraction with `--parallelism`, incremental refreshes with `--files` and `--commits`, continuous `--watch`, exact `status --check`, and configurable stale thresholds via `--stale-after` / `CDIDX_STALE_AFTER`. |
113113
| Storage | Local-first `.cdidx/codeindex.db` storage. Query commands run from nested directories prefer the outermost ancestor `.cdidx/codeindex.db` before falling back to the current directory. `--data-dir <dir>`, `CDIDX_DATA_DIR`, or `XDG_DATA_HOME` can move default SQLite storage outside the workspace; explicit `--db <path>` still wins. |
114114
| DB maintenance | New indexes use SQLite incremental auto-vacuum. `cdidx vacuum` reclaims free pages from existing DBs, including a one-time full `VACUUM` conversion for legacy no-autovacuum DBs, and `status --json` reports metrics under `db_pragma_settings`. |
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
category: added
3+
issues:
4+
- 1696
5+
affected:
6+
- src/CodeIndex/Mcp/McpToolDefinitions.cs
7+
- README.md
8+
- DEVELOPER_GUIDE.md
9+
- tests/CodeIndex.Tests/McpServerTests.cs
10+
---
11+
12+
## English
13+
14+
- **MCP tools now publish stability markers (#1696)** — every advertised tool includes `x-stability`, with experimental tools marked explicitly in `tools/list`.
15+
16+
## 日本語
17+
18+
- **MCP tool が stability marker を公開するようになりました (#1696)** — 公開される全 tool に `x-stability` を追加し、experimental な tool は `tools/list` で明示します。
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
category: changed
3+
issues:
4+
- 1723
5+
affected:
6+
- src/CodeIndex/Mcp/McpServer.cs
7+
- src/CodeIndex/Mcp/McpToolHandlers.cs
8+
- tests/CodeIndex.Tests/McpServerTests.cs
9+
---
10+
11+
## English
12+
13+
- **MCP structured JSON now uses snake_case payload keys (#1723)** — manually assembled SQL/exact-signal payloads now align with the CLI JSON naming convention while preserving MCP protocol envelope fields.
14+
15+
## 日本語
16+
17+
- **MCP の構造化 JSON payload key を snake_case に統一しました (#1723)** — MCP protocol envelope field は維持しつつ、手組みの SQL / exact signal payload が CLI JSON の命名規則と揃いました。
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
category: fixed
3+
issues:
4+
- 1778
5+
affected:
6+
- src/CodeIndex/Mcp/McpToolDefinitions.cs
7+
- src/CodeIndex/Mcp/McpToolHandlers.cs
8+
- tests/CodeIndex.Tests/McpServerTests.cs
9+
---
10+
11+
## English
12+
13+
- **MCP tools now reject misspelled arguments (#1778)**`tools/list` schemas advertise `additionalProperties: false`, and `tools/call` returns an invalid-argument error when a request includes an unknown field.
14+
15+
## 日本語
16+
17+
- **MCP tool が綴り間違いの引数を拒否するようになりました (#1778)**`tools/list` schema は `additionalProperties: false` を公開し、`tools/call` は未知の field を含むリクエストに invalid-argument error を返します。

src/CodeIndex/Mcp/McpServer.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1999,7 +1999,16 @@ private async Task<JsonNode> HandleToolsCallAsync(JsonNode? id, JsonNode? callPa
19991999
JsonNode response;
20002000
try
20012001
{
2002-
if (ValidateCommonListArguments(args) is JsonObject listArgumentError)
2002+
if (ValidateToolArguments(toolName, args) is JsonObject argumentError)
2003+
{
2004+
metricsError = "invalid_argument";
2005+
response = CreateToolErrorResponse(id, argumentError["message"]!.GetValue<string>(),
2006+
category: McpErrorEnvelope.CategoryInvalidArgument,
2007+
suggestion: "Use exactly the argument names advertised by tools/list for this tool.",
2008+
retrySafe: false,
2009+
extraData: argumentError);
2010+
}
2011+
else if (ValidateCommonListArguments(args) is JsonObject listArgumentError)
20032012
{
20042013
metricsError = "invalid_list_argument";
20052014
response = CreateToolErrorResponse(id, listArgumentError["message"]!.GetValue<string>(),

0 commit comments

Comments
 (0)