turbomcp-openapi 3.0.0-beta.4

OpenAPI to MCP conversion - expose REST APIs as MCP tools and resources
docs.rs failed to build turbomcp-openapi-3.0.0-beta.4
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Visit the last successful build: turbomcp-openapi-3.0.2

turbomcp-openapi

OpenAPI to MCP conversion for TurboMCP. Expose REST APIs as MCP tools and resources.

Overview

This crate allows you to automatically convert an OpenAPI 3.x specification into MCP (Model Context Protocol) tools and resources. This enables AI agents to interact with REST APIs without writing custom handlers.

Default mapping:

  • GET endpoints → MCP Resources (readable content)
  • POST, PUT, PATCH, DELETE endpoints → MCP Tools (callable operations)

Quick Start

use turbomcp_openapi::{OpenApiProvider, OpenApiHandler};
use turbomcp_server::McpServer;
use std::time::Duration;

// Load from URL
let provider = OpenApiProvider::from_url("https://api.example.com/openapi.json")
    .await?
    .with_base_url("https://api.example.com")?
    .with_timeout(Duration::from_secs(30));  // Optional, 30s default

// Or load from file
let provider = OpenApiProvider::from_file(Path::new("openapi.yaml"))?
    .with_base_url("https://api.example.com")?;

// Or load from string
let provider = OpenApiProvider::from_string(spec_json)?
    .with_base_url("https://api.example.com")?;

// Convert to MCP handler
let handler = provider.into_handler();

// Use with TurboMCP server
let server = McpServer::from_handler(handler);

Security Features

SSRF Protection

The provider includes built-in Server-Side Request Forgery (SSRF) protection that blocks requests to:

  • Localhost/loopback: 127.0.0.0/8, ::1, localhost
  • Private networks: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
  • Cloud metadata endpoints: 169.254.169.254 and 169.254.0.0/16
  • Link-local addresses: fe80::/10
  • Other reserved ranges: Multicast, broadcast, etc.

This prevents malicious API specs from making requests to internal infrastructure.

Request Timeouts

All HTTP requests have a configurable timeout (default: 30 seconds) to prevent:

  • Slowloris attacks
  • Indefinite hangs on unresponsive servers
  • Resource exhaustion
use std::time::Duration;

let provider = OpenApiProvider::from_string(spec)?
    .with_base_url("https://api.example.com")?
    .with_timeout(Duration::from_secs(10));  // 10 second timeout

// Check current timeout
println!("Timeout: {:?}", provider.timeout());

Custom Route Mapping

You can customize how OpenAPI operations map to MCP types:

use turbomcp_openapi::{OpenApiProvider, RouteMapping, McpType};

let mapping = RouteMapping::new()
    // Default: GET -> Resource
    .map_method("GET", McpType::Resource)
    // Custom: All /admin/* paths are skipped
    .map_pattern(r"/admin/.*", McpType::Skip)?
    // Custom: Force specific paths to be tools
    .map_rule(["GET"], r"/api/search.*", McpType::Tool, 10)?;

let provider = OpenApiProvider::from_string(spec)?
    .with_route_mapping(mapping)
    .with_base_url("https://api.example.com")?;

Route Mapping Rules

Rules are evaluated in priority order (highest first):

use turbomcp_openapi::{RouteRule, McpType};

// Create a rule matching POST/PUT to /users/* paths
let rule = RouteRule::new(McpType::Tool)
    .methods(["POST", "PUT"])
    .pattern(r"/users/\d+")?
    .priority(100);  // Higher priority = checked first

McpType Variants

  • McpType::Tool - Expose as MCP tool (callable operation)
  • McpType::Resource - Expose as MCP resource (readable content)
  • McpType::Skip - Don't expose via MCP

Features

  • OpenAPI 3.x Support - Parse both JSON and YAML specifications
  • Multiple Loading Methods - From URL, file path, or string
  • Configurable Mapping - Customize how operations map to MCP types
  • Regex Pattern Matching - Route rules support regex path patterns
  • Parameter Handling - Path, query, header, and cookie parameters
  • Request Body Support - JSON request bodies converted to tool inputs
  • HTTP Client Integration - Built-in reqwest client for API calls
  • Custom Client Support - Provide your own configured reqwest::Client
  • SSRF Protection - Built-in protection against server-side request forgery
  • Request Timeouts - Configurable timeouts (default: 30 seconds)

API Reference

OpenApiProvider

The main entry point for loading and configuring OpenAPI specs:

impl OpenApiProvider {
    // Loading methods
    pub fn from_spec(spec: OpenAPI) -> Self;
    pub fn from_string(content: &str) -> Result<Self>;
    pub fn from_file(path: &Path) -> Result<Self>;
    pub async fn from_url(url: &str) -> Result<Self>;

    // Configuration
    pub fn with_base_url(self, base_url: &str) -> Result<Self>;
    pub fn with_route_mapping(self, mapping: RouteMapping) -> Self;
    pub fn with_client(self, client: reqwest::Client) -> Self;
    pub fn with_timeout(self, timeout: Duration) -> Self;

    // Inspection
    pub fn title(&self) -> &str;
    pub fn version(&self) -> &str;
    pub fn timeout(&self) -> Duration;
    pub fn operations(&self) -> &[ExtractedOperation];
    pub fn tools(&self) -> impl Iterator<Item = &ExtractedOperation>;
    pub fn resources(&self) -> impl Iterator<Item = &ExtractedOperation>;

    // Conversion
    pub fn into_handler(self) -> OpenApiHandler;
}

OpenApiHandler

Implements McpHandler for use with TurboMCP servers:

impl McpHandler for OpenApiHandler {
    fn server_info(&self) -> ServerInfo;
    fn list_tools(&self) -> Vec<Tool>;
    fn list_resources(&self) -> Vec<Resource>;
    fn list_prompts(&self) -> Vec<Prompt>;
    async fn call_tool(&self, name: &str, args: Value, ctx: &RequestContext) -> McpResult<ToolResult>;
    async fn read_resource(&self, uri: &str, ctx: &RequestContext) -> McpResult<ResourceResult>;
    async fn get_prompt(&self, name: &str, args: Option<Value>, ctx: &RequestContext) -> McpResult<PromptResult>;
}

Error Types

pub enum OpenApiError {
    FetchError(reqwest::Error),     // Failed to fetch spec from URL
    ParseError(String),              // Failed to parse spec (JSON/YAML)
    IoError(std::io::Error),        // Failed to read file
    InvalidUrl(url::ParseError),     // Invalid URL
    InvalidPattern(regex::Error),    // Invalid regex pattern
    ApiError(String),                // API call returned error
    MissingParameter(String),        // Required parameter missing
    InvalidParameter(String, String), // Invalid parameter value
    OperationNotFound(String),       // Operation not found
    NoBaseUrl,                       // Base URL not configured
    SsrfBlocked(String),            // SSRF protection blocked request
    Timeout(u64),                    // Request timed out
}

Example

Given this OpenAPI spec:

openapi: 3.0.0
info:
  title: Pet Store
  version: 1.0.0
paths:
  /pets:
    get:
      operationId: listPets
      summary: List all pets
    post:
      operationId: createPet
      summary: Create a pet
  /pets/{id}:
    get:
      operationId: getPet
      summary: Get a pet by ID
    delete:
      operationId: deletePet
      summary: Delete a pet

The handler exposes:

Resources:

  • openapi://get/pets (listPets)
  • openapi://get/pets/{id} (getPet)

Tools:

  • createPet - Create a pet
  • deletePet - Delete a pet

Running the Example

cargo run -p turbomcp-openapi --example petstore

License

MIT