modelcontextprotocol / modelcontextprotocol/python-sdk
Tool input schemas carry a pydantic-derived title on every property
還沒有人認領這個 Issue。
- 主要語言
- Python
- 星號
- 24.3k
- 分支
- 4k
- 平均合併
- 1 天 1 小時
- 30 天內合併 PR
- 31
描述
Description
Every tool's inputSchema carries a title on every property, derived by pydantic from the field name. A parameter named exercise_id gets "title": "Exercise Id" — a restatement of the key it already sits under. Tool schemas are re-sent to the model on every request, so this is paid for in context on every turn.
I ran into this running a local 27B model against the wger MCP server, where context is genuinely scarce. Measuring its live tools/list:
| bytes | share | |
|---|---|---|
| whole payload, 49 tools | 43,710 | 100% |
| tool descriptions (prose) | 10,904 | 25% |
auto-derived title keys (297 of them) |
8,333 | 19% |
anyOf null-wrapping on optionals |
1,869 | 4% |
My agent is granted 43 of those tools, which is ~11,100 tokens of schema against a 32k window — 42% of the context gone before the first message, once the system prompt is counted. Roughly 2,000 of those tokens are titles.
Reproduction — any tool at all:
from mcp.server.mcpserver import MCPServer
mcp = MCPServer("demo")
@mcp.tool()
def log_set(exercise_id: str, reps: int) -> str:
"""Log a set."""
return "ok"
inputSchema.properties is:
{
"exercise_id": {"title": "Exercise Id", "type": "string"},
"reps": {"title": "Reps", "type": "integer"}
}
I'd expect the titles not to be there, since they add nothing a model can act on that the property name doesn't already say.
GenerateJsonSchema has a hook for exactly this — field_title_should_be_set — and Tool.from_function already passes a custom generator elsewhere in the file, so it's a small change. Suppressing the automatic titles leaves an explicit Field(title=...) intact, which seems like the right line to draw: an explicit title is the author's choice, an auto-derived one is a default nobody asked for.
Two things I'd want a maintainer's call on before this is worth doing:
- Default or opt-in. Changing the default updates 12 test expectations in this repo (mostly
snapshot(...)intests/docs_src/), so it's visible. An opt-in flag onMCPServer(...)avoids that but adds public API. - Scope. Output schemas, prompts and resource templates generate titles the same way. Output schemas alone are another 61 titles in the payload I measured. Worth doing together, or separately?
Happy to open a PR if it's useful — I have the change and the test updates working locally against main, full suite green. Equally happy to leave it if you'd rather write it yourselves.
Disclosure: I used an AI agent to take the measurements and draft the change. The problem is one I actually hit, and I've read and can explain the result.
References
field_title_should_be_set— https://docs.pydantic.dev/latest/api/json_schema/#pydantic.json_schema.GenerateJsonSchema.field_title_should_be_set- Server measured — https://github.com/wger-project/mcp-server
貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
研究方向
從 Tool.from_function 及其現有的自訂產生器開始,接著檢查 Pydantic 的 GenerateJsonSchema.field_title_should_be_set hook。查看 tests/docs_src/ 中的快照預期,並與 maintainer 一起決定這項變更是否只涵蓋輸入 schema,還是也涵蓋其他產生的 schema。完成的標準是移除自動產生的屬性標題,同時保留明確指定的 Field 標題,並更新受影響的測試且使其通過。
由索引模型根據 Issue 內容生成。
評估
- 技術堆疊
- python
- 領域
- api, backend
- Issue 類型
- 功能
- 難度
- 3/5
- 預估耗時
- 1-2 天
- 活躍度
- 活躍
- 描述清晰度
- 基本清楚
- 新手友好度
- 52/100