Skip to content

Conversation

@zerob13
Copy link
Collaborator

@zerob13 zerob13 commented Aug 12, 2025

feat #681

接入了https://mcprouter.co/ 提供的 MCP 市场
可以直接在应用中一键安装 MCP
image
image
image

Summary by CodeRabbit

  • New Features

    • Built-in MCP Market: browse, paginate, and install servers with API key support and install status; new settings route and "Browse Built-in MCP Market" button.
    • MCP server listing: improved server name display (uses localized/name/id fallback) and preserved emoji icons.
    • MCP server form: masked custom headers with "Click to edit", smarter edit-mode prefill, and automatic image-model selection.
  • Bug Fixes / Behavior

    • Installed servers default to safer auto-approve/disabled flags when added.
  • Chores

    • Added MCP Market and "Saved" i18n strings across multiple locales and route titles.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 12, 2025

Walkthrough

Adds MCP Router marketplace integration: a new McpRouterManager, presenter APIs for listing/installing marketplace servers and API-key management, built-in market UI and route, MCP server config shape changes (source/sourceId, descriptions, auto-approve/disable), and UI enhancements for masked custom headers and smarter edit-mode initialization.

Changes

Cohort / File(s) Summary
Modelscope provider config reshape
src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
Reworks convertMcpServerToConfig output: replaces provider metadata with source/sourceId, descriptions, icons, command/args/env, adds autoApprove & disable defaults, adjusts displayName fallback and makes source a string.
MCP presenter + router manager & types
src/main/presenter/mcpPresenter/index.ts, src/main/presenter/mcpPresenter/mcprouterManager.ts, src/shared/presenter.d.ts
Adds McpRouterManager; initializes optional mcprouter in McpPresenter with guarded constructor logic; extends IMCPPresenter with list/install API, apiKey get/set, isServerInstalled, updateMcpRouterServersAuth; adds MCPServerConfig.source/sourceId fields.
Renderer: built-in market UI & routing
src/renderer/src/components/settings/McpBuiltinMarket.vue, src/renderer/src/components/settings/McpSettings.vue, src/renderer/src/router/index.ts
New MCP market Vue component and route; adds “Browse Built-in” button to settings that routes to /settings/mcp-market; supports API-key input, pagination, install flow and installed-state checks.
MCP server form enhancements
src/renderer/src/components/mcp-config/mcpServerForm.vue
Adds masked display overlay for sensitive customHeaders with focus/blur behavior and parsing helpers; parses Key=Value headers, supports JSON/default config loading, auto-selects imageServer model from args, improved edit-mode initialization.
i18n additions (market, saved, clickToEdit, route labels)
src/renderer/src/i18n/*/* (multiple locales: en-US, fa-IR, fr-FR, ja-JP, ko-KR, ru-RU, zh-CN, zh-HK, zh-TW)
Adds market translation blocks and route label settings-mcp-market, adds saved and clickToEdit where applicable across locales; mostly additive JSON changes with minor trailing-comma formatting adjustments.
Small i18n route file updates
src/renderer/src/i18n/*/routes.json
Adds settings-mcp-market entries to locale route files.

Sequence Diagram(s)

sequenceDiagram
  participant U as User
  participant V as McpBuiltinMarket (Vue)
  participant P as McpPresenter
  participant R as McpRouterManager
  participant A as MCPRouter API

  U->>V: Open Built-in Market
  V->>P: listMcpRouterServers(page, limit)
  P->>R: listServers(page, limit)
  R->>A: POST /market/list {page, limit}
  A-->>R: { code:0, data:{ servers[] } }
  R-->>P: servers[]
  P-->>V: servers[]
  V-->>U: Render items
Loading
sequenceDiagram
  participant U as User
  participant V as McpBuiltinMarket (Vue)
  participant P as McpPresenter
  participant R as McpRouterManager
  participant C as ConfigPresenter
  participant A as MCPRouter API

  U->>V: Click Install (server_key)
  V->>P: setMcpRouterApiKey(key)
  P->>C: save mcprouterApiKey
  V->>P: installMcpRouterServer(server_key)
  P->>R: installServer(server_key)
  R->>A: POST /market/get {server: server_key} + Authorization
  A-->>R: { code:0, data:{ detail } }
  R->>C: addMcpServer({ source:'mcprouter', sourceId:server_key, ... })
  C-->>R: true
  R-->>P: true
  P-->>V: success
  V-->>U: Mark as installed + toast
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • deepinfect

Poem

Hoppity hop, I browse the wares,
A bag of MCPs with tiny flares. 🛍️
Keys tucked safe, headers masked tight,
Click—install—icons glow at night. ✨
From burrow to market, quick and keen,
I nibble new servers, bright and clean. 🐇


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 53683a4 and 5bd3a4c.

📒 Files selected for processing (1)
  • src/renderer/src/i18n/zh-TW/mcp.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/renderer/src/i18n/zh-TW/mcp.json
✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/add-mcprouter-market

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

♻️ Duplicate comments (1)
src/renderer/src/i18n/en-US/common.json (1)

75-76: LGTM: Shared “Saved” key added

Key is correctly placed in common.json and matches usage expectations.

Note: See the FA-IR comment for a repository-wide verification script ensuring this key exists across all locales.

🧹 Nitpick comments (23)
src/renderer/src/i18n/zh-HK/common.json (1)

75-77: Unify terminology: use Traditional HK form consistent with "save"

"save" is translated as "儲存", but "saved" is "已保存". For zh-HK, prefer "已儲存" to stay consistent and avoid Simplified usage.

-  "saved": "已保存"
+  "saved": "已儲存"
src/renderer/src/i18n/ko-KR/common.json (1)

75-77: Adjust "saved" to avoid collision with "save"

Currently both "save" and "saved" are "저장". Suggest "저장됨" for the past/complete state, which is standard in Korean UIs.

-  "saved": "저장"
+  "saved": "저장됨"
src/renderer/src/i18n/ru-RU/common.json (1)

75-77: Fix Russian aspect: use neutral passive form

"Сохранил" reads as “He saved”. For status labels, use "Сохранено".

-  "saved": "Сохранил"
+  "saved": "Сохранено"
src/renderer/src/i18n/zh-TW/common.json (1)

75-76: Nit: Prefer TW phrasing “已儲存” for consistency with “儲存”

For zh-TW, “儲存” is used for the “save” label; aligning the past tense to “已儲存” improves locale consistency.

Apply:

-  "saved": "已保存"
+  "saved": "已儲存"
src/renderer/src/i18n/fr-FR/settings.json (1)

632-633: French phrasing + consistency: prefer “clé API” and adjust style

  • “Apikey” is not idiomatic French. Use “clé API” and neutral phrasing.
  • Optional: “fonctionnalité” reads more natural than “fonction” in UX copy.

Proposed update:

-      "e2bApiKeyRequired": "Apikey doit être entré pour activer la fonction E2B",
+      "e2bApiKeyRequired": "La clé API est requise pour activer la fonctionnalité E2B",
src/renderer/src/i18n/fr-FR/common.json (1)

75-76: Use the correct French past participle for “Saved”

“Sauvé” is unnatural in this UX context. Prefer “Enregistré” (consistent with “Enregistrer”).

-  "saved": "Sauvé"
+  "saved": "Enregistré"
src/renderer/src/i18n/fr-FR/routes.json (1)

13-15: Minor casing/style consistency for French

French UI labels generally avoid capitalizing common nouns mid-sentence. Consider lowercasing “Prompts” for consistency with other entries.

-  "settings-prompt": "Gestion des Prompts",
+  "settings-prompt": "Gestion des prompts",

“Marché MCP” looks good.

src/renderer/src/i18n/ru-RU/routes.json (1)

14-15: Localize the new route label into Russian

Currently the value is in English. Consider translating for consistency with other RU labels.

Suggested change:

-  "settings-mcp-market": "MCP Market"
+  "settings-mcp-market": "Рынок MCP"

If you prefer a different style (e.g., "Маркет MCP"), I can update across locales for consistency notes.

src/renderer/src/i18n/fa-IR/settings.json (1)

