mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-08-06 19:35:31 +00:00
* feat(mcp): add Streamable HTTP transport with OAuth 2.0 Odysseus could only reach MCP servers over stdio and SSE, so modern remote servers like https://mcp.higgsfield.ai/mcp (Streamable HTTP, gated behind OAuth) could not be connected. Add an `http` transport that connects via the SDK's streamablehttp_client and authenticates with the SDK's OAuthClientProvider: RFC 9728 protected-resource discovery, RFC 8414 authorization-server metadata, Dynamic Client Registration, authorization-code + PKCE, and token refresh. A small bridge (src/mcp_oauth.py) connects the SDK's blocking callback to the existing web callback route via an asyncio.Future keyed by the OAuth `state`, and the dynamic client registration plus tokens persist per-server in a new encrypted `oauth_tokens` column. The connect runs as a bounded background task so the "Add server" request returns immediately; redirect_handler publishes needs_auth + auth_url to connection state as soon as discovery/DCR completes (which can exceed the bounded wait), and the UI polls until connected. Remote users finish via the existing paste-back flow. The Google OAuth path is left unchanged. - core/database.py: encrypted oauth_tokens column + migration - src/mcp_oauth.py: OAuth provider, DB-backed TokenStorage, state registry - src/mcp_manager.py: http dispatch, background connect, _connect_http - routes/mcp_routes.py: http validation, needs_auth/auth_url, callback bridge - static/js/settings.js: Streamable HTTP option + OAuth flow with polling - tests: 5 new unit tests (transport dispatch, registry, token storage) Verified against the live Higgsfield server: discovery, DCR (client_id issued), loopback redirect accepted, and a PKCE authorization URL with needs_auth status. No regressions (full suite delta is only the 5 added passing tests). * fix(mcp): address PR #1033 review feedback - mcp_oauth: derive redirect URI from OAUTH_REDIRECT_BASE_URL/APP_PUBLIC_URL (default http://localhost:7000) instead of hardcoding the port - mcp_oauth: leave OAuth scope unset so the SDK derives it from the server's WWW-Authenticate/protected-resource metadata; hardcoding an OIDC scope broke non-OpenID MCP servers (verified: Higgsfield still gets its server-derived scope) - mcp_oauth: prune abandoned OAuth flows (_prune_stale + _pending_ts) so the module-level registries can't grow unbounded - mcp_oauth: persist tokens/client-info in a single DB session/commit (_update) instead of a load+save double round-trip - mcp_manager: cancel and drop the background connect task in disconnect_server so a deleted server stops publishing status - database: document why the oauth_tokens migration uses TEXT while the model declares EncryptedText (encryption is applied at the Python layer) - settings.js: surface persistent OAuth-poll failures and an explicit timeout message instead of silently swallowing errors - tests: cover the stale-flow pruning * static/js/settings.js now shows an in-flight loading state on the buttons that fire requests: |
||
|---|---|---|
| .. | ||
| calendar | ||
| color | ||
| compare | ||
| editor | ||
| emailLibrary | ||
| markdown | ||
| model | ||
| research | ||
| util | ||
| a11y.js | ||
| admin.js | ||
| assistant.js | ||
| calendar.js | ||
| censor.js | ||
| chat.js | ||
| chatRenderer.js | ||
| chatStream.js | ||
| codeRunner.js | ||
| colorPicker.js | ||
| cookbook-diagnosis.js | ||
| cookbook-hwfit.js | ||
| cookbook.js | ||
| cookbookDownload.js | ||
| cookbookProgressSignal.js | ||
| cookbookRunning.js | ||
| cookbookServe.js | ||
| document.js | ||
| documentLibrary.js | ||
| dragSort.js | ||
| emailInbox.js | ||
| emailLibrary.js | ||
| emojiPicker.js | ||
| emojiShortcodes.js | ||
| escMenuStack.js | ||
| fileHandler.js | ||
| gallery.js | ||
| galleryEditor.js | ||
| group.js | ||
| init.js | ||
| keyboard-shortcuts.js | ||
| langIcons.js | ||
| markdown.js | ||
| memory.js | ||
| modalManager.js | ||
| modalSnap.js | ||
| modelPicker.js | ||
| models.js | ||
| modelSort.js | ||
| MODULE_SUMMARY.md | ||
| notes.js | ||
| package.json | ||
| platform.js | ||
| presets.js | ||
| providers.js | ||
| rag.js | ||
| researchSynapse.js | ||
| search-chat.js | ||
| search.js | ||
| section-management.js | ||
| sessions.js | ||
| settings.js | ||
| sidebar-layout.js | ||
| signature.js | ||
| skills.js | ||
| slashAutocomplete.js | ||
| slashCommands.js | ||
| spinner.js | ||
| storage.js | ||
| tasks.js | ||
| theme.js | ||
| tileManager.js | ||
| tourAutoplay.js | ||
| tourHints.js | ||
| tts-ai.js | ||
| ui.js | ||
| voiceRecorder.js | ||
| windowDrag.js | ||
| windowResize.js | ||
| workspace.js | ||