devtu-fix-tool by mims-harvard/tooluniverse
npx skills add https://github.com/mims-harvard/tooluniverse --skill devtu-fix-tool通过系统性的错误识别、针对性修复和验证,诊断并修复失效的 ToolUniverse 工具。
在编写任何修复之前,先问:用户为什么会进入这个失败状态?
需要避免的反模式:
在实现任何错误报告之前,首先通过 CLI 验证:
python3 -m tooluniverse.cli run <ToolName> '<json_args>'
许多代理报告的错误是由 MCP 接口混淆导致的误报。在实施修复之前,务必确认错误是可复现的。
修复失效工具时:
python scripts/test_new_tools.py <tool-pattern> -v
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
验证 API 是否正确 - 在线搜索官方 API 文档,确认端点、参数和模式正确
识别错误类型(参见错误类型部分)
根据错误模式应用适当的修复
如果修改了 JSON 配置或工具类,则重新生成工具:
python -m tooluniverse.generate_tools
tests/tools/ 中):ls tests/tools/test_<tool-name>_tool.py
验证修复,重新运行集成测试和单元测试
提供修复摘要,包括问题、根本原因、解决方案和测试结果
| 问题类型 | 需要修改的文件 |
|---|---|
| 二进制响应 | src/tooluniverse/*_tool.py + src/tooluniverse/data/*_tools.json |
| 模式不匹配 | src/tooluniverse/data/*_tools.json (return_schema) |
| 缺少数据包装器 | src/tooluniverse/*_tool.py (operation 方法) |
| 端点 URL | src/tooluniverse/data/*_tools.json (endpoint 字段) |
| 无效的测试示例 | src/tooluniverse/data/*_tools.json (test_examples) |
| 工具测试更新 | tests/tools/test_*_tool.py (如果存在) |
| API 密钥作为参数 | src/tooluniverse/data/*_tools.json (移除参数) + *_tool.py (使用环境变量) |
| 工具未加载(可选密钥) | src/tooluniverse/data/*_tools.json (使用 optional_api_keys 而非 required_api_keys) |
症状:Expecting value: line 1 column 1 (char 0)
原因:工具期望 JSON 但接收到二进制数据(图像、PDF、文件)
修复:检查 Content-Type 头。对于二进制响应,返回描述字符串而不是解析 JSON。将 return_schema 更新为 {"type": "string"}。
症状:Schema Mismatch: At root: ... is not of type 'object' 或 Data: None
原因:缺少 data 字段包装器 或 错误的模式类型
修复取决于错误类型:
Data: None → 为所有 operation 方法添加 data 包装器(参见下面的多操作模式)return_schema:
{"type": "string"}{"type": "array", "items": {...}}{"type": "object", "properties": {...}}关键概念:模式验证的是 data 字段的内容,而不是完整的响应。
症状:Schema Mismatch: At N->fieldName: None is not of type 'integer'
原因:API 为可选字段返回 None/null
修复:在 JSON 配置中使用 {"type": ["<base_type>", "null"]} 允许可空类型。用于可选字段,而非必需标识符。
症状:当传递另一个参数时,出现 Parameter validation failed for 'param_name': None is not of type 'integer'
原因:工具接受 参数A 或 参数B(互斥),但两者都定义为固定类型。当只提供一个时,验证失败,因为另一个是 None。
示例:
{
"neuron_id": {"type": "integer"}, // ❌ 当使用 neuron_name 时失败
"neuron_name": {"type": "string"} // ❌ 当使用 neuron_id 时失败
}
修复:使互斥参数可空:
{
"neuron_id": {"type": ["integer", "null"]}, // ✅ 允许 None
"neuron_name": {"type": ["string", "null"]} // ✅ 允许 None
}
常见模式:
id 或 name 参数(通过 ID 或名称获取)acronym 或 name 参数(通过符号或全名搜索)重要提示:即使不是互斥的,也要使真正可选的参数(如 filter_field、filter_value)可空。
症状:Schema Mismatch: At N->field: {object} is not of type 'string', 'null'
原因:字段根据上下文返回不同的结构
修复:对于具有多个不同模式的字段,在 JSON 配置中使用 oneOf。这与可空类型({"type": ["string", "null"]})不同,后者是相同基础类型 + null。
症状:404 ERROR - Not found 或 400 Bad Request
原因:测试示例使用了无效/过期的 ID
修复:使用下面的 列表 → 获取 或 搜索 → 详情 模式来发现有效的示例。
症状:400 Bad Request 或参数验证错误
修复:使用正确的类型、必需字段和枚举更新 JSON 配置中的参数模式。
症状:当 API 密钥为可选时工具未加载,或者 api_key 参数导致混淆
原因:对应该为可选的密钥使用了 required_api_keys,或者将 API 密钥暴露为工具参数
关键区别:
required_api_keys:如果密钥缺失,工具被跳过optional_api_keys:工具加载并工作,无需密钥(性能可能降低)修复:对于无需密钥即可工作(但使用密钥有更好速率限制)的 API,在 JSON 配置中使用 optional_api_keys。仅从环境变量读取 API 密钥(os.environ.get()),切勿作为工具参数。
症状:对有效资源返回 404,或出现意外结果
修复:验证官方 API 文档 - 检查值属于 URL 路径还是查询参数。
症状:测试间歇性失败,出现超时/连接/5xx 错误
修复:在单元测试中对瞬态错误使用 pytest.skip() - 不要因为外部 API 中断而失败。
模式验证的是 data 字段的内容,而不是完整的响应。将 return_schema 类型与 data 内部的内容(数组、对象或字符串)匹配。
每个内部方法必须返回 {"status": "...", "data": {...}}。不要在顶层使用替代字段名。
当测试示例因 400/404 失败时,通过以下方式发现有效的 ID:
修复工具后,检查是否存在单元测试:
ls tests/tools/test_<tool-name>_tool.py
在以下情况下更新单元测试:
result["data"] 结构的断言# 运行特定工具测试
pytest tests/tools/test_<tool-name>_tool.py -v
# 运行所有单元测试
pytest tests/tools/ -v
tests/tools/test_<tool-name>_tool.py 是否存在有关详细的单元测试模式和示例,请参阅 unit-tests-reference.md。
python scripts/test_new_tools.py <pattern> -v
pytest tests/tools/test_<tool-name>_tool.py -v
修改 JSON 配置或工具类后:
python -m tooluniverse.generate_tools
在以下情况下重新生成:
src/tooluniverse/data/*_tools.json 文件测试脚本更改不需要重新生成。
修复后,提供此摘要:
问题:[简要描述]
根本原因:[失败原因]
解决方案:[所做的更改]
所做的更改:
集成测试结果:
单元测试结果(如适用):
关键:始终阅读工具的 JSON 配置或生成的包装器以获取正确的参数名称。不要假设参数名称。
错误测试示例:
# ❌ 错误 - 假设了参数名称
AllenBrain_search_genes(query='Gad1') # 失败:意外的关键字 'query'
正确方法:
# ✅ 正确 - 首先检查了配置
# 配置显示参数:gene_acronym, gene_name
AllenBrain_search_genes(gene_acronym='Gad1') # 成功!
如何找到正确的参数名称:
src/tooluniverse/data/*_tools.jsonsrc/tooluniverse/tools/<ToolName>.py测试多个工具时:
python -m tooluniverse.generate_tools工具可以返回不同的数据结构:
{"data": {"id": 1, "name": "..."}} - 单个结果{"data": [{"id": 1}, {"id": 2}]} - 多个结果{"data": "description text"} - 文本响应相应地进行测试:
# 对于对象数据
result = tool()
data = result.get('data', {})
value = data.get('field_name') # ✅
# 对于数组数据
result = tool()
items = result.get('data', [])
count = len(items) # ✅
first = items[0] if items else {} # ✅
data 字段,而非完整响应{"status": "...", "data": {...}} 包装器optional_api_keys| 任务 | 命令 |
|---|---|
| 运行集成测试 | python scripts/test_new_tools.py <pattern> -v |
| 运行单元测试 | pytest tests/tools/test_<tool-name>_tool.py -v |
| 检查是否存在单元测试 | ls tests/tools/test_<tool-name>_tool.py |
| 重新生成工具 | python -m tooluniverse.generate_tools |
| 检查状态 | `git status --short |
| 错误类型 | 修复位置 |
| --- | --- |
| JSON 解析错误 | src/tooluniverse/*_tool.py 中的 run() 方法 |
| 模式不匹配 | src/tooluniverse/data/*_tools.json 中的 return_schema |
| 404 错误 | src/tooluniverse/data/*_tools.json 中的 test_examples 或 endpoint |
| 参数错误 | src/tooluniverse/data/*_tools.json 中的参数模式 |
| 单元测试失败 | tests/tools/test_*_tool.py 中的断言 |
| 工具被跳过(可选密钥) | src/tooluniverse/data/*_tools.json 中使用 optional_api_keys |
| API 密钥作为参数 | 从 JSON 参数中移除,在 Python 中使用 os.environ.get() |
每周安装量
141
仓库
GitHub 星标数
1.2K
首次出现
2026年2月12日
安全审计
安装于
codex134
gemini-cli133
opencode133
github-copilot131
kimi-cli126
amp126
Diagnose and fix failing ToolUniverse tools through systematic error identification, targeted fixes, and validation.
Before writing any fix, ask: why does the user reach this failure state?
Anti-patterns to avoid:
Before implementing any bug report, verify it via CLI first :
python3 -m tooluniverse.cli run <ToolName> '<json_args>'
Many agent-reported bugs are false positives caused by MCP interface confusion. Always confirm the bug is reproducible before implementing a fix.
When fixing a failing tool:
python scripts/test_new_tools.py <tool-pattern> -v
Verify API is correct - search online for official API documentation to confirm endpoints, parameters, and patterns are correct
Identify error type (see Error Types section)
Apply appropriate fix based on error pattern
Regenerate tools if you modified JSON configs or tool classes:
python -m tooluniverse.generate_tools
tests/tools/:ls tests/tools/test_<tool-name>_tool.py
Verify fix by re-running both integration and unit tests
Provide fix summary with problem, root cause, solution, and test results
| Issue Type | File to Modify |
|---|---|
| Binary response | src/tooluniverse/*_tool.py + src/tooluniverse/data/*_tools.json |
| Schema mismatch | src/tooluniverse/data/*_tools.json (return_schema) |
| Missing data wrapper | src/tooluniverse/*_tool.py (operation methods) |
| Endpoint URL | src/tooluniverse/data/*_tools.json (endpoint field) |
| Invalid test example | src/tooluniverse/data/*_tools.json (test_examples) |
Symptom : Expecting value: line 1 column 1 (char 0)
Cause : Tool expects JSON but receives binary data (images, PDFs, files)
Fix : Check Content-Type header. For binary responses, return a description string instead of parsing JSON. Update return_schema to {"type": "string"}.
Symptom : Schema Mismatch: At root: ... is not of type 'object' or Data: None
Cause : Missing data field wrapper OR wrong schema type
Fix depends on the error :
Data: None → Add data wrapper to ALL operation methods (see Multi-Operation Pattern below)return_schema in JSON config:
{"type": "string"}{"type": "array", "items": {...}}{"type": "object", "properties": {...}}Key concept : Schema validates the data field content, NOT the full response.
Symptom : Schema Mismatch: At N->fieldName: None is not of type 'integer'
Cause : API returns None/null for optional fields
Fix : Allow nullable types in JSON config using {"type": ["<base_type>", "null"]}. Use for optional fields, not required identifiers.
Symptom : Parameter validation failed for 'param_name': None is not of type 'integer' when passing a different parameter
Cause : Tool accepts EITHER paramA OR paramB (mutually exclusive), but both are defined with fixed types. When only one is provided, validation fails because the other is None.
Example :
{
"neuron_id": {"type": "integer"}, // ❌ Fails when neuron_name is used
"neuron_name": {"type": "string"} // ❌ Fails when neuron_id is used
}
Fix : Make mutually exclusive parameters nullable:
{
"neuron_id": {"type": ["integer", "null"]}, // ✅ Allows None
"neuron_name": {"type": ["string", "null"]} // ✅ Allows None
}
Common patterns :
id OR name parameters (get by ID or by name)acronym OR name parameters (search by symbol or full name)Important : Also make truly optional parameters (like filter_field, filter_value) nullable even if not mutually exclusive.
Symptom : Schema Mismatch: At N->field: {object} is not of type 'string', 'null'
Cause : Field returns different structures depending on context
Fix : Use oneOf in JSON config for fields with multiple distinct schemas. Different from nullable ({"type": ["string", "null"]}) which is same base type + null.
Symptom : 404 ERROR - Not found or 400 Bad Request
Cause : Test example uses invalid/outdated IDs
Fix : Discover valid examples using the List → Get or Search → Details patterns below.
Symptom : 400 Bad Request or parameter validation errors
Fix : Update parameter schema in JSON config with correct types, required fields, and enums.
Symptom : Tool not loading when API key is optional, or api_key parameter causing confusion
Cause : Using required_api_keys for keys that should be optional, or exposing API key as tool parameter
Key differences :
required_api_keys: Tool is skipped if keys are missingoptional_api_keys: Tool loads and works without keys (with reduced performance)Fix : Use optional_api_keys in JSON config for APIs that work anonymously but have better rate limits with keys. Read API key from environment only (os.environ.get()), never as a tool parameter.
Symptom : 404 for valid resources, or unexpected results
Fix : Verify official API docs - check if values belong in URL path vs query parameters.
Symptom : Tests fail intermittently with timeout/connection/5xx errors
Fix : Use pytest.skip() for transient errors in unit tests - don't fail on external API outages.
Schema validates the data field content, not the full response. Match return_schema type to what's inside data (array, object, or string).
Every internal method must return {"status": "...", "data": {...}}. Don't use alternative field names at top level.
When test examples fail with 400/404, discover valid IDs by:
After fixing a tool, check if unit tests exist:
ls tests/tools/test_<tool-name>_tool.py
Update unit tests when you:
result["data"] structure# Run specific tool tests
pytest tests/tools/test_<tool-name>_tool.py -v
# Run all unit tests
pytest tests/tools/ -v
tests/tools/test_<tool-name>_tool.py existsFor detailed unit test patterns and examples, see unit-tests-reference.md.
python scripts/test_new_tools.py <pattern> -v
pytest tests/tools/test_<tool-name>_tool.py -v
After modifying JSON configs or tool classes:
python -m tooluniverse.generate_tools
Regenerate after:
src/tooluniverse/data/*_tools.json filesNot needed for test script changes.
After fixing, provide this summary:
Problem : [Brief description]
Root Cause : [Why it failed]
Solution : [What was changed]
Changes Made :
Integration Test Results :
Unit Test Results (if applicable):
CRITICAL : Always read the tool's JSON config or generated wrapper to get the correct parameter names. Don't assume parameter names.
Example of incorrect testing :
# ❌ WRONG - assumed parameter name
AllenBrain_search_genes(query='Gad1') # Fails: unexpected keyword 'query'
Correct approach :
# ✅ RIGHT - checked config first
# Config shows parameters: gene_acronym, gene_name
AllenBrain_search_genes(gene_acronym='Gad1') # Works!
How to find correct parameter names :
src/tooluniverse/data/*_tools.jsonsrc/tooluniverse/tools/<ToolName>.pyWhen testing multiple tools:
python -m tooluniverse.generate_tools after all JSON changesTools can return different data structures:
{"data": {"id": 1, "name": "..."}} - single result{"data": [{"id": 1}, {"id": 2}]} - multiple results{"data": "description text"} - text responseTest accordingly :
# For object data
result = tool()
data = result.get('data', {})
value = data.get('field_name') # ✅
# For array data
result = tool()
items = result.get('data', [])
count = len(items) # ✅
first = items[0] if items else {} # ✅
data field, not full response{"status": "...", "data": {...}} wrapperoptional_api_keys for APIs that work without keys| Task | Command |
|---|---|
| Run integration tests | python scripts/test_new_tools.py <pattern> -v |
| Run unit tests | pytest tests/tools/test_<tool-name>_tool.py -v |
| Check if unit tests exist | ls tests/tools/test_<tool-name>_tool.py |
| Regenerate tools | python -m tooluniverse.generate_tools |
| Check status | `git status --short |
| Error Type | Fix Location |
| --- | --- |
| JSON parse error |
Weekly Installs
141
Repository
GitHub Stars
1.2K
First Seen
Feb 12, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
codex134
gemini-cli133
opencode133
github-copilot131
kimi-cli126
amp126
Azure Data Explorer (Kusto) 查询技能:KQL数据分析、日志遥测与时间序列处理
130,600 周安装
Sonos CLI 命令行工具:本地网络控制 Sonos 音箱,支持分组、收藏、Spotify 搜索
708 周安装
SwiftData 教程:iOS 26+ 数据持久化、查询与管理完整指南
709 周安装
Lightpanda 无头浏览器 - Zig 语言构建,AI 自动化与网页抓取利器,速度提升11倍
693 周安装
Apple端侧AI开发指南:Core ML、Foundation Models、MLX Swift与llama.cpp选择与优化
699 周安装
AutoResearchClaw:全自动AI研究流水线,从主题到完整学术论文(含LaTeX格式)
697 周安装
Vue Pinia单元测试指南:组件、组合函数与状态管理测试最佳实践
711 周安装
| Tool test updates | tests/tools/test_*_tool.py (if exists) |
| API key as parameter | src/tooluniverse/data/*_tools.json (remove param) + *_tool.py (use env var) |
| Tool not loading (optional key) | src/tooluniverse/data/*_tools.json (use optional_api_keys not required_api_keys) |
src/tooluniverse/*_tool.py run() method |
| Schema mismatch | src/tooluniverse/data/*_tools.json return_schema |
| 404 errors | src/tooluniverse/data/*_tools.json test_examples or endpoint |
| Parameter errors | src/tooluniverse/data/*_tools.json parameter schema |
| Unit test failures | tests/tools/test_*_tool.py assertions |
| Tool skipped (optional key) | src/tooluniverse/data/*_tools.json use optional_api_keys |
| API key as parameter | Remove from JSON params, use os.environ.get() in Python |