640-642: Polish Persian punctuation and term consistency (comma spacing + API Key phrasing).

  • Remove the space before the Persian comma in clickToEdit.
  • Prefer consistent terminology for API keys. Suggest "API Key" phrasing over "Apikey" and a more natural sentence.

Apply this diff:

-      "e2bApiKeyRequired": "برای فعال کردن عملکرد E2B باید Apikey وارد شود",
-      "clickToEdit": "برای مشاهده مطالب کامل ، روی ویرایش کلیک کنید"
+      "e2bApiKeyRequired": "برای فعال‌سازی E2B، وارد کردن API Key الزامی است",
+      "clickToEdit": "برای مشاهده مطالب کامل، روی ویرایش کلیک کنید"
src/renderer/src/i18n/ja-JP/common.json (1)

75-77: Clarify “saved” usage context for Japanese translation

The "saved" key is present in every common.json under src/renderer/src/i18n, so updating the Japanese file won’t introduce missing keys elsewhere. Please confirm whether this label is shown as:

  • a persistent status/state (e.g. “Status: Saved”)
    → use “保存済み”
  • a one-time toast/message after an action
    → use “保存しました”

Once confirmed, apply one of:

--- a/src/renderer/src/i18n/ja-JP/common.json
+++ b/src/renderer/src/i18n/ja-JP/common.json
@@ -74,3 +74,4 @@
   "clear": "クリア",
-  "saved": "保存"
+  "saved": "保存済み"
 }
--- a/src/renderer/src/i18n/ja-JP/common.json
+++ b/src/renderer/src/i18n/ja-JP/common.json
@@ -74,3 +74,4 @@
   "clear": "クリア",
-  "saved": "保存"
+  "saved": "保存しました"
 }
src/renderer/src/i18n/ru-RU/settings.json (1)

632-634: Unify “API key” terminology and improve sentence style.

Use “ключ API” (or “API‑ключ”) consistently across RU locale, and prefer a more natural construction.

Apply this diff:

-      "e2bApiKeyRequired": "Apikey должен быть введен, чтобы включить функцию E2B",
+      "e2bApiKeyRequired": "Для включения функции E2B необходимо ввести ключ API",
src/renderer/src/i18n/ko-KR/mcp.json (1)

249-268: Standardize MCPRouter brand and improve Korean phrasing (more natural, consistent formal tone).

Current strings mix “McProuter” and contain machine-translated/awkward phrasing. Suggested edits below keep the existing formal imperative tone “-하십시오” used elsewhere in this file and unify branding to “MCPRouter”.

-    "apiKeyPlaceholder": "McProuter API 키를 입력하십시오",
-    "apiKeyRequiredDesc": "설치하기 전에 먼저 McProuter API 키를 작성하십시오.",
+    "apiKeyPlaceholder": "MCPRouter API 키를 입력하십시오",
+    "apiKeyRequiredDesc": "설치 전에 먼저 MCPRouter API 키를 입력하십시오.",
     "apiKeyRequiredTitle": "API 키가 필요합니다",
-    "browseBuiltin": "내장 MCP 시장을 찾아보십시오",
+    "browseBuiltin": "내장 MCP 시장 둘러보기",
     "builtinTitle": "MCP 시장",
-    "empty": "아직 서비스가 없습니다",
-    "install": "설치하다",
-    "installFailed": "설치가 실패했습니다",
-    "installSuccess": "성공적으로 설치",
-    "installed": "설치",
-    "keyGuide": "열쇠를 얻으십시오",
-    "keyHelpEnd": "API 키를 신청 한 후 위의 입력 상자를 채우십시오.",
-    "keyHelpText": "먼저 도착하십시오",
-    "loadMore": "더로드하십시오",
-    "noMore": "더 이상",
-    "poweredBy": "McProuter에 의해 구동",
-    "pullDownToLoad": "더 많은로드하기 위해 계속 드롭 다운하십시오"
+    "empty": "표시할 서비스가 없습니다",
+    "install": "설치",
+    "installFailed": "설치 실패",
+    "installSuccess": "설치 성공",
+    "installed": "설치됨",
+    "keyGuide": "키 발급",
+    "keyHelpEnd": "API 키를 신청한 후 위의 입력란에 입력하십시오.",
+    "keyHelpText": "먼저 다음으로 이동하십시오",
+    "loadMore": "더 불러오기",
+    "noMore": "더 이상 없음",
+    "poweredBy": "MCPRouter 제공",
+    "pullDownToLoad": "더 불러오려면 아래로 당기십시오"
src/renderer/src/i18n/zh-CN/mcp.json (1)

253-253: Localize the “Powered by” label to Chinese.

Keep brand as “MCPRouter” but localize the phrase for consistency with the rest of zh-CN UI text.

-    "poweredBy": "Powered by MCPRouter",
+    "poweredBy": "由 MCPRouter 提供支持",
src/renderer/src/i18n/ru-RU/mcp.json (1)

249-268: Fix Russian grammar and unify “MCPRouter” brand.

Several phrases are unnatural, and the brand is inconsistently cased. Suggested improvements below.

-    "apiKeyPlaceholder": "Введите ключ McProuter API",
-    "apiKeyRequiredDesc": "Пожалуйста, заполните клавишу McProuter API сначала перед установкой",
-    "apiKeyRequiredTitle": "Требует ключа API",
-    "browseBuiltin": "Просмотрите встроенный рынок MCP",
-    "builtinTitle": "MCP Market",
-    "empty": "Пока нет услуг",
+    "apiKeyPlaceholder": "Введите ключ API MCPRouter",
+    "apiKeyRequiredDesc": "Пожалуйста, укажите ключ API MCPRouter перед установкой.",
+    "apiKeyRequiredTitle": "Требуется ключ API",
+    "browseBuiltin": "Просмотреть встроенный рынок MCP",
+    "builtinTitle": "Рынок MCP",
+    "empty": "Сервисы отсутствуют",
     "install": "Установить",
-    "installFailed": "Установка не удалась",
-    "installSuccess": "Установка успешно",
-    "installed": "Установлен",
-    "keyGuide": "Получите ключ",
-    "keyHelpEnd": "После подачи заявки на ключ API заполните поле ввода выше",
-    "keyHelpText": "Пожалуйста, приезжайте первым",
-    "loadMore": "Загружать больше",
-    "noMore": "Больше не надо",
-    "poweredBy": "Оборудован от McProuter",
-    "pullDownToLoad": "Продолжайте падать, чтобы загружать больше"
+    "installFailed": "Не удалось установить",
+    "installSuccess": "Установка выполнена успешно",
+    "installed": "Установлено",
+    "keyGuide": "Где получить ключ",
+    "keyHelpEnd": "После получения ключа API укажите его в поле выше.",
+    "keyHelpText": "Сначала перейдите на",
+    "loadMore": "Загрузить ещё",
+    "noMore": "Больше нет",
+    "poweredBy": "Работает на базе MCPRouter",
+    "pullDownToLoad": "Потяните вниз, чтобы загрузить ещё"
src/renderer/src/i18n/fa-IR/mcp.json (1)

250-268: Improve Persian phrasing and unify “MCPRouter” brand.

A few strings read unnatural or use inconsistent capitalization. Suggested edits below use idiomatic Persian and correct punctuation.

-    "apiKeyPlaceholder": "کلید API MCPROUTER را وارد کنید",
-    "apiKeyRequiredDesc": "لطفاً قبل از نصب ، ابتدا کلید API McProuter را پر کنید",
-    "apiKeyRequiredTitle": "به کلید API نیاز دارد",
+    "apiKeyPlaceholder": "کلید API MCPRouter را وارد کنید",
+    "apiKeyRequiredDesc": "لطفاً پیش از نصب، ابتدا کلید API MCPRouter را وارد کنید.",
+    "apiKeyRequiredTitle": "نیاز به کلید API",
     "browseBuiltin": "مرور بازار داخلی MCP",
     "builtinTitle": "بازار MCP",
