feat(mcp): add Qoder configuration

This commit is contained in:
miracle
2026-09-05 22:22:55 +08:00
committed by GitHub
parent 644812fa07
commit 7e06992f3b
13 changed files with 63 additions and 4 deletions
@@ -174,7 +174,7 @@ import { currentExecutableStatementRange, type SqlTextRange } from "@/lib/sql/sq
import { executableStatementRangeCacheForDoc, executableStatementRangeStartingAt, type ExecutableStatementRangeCache } from "@/lib/sql/executableStatementRangeCache";
import { EMPTY_TABLE_COLUMN_TEMPLATE_DATA_TYPE, parseTableColumnTemplateFields, TABLE_COLUMN_TEMPLATE_DATABASE_TYPES, tableColumnTemplateRowsToSettings } from "@/lib/table/tableColumnTemplates";
import { DEFAULT_SQL_VARIABLE_SYNTAX_TOGGLES, normalizeSqlVariableSyntaxOverrides, SQL_VARIABLE_SYNTAX_DATABASE_TYPES, SQL_VARIABLE_SYNTAX_KEYS, SQL_VARIABLE_SYNTAX_TOKENS, type SqlVariableSyntaxOverrides, type SqlVariableSyntaxToggles } from "@/lib/sql/sqlVariableSyntax";
import { buildMcpCherryStudioConfig, buildMcpCodexConfig, buildMcpDeepSeekHarnessConfig, buildMcpJsonConfig, buildMcpOpenCodeConfig, buildMcpPiConfig, buildMcpTraeConfig, buildMcpVsCodeConfig, mcpWebBackendUrl, type McpLaunchConfig } from "@/lib/mcp/mcpConfigTemplates";
import { buildMcpCherryStudioConfig, buildMcpCodexConfig, buildMcpDeepSeekHarnessConfig, buildMcpJsonConfig, buildMcpOpenCodeConfig, buildMcpPiConfig, buildMcpQoderConfig, buildMcpTraeConfig, buildMcpVsCodeConfig, mcpWebBackendUrl, type McpLaunchConfig } from "@/lib/mcp/mcpConfigTemplates";
import { beginMcpStatusRequest, mcpUpdateAvailability } from "@/lib/mcp/mcpUpdateStatus";
import { isMcpPolicyMutationBlocked, MCP_CAPABILITY_ROWS, MCP_EXECUTION_MODE_COLUMNS, mcpExecutionModeFromPolicy, mcpPolicyFieldsForExecutionMode, type McpExecutionMode } from "@/lib/mcp/mcpPolicySelection";
import { isMacOS, isWindows } from "@/lib/backend/platform";
@@ -2118,7 +2118,7 @@ async function exportDebugLogs() {
}
// ---------- MCP Server ----------
type McpConfigTab = "claude" | "cursor" | "codebuddy" | "zcode" | "trae" | "vscode" | "windsurf" | "codex" | "deepseek-harness" | "opencode" | "pi" | "cherry-studio";
type McpConfigTab = "claude" | "cursor" | "codebuddy" | "zcode" | "trae" | "vscode" | "windsurf" | "codex" | "deepseek-harness" | "opencode" | "pi" | "cherry-studio" | "qoder";
type McpCopyKind = "install" | "uninstall" | "http-endpoint" | "http-token" | "http-config" | `${McpConfigTab}-config`;
type McpTransportTab = "stdio" | "http";
@@ -2571,6 +2571,12 @@ const mcpTraeRecommendedConfig = computed(() => {
return buildMcpTraeConfig(mcpLaunchConfig.value, nativeBinPath ?? undefined);
});
const mcpQoderRecommendedConfig = computed(() => {
// Qoder follows TRAE's mcpServers JSON format and has the same Windows path parsing limitation.
const nativeBinPath = !isWeb && isWindows() ? mcpStatus.value?.native_bin_path : undefined;
return buildMcpQoderConfig(mcpLaunchConfig.value, nativeBinPath ?? undefined);
});
const mcpVsCodeRecommendedConfig = computed(() => buildMcpVsCodeConfig(mcpLaunchConfig.value));
const mcpCherryStudioRecommendedConfig = computed(() => buildMcpCherryStudioConfig(mcpLaunchConfig.value));
@@ -8341,6 +8347,7 @@ LIMIT 100;</pre
<TabsTrigger value="opencode" class="settings-mcp-config-tab h-7 flex-none shrink-0 px-2.5">OpenCode</TabsTrigger>
<TabsTrigger value="pi" class="settings-mcp-config-tab h-7 flex-none shrink-0 px-2.5">Pi</TabsTrigger>
<TabsTrigger value="cherry-studio" class="settings-mcp-config-tab h-7 flex-none shrink-0 px-2.5">Cherry Studio</TabsTrigger>
<TabsTrigger value="qoder" class="settings-mcp-config-tab h-7 flex-none shrink-0 px-2.5">Qoder</TabsTrigger>
</TabsList>
<TabsContent value="claude" class="m-0">
@@ -8517,6 +8524,21 @@ LIMIT 100;</pre
</div>
</div>
</TabsContent>
<TabsContent value="qoder" class="m-0">
<div class="space-y-2">
<div class="rounded-md border bg-muted/20 px-3 py-2 text-xs text-muted-foreground">
{{ t("settings.mcpQoderConfigPath") }}
</div>
<div class="relative rounded-md border bg-background p-3">
<pre class="overflow-x-auto whitespace-pre text-xs leading-relaxed"><code>{{ mcpQoderRecommendedConfig }}</code></pre>
<Button type="button" variant="outline" size="icon" class="absolute right-2 top-2 h-7 w-7" :title="t('common.copy')" @click="copyMcpText('qoder-config', mcpQoderRecommendedConfig)">
<CheckCircle2 v-if="mcpCopied === 'qoder-config'" class="h-3.5 w-3.5 text-green-500" />
<Copy v-else class="h-3.5 w-3.5" />
</Button>
</div>
</div>
</TabsContent>
</Tabs>
</div>
+1
View File
@@ -7150,6 +7150,7 @@ export default {
mcpCodeBuddyConfigPath: "CodeBuddy Code can use ~/.codebuddy/.mcp.json globally or .mcp.json in the project.",
mcpZCodeConfigPath: "ZCode: Settings > MCP Servers > New MCP Server > Full configuration; choose the User or Workspace scope, then paste the JSON configuration.",
mcpTraeConfigPath: "TRAE: Settings > MCP > Add > Add Manually, then paste the JSON configuration.",
mcpQoderConfigPath: "Qoder: Settings > MCP > Add Manually, then paste the JSON configuration.",
mcpCherryStudioConfigPath: "Cherry Studio: Settings > MCP Servers > Add Server > Import JSON, then paste the configuration.",
mcpVsCodeConfigPath: "VS Code/Copilot can use .vscode/mcp.json in the workspace or mcp.json in the user profile.",
mcpWindsurfConfigPath: "Windsurf can use ~/.codeium/windsurf/mcp_config.json.",
+1
View File
@@ -6764,6 +6764,7 @@ export default withEnglishFallback({
mcpCodeBuddyConfigPath: "CodeBuddy Code puede usar ~/.codebuddy/.mcp.json globalmente o .mcp.json en el proyecto.",
mcpZCodeConfigPath: "ZCode: Configuración > Servidores MCP > Nuevo servidor MCP > Configuración completa; elige el ámbito Usuario o Espacio de trabajo y pega la configuración JSON.",
mcpTraeConfigPath: "TRAE: Configuración > MCP > Agregar > Agregar manualmente; luego pega la configuración JSON.",
mcpQoderConfigPath: "Qoder: Configuración > MCP > Agregar manualmente; luego pega la configuración JSON.",
mcpCherryStudioConfigPath: "Cherry Studio: Configuración > Servidores MCP > Agregar servidor > Importar JSON; luego pega la configuración.",
mcpVsCodeConfigPath: "VS Code/Copilot puede usar .vscode/mcp.json en el espacio de trabajo o mcp.json en el perfil de usuario.",
mcpWindsurfConfigPath: "Windsurf puede usar ~/.codeium/windsurf/mcp_config.json.",
+1
View File
@@ -6764,6 +6764,7 @@ export default withEnglishFallback({
mcpCodeBuddyConfigPath: "CodeBuddy Code può usare ~/.codebuddy/.mcp.json globalmente oppure .mcp.json a livello di progetto.",
mcpZCodeConfigPath: "ZCode: Impostazioni > Server MCP > Nuovo server MCP > Configurazione completa; scegli l'ambito Utente o Area di lavoro, quindi incolla la configurazione JSON.",
mcpTraeConfigPath: "TRAE: Impostazioni > MCP > Aggiungi > Aggiungi manualmente, poi incolla la configurazione JSON.",
mcpQoderConfigPath: "Qoder: Impostazioni > MCP > Aggiungi manualmente, poi incolla la configurazione JSON.",
mcpCherryStudioConfigPath: "Cherry Studio: Impostazioni > Server MCP > Aggiungi server > Importa JSON, quindi incolla la configurazione.",
mcpVsCodeConfigPath: "VS Code/Copilot può usare .vscode/mcp.json nell'area di lavoro o mcp.json nel profilo utente.",
mcpWindsurfConfigPath: "Windsurf può usare ~/.codeium/windsurf/mcp_config.json.",
+1
View File
@@ -6771,6 +6771,7 @@ export default withEnglishFallback({
mcpCodeBuddyConfigPath: "CodeBuddy Codeはグローバル ~/.codebuddy/.mcp.json またはプロジェクトレベルの .mcp.json を使用できます。",
mcpZCodeConfigPath: "ZCode:設定 > MCP サーバー > 新しい MCP サーバー > 完全な設定を開き、ユーザーまたはワークスペースのスコープを選択して JSON 設定を貼り付けます。",
mcpTraeConfigPath: "TRAE: 設定 > MCP > 追加 > 手動で追加 からJSON設定を貼り付けます。",
mcpQoderConfigPath: "Qoder: 設定 > MCP > 手動で追加 からJSON設定を貼り付けます。",
mcpCherryStudioConfigPath: "Cherry Studio: 設定 > MCPサーバー > サーバーを追加 > JSONをインポート から設定を貼り付けます。",
mcpVsCodeConfigPath: "VS Code/Copilotはワークスペースの .vscode/mcp.json またはユーザープロファイルの mcp.json を使用できます。",
mcpWindsurfConfigPath: "Windsurfは ~/.codeium/windsurf/mcp_config.json を使用できます。",
+1
View File
@@ -6517,6 +6517,7 @@ export default withEnglishFallback({
mcpCodeBuddyConfigPath: "CodeBuddy Code는 전역 ~/.codebuddy/.mcp.json 또는 프로젝트의 .mcp.json을 사용할 수 있습니다.",
mcpZCodeConfigPath: "ZCode: 설정 > MCP 서버 > 새 MCP 서버 > 전체 구성에서 사용자 또는 작업 영역 범위를 선택한 다음 JSON 구성을 붙여넣으세요.",
mcpTraeConfigPath: "TRAE: 설정 > MCP > 추가 > 수동 추가 후 JSON 설정을 붙여넣으세요.",
mcpQoderConfigPath: "Qoder: 설정 > MCP > 수동 추가 후 JSON 설정을 붙여넣으세요.",
mcpCherryStudioConfigPath: "Cherry Studio: 설정 > MCP 서버 > 서버 추가 > JSON 가져오기 후 설정을 붙여넣으세요.",
mcpVsCodeConfigPath: "VS Code/Copilot은 작업 영역의 .vscode/mcp.json 또는 사용자 프로필의 mcp.json을 사용할 수 있습니다.",
mcpWindsurfConfigPath: "Windsurf는 ~/.codeium/windsurf/mcp_config.json을 사용할 수 있습니다.",
+1
View File
@@ -6766,6 +6766,7 @@ export default withEnglishFallback({
mcpCodeBuddyConfigPath: "O CodeBuddy Code pode usar ~/.codebuddy/.mcp.json globalmente ou .mcp.json no nível do projeto.",
mcpZCodeConfigPath: "ZCode: Configurações > Servidores MCP > Novo servidor MCP > Configuração completa; escolha o escopo Usuário ou Espaço de trabalho e cole a configuração JSON.",
mcpTraeConfigPath: "TRAE: Configurações > MCP > Adicionar > Adicionar manualmente; depois cole a configuração JSON.",
mcpQoderConfigPath: "Qoder: Configurações > MCP > Adicionar manualmente; depois cole a configuração JSON.",
mcpCherryStudioConfigPath: "Cherry Studio: Configurações > Servidores MCP > Adicionar servidor > Importar JSON; depois cole a configuração.",
mcpVsCodeConfigPath: "O VS Code/Copilot pode usar .vscode/mcp.json no workspace ou mcp.json no perfil do usuário.",
mcpWindsurfConfigPath: "O Windsurf pode usar ~/.codeium/windsurf/mcp_config.json.",
+1
View File
@@ -7138,6 +7138,7 @@ export default withEnglishFallback({
mcpCodeBuddyConfigPath: "CodeBuddy Code, genel olarak ~/.codebuddy/.mcp.json ya da projede .mcp.json kullanabilir.",
mcpZCodeConfigPath: "ZCode: Ayarlar > MCP Sunucuları > Yeni MCP Sunucusu > Tam yapılandırma; Kullanıcı ya da Çalışma Alanı kapsamını seçip JSON yapılandırmasını yapıştırın.",
mcpTraeConfigPath: "TRAE: Ayarlar > MCP > Ekle > Elle Ekle, ardından JSON yapılandırmasını yapıştırın.",
mcpQoderConfigPath: "Qoder: Ayarlar > MCP > Elle Ekle, ardından JSON yapılandırmasını yapıştırın.",
mcpCherryStudioConfigPath: "Cherry Studio: Ayarlar > MCP Sunucuları > Sunucu Ekle > JSON İçe Aktar, ardından yapılandırmayı yapıştırın.",
mcpVsCodeConfigPath: "VS Code/Copilot, çalışma alanında .vscode/mcp.json ya da kullanıcı profilinde mcp.json kullanabilir.",
mcpWindsurfConfigPath: "Windsurf, ~/.codeium/windsurf/mcp_config.json kullanabilir.",
+1
View File
@@ -7135,6 +7135,7 @@ export default withEnglishFallback({
mcpCodeBuddyConfigPath: "CodeBuddy Code 可使用全局 ~/.codebuddy/.mcp.json 或项目级 .mcp.json。",
mcpZCodeConfigPath: "ZCode:设置 > MCP 服务器 > 新建 MCP 服务器 > 完整配置,选择用户或工作区作用域后粘贴 JSON 配置。",
mcpTraeConfigPath: "TRAE:设置 > MCP > 添加 > 手动添加,然后粘贴 JSON 配置。",
mcpQoderConfigPath: "Qoder:设置 > MCP > 手动添加,然后粘贴 JSON 配置。",
mcpCherryStudioConfigPath: "Cherry Studio:设置 > MCP 服务器 > 添加服务器 > 导入 JSON,然后粘贴配置。",
mcpVsCodeConfigPath: "VS Code/Copilot 可放在工作区 .vscode/mcp.json 或用户配置文件 mcp.json。",
mcpWindsurfConfigPath: "Windsurf 可放在 ~/.codeium/windsurf/mcp_config.json。",
+1
View File
@@ -6099,6 +6099,7 @@ export default withEnglishFallback({
mcpCodeBuddyConfigPath: "CodeBuddy Code 可使用全域 ~/.codebuddy/.mcp.json 或專案級 .mcp.json。",
mcpZCodeConfigPath: "ZCode:設定 > MCP 伺服器 > 新增 MCP 伺服器 > 完整設定,選擇使用者或工作區範圍後貼上 JSON 設定。",
mcpTraeConfigPath: "TRAE:設定 > MCP > 新增 > 手動新增,然後貼上 JSON 設定。",
mcpQoderConfigPath: "Qoder:設定 > MCP > 手動新增,然後貼上 JSON 設定。",
mcpCherryStudioConfigPath: "Cherry Studio:設定 > MCP 伺服器 > 新增伺服器 > 匯入 JSON,然後貼上設定。",
mcpVsCodeConfigPath: "VS Code/Copilot 可放在工作區 .vscode/mcp.json 或使用者設定檔 mcp.json。",
mcpWindsurfConfigPath: "Windsurf 可放在 ~/.codeium/windsurf/mcp_config.json。",
@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { buildMcpCherryStudioConfig, buildMcpCodexConfig, buildMcpDeepSeekHarnessConfig, buildMcpJsonConfig, buildMcpOpenCodeConfig, buildMcpPiConfig, buildMcpTraeConfig, buildMcpVsCodeConfig, mcpWebBackendUrl } from "@/lib/mcp/mcpConfigTemplates";
import { buildMcpCherryStudioConfig, buildMcpCodexConfig, buildMcpDeepSeekHarnessConfig, buildMcpJsonConfig, buildMcpOpenCodeConfig, buildMcpPiConfig, buildMcpQoderConfig, buildMcpTraeConfig, buildMcpVsCodeConfig, mcpWebBackendUrl } from "@/lib/mcp/mcpConfigTemplates";
describe("MCP config templates", () => {
it("builds the standard mcpServers JSON used by Claude, Cursor, TRAE, and Windsurf", () => {
@@ -66,6 +66,19 @@ describe("MCP config templates", () => {
});
});
it("builds the Qoder config with the same launch shape as TRAE", () => {
const launch = {
command: "C:\\Program Files\\nodejs\\node.exe",
args: ["C:\\dbx\\mcp\\dist\\index.js"],
env: { DBX_DATA_DIR: "D:\\DBX Data" },
};
const nativeBinPath = "C:\\Users\\supervisor\\AppData\\Roaming\\npm\\node_modules\\@dbx-app\\mcp-win32-x64\\bin\\dbx-mcp.exe";
expect(JSON.parse(buildMcpQoderConfig(launch, nativeBinPath))).toEqual({
mcpServers: { dbx: { command: nativeBinPath, env: launch.env } },
});
});
it("includes Web runtime settings without restoring permission environment variables", () => {
const launch = {
command: "dbx-mcp-server",
@@ -123,10 +123,11 @@ describe("MCP policy settings state", () => {
expect(tabsSource).toContain("overscroll-x-contain");
expect(tabsSource).not.toContain("flex-wrap");
expect(tabsSource).not.toContain("grid-cols-");
expect(tabsSource.match(/flex-none shrink-0/g)).toHaveLength(12);
expect(tabsSource.match(/flex-none shrink-0/g)).toHaveLength(13);
expect(tabsSource).toContain('<TabsTrigger value="deepseek-harness"');
expect(tabsSource).toContain('<TabsTrigger value="codebuddy"');
expect(tabsSource).toContain('<TabsTrigger value="zcode"');
expect(tabsSource).toContain('<TabsTrigger value="qoder"');
expect(tabsSource).not.toContain("min-w-0 px-");
const codeBuddyStart = settingsDialogSource.indexOf('<TabsContent value="codebuddy"', tabsEnd);
@@ -148,6 +149,16 @@ describe("MCP policy settings state", () => {
expect(zCodeSource).toContain("settings.mcpZCodeConfigPath");
expect(zCodeSource).toContain("mcpJsonRecommendedConfig");
expect(zCodeSource).toContain("copyMcpText('zcode-config', mcpJsonRecommendedConfig)");
const qoderStart = settingsDialogSource.indexOf('<TabsContent value="qoder"', tabsEnd);
const qoderEnd = settingsDialogSource.indexOf("</TabsContent>", qoderStart);
const qoderSource = settingsDialogSource.slice(qoderStart, qoderEnd);
expect(qoderStart).toBeGreaterThan(tabsEnd);
expect(qoderEnd).toBeGreaterThan(qoderStart);
expect(qoderSource).toContain("settings.mcpQoderConfigPath");
expect(qoderSource).toContain("mcpQoderRecommendedConfig");
expect(qoderSource).toContain("copyMcpText('qoder-config', mcpQoderRecommendedConfig)");
});
});
@@ -44,6 +44,10 @@ export function buildMcpTraeConfig(config?: McpLaunchConfig, nativeBinPath?: str
return buildMcpJsonConfig(nativeBinPath ? { command: nativeBinPath, env: config?.env } : config);
}
export function buildMcpQoderConfig(config?: McpLaunchConfig, nativeBinPath?: string): string {
return buildMcpTraeConfig(config, nativeBinPath);
}
export function buildMcpVsCodeConfig(config?: McpLaunchConfig): string {
const dbx: Record<string, unknown> = {
type: "stdio",