Skip to main content

Convert REST API specifications (OpenAPI 3.x, Swagger 2.x, OpenAPI Actions) into MCP tools for AI agents. Supports JSON and YAML formats.

Project description

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

from adapter import (
    OpenAPILoader,
    Normalizer,
    ToolGenerator,
    ToolRegistry,
    APIExecutor,
    BearerAuth,
    MCPServer
)

# 1. Load OpenAPI spec
loader = OpenAPILoader()
spec = loader.load("https://api.example.com/openapi.json")

# 2. Normalize to canonical format
normalizer = Normalizer()
endpoints = normalizer.normalize_openapi(spec)

# 3. Generate MCP tools (auth params auto-filtered!)
generator = ToolGenerator(api_name="myapi")
tools = generator.generate_tools(endpoints)

# 4. Create tool registry
registry = ToolRegistry(name="My API")
registry.add_tools(tools)

# 5. Set up API executor with authentication
executor = APIExecutor(
    base_url="https://api.example.com",
    auth=BearerAuth(token="your-token")
)

# 6. Start MCP server (for Claude Desktop, etc.)
server = MCPServer(
    name="My API Server",
    version="1.0.0",
    tool_registry=registry,
    executor=executor,
    endpoints=endpoints
)
server.run()  # Claude can now use your API!

๐Ÿ“ฆ Installation

From PyPI (Recommended)

pip install rest-to-mcp-adapter

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
  • langchain-community>=0.0.20 - MCP protocol support

โœจ 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

# Create server (combines registry + executor + endpoints)
server = MCPServer(
    name="My API Server",
    version="1.0.0",
    tool_registry=registry,
    executor=executor,
    endpoints=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 โ†’ Organizes and manages tools
    โ†“
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.


๐Ÿ“š Examples

For complete, production-ready MCP server implementations with full source code, see the Real-World Integrations section below.


๐ŸŒ 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

  • โœ… Phase 1: OpenAPI ingestion and normalization
  • โœ… Phase 2: MCP tool generation
  • โœ… Phase 3: Runtime execution engine
  • โœ… Phase 4: MCP server implementation
  • ๐Ÿ”„ Phase 5: Additional loaders (Postman, GraphQL)
  • ๐Ÿ“‹ Future: 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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rest_to_mcp_adapter-0.1.1.tar.gz (54.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rest_to_mcp_adapter-0.1.1-py3-none-any.whl (54.1 kB view details)

Uploaded Python 3

File details

Details for the file rest_to_mcp_adapter-0.1.1.tar.gz.

File metadata

  • Download URL: rest_to_mcp_adapter-0.1.1.tar.gz
  • Upload date:
  • Size: 54.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for rest_to_mcp_adapter-0.1.1.tar.gz
Algorithm Hash digest
SHA256 88d8c31a587e472e3ffb0b23d7ce12731c2872423a7c760d11a7a8237e73e69d
MD5 828bb573c9c69879eff9b9a2216131f7
BLAKE2b-256 16a0f59f034508c096563528c133c6608dce4712317066eb1fe3f27f28063e5d

See more details on using hashes here.

File details

Details for the file rest_to_mcp_adapter-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for rest_to_mcp_adapter-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 680061cc7e4f62f9d61da761cd7664074651f9c399f68c56c0c1ab89c3ea208a
MD5 31cb31dd9955b303790e397e05b4b259
BLAKE2b-256 1a27258f0e627ea9df606f5ad63b790f10deb10532197e96948850f7fe66cedf

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page