Skip to main content
Glama
ttommyth

Interactive MCP

ask_intensive_chat

Ask follow-up questions in an existing interactive chat session to gather sequential information or present multiple-choice options.

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

  • The MCP server.tool handler function for 'ask_intensive_chat'. Validates session existence, calls askQuestionInSession, handles responses including timeouts and errors, 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,
            },
          ],
        };
      }
    },
  • Core helper function that implements the logic for asking a question in an intensive chat session. Writes question to session JSON file and polls for user response file with timeout.
    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 = (session.timeoutSeconds ?? 60) * 1000; // Use session timeout or default to 60s
      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';
    }
  • Zod schema defining input parameters for the ask_intensive_chat tool: sessionId, question, and optional predefinedOptions.
    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:232-302 (registration)
    Registration of the 'ask_intensive_chat' tool on the MCP server, specifying name, description, schema, and handler function.
    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,
              },
            ],
          };
        }
      },
    );
  • JSON schema capability definition for the ask_intensive_chat tool, used for MCP protocol advertisement and validation.
    const askCapability: ToolCapabilityInfo = {
      description: 'Ask a question in an active intensive chat session.',
      parameters: {
        type: 'object',
        properties: {
          sessionId: {
            type: 'string',
            description: 'ID of the intensive chat session',
          },
          question: {
            type: 'string',
            description: 'Question to ask the user',
          },
          predefinedOptions: {
            type: 'array',
            items: { type: 'string' },
            optional: true,
            description:
              'Predefined options for the user to choose from (optional)',
          },
        },
        required: ['sessionId', 'question'],
      },

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