analyze_pcap
Extract and convert packet data from a PCAP file into JSON format using WireMCP for LLM-driven network analysis, enabling threat detection and diagnostics.
Instructions
Analyze a PCAP file and provide general packet data as JSON for LLM analysis
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| pcapPath | Yes | Path to the PCAP file to analyze (e.g., ./demo.pcap) |
Implementation Reference
- index.js:307-361 (handler)The handler function executes the analyze_pcap tool: parses PCAP with tshark, extracts IPs, URLs, protocols, packet JSON (trimmed if needed), and returns formatted text output.async (args) => { try { const tsharkPath = await findTshark(); const { pcapPath } = args; console.error(`Analyzing PCAP file: ${pcapPath}`); // Check if file exists await fs.access(pcapPath); // Extract broad packet data const { stdout, stderr } = await execAsync( `${tsharkPath} -r "${pcapPath}" -T json -e frame.number -e ip.src -e ip.dst -e tcp.srcport -e tcp.dstport -e udp.srcport -e udp.dstport -e http.host -e http.request.uri -e frame.protocols`, { env: { ...process.env, PATH: `${process.env.PATH}:/usr/bin:/usr/local/bin:/opt/homebrew/bin` } } ); if (stderr) console.error(`tshark stderr: ${stderr}`); const packets = JSON.parse(stdout); const ips = [...new Set(packets.flatMap(p => [ p._source?.layers['ip.src']?.[0], p._source?.layers['ip.dst']?.[0] ]).filter(ip => ip))]; console.error(`Found ${ips.length} unique IPs: ${ips.join(', ')}`); const urls = packets .filter(p => p._source?.layers['http.host'] && p._source?.layers['http.request.uri']) .map(p => `http://${p._source.layers['http.host'][0]}${p._source.layers['http.request.uri'][0]}`); console.error(`Found ${urls.length} URLs: ${urls.join(', ') || 'None'}`); const protocols = [...new Set(packets.map(p => p._source?.layers['frame.protocols']?.[0]))].filter(p => p); console.error(`Found protocols: ${protocols.join(', ') || 'None'}`); const maxChars = 720000; let jsonString = JSON.stringify(packets); if (jsonString.length > maxChars) { const trimFactor = maxChars / jsonString.length; const trimCount = Math.floor(packets.length * trimFactor); packets.splice(trimCount); jsonString = JSON.stringify(packets); console.error(`Trimmed packets from ${packets.length} to ${trimCount} to fit ${maxChars} chars`); } const outputText = `Analyzed PCAP: ${pcapPath}\n\n` + `Unique IPs:\n${ips.join('\n')}\n\n` + `URLs:\n${urls.length > 0 ? urls.join('\n') : 'None'}\n\n` + `Protocols:\n${protocols.join('\n') || 'None'}\n\n` + `Packet Data (JSON for LLM):\n${jsonString}`; return { content: [{ type: 'text', text: outputText }], }; } catch (error) { console.error(`Error in analyze_pcap: ${error.message}`); return { content: [{ type: 'text', text: `Error: ${error.message}` }], isError: true }; } }
- index.js:304-306 (schema)Input schema using Zod: requires pcapPath string parameter.{ pcapPath: z.string().describe('Path to the PCAP file to analyze (e.g., ./demo.pcap)'), },
- index.js:301-362 (registration)Registers the analyze_pcap tool on the MCP server with name, description, schema, and handler.server.tool( 'analyze_pcap', 'Analyze a PCAP file and provide general packet data as JSON for LLM analysis', { pcapPath: z.string().describe('Path to the PCAP file to analyze (e.g., ./demo.pcap)'), }, async (args) => { try { const tsharkPath = await findTshark(); const { pcapPath } = args; console.error(`Analyzing PCAP file: ${pcapPath}`); // Check if file exists await fs.access(pcapPath); // Extract broad packet data const { stdout, stderr } = await execAsync( `${tsharkPath} -r "${pcapPath}" -T json -e frame.number -e ip.src -e ip.dst -e tcp.srcport -e tcp.dstport -e udp.srcport -e udp.dstport -e http.host -e http.request.uri -e frame.protocols`, { env: { ...process.env, PATH: `${process.env.PATH}:/usr/bin:/usr/local/bin:/opt/homebrew/bin` } } ); if (stderr) console.error(`tshark stderr: ${stderr}`); const packets = JSON.parse(stdout); const ips = [...new Set(packets.flatMap(p => [ p._source?.layers['ip.src']?.[0], p._source?.layers['ip.dst']?.[0] ]).filter(ip => ip))]; console.error(`Found ${ips.length} unique IPs: ${ips.join(', ')}`); const urls = packets .filter(p => p._source?.layers['http.host'] && p._source?.layers['http.request.uri']) .map(p => `http://${p._source.layers['http.host'][0]}${p._source.layers['http.request.uri'][0]}`); console.error(`Found ${urls.length} URLs: ${urls.join(', ') || 'None'}`); const protocols = [...new Set(packets.map(p => p._source?.layers['frame.protocols']?.[0]))].filter(p => p); console.error(`Found protocols: ${protocols.join(', ') || 'None'}`); const maxChars = 720000; let jsonString = JSON.stringify(packets); if (jsonString.length > maxChars) { const trimFactor = maxChars / jsonString.length; const trimCount = Math.floor(packets.length * trimFactor); packets.splice(trimCount); jsonString = JSON.stringify(packets); console.error(`Trimmed packets from ${packets.length} to ${trimCount} to fit ${maxChars} chars`); } const outputText = `Analyzed PCAP: ${pcapPath}\n\n` + `Unique IPs:\n${ips.join('\n')}\n\n` + `URLs:\n${urls.length > 0 ? urls.join('\n') : 'None'}\n\n` + `Protocols:\n${protocols.join('\n') || 'None'}\n\n` + `Packet Data (JSON for LLM):\n${jsonString}`; return { content: [{ type: 'text', text: outputText }], }; } catch (error) { console.error(`Error in analyze_pcap: ${error.message}`); return { content: [{ type: 'text', text: `Error: ${error.message}` }], isError: true }; } } );
- index.js:616-635 (helper)Associated prompt template for guiding LLM analysis after running analyze_pcap tool.server.prompt( 'analyze_pcap_prompt', { pcapPath: z.string().describe('Path to the PCAP file'), }, ({ pcapPath }) => ({ messages: [{ role: 'user', content: { type: 'text', text: `Please analyze the PCAP file at ${pcapPath} and provide insights about: 1. Overall traffic patterns 2. Unique IPs and their interactions 3. Protocols and services used 4. Notable events or anomalies 5. Potential security concerns` } }] }) );
- index.js:17-39 (helper)Helper function to locate tshark binary, used by analyze_pcap handler.async function findTshark() { try { const tsharkPath = await which('tshark'); console.error(`Found tshark at: ${tsharkPath}`); return tsharkPath; } catch (err) { console.error('which failed to find tshark:', err.message); const fallbacks = process.platform === 'win32' ? ['C:\\Program Files\\Wireshark\\tshark.exe', 'C:\\Program Files (x86)\\Wireshark\\tshark.exe'] : ['/usr/bin/tshark', '/usr/local/bin/tshark', '/opt/homebrew/bin/tshark', '/Applications/Wireshark.app/Contents/MacOS/tshark']; for (const path of fallbacks) { try { await execAsync(`${path} -v`); console.error(`Found tshark at fallback: ${path}`); return path; } catch (e) { console.error(`Fallback ${path} failed: ${e.message}`); } } throw new Error('tshark not found. Please install Wireshark (https://www.wireshark.org/download.html) and ensure tshark is in your PATH.'); } }