MCP server that dynamically generates tools from any OpenAPI 3.x specification
OpenAPI MCP Server
An MCP (Model Context Protocol) server that dynamically generates tools from any OpenAPI 3.x specification. Point it at a spec file or URL and it creates one MCP tool per API operation — no code generation, no AI, pure spec-driven mapping.
How it works
OpenAPI spec (file or URL)
→ parse & resolve $refs (swagger-parser)
→ filter operations (optional include/exclude rules)
→ for each operation:
→ derive tool name from operationId or method+path
→ merge path/query/header params + request body into a single JSON Schema
→ map HTTP method to MCP tool annotations (readOnly, destructive, idempotent)
→ register as an MCP tool with a call handler that makes the actual HTTP request
→ start MCP server over stdio
Features
- Any OpenAPI 3.0.x / 3.1.x spec — file path or URL
- Smart tool naming — uses
operationIdwhen available, falls back tomethod_pathpattern - MCP tool annotations — automatically sets
readOnlyHint,destructiveHint,idempotentHintbased on HTTP method - Schema merging — path, query, header params and request body flattened into one input schema
- Full schema support — objects, arrays,
allOf,oneOf,anyOf, enums, formats, nested structures - Auth strategies — Bearer, Basic, API Key (header or query), or none
- Operation filtering — include/exclude by path glob, HTTP method, tag, or operationId
- Security hardening — response sanitization with cryptographic boundary markers (prompt injection defense), response truncation, rate limiting
- Environment variable interpolation —
${API_TOKEN}in CLI args or config files
Prerequisites
- Java 21 or later
- Maven 3.8+ (to build from source)
Quick start
1. Build
git clone https://github.com/wrxck/openapi-mcp.git
cd openapi-mcp
mvn clean package -DskipTests
This produces target/openapi-mcp-1.0.0.jar — a self-contained executable JAR.
2. Register with Claude Code
claude mcp add --scope user --transport stdio openapi-petstore -- \
java -jar /path/to/openapi-mcp-1.0.0.jar \
--spec https://petstore3.swagger.io/api/v3/openapi.json
3. Use
> What pets are available in the store?
> Create a new pet named "Buddy" with tag "dog"
> Get the store inventory
Configuration
CLI arguments
# Minimal — just a spec
java -jar openapi-mcp.jar --spec petstore.yaml
# With auth
java -jar openapi-mcp.jar --spec https://api.example.com/openapi.json \
--auth-type bearer --auth-token '${API_TOKEN}'
# With API key
java -jar openapi-mcp.jar --spec spec.yaml \
--auth-type api-key-header --auth-header-name X-API-Key --auth-token 'my-key'
# Rate limiting and timeouts
java -jar openapi-mcp.jar --spec spec.yaml \
--max-requests-per-minute 30 --request-timeout 15
| Flag | Description | Default |
|------|-------------|---------|
| --spec | OpenAPI spec file path or URL | (required) |
| --config | JSON config file (see below) | |
| --auth-type | none, bearer, basic, api-key-header, api-key-query | none |
| --auth-token | Auth token/credentials (supports ${ENV_VAR}) | |
| --auth-header-name | Custom header name for api-key-header auth | X-API-Key |
| --auth-query-param | Query param name for api-key-query auth | api_key |
| --server-name | MCP server name | openapi-mcp |
| --server-version | MCP server version | 1.0.0 |
| --max-requests-per-minute | Rate limit | 60 |
| --max-response-length | Truncate responses beyond this length | 50000 |
| --connect-timeout | Connection timeout in seconds | 10 |
| --request-timeout | Request timeout in seconds | 30 |
JSON config file
For complex setups with filtering:
{
"spec": "https://api.example.com/openapi.json",
"authType": "bearer",
"authToken": "${API_TOKEN}",
"includeMethods": ["GET", "POST"],
"excludeTags": ["admin", "internal"],
"excludePaths": ["/debug/**"],
"maxRequestsPerMinute": 30,
"serverName": "my-api"
}
java -jar openapi-mcp.jar --config config.json
Tool annotations
Every generated tool includes MCP annotations based on the HTTP method:
| HTTP Method | readOnlyHint | destructiveHint | idempotentHint | |-------------|:---:|:---:|:---:| | GET, HEAD, OPTIONS | true | false | true | | POST | false | false | false | | PUT | false | false | true | | PATCH | false | false | false | | DELETE | false | true | true |
This means Claude will treat DELETE operations with appropriate caution and won't hesitate to call GET endpoints for information gathering.
Security
- Response sanitization — All API responses are wrapped in unique cryptographic boundary markers with instructions to treat the content as untrusted data. This defends against prompt injection via API responses.
- Response truncation — Responses are truncated at a configurable limit (default 50k chars) to prevent context overflow.
- Rate limiting — Sliding window rate limiter prevents excessive API calls (default 60/minute).
- Timeouts — Configurable connect timeout (10s) and request timeout (30s) prevent hanging connections.
Building from source
mvn clean verify
This compiles, runs all 114 tests, and produces the shaded JAR.
Project structure
src/main/java/com/openapi/mcp/
├── OpenApiMcpServer.java # Entry point, CLI, server bootstrap
├── ServerConfig.java # CLI args, JSON config, env var interpolation
├── SpecLoader.java # swagger-parser wrapper
├── ToolGenerator.java # Orchestrates tool generation from OpenAPI operations
├── ToolNaming.java # operationId sanitization, method+path fallback
├── SchemaConverter.java # OpenAPI Schema → JSON Schema
├── InputSchemaBuilder.java # Merge params + body into single input schema
├── ToolAnnotationMapper.java # HTTP method → MCP tool annotations
├── HttpApiClient.java # Execute HTTP requests to target API
├── RequestBuilder.java # Build HTTP requests from operation metadata
├── AuthProvider.java # Auth interface
├── AuthProviders.java # Bearer, Basic, API Key, None implementations
├── OperationFilter.java # Include/exclude by path, method, tag, operationId
├── ContentSanitizer.java # Prompt injection defense (boundary markers)
├── ResultHelper.java # MCP result formatting
└── RateLimiter.java # Sliding window rate limiter