Discover MCPs & agents
Loading MCPs and agents…
Loading MCPs and agents…
A Python library for converting REST API specifications into MCP (Model Context Protocol) tools for AI agents.
From the repo.
A Python library for converting REST API specifications into MCP (Model Context Protocol) tools for AI agents.
Transform any REST API specification into tools that Claude, GPT, and other LLM-powered agents can use.
Supported Formats:
⚠️ Beta Status: This library is currently in beta (v0.1.0). The core functionality is stable and production-ready, but the API may evolve based on community feedback. We welcome early adopters and contributors!
from adapter import ToolRegistry, MCPServer, APIExecutor, BearerAuth
# Create registry from OpenAPI spec (includes endpoints)
registry = ToolRegistry.create_from_openapi(
"https://api.example.com/openapi.json"
)
# Set up executor
executor = APIExecutor(
base_url="https://api.example.com",
auth=BearerAuth(token="your-token")
)
# Create server - endpoints are in the registry!
server = MCPServer(
name="My API Server",
version="1.0.0",
tool_registry=registry,
executor=executor
# No endpoints parameter needed!
)
server.run()
For advanced usage and individual step control, see Detailed Usage below.
pip install rest-to-mcp-adapter
To install the latest beta version with cutting-edge features:
pip install --pre rest-to-mcp-adapter
Or install a specific beta version:
pip install rest-to-mcp-adapter==0.2.0b1
git clone https://github.com/pawneetdev/rest-to-mcp-adapter.git
cd rest-to-mcp-adapter
pip install -e .
Core dependencies (automatically installed):
pydantic>=2.0.0 - Data validation and modelingpyyaml>=6.0 - YAML parsingrequests>=2.31.0 - HTTP clientOptional dependencies:
langchain-community>=0.0.20 - Enhanced OpenAPI validation (install with: pip install rest-to-mcp-adapter[langchain])tools/list endpointtools/call endpoint💡 Looking for advanced features? See LIBRARY_USAGE.md for:
- Advanced tool generation patterns
- Registry operations (search, filter, export/import)
- Batch API calls
- Integration patterns and best practices
- Troubleshooting guide
- Important limitations (64-char tool name limit, etc.)
The library supports multiple specification formats with automatic detection:
from adapter import OpenAPILoader
loader = OpenAPILoader()
# OpenAPI 3.x (JSON)
spec = loader.load("https://api.example.com/openapi.json")
# OpenAPI 3.x (YAML)
spec = loader.load("./specs/openapi.yaml")
# Swagger 2.x (JSON)
spec = loader.load("./specs/swagger.json")
# Swagger 2.x (YAML)
spec = loader.load("https://api.example.com/swagger.yaml")
# OpenAPI Actions format
spec = loader.load("./specs/actions.json")
# From raw YAML content
yaml_content = """
openapi: 3.0.0
info:
title: My API
version: 1.0.0
paths:
/users:
get:
summary: List users
"""
spec = loader.load(yaml_content)
# From raw JSON content
json_content = '{"openapi": "3.0.0", "info": {"title": "My API"}}'
spec = loader.load(json_content)
# Auto-detection works for all methods
# Automatically detects: URL vs file vs content, JSON vs YAML, OpenAPI vs Swagger
spec = loader.load(source)
from adapter import Normalizer
normalizer = Normalizer()
endpoints = normalizer.normalize_openapi(spec)
# Inspect normalized endpoints
for endpoint in endpoints:
print(f"{endpoint.method} {endpoint.path}")
print(f" Name: {endpoint.name}")
print(f" Parameters: {len(endpoint.parameters)}")
print(f" Requires auth: {bool(endpoint.security)}")
from adapter import ToolGenerator
generator = ToolGenerator(api_name="myapi")
tools = generator.generate_tools(endpoints)
# Tools are ready to use!
for tool in tools:
print(f"Tool: {tool.name}")
print(f"Description: {tool.description}")
print(f"Parameters: {tool.inputSchema}")
from adapter import OpenAPILoader, ToolGenerator
# Load spec
loader = OpenAPILoader()
spec = loader.load("api.yaml")
# Auto-detect auth parameters from security schemes
auto_detected = loader.extract_auth_parameters(spec)
print(f"Auto-detected: {auto_detected}")
# Output: {'x-api-key', 'signature', ...}
# Generate tools with hybrid filtering (defaults + auto-detected)
generator = ToolGenerator(
api_name="myapi",
auto_detected_auth_params=auto_detected
)
tools = generator.generate_tools(endpoints)
# Auth parameters are automatically hidden!
# Users only see business parameters
# Override defaults completely
generator = ToolGenerator(
api_name="myapi",
auth_params={'my_signature', 'my_timestamp', 'my_nonce'}
)
tools = generator.generate_tools(endpoints)
from adapter import ToolRegistry
# Create registry
registry = ToolRegistry(name="My API")
registry.add_tools(tools)
# Query tools
print(f"Total tools: {registry.count()}")
print(f"Tool names: {registry.get_tool_names()}")
# Filter tools
product_tools = registry.get_tools_by_tag("products")
get_tools = registry.get_tools_by_method("GET")
search_results = registry.search_tools("user")
# Get specific tool
user_tool = registry.get_tool("myapi_get_users")
# Export/Import
registry.export_json("tools.json")
registry2 = ToolRegistry.import_json("tools.json")
from adapter import APIExecutor, BearerAuth, APIKeyAuth, BasicAuth
# Bearer Token
executor = APIExecutor(
base_url="https://api.example.com",
auth=BearerAuth(token="your-bearer-token")
)
# API Key (in header)
executor = APIExecutor(
base_url="https://api.example.com",
auth=APIKeyAuth(api_key="your-api-key", header_name="X-API-Key")
)
# API Key (in query)
executor = APIExecutor(
base_url="https://api.example.com",
auth=APIKeyAuth(api_key="your-api-key", location="query", param_name="apikey")
)
# Basic Auth
executor = APIExecutor(
base_url="https://api.example.com",
auth=BasicAuth(username="user", password="pass")
)
from adapter.runtime import AuthHandler
class CustomAuth(AuthHandler):
def __init__(self, api_key: str, api_secret: str):
self.api_key = api_key
self.api_secret = api_secret
def apply(self, headers: dict, params: dict) -> None:
# Add custom authentication logic
import time
import hmac
import hashlib
timestamp = int(time.time() * 1000)
params["timestamp"] = str(timestamp)
# Create signature
query_string = "&".join(f"{k}={v}" for k, v in sorted(params.items()))
signature = hmac.new(
self.api_secret.encode(),
query_string.encode(),
hashlib.sha256
).hexdigest()
params["signature"] = signature
headers["X-API-KEY"] = self.api_key
# Use custom auth
executor = APIExecutor(
base_url="https://api.example.com",
auth=CustomAuth(api_key="key", api_secret="secret")
)
Real-World Example: The Binance MCP implements a production-grade version of this pattern with additional features:
recvWindow parameter for clock skew toleranceRefer to its auth.py module for a complete implementation you can adapt for similar signature-based APIs.
from adapter import APIExecutor, NoAuth
# Create executor
executor = APIExecutor(
base_url="https://api.example.com",
auth=NoAuth(), # Public endpoints
timeout=30,
max_retries=3
)
# Find an endpoint
endpoint = next(ep for ep in endpoints if ep.name == "get_users")
# Execute call
result = executor.execute(endpoint, arguments={"limit": 10})
if result.success:
print(f"Status: {result.status_code}")
print(f"Data: {result.response.data}")
else:
print(f"Error: {result.error}")
from adapter import MCPServer
# Option 1: With create_from_openapi (recommended)
registry = ToolRegistry.create_from_openapi("https://api.example.com/openapi.json")
executor = APIExecutor(base_url="https://api.example.com", auth=BearerAuth(token="token"))
server = MCPServer(
name="My API Server",
version="1.0.0",
tool_registry=registry, # Endpoints included automatically
executor=executor
)
# Option 2: Manual with explicit endpoints (backward compatible)
server = MCPServer(
name="My API Server",
version="1.0.0",
tool_registry=registry,
executor=executor,
endpoints=endpoints # Optional if registry has endpoints
)
# Run server (stdio transport for Claude Desktop)
server.run()
Add to claude_desktop_config.json:
{
"mcpServers": {
"myapi": {
"command": "python",
"args": ["/path/to/your/server.py"]
}
}
}
One of the most powerful features is automatic authentication parameter filtering. This ensures users never see or need to provide auth-related parameters.
The library uses a hybrid approach combining:
signature, timestamp, api_key, authorization, etc.securitySchemesDEFAULT_AUTH_PARAMS = {
'signature', 'timestamp', 'recvwindow', 'recv_window',
'api_key', 'apikey', 'api_secret', 'apisecret',
'access_token', 'accesstoken', 'token',
'authorization', 'auth',
'nonce', 'sign',
}
loader = OpenAPILoader()
spec = loader.load("api.yaml")
# Extract auth params from securitySchemes
auth_params = loader.extract_auth_parameters(spec)
# Returns: {'x-api-key', 'signature', ...}
# Use in tool generation
generator = ToolGenerator(
api_name="myapi",
auto_detected_auth_params=auth_params
)
| Type | Auto-Detected Parameters |
|---|---|
apiKey | Parameter name from spec |
http (bearer/basic) | authorization |
oauth2 | authorization, access_token, token |
openIdConnect | authorization |
Without filtering (❌ Bad):
# User sees auth parameters
tool.inputSchema = {
"properties": {
"symbol": {"type": "string"},
"timestamp": {"type": "integer"}, # ❌ Exposed
"signature": {"type": "string"} # ❌ Exposed
}
}
# User has to provide them (confusing!)
client.call_tool("get_price", {
"symbol": "BTCUSDT",
"timestamp": 1234567890, # ❌ User shouldn't know this
"signature": "abc123..." # ❌ User shouldn't know this
})
With filtering (✅ Good):
# User only sees business parameters
tool.inputSchema = {
"properties": {
"symbol": {"type": "string"} # ✅ Only what matters
}
}
# Clean API!
client.call_tool("get_price", {
"symbol": "BTCUSDT" # ✅ Simple and clear
})
# Auth handler adds timestamp and signature automatically
OpenAPI Spec (URL/file/content)
↓
OpenAPILoader → Parses and dereferences $refs
↓
Normalizer → Converts to CanonicalEndpoint models
↓
ToolGenerator → Creates MCP tool definitions
↓
ToolRegistry → Stores tools and endpoints
↓
MCPServer → Exposes tools via JSON-RPC (stdio)
↓
Claude/GPT → Calls tools
↓
APIExecutor → Executes actual REST API calls
↓
Response → Returns to agent
For detailed architecture documentation, see ARCHITECTURE.md.
The REST-to-MCP Adapter powers production MCP servers for real APIs. These example repositories demonstrate complete implementations with different authentication patterns and specification formats.
Repository: https://github.com/pawneetdev/dataforseo-mcp/
Production MCP server for the DataForSEO API demonstrating:
Quick Start:
git clone https://github.com/pawneetdev/dataforseo-mcp.git
cd dataforseo-mcp
pip install -e .
See the repository README for complete setup instructions and Claude Desktop integration.
Repository: https://github.com/pawneetdev/binance-mcp
Production MCP server for the Binance Spot Trading API demonstrating:
AuthHandler with cryptographic signaturesAuthentication Pattern:
The Binance MCP extends the AuthHandler base class to implement Binance's specific requirements:
X-MBX-APIKEY)recvWindow for timing flexibilityThis pattern can be adapted for other APIs with signature-based authentication (AWS, Kraken, etc.).
Quick Start:
git clone https://github.com/pawneetdev/binance-mcp.git
cd binance-mcp
pip install -e .
See the repository README for API key setup, credential management, and Claude Desktop integration.
Both repositories include:
# Run all tests
pytest
# With coverage
pytest --cov=adapter
# Run specific test
pytest tests/test_tool_generator.py
We welcome contributions from the community! Whether you're fixing bugs, adding features, or improving documentation, your help is appreciated.
git clone https://github.com/your-username/rest-to-mcp-adapter.git
cd rest-to-mcp-adapter
git checkout -b feature/your-feature-name
pip install -e .
pip install pytest pytest-cov black ruff
pytest
black .
ruff check .
git add .
git commit -m "Description of your changes"
git push origin feature/your-feature-name
Found a bug or have a feature request? Please open an issue with:
This project is licensed under the MIT License - see the LICENSE file for details.
Copyright (c) 2025 Pawneet Singh
This library was developed with significant assistance from Claude (Anthropic), an AI assistant that helped with:
Special thanks to the AI agent and MCP communities for inspiration and feedback.
Built with ❤️ for the AI agent ecosystem
Replace {MCP_ENDPOINT_URL} with this MCP’s endpoint URL (from its repo or docs above). No API key — you connect directly.
Tool
OS
Config file: ~/.cursor/mcp.json
{
"mcpServers": {
"mcp-server": {
"url": "{MCP_ENDPOINT_URL}"
}
}
}Paste into mcpServers in the config file. Restart Cursor after saving.
If this MCP is also published on mcpchannel.ai, you can subscribe from Browse and use the gateway config there instead.