-
Notifications
You must be signed in to change notification settings - Fork 0
Implement MCP Authentication #1
Description
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.pyomlx/mcp/client.pyomlx/mcp/manager.pyomlx/mcp/config.pymcp.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
-
Auth challenge detection
- Detect unauthorized responses from MCP HTTP transport.
- Parse auth challenge metadata where applicable.
-
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.
- Support at least one interactive flow suitable for desktop/local app usage:
-
Token management
- Persist
access_token,refresh_token,expires_atper MCP server. - Refresh expired tokens automatically before/after failed requests.
- Retry the original MCP request once after successful auth/refresh.
- Persist
-
Config extensions
- Extend MCP server config with optional
authblock (backward compatible), e.g.:auth.type(oauth2)client_idscopesaudience(optional)auth_url,token_url(optional override)token_storepath (optional override)
- Extend MCP server config with optional
-
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”.
- Add command to initiate login for a server (example:
-
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.
-
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.
- Unit tests for:
-
Docs
- Add setup docs for OAuth MCP servers (including Notion example).
- Update
mcp.example.jsonwith 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/logoutactions and vice versa
- UI auth state reflects
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