# Rest To Mcp Adapter

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

- **Type:** MCP server
- **Install:** `agentstack add mcp-pawneetdev-rest-to-mcp-adapter`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [pawneetdev](https://agentstack.voostack.com/s/pawneetdev)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [pawneetdev](https://github.com/pawneetdev)
- **Source:** https://github.com/pawneetdev/rest-to-mcp-adapter
- **Website:** https://pypi.org/project/rest-to-mcp-adapter

## Install

```sh
agentstack add mcp-pawneetdev-rest-to-mcp-adapter
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

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

[](https://www.python.org/downloads/)
[](https://opensource.org/licenses/MIT)
[](https://pypi.org/project/rest-to-mcp-adapter/)

> **⚠️ 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)

```python
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](#-detailed-usage) below.

---

## 📦 Installation

### Stable Release

```bash
pip install rest-to-mcp-adapter
```

### Beta Release (Latest Features)

To install the latest beta version with cutting-edge features:

```bash
pip install --pre rest-to-mcp-adapter
```

Or install a specific beta version:

```bash
pip install rest-to-mcp-adapter==0.2.0b1
```

### From Source (For Development)

```bash
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](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:

```python
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

```python
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

```python
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

```python
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

```python
# 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

```python
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

```python
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

```python
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](https://github.com/pawneetdev/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

```python
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

```python
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`:

```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

```python
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

```python
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):
```python
# 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):
```python
# 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](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**:
```bash
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**:
```bash
git clone https://github.com/pawneetdev/binance-mcp.git
cd binance-mcp
pip install -e .
```

See the repository README for API key setup, credential

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [pawneetdev](https://github.com/pawneetdev)
- **Source:** [pawneetdev/rest-to-mcp-adapter](https://github.com/pawneetdev/rest-to-mcp-adapter)
- **License:** MIT
- **Homepage:** https://pypi.org/project/rest-to-mcp-adapter

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-pawneetdev-rest-to-mcp-adapter
- Seller: https://agentstack.voostack.com/s/pawneetdev
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
