npm package: @modular-intelligence/pcap-analysis
Description: MCP server for network capture (PCAP) analysis via tshark
Latest version: 1.0.2

# PCAP Analysis MCP Server

A Model Context Protocol (MCP) server for network packet capture (PCAP) analysis via tshark, the command-line interface for Wireshark. Enables Claude and other MCP clients to analyze network traffic data with tools for protocol hierarchy inspection, DNS extraction, HTTP request parsing, connection enumeration, and custom packet filtering.

## Overview

This server provides programmatic access to network capture analysis without requiring direct Wireshark GUI interaction. It uses tshark under the hood to parse PCAP files and extract structured network intelligence. All analysis is performed locally—no data leaves your system.

## Tools

The server exposes five specialized tools for different aspects of PCAP analysis:

| Tool | Purpose |
|------|---------|
| `pcap_summary` | High-level statistics and protocol breakdown |
| `pcap_dns` | DNS query and response extraction |
| `pcap_http` | HTTP request and response parsing |
| `pcap_connections` | Connection tuples with flow statistics |
| `pcap_filter` | Custom BPF-filtered packet output |

### pcap_summary

Generates a comprehensive summary of a PCAP file including file metadata, protocol hierarchy, top IP talkers, and conversation count.

**Input Schema:**
```json
{
  "file": "string (absolute path to PCAP file, required)"
}
```

**Example Request:**
```json
{
  "file": "/var/tmp/capture.pcap"
}
```

**Example Output:**
```json
{
  "file": "/var/tmp/capture.pcap",
  "file_size": 2457600,
  "packet_count": 8942,
  "capture_duration": 342.5,
  "first_packet_time": "Feb  7, 2026 10:14:22.123456 PST",
  "last_packet_time": "Feb  7, 2026 10:20:04.987654 PST",
  "protocols": [
    {
      "name": "eth",
      "packets": 8942,
      "percentage": 100.0
    },
    {
      "name": "ip",
      "packets": 8635,
      "percentage": 96.56
    },
    {
      "name": "tcp",
      "packets": 5420,
      "percentage": 60.65
    },
    {
      "name": "dns",
      "packets": 284,
      "percentage": 3.18
    },
    {
      "name": "http",
      "packets": 1203,
      "percentage": 13.46
    },
    {
      "name": "tls",
      "packets": 2104,
      "percentage": 23.54
    }
  ],
  "top_talkers": [
    {
      "ip": "192.168.1.100",
      "packets": 3421,
      "bytes": 1847362
    },
    {
      "ip": "10.0.0.1",
      "packets": 2156,
      "bytes": 985621
    },
    {
      "ip": "172.16.0.50",
      "packets": 1842,
      "bytes": 652184
    }
  ],
  "conversation_count": 42
}
```

**Description:**

- `file_size`: Capture file size in bytes
- `packet_count`: Total packets captured
- `capture_duration`: Time span between first and last packet (seconds)
- `first_packet_time`, `last_packet_time`: Capture window boundaries
- `protocols`: Array of up to 20 protocols from Wireshark's protocol hierarchy. Percentage shows fraction of total packets
- `top_talkers`: Up to 10 most active IP addresses by packet count. Includes both transmitted and received bytes
- `conversation_count`: Unique IP pairs that exchanged traffic

### pcap_dns

Extracts DNS queries and responses from a PCAP, revealing domain resolution activity.

**Input Schema:**
```json
{
  "file": "string (absolute path to PCAP file, required)",
  "max_results": "integer (1-5000, default: 500)"
}
```

**Example Request:**
```json
{
  "file": "/var/tmp/capture.pcap",
  "max_results": 100
}
```

