Skip to content

HTTP mode requires PLANE_OAUTH_PROVIDER_* even for PAT-only deployments #131

Description

@realies

Summary

When running the server in HTTP transport mode (python -m plane_mcp http), startup unconditionally constructs the OAuth-provider MCP app via get_oauth_mcp(prefix + "/http") in plane_mcp/__main__.py. This forces PlaneOAuthProvider.__init__ to validate three OAuth-provider environment variables even when the operator only intends to expose the PAT/header-based transport that is mounted at /http/api-key/:

  • PLANE_OAUTH_PROVIDER_CLIENT_ID — raises ValueError if unset
  • PLANE_OAUTH_PROVIDER_CLIENT_SECRET — raises ValueError if unset
  • PLANE_OAUTH_PROVIDER_BASE_URL — the resulting issuer URL is validated against validate_issuer_url (from mcp/server/auth/routes.py) and must be https://, otherwise ValueError

For a self-hosted deployment that only needs the PAT-header transport (Section 3 in the README, /http/api-key/mcp), the OAuth provider is never actually exercised, yet the server cannot start without those three variables.

Reproduction

  1. Set only the PAT-related variables (e.g. PLANE_API_KEY, PLANE_WORKSPACE_SLUG, plus whatever else the header transport needs).
  2. Leave PLANE_OAUTH_PROVIDER_CLIENT_ID, PLANE_OAUTH_PROVIDER_CLIENT_SECRET, and PLANE_OAUTH_PROVIDER_BASE_URL unset (or set the base URL to a non-HTTPS value).
  3. Start the server: python -m plane_mcp http.
  4. Startup aborts before the header app is mounted.

Traceback summary:

File "plane_mcp/__main__.py", line ..., in main
    oauth_mcp = get_oauth_mcp(prefix + "/http")
File "plane_mcp/server.py", in get_oauth_mcp
    ...
File "plane_mcp/auth/plane_oauth_provider.py", in PlaneOAuthProvider.__init__
    raise ValueError("client_id is required - set via parameter or PLANE_OAUTH_PROVIDER_CLIENT_ID")

(If client_id/client_secret are stubbed, the next failure is validate_issuer_url rejecting a non-HTTPS PLANE_OAUTH_PROVIDER_BASE_URL.)

Current workaround

Stub all three variables with placeholder values, e.g.:

PLANE_OAUTH_PROVIDER_CLIENT_ID=stub-not-used
PLANE_OAUTH_PROVIDER_CLIENT_SECRET=stub-not-used
PLANE_OAUTH_PROVIDER_BASE_URL=https://example.invalid

This is non-obvious and undocumented; the operator has to read the source to figure it out.

Suggested fixes (options, not a prescription)

  1. Lazy-init the OAuth provider on first request rather than eagerly at startup, so a deployment that never routes to the OAuth mount never triggers the validation.
  2. Add an opt-out env var / flag (e.g. PLANE_DISABLE_OAUTH=1) that skips constructing and mounting the OAuth app entirely, leaving only the PAT-header transport.
  3. Document the stub-variable workaround in the README section that covers the PAT/header transport, so PAT-only operators at least know what to set.

Any one of these would unblock PAT-only self-hosted deployments. Happy to send a PR for whichever direction the maintainers prefer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions