readChat
Retrieve recent Minecraft server chat messages, including player chats, whispers, system alerts, action bar messages, and titles. Filter by type, username, or timeframe for focused insights.
Instructions
Read recent chat messages from the server. Returns player messages, system messages, whispers, action bar messages, and titles.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| count | No | Number of recent messages to return (default: 20, max: 100) | |
| filterType | No | Filter by message type: 'all', 'chat', 'whisper', 'system', 'actionbar', 'title' (default: 'all') | |
| filterUsername | No | Filter messages by specific username (optional) | |
| timeLimit | No | Only return messages from the last N seconds (optional) |
Implementation Reference
- The main handler function for the readChat MCP tool. It retrieves filtered recent chat messages from the bot's history, formats them, and outputs via bot.emit('alteraBotEndObservation').export const readChat = async ( bot: Bot, params: ISkillParams, serviceParams: ISkillServiceParams, ): Promise<boolean> => { const skillName = 'readChat'; const requiredParams: string[] = []; const isParamsValid = validateSkillParams( params, requiredParams, skillName, ); if (!isParamsValid) { serviceParams.cancelExecution?.(); bot.emit( 'alteraBotEndObservation', `Mistake: You didn't provide all of the required parameters ${requiredParams.join(', ')} for the ${skillName} skill.`, ); return false; } // Initialize chat history for this bot if not exists if (!chatHistories.has(bot)) { initializeChatHistory(bot); } const history = chatHistories.get(bot) || []; // Parse parameters with defaults const count = Math.min(params.count || 20, 100); // Cap at 100 messages const timeLimit = params.timeLimit as number | undefined; const filterType = (params.filterType || 'all') as string; const filterUsername = params.filterUsername as string | undefined; // Filter messages based on parameters let filteredMessages = [...history]; // Copy array to avoid mutation // Apply time filter if specified if (timeLimit && timeLimit > 0) { const cutoffTime = new Date(Date.now() - (timeLimit * 1000)); filteredMessages = filteredMessages.filter(msg => msg.timestamp >= cutoffTime); } // Apply type filter if (filterType !== 'all') { filteredMessages = filteredMessages.filter(msg => msg.type === filterType); } // Apply username filter if (filterUsername) { filteredMessages = filteredMessages.filter(msg => msg.username && msg.username.toLowerCase() === filterUsername.toLowerCase() ); } // Get the most recent messages up to count const recentMessages = filteredMessages.slice(-count); // Format messages for output const formattedMessages = recentMessages.map(msg => { const timeStr = msg.timestamp.toLocaleTimeString(); let formatted = `[${timeStr}]`; switch (msg.type) { case 'chat': formatted += ` <${msg.username || 'Unknown'}>: ${msg.message}`; break; case 'whisper': formatted += ` [Whisper] <${msg.username || 'Unknown'}>: ${msg.message}`; break; case 'system': formatted += ` [System] ${msg.message}`; break; case 'actionbar': formatted += ` [Action Bar] ${msg.message}`; break; case 'title': formatted += ` [Title] ${msg.message}`; break; default: formatted += ` ${msg.message}`; } return formatted; }); // Create summary const summary = [ `=== Chat History ===`, `Showing ${recentMessages.length} messages`, filterType !== 'all' ? `Filtered by type: ${filterType}` : '', filterUsername ? `Filtered by user: ${filterUsername}` : '', timeLimit ? `From last ${timeLimit} seconds` : '', `==================`, ...formattedMessages ].filter(line => line !== '').join('\n'); bot.emit('alteraBotEndObservation', summary); return true; };
- Input schema definition for readChat tool, including parameters and description used for MCP tool listing.readChat: { description: "Read recent chat messages from the server. Returns player messages, system messages, whispers, action bar messages, and titles.", params: { count: { type: "number", description: "Number of recent messages to return (default: 20, max: 100)" }, timeLimit: { type: "number", description: "Only return messages from the last N seconds (optional)" }, filterType: { type: "string", description: "Filter by message type: 'all', 'chat', 'whisper', 'system', 'actionbar', 'title' (default: 'all')" }, filterUsername: { type: "string", description: "Filter messages by specific username (optional)" } }, required: [] },
- Helper function to initialize chat message collection by attaching Mineflayer event listeners to the bot.export function initializeChatHistory(bot: Bot): void { // Don't initialize twice if (chatHistories.has(bot)) { return; } const history: ChatMessage[] = []; chatHistories.set(bot, history); // Helper function to add message to history const addToHistory = (type: ChatMessage['type'], message: string, username?: string, rawMessage?: any) => { history.push({ timestamp: new Date(), type, message: message.toString(), username, rawMessage }); // Trim history if it gets too large if (history.length > MAX_HISTORY_SIZE) { history.splice(0, history.length - MAX_HISTORY_SIZE); } }; // Listen to various chat events bot.on('chat', (username, message) => { addToHistory('chat', message, username); }); bot.on('whisper', (username, message) => { addToHistory('whisper', message, username); }); // System messages (server messages, join/leave, etc.) bot.on('message', (jsonMsg) => { // Skip if it's a regular chat message (already handled) const msgText = jsonMsg.toString(); // Try to determine if it's a system message if (jsonMsg.json) { // Check if it's not a regular chat message const isChat = jsonMsg.json.translate === 'chat.type.text'; const isWhisper = jsonMsg.json.translate === 'commands.message.display.incoming'; if (!isChat && !isWhisper) { addToHistory('system', msgText, undefined, jsonMsg); } } }); // Action bar messages bot.on('actionBar', (jsonMsg) => { if (jsonMsg) { addToHistory('actionbar', jsonMsg.toString(), undefined, jsonMsg); } }); // Title messages bot.on('title', (text) => { if (text) { addToHistory('title', text.toString()); } }); // Clean up on bot end bot.once('end', () => { chatHistories.delete(bot); }); }
- mcp-server/src/mcp-server.ts:127-134 (registration)Registers all skills (including readChat) as MCP tools in the ListToolsRequestHandler response.// Add all registered skills as tools const skillTools = skillRegistry.getAllSkills().map(skill => ({ name: skill.name, description: skill.description, inputSchema: skill.inputSchema })); return { tools: [...tools, ...skillTools] };
- mcp-server/src/mcp-server.ts:220-220 (helper)Calls initializeChatHistory after bot spawn to enable readChat functionality.initializeChatHistory(bot);