# Mcp Openapi Proxy

> Turn any OpenAPI 3.x spec into a fully functional MCP server — automatically. One binary, zero codegen, built-in OIDC PKCE auth with auto-refresh. Works with Claude Code, Codex, Gemini CLI, and any MCP client.

- **Type:** MCP server
- **Install:** `agentstack add mcp-rendis-mcp-openapi-proxy`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [rendis](https://agentstack.voostack.com/s/rendis)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [rendis](https://github.com/rendis)
- **Source:** https://github.com/rendis/mcp-openapi-proxy

## Install

```sh
agentstack add mcp-rendis-mcp-openapi-proxy
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## 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

  

```mermaid
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
```

1. The OpenAPI spec is loaded and parsed into a list of endpoints (method, path, parameters, request body)
2. Each endpoint gets a stable `toolName` identifier using `{prefix}_{method}_{sanitized_path}`
3. The proxy registers exactly three MCP tools: `list_endpoints`, `describe_endpoint`, and `call_endpoint`
4. 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](https://github.com/getkin/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_TOKEN` or per-scheme credentials via `MCP_AUTH__*`
- **Spec-aware auth resolution** — resolves `http bearer`, `http basic`, `apiKey`, `oauth2`, and `openIdConnect` from 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/list` stays small while `describe_endpoint` exposes the full OpenAPI contract on demand
- **Structured call output** — `call_endpoint` returns a typed envelope with `status`, `content_type`, `headers`, and `body`
- **Native image and audio content** — `image/*` and `audio/*` responses are also surfaced as native MCP `ImageContent` / `AudioContent` blocks so capable clients can render them inline
- **Forms and binary payloads** — supports `multipart/form-data`, `application/x-www-form-urlencoded`, text payloads, and `application/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](https://github.com/Mermade/oas-kit))
- **No SSE/WebSocket** — stdio transport only

## Quick Start

```bash
# 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

1. Install the binary:

   ```bash
   go install github.com/rendis/mcp-openapi-proxy/cmd/mcp-openapi-proxy@latest
   ```

2. 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.toml` manually

3. Choose one auth path:
   - Static token: add `MCP_AUTH_TOKEN` to the MCP client config
   - OIDC login: add `MCP_OIDC_ISSUER` and `MCP_OIDC_CLIENT_ID` to the MCP client config, then run one of:
     - `mcp-openapi-proxy login`
     - `mcp-openapi-proxy login `
     - `mcp-openapi-proxy login --mcp-config ./path/to/.mcp.json`
     - `mcp-openapi-proxy login --mcp-config ./path/to/.mcp.json --server `
     - `mcp-openapi-proxy login --codex-server `
     - `mcp-openapi-proxy login --codex-config ~/.codex/config.toml`
     - `mcp-openapi-proxy login --codex-config ~/.codex/config.toml --server `

4. Open your MCP client and use the server through `list_endpoints`, `describe_endpoint`, and `call_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:

1. `./.mcp.json`
2. `~/.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:

```bash
swag init -g cmd/api/main.go
swagger2openapi ./docs/swagger.json -o ./docs/openapi.json
MCP_SPEC=./docs/openapi.json mcp-openapi-proxy
```

## Installation

```bash
go install github.com/rendis/mcp-openapi-proxy/cmd/mcp-openapi-proxy@latest
```

Or build from source:

```bash
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:

```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_PROFILE": "myapi"
      }
    }
  }
}
```

Static token variant:

```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_PROFILE": "myapi",
        "MCP_AUTH_TOKEN": "your-token"
      }
    }
  }
}
```

OIDC variant:

```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_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:

```bash
mcp-openapi-proxy login
```

Or select the server explicitly:

```bash
mcp-openapi-proxy login my-api
```

Or against an explicit config path:

```bash
mcp-openapi-proxy login --mcp-config ./path/to/.mcp.json
```

Or with an explicit config path plus explicit server:

```bash
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:

```bash
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:

```bash
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:

```bash
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:

```toml
[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`:

```bash
mcp-openapi-proxy login --codex-server my-api
```

Or against an explicit Codex config file:

```bash
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

```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](https://github.com/rendis)
- **Source:** [rendis/mcp-openapi-proxy](https://github.com/rendis/mcp-openapi-proxy)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-rendis-mcp-openapi-proxy
- Seller: https://agentstack.voostack.com/s/rendis
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
