From mims-harvard-tooluniverse
Fixes failing ToolUniverse tools by diagnosing test failures, identifying root causes, implementing fixes in Python tool files/JSON, and validating via CLI and tests. Use for ToolUniverse errors or schema issues.
npx claudepluginhub joshuarweaver/cascade-data-analytics --plugin mims-harvard-tooluniverseThis skill uses the workspace's default tool permissions.
Diagnose and fix failing ToolUniverse tools through systematic error identification, targeted fixes, and validation.
Conducts multi-round deep research on GitHub repos via API and web searches, generating markdown reports with executive summaries, timelines, metrics, and Mermaid diagrams.
Dynamically discovers and combines enabled skills into cohesive, unexpected delightful experiences like interactive HTML or themed artifacts. Activates on 'surprise me', inspiration, or boredom cues.
Generates images from structured JSON prompts via Python script execution. Supports reference images and aspect ratios for characters, scenes, products, visuals.
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) |
| 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) |
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 | grep -E "(data|tools|.*_tool.py|tests/tools)" |
| Error Type | Fix Location |
|---|---|
| JSON parse error | 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 |