From 3b277c3925184545d09956a923002a72dc2b823e Mon Sep 17 00:00:00 2001 From: Carlos Gutierrez Date: Mon, 2 Feb 2026 13:40:55 -0500 Subject: [PATCH] fixing the issues on mcp --- src/commands/components/execute/execute.tsx | 45 +++++++++++++++++++-- src/services/mcp/manager.ts | 7 ++-- src/tui-solid/components/mcp-add-form.tsx | 30 ++++++++++++-- 3 files changed, 73 insertions(+), 9 deletions(-) diff --git a/src/commands/components/execute/execute.tsx b/src/commands/components/execute/execute.tsx index a81b07d..f2bdde7 100644 --- a/src/commands/components/execute/execute.tsx +++ b/src/commands/components/execute/execute.tsx @@ -51,10 +51,49 @@ export interface RenderAppProps { } | null; } +/** + * Parse arguments string, respecting quoted strings + * Supports both single and double quotes for arguments with spaces + * Example: '-y @modelcontextprotocol/server-filesystem "/path/with spaces"' + */ +const parseArgs = (argsString: string): string[] | undefined => { + const trimmed = argsString.trim(); + if (!trimmed) return undefined; + + const args: string[] = []; + let current = ""; + let inQuote: string | null = null; + + for (let i = 0; i < trimmed.length; i++) { + const char = trimmed[i]; + + if (inQuote) { + if (char === inQuote) { + inQuote = null; + } else { + current += char; + } + } else if (char === '"' || char === "'") { + inQuote = char; + } else if (char === " " || char === "\t") { + if (current) { + args.push(current); + current = ""; + } + } else { + current += char; + } + } + + if (current) { + args.push(current); + } + + return args.length > 0 ? args : undefined; +}; + const defaultHandleMCPAdd = async (data: MCPAddFormData): Promise => { - const serverArgs = data.args.trim() - ? data.args.trim().split(/\s+/) - : undefined; + const serverArgs = parseArgs(data.args); await addServer( data.name, diff --git a/src/services/mcp/manager.ts b/src/services/mcp/manager.ts index 8486265..6bde2d2 100644 --- a/src/services/mcp/manager.ts +++ b/src/services/mcp/manager.ts @@ -4,8 +4,8 @@ import fs from "fs/promises"; import path from "path"; -import os from "os"; import { MCPClient } from "@services/mcp/client"; +import { DIRS, LOCAL_CONFIG_DIR } from "@constants/paths"; import type { MCPConfig, MCPServerConfig, @@ -16,10 +16,11 @@ import type { /** * MCP Configuration file locations + * Uses XDG-compliant paths from constants/paths.ts */ const CONFIG_LOCATIONS = { - global: path.join(os.homedir(), ".codetyper", "mcp.json"), - local: path.join(process.cwd(), ".codetyper", "mcp.json"), + global: path.join(DIRS.config, "mcp.json"), + local: path.join(process.cwd(), LOCAL_CONFIG_DIR, "mcp.json"), }; /** diff --git a/src/tui-solid/components/mcp-add-form.tsx b/src/tui-solid/components/mcp-add-form.tsx index 295a0a5..ab198b6 100644 --- a/src/tui-solid/components/mcp-add-form.tsx +++ b/src/tui-solid/components/mcp-add-form.tsx @@ -17,14 +17,14 @@ const FIELD_ORDER: FormField[] = ["name", "command", "args", "scope"]; const FIELD_LABELS: Record = { name: "Server Name", command: "Command", - args: "Arguments (space-separated)", + args: "Arguments (use quotes for paths with spaces)", scope: "Scope", }; const FIELD_PLACEHOLDERS: Record = { - name: "e.g., sqlite", + name: "e.g., filesystem", command: "e.g., npx", - args: "e.g., @modelcontextprotocol/server-sqlite", + args: "e.g., -y @modelcontextprotocol/server-filesystem \"/path/to/dir\"", scope: "", }; @@ -165,10 +165,34 @@ export function MCPAddForm(props: MCPAddFormProps) { return; } + // Handle space key + if (evt.name === "space") { + setFieldValue(field, getFieldValue(field) + " "); + setError(null); + evt.preventDefault(); + return; + } + + // Handle paste (Ctrl+V) - terminal paste usually comes as sequence of characters + // but some terminals send the full pasted text as a single event + if (evt.ctrl && evt.name === "v") { + // Let the terminal handle paste - don't prevent default + return; + } + + // Handle regular character input if (evt.name.length === 1 && !evt.ctrl && !evt.meta) { setFieldValue(field, getFieldValue(field) + evt.name); setError(null); evt.preventDefault(); + return; + } + + // Handle multi-character input (e.g., pasted text from terminal) + if (evt.sequence && evt.sequence.length > 1 && !evt.ctrl && !evt.meta) { + setFieldValue(field, getFieldValue(field) + evt.sequence); + setError(null); + evt.preventDefault(); } });