
ToolUniverse Tool Creator
FreeEfficiently create scientific tools for the ToolUniverse framework.
Free · Opens the source repo
What ToolUniverse Tool Creator does
The ToolUniverse Tool Creator is designed for developers looking to create new scientific tools within the ToolUniverse framework. This skill provides a structured approach to tool creation, ensuring that tools are implemented with proper validation, error handling, and testing. It guides users through the process of adding tools, implementing API integrations, and creating tool wrappers for scientific databases or services. By following established patterns, users can avoid common pitfalls that lead to tool failures.
This skill emphasizes the importance of adhering to the ToolUniverse contribution guidelines. It includes critical information on the two-stage architecture required for tool registration and operation. Users will learn how to define tool classes and automatically generate wrappers for various operations, ensuring that their tools are both functional and compliant with the framework's requirements. The comprehensive implementation guide outlines the necessary files to create, from the tool class to JSON configurations and testing scripts.
The ToolUniverse Tool Creator also highlights the top mistakes that lead to tool failures, such as misconfigured parameters and inadequate testing. By providing a checklist and detailed instructions, it helps users build robust tools that meet the framework's standards. This skill is particularly useful for developers and researchers who are looking to expand the capabilities of ToolUniverse with new tools that integrate seamlessly into the existing ecosystem.
When to use it
Use this skill when you need to develop new scientific tools or integrate APIs into the ToolUniverse framework.
When not to use it
This skill is not suitable for general-purpose programming tasks outside of the ToolUniverse framework.
What you can build with it
Creating a New API Tool
Use this skill to develop a new tool that integrates with a scientific API, following the provided templates and guidelines.
Validating Existing Tools
Leverage the validation and testing features of this skill to ensure your existing tools comply with ToolUniverse standards.
Expanding ToolUniverse Capabilities
Implement new functionalities or services within the ToolUniverse framework by creating and registering new tools.
How to install ToolUniverse Tool Creator
View source1. Install with the skills CLI
npx skills add mims-harvard/tooluniverse/devtu-create-tool --agent claude-code2. Or install it manually
Download the skill folder and drop it into ~/.claude/skills/ for all projects, or .claude/skills/ to scope it to one repo. Restart Claude Code so it picks up the new skill.
Anthropic's agentic coding CLI, and the reference implementation of Agent Skills. Drop a skill folder into ~/.claude/skills and Claude Code loads it automatically whenever a task matches the skill's description. Claude Code docs
Inside SKILL.md
Written by mims-harvardToolUniverse Tool Creator
Create new scientific tools following established patterns.
Top 7 Mistakes (90% of Failures)
- Missing
default_config.pyEntry — tools silently won't load - Non-nullable Mutually Exclusive Parameters — validation errors (#1 issue in 2026)
- Fake test_examples — tests fail, agents get bad examples
- Single-level Testing — misses registration bugs
- Skipping
test_new_tools.py— misses schema/API issues - Tool Names > 55 chars — breaks MCP compatibility
- Raising Exceptions — should return error dicts instead
Two-Stage Architecture
Stage 1: Tool Class Stage 2: Wrappers (Auto-Generated)
@register_tool("MyTool") MyAPI_list_items()
class MyTool(BaseTool): MyAPI_search()
def run(arguments): MyAPI_get_details()
One class handles multiple operations. JSON defines individual wrappers. Need BOTH.
Three-Step Registration
Step 1: Class registration via @register_tool("MyAPITool")
Step 2 (MOST COMMONLY MISSED): Config registration in default_config.py:
TOOLS_CONFIGS = {
"my_category": os.path.join(current_dir, "data", "my_category_tools.json"),
}
Step 3: Automatic wrapper generation on tu.load_tools()
Implementation Guide
Files to Create
src/tooluniverse/my_api_tool.py— implementationsrc/tooluniverse/data/my_api_tools.json— tool definitionstests/tools/test_my_api_tool.py— tests
Python Tool Class (Multi-Operation Pattern)
from typing import Dict, Any
from tooluniverse.tool import BaseTool
from tooluniverse.tool_utils import register_tool
import requests
@register_tool("MyAPITool")
class MyAPITool(BaseTool):
BASE_URL = "https://api.example.com/v1"
def __init__(self, tool_config):
super().__init__(tool_config)
self.parameter = tool_config.get("parameter", {})
self.required = self.parameter.get("required", [])
def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
operation = arguments.get("operation")
if not operation:
return {"status": "error", "error": "Missing: operation"}
if operation == "search":
return self._search(arguments)
return {"status": "error", "error": f"Unknown: {operation}"}
def _search(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
query = arguments.get("query")
if not query:
return {"status": "error", "error": "Missing: query"}
try:
response = requests.get(
f"{self.BASE_URL}/search",
params={"q": query}, timeout=30
)
response.raise_for_status()
data = response.json()
return {"status": "success", "data": data.get("results", [])}
except requests.exceptions.Timeout:
return {"status": "error", "error": "Timeout after 30s"}
except requests.exceptions.HTTPError as e:
return {"status": "error", "error": f"HTTP {e.response.status_code}"}
except Exception as e:
return {"status": "error", "error": str(e)}
JSON Configuration
[
{
"name": "MyAPI_search",
"class": "MyAPITool",
"description": "Search items. Returns array of results. Supports Boolean operators. Example: 'protein AND membrane'.",
"parameter": {
"type": "object",
"required": ["operation", "query"],
"properties": {
"operation": {"const": "search", "description": "Operation (fixed)"},
"query": {"type": "string", "description": "Search term"},
"limit": {"type": ["integer", "null"], "description": "Max results (1-100)"}
}
},
"return_schema": {
"oneOf": [
{"type": "object", "properties": {"data": {"type": "array"}}},
{"type": "object", "properties": {"error": {"type": "string"}}, "required": ["error"]}
]
},
"test_examples": [{"operation": "search", "query": "protein", "limit": 10}]
}
]
Critical Requirements
- return_schema MUST have oneOf: success + error schemas
- test_examples MUST use real IDs: NO "TEST", "DUMMY", "PLACEHOLDER"
- Tool name <= 55 chars:
{API}_{action}_{target}template - Description 150-250 chars: what, format, example, notes
- NEVER raise in run(): return
{"status": "error", "error": "..."} - Set timeout on all HTTP requests (30s)
- Standard response:
{"status": "success|error", "data": {...}}
Parameter Design
Mutually Exclusive Parameters (CRITICAL — #1 issue)
When tool accepts EITHER id OR name, BOTH must be nullable:
{
"id": {"type": ["integer", "null"], "description": "Numeric ID"},
"name": {"type": ["string", "null"], "description": "Name (alternative to id)"}
}
Without "null", validation fails when user provides only one parameter.
Common cases: id OR name, gene_id OR gene_symbol, any optional filters.
API Key Configuration
Optional keys (tool works without, better with):
{"optional_api_keys": ["NCBI_API_KEY"]}
self.api_key = os.environ.get("NCBI_API_KEY", "") # Read from env only
Required keys (tool won't work without):
{"required_api_keys": ["NVIDIA_API_KEY"]}
Rules: Never add api_key as tool parameter for optional keys. Use env vars only.
Testing (MANDATORY)
Full guide: references/testing-guide.md
Quick Testing Checklist
- Level 1 — Direct class test: import class, call
run(), check response - Level 2 — ToolUniverse test:
tu.tools.YourTool_op1(...), check registration - Level 3 — Real API test: use real IDs, verify actual responses
- MANDATORY — Run
python scripts/test_new_tools.py your_tool -v→ 0 failures
Verification Script
# Check all 3 registration steps
python3 -c "
import sys; sys.path.insert(0, 'src')
from tooluniverse.tool_registry import get_tool_registry
import tooluniverse.your_tool_module
assert 'YourToolClass' in get_tool_registry(), 'Step 1 FAILED'
from tooluniverse.default_config import TOOLS_CONFIGS
assert 'your_category' in TOOLS_CONFIGS, 'Step 2 FAILED'
from tooluniverse import ToolUniverse
tu = ToolUniverse(); tu.load_tools()
assert hasattr(tu.tools, 'YourCategory_op1'), 'Step 3 FAILED'
print('All 3 steps verified!')
"
Quick Commands
python3 -m json.tool src/tooluniverse/data/your_tools.json # Validate JSON
python3 -m py_compile src/tooluniverse/your_tool.py # Check syntax
grep "your_category" src/tooluniverse/default_config.py # Verify config
python scripts/test_new_tools.py your_tool -v # MANDATORY test
References
- Testing guide: references/testing-guide.md
- Advanced patterns (async, SOAP, pagination): references/advanced-patterns.md
- Implementation guide (full checklist): references/implementation-guide.md
- Tool improvement checklist: references/tool-improvement-checklist.md
Frequently asked questions about ToolUniverse Tool Creator
Similar skills
WinMD API Search
Easily find and explore Windows desktop APIs.
WebMCPify
Transform any web app into an agent-ready platform.
Phoenix Tracing
Instrument LLM applications with OpenInference tracing.
Foundry Hosted Agent CopilotKit
Guidance for developing agentic web apps on Azure.
Power Automate Foundation
Connect AI agents to Power Automate seamlessly.
Power Automate Flow Builder
Efficiently build and deploy Power Automate flows programmatically.
