Skip to content

Implement MCP Authentication #1

@ChristianPraiss

Description

@ChristianPraiss

Title

Add OAuth 2.0 support for MCP streamable-http/sse servers (Notion MCP currently fails with 401)

Summary

omlx MCP client currently connects to configured servers but does not appear to implement OAuth negotiation for protected MCP endpoints. As a result, OAuth-protected servers (e.g. Notion MCP) return 401 Unauthorized, and no tools are discovered.

Example observed behavior:

  • HTTP Request: POST https://mcp.notion.com/mcp "HTTP/1.1 401 Unauthorized"
  • Manager logs:
    • Connected to 'notion'
    • MCP manager started: 0/1 servers, 0 tools available

Repository context (verified)

Relevant files:

  • omlx/mcp/types.py
  • omlx/mcp/client.py
  • omlx/mcp/manager.py
  • omlx/mcp/config.py
  • mcp.example.json

Current MCP config supports transport + optional static headers, but no full OAuth lifecycle is implemented (auth challenge handling, token acquisition, refresh, persistence, retry).

Problem

OAuth-protected MCP servers cannot be used unless users manually inject bearer tokens (if possible), and tokens cannot be refreshed automatically. This blocks common MCP deployments.

Proposal

Implement OAuth 2.0 support for MCP clients, including token lifecycle and retry on auth challenge.

Scope

  1. Auth challenge detection

    • Detect unauthorized responses from MCP HTTP transport.
    • Parse auth challenge metadata where applicable.
  2. OAuth flows

    • Support at least one interactive flow suitable for desktop/local app usage:
      • Authorization Code + PKCE (preferred), and/or
      • Device Authorization Grant (fallback).
    • Keep provider-agnostic design.
  3. Token management

    • Persist access_token, refresh_token, expires_at per MCP server.
    • Refresh expired tokens automatically before/after failed requests.
    • Retry the original MCP request once after successful auth/refresh.
  4. Config extensions

    • Extend MCP server config with optional auth block (backward compatible), e.g.:
      • auth.type (oauth2)
      • client_id
      • scopes
      • audience (optional)
      • auth_url, token_url (optional override)
      • token_store path (optional override)
  5. CLI / UX

    • Add command to initiate login for a server (example: omlx mcp login <server>).
    • Add command to clear auth (logout / token removal).
    • Improve logs to distinguish “transport connected” vs “authenticated tool discovery succeeded”.
  6. Security

    • Store tokens securely (prefer OS keychain; fallback encrypted/local file with strict perms if keychain unavailable).
    • Never log access/refresh tokens.
    • Validate redirect URI and state/PKCE verifier handling.
  7. Tests

    • Unit tests for:
      • config parsing
      • expired-token refresh path
      • 401 → auth → retry path
      • failed refresh path
    • Integration-style tests with mocked OAuth + MCP endpoints.
  8. Docs

    • Add setup docs for OAuth MCP servers (including Notion example).
    • Update mcp.example.json with OAuth sample.
    • Troubleshooting section for 401/403 and token refresh failures.

UI requirements

Add a dedicated MCP OAuth section in the oMLX UI (menu bar app/settings) for authentication management.

UI Scope

  • Show MCP server auth status per server:
    • Not authenticated
    • Authenticated
    • Token expired / refresh failed
  • Provide actions:
    • Login / Connect (start OAuth flow)
    • Re-authenticate
    • Logout / Disconnect (remove stored tokens)
  • Display basic account/session metadata where available:
    • Connected provider
    • Authenticated account/workspace (if returned by provider)
    • Last successful auth time
  • Provide clear error feedback and recovery:
    • 401/403 surfaced as actionable UI messages
    • Prompt to re-auth when refresh fails
  • Ensure sensitive data is never shown:
    • Do not display raw access/refresh tokens
  • Keep behavior consistent with CLI:
    • UI auth state reflects omlx mcp login/logout actions and vice versa

Acceptance Criteria

  • OAuth-protected MCP server can be configured without hardcoding bearer token.
  • First-time auth flow completes and tools are discoverable.
  • Expired token is refreshed automatically and requests recover without manual intervention.
  • On refresh failure, user gets actionable re-auth prompt.
  • Existing non-OAuth MCP configs continue to work unchanged.
  • UI includes an MCP OAuth management section with per-server auth status and login/logout actions.
  • CI tests cover the new auth paths.

Suggested implementation areas

  • omlx/mcp/types.py (config/auth schema)
  • omlx/mcp/config.py (validation/loading of auth config)
  • omlx/mcp/client.py (401 handling, auth orchestration, retry)
  • new module(s), e.g.:
    • omlx/mcp/oauth.py (flow + token exchange/refresh)
    • omlx/mcp/token_store.py (secure persistence)
  • UI/settings module(s) for MCP auth management in the menu bar app

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions