Skip to content

pawneetdev/rest-to-mcp-adapter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

78 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

REST-to-MCP Adapter

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:

  • OpenAPI 3.x (JSON, YAML)
  • Swagger 2.x (JSON, YAML)
  • OpenAPI Actions format (JSON)

Python 3.11+ License: MIT PyPI version

⚠️ 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!


πŸš€ Quick Start

Simple Approach (Recommended for Most Users)

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.


πŸ“¦ Installation

Stable Release

pip install rest-to-mcp-adapter

Beta Release (Latest Features)

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

From Source (For Development)

git clone https://github.com/pawneetdev/rest-to-mcp-adapter.git
cd rest-to-mcp-adapter
pip install -e .

Dependencies

Core dependencies (automatically installed):

  • pydantic>=2.0.0 - Data validation and modeling
  • pyyaml>=6.0 - YAML parsing
  • requests>=2.31.0 - HTTP client

Optional dependencies:

  • langchain-community>=0.0.20 - Enhanced OpenAPI validation (install with: pip install rest-to-mcp-adapter[langchain])

✨ Key Features

πŸ”„ Specification Ingestion

  • Multiple formats: OpenAPI 3.x, Swagger 2.x, OpenAPI Actions
  • JSON & YAML: Full support for both formats
  • Load from anywhere: URL, file path, or raw content
  • Auto-detection: Automatically determines input type and format
  • $ref dereferencing: Resolves all JSON pointer references

πŸ› οΈ MCP Tool Generation

  • Automatic conversion: OpenAPI endpoints β†’ MCP tools
  • Smart naming: 64-character limit with intelligent truncation
  • Auth filtering: Automatically hides auth parameters from users
  • Hybrid approach: Defaults + auto-detection + custom overrides

πŸ” Authentication Support

  • Built-in handlers: API Key, Bearer, Basic, OAuth2
  • Custom handlers: Easy to implement your own
  • Automatic parameter filtering: Auth params hidden from tool schemas
  • Conditional auth: Only applies to endpoints that require it

⚑ Runtime Execution

  • Direct API calls: Execute REST requests from canonical endpoints
  • Retry logic: Exponential backoff for failed requests
  • Error handling: Comprehensive error types and messages
  • Response processing: JSON, text, and binary support

πŸ€– MCP Server

  • Full MCP protocol: JSON-RPC 2.0 over stdio
  • Claude integration: Ready for Claude Desktop
  • Tool discovery: tools/list endpoint
  • Tool execution: tools/call endpoint

πŸ“– Detailed Usage

πŸ’‘ 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.)

1. Loading API Specifications

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)

2. Normalizing to Canonical Format

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)}")

3. Generating MCP Tools

Basic Usage

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}")

With Auto-Detected Auth Filtering

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

With Custom Auth Parameters

# Override defaults completely
generator = ToolGenerator(
    api_name="myapi",
    auth_params={'my_signature', 'my_timestamp', 'my_nonce'}
)
tools = generator.generate_tools(endpoints)

4. Working with Tool Registry

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")

5. Authentication Handlers

Built-in Handlers

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")
)

Custom Auth Handler

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:

  • Server time synchronization for timestamp accuracy
  • Query string canonicalization (sorted parameter ordering)
  • Optional recvWindow parameter for clock skew tolerance
  • Comprehensive error messages for auth failures

Refer to its auth.py module for a complete implementation you can adapt for similar signature-based APIs.

6. Executing API Calls Directly

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}")

7. Running an MCP Server

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()

Configure in Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "myapi": {
      "command": "python",
      "args": ["/path/to/your/server.py"]
    }
  }
}

πŸ” Authentication Parameter Filtering

One of the most powerful features is automatic authentication parameter filtering. This ensures users never see or need to provide auth-related parameters.

How It Works

The library uses a hybrid approach combining:

  1. Default common parameters: signature, timestamp, api_key, authorization, etc.
  2. Auto-detected from OpenAPI: Extracts from securitySchemes
  3. Custom overrides: You can specify your own

Default Auth Parameters

DEFAULT_AUTH_PARAMS = {
    'signature', 'timestamp', 'recvwindow', 'recv_window',
    'api_key', 'apikey', 'api_secret', 'apisecret',
    'access_token', 'accesstoken', 'token',
    'authorization', 'auth',
    'nonce', 'sign',
}

Auto-Detection Example

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
)

Supported Security Schemes

Type Auto-Detected Parameters
apiKey Parameter name from spec
http (bearer/basic) authorization
oauth2 authorization, access_token, token
openIdConnect authorization

Example: Before vs After

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

πŸ—οΈ Architecture Overview

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.


🌍 Real-World Integrations

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.

DataForSEO MCP

Repository: https://github.com/pawneetdev/dataforseo-mcp/

Production MCP server for the DataForSEO API demonstrating:

  • Authentication: HTTP Basic Authentication
  • Spec Format: OpenAPI Actions/JSON format
  • Use Case: SEO data retrieval and analysis
  • What You'll Learn:
    • Loading OpenAPI JSON specifications
    • Implementing standard HTTP Basic auth
    • Organizing tools by API categories
    • Handling paginated responses

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.


Binance MCP

Repository: https://github.com/pawneetdev/binance-mcp

Production MCP server for the Binance Spot Trading API demonstrating:

  • Authentication: Custom HMAC-SHA256 signature-based authentication
  • Spec Format: Swagger/OpenAPI YAML format
  • Use Case: Cryptocurrency trading and market data
  • What You'll Learn:
    • Loading Swagger YAML specifications
    • Implementing custom AuthHandler with cryptographic signatures
    • Query string signing with HMAC-SHA256
    • Automatic timestamp and nonce injection
    • Advanced parameter filtering for signature-based endpoints
    • Handling large APIs (100+ endpoints)

Authentication Pattern: The Binance MCP extends the AuthHandler base class to implement Binance's specific requirements:

  • API key in headers (X-MBX-APIKEY)
  • Timestamp query parameter (synchronized with server time)
  • HMAC-SHA256 signature of query string
  • Optional recvWindow for timing flexibility

This 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.


Learning Path

  1. Start with DataForSEO: Straightforward authentication, standard OpenAPI patterns
  2. Progress to Binance: Advanced custom authentication, complex parameter handling
  3. Build Your Own: Apply these patterns to your target API

Both repositories include:

  • Complete source code and project structure
  • Production-grade error handling
  • Retry logic and timeout management
  • Claude Desktop configuration examples
  • Deployment documentation

πŸ§ͺ Testing

# Run all tests
pytest

# With coverage
pytest --cov=adapter

# Run specific test
pytest tests/test_tool_generator.py

πŸ›£οΈ Roadmap

  • βœ… OpenAPI ingestion and normalization
  • βœ… MCP tool generation
  • βœ… Runtime execution engine
  • βœ… MCP server implementation
  • πŸ”„ Additional loaders (Postman, GraphQL)
  • πŸ“‹ WebSocket transport, enhanced caching

🀝 Contributing

We welcome contributions from the community! Whether you're fixing bugs, adding features, or improving documentation, your help is appreciated.

How to Contribute

  1. Fork the repository on GitHub
  2. Clone your fork locally:
    git clone https://github.com/your-username/rest-to-mcp-adapter.git
    cd rest-to-mcp-adapter
  3. Create a branch for your changes:
    git checkout -b feature/your-feature-name
  4. Install development dependencies:
    pip install -e .
    pip install pytest pytest-cov black ruff
  5. Make your changes and ensure tests pass:
    pytest
  6. Format your code:
    black .
    ruff check .
  7. Commit and push your changes:
    git add .
    git commit -m "Description of your changes"
    git push origin feature/your-feature-name
  8. Open a Pull Request on GitHub

Areas We're Looking For Help

  • Additional authentication methods (OAuth2 flows, custom schemes)
  • Performance optimizations (caching, parallel processing)
  • More loaders (Postman collections, GraphQL schemas, API Blueprint)
  • Documentation improvements (tutorials, examples, API docs)
  • Real-world usage examples (new MCP server implementations)
  • Testing (edge cases, integration tests, CI/CD improvements)

Development Guidelines

  • Follow existing code style and patterns
  • Add tests for new features
  • Update documentation as needed
  • Keep changes focused and atomic
  • Write clear commit messages

Reporting Issues

Found a bug or have a feature request? Please open an issue with:

  • Clear description of the problem/feature
  • Steps to reproduce (for bugs)
  • Expected vs actual behavior
  • Relevant code snippets or examples

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

Copyright (c) 2025 Pawneet Singh


πŸ™‹ Support


πŸ™ Acknowledgments

This library was developed with significant assistance from Claude (Anthropic), an AI assistant that helped with:

  • Architecture design and implementation
  • Code review and optimization
  • Documentation and examples
  • Testing and debugging

Special thanks to the AI agent and MCP communities for inspiration and feedback.


Built with ❀️ for the AI agent ecosystem

About

A Python library for converting REST API specifications into MCP (Model Context Protocol) tools for AI agents.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages