
Your support encourages me to keep creating/supporting my open-source projects. If you found value in this project, you can buy me a coffee to keep me inspired.
OpenAPI MCP Server is a Model Context Protocol server that bridges OpenAPI specifications with LLMs (Large Language Models). It loads OpenAPI specs from URLs or local files and exposes the API operations as MCP tools. Built on Alpine Linux for minimal footprint and maximum security, wrapped with mcp-proxy for HTTP/SSE/WebSocket transport.
| Architecture | Tag Prefix | Status |
|---|---|---|
| x86-64 | amd64-<version> | Stable |
| ARM64 | arm64v8-<version> | Stable |
Multi-arch images automatically select the correct architecture for your system.
| Tag | Stability | Description | Use Case |
|---|---|---|---|
stable | High | Most stable release | Recommended for production |
latest | High | Latest stable release | Stay current with stable features |
1.1.6 | High | Specific version | Specific version |
beta | Low | Beta releases | Testing only |
CRITICAL: Do NOT expose this container directly to the internet without proper security measures (reverse proxy, SSL/TLS, authentication, firewall rules).
services:
openapi-mcp-server:
image: mekayelanik/openapi-mcp-server:stable
container_name: openapi-mcp-server
restart: unless-stopped
ports:
- "8050:8050"
environment:
- PORT=8050
- INTERNAL_PORT=38011
- PUID=1000
- PGID=1000
- TZ=Asia/Dhaka
- PROTOCOL=SHTTP
- ENABLE_HTTPS=false
- HTTP_VERSION_MODE=auto
# OpenAPI configuration
- API_NAME=my-api
- API_BASE_URL=https://api.example.com
- API_SPEC_URL=https://api.example.com/openapi.json
# - API_SPEC_PATH=/specs/openapi.json
# Authentication (choose one)
- AUTH_TYPE=none
# - AUTH_TYPE=bearer
# - AUTH_TOKEN=your-bearer-token
# - AUTH_TYPE=api_key
# - AUTH_API_KEY=your-api-key
# - AUTH_API_KEY_NAME=X-API-Key
# - AUTH_API_KEY_IN=header
# Optional: require Bearer token auth at HAProxy layer
# - API_KEY=replace-with-strong-secret
hostname: openapi-mcp-server
domainname: local
Deploy:
docker compose up -d
docker compose logs -f openapi-mcp-server
docker run -d \
--name=openapi-mcp-server \
--restart=unless-stopped \
-p 8050:8050 \
-e PORT=8050 \
-e INTERNAL_PORT=38011 \
-e PUID=1000 \
-e PGID=1000 \
-e TZ=Asia/Dhaka \
-e PROTOCOL=SHTTP \
-e ENABLE_HTTPS=false \
-e HTTP_VERSION_MODE=auto \
-e API_NAME=my-api \
-e API_BASE_URL=https://api.example.com \
-e API_SPEC_URL=https://api.example.com/openapi.json \
-e AUTH_TYPE=none \
mekayelanik/openapi-mcp-server:stable
| Protocol | Endpoint | Use Case |
|---|---|---|
| HTTP | http://host-ip:8050/mcp | Best compatibility (recommended) |
| SSE | http://host-ip:8050/sse | Real-time streaming |
When HTTPS is enabled (ENABLE_HTTPS=true), use TLS endpoints:
| Protocol | Endpoint |
|---|---|
| SHTTP | https://host-ip:8050/mcp |
| SSE | https://host-ip:8050/sse |
Security Warning: The container now defaults to HTTP (
ENABLE_HTTPS=false) for easier local setup. UseENABLE_HTTPS=truefor production, public networks, or any untrusted environment.ARM Devices: Allow 30-60 seconds for initialization before accessing endpoints.
| Variable | Default | Description |
|---|---|---|
PORT | 8050 | External server port |
INTERNAL_PORT | 38011 | Internal MCP server port used by mcp-proxy |
PUID | 1000 | User ID for file permissions |
PGID | 1000 | Group ID for file permissions |
TZ | Asia/Dhaka | Container timezone (TZ databaseโ ) |
PROTOCOL | SHTTP | Default transport protocol |
| Variable | Default | Description |
|---|---|---|
API_NAME | awslabs-openapi-mcp-server | API name identifier |
API_BASE_URL | https://localhost:8000 | Base URL for the API |
API_SPEC_URL | (empty) | URL to OpenAPI specification (HTTP or HTTPS). Spec is prefetched into the container at startup, so upstream httpx never touches the network. |
API_SPEC_PATH | (empty) | Local path to OpenAPI specification file (at least one of API_SPEC_URL / API_SPEC_PATH is required). When both are set, API_SPEC_PATH wins and the URL is ignored. |
API_SPEC_SSL_VERIFY | true | TLS verification for the spec prefetch from API_SPEC_URL. Set to false to allow self-signed or private-CA endpoints (e.g. local dev APIs). Has no effect when API_SPEC_PATH is used. |
Local / self-signed HTTPS APIs: Upstream
awslabs.openapi-mcp-serverfetchesAPI_SPEC_URLviahttpxwith no flag to disable TLS verification or inject a custom CA bundle, which breaks startup against self-signed endpoints. To work around this, the entrypoint prefetches the spec withwgetbefore launching the server and rewritesAPI_SPEC_URLโAPI_SPEC_PATH. For self-signed or private-CA hosts, setAPI_SPEC_SSL_VERIFY=false. Keep the defaulttruefor any public/internet-facing API to avoid MITM exposure. ConfiguredAUTH_TYPEheaders (api_key/bearer/basic) are forwarded on the prefetch request as well.
| Variable | Default | Description |
|---|---|---|
AUTH_TYPE | none | Authentication type (none, basic, bearer, api_key, cognito) |
AUTH_USERNAME | (empty) | Basic auth username |
AUTH_PASSWORD | (empty) | Basic auth password |
AUTH_TOKEN | (empty) | Bearer token |
AUTH_API_KEY | (empty) | API key value |
AUTH_API_KEY_NAME | api_key | API key parameter name |
AUTH_API_KEY_IN | header | Where to send API key (header, query, cookie) |
| Variable | Default | Description |
|---|---|---|
AUTH_COGNITO_CLIENT_ID | (empty) | Cognito client ID |
AUTH_COGNITO_USERNAME | (empty) | Cognito username |
AUTH_COGNITO_PASSWORD | (empty) | Cognito password |
AUTH_COGNITO_CLIENT_SECRET | (empty) | Cognito client secret |
AUTH_COGNITO_DOMAIN | (empty) | Cognito domain |
AUTH_COGNITO_SCOPES | (empty) | Cognito scopes |
AUTH_COGNITO_USER_POOL_ID | (empty) | Cognito user pool ID |
AUTH_COGNITO_REGION | us-east-1 | AWS region for Cognito |
| Variable | Default | Description |
|---|---|---|
SERVER_DEBUG | false | Enable debug mode (passes --debug to upstream) |
SERVER_MESSAGE_TIMEOUT | 60 | Message timeout in seconds (forwarded to upstream as env var) |
LOG_LEVEL | INFO | Upstream log level: DEBUG, INFO, WARNING, ERROR, CRITICAL |
Note: Upstream
awslabs.openapi-mcp-serverruns with stdio transport only inside this container โ the HTTP layer is provided by supergateway onINTERNAL_PORTand exposed externally through HAProxy onPORT. Upstream env vars likeSERVER_HOST/SERVER_PORT/SERVER_TRANSPORTare forwarded to the child process as-is but have no user-visible effect in this image.
LOG_LEVELis not read by upstream as an env var (upstream only honors--log-levelon the CLI). This entrypoint forwards it by translating to--log-levelfor convenience.
| Variable | Default | Description |
|---|---|---|
ENABLE_PROMETHEUS | false | Enable the Prometheus metrics endpoint |
PROMETHEUS_PORT | 9090 | Port for the Prometheus metrics server |
ENABLE_OPERATION_PROMPTS | true | Generate operation-specific prompts from the OpenAPI spec |
| Variable | Default | Description |
|---|---|---|
UVICORN_GRACEFUL_SHUTDOWN | true | Enable graceful shutdown handling |
UVICORN_TIMEOUT_GRACEFUL_SHUTDOWN | 5.0 | Graceful shutdown timeout (seconds) |
| Variable | Default | Description |
|---|---|---|
ENABLE_HTTPS | false | Enables TLS termination in HAProxy |
TLS_CERT_PATH | /etc/haproxy/certs/server.crt | TLS cert path |
TLS_KEY_PATH | /etc/haproxy/certs/server.key | TLS private key path |
TLS_PEM_PATH | /etc/haproxy/certs/server.pem | Combined PEM file used by HAProxy |
TLS_CN | localhost | CN for auto-generated certificate |
TLS_SAN | DNS:<TLS_CN> | SAN for auto-generated certificate |
TLS_DAYS | 365 | Auto-generated cert validity period |
TLS_MIN_VERSION | TLSv1.3 | Minimum TLS protocol (TLSv1.2 or TLSv1.3) |
HTTP_VERSION_MODE | auto | auto, all, h1, h2, h3, h1+h2 |
| Variable | Default | Description |
|---|---|---|
API_KEY | (empty) | Enables Bearer token auth at HAProxy layer (Authorization: Bearer <API_KEY>) |
CORS | (empty) | Comma-separated CORS origins, supports * |
RATE_LIMIT | 0 | Max requests per RATE_LIMIT_PERIOD per IP (0 = disabled) |
RATE_LIMIT_PERIOD | 10s | Sliding window for rate limiting (e.g., 10s, 1m, 1h) |
MAX_CONNECTIONS_PER_IP | 0 | Max concurrent connections per IP (0 = disabled) |
IP_ALLOWLIST | (empty) | Comma-separated IPs/CIDRs to allow (all others blocked) |
IP_BLOCKLIST | (empty) | Comma-separated IPs/CIDRs to block |
ENABLE_HTTPS=true and cert files are missing, the container auto-generates a self-signed certificate.TLS_CERT_PATH and TLS_KEY_PATH exist, they are merged into TLS_PEM_PATH and used directly.HTTP_VERSION_MODE=h3 (or auto) enables HTTP/3 only when HAProxy build includes QUIC; otherwise it safely falls back.API_KEY to enforce authentication at reverse proxy level.Authorization: Bearer <API_KEY>.RATE_LIMIT=100 to allow 100 requests per RATE_LIMIT_PERIOD (default 10s) per IP. Exceeding the limit returns HTTP 429 with a Retry-After header.MAX_CONNECTIONS_PER_IP=50 to cap concurrent connections per IP. Exceeding returns HTTP 429.IP_BLOCKLIST=192.0.2.0/24,198.51.100.5 to block specific IPs/CIDRs. Blocked IPs receive HTTP 403.IP_ALLOWLIST=10.0.0.0/8,192.168.1.0/24 to allow only listed IPs/CIDRs. All others receive HTTP 403. Localhost is always allowed.Find your IDs and set them to avoid permission issues:
id username
# uid=1000(user) gid=1000(group)
- TZ=Asia/Dhaka # Bangladesh
- TZ=America/New_York # US Eastern
- TZ=Europe/London # UK
- TZ=UTC # Universal Time
This image embeds mcp-proxy (sparfenyuk/mcp-proxy) as the stdioโHTTP bridge.
MCP_PROXY_STATELESS=false (default): one stdio backend child is shared across all MCP sessions, JSON-RPC-id-multiplexed. Minimal memory.MCP_PROXY_STATELESS=true: per-request transport instance. Use only when full session isolation is required.HAPROXY_FRONTEND_MAXCONN / HAPROXY_SERVER_MAXCONN: HAProxy-level caps. Defaults 64/16.Root cause: supergateway 3.4.3 stateless mode leaks child processes (supercorp-ai/supergateway#108).
| Client | HTTP | SSE | Recommended |
|---|---|---|---|
| VS Code (Cline/Roo-Cline) | Yes | Yes | No |
| Claude Desktop | Yes | Yes | Experimental |
| Claude CLI | Yes | Yes | Experimental |
| Codex CLI | Yes | Yes | Experimental |
| Codeium (Windsurf) | Yes | Yes | Experimental |
| Cursor | Yes | Yes | Experimental |
Configure in .vscode/settings.json:
{
"mcp.servers": {
"openapi-mcp": {
"url": "http://host-ip:8050/mcp",
"transport": "http"
}
}
}
With API_KEY:
claude mcp add-json openapi-mcp '{"type":"http","url":"http://localhost:8050/mcp","headers":{"Authorization":"Bearer <YOUR_API_KEY>"}}'
Without API_KEY:
claude mcp add-json openapi-mcp '{"type":"http","url":"http://localhost:8050/mcp"}'
Configure in ~/.codex/config.json:
{
"mcpServers": {
"openapi-mcp": {
"transport": "http",
"url": "http://host-ip:8050/mcp"
}
}
}
Configure in .codeium/mcp_settings.json:
{
"mcpServers": {
"openapi-mcp": {
"transport": "http",
"url": "http://host-ip:8050/mcp"
}
}
}
Configure in ~/.cursor/mcp.json:
{
"mcpServers": {
"openapi-mcp": {
"transport": "http",
"url": "http://host-ip:8050/mcp"
}
}
}
Verify with MCP Inspectorโ :
npm install -g @modelcontextprotocol/inspector
mcp-inspector http://host-ip:8050/mcp
| Network Mode | Complexity | Performance | Use Case |
|---|---|---|---|
| Bridge | Easy | Good | Default, isolated |
| Host | Moderate | Excellent | Direct host access |
| MACVLAN | Advanced | Excellent | Dedicated IP |
services:
openapi-mcp-server:
image: mekayelanik/openapi-mcp-server:stable
ports:
- "8050:8050"
Benefits: Container isolation, easy setup, works everywhere
Access: http://localhost:8050/mcp
services:
openapi-mcp-server:
image: mekayelanik/openapi-mcp-server:stable
network_mode: host
Benefits: Maximum performance, no NAT overhead, no port mapping needed
Considerations: Linux only, shares host network namespace
Access: http://localhost:8050/mcp
services:
openapi-mcp-server:
image: mekayelanik/openapi-mcp-server:stable
mac_address: "AB:BC:CD:DE:EF:01"
networks:
macvlan-net:
ipv4_address: 192.168.1.100
networks:
macvlan-net:
driver: macvlan
driver_opts:
parent: eth0
ipam:
config:
- subnet: 192.168.1.0/24
gateway: 192.168.1.1
Benefits: Dedicated IP, direct LAN access
Considerations: Linux only, requires additional setup
Access: http://192.168.1.100:8050/mcp
docker compose pull
docker compose up -d
docker image prune -f
docker pull mekayelanik/openapi-mcp-server:stable
docker stop openapi-mcp-server && docker rm openapi-mcp-server
# Run your original docker run command
docker image prune -f
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
containrrr/watchtower \
--run-once \
openapi-mcp-server
# Check Docker version
docker --version
# Verify port availability
sudo netstat -tulpn | grep 8050
# Check logs
docker logs openapi-mcp-server
# Get your IDs
id $USER
# Update configuration with correct PUID/PGID
# Fix volume permissions if needed
sudo chown -R 1000:1000 /path/to/volume
# Test connectivity
curl http://localhost:8050/mcp
curl http://host-ip:8050/mcp
curl -k https://localhost:8050/mcp
curl -k https://host-ip:8050/mcp
# Check firewall
sudo ufw status
# Verify container
docker inspect openapi-mcp-server | grep IPAddress
docker logs -f openapi-mcp-serverdocker stats openapi-mcp-serverWhen reporting issues, include:
# System info
docker --version && uname -a
# Container logs
docker logs openapi-mcp-server --tail 200 > logs.txt
# Container config
docker inspect openapi-mcp-server > inspect.json
Your support encourages me to keep creating/supporting my open-source projects. If you found value in this project, you can buy me a coffee to keep me inspired.
Docker Image Issues:
OpenAPI MCP Issues:
We welcome contributions:
GPL License. See LICENSEโ for details.
OpenAPI MCP server has its own license - see upstream repositoryโ .
Content type
Image
Digest
sha256:4df6c8a5eโฆ
Size
77 MB
Last updated
12 days ago
docker pull mekayelanik/openapi-mcp-server