start_intensive_chat
Start a persistent chat session to collect multiple user inputs quickly for multi-step processes, brainstorming, or sequential configurations.
Instructions
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| sessionTitle | Yes | Title for the intensive chat session |
Implementation Reference
- Core handler function `startIntensiveChatSession` that implements the logic for starting an intensive chat session: creates temp dir, spawns platform-specific child process running ui.js with session payload.export async function startIntensiveChatSession( title: string, timeoutSeconds?: number, ): Promise<string> { // Create a session directory const sessionDir = await createSessionDir(); // Generate a unique session ID const sessionId = path.basename(sessionDir).replace('intensive-chat-', ''); // Path to the UI script - Updated to use the compiled 'ui.js' filename const uiScriptPath = path.join(__dirname, 'ui.js'); // Create options payload for the UI const options = { sessionId, title, outputDir: sessionDir, timeoutSeconds, }; // Encode options as base64 payload const payload = Buffer.from(JSON.stringify(options)).toString('base64'); // Platform-specific spawning const platform = os.platform(); let childProcess: ChildProcess; if (platform === 'darwin') { // macOS // Escape potential special characters in paths/payload for the shell command // For the shell command executed by 'do script', we primarily need to handle spaces // or other characters that might break the command if paths aren't quoted. // The `${...}` interpolation within backticks handles basic variable insertion. // Quoting the paths within nodeCommand handles spaces. const escapedScriptPath = uiScriptPath; // Keep original path, rely on quotes below const escapedPayload = payload; // Keep original payload, rely on quotes below // Construct the command string directly for the shell. Quotes handle paths with spaces. const nodeCommand = `exec node "${escapedScriptPath}" "${escapedPayload}"; exit 0`; // Escape the node command for osascript's AppleScript string: // 1. Escape existing backslashes (\ -> \\) // 2. Escape double quotes (" -> \") const escapedNodeCommand = nodeCommand // Escape backslashes first .replace(/\\/g, '\\\\') // Using /\\/g instead of /\/g // Then escape double quotes .replace(/"/g, '\\"'); // Activate Terminal first, then do script with exec const command = `osascript -e 'tell application "Terminal" to activate' -e 'tell application "Terminal" to do script "${escapedNodeCommand}"'`; const commandArgs: string[] = []; // No args needed when command is a single string for shell childProcess = spawn(command, commandArgs, { stdio: ['ignore', 'ignore', 'ignore'], shell: true, detached: true, }); } else if (platform === 'win32') { // Windows childProcess = spawn('node', [uiScriptPath, payload], { stdio: ['ignore', 'ignore', 'ignore'], shell: true, detached: true, windowsHide: false, }); } else { // Linux or other - use original method (might not pop up window) childProcess = spawn('node', [uiScriptPath, payload], { stdio: ['ignore', 'ignore', 'ignore'], shell: true, detached: true, }); } // Unref the process so it can run independently childProcess.unref(); // Store session info activeSessions[sessionId] = { id: sessionId, process: childProcess, // Use the conditionally spawned process outputDir: sessionDir, lastHeartbeatTime: Date.now(), isActive: true, title, }; // Wait a bit to ensure the UI has started await new Promise((resolve) => setTimeout(resolve, 500)); return sessionId; }
- src/index.ts:175-221 (registration)Registers the 'start_intensive_chat' MCP tool on the server, providing description, schema from tool-definitions, and inline async handler that calls startIntensiveChatSession and handles response/error formatting.server.tool( 'start_intensive_chat', // Description is a function here typeof intensiveChatTools.start.description === 'function' ? intensiveChatTools.start.description(globalTimeoutSeconds) : intensiveChatTools.start.description, intensiveChatTools.start.schema, // Use schema property async (args) => { // Use inferred args type const { sessionTitle } = args; try { // Start a new intensive chat session, passing global timeout const sessionId = await startIntensiveChatSession( sessionTitle, globalTimeoutSeconds, ); // Track this session for the client activeChatSessions.set(sessionId, sessionTitle); return { content: [ { type: 'text', text: `Intensive chat session started successfully. Session ID: ${sessionId}`, }, ], }; } catch (error: unknown) { let errorMessage = 'Failed to start intensive chat session.'; if (error instanceof Error) { errorMessage = `Failed to start intensive chat session: ${error.message}`; } else if (typeof error === 'string') { errorMessage = `Failed to start intensive chat session: ${error}`; } return { content: [ { type: 'text', text: errorMessage, }, ], }; } }, ); }
- Defines the input schema (JSON Schema in capability.parameters and Zod schema) and tool definition object for 'start_intensive_chat' used in registration.const startCapability: ToolCapabilityInfo = { description: 'Start an intensive chat session for gathering multiple answers quickly.', parameters: { type: 'object', properties: { sessionTitle: { type: 'string', description: 'Title for the intensive chat session', }, }, required: ['sessionTitle'], }, }; const startDescription: ToolRegistrationDescription = ( globalTimeoutSeconds: number, ) => `<description> Start an intensive chat session for gathering multiple answers quickly from the user. **Highly recommended** for scenarios requiring a sequence of related inputs or confirmations. Very useful for gathering multiple answers from the user in a short period of time. Especially useful for brainstorming ideas or discussing complex topics with the user. </description> <importantNotes> - (!important!) Opens a persistent console window that stays open for multiple questions. - (!important!) Returns a session ID that **must** be used for subsequent questions via 'ask_intensive_chat'. - (!important!) **Must** be closed with 'stop_intensive_chat' when finished gathering all inputs. - (!important!) After starting a session, **immediately** continue asking all necessary questions using 'ask_intensive_chat' within the **same response message**. Do not end the response until the chat is closed with 'stop_intensive_chat'. This creates a seamless conversational flow for the user. </importantNotes> <whenToUseThisTool> - When you need to collect a series of quick answers from the user (more than 2-3 questions) - When setting up a project with multiple configuration options - When guiding a user through a multi-step process requiring input at each stage - When gathering sequential user preferences - When you want to maintain context between multiple related questions efficiently - When brainstorming ideas with the user interactively </whenToUseThisTool> <features> - Opens a persistent console window for continuous interaction - Supports starting with an initial question - Configurable timeout for each question (set via -t/--timeout, defaults to ${globalTimeoutSeconds} seconds) - Returns a session ID for subsequent interactions - Keeps full chat history visible to the user - Maintains state between questions </features> <bestPractices> - Use a descriptive session title related to the task - Start with a clear initial question when possible - Do not ask the question if you have another tool that can answer the question - e.g. when you searching file in the current repository, do not ask the question "Do you want to search for a file in the current repository?" - e.g. prefer to use other tools to find the answer (Cursor tools or other MCP Server tools) - Always store the returned session ID for later use - Always close the session when you're done with stop_intensive_chat </bestPractices> <parameters> - sessionTitle: Title for the intensive chat session (appears at the top of the console) </parameters> <examples> - Start session for project setup: { "sessionTitle": "Project Configuration" } </examples>`; const startSchema: ZodRawShape = { sessionTitle: z.string().describe('Title for the intensive chat session'), }; const startToolDefinition: ToolDefinition = { capability: startCapability, description: startDescription, schema: startSchema, };