**Example Output:**
```json
{
  "file": "/var/tmp/capture.pcap",
  "total_queries": 24,
  "queries": [
    {
      "timestamp": "Feb  7, 2026 10:14:35.234567 PST",
      "source": "192.168.1.100",
      "query_name": "www.example.com",
      "query_type": "A",
      "response_code": "0",
      "answers": ["93.184.216.34"]
    },
    {
      "timestamp": "Feb  7, 2026 10:14:36.456789 PST",
      "source": "192.168.1.100",
      "query_name": "api.github.com",
      "query_type": "A",
      "response_code": "0",
      "answers": ["140.82.113.5", "140.82.113.4"]
    },
    {
      "timestamp": "Feb  7, 2026 10:14:37.678901 PST",
      "source": "192.168.1.105",
      "query_name": "internal.corp",
      "query_type": "A",
      "response_code": "3",
      "answers": []
    }
  ],
  "unique_domains": [
    "api.github.com",
    "internal.corp",
    "www.example.com"
  ]
}
```

**Description:**

- `timestamp`: When the DNS query was observed
- `source`: IP address that initiated the query
- `query_name`: Domain name being resolved
- `query_type`: DNS record type (A, AAAA, MX, CNAME, etc.)
- `response_code`: DNS response code (0=success, 3=NXDomain, etc.)
- `answers`: List of resolved IP addresses or CNAME targets
- `unique_domains`: Sorted list of all queried domains for quick reference

### pcap_http

Extracts HTTP requests and responses, capturing web traffic details including method, URI, host, status codes, and user agents.

**Input Schema:**
```json
{
  "file": "string (absolute path to PCAP file, required)",
  "max_results": "integer (1-5000, default: 500)"
}
```

**Example Request:**
```json
{
  "file": "/var/tmp/capture.pcap",
  "max_results": 50
}
```

**Example Output:**
```json
{
  "file": "/var/tmp/capture.pcap",
  "total_requests": 12,
  "requests": [
    {
      "timestamp": "Feb  7, 2026 10:15:02.123456 PST",
      "source": "192.168.1.100",
      "destination": "93.184.216.34",
      "method": "GET",
      "uri": "/path/to/resource?key=value",
      "host": "www.example.com",
      "status_code": 200,
      "content_type": "text/html; charset=utf-8",
      "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)"
    },
    {
      "timestamp": "Feb  7, 2026 10:15:03.234567 PST",
      "source": "192.168.1.100",
      "destination": "93.184.216.34",
      "method": "POST",
      "uri": "/api/submit",
      "host": "www.example.com",
      "status_code": 201,
      "content_type": null,
      "user_agent": "curl/7.68.0"
    },
    {
      "timestamp": "Feb  7, 2026 10:15:04.345678 PST",
      "source": "192.168.1.105",
      "destination": "140.82.112.22",
      "method": "GET",
      "uri": "/api/users",
      "host": "api.github.com",
      "status_code": 301,
      "content_type": null,
      "user_agent": "python-requests/2.28.1"
    }
  ]
}
```

**Description:**

- `timestamp`: When the HTTP request or response was captured
- `source`: Client IP address
- `destination`: Server IP address
- `method`: HTTP verb (GET, POST, PUT, DELETE, etc.)
- `uri`: Full request path and query string
- `host`: HTTP Host header value
- `status_code`: HTTP response status (200, 404, 500, etc.). May be null for requests without captured responses
- `content_type`: Response Content-Type header, or null if not captured
- `user_agent`: User-Agent header string, or null if not captured

### pcap_connections

Lists all TCP/UDP connections (flow tuples) with packet and byte counts, timing information, and protocol type filtering.

**Input Schema:**
```json
{
  "file": "string (absolute path to PCAP file, required)",
  "protocol": "string enum ('tcp', 'udp', 'all', default: 'all')",
  "max_results": "integer (1-5000, default: 500)"
}
```

**Example Request:**
```json
{
  "file": "/var/tmp/capture.pcap",
  "protocol": "tcp",
  "max_results": 25
}
```

