anthropics / anthropics/claude-code

[FEATURE] Expose the resolved MCP tool catalogue to plugins: add `inputSchema`/`outputSchema` to `$.tool.list()`

未关闭
#90,131 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
area:mcp area:plugins enhancement
主要语言
Python
星标
145k
派生
23.1k
PR 合并指标
PR 指标待抓取

描述

### Preflight Checklist

- [x] I have searched [existing requests](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20label%3Aenhancement) and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)

### Problem Statement

### Use case

We build a security product that inventories and governs MCP servers on managed developer
endpoints. For each configured MCP server we need its **declared** tool surface — names,
descriptions, `inputSchema` — to inventory what an endpoint can reach, and to validate
`tools/call` arguments against the schema the server declared.

Scope: we are not asking for anything not already resident in the Claude Code process, and not
asking to read user conversation content.

### Why hooks are not sufficient

Hooks fire on `tools/call`, so we see only the tools someone happened to invoke, by name, with no
schema. A server can expose forty tools and we see the three that were used.

### Proposed Solution

### Asks, in priority order

1. **Add `inputSchema` and `outputSchema` to `$.tool.list()`.** The data is already resident; this
is a field addition, and the one change that unblocks schema validation.
2. **Ship `tengu_plugin_hooks_modules`** — or provide any supported way for a plugin to read the
resolved MCP tool catalogue. The flag is not in the served payload at all, so the seam is
unreachable, not merely disabled.
3. **Lift or make configurable the 300-char description truncation**, or return the untruncated
description on a catalogue-oriented call. Truncation that is fine for prompt-building is lossy
for inventory.
4. **Provide a non-interactive path.** Inventory collection is not an interactive activity;
requiring a bound interactive session rules out the scanning context entirely.
5. Lower priority: a stable, documented way to read the catalogue **without** parsing the private
transcript format.

### Alternative Solutions

### What we do today, and why we would rather not

Our fallback parses the session transcript (`~/.claude/projects//.jsonl`), whose
`deferred_tools_delta` attachment lists every MCP tool name on connect — complete, including
never-invoked tools, but names only, with `.` irreversibly sanitized to `_`. That is
unsatisfactory for both sides: it is a private format with no stability contract (its shape
changed between 2.1.246 and 2.1.247), and it means a security agent reads files containing **user
conversation content** just to obtain a tool list. A supported catalogue API would let us stop
touching those files — which we think is the strongest reason to do this.

### Priority

High - Significant impact on productivity

### Feature Category

MCP server integration

### Use Case Example

_No response_

### Additional Context

### What we measured (Claude Code 2.1.247)

- A plugin's `hooks/hooks.json` may declare `modules: ["./register.js"]`; Claude Code loads it
into a `node:vm` and passes a capability object of ~32 ops, including `$.tool.list()`.
- `$.tool.list()` returns exactly `{name, description, mcp}` — **no `inputSchema`, no
`outputSchema`** — and `description` is hard-truncated at 300 characters (a 616-char
description came back cut mid-word, no ellipsis).
- The seam is gated on the GrowthBook flag `tengu_plugin_hooks_modules`, which is **absent from
the served feature payload entirely** (556 features fetched) — not off for this user, but not
shipped to this client population.
- `$.tool.describe` is referenced in the bundle but is `undefined` at runtime.
- `$.tool.list()` refuses to run headlessly: *"not available in this mode: no interactive session
is bound in this process (a `-p` run or the SDK)"*.
- The schema **is** in the process: Claude Code's own `/mcp` panel renders both `Description:`
and `Parameters:` per tool. So omitting `inputSchema` from `$.tool.list()` is an API-shape
choice, not a data-availability limit.

Happy to test a build behind a flag.

#### Appendix — verbatim measurements (Claude Code 2.1.247)

| Observation | Detail |
|---|---|
| Plugin module seam | `hooks/hooks.json` → `modules: ["./register.js"]`, loaded into a `node:vm`, called with a capability object of ~32 ops including `$.tool.list()` |
| `$.tool.list()` shape | `{name, description, mcp}` — no `inputSchema`, no `outputSchema` |
| Description truncation | Hard cut at 300 chars; a 616-char description returned cut mid-word, no ellipsis |
| Gating flag | `tengu_plugin_hooks_modules` — absent from the served feature payload (556 features fetched); not present-and-false |
| `$.tool.describe` | Referenced in the bundle, `undefined` at runtime |
| Headless behaviour | `$.tool.list()`: *"not available in this mode: no interactive session is bound in this process (a `-p` run or the SDK)"* |
| Data is resident | `/mcp` panel renders `Description:` and `Parameters:` per tool |
| Transcript fallback | `~/.claude/projects//.jsonl`, `deferred_tools_delta` attachment, written on connect; complete tool-name list incl. never-invoked tools; names only; `.` → `_`, irreversible; shape changed between 2.1.246 and 2.1.247 |

贡献指南

这个仓库没有索引到贡献指南

调研方向

Start with hooks/hooks.json and its modules entry, then examine the plugin capability object around $.tool.list() and the reported interactive-session restriction. Done means plugins can access the resolved MCP catalogue with inputSchema and outputSchema through a supported path, with the requested truncation and non-interactive behavior addressed or explicitly scoped.

由索引模型根据 Issue 内容生成。

评估

技术栈
javascript, node.js
领域
api, devtools, tooling
Issue 类型
功能
难度
5/5
预计耗时
一周以上
活跃度
活跃
描述清晰度
基本清楚
新手友好度
35/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。