Skip to content

Authentication

Configure API key, bearer, basic and OAuth2 client-credentials auth for generated MCP servers using environment variables and wrangler secrets.

By Updated

The generated server authenticates to your upstream API using the security schemes declared in your OpenAPI spec. Credentials are read at runtime, never baked into the generated source.

Supported schemes#

Auth type Environment variables
API key API_KEY_<SCHEME_NAME>
Bearer BEARER_TOKEN_<SCHEME_NAME>
Basic BASIC_USERNAME_<SCHEME_NAME>, BASIC_PASSWORD_<SCHEME_NAME>
OAuth2, any flow OAUTH_TOKEN_<SCHEME_NAME>, a token you already obtained
OAuth2 client credentials OAUTH_CLIENT_ID_<SCHEME_NAME>, OAUTH_CLIENT_SECRET_<SCHEME_NAME> and optional OAUTH_SCOPES_<SCHEME_NAME>. The server fetches the token and caches it until shortly before it expires.
OpenID Connect OPENID_TOKEN_<SCHEME_NAME>

Authorization code, implicit and password flows need OAUTH_TOKEN_<SCHEME_NAME>. The server only fetches tokens itself with the client credentials grant.

Each variable is the prefix plus the security scheme name from your spec's components.securitySchemes, upper-cased, with every character that is not a letter or digit replaced by _. For example, a scheme called petstore-auth uses API_KEY_PETSTORE_AUTH. The generated .env.example lists the exact names for your spec.

Details:

  • API keys can be sent in a header, query parameter or cookie, as the spec declares.
  • HTTP basic works with an empty password. Only a username is required.
  • HTTP scheme names are matched case-insensitively, so Basic and Bearer work.
  • OAuth2 client credentials are sent in a Basic Authorization header by default. Use --oauth-creds-in-body to send them in the token request body instead. Tokens are requested with the operation's scopes unless OAUTH_SCOPES_<SCHEME_NAME> overrides them.

Missing credentials fail closed#

An operation's security list holds alternatives: the first requirement whose schemes are all configured is used, and every scheme inside one requirement is applied together. A header forwarded with --header-passthrough counts as configured.

If no requirement can be satisfied and the operation does not allow anonymous access with an empty {} requirement, the tool does not call your API. It returns an error naming what to set, for example:

text
Missing credentials for 'getPet': set API_KEY_PETSTORE_AUTH.

Set MCP_ALLOW_MISSING_CREDENTIALS=true (a vars entry for Workers) to send such requests without credentials instead.

Local servers: .env#

Node-based transports (stdio, web, streamable-http) read credentials from the environment. The generated project includes .env.example:

bash
cp .env.example .env
dotenv
API_KEY_PETSTORE_AUTH=your-key-here
# API_BASE_URL=https://staging.example.com

API_BASE_URL overrides the server URL from your spec, so leave it unset unless you need another environment. The .env.example generated by 5.0.0 sets it to the placeholder your_api_base_url_here; delete or comment out that line after copying. The next release ships it commented out.

Keep .env out of version control.

Cloudflare Workers: wrangler secrets#

For --transport=cloudflare-worker, secrets are set with Wrangler and read from the Worker's env binding. They are never committed:

bash
npx wrangler secret put <SCHEME>_API_KEY

Worker secret names put the scheme name first (upper-cased, with every character that is not a letter or digit replaced by _):

Auth type Wrangler secrets
API key <SCHEME>_API_KEY
Bearer and other HTTP schemes <SCHEME>_TOKEN
Basic <SCHEME>_USERNAME, <SCHEME>_PASSWORD
OAuth2 client credentials <SCHEME>_CLIENT_ID, <SCHEME>_CLIENT_SECRET, plus <SCHEME>_TOKEN_URL when the spec has no token URL

Generic fallbacks are also read: API_KEY, API_TOKEN, API_USERNAME, API_PASSWORD, OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET and OAUTH_TOKEN_URL. The generated .dev.vars.example lists the exact names for your spec.

OpenID Connect schemes read <SCHEME>_TOKEN. Non-secret configuration such as API_BASE_URL lives under vars in wrangler.jsonc. For local development, copy .dev.vars.example to .dev.vars and fill in values. The generated .gitignore excludes .dev.vars.

Per-user credentials#

By default every caller of the MCP server shares the credentials you configure. For web, streamable-http and cloudflare-worker, --header-passthrough forwards selected inbound headers to the upstream API so each MCP client can send its own key and the server stores no shared secret:

bash
openapi-mcp-generator -i ./openapi.json -o ./my-mcp --transport=streamable-http --header-passthrough X-API-Key

A forwarded header satisfies the scheme whose credential travels in it; other schemes of the same requirement still come from server configuration. Authorization cannot be forwarded while --inbound-auth bearer is on, because that header carries the MCP token.

Protecting the MCP endpoint#

Callers of your MCP server authenticate separately, with --inbound-auth bearer and MCP_AUTH_TOKEN. See Security model.

Custom auth#

--custom-auth generates an editable src/auth.ts hook, applyCustomAuth, that runs before built-in auth. Return true to skip the built-in handling. This flag does not apply to the Cloudflare Worker target.