Skip to main content
Glama
ttommyth

Interactive MCP

start_intensive_chat

Start a persistent chat session to collect multiple user inputs quickly for brainstorming, multi-step processes, or gathering sequential preferences.

Instructions

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
sessionTitleYesTitle for the intensive chat session

Implementation Reference

  • Core handler function that implements the logic for starting an intensive chat session: creates temp dir, spawns platform-specific child process for UI, stores session in global map, returns session ID.
    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 nodeBin = process.execPath;
        const nodeCommand = `exec "${nodeBin}" "${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
    
        // Fallback launcher using .command + open -a Terminal
        const launchViaOpenCommand = async () => {
          try {
            const launcherPath = path.join(
              sessionDir,
              `interactive-mcp-intchat-${sessionId}.command`,
            );
            const scriptContent = `#!/bin/bash\nexec "${process.execPath}" "${escapedScriptPath}" "${escapedPayload}"\n`;
            await fs.writeFile(launcherPath, scriptContent, 'utf8');
            await fs.chmod(launcherPath, 0o755);
            const openProc = spawn('open', ['-a', 'Terminal', launcherPath], {
              stdio: ['ignore', 'ignore', 'ignore'],
              detached: true,
            });
            openProc.unref();
          } catch (e) {
            logger.error(
              { error: e },
              'Fallback open -a Terminal failed (intensive chat)',
            );
          }
        };
    
        childProcess = spawn(command, commandArgs, {
          stdio: ['ignore', 'ignore', 'ignore'],
          shell: true,
          detached: true,
        });
    
        childProcess.on('error', () => {
          void launchViaOpenCommand();
        });
        childProcess.on('close', (code: number | null) => {
          if (code !== null && code !== 0) {
            void launchViaOpenCommand();
          }
        });
      } else if (platform === 'win32') {
        // Windows
        childProcess = spawn(process.execPath, [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(process.execPath, [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,
        timeoutSeconds,
      };
    
      // Wait a bit to ensure the UI has started
      await new Promise((resolve) => setTimeout(resolve, 500));
    
      return sessionId;
    }
  • src/index.ts:180-228 (registration)
    MCP server registration of the 'start_intensive_chat' tool, which validates input via schema, calls the handler startIntensiveChatSession, tracks session, and returns success/error response.
    if (isToolEnabled('start_intensive_chat')) {
      // Use properties from the imported intensiveChatTools object
      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,
                },
              ],
            };
          }
        },
      );
    }
  • Tool definition including schema (sessionTitle: string), capability/parameters, and detailed description for start_intensive_chat.
    const startToolDefinition: ToolDefinition = {
      capability: startCapability,
      description: startDescription,
      schema: startSchema,
    };
  • Capability definition with input parameters schema for the tool.
    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'],
      },
    };
  • src/index.ts:28-31 (registration)
    Initial declaration of tool capabilities including start_intensive_chat before filtering.
    const allToolCapabilities = {
      request_user_input: requestUserInputTool.capability,
      message_complete_notification: messageCompleteNotificationTool.capability,
      start_intensive_chat: intensiveChatTools.start.capability,

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ttommyth/interactive-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server