From 3c719f05a178e162e2ffc0e5e5643f42a89dbe45 Mon Sep 17 00:00:00 2001 From: Kacper Date: Sun, 28 Dec 2025 17:07:57 +0100 Subject: [PATCH] refactor: split mcp-servers-section into modular components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactored 1348-line monolithic file into proper folder structure following folder-pattern.md conventions: Structure: - components/ - UI components (card, header, settings, warning) - dialogs/ - 5 dialog components (add/edit, delete, import, json edit) - hooks/use-mcp-servers.ts - all state management & handlers - types.ts, constants.ts, utils.tsx - shared code Main file reduced from 1348 to 192 lines (composition only). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../mcp-servers/components/index.ts | 4 + .../components/mcp-permission-settings.tsx | 62 + .../components/mcp-server-card.tsx | 169 ++ .../components/mcp-server-header.tsx | 87 + .../components/mcp-tools-warning.tsx | 25 + .../settings-view/mcp-servers/constants.ts | 14 + .../dialogs/add-edit-server-dialog.tsx | 161 ++ .../dialogs/delete-server-dialog.tsx | 42 + .../dialogs/global-json-edit-dialog.tsx | 82 + .../dialogs/import-json-dialog.tsx | 69 + .../mcp-servers/dialogs/index.ts | 5 + .../mcp-servers/dialogs/json-edit-dialog.tsx | 77 + .../settings-view/mcp-servers/hooks/index.ts | 1 + .../mcp-servers/hooks/use-mcp-servers.ts | 678 ++++++++ .../views/settings-view/mcp-servers/index.ts | 1 + .../mcp-servers/mcp-servers-section.tsx | 1438 ++--------------- .../mcp-servers/mcp-tools-list.tsx | 4 +- .../views/settings-view/mcp-servers/types.ts | 32 + .../views/settings-view/mcp-servers/utils.tsx | 51 + 19 files changed, 1703 insertions(+), 1299 deletions(-) create mode 100644 apps/ui/src/components/views/settings-view/mcp-servers/components/index.ts create mode 100644 apps/ui/src/components/views/settings-view/mcp-servers/components/mcp-permission-settings.tsx create mode 100644 apps/ui/src/components/views/settings-view/mcp-servers/components/mcp-server-card.tsx create mode 100644 apps/ui/src/components/views/settings-view/mcp-servers/components/mcp-server-header.tsx create mode 100644 apps/ui/src/components/views/settings-view/mcp-servers/components/mcp-tools-warning.tsx create mode 100644 apps/ui/src/components/views/settings-view/mcp-servers/constants.ts create mode 100644 apps/ui/src/components/views/settings-view/mcp-servers/dialogs/add-edit-server-dialog.tsx create mode 100644 apps/ui/src/components/views/settings-view/mcp-servers/dialogs/delete-server-dialog.tsx create mode 100644 apps/ui/src/components/views/settings-view/mcp-servers/dialogs/global-json-edit-dialog.tsx create mode 100644 apps/ui/src/components/views/settings-view/mcp-servers/dialogs/import-json-dialog.tsx create mode 100644 apps/ui/src/components/views/settings-view/mcp-servers/dialogs/index.ts create mode 100644 apps/ui/src/components/views/settings-view/mcp-servers/dialogs/json-edit-dialog.tsx create mode 100644 apps/ui/src/components/views/settings-view/mcp-servers/hooks/index.ts create mode 100644 apps/ui/src/components/views/settings-view/mcp-servers/hooks/use-mcp-servers.ts create mode 100644 apps/ui/src/components/views/settings-view/mcp-servers/types.ts create mode 100644 apps/ui/src/components/views/settings-view/mcp-servers/utils.tsx diff --git a/apps/ui/src/components/views/settings-view/mcp-servers/components/index.ts b/apps/ui/src/components/views/settings-view/mcp-servers/components/index.ts new file mode 100644 index 00000000..db49d81d --- /dev/null +++ b/apps/ui/src/components/views/settings-view/mcp-servers/components/index.ts @@ -0,0 +1,4 @@ +export { MCPServerHeader } from './mcp-server-header'; +export { MCPPermissionSettings } from './mcp-permission-settings'; +export { MCPToolsWarning } from './mcp-tools-warning'; +export { MCPServerCard } from './mcp-server-card'; diff --git a/apps/ui/src/components/views/settings-view/mcp-servers/components/mcp-permission-settings.tsx b/apps/ui/src/components/views/settings-view/mcp-servers/components/mcp-permission-settings.tsx new file mode 100644 index 00000000..b7db14a4 --- /dev/null +++ b/apps/ui/src/components/views/settings-view/mcp-servers/components/mcp-permission-settings.tsx @@ -0,0 +1,62 @@ +import { Label } from '@/components/ui/label'; +import { Switch } from '@/components/ui/switch'; +import { syncSettingsToServer } from '@/hooks/use-settings-migration'; + +interface MCPPermissionSettingsProps { + mcpAutoApproveTools: boolean; + mcpUnrestrictedTools: boolean; + onAutoApproveChange: (checked: boolean) => void; + onUnrestrictedChange: (checked: boolean) => void; +} + +export function MCPPermissionSettings({ + mcpAutoApproveTools, + mcpUnrestrictedTools, + onAutoApproveChange, + onUnrestrictedChange, +}: MCPPermissionSettingsProps) { + return ( +
+
+
+
+ +

+ Allow MCP tool calls without permission prompts (recommended) +

+
+ { + onAutoApproveChange(checked); + await syncSettingsToServer(); + }} + data-testid="mcp-auto-approve-toggle" + /> +
+
+
+ +

+ Allow all tools when MCP is enabled (don't filter to default set) +

+
+ { + onUnrestrictedChange(checked); + await syncSettingsToServer(); + }} + data-testid="mcp-unrestricted-toggle" + /> +
+
+
+ ); +} diff --git a/apps/ui/src/components/views/settings-view/mcp-servers/components/mcp-server-card.tsx b/apps/ui/src/components/views/settings-view/mcp-servers/components/mcp-server-card.tsx new file mode 100644 index 00000000..babf4bda --- /dev/null +++ b/apps/ui/src/components/views/settings-view/mcp-servers/components/mcp-server-card.tsx @@ -0,0 +1,169 @@ +import { ChevronDown, ChevronRight, Code, Pencil, Trash2, PlayCircle, Loader2 } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { Switch } from '@/components/ui/switch'; +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'; +import { cn } from '@/lib/utils'; +import type { MCPServerConfig } from '@automaker/types'; +import type { ServerTestState } from '../types'; +import { getServerIcon, getTestStatusIcon, maskSensitiveUrl } from '../utils'; +import { MCPToolsList } from '../mcp-tools-list'; + +interface MCPServerCardProps { + server: MCPServerConfig; + testState?: ServerTestState; + isExpanded: boolean; + onToggleExpanded: () => void; + onTest: () => void; + onToggleEnabled: () => void; + onEditJson: () => void; + onEdit: () => void; + onDelete: () => void; +} + +export function MCPServerCard({ + server, + testState, + isExpanded, + onToggleExpanded, + onTest, + onToggleEnabled, + onEditJson, + onEdit, + onDelete, +}: MCPServerCardProps) { + const Icon = getServerIcon(server.type); + const hasTools = testState?.tools && testState.tools.length > 0; + + return ( + +
+
+
+ + + +
+
+ + + + + +
+
+ {hasTools && ( + +
+
Available Tools
+ +
+
+ )} +
+
+ ); +} diff --git a/apps/ui/src/components/views/settings-view/mcp-servers/components/mcp-server-header.tsx b/apps/ui/src/components/views/settings-view/mcp-servers/components/mcp-server-header.tsx new file mode 100644 index 00000000..a85fc305 --- /dev/null +++ b/apps/ui/src/components/views/settings-view/mcp-servers/components/mcp-server-header.tsx @@ -0,0 +1,87 @@ +import { Plug, RefreshCw, Download, Code, FileJson, Plus } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { cn } from '@/lib/utils'; + +interface MCPServerHeaderProps { + isRefreshing: boolean; + hasServers: boolean; + onRefresh: () => void; + onExport: () => void; + onEditAllJson: () => void; + onImport: () => void; + onAdd: () => void; +} + +export function MCPServerHeader({ + isRefreshing, + hasServers, + onRefresh, + onExport, + onEditAllJson, + onImport, + onAdd, +}: MCPServerHeaderProps) { + return ( +
+
+
+
+
+ +
+

MCP Servers

+
+

+ Configure Model Context Protocol servers to extend agent capabilities. +

+
+
+ + {hasServers && ( + <> + + + + )} + + +
+
+
+ ); +} diff --git a/apps/ui/src/components/views/settings-view/mcp-servers/components/mcp-tools-warning.tsx b/apps/ui/src/components/views/settings-view/mcp-servers/components/mcp-tools-warning.tsx new file mode 100644 index 00000000..019a0bbb --- /dev/null +++ b/apps/ui/src/components/views/settings-view/mcp-servers/components/mcp-tools-warning.tsx @@ -0,0 +1,25 @@ +import { AlertTriangle } from 'lucide-react'; +import { MAX_RECOMMENDED_TOOLS } from '../constants'; + +interface MCPToolsWarningProps { + totalTools: number; +} + +export function MCPToolsWarning({ totalTools }: MCPToolsWarningProps) { + return ( +
+
+ +
+

+ High tool count detected ({totalTools} tools) +

+

+ Having more than {MAX_RECOMMENDED_TOOLS} MCP tools may degrade AI model performance. + Consider disabling unused servers or removing unnecessary tools. +

+
+
+
+ ); +} diff --git a/apps/ui/src/components/views/settings-view/mcp-servers/constants.ts b/apps/ui/src/components/views/settings-view/mcp-servers/constants.ts new file mode 100644 index 00000000..8a41cd8b --- /dev/null +++ b/apps/ui/src/components/views/settings-view/mcp-servers/constants.ts @@ -0,0 +1,14 @@ +// Patterns that indicate sensitive values in URLs or config +export const SENSITIVE_PARAM_PATTERNS = [ + /api[-_]?key/i, + /api[-_]?token/i, + /auth/i, + /token/i, + /secret/i, + /password/i, + /credential/i, + /bearer/i, +]; + +// Maximum recommended MCP tools before performance degradation +export const MAX_RECOMMENDED_TOOLS = 80; diff --git a/apps/ui/src/components/views/settings-view/mcp-servers/dialogs/add-edit-server-dialog.tsx b/apps/ui/src/components/views/settings-view/mcp-servers/dialogs/add-edit-server-dialog.tsx new file mode 100644 index 00000000..5671ab60 --- /dev/null +++ b/apps/ui/src/components/views/settings-view/mcp-servers/dialogs/add-edit-server-dialog.tsx @@ -0,0 +1,161 @@ +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { Textarea } from '@/components/ui/textarea'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; +import type { MCPServerConfig } from '@automaker/types'; +import type { ServerFormData, ServerType } from '../types'; + +interface AddEditServerDialogProps { + open: boolean; + onOpenChange: (open: boolean) => void; + editingServer: MCPServerConfig | null; + formData: ServerFormData; + onFormDataChange: (data: ServerFormData) => void; + onSave: () => void; + onCancel: () => void; +} + +export function AddEditServerDialog({ + open, + onOpenChange, + editingServer, + formData, + onFormDataChange, + onSave, + onCancel, +}: AddEditServerDialogProps) { + return ( + + + + {editingServer ? 'Edit MCP Server' : 'Add MCP Server'} + + Configure an MCP server to extend agent capabilities with custom tools. + + +
+
+ + onFormDataChange({ ...formData, name: e.target.value })} + placeholder="my-mcp-server" + data-testid="mcp-server-name-input" + /> +
+
+ + onFormDataChange({ ...formData, description: e.target.value })} + placeholder="What this server provides..." + data-testid="mcp-server-description-input" + /> +
+
+ + +
+ {formData.type === 'stdio' ? ( + <> +
+ + onFormDataChange({ ...formData, command: e.target.value })} + placeholder="npx, node, python, etc." + data-testid="mcp-server-command-input" + /> +
+
+ + onFormDataChange({ ...formData, args: e.target.value })} + placeholder="-y @modelcontextprotocol/server-filesystem" + data-testid="mcp-server-args-input" + /> +
+
+ +