read-mcp-logs
Extract and analyze the latest logs from an MCP server to diagnose and troubleshoot issues by specifying the number of lines and server name for targeted insights.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| lines | No | Number of lines to read from the end | |
| serverName | No | Specific server name to filter logs for |
Implementation Reference
- src/index.ts:70-131 (handler)The async handler function that implements the core logic of the 'read-mcp-logs' tool. It reads MCP log files from the platform-specific log directory, filters for mcp*.log files, optionally filters by serverName, reads the last 'lines' number of lines from each, concatenates them with headers, and returns as markdown text content.
async ({ lines, serverName }) => { try { // Ensure log directory exists try { await fs.access(logDirectory); } catch (error) { return { isError: true, content: [{ type: "text", text: `Log directory not found at ${logDirectory}. Claude Desktop might not be installed or hasn't generated logs yet.` }] }; } // Get all log files const files = await fs.readdir(logDirectory); // Filter for MCP logs const mcpLogs = files.filter(file => file.startsWith("mcp")); if (mcpLogs.length === 0) { return { content: [{ type: "text", text: "No MCP log files found in the log directory." }] }; } // Further filter for specific server if requested const targetLogs = serverName ? mcpLogs.filter(file => file.includes(serverName)) : mcpLogs; if (targetLogs.length === 0 && serverName) { return { content: [{ type: "text", text: `No logs found for server name '${serverName}'.` }] }; } // Read and concatenate log content let combinedLogs = ""; for (const logFile of targetLogs) { const filePath = path.join(logDirectory, logFile); try { let content = await fs.readFile(filePath, 'utf-8'); // Get last N lines const allLines = content.split('\n'); const lastLines = allLines.slice(-lines).join('\n'); combinedLogs += `\n---- ${logFile} ----\n${lastLines}\n\n`; } catch (error) { combinedLogs += `\n---- ${logFile} ----\nError reading file: ${error.message}\n\n`; } } return { content: [{ type: "text", text: combinedLogs || "Log files exist but are empty." }] }; } catch (error) { return { isError: true, content: [{ type: "text", text: `Error reading logs: ${error.message}` }] }; } } - src/index.ts:66-69 (schema)Zod input schema defining the parameters for the 'read-mcp-logs' tool: optional 'lines' (default 100) and optional 'serverName' for filtering.
{ lines: z.number().optional().default(100).describe("Number of lines to read from the end"), serverName: z.string().optional().describe("Specific server name to filter logs for") }, - src/index.ts:64-132 (registration)Registration of the 'read-mcp-logs' tool on the MCP server using server.tool(), including name, input schema, and handler function.
server.tool( "read-mcp-logs", { lines: z.number().optional().default(100).describe("Number of lines to read from the end"), serverName: z.string().optional().describe("Specific server name to filter logs for") }, async ({ lines, serverName }) => { try { // Ensure log directory exists try { await fs.access(logDirectory); } catch (error) { return { isError: true, content: [{ type: "text", text: `Log directory not found at ${logDirectory}. Claude Desktop might not be installed or hasn't generated logs yet.` }] }; } // Get all log files const files = await fs.readdir(logDirectory); // Filter for MCP logs const mcpLogs = files.filter(file => file.startsWith("mcp")); if (mcpLogs.length === 0) { return { content: [{ type: "text", text: "No MCP log files found in the log directory." }] }; } // Further filter for specific server if requested const targetLogs = serverName ? mcpLogs.filter(file => file.includes(serverName)) : mcpLogs; if (targetLogs.length === 0 && serverName) { return { content: [{ type: "text", text: `No logs found for server name '${serverName}'.` }] }; } // Read and concatenate log content let combinedLogs = ""; for (const logFile of targetLogs) { const filePath = path.join(logDirectory, logFile); try { let content = await fs.readFile(filePath, 'utf-8'); // Get last N lines const allLines = content.split('\n'); const lastLines = allLines.slice(-lines).join('\n'); combinedLogs += `\n---- ${logFile} ----\n${lastLines}\n\n`; } catch (error) { combinedLogs += `\n---- ${logFile} ----\nError reading file: ${error.message}\n\n`; } } return { content: [{ type: "text", text: combinedLogs || "Log files exist but are empty." }] }; } catch (error) { return { isError: true, content: [{ type: "text", text: `Error reading logs: ${error.message}` }] }; } } ); - src/index.ts:32-41 (helper)Platform-specific helper function getLogDirectory() used by the tool to determine the MCP logs path based on OS (Windows, macOS, Linux). Called globally at line 44 to set logDirectory.
const getLogDirectory = () => { const platform = os.platform(); if (platform === "win32") { return path.join(os.homedir(), "AppData", "Roaming", "Claude", "logs"); } else if (platform === "darwin") { return path.join(os.homedir(), "Library", "Logs", "Claude"); } else { return path.join(os.homedir(), ".local", "share", "Claude", "logs"); } };