Skip to main content
Glama
jus1-c

network-forensics-mcp-server

by jus1-c
README.md
# MCP Network Forensics

[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![MCP](https://img.shields.io/badge/MCP-Compatible-green.svg)](https://modelcontextprotocol.io/)

A case-oriented MCP Server for Network Forensics that turns PCAP evidence into a reproducible local investigation: capture manifests, normalized flows/events, IOC pivots, timelines, deterministic findings, stream reconstruction, and quarantined artifacts. TShark remains the dissector backend, not the user-facing workflow.

## Features

- **Case-centric workflow**: Register and hash evidence once, then reuse a local SQLite index
- **Evidence provenance**: Findings contain capture, frame, stream, and reproduction references
- **Deterministic triage**: Scan, beacon, DNS tunneling, outbound volume, and lateral-movement heuristics
- **Bounded execution**: Streaming TShark runner, timeout/cancellation, output budgets, and isolated artifacts
- **MCP-native output**: Typed tools, pagination, background jobs, and reusable resources
- **Optional engine adapters**: Offline Zeek JSON logs, Suricata EVE alerts, and YARA artifact matches
- **Deep Packet Inspection**: Access to all Wireshark dissectors (1000+ protocols)
- **Advanced Filtering**: Support for all Wireshark display filters
- **Protocol Analysis**: Automatic statistics and distribution analysis
- **Security First**: Path validation, size limits, input sanitization
- **Memory Efficient**: Streaming extraction and indexed warm queries for large files
- **Auto-Detection**: Automatically finds tshark installation

## Performance Model

The first `index_capture` pass reads the PCAP through a bounded streaming
TShark process and writes normalized facts to SQLite. Repeated flow, event,
IOC, timeline, and finding queries use that local index and do not launch a
new TShark process. Runtime depends on dissectors, storage, and capture shape;
benchmark your own evidence corpus rather than relying on fixed timings.

### Reproducible Benchmark

Run the executable benchmark against a real PCAP/PCAPNG. It reports registration
time, cold indexing time, p50/p95 warm-query latency, peak RSS, and whether the
configured file/output/response budgets held. Use a fresh case root for a cold
measurement:

```bash
python benchmarks/benchmark_case.py /absolute/path/to/large.pcapng \
  --case-root /tmp/mcp-network-forensics-benchmark \
  --queries 10 \
  --max-rss-bytes 2147483648 \
  --json-out /tmp/mcp-network-forensics-benchmark.json
```

The harness does not fabricate a target size or timing claim. For PCAPs near
the 10 GB default file limit, allow sufficient disk space for the SQLite case
index and use `--force` only when intentionally repeating a cold index.

## Requirements

- Python 3.9+
- Wireshark/tshark (4.0+) and capinfos installed
- MCP-compatible client (Claude Desktop, VSCode, Cline, etc.)
- Optional: Zeek, Suricata, and YARA installed locally for their adapters

## Installation

### 1. Install Wireshark

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

**macOS:**
```bash
brew install wireshark
```

**Windows:**
Download from [wireshark.org](https://www.wireshark.org/download.html)

Verify installation:
```bash
tshark --version
capinfos --version  # Optional, for faster packet counting
```

### 2. Install MCP Server

```bash
# Clone repository
git clone https://github.com/yourusername/mcp-network-forensics.git
cd mcp-network-forensics

# Create virtual environment
python -m venv venv
source venv/bin/activate  # Linux/Mac
# or: venv\Scripts\activate  # Windows

# Install package
pip install -e .
```

## Configuration

### Claude Desktop

Edit `claude_desktop_config.json`:

**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows:** `%APPDATA%/Claude/claude_desktop_config.json`

```json
{
  "mcpServers": {
    "network-forensics": {
      "command": "python",
      "args": ["-m", "mcp_network_forensics"],
      "env": {
        "MCP_MAX_FILE_SIZE": "10737418240",
        "MCP_MAX_PACKETS": "10000",
        "TSHARK_PATH": "/usr/bin/tshark"
      }
    }
  }
}
```

### VSCode (with Cline extension)

Add to your settings:

```json
{
  "mcpServers": {
    "network-forensics": {
      "command": "python",
      "args": ["-m", "mcp_network_forensics"],
      "disabled": false,
      "autoApprove": []
    }
  }
}
```

## Available Tools

### DFIR workflow

1. `open_capture(file_path)` creates a SHA-256-backed capture manifest.
2. `index_capture(capture_id)` builds the normalized frame/flow/event index. Set `background=true` for a job.
3. `triage_capture(capture_id)` returns ranked findings and top entities.
4. `query_flows`, `query_events`, `pivot_iocs`, and `get_entity_timeline` perform warm indexed pivots.
5. `reconstruct_stream`, `export_objects`, and `preview_artifact` handle bounded content safely.
6. `get_capture_health` and `inspect_capture_health` expose integrity and expert diagnostics.
7. `run_zeek_adapter`, `run_suricata_adapter`, and `run_yara_adapter` invoke optional local engines with fixed offline commands and bounded output. Use `parse_zeek_adapter`, `parse_suricata_adapter`, and `parse_yara_adapter` to normalize existing tool output without executing an engine.

### Optional Engine Adapters

Adapters never install tools, open sockets, or accept arbitrary child-process
arguments. `list_plugins()` reports capability state without claiming an engine
is installed. Missing binaries return `status: "unavailable"` with a warning.

- **Zeek**: `zeek -r <pcap> LogAscii::use_json=T Log::default_logdir=<managed-dir>`. Normalizes `conn`, `dns`, `http`, `ssl`, and `notice`-style JSON records and preserves original fields under `fields`.
- **Suricata**: `suricata -c <yaml> -r <pcap> -l <managed-dir>`. Requires an operator-supplied YAML configuration so EVE output policy is explicit. Normalizes EVE events and exposes alert records with `pcap_cnt` when present.
- **YARA**: `yara -a <timeout> <rules> --scan-list <managed-list>`. Skips symlinks, bounds file count and file size, and normalizes standard `RULE PATH` matches.

Each adapter returns `mcp-network-forensics.plugin-result.v1` with status,
records, warnings, truncation state, duration, and `network_access: false`.
Versioned command policies are stored in `src/mcp_network_forensics/plugins/manifests/`.

Compatibility packet tools remain available below, but they are bounded adapters. Prefer the case workflow for investigation.

### Compatibility packet tools

#### `analyze_pcap_file`
Analyze a PCAP file and return summary statistics.

**Parameters:**
- `file_path`: Absolute path to PCAP file (required)
- `packet_limit`: Maximum packets to analyze (default: 1000)
- `display_filter`: Optional Wireshark display filter

**Example:**
```json
{
  "file_path": "/home/user/captures/traffic.pcap",
  "packet_limit": 100,
  "display_filter": "ip.addr == 192.168.1.1"
}
```

#### `get_packet_details`
Get detailed information about a specific packet.

**Parameters:**
- `file_path`: Absolute path to PCAP file
- `packet_index`: Index of packet (0-based)
- `include_layers`: Include layer information (default: true)

**Example:**
```json
{
  "file_path": "/home/user/captures/traffic.pcap",
  "packet_index": 0,
  "include_layers": true
}
```

#### `filter_packets`
Filter packets using Wireshark display filter syntax.

**Parameters:**
- `file_path`: Absolute path to PCAP file
- `display_filter`: Wireshark filter (e.g., "tcp.port == 80", "http", "dns.qry.name contains 'google'")
- `max_results`: Maximum results to return (default: 100)

**Example:**
```json
{
  "file_path": "/home/user/captures/traffic.pcap",
  "display_filter": "tcp.flags.syn == 1 and tcp.flags.ack == 0",
  "max_results": 50
}
```

#### `get_protocol_statistics`
Get protocol distribution statistics.

**Parameters:**
- `file_path`: Absolute path to PCAP file
- `packet_limit`: Maximum packets to analyze (default: 1000)

**Example:**
```json
{
  "file_path": "/home/user/captures/traffic.pcap",
  "packet_limit": 1000
}
```

#### `extract_unique_ips`
Extract unique IP addresses from the capture.

**Parameters:**
- `file_path`: Absolute path to PCAP file

**Example:**
```json
{
  "file_path": "/home/user/captures/traffic.pcap"
}
```

## Usage Examples

### Basic Analysis
```
Please analyze this PCAP file and show me the protocol distribution.
File: /home/user/captures/traffic.pcap
```

### Threat Hunting
```
Find all HTTP requests to external IPs in this capture.
File: /home/user/captures/web.pcap
```

### Network Troubleshooting
```
Show me all TCP SYN packets without ACK (possible port scan).
File: /home/user/captures/suspicious.pcap
```

### Deep Inspection
```
Get detailed information about packet 100, including all layers.
File: /home/user/captures/malware.pcap
```

## Security Features

- **Path Validation**: Only absolute paths allowed, no directory traversal
- **File Size Limits**: Configurable max file size (default: 10GB)
- **Packet Limits**: Configurable max packets per request (default: 10,000)
- **Filter Validation**: Syntax is checked by TShark; valid operators such as `>`, `<`, `&`, and `|` remain available
- **Timeout Protection**: Request timeout configuration (default: 300s)
- **Response Budgets**: Bounded MCP responses, extraction output, stderr, and artifact bytes
- **Evidence Roots**: Optional `MCP_ALLOWED_ROOTS` allowlist for input captures
- **Plugin Boundary**: Plugins must be pre-installed, hash-validated, offline, and manifest-bounded

## Environment Variables

| Variable | Description | Default |
|----------|-------------|---------|
| `MCP_SERVER_NAME` | Server name | mcp-network-forensics |
| `MCP_MAX_FILE_SIZE` | Max file size in bytes | 10737418240 (10GB) |
| `MCP_MAX_PACKETS` | Max packets per request | 10000 |
| `MCP_TIMEOUT` | Request timeout in seconds | 300 |
| `MCP_RESPONSE_BYTES` | Maximum inline response bytes | 1048576 |
| `MCP_EXTRACTION_BYTES` | Maximum streamed TShark output bytes | 21474836480 |
| `MCP_ARTIFACT_BYTES` | Maximum bytes exported per object operation | 52428800 |
| `MCP_MAX_CONCURRENT_JOBS` | Maximum disk-heavy background jobs | 2 |
| `MCP_PLUGIN_MEMORY_BYTES` | Address-space limit for optional engine adapters | 2147483648 (2GB) |
| `MCP_CASE_ROOT` | SQLite/artifact/plugin workspace | `~/.mcp-network-forensics` |
| `MCP_ALLOWED_ROOTS` | OS path-separator-delimited evidence allowlist | unset |
| `WIRESHARK_PROFILE` | Explicit Wireshark profile | unset |
| `MCP_NAME_RESOLUTION` | Enable name resolution | false |
| `TSHARK_PATH` | Path to tshark binary | auto-detect |
| `ZEEK_PATH` | Path to Zeek binary | auto-detect |
| `SURICATA_PATH` | Path to Suricata binary | auto-detect |
| `SURICATA_CONFIG` | Default Suricata YAML configuration | unset; required by adapter |
| `YARA_PATH` | Path to YARA binary | auto-detect |

## Architecture

```text
MCP client
    |
    v
FastMCP tools/resources
    |
Case registry + bounded jobs
    |
Streaming TShark runner
    |
SQLite normalized index + quarantined artifacts
    |
Deterministic triage/detections + optional plugins
```

## Project Structure

```
mcp-network-forensics/
├── src/mcp_network_forensics/
│   ├── server.py                 # Typed MCP tools/resources
│   ├── core/tshark_runner.py     # Bounded subprocess execution
│   ├── core/jobs.py              # Background jobs/cancellation
│   ├── storage/case_store.py     # SQLite case registry/index
│   ├── storage/artifact_store.py # Quarantined content-addressed objects
│   ├── analysis/triage.py        # Explainable DFIR detections
│   ├── plugins/adapters.py       # Zeek, Suricata, and YARA offline adapters
│   ├── plugins/manifests/         # Versioned command/output policies
│   ├── plugins/runner.py          # Generic manifest-driven plugins
│   ├── capture/                  # Compatibility adapters
│   ├── models/                   # Versioned Pydantic contracts
│   └── utils/                    # Validation and formatting
├── pyproject.toml
├── requirements.txt
├── requirements-dev.txt
└── README.md
```

## Development

### Setup Development Environment
```bash
pip install -e ".[dev]"
```

### Code Quality
```bash
black src
isort src
flake8 src
mypy src
pytest
```

Coverage is optional when `pytest-cov` is installed:

```bash
pytest --cov=mcp_network_forensics --cov-report=term-missing
```

## Troubleshooting

### tshark not found
```bash
# Check installation
which tshark  # Linux/Mac
where tshark  # Windows

# Set path manually
export TSHARK_PATH=/usr/bin/tshark  # Linux/Mac
set TSHARK_PATH=C:\Program Files\Wireshark\tshark.exe  # Windows
```

### Timeout errors on large files
Increase timeout or reduce requested scope. Indexing can run in the background
and be monitored with `get_job_status`:
```bash
export MCP_TIMEOUT=600
export MCP_MAX_PACKETS=5000
```

## License

MIT License - see [LICENSE](LICENSE) file for details.

## Acknowledgments

- [Wireshark](https://www.wireshark.org/) - Network protocol analyzer
- [Model Context Protocol](https://modelcontextprotocol.io/) - MCP specification
- [FastMCP](https://github.com/modelcontextprotocol/python-sdk) - Python MCP SDK

## Support

For issues and feature requests, please use the [GitHub issue tracker](https://github.com/yourusername/mcp-network-forensics/issues).