diff --git a/server/routes/cursor.js b/server/routes/cursor.js index 7e395023..9842e7a6 100644 --- a/server/routes/cursor.js +++ b/server/routes/cursor.js @@ -178,171 +178,6 @@ router.get('/mcp', async (req, res) => { } }); -// POST /api/cursor/mcp/add - Add MCP server to Cursor configuration -router.post('/mcp/add', async (req, res) => { - try { - const { name, type = 'stdio', command, args = [], url, headers = {}, env = {} } = req.body; - const mcpPath = path.join(os.homedir(), '.cursor', 'mcp.json'); - - console.log(`➕ Adding MCP server to Cursor config: ${name}`); - - // Read existing config or create new - let mcpConfig = { mcpServers: {} }; - - try { - const existing = await fs.readFile(mcpPath, 'utf8'); - mcpConfig = JSON.parse(existing); - if (!mcpConfig.mcpServers) { - mcpConfig.mcpServers = {}; - } - } catch (error) { - console.log('Creating new Cursor MCP config'); - } - - // Build server config based on type - let serverConfig = {}; - - if (type === 'stdio') { - serverConfig = { - command: command, - args: args, - env: env - }; - } else if (type === 'http' || type === 'sse') { - serverConfig = { - url: url, - transport: type, - headers: headers - }; - } - - // Add server to config - mcpConfig.mcpServers[name] = serverConfig; - - // Ensure directory exists - const mcpDir = path.dirname(mcpPath); - await fs.mkdir(mcpDir, { recursive: true }); - - // Write updated config - await fs.writeFile(mcpPath, JSON.stringify(mcpConfig, null, 2)); - - res.json({ - success: true, - message: `MCP server "${name}" added to Cursor configuration`, - config: mcpConfig - }); - } catch (error) { - console.error('Error adding MCP server to Cursor:', error); - res.status(500).json({ - error: 'Failed to add MCP server', - details: error.message - }); - } -}); - -// DELETE /api/cursor/mcp/:name - Remove MCP server from Cursor configuration -router.delete('/mcp/:name', async (req, res) => { - try { - const { name } = req.params; - const mcpPath = path.join(os.homedir(), '.cursor', 'mcp.json'); - - console.log(`🗑️ Removing MCP server from Cursor config: ${name}`); - - // Read existing config - let mcpConfig = { mcpServers: {} }; - - try { - const existing = await fs.readFile(mcpPath, 'utf8'); - mcpConfig = JSON.parse(existing); - } catch (error) { - return res.status(404).json({ - error: 'Cursor MCP configuration not found' - }); - } - - // Check if server exists - if (!mcpConfig.mcpServers || !mcpConfig.mcpServers[name]) { - return res.status(404).json({ - error: `MCP server "${name}" not found in Cursor configuration` - }); - } - - // Remove server from config - delete mcpConfig.mcpServers[name]; - - // Write updated config - await fs.writeFile(mcpPath, JSON.stringify(mcpConfig, null, 2)); - - res.json({ - success: true, - message: `MCP server "${name}" removed from Cursor configuration`, - config: mcpConfig - }); - } catch (error) { - console.error('Error removing MCP server from Cursor:', error); - res.status(500).json({ - error: 'Failed to remove MCP server', - details: error.message - }); - } -}); - -// POST /api/cursor/mcp/add-json - Add MCP server using JSON format -router.post('/mcp/add-json', async (req, res) => { - try { - const { name, jsonConfig } = req.body; - const mcpPath = path.join(os.homedir(), '.cursor', 'mcp.json'); - - console.log(`➕ Adding MCP server to Cursor config via JSON: ${name}`); - - // Validate and parse JSON config - let parsedConfig; - try { - parsedConfig = typeof jsonConfig === 'string' ? JSON.parse(jsonConfig) : jsonConfig; - } catch (parseError) { - return res.status(400).json({ - error: 'Invalid JSON configuration', - details: parseError.message - }); - } - - // Read existing config or create new - let mcpConfig = { mcpServers: {} }; - - try { - const existing = await fs.readFile(mcpPath, 'utf8'); - mcpConfig = JSON.parse(existing); - if (!mcpConfig.mcpServers) { - mcpConfig.mcpServers = {}; - } - } catch (error) { - console.log('Creating new Cursor MCP config'); - } - - // Add server to config - mcpConfig.mcpServers[name] = parsedConfig; - - // Ensure directory exists - const mcpDir = path.dirname(mcpPath); - await fs.mkdir(mcpDir, { recursive: true }); - - // Write updated config - await fs.writeFile(mcpPath, JSON.stringify(mcpConfig, null, 2)); - - res.json({ - success: true, - message: `MCP server "${name}" added to Cursor configuration via JSON`, - config: mcpConfig - }); - } catch (error) { - console.error('Error adding MCP server to Cursor via JSON:', error); - res.status(500).json({ - error: 'Failed to add MCP server', - details: error.message - }); - } -}); - // GET /api/cursor/sessions - Get Cursor sessions from SQLite database router.get('/sessions', async (req, res) => { try { @@ -577,4 +412,4 @@ router.get('/sessions', async (req, res) => { }); } }); -export default router; \ No newline at end of file +export default router; diff --git a/src/components/settings/constants/constants.ts b/src/components/settings/constants/constants.ts index 52f16e10..1504bc20 100644 --- a/src/components/settings/constants/constants.ts +++ b/src/components/settings/constants/constants.ts @@ -5,8 +5,6 @@ import type { CodexMcpFormState, CodeEditorSettingsState, CursorPermissionsState, - McpToolsResult, - McpTestResult, ProjectSortOrder, SettingsMainTab, } from '../types/types'; @@ -33,20 +31,6 @@ export const DEFAULT_CODE_EDITOR_SETTINGS: CodeEditorSettingsState = { fontSize: '14', }; -export const DEFAULT_MCP_TEST_RESULT: McpTestResult = { - success: false, - message: '', - details: [], - loading: false, -}; - -export const DEFAULT_MCP_TOOLS_RESULT: McpToolsResult = { - success: false, - tools: [], - resources: [], - prompts: [], -}; - export const DEFAULT_CLAUDE_MCP_FORM: ClaudeMcpFormState = { name: '', type: 'stdio', diff --git a/src/components/settings/hooks/useSettingsController.ts b/src/components/settings/hooks/useSettingsController.ts index 09550265..8a8f7141 100644 --- a/src/components/settings/hooks/useSettingsController.ts +++ b/src/components/settings/hooks/useSettingsController.ts @@ -16,8 +16,6 @@ import type { CursorPermissionsState, GeminiPermissionMode, McpServer, - McpToolsResult, - McpTestResult, NotificationPreferencesState, ProjectSortOrder, SettingsMainTab, @@ -58,16 +56,6 @@ type McpCliReadResponse = { servers?: McpCliServer[]; }; -type McpTestResponse = { - testResult?: McpTestResult; - error?: string; -}; - -type McpToolsResponse = { - toolsResult?: McpToolsResult; - error?: string; -}; - type ClaudeSettingsStorage = { allowedTools?: string[]; disallowedTools?: string[]; @@ -205,9 +193,6 @@ export function useSettingsController({ isOpen, initialTab }: UseSettingsControl const [mcpServers, setMcpServers] = useState([]); const [cursorMcpServers, setCursorMcpServers] = useState([]); const [codexMcpServers, setCodexMcpServers] = useState([]); - const [mcpTestResults, setMcpTestResults] = useState>({}); - const [mcpServerTools, setMcpServerTools] = useState>({}); - const [mcpToolsLoading, setMcpToolsLoading] = useState>({}); const [showMcpForm, setShowMcpForm] = useState(false); const [editingMcpServer, setEditingMcpServer] = useState(null); @@ -285,14 +270,7 @@ export function useSettingsController({ isOpen, initialTab }: UseSettingsControl } } - const fallbackResponse = await authenticatedFetch('/api/mcp/servers?scope=user'); - if (!fallbackResponse.ok) { - console.error('Failed to fetch MCP servers'); - return; - } - - const fallbackData = await toResponseJson<{ servers?: McpServer[] }>(fallbackResponse); - setMcpServers(fallbackData.servers || []); + console.error('Failed to fetch MCP servers'); } catch (error) { console.error('Error fetching MCP servers:', error); } @@ -422,76 +400,6 @@ export function useSettingsController({ isOpen, initialTab }: UseSettingsControl [deleteMcpServer, fetchMcpServers], ); - const testMcpServer = useCallback(async (serverId: string, scope = 'user') => { - const response = await authenticatedFetch(`/api/mcp/servers/${serverId}/test?scope=${scope}`, { - method: 'POST', - }); - - if (!response.ok) { - const error = await toResponseJson(response); - throw new Error(error.error || 'Failed to test server'); - } - - const data = await toResponseJson(response); - return data.testResult || { success: false, message: 'No test result returned' }; - }, []); - - const discoverMcpTools = useCallback(async (serverId: string, scope = 'user') => { - const response = await authenticatedFetch(`/api/mcp/servers/${serverId}/tools?scope=${scope}`, { - method: 'POST', - }); - - if (!response.ok) { - const error = await toResponseJson(response); - throw new Error(error.error || 'Failed to discover tools'); - } - - const data = await toResponseJson(response); - return data.toolsResult || { success: false, tools: [], resources: [], prompts: [] }; - }, []); - - const handleMcpTest = useCallback( - async (serverId: string, scope = 'user') => { - try { - setMcpTestResults((prev) => ({ - ...prev, - [serverId]: { success: false, message: 'Testing server...', details: [], loading: true }, - })); - - const result = await testMcpServer(serverId, scope); - setMcpTestResults((prev) => ({ ...prev, [serverId]: result })); - } catch (error) { - setMcpTestResults((prev) => ({ - ...prev, - [serverId]: { - success: false, - message: getErrorMessage(error), - details: [], - }, - })); - } - }, - [testMcpServer], - ); - - const handleMcpToolsDiscovery = useCallback( - async (serverId: string, scope = 'user') => { - try { - setMcpToolsLoading((prev) => ({ ...prev, [serverId]: true })); - const result = await discoverMcpTools(serverId, scope); - setMcpServerTools((prev) => ({ ...prev, [serverId]: result })); - } catch { - setMcpServerTools((prev) => ({ - ...prev, - [serverId]: { success: false, tools: [], resources: [], prompts: [] }, - })); - } finally { - setMcpToolsLoading((prev) => ({ ...prev, [serverId]: false })); - } - }, - [discoverMcpTools], - ); - const deleteCodexMcpServer = useCallback(async (serverId: string) => { const response = await authenticatedFetch(`/api/codex/mcp/cli/remove/${serverId}`, { method: 'DELETE', @@ -835,17 +743,12 @@ export function useSettingsController({ isOpen, initialTab }: UseSettingsControl mcpServers, cursorMcpServers, codexMcpServers, - mcpTestResults, - mcpServerTools, - mcpToolsLoading, showMcpForm, editingMcpServer, openMcpForm, closeMcpForm, submitMcpForm, handleMcpDelete, - handleMcpTest, - handleMcpToolsDiscovery, showCodexMcpForm, editingCodexMcpServer, openCodexMcpForm, diff --git a/src/components/settings/types/types.ts b/src/components/settings/types/types.ts index 235d0b47..74c125ed 100644 --- a/src/components/settings/types/types.ts +++ b/src/components/settings/types/types.ts @@ -77,25 +77,6 @@ export type CodexMcpFormState = { config: CodexMcpFormConfig; }; -export type McpTestResult = { - success: boolean; - message: string; - details?: string[]; - loading?: boolean; -}; - -export type McpTool = { - name: string; - [key: string]: unknown; -}; - -export type McpToolsResult = { - success?: boolean; - tools?: McpTool[]; - resources?: unknown[]; - prompts?: unknown[]; -}; - export type ClaudePermissionsState = { allowedTools: string[]; disallowedTools: string[]; diff --git a/src/components/settings/view/Settings.tsx b/src/components/settings/view/Settings.tsx index c1977cf2..d7d45c5e 100644 --- a/src/components/settings/view/Settings.tsx +++ b/src/components/settings/view/Settings.tsx @@ -39,17 +39,12 @@ function Settings({ isOpen, onClose, projects = [], initialTab = 'agents' }: Set mcpServers, cursorMcpServers, codexMcpServers, - mcpTestResults, - mcpServerTools, - mcpToolsLoading, showMcpForm, editingMcpServer, openMcpForm, closeMcpForm, submitMcpForm, handleMcpDelete, - handleMcpTest, - handleMcpToolsDiscovery, showCodexMcpForm, editingCodexMcpServer, openCodexMcpForm, @@ -159,13 +154,8 @@ function Settings({ isOpen, onClose, projects = [], initialTab = 'agents' }: Set mcpServers={mcpServers} cursorMcpServers={cursorMcpServers} codexMcpServers={codexMcpServers} - mcpTestResults={mcpTestResults} - mcpServerTools={mcpServerTools} - mcpToolsLoading={mcpToolsLoading} onOpenMcpForm={openMcpForm} onDeleteMcpServer={handleMcpDelete} - onTestMcpServer={handleMcpTest} - onDiscoverMcpTools={handleMcpToolsDiscovery} onOpenCodexMcpForm={openCodexMcpForm} onDeleteCodexMcpServer={handleCodexMcpDelete} deleteError={deleteError} diff --git a/src/components/settings/view/tabs/agents-settings/AgentsSettingsTab.tsx b/src/components/settings/view/tabs/agents-settings/AgentsSettingsTab.tsx index c1ad2e35..7ef02389 100644 --- a/src/components/settings/view/tabs/agents-settings/AgentsSettingsTab.tsx +++ b/src/components/settings/view/tabs/agents-settings/AgentsSettingsTab.tsx @@ -19,14 +19,9 @@ export default function AgentsSettingsTab({ mcpServers, cursorMcpServers, codexMcpServers, - mcpTestResults, - mcpServerTools, - mcpToolsLoading, deleteError, onOpenMcpForm, onDeleteMcpServer, - onTestMcpServer, - onDiscoverMcpTools, onOpenCodexMcpForm, onDeleteCodexMcpServer, }: AgentsSettingsTabProps) { @@ -87,14 +82,9 @@ export default function AgentsSettingsTab({ mcpServers={mcpServers} cursorMcpServers={cursorMcpServers} codexMcpServers={codexMcpServers} - mcpTestResults={mcpTestResults} - mcpServerTools={mcpServerTools} - mcpToolsLoading={mcpToolsLoading} deleteError={deleteError} onOpenMcpForm={onOpenMcpForm} onDeleteMcpServer={onDeleteMcpServer} - onTestMcpServer={onTestMcpServer} - onDiscoverMcpTools={onDiscoverMcpTools} onOpenCodexMcpForm={onOpenCodexMcpForm} onDeleteCodexMcpServer={onDeleteCodexMcpServer} /> diff --git a/src/components/settings/view/tabs/agents-settings/sections/AgentCategoryContentSection.tsx b/src/components/settings/view/tabs/agents-settings/sections/AgentCategoryContentSection.tsx index 3852df03..94b5d1c6 100644 --- a/src/components/settings/view/tabs/agents-settings/sections/AgentCategoryContentSection.tsx +++ b/src/components/settings/view/tabs/agents-settings/sections/AgentCategoryContentSection.tsx @@ -16,14 +16,9 @@ export default function AgentCategoryContentSection({ mcpServers, cursorMcpServers, codexMcpServers, - mcpTestResults, - mcpServerTools, - mcpToolsLoading, deleteError, onOpenMcpForm, onDeleteMcpServer, - onTestMcpServer, - onDiscoverMcpTools, onOpenCodexMcpForm, onDeleteCodexMcpServer, }: AgentCategoryContentSectionProps) { @@ -91,11 +86,6 @@ export default function AgentCategoryContentSection({ onAdd={() => onOpenMcpForm()} onEdit={(server) => onOpenMcpForm(server)} onDelete={onDeleteMcpServer} - onTest={onTestMcpServer} - onDiscoverTools={onDiscoverMcpTools} - testResults={mcpTestResults} - serverTools={mcpServerTools} - toolsLoading={mcpToolsLoading} deleteError={deleteError} /> )} diff --git a/src/components/settings/view/tabs/agents-settings/sections/content/McpServersContent.tsx b/src/components/settings/view/tabs/agents-settings/sections/content/McpServersContent.tsx index c62f8f8f..7384cfe9 100644 --- a/src/components/settings/view/tabs/agents-settings/sections/content/McpServersContent.tsx +++ b/src/components/settings/view/tabs/agents-settings/sections/content/McpServersContent.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'; import { Badge, Button } from '../../../../../../../shared/view/ui'; import { IS_PLATFORM } from '../../../../../../../constants/config'; import PremiumFeatureCard from '../../../../PremiumFeatureCard'; -import type { McpServer, McpToolsResult, McpTestResult } from '../../../../../types/types'; +import type { McpServer } from '../../../../../types/types'; const getTransportIcon = (type: string | undefined) => { if (type === 'stdio') { @@ -36,11 +36,6 @@ type ClaudeMcpServersProps = { onAdd: () => void; onEdit: (server: McpServer) => void; onDelete: (serverId: string, scope?: string) => void; - onTest: (serverId: string, scope?: string) => void; - onDiscoverTools: (serverId: string, scope?: string) => void; - testResults: Record; - serverTools: Record; - toolsLoading: Record; deleteError?: string | null; }; @@ -49,10 +44,8 @@ function ClaudeMcpServers({ onAdd, onEdit, onDelete, - testResults, - serverTools, deleteError, -}: Omit) { +}: Omit) { const { t } = useTranslation('settings'); return ( @@ -78,8 +71,6 @@ function ClaudeMcpServers({
{servers.map((server) => { const serverId = server.id || server.name; - const testResult = testResults[serverId]; - const toolsResult = serverTools[serverId]; return (
@@ -121,36 +112,6 @@ function ClaudeMcpServers({ )}
- {testResult && ( -
-
{testResult.message}
-
- )} - - {toolsResult && toolsResult.tools && toolsResult.tools.length > 0 && ( -
-
- {t('mcpServers.tools.title')} {t('mcpServers.tools.count', { count: toolsResult.tools.length })} -
-
- {toolsResult.tools.slice(0, 5).map((tool, index) => ( - - {tool.name} - - ))} - {toolsResult.tools.length > 5 && ( - - {t('mcpServers.tools.more', { count: toolsResult.tools.length - 5 })} - - )} -
-
- )}
diff --git a/src/components/settings/view/tabs/agents-settings/types.ts b/src/components/settings/view/tabs/agents-settings/types.ts index a2cecdc8..0ee43070 100644 --- a/src/components/settings/view/tabs/agents-settings/types.ts +++ b/src/components/settings/view/tabs/agents-settings/types.ts @@ -7,8 +7,6 @@ import type { CodexPermissionMode, GeminiPermissionMode, McpServer, - McpToolsResult, - McpTestResult, } from '../../../types/types'; export type AgentContext = { @@ -33,14 +31,9 @@ export type AgentsSettingsTabProps = { mcpServers: McpServer[]; cursorMcpServers: McpServer[]; codexMcpServers: McpServer[]; - mcpTestResults: Record; - mcpServerTools: Record; - mcpToolsLoading: Record; deleteError: string | null; onOpenMcpForm: (server?: McpServer) => void; onDeleteMcpServer: (serverId: string, scope?: string) => void; - onTestMcpServer: (serverId: string, scope?: string) => void; - onDiscoverMcpTools: (serverId: string, scope?: string) => void; onOpenCodexMcpForm: (server?: McpServer) => void; onDeleteCodexMcpServer: (serverId: string) => void; }; @@ -71,14 +64,9 @@ export type AgentCategoryContentSectionProps = { mcpServers: McpServer[]; cursorMcpServers: McpServer[]; codexMcpServers: McpServer[]; - mcpTestResults: Record; - mcpServerTools: Record; - mcpToolsLoading: Record; deleteError: string | null; onOpenMcpForm: (server?: McpServer) => void; onDeleteMcpServer: (serverId: string, scope?: string) => void; - onTestMcpServer: (serverId: string, scope?: string) => void; - onDiscoverMcpTools: (serverId: string, scope?: string) => void; onOpenCodexMcpForm: (server?: McpServer) => void; onDeleteCodexMcpServer: (serverId: string) => void; };