Skip to main content
Glama

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