Skip to main content
Glama
OpenAPI to Model Context Protocol (MCP)

OpenAPI to Model Context Protocol (MCP)

by gujord

OpenAPI to Model Context Protocol (MCP)

PyPI version License: MIT Python version

OpenAPI-MCP exposes operations from an OpenAPI document as MCP tools. It also provides schema resources, a usage prompt, and request previews. The server uses FastMCP for MCP transport and tool registration.

OpenAPI-MCP

Release candidate: 2.0.0rc1. This candidate targets FastMCP 4.1.6 and MCP Python SDK 2.3.0, with compatible minor updates allowed. Version 1.0.4 does not contain these fixes. Read the upgrade guide before upgrading an existing installation. See the review and validation record for tested versions, findings, and remaining work.

Install and run

Python 3.10 or later is required. Install the candidate explicitly:

pip install 'openapi-mcp-proxy==2.0.0rc1'

To use this checkout:

python -m venv .venv
source .venv/bin/activate
pip install -e .
OPENAPI_URL="./test/fixtures/petstore.json" \
MCP_ALLOWED_OPERATIONS='["GET /pets"]' \
SERVER_NAME="petstore" openapi-mcp

The default transport is stdio. A client launches the process and communicates through its standard input and output. OPENAPI_URL accepts a local JSON/YAML file or an HTTP(S) URL. Use specifications and API endpoints you trust.

A stdio client configuration can use the installed executable:

{
  "mcpServers": {
    "petstore": {
      "command": "/absolute/path/to/.venv/bin/openapi-mcp",
      "env": {
        "OPENAPI_URL": "/absolute/path/to/OpenAPI-MCP/test/fixtures/petstore.json",
        "SERVER_NAME": "petstore",
        "MCP_ALLOWED_OPERATIONS": "[\"GET /pets\"]"
      }
    }
  }
}

For Streamable HTTP:

OPENAPI_URL="./test/fixtures/petstore.json" \
SERVER_NAME="petstore" \
MCP_ALLOWED_OPERATIONS='["GET /pets"]' \
MCP_HTTP_ENABLED=true \
MCP_HTTP_PORT=8001 \
openapi-mcp

The MCP endpoint is http://127.0.0.1:8001/mcp. The supplied client configuration uses mcp-remote to connect stdio clients to HTTP. Client applications and mcp-remote are separate components and were not tested in the offline review.

Legacy SSE is available explicitly with MCP_TRANSPORT_TYPE=sse, at /sse. The default HTTP endpoint changed from /sse to /mcp; update existing clients.

Related MCP server: OpenAPI to MCP

Choose which API operations to expose

By default, no API operations are exposed. Set MCP_ALLOWED_OPERATIONS to a JSON array of exact uppercase HTTP method and OpenAPI path pairs:

MCP_ALLOWED_OPERATIONS='["GET /pets", "GET /pets/{petId}"]'

Selectors use the paths in the specification, without the server URL/base path. They are literal matches, not regular expressions or wildcards. An unknown selector, malformed list, duplicate selector, or conflicting policy stops startup. Only permitted operations appear as tools, in the operation list, and in the usage prompt. A direct call to an omitted tool is rejected before request preparation or authentication. An empty list leaves only the information tools, usage prompt, and schema resources available. API descriptions and component schemas remain metadata; this policy is not a document-redaction feature.

To deliberately expose every operation, set MCP_OPERATION_POLICY=all and leave MCP_ALLOWED_OPERATIONS unset. This restores the previous exposure behavior. A policy applies to the entire server instance, not individual users. Restart with a new server instance to apply changes. A GET-only list is not a guarantee of harmless operations; choose each route based on what its API actually does.

Operation IDs that collide after name sanitization, or permitted IDs that collide with management tool names, are rejected instead of silently replacing a tool.

Tools and request previews

Each permitted API operation becomes a tool named <server_name>_<operation_id>. Inputs use the parameter names from the specification, including names such as customerId or X-Trace. JSON request bodies use the argument body. Required fields and supported JSON Schema constraints are checked before an API request. Local #/components/schemas/ references are supported; external schema references are not fetched.

Every generated operation accepts two additional arguments:

  • dry_run: true returns the prepared URL, parameters, caller-supplied headers, and body without executing the API request or obtaining an authentication token. Server-configured authentication headers are omitted from the preview.

  • req_id is an optional correlation string.

For example, a tool with a customerId path parameter and JSON request body can be called with:

{"customerId": "c1", "body": {"quantity": 2}, "dry_run": true}

Previews still contain caller-supplied data. They are not a general redaction service. dry_run, req_id, and kwargs are reserved names; specifications that use them, or reuse one input name across locations, are rejected rather than silently mapped to the wrong input.

Additional tools list operations and server information. Component schemas are available as JSON resources under schema://<server_name>_<schema_name> (with sanitized names), and a generated prompt describes API usage.

Configuration

Environment variables and a local .env file configure the executable. The Python API also exposes ServerConfig.from_file() for JSON/YAML settings. Process environment overrides .env, which overrides file values. Loading a file does not modify the process environment or other server instances.

Variable

Meaning

Default

OPENAPI_URL

Trusted specification URL or local file

Required

SERVER_NAME

Prefix for tools and resources

openapi_proxy_server

MCP_OPERATION_POLICY

allowlist or explicit all

allowlist

MCP_ALLOWED_OPERATIONS

JSON array of exact METHOD /path selectors

