Go CLI that converts OpenAPI 3.x specs into a lightweight MCP stdio navigator/executor — 3 MCP tools plus indexed endpoint toolName identifiers, no codegen.
cmd/mcp-openapi-proxy/main.go— CLI entry point, env var parsing, subcommands: serve/login/logout/statuspkg/spec/model.go— internal OpenAPI model types: endpoints, params, media types, security, serverspkg/spec/parser.go— OpenAPI 3.x parser (kin-openapi), validates the spec and extracts Endpoint structspkg/server/server.go— MCP server setup, stdio transportpkg/server/generator.go— endpointtoolName/ path sanitization helperspkg/server/navigator.go— endpoint index plus the 3 registered MCP tools: list/describe/callpkg/server/schema.go— JSON Schema generation for the lightweight navigator tool inputs plus response helperspkg/server/runtime.go— request serialization, auth application, HTTP execution, MCP envelope responsespkg/client/client.go— HTTP client execution, content-type aware decoding, response body limitspkg/client/errors.go— client transport/body limit errorspkg/auth/provider.go— TokenProvider interface + StaticTokenProviderpkg/auth/resolver.go— resolves OpenAPI security requirements to concrete HTTP auth materialpkg/auth/oidc_provider.go— OIDC token storage, auto-refresh (30s margin)pkg/auth/discovery.go— OIDC .well-known/openid-configuration endpoint discoverypkg/auth/login.go— Browser-based OIDC Authorization Code + PKCE flowpkg/auth/logout.go— Token file removalpkg/auth/status.go— Auth state display
github.com/getkin/kin-openapi— OpenAPI 3.x parsinggithub.com/modelcontextprotocol/go-sdk— MCP server (go-sdk v0.4.0)github.com/google/jsonschema-go— JSON Schema for tool inputs
- Install latest binary:
go install github.com/rendis/mcp-openapi-proxy/cmd/mcp-openapi-proxy@latest go build -C . -o bin/mcp-openapi-proxy ./cmd/mcp-openapi-proxy- Config is 100% env vars:
MCP_SPEC, optionalMCP_BASE_URL,MCP_TOOL_PREFIX,MCP_AUTH_PROFILE,MCP_AUTH_TOKEN,MCP_OIDC_ISSUER,MCP_OIDC_CLIENT_ID,MCP_OIDC_SCOPES,MCP_EXTRA_HEADERS,MCP_MAX_BODY_BYTES,MCP_ALLOW_INSECURE_HTTP,MCP_EXCLUDE_DEPRECATED, plusMCP_AUTH_<SCHEME>_* - Claude Code uses
.mcp.json; Codex global install usescodex mcp add <name> ... -- mcp-openapi-proxy; Codex project-local config is manual in./.codex/config.toml - Static token path: put
MCP_AUTH_TOKENin the MCP client config entry - OIDC login examples:
mcp-openapi-proxy loginmcp-openapi-proxy login my-apimcp-openapi-proxy login --mcp-config ./path/to/.mcp.jsonmcp-openapi-proxy login --mcp-config ./path/to/.mcp.json --server my-apimcp-openapi-proxy login --codex-server my-apimcp-openapi-proxy login --codex-config ~/.codex/config.tomlmcp-openapi-proxy login --codex-config ~/.codex/config.toml --server my-api
- Tests:
go test ./...— run before committing - Registered MCP tools:
{prefix}_list_endpoints,{prefix}_describe_endpoint,{prefix}_call_endpoint - Endpoint IDs:
{prefix}_{method}_{sanitized_path}(lowercase, special chars →_, collapsed) - Auth resolution priority: per-scheme
MCP_AUTH_<SCHEME>_*> globalMCP_AUTH_TOKEN> OIDC token cache forMCP_AUTH_PROFILE loginsupports env-only mode,login <mcp_name>using./.mcp.json,login --mcp-config <path>,login --mcp-config <path> --server <mcp_name>,login --codex-config <path>,login --codex-config <path> --server <name>, andlogin --codex-server <name>- Plain
loginis env-first, then falls back to./.mcp.json, then~/.codex/config.toml(or$CODEX_HOME/config.toml) when shell env is insufficient - For config-aware login, precedence is shell env > selected config entry env (
mcpServers.<name>.envormcp_servers.<name>.env) > existing defaults - If
loginomits the server name and the selected config contains multiple eligible entries, it lists the availablemcp-openapi-proxyservers and prompts you to choose one on interactive stdin .mcp.jsonand Codex TOML login discovery only consider directcommandvalues whose normalized basename ismcp-openapi-proxy(including full paths and.exe); wrappers likego,env,docker, or shell scripts are intentionally ignored- Codex global install is documented via
codex mcp add <name> ... -- mcp-openapi-proxy; Codex project-local config is manual in./.codex/config.toml - For this stdio server, use
mcp-openapi-proxy loginfor API auth;codex mcp loginis not the correct flow - Tokens stored at
~/.mcp-openapi-proxy/{profile}-tokens.jsonwith 0600 perms list_endpointsreturns lightweight discovery items withtoolName,method,path,description,requiredAuth,tags,deprecateddescribe_endpointreturns the full normalized OpenAPI contract for one endpointcall_endpointinput usestoolNamepluspath,query,headers,cookies,bodycall_endpointoutput is always an envelope:{status, content_type, headers, body}and marks API4xx/5xxasIsError=true- Deprecated endpoints are registered by default and skipped only when
MCP_EXCLUDE_DEPRECATED=1 client.Do()returns*client.Responsewith StatusCode, Headers, ContentType, RawContentType, Body- stdio transport only
go-sdkAPI may change — check import paths if build failsjsonschema-gousesjson.RawMessagefor Default field- kin-openapi
SchemaRef.Value.Typereturns*openapi3.Types(slice), not a string — use.Slice() - Version hardcoded as
0.1.0inserver.go swag initgenerates Swagger 2.0 output; convertswagger.jsonwithswagger2openapibeforeLoadSpec/MCP_SPECbecause this repo only supports OpenAPI 3.x at runtime- Authenticated requests to non-loopback
http://URLs are blocked unlessMCP_ALLOW_INSECURE_HTTP=1 - The registered MCP tools intentionally omit
OutputSchemato keeptools/listsmall; detailed endpoint contracts come fromdescribe_endpoint multipart/form-data,application/x-www-form-urlencoded, text bodies, andapplication/octet-streamare supported- Path/query/header/cookie serialization follows OpenAPI
style/explode; path params are URL-encoded - Non-JSON API responses are returned as raw text strings; binary responses are wrapped as base64 objects
- Trailing slash on
MCP_BASE_URLis stripped automatically .mcp.json/ Codex config lookup and interactive server selection are implemented only forlogin;serve,logout, andstatusstill read process env only- OIDC token refresh uses detached context (context.Background)
- Token file writes are atomic (tmp + rename)