-    "empty": "هنوز هیچ خدمتی وجود ندارد",
-    "install": "نصب کردن",
-    "installFailed": "نصب انجام نشد",
-    "installSuccess": "نصب با موفقیت",
+    "empty": "هیچ خدمتی موجود نیست",
+    "install": "نصب",
+    "installFailed": "نصب ناموفق بود",
+    "installSuccess": "نصب با موفقیت انجام شد",
     "installed": "نصب شده",
-    "keyGuide": "کلید را دریافت کنید",
-    "keyHelpEnd": "پس از درخواست کلید API ، کادر ورودی را در بالا پر کنید",
-    "keyHelpText": "لطفا ابتدا وارد شوید",
-    "loadMore": "بار بیشتر",
-    "noMore": "نه بیشتر",
-    "poweredBy": "نیرو توسط McProuter",
-    "pullDownToLoad": "برای بارگیری بیشتر به پایین بیاید"
+    "keyGuide": "دریافت کلید",
+    "keyHelpEnd": "پس از دریافت کلید API، آن را در کادر بالا وارد کنید.",
+    "keyHelpText": "ابتدا به",
+    "loadMore": "بارگذاری بیشتر",
+    "noMore": "مورد بیشتری نیست",
+    "poweredBy": "قدرت‌گرفته از MCPRouter",
+    "pullDownToLoad": "برای بارگذاری بیشتر پایین بکشید"
src/shared/presenter.d.ts (1)

991-993: Consider adding JSDoc comments for the new source tracking fields.

The source and sourceId fields enable tracking of server origins, which is crucial for the marketplace integration. However, their purpose and expected values should be documented for better maintainability.

Add documentation to clarify the purpose and expected values:

-  source?: string // 来源标识: "mcprouter" | "modelscope" | undefined(for manual)
-  sourceId?: string // 来源ID: mcprouter的uuid 或 modelscope的mcpServer.id
+  /** Source identifier indicating where the server configuration originated from */
+  source?: 'mcprouter' | 'modelscope' // undefined for manually added servers
+  /** Unique identifier from the source system (e.g., UUID for mcprouter, server.id for modelscope) */
+  sourceId?: string
src/renderer/src/components/mcp-config/mcpServerForm.vue (1)

556-574: Consider extracting the masking logic to a utility function.

The maskSensitiveValue function could be useful in other parts of the application where sensitive data needs to be displayed. Consider moving it to a shared utility module for reusability.

Create a shared utility function:

// src/renderer/src/utils/sensitive.ts
export function maskSensitiveValue(value: string): string {
  return value.replace(/=(.+)/g, (_, val) => {
    const trimmedVal = val.trim()
    if (trimmedVal.length <= 4) {
      return '=' + '*'.repeat(trimmedVal.length)
    } else if (trimmedVal.length <= 12) {
      return '=' + trimmedVal.substring(0, 1) + '*'.repeat(6)
    } else {
      const start = trimmedVal.substring(0, 2)
      const end = trimmedVal.substring(trimmedVal.length - 2)
      return '=' + start + '*'.repeat(8) + end
    }
  })
}

Then import and use it in the component:

+import { maskSensitiveValue } from '@/utils/sensitive'

-const maskSensitiveValue = (value: string): string => {
-  // ... existing implementation
-}
src/main/presenter/mcpPresenter/mcprouterManager.ts (1)

40-41: Consider using environment variables for API endpoints

The API endpoints are hardcoded. Consider moving them to a configuration file or environment variables for better maintainability and to support different environments (development, staging, production).

-const LIST_ENDPOINT = 'https://api.mcprouter.to/v1/list-servers'
-const GET_ENDPOINT = 'https://api.mcprouter.to/v1/get-server'
+const LIST_ENDPOINT = process.env.MCPROUTER_LIST_ENDPOINT || 'https://api.mcprouter.to/v1/list-servers'
+const GET_ENDPOINT = process.env.MCPROUTER_GET_ENDPOINT || 'https://api.mcprouter.to/v1/get-server'
src/renderer/src/components/settings/McpBuiltinMarket.vue (3)

140-147: Add error handling for loadApiKey

The loadApiKey function silently catches all errors. Consider at least logging errors for debugging purposes.

 const loadApiKey = async () => {
   try {
     const key = await mcpP.getMcpRouterApiKey?.()
     apiKeyInput.value = key || ''
-  } catch {}
+  } catch (error) {
+    console.error('Failed to load MCP Router API key:', error)
+  }
 }

169-183: Performance: Consider batch checking installation status

The current implementation checks installation status one by one. For better performance, consider implementing a batch check method.

 const checkInstalledServers = async () => {
   const installed = new Set<string>()
-  for (const item of items.value) {
-    try {
-      // 使用 server_key 作为 sourceId 检查安装状态,因为这是我们在安装时保存的标识符
-      const isInstalled = await mcpP.isServerInstalled?.('mcprouter', item.server_key)
-      if (isInstalled) {
-        installed.add(item.server_key)
-      }
-    } catch (e) {
-      console.error('Failed to check installation status:', e)
-    }
-  }
+  // Consider implementing a batch check method in the presenter
+  const serverKeys = items.value.map(item => item.server_key)
+  try {
+    // This would require implementing a new batch check method
+    const installationStatuses = await mcpP.batchCheckServerInstallation?.('mcprouter', serverKeys)
+    if (installationStatuses) {
+      installationStatuses.forEach((status, index) => {
+        if (status) {
+          installed.add(serverKeys[index])
+        }
+      })
+    }
+  } catch (e) {
+    console.error('Failed to batch check installation status:', e)
+    // Fallback to individual checks
+    for (const item of items.value) {
+      try {
+        const isInstalled = await mcpP.isServerInstalled?.('mcprouter', item.server_key)
+        if (isInstalled) {
+          installed.add(item.server_key)
+        }
+      } catch (e) {
+        console.error('Failed to check installation status:', e)
+      }
+    }
+  }
   installedServers.value = installed
 }

286-296: Potential race condition with setTimeout

Using setTimeout to check content height after mounting could lead to race conditions. Consider using nextTick or MutationObserver for more reliable detection.

 onMounted(async () => {
   await loadApiKey()
   await fetchPage()

   // 初始加载后检查是否需要启用强制拉取模式
-  setTimeout(() => {
+  await nextTick()
     const el = scrollContainer.value
     if (el && !hasMore.value) {
       const contentTooShort = el.scrollHeight <= el.clientHeight
       if (contentTooShort && items.value.length > 0) {
         canPullMore.value = true
         showPullToLoad.value = true
       }
     }
-  }, 100)
 })
src/main/presenter/mcpPresenter/index.ts (2)

217-220: Consider adding error details for better debugging

The error message could be more descriptive to help with debugging.

   async installMcpRouterServer(serverKey: string): Promise<boolean> {
-    if (!this.mcprouter) throw new Error('McpRouterManager not available')
+    if (!this.mcprouter) throw new Error('McpRouterManager not available - initialization may have failed')
     return this.mcprouter.installServer(serverKey)
   }

240-263: Consider optimizing batch updates

The updateMcpRouterServersAuth method could be optimized by batching all updates into a single configuration save operation instead of multiple individual updates.

   async updateMcpRouterServersAuth(apiKey: string): Promise<void> {
     const servers = await this.configPresenter.getMcpServers()
-    const updates: Array<{ name: string; config: Partial<MCPServerConfig> }> = []
+    const updatedServers = { ...servers }
+    let updateCount = 0

     for (const [serverName, config] of Object.entries(servers)) {
       if (config.source === 'mcprouter' && config.customHeaders) {
         const updatedHeaders = {
           ...config.customHeaders,
           Authorization: `Bearer ${apiKey}`
         }
-        updates.push({
-          name: serverName,
-          config: { customHeaders: updatedHeaders }
-        })
+        updatedServers[serverName] = {
+          ...config,
+          customHeaders: updatedHeaders
+        }
+        updateCount++
       }
     }

-    // 批量更新所有服务器的 Authorization
-    for (const update of updates) {
-      await this.configPresenter.updateMcpServer(update.name, update.config)
-    }
+    // Single batch update
+    if (updateCount > 0) {
+      await this.configPresenter.setMcpServers(updatedServers)
+    }

-    console.log(`Updated Authorization for ${updates.length} mcprouter servers`)
+    console.log(`Updated Authorization for ${updateCount} mcprouter servers`)
   }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f5f93c9 and 53683a4.

