Install
$ agentstack add mcp-rendis-mcp-openapi-proxy ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
mcp-openapi-proxy
Turn any OpenAPI 3.x spec into a lightweight MCP navigator/executor server — automatically.
Every REST API has an OpenAPI spec. Every AI agent speaks MCP. This bridge connects the two with zero code — point it at a spec, get a usable MCP navigator/executor.
[](https://go.dev) [](LICENSE) [](https://modelcontextprotocol.io)
The Problem
You have a REST API with 50+ endpoints and an OpenAPI spec that documents every one of them. You want an AI agent (Claude Code, Codex, Gemini CLI) to call your API through MCP. The standard approach: write one MCP tool definition per endpoint — input schemas, handlers, auth wiring — thousands of lines of boilerplate that breaks every time the API changes.
mcp-openapi-proxy eliminates that. One binary. One environment variable pointing to your spec. The proxy indexes every endpoint at startup, then exposes a small MCP navigator/executor surface that agents can actually load. No codegen, no generated files, no maintenance.
And authentication makes it worse. Production APIs use OIDC, OAuth2, or token-based auth — the agent needs valid credentials, tokens that expire need refreshing, and secrets need secure storage. mcp-openapi-proxy handles this end-to-end: static tokens for development, browser-based OIDC PKCE for production, with automatic token refresh and secure on-disk storage.
How It Works
flowchart LR
A["OpenAPI SpecYAML · JSON · URL"] --> B["Spec Parserkin-openapi"]
B --> C["Endpoints[]"]
C --> D["Endpoint IndextoolName + metadata"]
D --> E["3 MCP Toolslist · describe · call"]
E |"tool calls"| F["AI AgentClaude · Codex · Gemini"]
style A fill:#24283b,stroke:#bb9af7,color:#bb9af7
style B fill:#24283b,stroke:#7dcfff,color:#7dcfff
style C fill:#24283b,stroke:#e0af68,color:#e0af68
style D fill:#24283b,stroke:#9ece6a,color:#9ece6a
style E fill:#24283b,stroke:#bb9af7,color:#bb9af7
style F fill:#1a1b26,stroke:#7aa2f7,color:#7aa2f7
- The OpenAPI spec is loaded and parsed into a list of endpoints (method, path, parameters, request body)
- Each endpoint gets a stable
toolNameidentifier using{prefix}_{method}_{sanitized_path} - The proxy registers exactly three MCP tools:
list_endpoints,describe_endpoint, andcall_endpoint - Agents discover endpoints cheaply, fetch the full contract only when needed, and execute calls through the shared HTTP runtime
Features
- OpenAPI 3.x — parses paths, parameters, request bodies, and security schemes via kin-openapi
- Local and remote specs — load from a file path or any
http:///https://URL - Navigator/executor MCP surface — exactly 3 tools per server, regardless of API size
- Stable endpoint identifiers — every endpoint still gets a deterministic
toolName - Production-ready authentication — built-in OIDC Authorization Code + PKCE flow with browser-based login, automatic token refresh, and secure on-disk storage (
0600). Works with any OIDC provider: Keycloak, Auth0, Okta, Google, and more. No auth code to write. - Development auth — static bearer token via
MCP_AUTH_TOKENor per-scheme credentials viaMCP_AUTH__* - Spec-aware auth resolution — resolves
http bearer,http basic,apiKey,oauth2, andopenIdConnectfrom OpenAPI security requirements - Configurable tool prefix — namespace tools to avoid collisions when running multiple proxies
- Extra headers — inject custom headers (workspace IDs, API versions) into every request
- Lightweight discovery —
tools/liststays small whiledescribe_endpointexposes the full OpenAPI contract on demand - Structured call output —
call_endpointreturns a typed envelope withstatus,content_type,headers, andbody - Native image and audio content —
image/*andaudio/*responses are also surfaced as native MCPImageContent/AudioContentblocks so capable clients can render them inline - Forms and binary payloads — supports
multipart/form-data,application/x-www-form-urlencoded, text payloads, andapplication/octet-stream - stdio transport — compatible with Claude Code, OpenAI Codex, Gemini CLI, and any MCP client
What it does NOT do
- No codegen — tools are created dynamically at startup, no build step
- No API modification — read-only proxy, never changes the spec or backend
- No response rewriting — returns the real API response envelope, even when the backend deviates from the spec
- No OpenAPI 2.0 — only 3.x specs (convert older specs with swagger2openapi)
- No SSE/WebSocket — stdio transport only
Quick Start
# Install
go install github.com/rendis/mcp-openapi-proxy/cmd/mcp-openapi-proxy@latest
# Run with a local spec and static token
MCP_SPEC=./openapi.yaml \
MCP_BASE_URL=https://api.example.com \
MCP_AUTH_TOKEN=your-token \
mcp-openapi-proxy
If MCP_BASE_URL is omitted, the proxy falls back to a single absolute server declared in the OpenAPI spec when one can be resolved unambiguously.
Minimal setup flow
- Install the binary:
``bash go install github.com/rendis/mcp-openapi-proxy/cmd/mcp-openapi-proxy@latest ``
- Choose your MCP client setup:
- Claude Code: copy [
.mcp.json.example](./.mcp.json.example) into your project as.mcp.json - Codex global: register the server with
codex mcp add ... - Codex project-local: create
./.codex/config.tomlmanually
- Choose one auth path:
- Static token: add
MCP_AUTH_TOKENto the MCP client config - OIDC login: add
MCP_OIDC_ISSUERandMCP_OIDC_CLIENT_IDto the MCP client config, then run one of: mcp-openapi-proxy loginmcp-openapi-proxy loginmcp-openapi-proxy login --mcp-config ./path/to/.mcp.jsonmcp-openapi-proxy login --mcp-config ./path/to/.mcp.json --servermcp-openapi-proxy login --codex-servermcp-openapi-proxy login --codex-config ~/.codex/config.tomlmcp-openapi-proxy login --codex-config ~/.codex/config.toml --server
- Open your MCP client and use the server through
list_endpoints,describe_endpoint, andcall_endpoint.
When login is invoked with .mcp.json or Codex config support, it reads the selected server’s env from that config entry. If the same variable is present in both places, the shell environment wins.
Plain mcp-openapi-proxy login stays env-first for compatibility. When shell env is not enough, it falls back in this order:
./.mcp.json~/.codex/config.toml(or$CODEX_HOME/config.toml)
If the server name is omitted, login discovers eligible entries from the selected config file:
- direct
command: "mcp-openapi-proxy" - direct paths such as
"/path/to/bin/mcp-openapi-proxy"or"C:\\tools\\mcp-openapi-proxy.exe"
Wrapper commands such as go, env, docker, or shell scripts are ignored on purpose. If more than one eligible server exists, login shows the available names and prompts you to choose one.
If your spec comes from swag init
swag init generates Swagger 2.0 output. mcp-openapi-proxy only accepts OpenAPI 3.x specs, so do not point MCP_SPEC directly at the generated swagger.json.
Convert it first, then use the converted OpenAPI 3.x file:
swag init -g cmd/api/main.go
swagger2openapi ./docs/swagger.json -o ./docs/openapi.json
MCP_SPEC=./docs/openapi.json mcp-openapi-proxy
Installation
go install github.com/rendis/mcp-openapi-proxy/cmd/mcp-openapi-proxy@latest
Or build from source:
git clone https://github.com/rendis/mcp-openapi-proxy.git
go build -C mcp-openapi-proxy -o bin/mcp-openapi-proxy ./cmd/mcp-openapi-proxy
Configuration
All configuration is done through environment variables.
| Variable | Required | Default | Description | |---|---|---|---| | MCP_SPEC | Yes | — | Path or URL to an OpenAPI 3.x spec (YAML or JSON) | | MCP_BASE_URL | No | — | Explicit API base URL. If omitted, the proxy uses a single absolute OpenAPI server when available | | MCP_TOOL_PREFIX | No | api | Prefix for the 3 MCP navigator tools and for endpoint toolName identifiers | | MCP_AUTH_PROFILE | No | MCP_TOOL_PREFIX or default | Namespace for stored OIDC tokens | | MCP_AUTH_TOKEN | No | — | Global bearer token fallback | | MCP_OIDC_ISSUER | No | — | OIDC issuer URL (used with login command) | | MCP_OIDC_CLIENT_ID | No | — | OIDC client ID (used with login command) | | MCP_OIDC_SCOPES | No | Scopes discovered from MCP_SPEC or openid profile email offline_access | Override OIDC login scopes | | MCP_EXTRA_HEADERS | No | — | Comma-separated key:value pairs added to every request | | MCP_MAX_BODY_BYTES | No | 10485760 | Maximum response body size to buffer and return | | MCP_ALLOW_INSECURE_HTTP | No | 0 | Allow sending resolved credentials over non-loopback http:// URLs | | MCP_EXCLUDE_DEPRECATED | No | 0 | Skip deprecated endpoints when generating tools |
> [!IMPORTANT] > Auth resolution: MCP_AUTH__* → global MCP_AUTH_TOKEN → OIDC token cache for MCP_AUTH_PROFILE. > > Trailing slashes on MCP_BASE_URL are stripped automatically.
Commands
| Command | Description | |---|---| | mcp-openapi-proxy | Start the MCP server (default, same as serve) | | mcp-openapi-proxy serve | Start the MCP server explicitly | | mcp-openapi-proxy login | Browser-based OIDC Authorization Code + PKCE login | | mcp-openapi-proxy login | Run login using ./.mcp.json and mcpServers..env | | mcp-openapi-proxy login --mcp-config | Run login using an MCP config file, auto-selecting or prompting for an eligible mcp-openapi-proxy server | | mcp-openapi-proxy login --mcp-config --server | Run login using a selected server from an MCP config file | | mcp-openapi-proxy login --codex-config | Run login using a Codex TOML config, auto-selecting or prompting for an eligible mcp-openapi-proxy server | | mcp-openapi-proxy login --codex-config --server | Run login using a selected server from a Codex TOML config | | mcp-openapi-proxy login --codex-server | Run login using ~/.codex/config.toml (or $CODEX_HOME/config.toml) and mcp_servers..env | | mcp-openapi-proxy logout | Remove stored tokens from disk | | mcp-openapi-proxy status | Display current authentication state |
Usage with AI Agents
Claude Code — .mcp.json
Generic example:
{
"mcpServers": {
"my-api": {
"command": "mcp-openapi-proxy",
"env": {
"MCP_SPEC": "./openapi.yaml",
"MCP_BASE_URL": "https://api.example.com",
"MCP_TOOL_PREFIX": "myapi",
"MCP_AUTH_PROFILE": "myapi"
}
}
}
}
Static token variant:
{
"mcpServers": {
"my-api": {
"command": "mcp-openapi-proxy",
"env": {
"MCP_SPEC": "./openapi.yaml",
"MCP_BASE_URL": "https://api.example.com",
"MCP_TOOL_PREFIX": "myapi",
"MCP_AUTH_PROFILE": "myapi",
"MCP_AUTH_TOKEN": "your-token"
}
}
}
}
OIDC variant:
{
"mcpServers": {
"my-api": {
"command": "mcp-openapi-proxy",
"env": {
"MCP_SPEC": "./openapi.yaml",
"MCP_BASE_URL": "https://api.example.com",
"MCP_TOOL_PREFIX": "myapi",
"MCP_AUTH_PROFILE": "myapi",
"MCP_OIDC_ISSUER": "https://auth.example.com/realms/myrealm",
"MCP_OIDC_CLIENT_ID": "my-client"
}
}
}
}
If you use the OIDC variant, run login once before starting Claude Code. You can now do that directly from the .mcp.json entry:
mcp-openapi-proxy login
Or select the server explicitly:
mcp-openapi-proxy login my-api
Or against an explicit config path:
mcp-openapi-proxy login --mcp-config ./path/to/.mcp.json
Or with an explicit config path plus explicit server:
mcp-openapi-proxy login --mcp-config ./path/to/.mcp.json --server my-api
When the server name is omitted, login only considers .mcp.json entries whose command is a direct mcp-openapi-proxy binary or path to that binary. Wrapper commands such as go, env, docker, or shell scripts are not used for login discovery.
Equivalent env-only form:
MCP_AUTH_PROFILE=myapi \
MCP_OIDC_ISSUER=https://auth.example.com/realms/myrealm \
MCP_OIDC_CLIENT_ID=my-client \
mcp-openapi-proxy login
OpenAI Codex — .codex/config.toml
Global install via Codex CLI:
codex mcp add my-api \
--env MCP_SPEC=./openapi.yaml \
--env MCP_BASE_URL=https://api.example.com \
--env MCP_TOOL_PREFIX=myapi \
--env MCP_AUTH_TOKEN=your-token \
-- mcp-openapi-proxy
OIDC variant via Codex CLI:
codex mcp add my-api \
--env MCP_SPEC=./openapi.yaml \
--env MCP_BASE_URL=https://api.example.com \
--env MCP_TOOL_PREFIX=myapi \
--env MCP_AUTH_PROFILE=myapi \
--env MCP_OIDC_ISSUER=https://auth.example.com/realms/myrealm \
--env MCP_OIDC_CLIENT_ID=my-client \
-- mcp-openapi-proxy
Codex CLI writes the global server entry to ~/.codex/config.toml.
Project-local Codex config is manual because the visible codex mcp add help does not expose a project-scoped install mode. Create ./.codex/config.toml yourself when you want repo-local configuration:
[mcp_servers.my-api]
command = "mcp-openapi-proxy"
[mcp_servers.my-api.env]
MCP_SPEC = "./openapi.yaml"
MCP_BASE_URL = "https://api.example.com"
MCP_TOOL_PREFIX = "myapi"
MCP_AUTH_TOKEN = "your-token"
OIDC login for Codex-managed entries is still done with mcp-openapi-proxy login, not codex mcp login:
mcp-openapi-proxy login --codex-server my-api
Or against an explicit Codex config file:
mcp-openapi-proxy login --codex-config ~/.codex/config.toml
mcp-openapi-proxy login --codex-config ~/.codex/config.toml --server my-api
mcp-openapi-proxy login --codex-config ./.codex/config.toml --server my-api
codex mcp login is for OAuth flows that Codex manages itself. For this stdio server, keep using mcp-openapi-proxy login so the proxy can perform OIDC discovery, PKCE, and token storage.
> [!NOTE] > Codex has the concept of project config.toml files and can ignore them in untrusted folders. If a local ./.codex/config.toml entry does not load, either use the global ~/.codex/config.toml path or work from a trusted project.
Gemini CLI — ~/.gemini/settings.json
{
"mcpServers": {
"my-api": {
"command": "mcp-openapi-proxy",
"env": {
"MCP_SPEC": "./openapi.yaml",
"MCP_BASE_URL": "https://api.example.com",
"MCP_TOOL_PREFIX": "myapi",
"MCP_AUTH_TOKEN": "your-token"
}
}
}
}
MCP Surface
The server always registers exactly these 3 MCP tools:
| Tool | Purpose | |---|---| | {prefix}_list_endpoints | Lightweight discovery with filtering and pagination | | {prefix}_describe_endpoint | Full OpenAPI contract for one endpoint | | {prefix}_call_endpoint | Execute one endpoint by toolName |
Agents should always inspect these registered tools first. The proxy no longer exposes one MCP tool per endpoint.
Endpoint IDs
Each OpenAPI operation still gets a stable identifier called toolName:
{prefix}_{method}_{sanitized_path}
Path segments are lowercased. Special characters (/, -, {, }, .) are replaced with underscores. Consecutive underscores are collapsed.
| Method | Path | Prefix | Endpoint toolName | |---|---|---|---| | GET | /users | api | api_get_users | | POST | /users | api | api_post_users | | GET | /users/{id} | api | api_get_users_id | | DELETE | /admin/features/{key} | fe | fe_delete_admin_features_key | | GET | /v1/health.check | svc | svc_get_v1_health_check |
toolName is the identifier passed to describe_endpoint and call_endpoint. It is no longer a registered MCP tool by itself.
Disco
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: rendis
- Source: rendis/mcp-openapi-proxy
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.