refactor: better claude integration

This commit is contained in:
zhom
2026-03-24 09:05:52 +04:00
parent 9a6b500a4f
commit ad18966294
13 changed files with 664 additions and 174 deletions
-1
View File
@@ -1056,7 +1056,6 @@ export default function Home() {
onExtensionManagementDialogOpen={setExtensionManagementDialogOpen}
searchQuery={searchQuery}
onSearchQueryChange={setSearchQuery}
crossOsUnlocked={crossOsUnlocked}
/>
</div>
<div className="w-full mt-2.5">
-2
View File
@@ -177,7 +177,6 @@ type Props = {
onExtensionManagementDialogOpen: (open: boolean) => void;
searchQuery: string;
onSearchQueryChange: (query: string) => void;
crossOsUnlocked?: boolean;
};
const HomeHeader = ({
@@ -191,7 +190,6 @@ const HomeHeader = ({
onExtensionManagementDialogOpen,
searchQuery,
onSearchQueryChange,
crossOsUnlocked = false,
}: Props) => {
const { t } = useTranslation();
const {
+144 -67
View File
@@ -31,7 +31,6 @@ interface AppSettings {
interface McpConfig {
port: number;
token: string;
config_json: string;
}
interface IntegrationsDialogProps {
@@ -59,6 +58,8 @@ export function IntegrationsDialog({
const [showMcpToken, setShowMcpToken] = useState(false);
const [isApiStarting, setIsApiStarting] = useState(false);
const [isMcpStarting, setIsMcpStarting] = useState(false);
const [mcpInClaudeDesktop, setMcpInClaudeDesktop] = useState(false);
const [mcpInClaudeCode, setMcpInClaudeCode] = useState(false);
const { termsAccepted } = useWayfernTerms();
@@ -98,12 +99,32 @@ export function IntegrationsDialog({
}
}, []);
const loadClaudeDesktopStatus = useCallback(async () => {
try {
const exists = await invoke<boolean>("is_mcp_in_claude_desktop");
setMcpInClaudeDesktop(exists);
} catch {
// Not critical
}
}, []);
const loadClaudeCodeStatus = useCallback(async () => {
try {
const exists = await invoke<boolean>("is_mcp_in_claude_code");
setMcpInClaudeCode(exists);
} catch {
// Claude CLI may not be installed
}
}, []);
useEffect(() => {
if (isOpen) {
loadSettings();
loadApiServerStatus();
loadMcpConfig();
loadMcpServerStatus();
loadClaudeDesktopStatus();
loadClaudeCodeStatus();
}
}, [
isOpen,
@@ -111,6 +132,8 @@ export function IntegrationsDialog({
loadApiServerStatus,
loadMcpConfig,
loadMcpServerStatus,
loadClaudeDesktopStatus,
loadClaudeCodeStatus,
]);
const handleApiToggle = async (enabled: boolean) => {
@@ -175,45 +198,9 @@ export function IntegrationsDialog({
}
};
const obfuscateToken = (token: string) =>
const _obfuscateToken = (token: string) =>
"•".repeat(Math.min(token.length, 32));
const getFormattedMcpConfig = () => {
if (!mcpConfig) return "";
return JSON.stringify(
{
mcpServers: {
"donut-browser": {
url: `http://127.0.0.1:${mcpConfig.port}/mcp`,
headers: {
Authorization: `Bearer ${mcpConfig.token}`,
},
},
},
},
null,
2,
);
};
const getObfuscatedMcpConfig = () => {
if (!mcpConfig) return "";
return JSON.stringify(
{
mcpServers: {
"donut-browser": {
url: `http://127.0.0.1:${mcpConfig.port}/mcp`,
headers: {
Authorization: `Bearer ${obfuscateToken(mcpConfig.token)}`,
},
},
},
},
null,
2,
);
};
return (
<Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>
<DialogContent className="max-w-xl max-h-[80vh] my-8 flex flex-col">
@@ -331,39 +318,129 @@ export function IntegrationsDialog({
</div>
{mcpConfig && (
<div className="space-y-3 p-4 rounded-md border bg-muted/40">
<div className="relative">
<pre className="p-3 text-xs font-mono rounded-md bg-background border overflow-x-auto whitespace-pre">
{showMcpToken
? getFormattedMcpConfig()
: getObfuscatedMcpConfig()}
</pre>
<div className="absolute top-2 right-2 flex items-center space-x-1">
<Button
type="button"
variant="ghost"
size="sm"
className="h-7 w-7 p-0"
onClick={() => setShowMcpToken(!showMcpToken)}
>
{showMcpToken ? (
<EyeOff className="h-3.5 w-3.5" />
) : (
<Eye className="h-3.5 w-3.5" />
)}
</Button>
<div className="space-y-4 p-4 rounded-md border bg-muted/40">
<div className="space-y-2">
<Label className="text-sm font-medium">
{t("integrations.mcp.url")}
</Label>
<div className="flex items-center space-x-2">
<div className="relative flex-1">
<Input
type={showMcpToken ? "text" : "password"}
value={`http://127.0.0.1:${mcpConfig.port}/mcp/${mcpConfig.token}`}
readOnly
className="font-mono text-xs pr-10"
/>
<Button
type="button"
variant="ghost"
size="sm"
className="absolute right-0 top-0 h-full px-3 hover:bg-transparent"
onClick={() => setShowMcpToken(!showMcpToken)}
>
{showMcpToken ? (
<EyeOff className="h-4 w-4" />
) : (
<Eye className="h-4 w-4" />
)}
</Button>
</div>
<CopyToClipboard
text={getFormattedMcpConfig()}
successMessage="Configuration copied"
text={`http://127.0.0.1:${mcpConfig.port}/mcp/${mcpConfig.token}`}
successMessage={t("integrations.mcp.urlCopied")}
/>
</div>
</div>
<p className="text-xs text-muted-foreground">
{t("integrations.mcpCopyHint")}
</p>
<p className="text-xs text-muted-foreground">
{t("integrations.mcpConfigPath")}
</p>
<div className="space-y-2 pt-1 border-t">
<p className="text-xs font-medium text-muted-foreground">
{t("integrations.mcp.claudeDesktopTitle")}
</p>
{mcpInClaudeDesktop ? (
<Button
variant="outline"
size="sm"
className="w-full"
onClick={async () => {
try {
await invoke("remove_mcp_from_claude_desktop");
setMcpInClaudeDesktop(false);
showSuccessToast(
t("integrations.mcp.removedFromClaudeDesktop"),
);
} catch (e) {
showErrorToast(String(e));
}
}}
>
{t("integrations.mcp.removeFromClaudeDesktop")}
</Button>
) : (
<Button
variant="outline"
size="sm"
className="w-full"
onClick={async () => {
try {
await invoke("add_mcp_to_claude_desktop");
setMcpInClaudeDesktop(true);
showSuccessToast(
t("integrations.mcp.addedToClaudeDesktop"),
);
} catch (e) {
showErrorToast(String(e));
}
}}
>
{t("integrations.mcp.addToClaudeDesktop")}
</Button>
)}
</div>
<div className="space-y-2 pt-1 border-t">
<p className="text-xs font-medium text-muted-foreground">
{t("integrations.mcp.claudeCodeTitle")}
</p>
{mcpInClaudeCode ? (
<Button
variant="outline"
size="sm"
className="w-full"
onClick={async () => {
try {
await invoke("remove_mcp_from_claude_code");
setMcpInClaudeCode(false);
showSuccessToast(
t("integrations.mcp.removedFromClaudeCode"),
);
} catch (e) {
showErrorToast(String(e));
}
}}
>
{t("integrations.mcp.removeFromClaudeCode")}
</Button>
) : (
<Button
variant="outline"
size="sm"
className="w-full"
onClick={async () => {
try {
await invoke("add_mcp_to_claude_code");
setMcpInClaudeCode(true);
showSuccessToast(
t("integrations.mcp.addedToClaudeCode"),
);
} catch (e) {
showErrorToast(String(e));
}
}}
>
{t("integrations.mcp.addToClaudeCode")}
</Button>
)}
</div>
</div>
)}
</TabsContent>
+16 -4
View File
@@ -417,12 +417,24 @@
"enabled": "MCP Enabled",
"disabled": "MCP Disabled",
"port": "Port",
"token": "MCP Token",
"token": "Authentication Token",
"tokenCopied": "Token copied",
"url": "MCP Server URL",
"urlCopied": "URL copied",
"claudeDesktopTitle": "Claude Desktop",
"claudeDesktopHint": "Configures claude_desktop_config.json automatically",
"addToClaudeDesktop": "Add to Claude Desktop",
"removeFromClaudeDesktop": "Remove from Claude Desktop",
"addedToClaudeDesktop": "Added to Claude Desktop. Restart Claude Desktop and enable the extension in Settings.",
"removedFromClaudeDesktop": "Removed from Claude Desktop config. Please restart Claude Desktop.",
"claudeCodeTitle": "Claude Code",
"addToClaudeCode": "Add to Claude Code",
"removeFromClaudeCode": "Remove from Claude Code",
"addedToClaudeCode": "Added to Claude Code",
"removedFromClaudeCode": "Removed from Claude Code",
"config": "MCP Configuration",
"copyConfig": "Copy Configuration"
},
"mcpCopyHint": "Copy and paste this into your MCP client configuration.",
"mcpConfigPath": "Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\\Claude\\claude_desktop_config.json (Windows)"
}
},
"import": {
"title": "Import Profile",
+16 -4
View File
@@ -417,12 +417,24 @@
"enabled": "MCP Habilitado",
"disabled": "MCP Deshabilitado",
"port": "Puerto",
"token": "Token MCP",
"token": "Token de autenticación",
"tokenCopied": "Token copiado",
"url": "URL del servidor MCP",
"urlCopied": "URL copiada",
"claudeDesktopTitle": "Claude Desktop",
"claudeDesktopHint": "Configura claude_desktop_config.json automáticamente",
"addToClaudeDesktop": "Agregar a Claude Desktop",
"removeFromClaudeDesktop": "Eliminar de Claude Desktop",
"addedToClaudeDesktop": "Agregado a Claude Desktop. Reinicia Claude Desktop y activa la extensión en Configuración.",
"removedFromClaudeDesktop": "Eliminado de la configuración de Claude Desktop. Reinicia Claude Desktop.",
"claudeCodeTitle": "Claude Code",
"addToClaudeCode": "Agregar a Claude Code",
"removeFromClaudeCode": "Eliminar de Claude Code",
"addedToClaudeCode": "Agregado a Claude Code",
"removedFromClaudeCode": "Eliminado de Claude Code",
"config": "Configuración MCP",
"copyConfig": "Copiar Configuración"
},
"mcpCopyHint": "Copia y pega esto en la configuración de tu cliente MCP.",
"mcpConfigPath": "Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) o %APPDATA%\\Claude\\claude_desktop_config.json (Windows)"
}
},
"import": {
"title": "Importar Perfil",
+16 -4
View File
@@ -417,12 +417,24 @@
"enabled": "MCP activé",
"disabled": "MCP désactivé",
"port": "Port",
"token": "Jeton MCP",
"token": "Jeton d'authentification",
"tokenCopied": "Jeton copié",
"url": "URL du serveur MCP",
"urlCopied": "URL copiée",
"claudeDesktopTitle": "Claude Desktop",
"claudeDesktopHint": "Configure claude_desktop_config.json automatiquement",
"addToClaudeDesktop": "Ajouter à Claude Desktop",
"removeFromClaudeDesktop": "Supprimer de Claude Desktop",
"addedToClaudeDesktop": "Ajouté à Claude Desktop. Redémarrez Claude Desktop et activez l'extension dans les Paramètres.",
"removedFromClaudeDesktop": "Supprimé de la configuration de Claude Desktop. Veuillez redémarrer Claude Desktop.",
"claudeCodeTitle": "Claude Code",
"addToClaudeCode": "Ajouter à Claude Code",
"removeFromClaudeCode": "Supprimer de Claude Code",
"addedToClaudeCode": "Ajouté à Claude Code",
"removedFromClaudeCode": "Supprimé de Claude Code",
"config": "Configuration MCP",
"copyConfig": "Copier la configuration"
},
"mcpCopyHint": "Copiez et collez ceci dans la configuration de votre client MCP.",
"mcpConfigPath": "Claude Desktop : ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) ou %APPDATA%\\Claude\\claude_desktop_config.json (Windows)"
}
},
"import": {
"title": "Importer un profil",
+16 -4
View File
@@ -417,12 +417,24 @@
"enabled": "MCP有効",
"disabled": "MCP無効",
"port": "ポート",
"token": "MCPトークン",
"token": "認証トークン",
"tokenCopied": "トークンをコピーしました",
"url": "MCPサーバーURL",
"urlCopied": "URLをコピーしました",
"claudeDesktopTitle": "Claude Desktop",
"claudeDesktopHint": "claude_desktop_config.json を自動的に設定します",
"addToClaudeDesktop": "Claude Desktop に追加",
"removeFromClaudeDesktop": "Claude Desktop から削除",
"addedToClaudeDesktop": "Claude Desktop に追加しました。Claude Desktop を再起動し、設定で拡張機能を有効にしてください。",
"removedFromClaudeDesktop": "Claude Desktop の設定から削除しました。Claude Desktop を再起動してください。",
"claudeCodeTitle": "Claude Code",
"addToClaudeCode": "Claude Code に追加",
"removeFromClaudeCode": "Claude Code から削除",
"addedToClaudeCode": "Claude Code に追加しました",
"removedFromClaudeCode": "Claude Code から削除しました",
"config": "MCP設定",
"copyConfig": "設定をコピー"
},
"mcpCopyHint": "MCPクライアントの設定にコピーして貼り付けてください。",
"mcpConfigPath": "Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) または %APPDATA%\\Claude\\claude_desktop_config.json (Windows)"
}
},
"import": {
"title": "プロファイルをインポート",
+16 -4
View File
@@ -417,12 +417,24 @@
"enabled": "MCP Ativado",
"disabled": "MCP Desativado",
"port": "Porta",
"token": "Token MCP",
"token": "Token de autenticação",
"tokenCopied": "Token copiado",
"url": "URL do servidor MCP",
"urlCopied": "URL copiada",
"claudeDesktopTitle": "Claude Desktop",
"claudeDesktopHint": "Configura claude_desktop_config.json automaticamente",
"addToClaudeDesktop": "Adicionar ao Claude Desktop",
"removeFromClaudeDesktop": "Remover do Claude Desktop",
"addedToClaudeDesktop": "Adicionado ao Claude Desktop. Reinicie o Claude Desktop e ative a extensão em Configurações.",
"removedFromClaudeDesktop": "Removido da configuração do Claude Desktop. Reinicie o Claude Desktop.",
"claudeCodeTitle": "Claude Code",
"addToClaudeCode": "Adicionar ao Claude Code",
"removeFromClaudeCode": "Remover do Claude Code",
"addedToClaudeCode": "Adicionado ao Claude Code",
"removedFromClaudeCode": "Removido do Claude Code",
"config": "Configuração MCP",
"copyConfig": "Copiar Configuração"
},
"mcpCopyHint": "Copie e cole isso na configuração do seu cliente MCP.",
"mcpConfigPath": "Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) ou %APPDATA%\\Claude\\claude_desktop_config.json (Windows)"
}
},
"import": {
"title": "Importar Perfil",
+16 -4
View File
@@ -417,12 +417,24 @@
"enabled": "MCP включён",
"disabled": "MCP выключен",
"port": "Порт",
"token": "MCP токен",
"token": "Токен аутентификации",
"tokenCopied": "Токен скопирован",
"url": "URL MCP сервера",
"urlCopied": "URL скопирован",
"claudeDesktopTitle": "Claude Desktop",
"claudeDesktopHint": "Автоматически настраивает claude_desktop_config.json",
"addToClaudeDesktop": "Добавить в Claude Desktop",
"removeFromClaudeDesktop": "Удалить из Claude Desktop",
"addedToClaudeDesktop": "Добавлено в Claude Desktop. Перезапустите Claude Desktop и включите расширение в Настройках.",
"removedFromClaudeDesktop": "Удалено из конфигурации Claude Desktop. Перезапустите Claude Desktop.",
"claudeCodeTitle": "Claude Code",
"addToClaudeCode": "Добавить в Claude Code",
"removeFromClaudeCode": "Удалить из Claude Code",
"addedToClaudeCode": "Добавлено в Claude Code",
"removedFromClaudeCode": "Удалено из Claude Code",
"config": "Конфигурация MCP",
"copyConfig": "Копировать конфигурацию"
},
"mcpCopyHint": "Скопируйте и вставьте это в конфигурацию вашего MCP-клиента.",
"mcpConfigPath": "Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) или %APPDATA%\\Claude\\claude_desktop_config.json (Windows)"
}
},
"import": {
"title": "Импорт профиля",
+16 -4
View File
@@ -417,12 +417,24 @@
"enabled": "MCP 已启用",
"disabled": "MCP 已禁用",
"port": "端口",
"token": "MCP 令牌",
"token": "认证令牌",
"tokenCopied": "令牌已复制",
"url": "MCP 服务器 URL",
"urlCopied": "URL 已复制",
"claudeDesktopTitle": "Claude Desktop",
"claudeDesktopHint": "自动配置 claude_desktop_config.json",
"addToClaudeDesktop": "添加到 Claude Desktop",
"removeFromClaudeDesktop": "从 Claude Desktop 移除",
"addedToClaudeDesktop": "已添加到 Claude Desktop。请重启 Claude Desktop 并在设置中启用扩展。",
"removedFromClaudeDesktop": "已从 Claude Desktop 配置移除。请重启 Claude Desktop。",
"claudeCodeTitle": "Claude Code",
"addToClaudeCode": "添加到 Claude Code",
"removeFromClaudeCode": "从 Claude Code 移除",
"addedToClaudeCode": "已添加到 Claude Code",
"removedFromClaudeCode": "已从 Claude Code 移除",
"config": "MCP 配置",
"copyConfig": "复制配置"
},
"mcpCopyHint": "将此内容复制并粘贴到您的 MCP 客户端配置中。",
"mcpConfigPath": "Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) 或 %APPDATA%\\Claude\\claude_desktop_config.json (Windows)"
}
},
"import": {
"title": "导入配置文件",