📒 Files selected for processing (44)
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts (1 hunks)
  • src/main/presenter/mcpPresenter/index.ts (3 hunks)
  • src/main/presenter/mcpPresenter/mcprouterManager.ts (1 hunks)
  • src/renderer/src/components/mcp-config/mcpServerForm.vue (3 hunks)
  • src/renderer/src/components/settings/McpBuiltinMarket.vue (1 hunks)
  • src/renderer/src/components/settings/McpSettings.vue (3 hunks)
  • src/renderer/src/i18n/en-US/common.json (1 hunks)
  • src/renderer/src/i18n/en-US/mcp.json (1 hunks)
  • src/renderer/src/i18n/en-US/routes.json (1 hunks)
  • src/renderer/src/i18n/en-US/settings.json (1 hunks)
  • src/renderer/src/i18n/fa-IR/common.json (1 hunks)
  • src/renderer/src/i18n/fa-IR/mcp.json (1 hunks)
  • src/renderer/src/i18n/fa-IR/routes.json (1 hunks)
  • src/renderer/src/i18n/fa-IR/settings.json (1 hunks)
  • src/renderer/src/i18n/fr-FR/common.json (1 hunks)
  • src/renderer/src/i18n/fr-FR/mcp.json (1 hunks)
  • src/renderer/src/i18n/fr-FR/routes.json (1 hunks)
  • src/renderer/src/i18n/fr-FR/settings.json (1 hunks)
  • src/renderer/src/i18n/ja-JP/common.json (1 hunks)
  • src/renderer/src/i18n/ja-JP/mcp.json (1 hunks)
  • src/renderer/src/i18n/ja-JP/routes.json (1 hunks)
  • src/renderer/src/i18n/ja-JP/settings.json (1 hunks)
  • src/renderer/src/i18n/ko-KR/common.json (1 hunks)
  • src/renderer/src/i18n/ko-KR/mcp.json (1 hunks)
  • src/renderer/src/i18n/ko-KR/routes.json (1 hunks)
  • src/renderer/src/i18n/ko-KR/settings.json (1 hunks)
  • src/renderer/src/i18n/ru-RU/common.json (1 hunks)
  • src/renderer/src/i18n/ru-RU/mcp.json (1 hunks)
  • src/renderer/src/i18n/ru-RU/routes.json (1 hunks)
  • src/renderer/src/i18n/ru-RU/settings.json (1 hunks)
  • src/renderer/src/i18n/zh-CN/common.json (1 hunks)
  • src/renderer/src/i18n/zh-CN/mcp.json (1 hunks)
  • src/renderer/src/i18n/zh-CN/routes.json (1 hunks)
  • src/renderer/src/i18n/zh-CN/settings.json (1 hunks)
  • src/renderer/src/i18n/zh-HK/common.json (1 hunks)
  • src/renderer/src/i18n/zh-HK/mcp.json (1 hunks)
  • src/renderer/src/i18n/zh-HK/routes.json (1 hunks)
  • src/renderer/src/i18n/zh-HK/settings.json (1 hunks)
  • src/renderer/src/i18n/zh-TW/common.json (1 hunks)
  • src/renderer/src/i18n/zh-TW/mcp.json (1 hunks)
  • src/renderer/src/i18n/zh-TW/routes.json (1 hunks)
  • src/renderer/src/i18n/zh-TW/settings.json (1 hunks)
  • src/renderer/src/router/index.ts (1 hunks)
  • src/shared/presenter.d.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (21)
src/renderer/src/**/*

📄 CodeRabbit Inference Engine (.cursor/rules/i18n.mdc)

src/renderer/src/**/*: All user-facing strings must use i18n keys (avoid hardcoded user-visible text in code)
Use the 'vue-i18n' framework for all internationalization in the renderer
Ensure all user-visible text in the renderer uses the translation system

Files:

  • src/renderer/src/i18n/fr-FR/settings.json
  • src/renderer/src/i18n/ko-KR/routes.json
  • src/renderer/src/i18n/en-US/common.json
  • src/renderer/src/i18n/en-US/routes.json
  • src/renderer/src/router/index.ts
  • src/renderer/src/i18n/ja-JP/common.json
  • src/renderer/src/i18n/zh-HK/routes.json
  • src/renderer/src/i18n/zh-TW/routes.json
  • src/renderer/src/i18n/fr-FR/routes.json
  • src/renderer/src/i18n/zh-TW/common.json
  • src/renderer/src/i18n/fa-IR/common.json
  • src/renderer/src/i18n/zh-CN/common.json
  • src/renderer/src/i18n/en-US/settings.json
  • src/renderer/src/i18n/fa-IR/routes.json
  • src/renderer/src/components/settings/McpSettings.vue
  • src/renderer/src/i18n/zh-CN/settings.json
  • src/renderer/src/i18n/ko-KR/common.json
  • src/renderer/src/i18n/ru-RU/settings.json
  • src/renderer/src/i18n/ko-KR/settings.json
  • src/renderer/src/i18n/zh-TW/mcp.json
  • src/renderer/src/i18n/fa-IR/settings.json
  • src/renderer/src/i18n/ko-KR/mcp.json
  • src/renderer/src/i18n/fr-FR/common.json
  • src/renderer/src/i18n/fr-FR/mcp.json
  • src/renderer/src/i18n/zh-TW/settings.json
  • src/renderer/src/i18n/ja-JP/settings.json
  • src/renderer/src/i18n/ru-RU/mcp.json
  • src/renderer/src/components/settings/McpBuiltinMarket.vue
  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/i18n/zh-HK/common.json
  • src/renderer/src/i18n/ja-JP/routes.json
  • src/renderer/src/i18n/ru-RU/common.json
  • src/renderer/src/i18n/ru-RU/routes.json
  • src/renderer/src/i18n/zh-CN/mcp.json
  • src/renderer/src/i18n/zh-CN/routes.json
  • src/renderer/src/i18n/en-US/mcp.json
  • src/renderer/src/i18n/zh-HK/mcp.json
  • src/renderer/src/i18n/fa-IR/mcp.json
  • src/renderer/src/i18n/ja-JP/mcp.json
  • src/renderer/src/components/mcp-config/mcpServerForm.vue
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Use English for logs and comments

Files:

  • src/renderer/src/router/index.ts
  • src/renderer/src/components/settings/McpSettings.vue
  • src/main/presenter/mcpPresenter/mcprouterManager.ts
  • src/renderer/src/components/settings/McpBuiltinMarket.vue
  • src/shared/presenter.d.ts
  • src/renderer/src/components/mcp-config/mcpServerForm.vue
  • src/main/presenter/mcpPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (CLAUDE.md)

Strict type checking enabled for TypeScript

**/*.{ts,tsx}: 始终使用 try-catch 处理可能的错误
提供有意义的错误信息
记录详细的错误日志
优雅降级处理
日志应包含时间戳、日志级别、错误代码、错误描述、堆栈跟踪(如适用)、相关上下文信息
日志级别应包括 ERROR、WARN、INFO、DEBUG
不要吞掉错误
提供用户友好的错误信息
实现错误重试机制
避免记录敏感信息
使用结构化日志
设置适当的日志级别

Files:

  • src/renderer/src/router/index.ts
  • src/main/presenter/mcpPresenter/mcprouterManager.ts
  • src/shared/presenter.d.ts
  • src/main/presenter/mcpPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
src/renderer/src/**/*.{ts,tsx,vue}

📄 CodeRabbit Inference Engine (CLAUDE.md)

src/renderer/src/**/*.{ts,tsx,vue}: Use Pinia for frontend state management
Renderer to Main: Use usePresenter.ts composable for direct presenter method calls

Files:

  • src/renderer/src/router/index.ts
  • src/renderer/src/components/settings/McpSettings.vue
  • src/renderer/src/components/settings/McpBuiltinMarket.vue
  • src/renderer/src/components/mcp-config/mcpServerForm.vue
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/development-setup.mdc)