[] (no API operations)

MCP_HTTP_ENABLED

Enable HTTP instead of stdio

false

MCP_HTTP_HOST

Address to bind

127.0.0.1

MCP_HTTP_PORT

Port

8000

MCP_TRANSPORT_TYPE

http or legacy sse

http

MCP_ALLOWED_HOSTS

Additional trusted HTTP Host values, comma-separated

FastMCP loopback defaults

MCP_CORS_ORIGINS

Allowed HTTP Origin values, comma-separated

localhost and 127.0.0.1 on ports 3000 and 8080

MCP_AUTH_HEADERS

Upstream headers as JSON or key=value,key2=value2

Empty

OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET, OAUTH_TOKEN_URL

Upstream OAuth client credentials

Unset

OAUTH_SCOPE

Upstream OAuth scope

api

API_USERNAME, API_PASSWORD, API_LOGIN_ENDPOINT

Upstream username/password login

Unset

HTTP_TIMEOUT

Upstream request timeout in seconds

30

HTTP_MAX_RETRIES

Retries for idempotent HTTP methods

3

HTTP_RETRY_BASE_DELAY, HTTP_RETRY_MAX_DELAY

Retry delays in seconds

1, 30

MCP_DEBUG

Enable debug logging

false

MCP_CORS_ORIGINS is retained as a configuration name for compatibility; it controls Origin validation in the FastMCP transport, not MCP client identity or a complete browser CORS policy. HTTP Host/Origin protection is enabled explicitly.

The old MCP_MESSAGE_SIZE_LIMIT, MCP_BATCH_TIMEOUT, MCP_SESSION_TIMEOUT, and SSE_* settings belong to legacy modules. They do not configure limits or transport selection in the current openapi-mcp executable.

Upstream authentication

OPENAPI_URL="./specs/my-api.yaml" \
MCP_AUTH_HEADERS='{"X-API-Key": "example-placeholder"}' \
MCP_ALLOWED_OPERATIONS='["GET /items"]' \
openapi-mcp

These credentials authenticate outgoing API calls, not incoming MCP clients. Anyone allowed to call this MCP server can invoke its registered API operations with the server's API privileges. The operation allowlist limits those tools, but there is no per-user authorization layer yet. Use restricted API credentials and allow only the operations you intend to expose. See SECURITY.md.

A configured token login that fails now stops the API request. POST and PATCH requests are not retried automatically, because a lost response may hide a successful mutation. GET, HEAD, OPTIONS, PUT, and DELETE may be retried according to the configured limit; set HTTP_MAX_RETRIES=0 if the API does not implement those methods idempotently. Numeric Retry-After delays are bounded by the configured maximum; HTTP-date values fall back to exponential delay.

Docker

docker compose up --build -d

The example services publish ports 8001 and 8002 on 127.0.0.1 only. The process binds to 0.0.0.0 inside each container. Both example services fetch public specifications at startup. GET /health reports process liveness; it does not test upstream authentication or API availability. Health checks fail on HTTP errors. Container builds were not exercised in the local review.

Development and current scope

pip install -e '.[dev]'
python -m pytest test/ -q

Normal tests block network sockets, isolate credentials, and use fixtures or mock HTTP responses. Eleven legacy live examples are skipped explicitly. Returning a value from a test is an error, so returning False cannot masquerade as a passing assertion. See CONTRIBUTING.md for the checks and the opt-in command for legacy live examples.

This is a custom OpenAPI adapter, not a complete OpenAPI implementation. Selected operations with unsupported request formats are rejected at startup: form/multipart/XML bodies, array/object path/query/header values, cookie inputs, parameter references/content, and nondefault serialization styles. Direct JSON bodies and scalar path/query/header parameters are supported. Explicit null JSON bodies are rejected before authentication. Unsupported omitted operations may remain in the specification. Response size limits and per-user MCP authorization still require more work. Deprecated server and transport modules remain for historical compatibility and have not received the same end-to-end validation as fastmcp_server.py.

FastMCP's native OpenAPI integration handles additional request formats. The adapter comparison and policy review records a shared-fixture comparison, including differences in body input shapes, argument validation, and request previews. The current adapter remains in use; a replacement must preserve those contracts. The comparison script reports known gaps with a nonzero exit status:

python scripts/compare_openapi_adapters.py --output build/adapter-comparison.json

The initial review also covers the July 2026 MCP protocol changes. Updating the SDK alone is not proof of complete protocol conformance.

License

MIT.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      A dynamic proxy that converts OpenAPI Specification (OAS) endpoints into Message Communication Protocol (MCP) tools, allowing AI agents to use existing REST APIs as if they were native MCP tools without manual implementation.
      16
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      A standalone proxy that transforms any OpenAPI or Swagger-described REST API into an MCP server by mapping API operations to executable MCP tools. It enables AI clients to interact with existing web services through automated HTTP requests based on their official documentation.
      17 npm
      16
      MIT
    • F
      license
      Not graded
      quality
      D
      maintenance
      A universal MCP server that connects any REST API to AI assistants via OpenAPI or Postman specifications. It enables dynamic tool creation with GraphQL-style field selection and automatic schema inference for efficient data retrieval.
      9 npm
      6
      -
    • A
      license
      Not graded
      quality
      D
      maintenance
      Turns any OpenAPI specification into a fully working MCP server with a single command, enabling AI agents to call APIs without writing any glue code.
      6 npm
      MIT