Skip to main content
Glama
mikeysrecipes

interactive-mcp

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
NameRequiredDescriptionDefault
sessionTitleYesTitle 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,
    };

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observed

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description fully discloses behaviors: opens persistent console window, returns session ID, must be closed, configurable timeout, maintains chat history, and warns against unnecessary questions. This is comprehensive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with separate sections but contains some redundancy (e.g., 'Highly recommended' and 'Very useful' are similar). It is thorough but could be slightly more concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the simple parameter list, no output schema, and missing annotations, the description covers all necessary aspects: purpose, usage, important notes, parameters, examples, and best practices. It feels complete for the tool's role.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Only one parameter (sessionTitle) with 100% schema coverage. The description adds context that the title appears at the top of the console, which goes beyond the schema's description. A score of 4 is appropriate for the added value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it starts an intensive chat session for gathering multiple answers quickly. It uses specific verbs like 'start', 'gather', 'opens', and distinguishes from sibling tools such as ask_intensive_chat and stop_intensive_chat.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description includes explicit when-to-use scenarios (e.g., collecting series of quick answers, multi-step processes) and when-not-to-use (e.g., prefer other tools if they can answer). It also provides important instructions on using ask_intensive_chat and closing with stop_intensive_chat in the same response.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.