diff --git a/apps/desktop/src/App.vue b/apps/desktop/src/App.vue
index a4b58c11cc..03e774aa65 100644
--- a/apps/desktop/src/App.vue
+++ b/apps/desktop/src/App.vue
@@ -2652,8 +2652,10 @@ onUnmounted(() => {
:initial-section="settingsInitialSection"
:navigation-request-id="settingsNavigationRequestId"
:app-version="appVersion"
+ :checking-updates="checkingUpdates"
class="flex-1 min-h-0"
@update:open="(open: boolean) => (open ? activateSettingsPage() : closeSettingsPage())"
+ @check-updates="checkUpdates()"
/>
();
const emit = defineEmits<{
"update:open": [value: boolean];
+ "check-updates": [];
}>();
const isSettingsPage = computed(() => props.variant === "page");
@@ -1723,7 +1726,7 @@ async function exportDebugLogs() {
// ---------- MCP Server ----------
type McpConfigTab = "claude" | "cursor" | "trae" | "vscode" | "windsurf" | "codex" | "opencode" | "cherry-studio";
-type McpCopyKind = "install" | `${McpConfigTab}-config`;
+type McpCopyKind = "install" | "uninstall" | `${McpConfigTab}-config`;
const mcpStatus = ref(null);
const mcpStatusLoading = ref(false);
@@ -1736,6 +1739,7 @@ const mcpPolicyLoading = ref(false);
const mcpPolicySaving = ref(false);
const mcpPolicyLoadError = ref("");
const mcpInstalling = ref(false);
+const mcpUninstalling = ref(false);
const mcpInstallMessage = ref("");
const mcpInstallError = ref(false);
const mcpExecutionMode = computed(() => mcpExecutionModeFromPolicy(settingsStore.mcpGlobalPolicy));
@@ -1854,6 +1858,8 @@ const mcpCommand = computed(() => {
return mcpStatus.value.installed ? mcpStatus.value.update_command : mcpStatus.value.install_command;
});
+const mcpUninstallCommand = computed(() => mcpStatus.value?.uninstall_command || "npm uninstall -g @dbx-app/mcp-server");
+
async function refreshMcpStatus() {
if (mcpStatusLoading.value) return;
mcpStatusLoading.value = true;
@@ -1888,7 +1894,7 @@ async function copyMcpText(kind: McpCopyKind, value: string) {
}
async function installMcp() {
- if (mcpInstalling.value) return;
+ if (mcpInstalling.value || mcpUninstalling.value) return;
mcpInstalling.value = true;
mcpInstallMessage.value = "";
mcpInstallError.value = false;
@@ -1911,6 +1917,27 @@ async function installMcp() {
}
}
+async function uninstallMcp() {
+ if (mcpInstalling.value || mcpUninstalling.value || !mcpStatus.value?.installed) return;
+ if (!window.confirm(t("settings.mcpUninstallConfirm"))) return;
+ mcpUninstalling.value = true;
+ mcpInstallMessage.value = "";
+ mcpInstallError.value = false;
+ try {
+ mcpInstallMessage.value = await uninstallMcpServer();
+ await refreshMcpStatus();
+ } catch (e: any) {
+ mcpInstallMessage.value = t("settings.mcpUninstallFailed", { error: e?.message || String(e) });
+ mcpInstallError.value = true;
+ } finally {
+ mcpUninstalling.value = false;
+ window.setTimeout(() => {
+ mcpInstallMessage.value = "";
+ mcpInstallError.value = false;
+ }, 3000);
+ }
+}
+
// ---------- WebDAV Sync ----------
const webdavEndpoint = ref(localStorage.getItem("dbx-webdav-endpoint") || "");
const webdavUsername = ref(localStorage.getItem("dbx-webdav-username") || "");
@@ -2873,7 +2900,7 @@ const aiSupportsAnthropicApiStyle = computed(() => aiEditProvider.value === "cus
const aiCliMcpNeedsInstall = computed(() => aiIsCliProvider.value && (!mcpStatus.value || !mcpStatus.value.installed));
const aiCliMcpCanInstall = computed(() => {
const status = mcpStatus.value;
- return !mcpInstalling.value && !!status?.npm_available && (!status.installed || status.update_available);
+ return !mcpInstalling.value && !mcpUninstalling.value && !!status?.npm_available && (!status.installed || status.update_available);
});
const aiCliMcpActionLabel = computed(() => {
if (!mcpStatus.value?.installed) return t("settings.mcpInstallButton");
@@ -6273,7 +6300,7 @@ onUnmounted(() => {
-
+
+
+
+
+ {{ mcpUninstallCommand }}
+
+
+
+
+
+
+
+
+ {{ mcpUninstalling ? t("settings.mcpUninstalling") : t("settings.mcpUninstallButton") }}
+
+
+
+
{{ t("settings.mcpConfigOptionsHint") }}
@@ -6611,7 +6656,7 @@ onUnmounted(() => {
-
+
diff --git a/apps/desktop/src/components/settings/ChangelogPanel.vue b/apps/desktop/src/components/settings/ChangelogPanel.vue
index fd80678aa6..d52358eb9f 100644
--- a/apps/desktop/src/components/settings/ChangelogPanel.vue
+++ b/apps/desktop/src/components/settings/ChangelogPanel.vue
@@ -1,7 +1,7 @@