**/*.{js,jsx,ts,tsx}: 使用 OxLint 进行代码检查
Log和注释使用英文书写

Files:

  • src/renderer/src/router/index.ts
  • src/main/presenter/mcpPresenter/mcprouterManager.ts
  • src/shared/presenter.d.ts
  • src/main/presenter/mcpPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
src/{main,renderer}/**/*.ts

📄 CodeRabbit Inference Engine (.cursor/rules/electron-best-practices.mdc)

src/{main,renderer}/**/*.ts: Use context isolation for improved security
Implement proper inter-process communication (IPC) patterns
Optimize application startup time with lazy loading
Implement proper error handling and logging for debugging

Files:

  • src/renderer/src/router/index.ts
  • src/main/presenter/mcpPresenter/mcprouterManager.ts
  • src/main/presenter/mcpPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
src/renderer/**/*.{vue,ts,js,tsx,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)

渲染进程代码放在 src/renderer

Files:

  • src/renderer/src/router/index.ts
  • src/renderer/src/components/settings/McpSettings.vue
  • src/renderer/src/components/settings/McpBuiltinMarket.vue
  • src/renderer/src/components/mcp-config/mcpServerForm.vue
src/renderer/src/**/*.{vue,ts,tsx,js,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/vue-best-practices.mdc)

src/renderer/src/**/*.{vue,ts,tsx,js,jsx}: Use the Composition API for better code organization and reusability
Implement proper state management with Pinia
Utilize Vue Router for navigation and route management
Leverage Vue's built-in reactivity system for efficient data handling

Files:

  • src/renderer/src/router/index.ts
  • src/renderer/src/components/settings/McpSettings.vue
  • src/renderer/src/components/settings/McpBuiltinMarket.vue
  • src/renderer/src/components/mcp-config/mcpServerForm.vue
src/renderer/src/router/**/*.{vue,ts,tsx,js,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/vue-router-best-practices.mdc)

src/renderer/src/router/**/*.{vue,ts,tsx,js,jsx}: Use named routes for easier navigation and maintenance
Implement route-level code splitting for better performance
Use route meta fields for attaching additional data to routes
Implement proper navigation guards for authentication and authorization
Use dynamic routing for handling variable route segments

Files:

  • src/renderer/src/router/index.ts
src/renderer/**/*.{ts,tsx,vue}

📄 CodeRabbit Inference Engine (.cursor/rules/vue-shadcn.mdc)

src/renderer/**/*.{ts,tsx,vue}: Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError).
Use TypeScript for all code; prefer types over interfaces.
Avoid enums; use const objects instead.
Use arrow functions for methods and computed properties.
Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements.

Files:

  • src/renderer/src/router/index.ts
  • src/renderer/src/components/settings/McpSettings.vue
  • src/renderer/src/components/settings/McpBuiltinMarket.vue
  • src/renderer/src/components/mcp-config/mcpServerForm.vue
src/renderer/**/*.{vue,ts}

📄 CodeRabbit Inference Engine (.cursor/rules/vue-shadcn.mdc)

Implement lazy loading for routes and components.

Files:

  • src/renderer/src/router/index.ts
  • src/renderer/src/components/settings/McpSettings.vue
  • src/renderer/src/components/settings/McpBuiltinMarket.vue
  • src/renderer/src/components/mcp-config/mcpServerForm.vue
src/renderer/**/*.{ts,vue}

📄 CodeRabbit Inference Engine (.cursor/rules/vue-shadcn.mdc)

src/renderer/**/*.{ts,vue}: Use useFetch and useAsyncData for data fetching.
Implement SEO best practices using Nuxt's useHead and useSeoMeta.

Files:

  • src/renderer/src/router/index.ts
  • src/renderer/src/components/settings/McpSettings.vue
  • src/renderer/src/components/settings/McpBuiltinMarket.vue
  • src/renderer/src/components/mcp-config/mcpServerForm.vue
src/renderer/src/**/*.vue

📄 CodeRabbit Inference Engine (CLAUDE.md)

src/renderer/src/**/*.vue: Use Composition API for all Vue 3 components
Use Tailwind CSS with scoped styles for styling
Organize components by feature in src/renderer/src/
Follow existing component patterns in src/renderer/src/ when creating new UI components
Use Composition API with proper TypeScript typing for new UI components
Implement responsive design with Tailwind CSS for new UI components
Add proper error handling and loading states for new UI components

Use scoped styles to prevent CSS conflicts between components

Files:

  • src/renderer/src/components/settings/McpSettings.vue
  • src/renderer/src/components/settings/McpBuiltinMarket.vue
  • src/renderer/src/components/mcp-config/mcpServerForm.vue
src/main/**/*.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

Main to Renderer: Use EventBus to broadcast events via mainWindow.webContents.send()

Use Electron's built-in APIs for file system and native dialogs

Files:

  • src/main/presenter/mcpPresenter/mcprouterManager.ts
  • src/main/presenter/mcpPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
src/main/presenter/**/*.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

One presenter per functional domain

Files:

  • src/main/presenter/mcpPresenter/mcprouterManager.ts
  • src/main/presenter/mcpPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
src/main/**/*.{ts,js,tsx,jsx}

📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)

主进程代码放在 src/main

Files:

  • src/main/presenter/mcpPresenter/mcprouterManager.ts
  • src/main/presenter/mcpPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
src/shared/**/*.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

Shared types in src/shared/

Files:

  • src/shared/presenter.d.ts
src/shared/*.d.ts

📄 CodeRabbit Inference Engine (.cursor/rules/electron-best-practices.mdc)

The shared/*.d.ts files are used to define the types of objects exposed by the main process to the renderer process

Files:

  • src/shared/presenter.d.ts
src/shared/**/*.{ts,tsx,d.ts}

📄 CodeRabbit Inference Engine (.cursor/rules/project-structure.mdc)

共享类型定义放在 shared 目录

Files:

  • src/shared/presenter.d.ts
src/main/presenter/mcpPresenter/index.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

Register new MCP tool in mcpPresenter/index.ts

Files:

  • src/main/presenter/mcpPresenter/index.ts
src/main/presenter/llmProviderPresenter/providers/*.ts

📄 CodeRabbit Inference Engine (CLAUDE.md)

src/main/presenter/llmProviderPresenter/providers/*.ts: Create provider file in src/main/presenter/llmProviderPresenter/providers/ when adding a new LLM provider
Implement coreStream method following standardized event interface in LLM provider files

src/main/presenter/llmProviderPresenter/providers/*.ts: Each file in src/main/presenter/llmProviderPresenter/providers/*.ts should handle interaction with a specific LLM API, including request/response formatting, tool definition conversion, native/non-native tool call management, and standardizing output streams to a common event format.
Provider implementations must use a coreStream method that yields standardized stream events to decouple the main loop from provider-specific details.
The coreStream method in each Provider must perform a single streaming API request per conversation round and must not contain multi-round tool call loop logic.
Provider files should implement helper methods such as formatMessages, convertToProviderTools, parseFunctionCalls, and prepareFunctionCallPrompt as needed for provider-specific logic.
All provider implementations must parse provider-specific data chunks and yield standardized events for text, reasoning, tool calls, usage, errors, stop reasons, and image data.
When a provider does not support native function calling, it must prepare messages using prompt wrapping (e.g., prepareFunctionCallPrompt) before making the API call.
When a provider supports native function calling, MCP tools must be converted to the provider's format (e.g., using convertToProviderTools) and included in the API request.
Provider implementations should aggregate and yield usage events as part of the standardized stream.
Provider implementations should yield image data events in the standardized format when applicable.
Provider implementations should yield reasoning events in the standardized format when applicable.
Provider implementations should yield tool call events (`tool_call_star...

Files:

  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
🧠 Learnings (11)
📚 Learning: 2025-07-21T01:46:30.354Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-07-21T01:46:30.354Z
Learning: Applies to src/renderer/src/i18n/common.json : Shared translation keys must be placed in 'src/renderer/src/i18n/common.json'

Applied to files:

  • src/renderer/src/i18n/fr-FR/settings.json
  • src/renderer/src/i18n/en-US/common.json
  • src/renderer/src/i18n/ja-JP/common.json
  • src/renderer/src/i18n/zh-HK/routes.json
  • src/renderer/src/i18n/zh-TW/routes.json
  • src/renderer/src/i18n/fr-FR/routes.json
  • src/renderer/src/i18n/zh-TW/common.json
  • src/renderer/src/i18n/zh-CN/common.json
  • src/renderer/src/i18n/ko-KR/common.json
  • src/renderer/src/i18n/ru-RU/settings.json
  • src/renderer/src/i18n/fr-FR/common.json
  • src/renderer/src/i18n/zh-HK/settings.json
  • src/renderer/src/i18n/zh-HK/common.json
  • src/renderer/src/i18n/ru-RU/common.json
  • src/renderer/src/i18n/ru-RU/routes.json
📚 Learning: 2025-07-21T01:46:30.354Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-07-21T01:46:30.354Z
Learning: Applies to src/renderer/src/i18n/*.json : When adding new translations, add shared keys to 'common.json' and language-specific keys to the respective language file; keep all language files' keys consistent

Applied to files:

  • src/renderer/src/i18n/fr-FR/settings.json
  • src/renderer/src/i18n/en-US/common.json
  • src/renderer/src/i18n/ja-JP/common.json
  • src/renderer/src/i18n/zh-TW/common.json
  • src/renderer/src/i18n/zh-CN/common.json
  • src/renderer/src/i18n/zh-HK/common.json
  • src/renderer/src/i18n/ru-RU/common.json
📚 Learning: 2025-07-21T01:47:28.817Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-best-practices.mdc:0-0
Timestamp: 2025-07-21T01:47:28.817Z
Learning: Applies to src/renderer/src/**/*.{vue,ts,tsx,js,jsx} : Utilize Vue Router for navigation and route management

