Skip to content
Open
20 changes: 13 additions & 7 deletions apps/desktop/src/components/editor/EditorSettingsDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -1920,7 +1920,7 @@
// 安装成功后刷新状态
await refreshMcpStatus();
} catch (e: any) {
mcpInstallMessage.value = e?.message || String(e);
mcpInstallMessage.value = translateBackendError(t, e);
mcpInstallError.value = true;
} finally {
mcpInstalling.value = false;
Expand All @@ -1942,7 +1942,7 @@
mcpInstallMessage.value = await uninstallMcpServer();
await refreshMcpStatus();
} catch (e: any) {
mcpInstallMessage.value = t("settings.mcpUninstallFailed", { error: e?.message || String(e) });
mcpInstallMessage.value = t("settings.mcpUninstallFailed", { error: translateBackendError(t, e) });
mcpInstallError.value = true;
} finally {
mcpUninstalling.value = false;
Expand Down Expand Up @@ -2915,7 +2915,7 @@
const aiCliMcpNeedsInstall = computed(() => aiIsCliProvider.value && (!mcpStatus.value || !mcpStatus.value.installed));
const aiCliMcpCanInstall = computed(() => {
const status = mcpStatus.value;
return !mcpInstalling.value && !mcpUninstalling.value && !!status?.npm_available && (!status.installed || status.update_available);
return !mcpInstalling.value && !mcpUninstalling.value && !!status?.runtime_available && (!status.installed || status.update_available);
});
const aiCliMcpActionLabel = computed(() => {
if (!mcpStatus.value?.installed) return t("settings.mcpInstallButton");
Expand Down Expand Up @@ -6348,15 +6348,18 @@

<div v-if="!isWeb" class="space-y-2">
<Label>{{ mcpStatus?.installed ? t("settings.mcpUpdateCommand") : t("settings.mcpInstallCommand") }}</Label>
<div class="flex min-w-0 items-center gap-2">
<div v-if="mcpStatus?.installed && mcpStatus?.managed_automatically === false" class="rounded-md border bg-muted/20 px-3 py-2 text-xs text-muted-foreground">
{{ t("settings.mcpManualManagementHint") }}
</div>
<div v-else class="flex min-w-0 items-center gap-2">
<div class="min-w-0 flex-1 overflow-x-auto rounded-md border bg-background px-3 py-2 font-mono text-xs whitespace-nowrap">
{{ mcpCommand }}
</div>
<Button type="button" variant="outline" size="icon" :title="t('common.copy')" @click="copyMcpText('install', mcpCommand)">
<CheckCircle2 v-if="mcpCopied === 'install'" class="h-4 w-4 text-green-500" />
<Copy v-else class="h-4 w-4" />
</Button>
<Button type="button" variant="default" :disabled="mcpInstalling || mcpUninstalling || !mcpStatus?.npm_available || (mcpStatus?.installed && !mcpStatus?.update_available)" @click="installMcp">
<Button type="button" variant="default" :disabled="mcpInstalling || mcpUninstalling || !mcpStatus?.runtime_available || mcpStatus?.managed_automatically === false || (mcpStatus?.installed && !mcpStatus?.update_available)" @click="installMcp">
<Loader2 v-if="mcpInstalling" class="mr-2 h-4 w-4 animate-spin" />
<CheckCircle2 v-if="!mcpInstalling && mcpStatus?.installed && !mcpStatus?.update_available" class="mr-2 h-4 w-4" />
{{ mcpInstalling ? t("settings.mcpInstalling") : !mcpStatus?.installed ? t("settings.mcpInstallButton") : mcpStatus?.update_available ? t("settings.mcpUpdateButton") : t("settings.mcpUpToDate") }}
Expand All @@ -6372,16 +6375,19 @@

<div v-if="!isWeb && mcpStatus?.installed" class="space-y-2">
<Label>{{ t("settings.mcpUninstallCommand") }}</Label>
<div class="flex min-w-0 items-center gap-2">
<div v-if="mcpStatus?.managed_automatically === false" class="rounded-md border bg-muted/20 px-3 py-2 text-xs text-muted-foreground">
{{ t("settings.mcpManualManagementHint") }}
</div>
<div v-else class="flex min-w-0 items-center gap-2">
<div class="min-w-0 flex-1 overflow-x-auto rounded-md border bg-background px-3 py-2 font-mono text-xs whitespace-nowrap">
{{ mcpUninstallCommand }}
</div>
<Button type="button" variant="outline" size="icon" :title="t('common.copy')" @click="copyMcpText('uninstall', mcpUninstallCommand)">
<CheckCircle2 v-if="mcpCopied === 'uninstall'" class="h-4 w-4 text-green-500" />
<Copy v-else class="h-4 w-4" />
</Button>
<Button type="button" variant="outline" class="text-destructive hover:text-destructive" :disabled="mcpInstalling || mcpUninstalling || !mcpStatus.npm_available" @click="uninstallMcp">
<Button type="button" variant="outline" class="text-destructive hover:text-destructive" :disabled="mcpInstalling || mcpUninstalling || !mcpStatus.runtime_available || mcpStatus.managed_automatically === false" @click="uninstallMcp">
<Loader2 v-if="mcpUninstalling" class="mr-2 h-4 w-4 animate-spin" />

Check failure on line 6390 in apps/desktop/src/components/editor/EditorSettingsDialog.vue

View workflow job for this annotation

GitHub Actions / frontend

This comparison appears to be unintentional because the types 'true' and 'false' have no overlap.
<Trash2 v-else class="mr-2 h-4 w-4" />
{{ mcpUninstalling ? t("settings.mcpUninstalling") : t("settings.mcpUninstallButton") }}
</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ function deferred<T>(): Deferred<T> {
function makeStatus(update_available: boolean, overrides: Partial<McpServerStatus> = {}): McpServerStatus {
return {
installed: true,
runtime_available: true,
npm_available: true,
node_path: null,
node_version: null,
Expand Down
4 changes: 4 additions & 0 deletions apps/desktop/src/i18n/backend-errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ const patterns: [RegExp, string][] = [
// Message queues (crates/dbx-core/src/mq/adapters/kafka.rs)
[/^Kafka does not support unloading topics$/, "mqClients.unloadTopicUnsupportedKafka"],

// MCP server management (src-tauri/src/commands/mcp.rs)
[/^DBX MCP is installed but its package manager could not be confirmed[\s\S]*$/, "settings.mcpUnknownPackageManager"],
[/^npm CLI is not available in this environment$/, "settings.mcpNpmCliUnavailable"],

// Filesystem (src-tauri/src/commands/fs_open.rs)
[/^file does not exist: (.+)$/, "common.fileNotFound"],

Expand Down
3 changes: 3 additions & 0 deletions apps/desktop/src/i18n/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6201,6 +6201,9 @@ export default {
mcpInstallCommand: "Install command",
mcpUpdateCommand: "Upgrade command",
mcpUninstallCommand: "Uninstall command",
mcpManualManagementHint: "DBX MCP is installed but its package manager could not be confirmed. Please update or remove it with the package manager you used.",
mcpUnknownPackageManager: "DBX MCP is installed but its package manager could not be confirmed (Yarn, Bun, or a manual copy). DBX does not run npm/pnpm management commands against it; please update or remove it with the package manager you used.",
mcpNpmCliUnavailable: "npm CLI is not available in this environment.",
mcpInstallButton: "Install",
mcpUpdateButton: "Upgrade",
mcpUpToDate: "Up to date",
Expand Down
3 changes: 3 additions & 0 deletions apps/desktop/src/i18n/locales/zh-CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6190,6 +6190,9 @@ export default withEnglishFallback({
mcpInstallCommand: "安装命令",
mcpUpdateCommand: "升级命令",
mcpUninstallCommand: "卸载命令",
mcpManualManagementHint: "已检测到 DBX MCP 安装,但无法确认其包管理器来源。请用你当初使用的包管理器手动更新/卸载。",
mcpUnknownPackageManager: "已检测到 DBX MCP 安装,但无法确认其包管理器来源(可能是 Yarn、Bun 或手动复制)。DBX 不会对其执行 npm/pnpm 管理命令,请用你当初使用的包管理器手动更新/卸载。",
mcpNpmCliUnavailable: "当前环境中没有可用的 npm CLI。",
mcpInstallButton: "安装",
mcpUpdateButton: "升级",
mcpUpToDate: "已是最新",
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src/lib/backend/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3929,8 +3929,9 @@
}

export async function checkMcpServerStatus(): Promise<import("@/lib/backend/tauri").McpServerStatus> {
return {

Check failure on line 3932 in apps/desktop/src/lib/backend/http.ts

View workflow job for this annotation

GitHub Actions / frontend

Property 'managed_automatically' is missing in type '{ installed: false; runtime_available: false; npm_available: false; node_path: null; node_version: null; current_version: null; latest_version: null; update_available: false; bin_path: null; ... 6 more ...; error: string; }' but required in type 'McpServerStatus'.
installed: false,
runtime_available: false,
npm_available: false,
node_path: null,
node_version: null,
Expand Down
2 changes: 2 additions & 0 deletions apps/desktop/src/lib/backend/tauri.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2023,6 +2023,7 @@ export interface UpdateDownloadProgress {

export interface McpServerStatus {
installed: boolean;
runtime_available: boolean;
npm_available: boolean;
node_path: string | null;
node_version: string | null;
Expand All @@ -2032,6 +2033,7 @@ export interface McpServerStatus {
bin_path: string | null;
native_bin_path: string | null;
script_path: string | null;
managed_automatically: boolean;
data_dir: string | null;
install_command: string;
update_command: string;
Expand Down
Loading
Loading