feat(mcp): detect and authorize macOS Keychain access for dbx-mcp

This commit is contained in:
t8y2
2026-10-16 18:42:35 +08:00
parent c8a16708ca
commit 5cecc55613
21 changed files with 367 additions and 1 deletions
@@ -153,6 +153,8 @@ import {
loadCcSwitchAiConfigs,
loadMagpieAiConfigs,
checkMcpServerStatus,
checkMcpKeychainAccess,
authorizeMcpKeychain,
installMcpServer,
installNativeMcpServer,
uninstallMcpServer,
@@ -210,6 +212,7 @@ import {
type WebMcpHttpStatus,
type WebMcpHttpSettings,
type McpServerStatus,
type McpKeychainAccess,
type SnippetProvider,
type SnippetSyncConfig,
type SyncSelection,
@@ -3892,6 +3895,11 @@ type McpManagementTab = "access" | "permissions";
const mcpStatus = ref<McpServerStatus | null>(null);
const mcpStatusLoading = ref(false);
const mcpStatusError = ref("");
const mcpKeychainAccess = ref<McpKeychainAccess | null>(null);
const mcpKeychainAuthorizing = ref(false);
const mcpKeychainMessage = ref("");
const mcpKeychainMessageError = ref(false);
const mcpKeychainNeedsAuthorization = computed(() => mcpKeychainAccess.value === "needs_authorization");
const mcpCopied = ref<"" | McpCopyKind>("");
const mcpConfigTab = ref<McpConfigTab>("claude");
const mcpTransportTab = ref<McpTransportTab>("stdio");
@@ -4556,7 +4564,7 @@ const mcpWorkBuddyRecommendedConfig = computed(() => buildMcpWorkBuddyConfig(mcp
const mcpStatusTone = computed<"ok" | "warning" | "muted">(() => {
if (!mcpStatus.value) return "muted";
if (!mcpStatus.value.installed || mcpStatus.value.update_available || mcpStatus.value.error) return "warning";
if (!mcpStatus.value.installed || mcpStatus.value.update_available || mcpStatus.value.error || mcpKeychainNeedsAuthorization.value) return "warning";
return "ok";
});
@@ -4566,6 +4574,7 @@ const mcpStatusLabel = computed(() => {
if (!mcpStatus.value) return t("settings.mcpStatusUnknown");
if (!mcpStatus.value.installed) return t("settings.mcpNotInstalled");
if (mcpStatus.value.update_available) return t("settings.mcpUpdateAvailable");
if (mcpKeychainNeedsAuthorization.value) return t("settings.mcpKeychainBadge");
return t("settings.mcpReady");
});
@@ -4602,6 +4611,40 @@ async function refreshMcpStatus() {
} finally {
mcpStatusLoading.value = false;
}
await refreshMcpKeychainAccess();
}
// macOS only: an MCP client launches dbx-mcp in the background, where Keychain cannot prompt.
// A missing or stale authorization therefore surfaces only as an opaque tool error in the client.
async function refreshMcpKeychainAccess() {
if (!mcpStatus.value?.installed) {
mcpKeychainAccess.value = null;
return;
}
try {
mcpKeychainAccess.value = await checkMcpKeychainAccess();
} catch {
mcpKeychainAccess.value = "unknown";
}
}
async function authorizeMcpKeychainAccess() {
if (mcpKeychainAuthorizing.value) return;
mcpKeychainAuthorizing.value = true;
mcpKeychainMessage.value = "";
mcpKeychainMessageError.value = false;
try {
await authorizeMcpKeychain();
await refreshMcpKeychainAccess();
// The command re-verifies from a fresh process, so a stale answer here means the choice was not retained.
mcpKeychainMessageError.value = mcpKeychainNeedsAuthorization.value;
mcpKeychainMessage.value = mcpKeychainNeedsAuthorization.value ? t("settings.mcpKeychainNotRetained") : t("settings.mcpKeychainAuthorized");
} catch (e: any) {
mcpKeychainMessage.value = t("settings.mcpKeychainAuthorizeFailed", { error: e?.message || String(e) });
mcpKeychainMessageError.value = true;
} finally {
mcpKeychainAuthorizing.value = false;
}
}
async function copyMcpText(kind: McpCopyKind, value: string) {
@@ -12086,6 +12129,27 @@ LIMIT 100;</pre>
</TabsContent>
<TabsContent value="stdio" class="m-0 space-y-4">
<div
v-if="!isWeb && (mcpKeychainNeedsAuthorization || mcpKeychainMessage)"
class="space-y-2 rounded-md border px-3 py-2.5 text-xs"
:class="mcpKeychainMessage && !mcpKeychainMessageError ? 'border-green-500/40 bg-green-500/10 text-green-700 dark:text-green-300' : 'border-amber-500/40 bg-amber-500/10 text-amber-800 dark:text-amber-200'"
>
<template v-if="mcpKeychainNeedsAuthorization">
<div class="flex items-center gap-1.5 font-medium">
<AlertTriangle class="h-3.5 w-3.5 shrink-0" />
{{ t("settings.mcpKeychainTitle") }}
</div>
<p class="leading-relaxed">{{ t("settings.mcpKeychainDescription") }}</p>
<div class="flex flex-wrap items-center gap-2">
<Button type="button" size="sm" :disabled="mcpKeychainAuthorizing" @click="authorizeMcpKeychainAccess">
<Loader2 v-if="mcpKeychainAuthorizing" class="mr-1 h-3 w-3 animate-spin" />
{{ mcpKeychainAuthorizing ? t("settings.mcpKeychainAuthorizing") : t("settings.mcpKeychainAuthorizeButton") }}
</Button>
<span class="text-[11px] opacity-80">{{ t("settings.mcpKeychainAlwaysAllowHint") }}</span>
</div>
</template>
<p v-if="mcpKeychainMessage" class="select-text leading-relaxed">{{ mcpKeychainMessage }}</p>
</div>
<div v-if="!isWeb" class="grid gap-3 sm:grid-cols-2">
<div class="rounded-md border p-3">
<div class="text-xs font-medium uppercase text-muted-foreground">
+9
View File
@@ -8326,6 +8326,15 @@ export default withEnglishFallback({
mcpStatusError: "Yoxlama uğursuz oldu",
mcpReady: "Hazırdır",
mcpNotInstalled: "Quraşdırılmayıb",
mcpKeychainBadge: "Açar zənciri icazəsi lazımdır",
mcpKeychainTitle: "Açar zəncirinə giriş üçün icazə tələb olunur",
mcpKeychainDescription: "MCP müştəriləri dbx-mcp-ni arxa planda işə salır, orada macOS açar zənciri sorğusunu göstərə bilmir, ona görə DBX məlumat şifrələmə açarını oxuya bilmir və bütün MCP alət çağırışları SECRET_KEY_UNAVAILABLE ilə uğursuz olur. Burada bir dəfə icazə verin.",
mcpKeychainAuthorizeButton: "Açar zəncirinə girişə icazə ver",
mcpKeychainAuthorizing: "İcazə gözlənilir...",
mcpKeychainAlwaysAllowHint: 'macOS soruşanda "Həmişə icazə ver" seçin ("İcazə ver" yox).',
mcpKeychainAuthorized: "Açar zəncirinə giriş icazəsi verildi. Qüvvəyə minməsi üçün MCP müştərisini yenidən başladın.",
mcpKeychainNotRetained: 'macOS icazəni saxlamadı. Yenidən işə salın və "Həmişə icazə ver" seçin ("İcazə ver" yox). Giriş açar zənciri kilidlidirsə, əvvəlcə kilidini açın.',
mcpKeychainAuthorizeFailed: "Açar zənciri icazəsi uğursuz oldu: {error}",
mcpUpdateAvailable: "Yeniləmə mövcuddur",
mcpCurrent: "Cari versiya",
mcpLatest: "Ən son versiya",
+9
View File
@@ -9829,6 +9829,15 @@ export default {
mcpStatusError: "Check failed",
mcpReady: "Ready",
mcpNotInstalled: "Not installed",
mcpKeychainBadge: "Keychain authorization needed",
mcpKeychainTitle: "Keychain authorization required",
mcpKeychainDescription: "MCP clients start dbx-mcp in the background, where macOS cannot show a Keychain prompt, so it cannot read the DBX data encryption key and every MCP tool call fails with SECRET_KEY_UNAVAILABLE. Authorize it once here.",
mcpKeychainAuthorizeButton: "Authorize Keychain access",
mcpKeychainAuthorizing: "Waiting for authorization...",
mcpKeychainAlwaysAllowHint: 'When macOS asks, choose "Always Allow" (not "Allow").',
mcpKeychainAuthorized: "Keychain access authorized. Restart your MCP client for it to take effect.",
mcpKeychainNotRetained: 'macOS did not retain the authorization. Run it again and choose "Always Allow" (not "Allow"). Unlock the login keychain first if it is locked.',
mcpKeychainAuthorizeFailed: "Keychain authorization failed: {error}",
mcpUpdateAvailable: "Update available",
mcpCurrent: "Current version",
mcpLatest: "Latest version",
+9
View File
@@ -8872,6 +8872,15 @@ export default withEnglishFallback({
mcpStatusError: "Error al comprobar",
mcpReady: "Listo",
mcpNotInstalled: "No instalado",
mcpKeychainBadge: "Se requiere autorización del llavero",
mcpKeychainTitle: "Se requiere autorizar el acceso al llavero",
mcpKeychainDescription: "Los clientes MCP inician dbx-mcp en segundo plano, donde macOS no puede mostrar el aviso del llavero, por lo que no puede leer la clave de cifrado de datos de DBX y todas las llamadas a herramientas MCP fallan con SECRET_KEY_UNAVAILABLE. Autorícelo una sola vez aquí.",
mcpKeychainAuthorizeButton: "Autorizar acceso al llavero",
mcpKeychainAuthorizing: "Esperando autorización...",
mcpKeychainAlwaysAllowHint: 'Cuando macOS pregunte, elija "Permitir siempre" (no "Permitir").',
mcpKeychainAuthorized: "Acceso al llavero autorizado. Reinicie su cliente MCP para que surta efecto.",
mcpKeychainNotRetained: 'macOS no conservó la autorización. Vuelva a ejecutarlo y elija "Permitir siempre" (no "Permitir"). Desbloquee antes el llavero de inicio de sesión si está bloqueado.',
mcpKeychainAuthorizeFailed: "Error al autorizar el llavero: {error}",
mcpUpdateAvailable: "Actualización disponible",
mcpCurrent: "Versión actual",
mcpLatest: "Última versión",
+9
View File
@@ -9134,6 +9134,15 @@ export default withEnglishFallback({
mcpStatusError: "Pemeriksaan gagal",
mcpReady: "Siap",
mcpNotInstalled: "Belum terpasang",
mcpKeychainBadge: "Otorisasi Keychain diperlukan",
mcpKeychainTitle: "Otorisasi akses Keychain diperlukan",
mcpKeychainDescription: "Klien MCP menjalankan dbx-mcp di latar belakang, tempat macOS tidak dapat menampilkan prompt Keychain, sehingga tidak dapat membaca kunci enkripsi data DBX dan setiap pemanggilan alat MCP gagal dengan SECRET_KEY_UNAVAILABLE. Otorisasi sekali saja di sini.",
mcpKeychainAuthorizeButton: "Otorisasi akses Keychain",
mcpKeychainAuthorizing: "Menunggu otorisasi...",
mcpKeychainAlwaysAllowHint: 'Saat macOS bertanya, pilih "Selalu Izinkan" (bukan "Izinkan").',
mcpKeychainAuthorized: "Akses Keychain diotorisasi. Mulai ulang klien MCP agar berlaku.",
mcpKeychainNotRetained: 'macOS tidak mempertahankan otorisasi. Jalankan lagi dan pilih "Selalu Izinkan" (bukan "Izinkan"). Buka kunci keychain login terlebih dahulu jika terkunci.',
mcpKeychainAuthorizeFailed: "Otorisasi Keychain gagal: {error}",
mcpUpdateAvailable: "Pembaruan tersedia",
mcpCurrent: "Versi saat ini",
mcpLatest: "Versi terbaru",
+10
View File
@@ -8635,6 +8635,16 @@ export default withEnglishFallback({
mcpStatusError: "Verifica non riuscita",
mcpReady: "Pronto",
mcpNotInstalled: "Non installato",
mcpKeychainBadge: "Autorizzazione portachiavi necessaria",
mcpKeychainTitle: "È necessario autorizzare l'accesso al portachiavi",
mcpKeychainDescription:
"I client MCP avviano dbx-mcp in background, dove macOS non può mostrare la richiesta del portachiavi, quindi non riesce a leggere la chiave di cifratura dei dati di DBX e ogni chiamata agli strumenti MCP fallisce con SECRET_KEY_UNAVAILABLE. Autorizzalo una sola volta qui.",
mcpKeychainAuthorizeButton: "Autorizza accesso al portachiavi",
mcpKeychainAuthorizing: "In attesa di autorizzazione...",
mcpKeychainAlwaysAllowHint: 'Quando macOS lo chiede, scegli "Consenti sempre" (non "Consenti").',
mcpKeychainAuthorized: "Accesso al portachiavi autorizzato. Riavvia il client MCP per applicarlo.",
mcpKeychainNotRetained: 'macOS non ha conservato l\'autorizzazione. Eseguilo di nuovo e scegli "Consenti sempre" (non "Consenti"). Se il portachiavi di login è bloccato, sbloccalo prima.',
mcpKeychainAuthorizeFailed: "Autorizzazione del portachiavi non riuscita: {error}",
mcpUpdateAvailable: "Aggiornamento disponibile",
mcpCurrent: "Versione corrente",
mcpLatest: "Ultima versione",
+9
View File
@@ -8625,6 +8625,15 @@ export default withEnglishFallback({
mcpStatusError: "確認失敗",
mcpReady: "準備完了",
mcpNotInstalled: "未インストール",
mcpKeychainBadge: "キーチェーンの承認が必要",
mcpKeychainTitle: "キーチェーンへのアクセス承認が必要です",
mcpKeychainDescription: "MCP クライアントは dbx-mcp をバックグラウンドで起動するため、macOS がキーチェーンの確認ダイアログを表示できず、DBX のデータ暗号化キーを読み取れません。その結果、すべての MCP ツール呼び出しが SECRET_KEY_UNAVAILABLE で失敗します。ここで一度だけ承認してください。",
mcpKeychainAuthorizeButton: "キーチェーンアクセスを承認",
mcpKeychainAuthorizing: "承認を待っています...",
mcpKeychainAlwaysAllowHint: "macOS の確認ダイアログでは「常に許可」を選択してください(「許可」ではありません)。",
mcpKeychainAuthorized: "キーチェーンアクセスを承認しました。反映するには MCP クライアントを再起動してください。",
mcpKeychainNotRetained: "macOS が承認を保持しませんでした。もう一度実行し、「常に許可」を選択してください(「許可」ではありません)。ログインキーチェーンがロックされている場合は先に解除してください。",
mcpKeychainAuthorizeFailed: "キーチェーンの承認に失敗しました:{error}",
mcpUpdateAvailable: "アップデートがあります",
mcpCurrent: "現在のバージョン",
mcpLatest: "最新バージョン",
+9
View File
@@ -8531,6 +8531,15 @@ export default withEnglishFallback({
mcpStatusError: "확인 실패",
mcpReady: "준비됨",
mcpNotInstalled: "설치되지 않음",
mcpKeychainBadge: "키체인 승인 필요",
mcpKeychainTitle: "키체인 접근 승인이 필요합니다",
mcpKeychainDescription: "MCP 클라이언트는 dbx-mcp를 백그라운드에서 실행하므로 macOS가 키체인 확인 창을 표시할 수 없고, DBX 데이터 암호화 키를 읽지 못해 모든 MCP 도구 호출이 SECRET_KEY_UNAVAILABLE로 실패합니다. 여기서 한 번만 승인해 주세요.",
mcpKeychainAuthorizeButton: "키체인 접근 승인",
mcpKeychainAuthorizing: "승인을 기다리는 중...",
mcpKeychainAlwaysAllowHint: 'macOS 창이 나타나면 "항상 허용"을 선택하세요("허용"이 아님).',
mcpKeychainAuthorized: "키체인 접근이 승인되었습니다. 적용하려면 MCP 클라이언트를 다시 시작하세요.",
mcpKeychainNotRetained: 'macOS가 승인을 유지하지 않았습니다. 다시 실행하고 "항상 허용"을 선택하세요("허용"이 아님). 로그인 키체인이 잠겨 있다면 먼저 잠금을 해제하세요.',
mcpKeychainAuthorizeFailed: "키체인 승인 실패: {error}",
mcpUpdateAvailable: "업데이트 가능",
mcpCurrent: "현재 버전",
mcpLatest: "최신 버전",
+10
View File
@@ -8633,6 +8633,16 @@ export default withEnglishFallback({
mcpStatusError: "Falha na verificação",
mcpReady: "Pronto",
mcpNotInstalled: "Não instalado",
mcpKeychainBadge: "Autorização do chaveiro necessária",
mcpKeychainTitle: "É necessário autorizar o acesso ao chaveiro",
mcpKeychainDescription:
"Os clientes MCP iniciam o dbx-mcp em segundo plano, onde o macOS não consegue exibir o aviso do chaveiro, então ele não consegue ler a chave de criptografia de dados do DBX e todas as chamadas de ferramentas MCP falham com SECRET_KEY_UNAVAILABLE. Autorize uma única vez aqui.",
mcpKeychainAuthorizeButton: "Autorizar acesso ao chaveiro",
mcpKeychainAuthorizing: "Aguardando autorização...",
mcpKeychainAlwaysAllowHint: 'Quando o macOS perguntar, escolha "Sempre Permitir" (não "Permitir").',
mcpKeychainAuthorized: "Acesso ao chaveiro autorizado. Reinicie seu cliente MCP para que tenha efeito.",
mcpKeychainNotRetained: 'O macOS não manteve a autorização. Execute novamente e escolha "Sempre Permitir" (não "Permitir"). Desbloqueie antes o chaveiro de login, se estiver bloqueado.',
mcpKeychainAuthorizeFailed: "Falha ao autorizar o chaveiro: {error}",
mcpUpdateAvailable: "Atualização disponível",
mcpCurrent: "Versão atual",
mcpLatest: "Versão mais recente",
+9
View File
@@ -10019,6 +10019,15 @@ export default withEnglishFallback({
mcpStatusError: "Проверка не удалась",
mcpReady: "Готово",
mcpNotInstalled: "Не установлено",
mcpKeychainBadge: "Требуется доступ к связке ключей",
mcpKeychainTitle: "Необходимо разрешить доступ к связке ключей",
mcpKeychainDescription: "Клиенты MCP запускают dbx-mcp в фоне, где macOS не может показать запрос связки ключей, поэтому он не может прочитать ключ шифрования данных DBX, и все вызовы инструментов MCP завершаются ошибкой SECRET_KEY_UNAVAILABLE. Разрешите доступ один раз здесь.",
mcpKeychainAuthorizeButton: "Разрешить доступ к связке ключей",
mcpKeychainAuthorizing: "Ожидание разрешения...",
mcpKeychainAlwaysAllowHint: "Когда macOS спросит, выберите «Всегда разрешать» (а не «Разрешить»).",
mcpKeychainAuthorized: "Доступ к связке ключей разрешён. Перезапустите клиент MCP, чтобы изменения вступили в силу.",
mcpKeychainNotRetained: "macOS не сохранила разрешение. Запустите снова и выберите «Всегда разрешать» (а не «Разрешить»). Если связка ключей входа заблокирована, сначала разблокируйте её.",
mcpKeychainAuthorizeFailed: "Не удалось разрешить доступ к связке ключей: {error}",
mcpUpdateAvailable: "Доступно обновление",
mcpCurrent: "Текущая версия",
mcpLatest: "Последняя версия",
+9
View File
@@ -10454,6 +10454,15 @@ export default withEnglishFallback({
mcpStatusError: "ตรวจสอบไม่สำเร็จ",
mcpReady: "พร้อม",
mcpNotInstalled: "ไม่ได้ติดตั้ง",
mcpKeychainBadge: "ต้องอนุญาตการเข้าถึง Keychain",
mcpKeychainTitle: "ต้องอนุญาตการเข้าถึง Keychain",
mcpKeychainDescription: "ไคลเอนต์ MCP เริ่ม dbx-mcp ในเบื้องหลัง ซึ่ง macOS ไม่สามารถแสดงหน้าต่างขออนุญาต Keychain ได้ จึงอ่านคีย์เข้ารหัสข้อมูลของ DBX ไม่ได้ และการเรียกเครื่องมือ MCP ทุกครั้งจะล้มเหลวด้วย SECRET_KEY_UNAVAILABLE โปรดอนุญาตเพียงครั้งเดียวที่นี่",
mcpKeychainAuthorizeButton: "อนุญาตการเข้าถึง Keychain",
mcpKeychainAuthorizing: "กำลังรอการอนุญาต...",
mcpKeychainAlwaysAllowHint: 'เมื่อ macOS ถาม ให้เลือก "อนุญาตเสมอ" (ไม่ใช่ "อนุญาต")',
mcpKeychainAuthorized: "อนุญาตการเข้าถึง Keychain แล้ว โปรดรีสตาร์ตไคลเอนต์ MCP เพื่อให้มีผล",
mcpKeychainNotRetained: 'macOS ไม่ได้จดจำการอนุญาต โปรดรันอีกครั้งและเลือก "อนุญาตเสมอ" (ไม่ใช่ "อนุญาต") หาก Keychain การเข้าสู่ระบบถูกล็อก ให้ปลดล็อกก่อน',
mcpKeychainAuthorizeFailed: "การอนุญาต Keychain ล้มเหลว: {error}",
mcpUpdateAvailable: "มีการอัปเดต",
mcpCurrent: "เวอร์ชันปัจจุบัน",
mcpLatest: "เวอร์ชันล่าสุด",
+9
View File
@@ -8228,6 +8228,15 @@ export default withEnglishFallback({
mcpStatusError: "Denetim başarısız",
mcpReady: "Hazır",
mcpNotInstalled: "Kurulu değil",
mcpKeychainBadge: "Anahtar zinciri yetkisi gerekli",
mcpKeychainTitle: "Anahtar zinciri erişimi için yetki gerekiyor",
mcpKeychainDescription: "MCP istemcileri dbx-mcp'yi arka planda başlatır; macOS orada anahtar zinciri isteğini gösteremez, bu yüzden DBX veri şifreleme anahtarı okunamaz ve tüm MCP araç çağrıları SECRET_KEY_UNAVAILABLE ile başarısız olur. Burada bir kez yetkilendirin.",
mcpKeychainAuthorizeButton: "Anahtar zinciri erişimini yetkilendir",
mcpKeychainAuthorizing: "Yetki bekleniyor...",
mcpKeychainAlwaysAllowHint: 'macOS sorduğunda "Her Zaman İzin Ver" seçeneğini seçin ("İzin Ver" değil).',
mcpKeychainAuthorized: "Anahtar zinciri erişimi yetkilendirildi. Etkili olması için MCP istemcinizi yeniden başlatın.",
mcpKeychainNotRetained: 'macOS yetkiyi korumadı. Tekrar çalıştırın ve "Her Zaman İzin Ver" seçeneğini seçin ("İzin Ver" değil). Oturum açma anahtar zinciri kilitliyse önce kilidini açın.',
mcpKeychainAuthorizeFailed: "Anahtar zinciri yetkilendirmesi başarısız: {error}",
mcpUpdateAvailable: "Güncelleme mevcut",
mcpCurrent: "Geçerli sürüm",
mcpLatest: "En son sürüm",
+9
View File
@@ -9811,6 +9811,15 @@ export default withEnglishFallback({
mcpStatusError: "检查失败",
mcpReady: "可用",
mcpNotInstalled: "未安装",
mcpKeychainBadge: "需要钥匙串授权",
mcpKeychainTitle: "需要授权钥匙串访问",
mcpKeychainDescription: "MCP 客户端在后台启动 dbx-mcp 时,macOS 无法弹出钥匙串授权框,导致它读不到 DBX 数据加密密钥,所有 MCP 工具调用都会报 SECRET_KEY_UNAVAILABLE。请在此处一次性授权。",
mcpKeychainAuthorizeButton: "授权钥匙串访问",
mcpKeychainAuthorizing: "等待授权...",
mcpKeychainAlwaysAllowHint: "macOS 弹窗时请选择“始终允许”(不要选“允许”)。",
mcpKeychainAuthorized: "钥匙串访问已授权。请重启 MCP 客户端使其生效。",
mcpKeychainNotRetained: "macOS 没有保留该授权。请重新授权并选择“始终允许”(不要选“允许”);若登录钥匙串已锁定,请先解锁。",
mcpKeychainAuthorizeFailed: "钥匙串授权失败:{error}",
mcpUpdateAvailable: "有更新",
mcpCurrent: "当前版本",
mcpLatest: "最新版本",
+9
View File
@@ -8006,6 +8006,15 @@ export default withEnglishFallback({
mcpStatusError: "檢查失敗",
mcpReady: "可用",
mcpNotInstalled: "未安裝",
mcpKeychainBadge: "需要鑰匙圈授權",
mcpKeychainTitle: "需要授權鑰匙圈存取",
mcpKeychainDescription: "MCP 用戶端在背景啟動 dbx-mcp 時,macOS 無法彈出鑰匙圈授權視窗,導致它讀不到 DBX 資料加密金鑰,所有 MCP 工具呼叫都會回報 SECRET_KEY_UNAVAILABLE。請在此處一次性授權。",
mcpKeychainAuthorizeButton: "授權鑰匙圈存取",
mcpKeychainAuthorizing: "等待授權...",
mcpKeychainAlwaysAllowHint: "macOS 彈出視窗時請選擇「永遠允許」(不要選「允許」)。",
mcpKeychainAuthorized: "鑰匙圈存取已授權。請重新啟動 MCP 用戶端使其生效。",
mcpKeychainNotRetained: "macOS 沒有保留該授權。請重新授權並選擇「永遠允許」(不要選「允許」);若登入鑰匙圈已鎖定,請先解鎖。",
mcpKeychainAuthorizeFailed: "鑰匙圈授權失敗:{error}",
mcpUpdateAvailable: "有更新",
mcpCurrent: "當前版本",
mcpLatest: "最新版本",
+2
View File
@@ -978,6 +978,8 @@ export const deleteHistoryEntry = forward("deleteHistoryEntry");
// Updates
export const checkMcpServerStatus = forward("checkMcpServerStatus");
export const checkMcpKeychainAccess = forward("checkMcpKeychainAccess");
export const authorizeMcpKeychain = forward("authorizeMcpKeychain");
export const installMcpServer = forward("installMcpServer");
export const installNativeMcpServer = forward("installNativeMcpServer");
export const uninstallMcpServer = forward("uninstallMcpServer");
+8
View File
@@ -5627,6 +5627,14 @@ export async function checkMcpServerStatus(): Promise<import("@/lib/backend/taur
};
}
export async function checkMcpKeychainAccess(): Promise<import("@/lib/backend/tauri").McpKeychainAccess> {
return "not_applicable";
}
export async function authorizeMcpKeychain(): Promise<string> {
throw new Error("MCP Keychain authorization is only available in the desktop app.");
}
export async function installMcpServer(): Promise<string> {
throw new Error("MCP Server installation is only available in the desktop app.");
}
+10
View File
@@ -3416,6 +3416,16 @@ export async function checkMcpServerStatus(): Promise<McpServerStatus> {
return invoke("check_mcp_server_status");
}
export type McpKeychainAccess = "authorized" | "needs_authorization" | "key_missing" | "unknown" | "not_applicable";
export async function checkMcpKeychainAccess(): Promise<McpKeychainAccess> {
return invoke("check_mcp_keychain_access");
}
export async function authorizeMcpKeychain(): Promise<string> {
return invoke("authorize_mcp_keychain");
}
export async function installMcpServer(): Promise<string> {
return invoke("install_mcp_server");
}