**Example Output:**
```json
{
  "file": "/var/tmp/capture.pcap",
  "protocol": "tcp",
  "total_connections": 8,
  "connections": [
    {
      "source": "192.168.1.100",
      "source_port": 52341,
      "destination": "93.184.216.34",
      "destination_port": 80,
      "protocol": "tcp",
      "packets": 45,
      "bytes": 23456,
      "duration": 12.34,
      "start_time": "10:15:02.123456"
    },
    {
      "source": "192.168.1.100",
      "source_port": 52342,
      "destination": "140.82.113.5",
      "destination_port": 443,
      "protocol": "tcp",
      "packets": 128,
      "bytes": 87634,
      "duration": 45.67,
      "start_time": "10:15:05.234567"
    },
    {
      "source": "192.168.1.105",
      "source_port": 61234,
      "destination": "8.8.8.8",
      "destination_port": 53,
      "protocol": "tcp",
      "packets": 3,
      "bytes": 512,
      "duration": 0.12,
      "start_time": "10:15:15.345678"
    }
  ]
}
```

**Description:**

- `source`, `source_port`: Initiating IP and port
- `destination`, `destination_port`: Receiving IP and port
- `protocol`: Protocol type filtered (tcp, udp, or ip for all)
- `packets`: Combined packet count from both directions
- `bytes`: Combined byte count from both directions
- `duration`: Connection lifetime in seconds
- `start_time`: When the connection began (relative to capture start)

### pcap_filter

Applies a Berkeley Packet Filter (BPF) expression to the PCAP and returns matching packets with full protocol details.

**Input Schema:**
```json
{
  "file": "string (absolute path to PCAP file, required)",
  "filter": "string (BPF expression, required)",
  "max_results": "integer (1-1000, default: 100)"
}
```

**BPF Filter Examples:**
```
tcp port 80                    # HTTP traffic
ip src 192.168.1.0/24         # Source subnet
tcp.flags.syn == 1            # TCP SYN packets
dns.qry.type == 1             # DNS A record queries
ip.len > 1000                 # Packets larger than 1000 bytes
(tcp port 443) or (tcp port 80)  # HTTPS or HTTP
```

**Example Request:**
```json
{
  "file": "/var/tmp/capture.pcap",
  "filter": "tcp port 80",
  "max_results": 10
}
```

**Example Output:**
```json
{
  "file": "/var/tmp/capture.pcap",
  "filter": "tcp port 80",
  "total_matched": 45,
  "packets": [
    {
      "number": 107,
      "timestamp": "Feb  7, 2026 10:15:02.123456 PST",
      "source": "192.168.1.100",
      "destination": "93.184.216.34",
      "protocol": "http",
      "length": 478,
      "info": "GET /path/to/resource HTTP/1.1"
    },
    {
      "number": 108,
      "timestamp": "Feb  7, 2026 10:15:02.125123 PST",
      "source": "93.184.216.34",
      "destination": "192.168.1.100",
      "protocol": "http",
      "length": 1514,
      "info": "HTTP/1.1 200 OK"
    },
    {
      "number": 112,
      "timestamp": "Feb  7, 2026 10:15:02.234567 PST",
      "source": "192.168.1.100",
      "destination": "93.184.216.34",
      "protocol": "http",
      "length": 234,
      "info": "GET /path/to/image.jpg HTTP/1.1"
    }
  ]
}
```

**Description:**

- `number`: Packet number in the capture file (1-indexed)
- `timestamp`: When packet was captured
- `source`: Source IP address
- `destination`: Destination IP address
- `protocol`: Highest layer protocol (http, dns, tls, ssh, etc.)
- `length`: Total packet size in bytes
- `info`: Protocol-specific summary (truncated to 200 chars)

BPF filters support full Wireshark display filter syntax. Filters are validated for injection safety (see Security section).

## Prerequisites

### Required: tshark

tshark is the command-line interface for Wireshark. Install it via your system package manager:

**macOS (Homebrew):**
```bash
brew install wireshark
```

**Ubuntu/Debian:**
```bash
sudo apt-get install tshark
```

**Fedora/RHEL:**
```bash
sudo dnf install wireshark
```

