11 KiB
11 KiB
title, task, lineage_type, upstream_source, upstream_sha, imported_at, prompt_class, upstream_changes, author, validated
| title | task | lineage_type | upstream_source | upstream_sha | imported_at | prompt_class | upstream_changes | author | validated |
|---|---|---|---|---|---|---|---|---|---|
| Quick Reference Guide | import | https://github.com/mims-harvard/ToolUniverse/blob/e2520a96/skills/devtu-create-tool/references/quick-reference.md | e2520a96 | 2026-06-26 | prompt | accepted | upstream | false |
Quick Reference Guide
Fast lookup for common ToolUniverse tool development tasks.
File Locations
src/tooluniverse/{category}_tool.py # Tool class
src/tooluniverse/data/{category}_tools.json # Configuration
tests/unit/test_{category}_tool.py # Unit tests
examples/{category}_tools_example.py # Example usage
src/tooluniverse/tools/{category}_*.py # Auto-generated (don't edit)
Basic Tool Class
from typing import Dict, Any
from .base_tool import BaseTool
from .tool_registry import register_tool
@register_tool("ToolName")
class ToolName(BaseTool):
def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
try:
# Your logic here
return {"status": "success", "data": result}
except Exception as e:
return {"status": "error", "error": str(e)}
Minimal JSON Config
{
"name": "tool_name",
"type": "ToolClassName",
"description": "What it does, inputs, outputs, use cases",
"parameter": {
"type": "object",
"properties": {
"param": {"type": "string", "description": "Parameter description"}
},
"required": ["param"]
},
"return_schema": {
"type": "object",
"properties": {
"status": {"type": "string"},
"data": {"type": "object", "additionalProperties": true}
}
},
"test_examples": [{"param": "value"}]
}
Common Return Patterns
Simple Success/Error
# Success
return {"status": "success", "data": result}
# Error
return {"status": "error", "error": "Error message"}
Paginated Results
return {
"status": "success",
"count": len(results),
"total": total_count,
"next": next_url,
"previous": prev_url,
"results": results
}
Detail Object
return {
"status": "success",
"data": {
"id": "123",
"name": "Item name",
"description": "Details...",
# ... other fields
}
}
Error with Details
return {
"status": "error",
"error": "Request failed",
"detail": error_details,
"suggestion": "Try this instead",
"url": request_url,
"status_code": 404
}
HTTP Requests
Basic GET Request
import requests
response = requests.get(
"https://api.example.com/endpoint",
params={"param": "value"},
timeout=30
)
response.raise_for_status()
data = response.json()
GET with Headers
response = requests.get(
url,
params=params,
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
},
timeout=30
)
POST Request
response = requests.post(
url,
json={"key": "value"},
headers=headers,
timeout=30
)
With Retry Logic
import time
for attempt in range(3):
try:
response = requests.get(url, params=params, timeout=30)
response.raise_for_status()
return response
except (requests.ConnectionError, requests.Timeout):
if attempt == 2:
raise
time.sleep(2 ** attempt)
Error Handling
Comprehensive Try-Except
try:
response = requests.get(url, params=params, timeout=30)
response.raise_for_status()
return {"status": "success", "data": response.json()}
except requests.Timeout:
return {
"status": "error",
"error": "Request timed out",
"suggestion": "Try again or use more specific query"
}
except requests.ConnectionError as e:
return {
"status": "error",
"error": "Failed to connect to API",
"detail": str(e)
}
except requests.HTTPError as e:
return {
"status": "error",
"error": f"API error: {e.response.status_code}",
"detail": e.response.text,
"url": e.response.url
}
except Exception as e:
return {
"status": "error",
"error": f"{type(e).__name__}: {str(e)}"
}
Validation
Parameter Validation
def validate_parameters(self, arguments: Dict[str, Any]) -> None:
param = arguments.get('param', '')
if not param:
raise ValueError("param cannot be empty")
if len(param) < 2:
raise ValueError("param must be at least 2 characters")
if not param.replace(' ', '').isalnum():
raise ValueError("param contains invalid characters")
In-Method Validation
def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
param = arguments.get('param')
if not param:
return {
"status": "error",
"error": "Missing required parameter: param"
}
# Continue with logic...
Common Patterns
Search Tool
def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
query = arguments.get('query')
limit = arguments.get('limit', 20)
response = requests.get(
f"{self.base_url}/search",
params={'q': query, 'limit': limit}
)
data = response.json()
return {
"status": "success",
"count": len(data['results']),
"results": data['results']
}
Detail Tool
def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
id_ = arguments.get('id')
response = requests.get(f"{self.base_url}/items/{id_}")
data = response.json()
return {
"status": "success",
"data": data
}
List Tool with Pagination
def run(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
page = arguments.get('page', 1)
page_size = arguments.get('page_size', 20)
response = requests.get(
f"{self.base_url}/items",
params={'page': page, 'page_size': page_size}
)
data = response.json()
return {
"status": "success",
"count": len(data['results']),
"total": data['total'],
"next": data.get('next'),
"previous": data.get('previous'),
"results": data['results']
}
Testing Commands
# Validate JSON syntax
python3 -m json.tool src/tooluniverse/data/{category}_tools.json
# Check Python syntax
python3 -m py_compile src/tooluniverse/{category}_tool.py
# Run tests
pytest tests/unit/test_{category}_tool.py -v
# Check tool loads
python3 -c "from tooluniverse import ToolUniverse; tu = ToolUniverse(); print('Loaded:', len(tu.list_tools()), 'tools')"
# Check tool name lengths
python scripts/check_tool_name_lengths.py --test-shortening
# List auto-generated wrappers
ls src/tooluniverse/tools/{category}_*.py
Quick Test Script
from tooluniverse import ToolUniverse
tu = ToolUniverse()
# Test tool
result = tu.run_tool("tool_name", {"param": "value"})
print(result)
# List all tools
print(f"Total tools: {len(tu.list_tools())}")
JSON Schema Types
{
"type": "string", // Text
"type": "integer", // Whole numbers
"type": "number", // Decimals
"type": "boolean", // true/false
"type": "array", // Lists
"type": "object", // Dictionaries
"type": ["string", "null"], // Union types
"type": "object",
"additionalProperties": true // Allow extra fields
}
Common Schema Patterns
String Parameter
{
"param_name": {
"type": "string",
"description": "Description with examples: 'example1', 'example2'"
}
}
Integer with Constraints
{
"limit": {
"type": "integer",
"description": "Max results. Range: 1-100. Default: 20",
"default": 20,
"minimum": 1,
"maximum": 100
}
}
Optional Boolean
{
"include_details": {
"type": "boolean",
"description": "Include detailed information. Default: false",
"default": false
}
}
Enum
{
"sort_by": {
"type": "string",
"description": "Sort order. Options: 'relevance', 'date', 'name'",
"enum": ["relevance", "date", "name"],
"default": "relevance"
}
}
Array of Strings
{
"tags": {
"type": "array",
"description": "List of tags to filter by",
"items": {
"type": "string"
}
}
}
Environment Variables
import os
# Get with default
api_key = os.environ.get('API_KEY', 'default_key')
# Get required
api_key = os.environ['API_KEY'] # Raises KeyError if missing
# Check existence
if 'API_KEY' in os.environ:
api_key = os.environ['API_KEY']
URL Building
# Simple concatenation
url = f"{base_url}/endpoint"
# With path parameter
url = f"{base_url}/items/{item_id}"
# With multiple segments
url = f"{base_url}/api/v1/items/{item_id}/details"
# Build with urllib
from urllib.parse import urljoin
url = urljoin(base_url, f"/items/{item_id}")
Common Mistakes to Avoid
❌ Don't
# Don't edit auto-generated files
src/tooluniverse/tools/category_tool_name.py
# Don't use bare except
except:
pass
# Don't ignore errors
result = some_function() # No error checking
# Don't hardcode URLs
response = requests.get("http://example.com/api")
# Don't forget timeouts
response = requests.get(url) # No timeout
# Don't create tools longer than 55 chars
"very_long_tool_name_that_exceeds_the_mcp_compatibility_limit"
✅ Do
# Do create tool class files
src/tooluniverse/category_tool.py
# Do catch specific exceptions
except ValueError as e:
return {"error": str(e)}
# Do check errors
if not result:
return {"error": "Failed"}
# Do use configurable URLs
self.base_url = "https://api.example.com"
# Do set timeouts
response = requests.get(url, timeout=30)
# Do keep names concise
"get_drug_info" # 13 chars
Debugging Tips
# Print arguments
print(f"Arguments: {arguments}")
# Print response
print(f"Status: {response.status_code}")
print(f"Data: {response.json()}")
# Check data type
print(f"Type: {type(data)}")
# Pretty print JSON
import json
print(json.dumps(data, indent=2))
# Log errors
import logging
logging.error(f"Failed: {str(e)}")
Return Schema Anti-Patterns
❌ Bad (Too Vague)
{
"return_schema": {
"type": "object",
"properties": {
"data": {"type": "object", "additionalProperties": true}
}
}
}
✅ Good (Specific)
{
"return_schema": {
"type": "object",
"properties": {
"status": {"type": "string"},
"count": {"type": "integer"},
"results": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {"type": "string"},
"name": {"type": "string"}
},
"additionalProperties": true
}
}
}
}
}
Time Savers
# Create all files at once
mkdir -p src/tooluniverse/data tests/unit examples
touch src/tooluniverse/my_tool.py
touch src/tooluniverse/data/my_tools.json
touch tests/unit/test_my_tool.py
# Validate everything
python3 -m json.tool src/tooluniverse/data/*.json
python3 -m py_compile src/tooluniverse/*_tool.py
# Count tools
grep -c '"name":' src/tooluniverse/data/*_tools.json
# Find tool registration
grep -r "@register_tool" src/tooluniverse/
# Check for long names
python scripts/check_tool_name_lengths.py