Skip to content

Environment variables

polar-flow-mcp is configured entirely through environment variables (loaded from .env at startup via godotenv). The server is fail-closed: missing required variables cause it to refuse to start with a descriptive error.

VariableDescription
POLAR_EMAILEmail of the Polar Flow account this server will act as.
POLAR_PASSWORDPassword for that account. Held in memory only — never written to disk.
VariableDefaultDescription
TRANSPORThttphttp (streamable HTTP at /mcp) or stdio (MCP over stdin/stdout).
COOKIE_JAR_PATH./polar-cookies.jsonPath to the chmod-600 JSON file holding FLOW_SESSION + remember-me. Use an absolute path in production.
BIND_ADDRESS127.0.0.1TCP address the HTTP server binds to. Anything other than localhost emits a warning at startup.
PORT8080TCP port for the HTTP server.
LOG_LEVELinfoinfo or debug.
LOG_FILE(empty — stderr)If set, slog output is appended to this file (chmod 0600). Useful when stderr is unavailable, e.g. when running under Claude Code’s stdio transport.

Setting MCP_API_KEY requires every /mcp request to carry that exact key as Authorization: Bearer <key>. It is the lightweight alternative to inbound OAuth: no issuer, no signing key, no forward-auth proxy, no browser round-trip — one secret on the server, the same secret in the client. The comparison is constant-time, and the key is never logged or echoed in a response.

MCP_API_KEY and OAUTH_PUBLIC_URL are mutually exclusive — the server refuses to start with both set. Pick the one that fits the deployment.

VariableDefaultDescription
MCP_API_KEY(unset → auth off)Fixed pre-shared secret required as a Bearer token on /mcp. Minimum 24 characters; generate one with openssl rand -base64 32.

Claude Code, for example, connects with:

Terminal window
claude mcp add --transport http polar-flow https://polar.example.com/mcp \
--header "Authorization: Bearer $MCP_API_KEY"

Inbound OAuth (app-as-Authorization-Server + DCR)

Section titled “Inbound OAuth (app-as-Authorization-Server + DCR)”

Setting OAUTH_PUBLIC_URL turns the server into its own OAuth 2.1 Authorization Server. Clients self-register via Dynamic Client Registration (RFC 7591) — nothing to pre-create — and every /mcp request must carry a valid Authorization: Bearer access token the server itself signed (EdDSA JWT, validated locally). Browser login on /mcp/oauth/authorize is delegated to a forward-auth proxy. When neither OAUTH_PUBLIC_URL nor MCP_API_KEY is set, /mcp is unauthenticated (the historical behaviour). See Expose the server securely for the full Caddy + Authelia + Claude.ai walkthrough.

VariableDefaultDescription
OAUTH_PUBLIC_URL(unset → auth off)Public origin and OAuth issuer, e.g. https://polar.example.com. The MCP resource (token audience) is this URL + /mcp. Setting this enables inbound OAuth and must match the host Claude connects to.
OAUTH_ALLOWED_EMAIL(required if auth on)Comma-separated allowlist of forward-auth identities permitted to consent. Matching is case-insensitive. This is the “lock to me” control.
OAUTH_TRUSTED_PROXIES(required if auth on)Comma-separated CIDRs/IPs whose forward-auth identity header is trusted on /authorize. An identity header from any other peer is ignored, so this is what stops header spoofing. Scope it to your proxy/container network.
VariableDefaultDescription
OAUTH_ALLOWED_GROUPS(unset)Comma-separated group allowlist. When set, the forward-auth groups header must also intersect this set to consent.
OAUTH_ALLOWED_ORIGINS(unset)Comma-separated Origin allowlist on /mcp (DNS-rebinding defence). Enforced only when set; requests with no Origin (Claude’s server-to-server calls) are always allowed.
OAUTH_FORWARD_AUTH_EMAIL_HEADERRemote-EmailForward-auth header carrying the authenticated email (Authelia default).
OAUTH_FORWARD_AUTH_GROUPS_HEADERRemote-GroupsForward-auth header carrying the user’s groups.
OAUTH_EXTRA_REDIRECT_URIS(unset)Comma-separated extra exact redirect URIs accepted at registration, beyond the built-in Claude callbacks and loopback. Normally empty.
OAUTH_SIGNING_KEY_PATH./polar-oauth-key.jsonchmod-600 JSON file holding the EdDSA signing key. Created on first start; persist it (e.g. on a named volume) so issued tokens survive restarts.
OAUTH_ACCESS_TTL_MINUTES60Access-token lifetime in minutes.
OAUTH_REFRESH_TTL_HOURS720Refresh-token lifetime in hours (default 30 days).

The following env vars existed before the migration to the Polar Flow web API. They are now ignored — you can delete them from .env:

POLAR_CLIENT_ID, POLAR_CLIENT_SECRET, POLAR_REDIRECT_URL, ENCRYPTION_KEY, ENCRYPTION_KEY_FILE, KEY_PROVIDER, DATABASE_PATH, AUTH_PROXY, PROXY_SHARED_SECRET, IDENTITY_HEADER, DEV_MODE, DEV_USER_ID.

The OAuth flow, SQLite store, encryption layer, and reverse-proxy auth contract no longer exist. See the security model for the current design.