stormino/openapi-mcp-server
If you are the rightful owner of openapi-mcp-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
The OpenAPI MCP Server is a Go-based server that dynamically loads tools from OpenAPI/Swagger specifications, supporting both STDIO and HTTP/SSE transport modes.
OpenAPI MCP Server
A Model Context Protocol (MCP) server that dynamically loads tools from OpenAPI/Swagger specifications. Written in Go, it provides both STDIO and HTTP/SSE transport modes for integration with Claude Desktop and web-based MCP clients.
Quick Start
# Install dependencies
go mod download
# Build (creates bin/openapi-mcp-server)
make build
# Run with example spec (STDIO mode)
./bin/openapi-mcp-server -s specs/petstore.json
# Run in HTTP mode
./bin/openapi-mcp-server -s specs/petstore.json -mode http -port 8080
Installation
Prerequisites
- Go 1.25 or higher
Build from Source
git clone <repository-url>
cd openapi-mcp-server
go mod download
make build
Usage
Command Line Options
./openapi-mcp-server [flags]
Flags:
-s, --spec string Path to OpenAPI spec file or URL (required)
-b, --base-url string Base URL to override the server URL from the OpenAPI spec
-m, --mode string Transport mode: stdio or http (default "stdio")
-p, --port int HTTP port (only used in http mode) (default 8080)
-l, --log-level string Logging level: debug, info, warn, error (default "info")
-h, --help Help for openapi-mcp-server
-v, --version Version for openapi-mcp-server
Spec Source: The -s flag accepts both local file paths and remote URLs:
- Local files:
specs/petstore.json,/path/to/openapi.yaml - Remote URLs:
https://example.com/openapi.json,http://api.example.com/spec.yaml
Configuration Priority
Configuration is loaded in the following priority (highest to lowest):
- CLI flags - Command-line arguments (e.g.,
-s specs/petstore.json) - Environment variables - Shell environment variables (e.g.,
MCP_MODE=http) - Config file - YAML configuration file (see below)
- Defaults - Built-in default values
Environment Variables
MCP_SPEC: Path to OpenAPI spec file or URLMCP_BASE_URLorAPI_BASE_URL: Base URL to override the OpenAPI spec's server URLMCP_MODE: Transport mode (stdioorhttp)MCP_PORTorHTTP_PORT: HTTP port number (default:8080)MCP_LOG_LEVELorLOG_LEVEL: Logging level (debug,info,warn,error)
Configuration File
Create a config.yaml file in one of these locations:
- Current directory:
./config.yaml - Home directory:
~/.openapi-mcp-server/config.yaml - System directory:
/etc/openapi-mcp-server/config.yaml
Example config.yaml:
spec: specs/petstore.json
base-url: https://api.example.com # Optional: override spec's server URL
mode: stdio
port: 8080
log-level: info
See for a full example.
Examples
# STDIO mode with local spec file
./bin/openapi-mcp-server -s specs/petstore.json
# Load spec from a remote URL
./bin/openapi-mcp-server -s https://petstore.swagger.io/v2/swagger.json
# Override the base URL from the spec
./bin/openapi-mcp-server -s specs/petstore.json -b https://my-api.example.com
# Load from URL and override base URL
./bin/openapi-mcp-server -s https://example.com/openapi.json -b https://api.production.com
# Short flags work too
./bin/openapi-mcp-server -s specs/petstore.json -m http -p 8080
# HTTP mode on default port (8080)
./bin/openapi-mcp-server --spec specs/petstore.json --mode http
# HTTP mode on custom port with base URL override
./bin/openapi-mcp-server -s specs/petstore.json -b https://staging.api.com -m http -p 3000
# Using environment variables
MCP_MODE=http MCP_PORT=9000 MCP_BASE_URL=https://api.example.com ./bin/openapi-mcp-server -s specs/petstore.json
# Using config file (create config.yaml first)
./bin/openapi-mcp-server
# Enable debug logging
./bin/openapi-mcp-server -s specs/petstore.json -l debug
# Get help
./bin/openapi-mcp-server --help
# Get version
./bin/openapi-mcp-server --version
Using Make
# Build the server
make build
# Run in STDIO mode (default)
make run
# Run in HTTP mode
make run-http
# Run with custom spec
make run SPEC=path/to/your/spec.yaml
# Run tests
make test
# Clean build artifacts
make clean
Integration with Claude Desktop
- Build the server:
make build
- Get the full path:
pwd
# Example output: /home/user/openapi-mcp-server
-
Edit Claude Desktop config:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
- macOS:
-
Add the server configuration:
{
"mcpServers": {
"openapi-tools": {
"command": "/home/user/openapi-mcp-server/bin/openapi-mcp-server",
"args": ["-s", "/home/user/openapi-mcp-server/specs/petstore.json"]
}
}
}
Optional: Override the base URL using the -b flag:
{
"mcpServers": {
"openapi-tools": {
"command": "/home/user/openapi-mcp-server/bin/openapi-mcp-server",
"args": [
"-s", "/home/user/openapi-mcp-server/specs/petstore.json",
"-b", "https://staging-api.example.com"
]
}
}
}
-
Restart Claude Desktop
-
Start using your API tools in Claude!
How It Works
- OpenAPI Spec: You provide an OpenAPI 3.x specification file
- Dynamic Loading: The loader parses the spec and creates an MCP tool for each operation
- Tool Registration: Tools are registered with the MCP server
- Tool Execution: When Claude calls a tool, the server makes an HTTP request to the actual API
- Response: The API response is formatted and returned to Claude
Base URL Override
By default, the server uses the base URL defined in the OpenAPI spec's servers array. However, you can override this using the -b flag or MCP_BASE_URL environment variable.
Use cases for base URL override:
- Environment switching: Use a production spec with staging/development URLs
- Local testing: Point to
http://localhost:3000instead of production - Proxying: Route requests through a proxy or gateway
- Custom deployments: Use the same spec with different deployed instances
Example:
# OpenAPI spec has servers: [{"url": "https://api.example.com"}]
# But you want to test against staging:
./bin/openapi-mcp-server -s specs/api.json -b https://staging-api.example.com
# Or use localhost for development:
./bin/openapi-mcp-server -s specs/api.json -b http://localhost:8080
Priority:
- Base URL from
-bflag orMCP_BASE_URLenvironment variable (if provided) - First server URL from the OpenAPI spec's
serversarray - Empty string (if no servers defined and no override provided)
Tool Generation
Given this OpenAPI operation:
/pets/{petId}:
get:
operationId: getPetById
summary: Find pet by ID
parameters:
- name: petId
in: path
required: true
schema:
type: integer
The server automatically creates an MCP tool named getPetById that:
- Accepts a
petIdparameter - Makes a GET request to
https://api.example.com/pets/{petId} - Returns the response to Claude
Tool Naming
Tools are named using:
operationIdfrom the OpenAPI spec (preferred)- Auto-generated from
method_pathif no operationId (e.g.,get_pets_petId)
Request Handling
The server automatically handles:
- Path parameters: Replaced in the URL (e.g.,
/pets/{petId}) - Query parameters: Added to the URL query string
- Request body: Sent as JSON in the request body (for POST/PUT/PATCH)
- Headers: Content-Type set automatically when body is present
Transport Modes
STDIO Mode (Default)
Best for local integrations like Claude Desktop:
- Communicates via standard input/output
- Process-based communication
- Default mode when
-modeis not specified
HTTP Mode
Best for web-based MCP clients:
- Server-Sent Events (SSE) transport
- RESTful interface
- Accessible via HTTP at
/sseendpoint - Supports remote connections
Extending the Server
Adding Authentication
Add API key support in the loader:
// In executeAPICall, before making the request:
if apiKey := os.Getenv("API_KEY"); apiKey != "" {
req.Header.Set("X-API-Key", apiKey)
// Or: req.Header.Set("Authorization", "Bearer " + apiKey)
}
Adding Rate Limiting
import "golang.org/x/time/rate"
type OpenAPIToolLoader struct {
// ... existing fields ...
limiter *rate.Limiter
}
// In executeAPICall:
if err := l.limiter.Wait(ctx); err != nil {
return nil, nil, fmt.Errorf("rate limit error: %w", err)
}
Adding Request Caching
type CacheEntry struct {
Response []byte
Timestamp time.Time
StatusCode int
}
// Cache GET requests based on URL and parameters
// Check cache before making request, store after successful response
Adding Retry Logic
maxRetries := 3
for i := 0; i < maxRetries; i++ {
resp, err = client.Do(req)
if err == nil && resp.StatusCode < 500 {
break // Success or client error
}
if i < maxRetries-1 {
time.Sleep(time.Duration(i+1) * time.Second)
}
}
Development
Running Tests
# Run all tests
make test
# Or use go test directly
go test ./... -v
# Run tests with coverage
go test ./... -cover
Testing with MCP Inspector
npx @modelcontextprotocol/inspector go run main.go -s specs/petstore.json
This opens a web interface where you can:
- See all loaded tools
- Test tool calls
- View request/response data
Example OpenAPI Spec
Create a file specs/myapi.yaml:
openapi: 3.0.0
info:
title: My API
version: 1.0.0
servers:
- url: https://api.example.com/v1
paths:
/users/{userId}:
get:
operationId: getUser
summary: Get user by ID
parameters:
- name: userId
in: path
required: true
schema:
type: string
responses:
'200':
description: User found
/users:
post:
operationId: createUser
summary: Create a new user
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
email:
type: string
required:
- name
- email
responses:
'201':
description: User created
Then run:
./openapi-mcp-server -s specs/myapi.yaml
Troubleshooting
"Error: spec file is required"
You must provide the -s flag with a path to an OpenAPI spec file.
"Error: spec file not found"
Check that the path to your OpenAPI spec is correct and the file exists.
"Failed to load spec"
Ensure your OpenAPI spec is valid. You can validate it at https://editor.swagger.io/
Tools not appearing in Claude
- Check that the server is running without errors
- Verify your Claude Desktop config has the correct paths
- Restart Claude Desktop after config changes
- Check server logs for any errors
Performance
- Startup: Instant, tools loaded in milliseconds
- Memory: Minimal, ~10MB base + spec size
- Concurrency: Thread-safe, handles multiple concurrent tool calls
Security Considerations
⚠️ Important: This server makes real HTTP requests to the APIs defined in your OpenAPI specs.
For production use:
- Use HTTPS for all API endpoints
- Add authentication to your APIs
- Validate and sanitize OpenAPI specs before loading
- Implement rate limiting
- Add request logging/auditing
- Consider running in a sandboxed environment
- Use environment variables for sensitive data (API keys, tokens)
Dependencies
github.com/modelcontextprotocol/go-sdk- Official MCP Go SDKgithub.com/getkin/kin-openapi- OpenAPI 3.x parser and validatorgithub.com/invopop/jsonschema- JSON Schema generationgithub.com/spf13/cobra- Modern CLI framework with command structuregithub.com/spf13/viper- Configuration management (env vars, config files, flags)
Contributing
Contributions are welcome! Feel free to:
- Report bugs
- Suggest features
- Submit pull requests
- Improve documentation
License
MIT