**Windows (Chocolatey):**
```bash
choco install wireshark
```

tshark is a lightweight CLI tool (not the full GUI) and is included in all Wireshark distributions. Verify installation:

```bash
tshark --version
```

### Required: capinfos

capinfos is also included with Wireshark and provides file metadata extraction. It is automatically available once Wireshark is installed.

Verify:
```bash
capinfos --version
```

## Installation

### Prerequisites

- Bun (v1.0+) – Install from https://bun.sh
- Node.js 18+ (if not using Bun)

### Steps

1. Clone or download this repository:
```bash
cd /path/to/mcp-servers/pcap-analysis
```

2. Install dependencies:
```bash
bun install
```

3. Build the server:
```bash
bun run build
```

The compiled server will be available at `dist/index.js`.

### Verify Installation

Test that the server starts:
```bash
bun run src/index.ts
```

If tshark/capinfos are installed correctly, the server will start without errors. Press Ctrl+C to exit.

## Usage

### Stdio Transport

The server uses the MCP stdio transport, meaning it communicates via standard input/output. It is designed to be invoked by MCP clients (Claude Desktop, Claude Code, etc.) rather than run directly.

### Claude Desktop Configuration

Add the server to your Claude Desktop config at `~/.config/Claude/claude_desktop_config.json` (macOS/Linux) or `%AppData%\Claude\claude_desktop_config.json` (Windows):

```json
{
  "mcpServers": {
    "pcap-analysis": {
      "command": "bun",
      "args": ["/path/to/mcp-servers/pcap-analysis/dist/index.js"]
    }
  }
}
```

Replace `/path/to` with the actual absolute path to the repository. Restart Claude Desktop to load the server.

### Claude Code (MCP Settings)

In Claude Code, configure the server via MCP settings:

1. Open Settings (Ctrl+, or Cmd+,)
2. Go to MCP Servers
3. Add server with:
   - **Command:** `bun`
   - **Args:** `/path/to/mcp-servers/pcap-analysis/dist/index.js`
   - **Name:** `pcap-analysis`

### Direct Testing

To test a tool from the command line, use the MCP Inspector or write a simple client. Example using Node.js with mcp-cli:

```bash
npm install -g mcp-cli
mcp-cli exec \
  "bun /path/to/mcp-servers/pcap-analysis/dist/index.js" \
  pcap_summary \
  '{"file": "/path/to/your/capture.pcap"}'
```

## Security

This server implements several security measures to prevent misuse:

### PCAP File Validation

All file paths are validated before use:

1. **File Existence:** Path must point to an existing file
2. **File Type:** Extension must be `.pcap`, `.pcapng`, or `.cap`
3. **File Size:** Maximum 500 MB per file to prevent resource exhaustion
4. **Path Normalization:** Paths are resolved and normalized to prevent directory traversal

Example error handling:
```
Input: {"file": "../../../etc/passwd"}
Error: Invalid file extension. Expected: .pcap, .pcapng, .cap

Input: {"file": "/var/huge-file.pcap"} (600 MB)
Error: File too large (600.0MB). Maximum: 500MB
```

### BPF Filter Injection Protection

Display filters (for `pcap_filter` tool) are validated to prevent shell injection:

1. **Length Limit:** Filters are limited to 500 characters
2. **Character Whitelist:** The following characters are blocked: `;`, `&`, `|`, `` ` ``, `$`, `(`, `)`, `{`, `}`

These characters are not valid in BPF filter syntax and are rejected if present.

Example:
```
Input: {"filter": "tcp port 80; rm -rf /"}
Error: Filter contains disallowed characters

Input: {"filter": "tcp port $(cat /etc/passwd)"}
Error: Filter contains disallowed characters
```

### Timeout Protection

All tshark/capinfos commands are subject to a 60-second timeout to prevent hanging processes on malformed or extremely large captures.

### Output Buffer Limits

Command output is capped at 20 MB to prevent unbounded memory consumption.

## License

MIT