feat(mcp): add OAuth authentication#1870
Conversation
Add OAuth support for streamable HTTP/SSE MCP servers with loopback callback handling, external browser login, callback URL fallback, and renderer auth status refreshes. Also switch Codex OAuth to external browser callback flow and fix related MCP panel close controls.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (37)
✅ Files skipped from review due to trivial changes (17)
🚧 Files skipped from review as they are similar to previous changes (13)
📝 WalkthroughWalkthroughThis PR adds MCP and OpenAI Codex OAuth loopback auth flows, renderer auth state and UI wiring, a shared sheet close-button no-drag fix, and documentation updates for MCP behavior changes. ChangesMCP and Codex OAuth Loopback Authentication
Sheet Close Button Drag Region Fix
MCP Behavior Documentation
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant McpServerCard
participant McpServers
participant mcpStore
participant McpClient
McpServerCard->>McpServers: authenticate
McpServers->>mcpStore: startServerAuth(serverName)
mcpStore->>McpClient: startServerAuth(serverName)
McpClient-->>mcpStore: McpServerAuthStatus
McpServers->>mcpStore: completeServerAuthFromCallbackUrl(serverName, url)
mcpStore->>McpClient: completeServerAuthFromCallbackUrl(...)
McpClient-->>mcpStore: authenticated status
sequenceDiagram
participant OpenAICodexOAuth
participant OpenAICodexAuth
participant Browser
OpenAICodexOAuth->>OpenAICodexAuth: startBrowserLogin()
OpenAICodexAuth->>Browser: shell.openExternal(authUrl)
Browser-->>OpenAICodexOAuth: callback URL
OpenAICodexOAuth->>OpenAICodexAuth: completeBrowserLoginFromCallbackUrl(url)
OpenAICodexAuth-->>OpenAICodexOAuth: OpenAICodexAuthStatus
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 20
🧹 Nitpick comments (5)
test/renderer/components/SheetContentDrag.test.ts (1)
4-11: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAssert the rendered close button, not the source file.
This source-text check is brittle: it can pass even if the effective DOM no longer carries the no-drag style after wrapper/template changes. A mount-based assertion would verify the Electron behavior directly.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/renderer/components/SheetContentDrag.test.ts` around lines 4 - 11, The current SheetContent drag-region test is asserting against the source text from SheetContent.vue instead of the rendered close button, which makes it brittle. Update the SheetContent drag test in SheetContent drag region to mount the component and inspect the actual DialogClose element in the rendered DOM, then assert that the close button carries the no-drag class/style (such as window-no-drag-region and -webkit-app-region: no-drag) directly on the rendered output.src/shared/contracts/events/mcp.events.ts (1)
4-4: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winReuse the strict
McpServerAuthStatusSchemainstead of a no-opz.custom().
z.object(...)-basedMcpServerAuthStatusSchemaalready exists insrc/shared/contracts/routes/mcp.routes.tswith real field/enum validation. This file redefines a same-named schema usingz.custom<McpServerAuthStatus>(), which performs no runtime validation (any value type-checks). That means this event payload'sstatusfield bypasses shape validation that the route contracts enforce for the identical type, and the duplicate name across two files is confusing.♻️ Proposed fix to reuse the strict schema
-import type { - McpServerAuthStatus, +import { McpServerAuthStatusSchema } from './routes/mcp.routes' +import type { ... } from '`@shared/presenter`' -const McpServerAuthStatusSchema = z.custom<McpServerAuthStatus>()(adjust the relative import path to match this file's actual location under
src/shared/contracts/events/)Also applies to: 13-13, 49-57
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/shared/contracts/events/mcp.events.ts` at line 4, The event contract is redefining McpServerAuthStatusSchema with z.custom<McpServerAuthStatus>(), which skips runtime validation and duplicates the same schema name already defined in the MCP route contracts. Update the schema definition in McpServerAuthStatusSchema to reuse the strict z.object-based schema from the routes module instead of the no-op custom validator, and adjust the related McpServerAuthStatus imports/usages in this events contract so the status field is validated consistently everywhere.src/shared/contracts/routes/oauth.routes.ts (1)
56-63: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winConsider validating
callbackUrlas a URL.
callbackUrl: z.string()accepts any string, including non-URL garbage from a manual paste. Zod v4 provides a top-levelz.url()format validator that would reject malformed input at the contract boundary rather than relying on downstream parsing to fail gracefully.♻️ Suggested tightening
export const oauthOpenAICodexCompleteBrowserLoginFromUrlRoute = defineRouteContract({ name: 'oauth.openaiCodex.completeBrowserLoginFromUrl', input: z.object({ - callbackUrl: z.string() + callbackUrl: z.url() }), output: OpenAICodexStatusResultSchema })🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/shared/contracts/routes/oauth.routes.ts` around lines 56 - 63, The oauth.openaiCodex.completeBrowserLoginFromUrl contract currently accepts any string for callbackUrl, so tighten the input validation at the route boundary. Update oauthOpenAICodexCompleteBrowserLoginFromUrlRoute in oauth.routes.ts to use Zod’s URL validator for callbackUrl instead of a plain string, keeping the rest of the contract unchanged.test/main/presenter/mcpPresenter/mcpOAuthManager.test.ts (1)
1-49: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy liftLGTM! Correctly exercises the credential-precedence path in
completeAuthFromCallbackUrl/getStatus.Given the issues flagged in
mcpOAuthManager.ts(missing stale-flow guard infinishAuthenticatedFlow, and theisOAuthErrorfield-check gap), consider adding regression tests for those once fixed — e.g., simulating a secondstartAuthcall completing before a stale first flow resolves.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/main/presenter/mcpPresenter/mcpOAuthManager.test.ts` around lines 1 - 49, Add regression coverage for the stale OAuth flow cases in McpOAuthManager: the current test only verifies credential precedence in completeAuthFromCallbackUrl/getStatus, but the review points to missing protection in finishAuthenticatedFlow and a gap in isOAuthError field detection. Add tests that simulate overlapping startAuth flows where an older flow resolves after a newer one, and verify the stale completion is ignored while the active flow still succeeds; also add a test that exercises isOAuthError with partial error objects to confirm the field check works as intended.src/renderer/src/i18n/ja-JP/settings.json (1)
1134-1138: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueNew OpenAI Codex/MCP auth strings left untranslated (English) in the Japanese locale file.
Keys like
openaiCodexPasteCallback,authRequired,authCallbackDescription, etc. are inserted verbatim in English rather than translated to Japanese, unlike the rest of the file's localized content.Also applies to: 1457-1465
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/renderer/src/i18n/ja-JP/settings.json` around lines 1134 - 1138, The Japanese locale file still contains several new OpenAI Codex/MCP auth strings in English, so translate those newly added keys to match the rest of the locale. Update the entries around the OpenAI Codex callback/auth section, including keys like openaiCodexPasteCallback, openaiCodexCallbackTitle, openaiCodexCallbackDescription, openaiCodexCallbackPlaceholder, openaiCodexCompleteAuthentication, and the related authRequired/authCallbackDescription strings mentioned in the later block. Keep the translations consistent with existing Japanese terminology used elsewhere in the settings.json localization.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/main/presenter/mcpPresenter/mcpOAuthManager.ts`:
- Around line 64-77: The isOAuthError helper is only checking the .code field
even though it declares status and httpStatus, so 401-style HTTP client errors
can be missed. Update isOAuthError in mcpOAuthManager to inspect the actual HTTP
status from status, httpStatus, and any response.status shape before falling
back to message patterns, using the existing UnauthorizedError and
OAUTH_AUTH_ERROR_PATTERNS logic. This should ensure handleConnectionError gets a
correct OAuth classification for fetch/axios-style errors.
- Around line 292-322: finishAuthenticatedFlow should ignore stale/superseded
OAuth flows the same way failAuthFlow does. Add an identity check against
pendingFlows.get(flow.serverName) at the start of finishAuthenticatedFlow so
only the currently active PendingMcpOAuthFlow can delete the entry, close the
callback session, set authenticated status, and trigger onAuthenticated. Keep
the existing failAuthFlow guard pattern and make sure both finishAuthFlow and
the AUTHORIZED path end up using the guarded finishAuthenticatedFlow behavior.
- Around line 262-276: The not-found path in completeAuthFromCallbackUrl sets an
error status, but the pending flow remains active so getStatus() returns
authenticating instead of the newly set error state. Update the mcpOAuthManager
flow handling so the not-found branch either cancels/removes the pending flow
before returning or returns the just-set error status directly, and ensure the
getStatus(serverName, config) path in this method does not override the callback
failure state.
In `@src/main/presenter/mcpPresenter/mcpOAuthProvider.ts`:
- Around line 68-74: The redirectToAuthorization method in MCPOAuthProvider
opens the remote authorizationUrl directly, so add a scheme check before calling
shell.openExternal. Validate that authorizationUrl.protocol is only http: or
https: and reject anything else with an error before opening the browser; keep
the existing interactive guard intact and apply the check in
redirectToAuthorization where the URL is passed to shell.openExternal.
In `@src/main/presenter/mcpPresenter/oauthCredentialStore.ts`:
- Around line 55-102: `clearEntryScope` in `McpOAuthCredentialStore` is deleting
fields only on a local copy, but `saveEntry` merges that copy back with the
existing persisted entry and restores the old values. Update the scoped-clear
flow so the targeted property is actually removed from storage, either by
teaching `saveEntry` to respect explicit deletions or by having
`clearEntryScope` rewrite the entry directly before calling `saveAll`. Make sure
the behavior for `clientInformation`, `tokens`, `codeVerifier`, and
`discoveryState` matches the intended scope removal, while `clearEntry` and
`saveEntry` still work for normal updates.
In `@src/renderer/settings/components/OpenAICodexOAuth.vue`:
- Around line 104-140: The Enter key handler on the callback Input can
re-trigger `completeBrowserLoginFromUrl` while the OAuth exchange is already
running, even though the submit Button is guarded by `busyAction ===
'callback'`. Update `OpenAICodexOAuth.vue` so the `@keydown.enter.prevent` path
uses the same in-flight guard as the Button, and make
`completeBrowserLoginFromUrl` itself no-op when `busyAction` indicates a
callback submission is already underway. Use the existing `busyAction`,
`callbackUrl`, and `completeBrowserLoginFromUrl` symbols to keep both submission
paths consistent and prevent duplicate `completeOpenAICodexBrowserLoginFromUrl`
calls.
In `@src/renderer/src/components/mcp-config/components/McpServerCard.vue`:
- Around line 110-121: The `getStatusInfo` mapping in `McpServerCard.vue` reuses
the wrong label for the `auth-error` case, so update that branch to use the
dedicated `settings.mcp.authFailed` i18n key instead of
`settings.mcp.authRequired`. Keep the existing `auth-required` case unchanged,
and make sure the `auth-error` status still returns its red styling while
showing the distinct failure text.
In `@src/renderer/src/components/mcp-config/components/McpServers.vue`:
- Around line 250-273: `submitAuthCallbackUrl` in `McpServers.vue` can be
re-entered while a request is already in flight, causing duplicate
`completeServerAuthFromCallbackUrl` calls for the same callback URL. Add an
early return guard at the start of `submitAuthCallbackUrl` using
`isSubmittingAuthCallback` so repeated Enter presses are ignored until the
current submission finishes. Keep the existing loading flag behavior intact in
the `try/finally` flow and preserve the current success/failure handling.
In `@src/renderer/src/i18n/da-DK/settings.json`:
- Around line 1067-1071: The new authentication copy in the Danish locale is
still in English, so translate the added OpenAI Codex callback/auth strings
before shipping. Update the entries around openaiCodexPasteCallback,
openaiCodexCallbackTitle, openaiCodexCallbackDescription,
openaiCodexCallbackPlaceholder, and openaiCodexCompleteAuthentication in the
da-DK settings JSON, and also translate the other added auth block referenced by
the review so the entire OAuth/MCP flow remains consistently Danish.
In `@src/renderer/src/i18n/de-DE/settings.json`:
- Around line 1391-1395: The new authentication strings in the locale entries
are still in English, so translate the added copy in the German settings and
related auth section before shipping. Update the newly added keys such as
openaiCodexPasteCallback, openaiCodexCallbackTitle,
openaiCodexCallbackDescription, openaiCodexCallbackPlaceholder, and
openaiCodexCompleteAuthentication, and also the matching block referenced by the
comment, keeping the wording consistent with the existing German translations in
this file.
In `@src/renderer/src/i18n/es-ES/settings.json`:
- Around line 1391-1395: The new auth-related strings in settings.json are still
in English, so update the Spanish locale copy for the affected keys before
shipping. Translate the added OpenAI Codex callback and
completion/authentication entries (for example openaiCodexPasteCallback,
openaiCodexCallbackTitle, openaiCodexCallbackDescription,
openaiCodexCallbackPlaceholder, openaiCodexCompleteAuthentication, and the other
added auth block around the later matching keys) to natural es-ES text, keeping
terminology consistent with the rest of the file.
In `@src/renderer/src/i18n/fa-IR/settings.json`:
- Around line 1134-1138: The new openaiCodex* and mcp.* entries in the fa-IR
locale are still in English, so translate these added auth/setup strings into
Persian to keep the DeepChat dialogs fully localized. Update the relevant keys
in settings.json, including the
openaiCodexCallback*/openaiCodexCompleteAuthentication group and the mcp.*
strings mentioned in the review, while preserving the existing key names and
JSON structure.
In `@src/renderer/src/i18n/fr-FR/settings.json`:
- Around line 1134-1138: The new authentication and MCP copy is still in English
in the fr-FR locale, so localize the added openaiCodex* and mcp.* entries in
settings.json before merging. Update the French translations for the new strings
near openaiCodexCallbackTitle/openaiCodexCompleteAuthentication and the related
mcp section so the auth/setup dialogs remain fully consistent in French.
In `@src/renderer/src/i18n/he-IL/settings.json`:
- Around line 1134-1138: The new authentication strings are still in English in
the he-IL locale, causing mixed-language UI. Localize the added openaiCodex*
entries and the related mcp.* strings in settings.json to Hebrew, keeping the
existing key names intact and matching the style used by other translations in
this file.
In `@src/renderer/src/i18n/id-ID/settings.json`:
- Around line 1391-1395: The new authentication strings are still in English in
the id-ID locale, so localize the added openaiCodex* and mcp.* entries in the
settings JSON before merging. Update the affected copy in the translation file
so the OAuth/authentication UI shows Indonesian text consistently, and use the
existing surrounding keys in settings.json as the reference point for all new
labels, descriptions, and placeholders.
In `@src/renderer/src/i18n/it-IT/settings.json`:
- Around line 1391-1395: The new auth-related entries in the it-IT locale are
still in English, so localize the added openaiCodex* and mcp.* strings in
settings.json to Italian. Update the translated copy for the
callback/authentication dialogs in the same locale block, keeping the existing
key names like openaiCodexPasteCallback, openaiCodexCallbackTitle, and the mcp.*
entries consistent with the rest of the file.
In `@src/renderer/src/i18n/tr-TR/settings.json`:
- Around line 1391-1395: The new authentication strings in the Turkish locale
are still in English, so translate the added OAuth/MCP copy before shipping.
Update the new entries in settings.json for the openaiCodex* keys, and also the
additional block referenced in the same locale file, so all auth-related text is
fully localized and consistent for Turkish users.
In `@src/renderer/src/i18n/vi-VN/settings.json`:
- Around line 1391-1395: The new authentication strings are still in English in
the vi-VN locale, so translate the added copy before shipping. Update the values
for the openaiCodex* keys in settings.json and the other newly added auth block
referenced by the same locale so Vietnamese users see a fully localized
OAuth/MCP flow. Keep the existing key names unchanged and replace only the
displayed text with Vietnamese translations.
In `@src/renderer/src/i18n/zh-HK/settings.json`:
- Around line 1133-1138: The newly added zh-HK strings are using Simplified
Chinese instead of Traditional Chinese, so retranslate all affected entries in
settings.json to match the rest of the locale. Update the new keys around the
OpenAI Codex/auth flow, including openaiCodexPasteCallback,
openaiCodexCallbackTitle, openaiCodexCallbackDescription,
openaiCodexCallbackPlaceholder, openaiCodexCompleteAuthentication, authRequired,
authenticate, authFailed, authCallbackTitle, authCallbackDescription,
authCallbackPlaceholder, completeAuthentication, saveSuccess, and saveFailed,
keeping terminology consistent with existing Traditional Chinese text such as
openaiCodexLoginTip.
In `@src/renderer/src/i18n/zh-TW/settings.json`:
- Around line 1133-1138: The newly added locale strings in zh-TW/settings.json
are using Simplified Chinese instead of Traditional Chinese, so update the
affected translation keys to zh-TW wording for consistency with the rest of the
file. Fix the values for the new auth/callback-related entries such as
openaiCodexPasteCallback, openaiCodexCallbackTitle,
openaiCodexCallbackDescription, openaiCodexCallbackPlaceholder,
openaiCodexCompleteAuthentication, authRequired, authenticate, authFailed,
authCallbackTitle, authCallbackDescription, authCallbackPlaceholder,
completeAuthentication, saveSuccess, and saveFailed, and verify the same set in
the later matching block referenced by the diff.
---
Nitpick comments:
In `@src/renderer/src/i18n/ja-JP/settings.json`:
- Around line 1134-1138: The Japanese locale file still contains several new
OpenAI Codex/MCP auth strings in English, so translate those newly added keys to
match the rest of the locale. Update the entries around the OpenAI Codex
callback/auth section, including keys like openaiCodexPasteCallback,
openaiCodexCallbackTitle, openaiCodexCallbackDescription,
openaiCodexCallbackPlaceholder, openaiCodexCompleteAuthentication, and the
related authRequired/authCallbackDescription strings mentioned in the later
block. Keep the translations consistent with existing Japanese terminology used
elsewhere in the settings.json localization.
In `@src/shared/contracts/events/mcp.events.ts`:
- Line 4: The event contract is redefining McpServerAuthStatusSchema with
z.custom<McpServerAuthStatus>(), which skips runtime validation and duplicates
the same schema name already defined in the MCP route contracts. Update the
schema definition in McpServerAuthStatusSchema to reuse the strict
z.object-based schema from the routes module instead of the no-op custom
validator, and adjust the related McpServerAuthStatus imports/usages in this
events contract so the status field is validated consistently everywhere.
In `@src/shared/contracts/routes/oauth.routes.ts`:
- Around line 56-63: The oauth.openaiCodex.completeBrowserLoginFromUrl contract
currently accepts any string for callbackUrl, so tighten the input validation at
the route boundary. Update oauthOpenAICodexCompleteBrowserLoginFromUrlRoute in
oauth.routes.ts to use Zod’s URL validator for callbackUrl instead of a plain
string, keeping the rest of the contract unchanged.
In `@test/main/presenter/mcpPresenter/mcpOAuthManager.test.ts`:
- Around line 1-49: Add regression coverage for the stale OAuth flow cases in
McpOAuthManager: the current test only verifies credential precedence in
completeAuthFromCallbackUrl/getStatus, but the review points to missing
protection in finishAuthenticatedFlow and a gap in isOAuthError field detection.
Add tests that simulate overlapping startAuth flows where an older flow resolves
after a newer one, and verify the stale completion is ignored while the active
flow still succeeds; also add a test that exercises isOAuthError with partial
error objects to confirm the field check works as intended.
In `@test/renderer/components/SheetContentDrag.test.ts`:
- Around line 4-11: The current SheetContent drag-region test is asserting
against the source text from SheetContent.vue instead of the rendered close
button, which makes it brittle. Update the SheetContent drag test in
SheetContent drag region to mount the component and inspect the actual
DialogClose element in the rendered DOM, then assert that the close button
carries the no-drag class/style (such as window-no-drag-region and
-webkit-app-region: no-drag) directly on the rendered output.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 128639e9-7231-479a-898d-a7cc44c48582
📒 Files selected for processing (62)
docs/features/mcp-oauth-authentication/plan.mddocs/features/mcp-oauth-authentication/spec.mddocs/features/mcp-oauth-authentication/tasks.mddocs/issues/mcp-oauth-callback-refresh/plan.mddocs/issues/mcp-oauth-callback-refresh/spec.mddocs/issues/mcp-oauth-callback-refresh/tasks.mddocs/issues/mcp-save-toast-i18n/plan.mddocs/issues/mcp-save-toast-i18n/spec.mddocs/issues/mcp-save-toast-i18n/tasks.mddocs/issues/sheet-close-no-drag/plan.mddocs/issues/sheet-close-no-drag/spec.mddocs/issues/sheet-close-no-drag/tasks.mdsrc/main/presenter/mcpPresenter/index.tssrc/main/presenter/mcpPresenter/mcpClient.tssrc/main/presenter/mcpPresenter/mcpOAuthManager.tssrc/main/presenter/mcpPresenter/mcpOAuthProvider.tssrc/main/presenter/mcpPresenter/oauthConstants.tssrc/main/presenter/mcpPresenter/oauthCredentialStore.tssrc/main/presenter/mcpPresenter/serverManager.tssrc/main/presenter/oauthLoopbackCallback.tssrc/main/presenter/oauthPresenter.tssrc/main/presenter/openaiCodexAuth/index.tssrc/main/routes/index.tssrc/renderer/api/McpClient.tssrc/renderer/api/OAuthClient.tssrc/renderer/settings/components/OpenAICodexOAuth.vuesrc/renderer/src/components/mcp-config/components/McpServerCard.vuesrc/renderer/src/components/mcp-config/components/McpServers.vuesrc/renderer/src/i18n/da-DK/settings.jsonsrc/renderer/src/i18n/de-DE/settings.jsonsrc/renderer/src/i18n/en-US/settings.jsonsrc/renderer/src/i18n/es-ES/settings.jsonsrc/renderer/src/i18n/fa-IR/settings.jsonsrc/renderer/src/i18n/fr-FR/settings.jsonsrc/renderer/src/i18n/he-IL/settings.jsonsrc/renderer/src/i18n/id-ID/settings.jsonsrc/renderer/src/i18n/it-IT/settings.jsonsrc/renderer/src/i18n/ja-JP/settings.jsonsrc/renderer/src/i18n/ko-KR/settings.jsonsrc/renderer/src/i18n/ms-MY/settings.jsonsrc/renderer/src/i18n/pl-PL/settings.jsonsrc/renderer/src/i18n/pt-BR/settings.jsonsrc/renderer/src/i18n/ru-RU/settings.jsonsrc/renderer/src/i18n/tr-TR/settings.jsonsrc/renderer/src/i18n/vi-VN/settings.jsonsrc/renderer/src/i18n/zh-CN/settings.jsonsrc/renderer/src/i18n/zh-HK/settings.jsonsrc/renderer/src/i18n/zh-TW/settings.jsonsrc/renderer/src/pages/plugins/McpPluginsPage.vuesrc/renderer/src/stores/mcp.tssrc/shadcn/components/ui/sheet/SheetContent.vuesrc/shared/contracts/events.tssrc/shared/contracts/events/mcp.events.tssrc/shared/contracts/routes.tssrc/shared/contracts/routes/mcp.routes.tssrc/shared/contracts/routes/oauth.routes.tssrc/shared/types/presenters/core.presenter.d.tstest/main/presenter/mcpPresenter/mcpOAuthManager.test.tstest/main/presenter/openaiCodexAuth.test.tstest/renderer/components/McpServers.test.tstest/renderer/components/SheetContentDrag.test.tstest/renderer/stores/mcpStore.test.ts
Summary
Tests
Note: lint/typecheck print the existing local engine warning because this machine is on Node v24.14.0 while package.json wants >=24.14.1 <25.
Summary by CodeRabbit