Applied to files:

  • src/renderer/src/router/index.ts
  • src/renderer/src/components/settings/McpSettings.vue
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/main/presenter/mcpPresenter/inMemoryServers/*.ts : Implement new MCP tool in src/main/presenter/mcpPresenter/inMemoryServers/ when adding a new MCP tool

Applied to files:

  • src/main/presenter/mcpPresenter/mcprouterManager.ts
  • src/shared/presenter.d.ts
  • src/main/presenter/mcpPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/main/presenter/mcpPresenter/index.ts : Register new MCP tool in mcpPresenter/index.ts

Applied to files:

  • src/main/presenter/mcpPresenter/mcprouterManager.ts
  • src/shared/presenter.d.ts
  • src/main/presenter/mcpPresenter/index.ts
📚 Learning: 2025-07-21T01:46:52.880Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-07-21T01:46:52.880Z
Learning: Applies to src/main/presenter/llmProviderPresenter/index.ts : `src/main/presenter/llmProviderPresenter/index.ts` should manage the overall Agent loop, conversation history, tool execution via `McpPresenter`, and frontend communication via `eventBus`.

Applied to files:

  • src/main/presenter/mcpPresenter/mcprouterManager.ts
  • src/shared/presenter.d.ts
  • src/main/presenter/mcpPresenter/index.ts
  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/main/presenter/configPresenter/**/*.ts : Centralize configuration in configPresenter/

Applied to files:

  • src/main/presenter/mcpPresenter/index.ts
