Skip to main content
Glama
mikeysrecipes

interactive-mcp

ask_intensive_chat

Ask follow-up questions within an active chat session to gather sequential information or offer multiple-choice options for user responses.

Instructions

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
sessionIdYesID of the intensive chat session
questionYesQuestion to ask the user
predefinedOptionsNoPredefined options for the user to choose from (optional)

Implementation Reference

  • MCP tool handler for 'ask_intensive_chat': destructures args, checks active session, calls askQuestionInSession helper, handles timeout/empty/error responses and formats MCP content response
    async (args) => {
      // Use inferred args type
      const { sessionId, question, predefinedOptions } = args;
      // Check if session exists
      if (!activeChatSessions.has(sessionId)) {
        return {
          content: [
            { type: 'text', text: 'Error: Invalid or expired session ID.' },
          ],
        };
      }
    
      try {
        // Ask the question in the session
        const answer = await askQuestionInSession(
          sessionId,
          question,
          predefinedOptions,
        );
    
        // Check for the specific timeout indicator
        if (answer === '__TIMEOUT__') {
          return {
            content: [
              {
                type: 'text',
                text: 'User did not reply to question in intensive chat: Timeout occurred.',
              },
            ],
          };
        }
        // Empty string means user submitted empty input, non-empty is actual reply
        else if (answer === '') {
          return {
            content: [
              {
                type: 'text',
                text: 'User replied with empty input in intensive chat.',
              },
            ],
          };
        } else {
          return {
            content: [{ type: 'text', text: `User replied: ${answer}` }],
          };
        }
      } catch (error: unknown) {
        let errorMessage = 'Failed to ask question in session.';
        if (error instanceof Error) {
          errorMessage = `Failed to ask question in session: ${error.message}`;
        } else if (typeof error === 'string') {
          errorMessage = `Failed to ask question in session: ${error}`;
        }
        return {
          content: [
            {
              type: 'text',
              text: errorMessage,
            },
          ],
        };
      }
    },
  • Zod schema defining input parameters for ask_intensive_chat tool: sessionId (required), question (required), predefinedOptions (optional array)
    const askSchema: ZodRawShape = {
      sessionId: z.string().describe('ID of the intensive chat session'),
      question: z.string().describe('Question to ask the user'),
      predefinedOptions: z
        .array(z.string())
        .optional()
        .describe('Predefined options for the user to choose from (optional)'),
    };
  • src/index.ts:223-296 (registration)
    Registration of 'ask_intensive_chat' tool with MCP server using server.tool(), including dynamic description, schema from intensiveChatTools, and handler function
    if (isToolEnabled('ask_intensive_chat')) {
      // Use properties from the imported intensiveChatTools object
      server.tool(
        'ask_intensive_chat',
        // Description is a string here
        typeof intensiveChatTools.ask.description === 'function'
          ? intensiveChatTools.ask.description(globalTimeoutSeconds) // Should not happen, but safe
          : intensiveChatTools.ask.description,
        intensiveChatTools.ask.schema, // Use schema property
        async (args) => {
          // Use inferred args type
          const { sessionId, question, predefinedOptions } = args;
          // Check if session exists
          if (!activeChatSessions.has(sessionId)) {
            return {
              content: [
                { type: 'text', text: 'Error: Invalid or expired session ID.' },
              ],
            };
          }
    
          try {
            // Ask the question in the session
            const answer = await askQuestionInSession(
              sessionId,
              question,
              predefinedOptions,
            );
    
            // Check for the specific timeout indicator
            if (answer === '__TIMEOUT__') {
              return {
                content: [
                  {
                    type: 'text',
                    text: 'User did not reply to question in intensive chat: Timeout occurred.',
                  },
                ],
              };
            }
            // Empty string means user submitted empty input, non-empty is actual reply
            else if (answer === '') {
              return {
                content: [
                  {
                    type: 'text',
                    text: 'User replied with empty input in intensive chat.',
                  },
                ],
              };
            } else {
              return {
                content: [{ type: 'text', text: `User replied: ${answer}` }],
              };
            }
          } catch (error: unknown) {
            let errorMessage = 'Failed to ask question in session.';
            if (error instanceof Error) {
              errorMessage = `Failed to ask question in session: ${error.message}`;
            } else if (typeof error === 'string') {
              errorMessage = `Failed to ask question in session: ${error}`;
            }
            return {
              content: [
                {
                  type: 'text',
                  text: errorMessage,
                },
              ],
            };
          }
        },
      );
    }
  • Helper function implementing the core logic: writes question to session JSON file, generates unique question ID, polls for corresponding response file, handles timeout and session checks
    export async function askQuestionInSession(
      sessionId: string,
      question: string,
      predefinedOptions?: string[],
    ): Promise<string | null> {
      const session = activeSessions[sessionId];
    
      if (!session || !session.isActive) {
        return null; // Session doesn't exist or is not active
      }
    
      // Generate a unique ID for this question-answer pair
      const questionId = crypto.randomUUID();
    
      // Create the input data object
      const inputData: { id: string; text: string; options?: string[] } = {
        id: questionId,
        text: question,
      };
    
      if (predefinedOptions && predefinedOptions.length > 0) {
        inputData.options = predefinedOptions;
      }
    
      // Write the combined input data to a session-specific JSON file
      const inputFilePath = path.join(session.outputDir, `${sessionId}.json`);
      await fs.writeFile(inputFilePath, JSON.stringify(inputData), 'utf8');
    
      // Wait for the response file corresponding to the generated ID
      const responseFilePath = path.join(
        session.outputDir,
        `response-${questionId}.txt`,
      );
    
      // Wait for response with timeout
      const maxWaitTime = 60000; // 60 seconds max wait time
      const pollInterval = 100; // 100ms polling interval
      const startTime = Date.now();
    
      while (Date.now() - startTime < maxWaitTime) {
        try {
          // Check if the response file exists
          await fs.access(responseFilePath);
    
          // Read the response
          const response = await fs.readFile(responseFilePath, 'utf8');
    
          // Clean up the response file
          await fs.unlink(responseFilePath).catch(() => {});
    
          return response;
        } catch {
          // Response file doesn't exist yet, check session status
          if (!(await isSessionActive(sessionId))) {
            return null; // Session has ended
          }
    
          // Wait before polling again
          await new Promise((resolve) => setTimeout(resolve, pollInterval));
        }
      }
    
      // Timeout reached
      return 'User closed intensive chat session';
    }
  • src/index.ts:28-34 (registration)
    Initial registration of tool capabilities including 'ask_intensive_chat' from intensiveChatTools.ask.capability for MCP server capabilities
    const allToolCapabilities = {
      request_user_input: requestUserInputTool.capability,
      message_complete_notification: messageCompleteNotificationTool.capability,
      start_intensive_chat: intensiveChatTools.start.capability,
      ask_intensive_chat: intensiveChatTools.ask.capability,
      stop_intensive_chat: intensiveChatTools.stop.capability,
    } satisfies ToolCapabilitiesStructure;

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/mikeysrecipes/interactive-mcp'

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