mcp-server-openapi

Automatically convert OpenAPI endpoints into MCP tools
Turn any OpenAPI-documented API into a set of tools that Claude Desktop (or any MCP client) can call. Just tag the endpoints you want to expose, point the server at your spec, and you're done.
Why mcp-server-openapi?
| Feature |
mcp-server-openapi |
mcp-link |
emcee |
| OpenAPI parser |
kin-openapi (official, battle-tested) |
Custom parser |
Custom parser |
| Tag-based filtering |
Yes (mcp tag + x-mcp-hidden) |
No (exposes everything) |
Limited |
| Custom tool names |
x-mcp-tool-name |
No |
No |
| Custom descriptions |
x-mcp-description |
No |
No |
| Collision detection |
Yes (operationId + path-based fallback) |
No |
No |
| Bearer auth |
Yes |
Yes |
Yes |
| API key auth (header + query) |
Yes |
No |
Yes |
| $ref resolution |
Full (kin-openapi) |
Partial |
Partial |
| Go version |
1.23 |
1.21 |
1.22 |
TL;DR: We use the official kin-openapi parser, support fine-grained control via OpenAPI extensions, and detect/prevent tool name collisions automatically.
Quick Start
1. Install
go install github.com/soyvural/mcp-server-openapi/cmd/mcp-server-openapi@latest
Or clone and build:
git clone https://github.com/soyvural/mcp-server-openapi.git
cd mcp-server-openapi
make build
2. Run the Server
mcp-server-openapi --spec ./examples/petstore/petstore.yaml
Edit your Claude Desktop config:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json
- Windows:
%APPDATA%\Claude\claude_desktop_config.json
Add:
{
"mcpServers": {
"openapi": {
"command": "/path/to/mcp-server-openapi",
"args": [
"--spec",
"/path/to/your/openapi.yaml"
]
}
}
}
Restart Claude Desktop. You should now see the exposed tools in the MCP tools panel.
How It Works
┌──────────────────┐
│ OpenAPI Spec │ (YAML or JSON, local or URL)
│ (tagged with │
│ "mcp") │
└────────┬─────────┘
│
v
┌────────────────────────────────────────────────────┐
│ mcp-server-openapi │
│ │
│ 1. Parse spec (kin-openapi) │
│ 2. Filter operations by tag │
│ 3. Generate MCP tool schema (JSON Schema) │
│ 4. Serve tools via stdio (mcp-go SDK) │
│ 5. Execute HTTP requests when called │
└────────┬───────────────────────────────────────────┘
│
v
┌──────────────────┐
│ Claude Desktop │ (or any MCP client)
│ calls tools │
└──────────────────┘
│
v
┌──────────────────┐
│ Your API │ (GET /pet/123, POST /orders, etc.)
└──────────────────┘
Key steps:
- Operations with the
mcp tag (configurable via --tag) are selected
- Each operation becomes an MCP tool with a JSON Schema input definition
- Path params, query params, headers, and request body are mapped to tool arguments
- When Claude calls a tool, we build and execute the HTTP request
- Response is returned as text (JSON, XML, plain text, etc.)
Tag Your Endpoints
Basic Tagging
Add the mcp tag to any operation you want to expose:
paths:
/pets/{petId}:
get:
tags:
- mcp
operationId: getPetById
summary: Get a pet by ID
parameters:
- name: petId
in: path
required: true
schema:
type: integer
responses:
"200":
description: OK
By default, only operations with the mcp tag are exposed. Operations without the tag are ignored.
OpenAPI Extensions (x-mcp-*)
Fine-tune tool generation with custom extensions:
paths:
/users/{id}:
get:
tags: [mcp]
operationId: getUserById
summary: Retrieve user by ID
x-mcp-tool-name: get_user # Override default tool name
x-mcp-description: | # Custom description for Claude
Fetch detailed user information including profile, settings, and metadata.
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
"200":
description: OK
/internal/health:
get:
tags: [mcp] # Tagged, but...
operationId: healthCheck
x-mcp-hidden: true # Explicitly hidden
responses:
"200":
description: OK
/debug/stats:
get:
tags: [internal] # No mcp tag, but...
operationId: getStats
x-mcp-hidden: false # Force visible
responses:
"200":
description: OK
Supported extensions:
x-mcp-tool-name (string): Override the tool name (defaults to operationId or generated from method+path)
x-mcp-description (string): Override the tool description (defaults to summary or description)
x-mcp-hidden (boolean): Explicitly hide (true) or show (false) the operation, regardless of tag
CLI Reference
mcp-server-openapi [flags]
Flags:
--spec string OpenAPI spec file path or URL (required)
--tag string Tag to filter operations (default: "mcp")
--server-url string Override base URL from spec
--timeout duration HTTP request timeout (default: 30s)
--auth-type string Authentication type: bearer or api-key
--auth-token-env string Env var name for bearer token (e.g., GITHUB_TOKEN)
--auth-key-env string Env var name for API key (e.g., API_KEY)
--auth-key-name string Header/query param name for API key (e.g., X-API-Key)
--auth-key-in string Where to send API key: header or query
--log-level string Log level: debug, info, warn, error (default: info)
--log-file string Log file path (default: stderr)
Commands:
version Print version
Environment variables:
All flags can be set via OPENAPI_MCP_* env vars (e.g., OPENAPI_MCP_SPEC, OPENAPI_MCP_TAG).
Authentication
Bearer Token
export GITHUB_TOKEN="ghp_..."
mcp-server-openapi \
--spec https://api.github.com/openapi.yaml \
--auth-type bearer \
--auth-token-env GITHUB_TOKEN
The token is read from the specified env var and sent as Authorization: Bearer <token>.
export MY_API_KEY="sk_..."
mcp-server-openapi \
--spec ./api.yaml \
--auth-type api-key \
--auth-key-env MY_API_KEY \
--auth-key-name X-API-Key \
--auth-key-in header
Sends X-API-Key: sk_... with every request.
API Key (Query Parameter)
export MY_API_KEY="abc123"
mcp-server-openapi \
--spec ./api.yaml \
--auth-type api-key \
--auth-key-env MY_API_KEY \
--auth-key-name api_key \
--auth-key-in query
Appends ?api_key=abc123 to every request URL.
Examples
Petstore (Public API)
The classic Swagger Petstore example with 5 pet management operations:
mcp-server-openapi --spec examples/petstore/petstore.yaml
See examples/petstore/README.md for details.
Demo API (Full Feature Showcase)
A synthetic API demonstrating all parameter types, auth, and extensions:
cd examples/demo-api
go run main.go # Start local test server on :8080
In another terminal:
mcp-server-openapi --spec http://localhost:8080/openapi.yaml
See examples/demo-api/main.go for the full implementation.
Docker
Build the image:
docker build -t mcp-server-openapi .
Run with a local spec:
docker run --rm -i \
-v $(pwd)/examples:/specs \
mcp-server-openapi --spec /specs/petstore/petstore.yaml
Run with authentication:
docker run --rm -i \
-e GITHUB_TOKEN="ghp_..." \
mcp-server-openapi \
--spec https://api.github.com/openapi.yaml \
--auth-type bearer \
--auth-token-env GITHUB_TOKEN
Contributing
Contributions welcome! Please open an issue or PR.
Development:
make test # Run tests
make lint # Run golangci-lint
make build # Build binary to ./bin/
License
MIT License - see LICENSE for details.