📚 Learning: 2025-07-21T01:46:52.880Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-07-21T01:46:52.880Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : When a provider supports native function calling, MCP tools must be converted to the provider's format (e.g., using `convertToProviderTools`) and included in the API request.

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
📚 Learning: 2025-07-21T01:45:33.790Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-21T01:45:33.790Z
Learning: Applies to src/main/presenter/configPresenter/providers.ts : Add provider configuration in configPresenter/providers.ts when adding a new LLM provider

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
📚 Learning: 2025-07-21T01:46:52.880Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-07-21T01:46:52.880Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : Provider files should implement helper methods such as `formatMessages`, `convertToProviderTools`, `parseFunctionCalls`, and `prepareFunctionCallPrompt` as needed for provider-specific logic.

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
📚 Learning: 2025-07-21T01:46:52.880Z
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/llm-agent-loop.mdc:0-0
Timestamp: 2025-07-21T01:46:52.880Z
Learning: Applies to src/main/presenter/llmProviderPresenter/providers/*.ts : Each file in `src/main/presenter/llmProviderPresenter/providers/*.ts` should handle interaction with a specific LLM API, including request/response formatting, tool definition conversion, native/non-native tool call management, and standardizing output streams to a common event format.

Applied to files:

  • src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts
🧬 Code Graph Analysis (2)
src/main/presenter/mcpPresenter/mcprouterManager.ts (1)
src/shared/presenter.d.ts (2)
  • IConfigPresenter (343-465)
  • MCPServerConfig (979-993)
src/main/presenter/mcpPresenter/index.ts (3)
src/main/presenter/mcpPresenter/mcprouterManager.ts (1)
  • McpRouterManager (43-124)
src/shared/presenter.d.ts (2)
  • IConfigPresenter (343-465)
  • MCPServerConfig (979-993)
src/main/presenter/index.ts (1)
  • presenter (184-184)
🔇 Additional comments (36)
src/renderer/src/i18n/ko-KR/routes.json (1)

13-15: LGTM: new route key added and JSON remains valid

"settings-mcp-market" is correctly added and matches the router meta usage. No issues.

src/renderer/src/i18n/zh-CN/common.json (1)

75-77: i18n: Verified “saved” key across all locales
All common.json files for en-US, fa-IR, fr-FR, ja-JP, ko-KR, ru-RU, zh-CN, zh-HK, and zh-TW include the new "saved" key, meeting our shared-key placement guidelines. LGTM.

src/renderer/src/i18n/zh-HK/routes.json (1)

13-14: LGTM: ‘settings-mcp-market’ present in all route locales

Verified that every routes.json under src/renderer/src/i18n includes the new settings-mcp-market key. JSON syntax is intact and placement is appropriate for router titleKey resolution. No further changes required.

src/renderer/src/i18n/zh-TW/routes.json (1)

13-14: LGTM: TW route label added consistently for MCP Market

settings-mcp-market is correctly added and localized. Placement in routes.json is correct.

src/renderer/src/i18n/fa-IR/common.json (1)

75-76: LGTM: Consistent addition of “saved” key across all locales
Verified that every common.json under src/renderer/src/i18n defines the shared "saved" key, fully aligning with our i18n conventions.

src/renderer/src/i18n/fa-IR/routes.json (1)

13-15: LGTM for new route label

The addition of “بازار MCP” aligns with the new route and matches the pattern across locales.

src/renderer/src/i18n/zh-TW/settings.json (1)

632-633: LGTM for zh-TW additions

  • “啟用E2B功能必須要輸入 ApiKey” and “點擊編輯以查看完整內容” read correctly and match the intended UX.
  • The casing “ApiKey” matches nearby strings in this locale file.

No changes needed.

src/renderer/src/i18n/en-US/settings.json (2)

627-627: LGTM: added clickToEdit key aligns with masked headers UX

The key placement under mcp.serverForm is appropriate and the English copy is clear.


575-642: Locale key presence and JSON validity confirmed
All i18n settings.json files are valid JSON and include the mcp.serverForm.clickToEdit entry. No further action is needed.

src/renderer/src/i18n/ja-JP/settings.json (1)

619-620: LGTM: natural JP translation for clickToEdit

「クリックして編集し、完全な内容を表示」はわかりやすく、文脈に合っています。

src/renderer/src/i18n/ko-KR/settings.json (1)

632-634: LGTM: KR translation added and JSON punctuation adjusted correctly

The added clickToEdit string is clear and formal; preceding comma fix maintains valid JSON.

src/renderer/src/i18n/zh-CN/settings.json (1)

626-627: LGTM: CN translation added under correct scope

“点击编辑以查看完整内容” reads well and matches the intended UX hint.

src/renderer/src/i18n/zh-HK/settings.json (1)

632-634: LGTM: Natural HK Traditional phrasing for clickToEdit.

“點擊編輯以查看完整內容” reads well and aligns with other locales.

src/renderer/src/i18n/zh-CN/routes.json (1)

13-14: LGTM — new route key is correct and consistent.

The added routes.settings-mcp-market entry looks good and matches the router’s titleKey. No hardcoded UI strings in code paths depend on this.

src/renderer/src/i18n/zh-CN/mcp.json (1)

249-268: All .market keys are consistent across locales

I’ve compared src/renderer/src/i18n/en-US/mcp.json against every other mcp.json and found no missing or extra keys in any locale. All .market sections are fully synchronized.

src/renderer/src/i18n/zh-HK/mcp.json (1)

250-268: LGTM! Comprehensive MCP market translations added.

The new market translations are well-structured and cover all necessary UI elements for the MCP marketplace integration. The translations maintain consistency with other language variants and follow the established i18n pattern.

src/shared/presenter.d.ts (1)

1144-1167: Well-structured MCP Router marketplace API methods.

The new optional methods for MCP Router integration are properly typed and follow the existing interface patterns. The pagination support in listMcpRouterServers and the comprehensive server metadata structure are well-designed.

src/renderer/src/components/mcp-config/mcpServerForm.vue (5)

59-61: Good implementation of sensitive data masking for custom headers.

The addition of state management for masking sensitive header values enhances security by preventing accidental exposure of API keys and tokens in the UI.


1145-1182: Excellent UX implementation for sensitive header editing.

The masked overlay approach with focus/blur handlers provides a secure and intuitive way to edit sensitive headers. The visual feedback with the "click to edit" hint and proper border styling maintains consistency with the rest of the form.


696-717: Robust header parsing implementation.

The parseKeyValueHeaders function correctly handles edge cases like empty lines and ensures proper key-value separation. The use of indexOf instead of split prevents issues with values containing multiple = characters.


615-637: Smart auto-detection of imageServer model configuration.

The watcher effectively parses and applies the model configuration from args for imageServer type, with appropriate error handling via console.warn when no matching model is found.


639-683: Comprehensive edit mode initialization.

The watcher properly handles initial configuration loading in edit mode, including special handling for powerpack E2B settings and custom headers formatting. The guard against overwriting when defaultJsonConfig is provided prevents conflicts.

src/renderer/src/router/index.ts (1)

74-82: Well-integrated MCP Market route.

The new route follows the established pattern for settings sub-routes, with proper component lazy-loading, i18n integration, and consistent icon usage. The placement within the settings hierarchy is logical.

src/renderer/src/i18n/en-US/routes.json (1)

13-14: Route translation properly added.

The new "MCP Market" translation entry is correctly placed and follows the naming convention.

src/renderer/src/i18n/ja-JP/routes.json (1)

13-14: LGTM! Proper JSON formatting and consistent localization.

The addition of the MCP Market route translation is well-formatted with the correct trailing comma and consistent with other Japanese translations in the file.

src/renderer/src/components/settings/McpSettings.vue (3)

219-223: LGTM! Proper Vue Router integration following coding guidelines.

The import and usage of useRouter follows Vue.js best practices and the coding guidelines for utilizing Vue Router for navigation management.


172-180: LGTM! Well-structured button with proper i18n integration.

The new "Browse Builtin" button follows the existing UI pattern with proper icon usage, localized text, and consistent styling. The implementation correctly uses the translation key mcp.market.browseBuiltin.


454-457: LGTM! Clean navigation implementation with proper routing.

The openBuiltinMarket function correctly uses Vue Router's push method for programmatic navigation to the MCP market route, following the coding guidelines for route management.

src/renderer/src/i18n/fr-FR/mcp.json (1)

250-268: LGTM! Comprehensive French translations for MCP Market feature.

The market object contains well-structured French translations covering all aspects of the MCP Market UI:

  • API key management and validation messages
  • Installation states and feedback
  • Navigation and loading states
  • Proper French terminology and grammar

The translations are consistent with the existing French localization patterns in the file.

src/renderer/src/i18n/ja-JP/mcp.json (1)

250-268: LGTM! Complete Japanese translations for MCP Market functionality.

The market translations are comprehensive and properly formatted:

  • Clear Japanese terminology for technical concepts like "API key" and "installation"
  • Appropriate honorific language ("APIキーを申請し")
  • Consistent formatting with existing Japanese translations
  • Covers all UI states from browsing to installation feedback
src/renderer/src/i18n/en-US/mcp.json (1)

250-268: LGTM! Complete English translations for MCP Market integration.

The market object provides comprehensive English translations covering all MCP Market functionality:

  • Clear and professional language for API key management
  • Appropriate user feedback messages for installation states
  • Consistent terminology with "MCPRouter" branding
  • Well-structured loading and pagination messages

The translations follow the existing English localization patterns and maintain consistency with technical terminology used throughout the application.

src/main/presenter/llmProviderPresenter/providers/modelscopeProvider.ts (1)

307-308: Improved displayName fallback chain

The updated fallback logic now considers mcpServer.name before falling back to id, providing a more meaningful display name.

src/renderer/src/components/settings/McpBuiltinMarket.vue (1)

15-21: Verified: No API key logging or exposure detected
All searches for console.log|error|warn|debug and error-handler patterns referencing apiKey across .ts and .vue files returned no hits. The <Input type="password"> correctly masks the value, and there’s no evidence the key is ever logged or surfaced in error messages. No further action required.

src/main/presenter/mcpPresenter/index.ts (3)

96-101: Good defensive error handling for McpRouterManager initialization

The try-catch block gracefully handles initialization failures and logs a warning instead of crashing the application. This ensures the MCP presenter can still function even if McpRouter integration fails.


193-215: LGTM! Well-structured McpRouter API methods

The listMcpRouterServers method properly validates the manager availability, delegates to the manager, and provides a safe default return value.


230-238: Efficient server installation check implementation

Good implementation using source and sourceId fields to check if a server is already installed. This aligns well with the new source-based server management architecture.

Comment on lines +154 to +157
// 更新现有 mcprouter 服务器的 Authorization header
if (newKey) {
await mcpP.updateMcpRouterServersAuth?.(newKey)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Security concern: API key update in Authorization headers

Updating Authorization headers for existing servers when the API key changes is good, but ensure that the old API key is properly invalidated and that this doesn't create a security vulnerability if multiple API keys exist.


🏁 Script executed:

#!/bin/bash
# Check how API keys are stored and managed
echo "Checking API key storage patterns..."
rg "mcprouterApiKey" --type ts -A 3 -B 3 | head -30

# Check for any API key validation or rotation logic
echo -e "\nChecking for API key validation..."
rg "validateApiKey|rotateApiKey|invalidateApiKey" --type ts

Length of output: 2375


#!/bin/bash
echo "Locating updateMcpRouterServersAuth usage and definition..."
rg "updateMcpRouterServersAuth" -n -A5 -B5 --type ts

Ensure old API key is invalidated when rotating keys

I didn’t find any invalidateApiKey or rotation logic in the mcpPresenter after updating the key. Without revoking the previous key, any servers still holding it could continue to authenticate. Please add explicit invalidation of the old key when you call updateMcpRouterServersAuth(newKey):

• In src/renderer/src/components/settings/McpBuiltinMarket.vue (lines 154–157), you already invoke
await mcpP.updateMcpRouterServersAuth?.(newKey)
– ensure this method also handles revoking the previous key.
• In src/main/presenter/mcpPresenter/index.ts under setMcpRouterApiKey, call your key-rotation or invalidation endpoint.
• In src/main/presenter/mcpPresenter/mcprouterManager.ts, extend updateMcpRouterServersAuth (or add a new helper) to send a revoke/invalidate request for the old API key before applying the new one.

This will close the gap where stale keys remain valid.

🤖 Prompt for AI Agents
In src/renderer/src/components/settings/McpBuiltinMarket.vue around lines
154–157, you call await mcpP.updateMcpRouterServersAuth?.(newKey) but there is
no invalidation of the previous API key; update the flow so the old key is
revoked when rotating keys: ensure mcpP.updateMcpRouterServersAuth triggers a
revoke of the old key before applying the new one, modify
src/main/presenter/mcpPresenter/index.ts in setMcpRouterApiKey to call the
key-rotation/invalidate endpoint (pass oldKey and newKey or token id), and
extend src/main/presenter/mcpPresenter/mcprouterManager.ts
updateMcpRouterServersAuth (or add a helper) to first send an HTTP request to
the mcprouter revoke/invalidate API for the old key, verify successful
revocation, then propagate the new key to servers; handle errors and rollback if
revoke fails.

@zerob13 zerob13 merged commit f02aaaf into dev Aug 12, 2025
2 checks passed
zerob13 added a commit that referenced this pull request Aug 13, 2025
* fix: add AlertDialogDescription to resolve accessibility warning (#706)

* fix: resolve focus flicker when creating new windows with Ctrl+Shift+N (#707)

* feat: enhance window management by implementing main window ID handling (#709)

* docs: update zhipu developer doc website link (#715)

Co-authored-by: gongchao <chao.gong@aminer.cn>

* refactor: better translate (#716)

* chore: en-us i18n

* chore(i18n): polish ja-JP translations across UI; keep chat.input.placeholder unchanged

* chore(i18n): polish fr-FR translations; keep chat.input.placeholder unchanged

* chore(i18n): refine fr-FR MCP & Settings copy; idiomatic, concise, brand-consistent

* chore(i18n): polish ru-RU translations across UI; keep chat.input.placeholder unchanged

* chore(i18n): polish fa-IR translations across UI; keep chat.input.placeholder unchanged

* chore: fix format

* chore: fix i18n

* chore: lock rolldown-vite version

* feat: add GPT-5 series model support (#717)

* ci(vite): Bundle the main file into a single file to speed up loading. (#718)

* fix(math): parser by upgrade vue-renderer-markdown (#722)

* chore: bump deps (#721)

* chore: bump deps

* fix: rolldown-vite 7.1.0 and duckdb bundle issue

* chore: back to vite

* chore: update electron

* chore: update versions

* fix(math): parser by upgrade vue-renderer-markdown (#722)

* chore: bump deps

---------

Co-authored-by: Simon He <57086651+Simon-He95@users.noreply.github.com>

* fix: add scrollable support to PopoverContent to prevent overflow (#720)

* feat: implement floating chat window system with performance optimization (#724)

* feat: add mcp sync and modelscope provider #615 (#723)

* wip: add modelscope provider

* feat: add mcp sync to modelscope

* fix: add scrollable support to PopoverContent to prevent overflow (#720)

* feat: implement floating chat window system with performance optimization (#724)

* chore: i18n and format

* feat: better style

* fix: mcp tool display

---------

Co-authored-by: yyhhyyyyyy <yyhhyyyyyy8@gmail.com>

* fix: move_files newPath parse issue (#725)

* fix: move_files newPath 参数计算规则

* fix: move_files 移动前需要判断dest是目录还是文件

* feat: add Claude Opus 4.1 to anthropic default model list (#726)

* feat: Add mcprouter's MCP marketplace api support (#727)

* wip: add mcp market

* feat: mcp market install

* wip: mcp install status sync

* feat: mcp server config mask

* chore: remove working doc

* chore: add translate

* feat: add ESC key to close floating chat window (#728)

* feat: add floating button position persistence with boundary validation (#729)

* feat: add floating button position persistence with boundary validation

* feat: refactor floating button to use electron-window-state

* chore: bump to 0.3.0

* feat: add reasoning_effort parameter support for gpt-oss models (#731)

* feat: add reasoning_effort parameter support for gpt-oss models

- add reasoning effort UI support across all components

* fix: preserve user reasoning effort settings and improve display logic

* fix: artifacts code not streaming (#732)

* fix: artifact react load failed

* chore: remove log

* fix: artifacts code not stream

* fix: format

---------

Co-authored-by: yyhhyyyyyy <yyhhyyyyyy8@gmail.com>
Co-authored-by: hllshiro <40970081+hllshiro@users.noreply.github.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: gongchao <chao.gong@aminer.cn>
Co-authored-by: Simon He <57086651+Simon-He95@users.noreply.github.com>
Co-authored-by: wanna <wanna.w@binarywalk.com>
zerob13 added a commit that referenced this pull request Aug 13, 2025
* fix: add AlertDialogDescription to resolve accessibility warning (#706)

* fix: resolve focus flicker when creating new windows with Ctrl+Shift+N (#707)

* feat: enhance window management by implementing main window ID handling (#709)

* docs: update zhipu developer doc website link (#715)

Co-authored-by: gongchao <chao.gong@aminer.cn>

* refactor: better translate (#716)

* chore: en-us i18n

* chore(i18n): polish ja-JP translations across UI; keep chat.input.placeholder unchanged

* chore(i18n): polish fr-FR translations; keep chat.input.placeholder unchanged

* chore(i18n): refine fr-FR MCP & Settings copy; idiomatic, concise, brand-consistent

* chore(i18n): polish ru-RU translations across UI; keep chat.input.placeholder unchanged

* chore(i18n): polish fa-IR translations across UI; keep chat.input.placeholder unchanged

* chore: fix format

* chore: fix i18n

* chore: lock rolldown-vite version

* feat: add GPT-5 series model support (#717)

* ci(vite): Bundle the main file into a single file to speed up loading. (#718)

* fix(math): parser by upgrade vue-renderer-markdown (#722)

* chore: bump deps (#721)

* chore: bump deps

* fix: rolldown-vite 7.1.0 and duckdb bundle issue

* chore: back to vite

* chore: update electron

* chore: update versions

* fix(math): parser by upgrade vue-renderer-markdown (#722)

* chore: bump deps

---------

Co-authored-by: Simon He <57086651+Simon-He95@users.noreply.github.com>

* fix: add scrollable support to PopoverContent to prevent overflow (#720)

* feat: implement floating chat window system with performance optimization (#724)

* feat: add mcp sync and modelscope provider #615 (#723)

* wip: add modelscope provider

* feat: add mcp sync to modelscope

* fix: add scrollable support to PopoverContent to prevent overflow (#720)

* feat: implement floating chat window system with performance optimization (#724)

* chore: i18n and format

* feat: better style

* fix: mcp tool display

---------

Co-authored-by: yyhhyyyyyy <yyhhyyyyyy8@gmail.com>

* fix: move_files newPath parse issue (#725)

* fix: move_files newPath 参数计算规则

* fix: move_files 移动前需要判断dest是目录还是文件

* feat: add Claude Opus 4.1 to anthropic default model list (#726)

* feat: Add mcprouter's MCP marketplace api support (#727)

* wip: add mcp market

* feat: mcp market install

* wip: mcp install status sync

* feat: mcp server config mask

* chore: remove working doc

* chore: add translate

* feat: add ESC key to close floating chat window (#728)

* feat: add floating button position persistence with boundary validation (#729)

* feat: add floating button position persistence with boundary validation

* feat: refactor floating button to use electron-window-state

* chore: bump to 0.3.0

* feat: add reasoning_effort parameter support for gpt-oss models (#731)

* feat: add reasoning_effort parameter support for gpt-oss models

- add reasoning effort UI support across all components

* fix: preserve user reasoning effort settings and improve display logic

* fix: artifacts code not streaming (#732)

* fix: artifact react load failed

* chore: remove log

* fix: artifacts code not stream

* fix: format

* feat: disable automatic model enabling for better UX (#734)

* feat: sync provider sorting from settings to model selection (#736)

* feat: sync provider sorting from settings to model selection

* feat: refactor ModelSelect to use computed providers for better reactivity

---------

Co-authored-by: yyhhyyyyyy <yyhhyyyyyy8@gmail.com>
Co-authored-by: hllshiro <40970081+hllshiro@users.noreply.github.com>
Co-authored-by: tomsun28 <tomsun28@outlook.com>
Co-authored-by: gongchao <chao.gong@aminer.cn>
Co-authored-by: Simon He <57086651+Simon-He95@users.noreply.github.com>
Co-authored-by: wanna <wanna.w@binarywalk.com>
@zerob13 zerob13 deleted the feature/add-mcprouter-market branch September 21, 2025 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants