Skip to main content
Glama
README.md
# TShark MCP Server

An MCP (Model Context Protocol) server that exposes TShark as tools for AI-assisted network packet analysis. Supports PCAP analysis, live capture, TLS decryption, and telecom / SS7 signaling protocols.

## Requirements

- Python 3.10+
- [Wireshark / TShark](https://www.wireshark.org/download.html) installed on the system
- `mergecap` (bundled with Wireshark, required for `merge_pcap_files`)

## Installation

```bash
# Recommended — installs into an isolated env and puts the
# tshark-mcp / tshark-mcp-http commands on your PATH.
uv tool install tshark-mcp

# With Windows service support (Windows only).
uv tool install "tshark-mcp[windows-service]"

# Or into a project venv:
uv pip install tshark-mcp
```

**From a local source build** (in the project root):

```powershell
uv build
uv tool install --reinstall ".\dist\tshark_mcp-1.0.0-py3-none-any.whl[windows-service]"
```

**Verify the commands are on PATH:**

```powershell
Get-Command tshark-mcp, tshark-mcp-http, tshark-mcp-win-service | Select-Object Name, Source
```

**Uninstall the system installation** (after removing the Windows service if any — see below):

```powershell
uv tool uninstall tshark-mcp
```

After install you have three console scripts:

| Command | Default | What it does |
|---------|---------|--------------|
| `tshark-mcp` | stdio | Run via MCP client (Claude Code / VS Code) — client manages the process |
| `tshark-mcp-http` | HTTP on 127.0.0.1:8100 | Standalone HTTP server (WSL, remote, shared) |
| `tshark-mcp-win-service` | Windows service | Register as a Windows service (auto-start at boot) |

## Running modes

### STDIO — managed by your MCP client

The MCP client launches `tshark-mcp` as a child process. You don't run anything manually. Just configure the client.

**Claude Code** — `.mcp.json` (project) or `~/.claude.json` (user):

```json
{
  "mcpServers": {
    "tshark-mcp": {
      "type": "stdio",
      "command": "tshark-mcp"
    }
  }
}
```

Or via CLI:

```bash
claude mcp add tshark-mcp -- tshark-mcp
```

**VS Code** — `.vscode/mcp.json` (project) or your user `mcp.json`:

```json
{
  "servers": {
    "tshark-mcp": {
      "type": "stdio",
      "command": "tshark-mcp"
    }
  }
}
```

> If `tshark-mcp` is not on PATH (you installed via `uv pip install` instead of `uv tool install`), replace `command: "tshark-mcp"` with `command: "uv", args: ["tool", "run", "tshark-mcp"]`.

### HTTP — standalone server

You start the server yourself; clients connect to its URL. Stays running across client restarts and can be shared by multiple clients.

```bash
# Default 127.0.0.1:8100, endpoint /mcp
tshark-mcp-http

# Custom host/port
tshark-mcp-http --host 0.0.0.0 --port 9000

# Use a config file (see Configuration below)
tshark-mcp-http --config /path/to/config.toml
```

The endpoint URL is `http://<host>:<port>/mcp`.

**Claude Code**:

```json
{
  "mcpServers": {
    "tshark-mcp": {
      "type": "http",
      "url": "http://127.0.0.1:8100/mcp"
    }
  }
}
```

Or via CLI:

```bash
claude mcp add --transport http tshark-mcp http://127.0.0.1:8100/mcp
```

**VS Code**:

```json
{
  "servers": {
    "tshark-mcp": {
      "type": "http",
      "url": "http://127.0.0.1:8100/mcp"
    }
  }
}
```

> WSL: run the HTTP server inside WSL and point Windows-side Claude Code / VS Code at `http://127.0.0.1:8100/mcp` — WSL2 forwards `localhost` automatically.

### Windows service — auto-start at boot

Register `tshark-mcp-http` as a Windows service. Survives reboots, runs in the background under `LocalSystem`. All commands below need an **elevated PowerShell** (admin).

> pywin32 expects options BEFORE the verb (`install`/`start`/`stop`/`remove`). `tshark-mcp-win-service install --startup auto` is wrong — it must be `--startup auto install`.

**Install + start:**

```powershell
tshark-mcp-win-service --startup auto install
tshark-mcp-win-service --wait 15 start
```

**Verify it's running:**

```powershell
Get-Service TsharkMcp                                  # Status should be Running
Get-NetTCPConnection -LocalPort 8100 -State Listen     # 127.0.0.1:8100 listening
```

**Manage:**

```powershell
tshark-mcp-win-service stop
tshark-mcp-win-service restart        # reload after editing config.toml
```

**Uninstall the service only:**

```powershell
tshark-mcp-win-service stop
tshark-mcp-win-service remove
```

**Full cleanup (service + uv tool + leftover pywin32 DLLs):**

```powershell
# 1. Remove the service (admin PS)
tshark-mcp-win-service stop
tshark-mcp-win-service remove

# 2. Uninstall the uv tool venv (admin not required)
uv tool uninstall tshark-mcp

# 3. Optional — pywin32 leaves two DLLs in the uv-managed Python dir.
#    Only remove these if no other pywin32-using uv tool is installed.
$pyDir = "$env:APPDATA\uv\python\cpython-3.13-windows-x86_64-none"
Remove-Item -Force -ErrorAction SilentlyContinue `
    "$pyDir\pywintypes313.dll", "$pyDir\pythoncom313.dll"
```

Because Windows services don't receive command-line arguments, configure the service via:

- **Config file** at `%PROGRAMDATA%\tshark-mcp\config.toml` (recommended) — restart the service after editing
- **System-wide environment variables** (`TSHARK_MCP_HOST`, `TSHARK_MCP_PORT`, `TSHARK_PATH`, …)

Once running, point your MCP client at `http://127.0.0.1:8100/mcp` exactly as in the HTTP section above.

## Configuration

Configuration is layered — later sources override earlier ones:

```
built-in defaults  <  config file (TOML)  <  environment variables  <  CLI arguments
```

### Config file (TOML)

Search order (first match wins):

1. `--config <path>` CLI argument
2. `TSHARK_MCP_CONFIG` environment variable
3. **Windows**: `%APPDATA%\tshark-mcp\config.toml`, then `%PROGRAMDATA%\tshark-mcp\config.toml`
4. **Linux/macOS**: `$XDG_CONFIG_HOME/tshark-mcp/config.toml` (or `~/.config/tshark-mcp/config.toml`), then `/etc/tshark-mcp/config.toml`

Full schema (also see [config.example.toml](config.example.toml)):

```toml
[server]
# stdio | http | streamable-http | sse
# "http" is an alias for "streamable-http" (the current MCP HTTP transport).
# "sse" is the deprecated MCP HTTP+SSE transport; kept for legacy clients.
transport = "http"
host = "127.0.0.1"
port = 8100

# Optional endpoint paths (default to FastMCP defaults)
# mount_path = "/"
# streamable_http_path = "/mcp"
# sse_path = "/sse"
# message_path = "/messages"

[tshark]
# Override tshark binary location (otherwise auto-detected).
# path = "C:\\Program Files\\Wireshark\\tshark.exe"
```

### Environment variables

| Variable | Maps to |
|----------|---------|
| `TSHARK_MCP_CONFIG` | Path to TOML config file |
| `TSHARK_MCP_TRANSPORT` | `[server] transport` |
| `TSHARK_MCP_HOST` | `[server] host` |
| `TSHARK_MCP_PORT` | `[server] port` |
| `TSHARK_MCP_MOUNT_PATH` | `[server] mount_path` |
| `TSHARK_MCP_STREAMABLE_HTTP_PATH` | `[server] streamable_http_path` |
| `TSHARK_MCP_SSE_PATH` | `[server] sse_path` |
| `TSHARK_MCP_MESSAGE_PATH` | `[server] message_path` |
| `TSHARK_PATH` | `[tshark] path` |

### CLI arguments

`tshark-mcp` and `tshark-mcp-http` accept the same flags:

```
--config PATH                  TOML config file (overrides search paths)
--transport {stdio,http,streamable-http,sse}
--host HOST
--port PORT
--mount-path PATH
--streamable-http-path PATH    default '/mcp'
--sse-path PATH
--message-path PATH
--tshark-path PATH             tshark binary (overrides TSHARK_PATH env)
```

The two scripts differ only in their starting defaults — `tshark-mcp` starts from stdio defaults, `tshark-mcp-http` starts from `transport=http, host=127.0.0.1, port=8100`. Either way, file → env → CLI all layer on top.

### TShark binary auto-detection

If `[tshark] path`, `TSHARK_PATH`, and `--tshark-path` are all unset, the server probes:

- **Windows**: `C:\Program Files\Wireshark\tshark.exe`, `C:\Program Files (x86)\Wireshark\tshark.exe`
- **macOS**: `/Applications/Wireshark.app/Contents/MacOS/tshark`, `/opt/homebrew/bin/tshark`, `/usr/local/bin/tshark`
- **Linux**: `/usr/bin/tshark`, `/usr/sbin/tshark`, `/usr/local/bin/tshark`

Then falls back to PATH lookup.

---

## Tools (25 total)

### Basic Analysis

| Tool | Key Parameters | Description |
|------|---------------|-------------|
| `analyze_pcap_file` | `display_filter`, `keylog_file`, `max_packets` | Packet summaries with optional display filter and TLS decryption |
| `get_packet_statistics` | — | Protocol hierarchy statistics (`io,phs`) — shows all protocol layers present |
| `extract_packet_details` | `packet_number` | Full verbose detail for a specific packet (1-based index) |
| `extract_fields` | `fields`, `display_filter`, `keylog_file` | Extract any tshark field as tab-separated values |
| `export_to_json` | `display_filter`, `keylog_file`, `max_packets` | Export packets as JSON for structured analysis |
| `run_tshark_command` | `command_args` | Run any raw tshark command |

### Traffic Aggregation & Statistics

| Tool | Key Parameters | Description |
|------|---------------|-------------|
| `get_conversations` | `protocol` | Conversation statistics — protocol: `eth` / `ip` / `tcp` / `udp` / `sctp` |
| `get_flow_matrix` | `display_filter`, `top_n` | Host-pair communication matrix (ip.src × ip.dst), ranked by bytes |
| `get_traffic_timeseries` | `interval_seconds`, `display_filter` | Packets and bytes per time bucket — identifies bursts and periodic patterns |
| `aggregate_flows` | `group_by`, `display_filter`, `top_n` | Group packets by any field combination (e.g. `ip.src,tcp.dstport`) |

### Protocol-Specific Analysis

| Tool | Key Parameters | Description |
|------|---------------|-------------|
| `analyze_dns` | `display_filter`, `top_n` | DNS query patterns, NXDOMAIN detection, response time statistics |
| `get_tcp_performance` | `display_filter` | RTT, retransmissions, window size — diagnose network quality issues |
| `follow_stream` | `protocol`, `stream_index`, `keylog_file` | Reconstruct a TCP / UDP / **SCTP** stream as ASCII text |

### Telecom / SS7 Signaling

These tools handle the telecom core network signaling stack:
**SCTP → M3UA → SCCP → TCAP → MAP**

| Tool | Key Parameters | Description |
|------|---------------|-------------|
| `reconstruct_tcap_dialogue` | `display_filter`, `max_dialogues` | Group TCAP messages (Begin/Continue/End/Abort) by transaction ID (OTID/DTID) |
| `analyze_map_operations` | `display_filter`, `top_n` | MAP operation frequency table + per-IMSI activity summary |

### TLS Decryption

> Requires a [TLS key log file](#tls-decryption-setup) generated by the target application.

| Tool | Description |
|------|-------------|
| `follow_tls_stream` | Reconstruct a decrypted TLS stream as plaintext from a PCAP + key log file |
| `capture_and_decrypt` | Capture live traffic and immediately show decrypted TLS content |
| `tshark_reading_manual` | **Read this first** — full TLS decryption workflow including debugger-based key extraction |

### Live Capture

| Tool | Key Parameters | Description |
|------|---------------|-------------|
| `list_interfaces` | — | List available network interfaces for live capture |
| `capture_live` | `interface`, `packet_count`, `duration`, `display_filter` | Capture live packets (max 500 packets / 60 s) |
| `capture_process` | `pid`, `interface`, `output_pcap`, `duration`, `keylog_file` | Capture traffic for a specific process by PID |

### File Operations

| Tool | Key Parameters | Description |
|------|---------------|-------------|
| `filter_and_save` | `display_filter` | Filter packets from a PCAP and save to a new PCAP file |
| `export_objects` | `protocol`, `output_dir` | Extract files transferred over HTTP / SMB / TFTP / IMF / DICOM |
| `merge_pcap_files` | `input_files`, `output_file`, `display_filter` | Merge multiple PCAPs in timestamp order (uses `mergecap`) |

### Process Management

| Tool | Description |
|------|-------------|
| `list_processes` | List running processes with PIDs (filter by name) |

---

## Examples

### General PCAP Analysis

```python
# Protocol hierarchy — confirm what layers are in the capture
get_packet_statistics("/captures/traffic.pcap")

# First 100 packets, HTTP only
analyze_pcap_file("/captures/traffic.pcap", display_filter="http")

# Extract source IPs, methods, and URIs from HTTP requests
extract_fields(
    file_path="/captures/traffic.pcap",
    fields="ip.src,http.request.method,http.request.uri",
    display_filter="http.request"
)

# Full detail for packet 42
extract_packet_details("/captures/traffic.pcap", packet_number=42)
```

### Traffic Aggregation

```python
# Which hosts talk to each other most? (top 20 by bytes)
get_flow_matrix("/captures/traffic.pcap")

# Traffic volume over time — 5-second buckets
get_traffic_timeseries("/captures/traffic.pcap", interval_seconds=5.0)

# TCP traffic only, 1-second buckets
get_traffic_timeseries("/captures/traffic.pcap", interval_seconds=1.0, display_filter="tcp")

# Per-service breakdown: which src IP hits which dst port most?
aggregate_flows(
    file_path="/captures/traffic.pcap",
    group_by="ip.src,ip.dst,tcp.dstport",
    display_filter="tcp"
)

# SCTP conversation statistics
get_conversations("/captures/ss7.pcap", protocol="sctp")
```

### DNS Analysis

```python
# Top queried domains, NXDOMAIN failures, response times
analyze_dns("/captures/traffic.pcap")

# DNS from a specific client only
analyze_dns("/captures/traffic.pcap", display_filter="ip.src == 192.168.1.10")
```

### TCP Performance Diagnosis

```python
# RTT, retransmission rate, window size — is the network healthy?
get_tcp_performance("/captures/traffic.pcap")

# Performance for a specific server
get_tcp_performance("/captures/traffic.pcap", display_filter="ip.addr == 10.0.0.1")
```

### Stream Reconstruction

```python
# Follow the first TCP stream
follow_stream("/captures/traffic.pcap", protocol="tcp", stream_index=0)

# Follow an SCTP stream
follow_stream("/captures/ss7.pcap", protocol="sctp", stream_index=0)

# Follow a TELNET session (TELNET runs over TCP port 23)
follow_stream("/captures/traffic.pcap", protocol="tcp", stream_index=0)
```

### Telecom / SS7 Signaling Analysis

The typical protocol stack is: **SCTP → M3UA → SCCP → TCAP → MAP**

```python
# Step 1 — confirm SS7 layers are present
get_packet_statistics("/captures/ss7.pcap")
# Expected output includes: sctp, m3ua, mtp3, sccp, tcap, gsm_map

# Step 2 — reconstruct TCAP dialogues (Begin→Continue→End chains)
reconstruct_tcap_dialogue("/captures/ss7.pcap")

# Step 3 — MAP operation frequency + IMSI tracking
analyze_map_operations("/captures/ss7.pcap")

# Step 4 — raw MAP field extraction
extract_fields(
    file_path="/captures/ss7.pcap",
    fields="gsm_map.opr.code,gsm_map.imsi,gsm_map.msisdn.digits",
    display_filter="gsm_map"
)

# SCCP routing analysis — who calls whom?
aggregate_flows(
    file_path="/captures/ss7.pcap",
    group_by="sccp.calling_party,sccp.called_party",
    display_filter="sccp"
)

# Filter to a specific TCAP dialogue by OTID
extract_fields(
    file_path="/captures/ss7.pcap",
    fields="frame.time_relative,tcap.MessageType,tcap.otid,tcap.dtid,gsm_map.opr.code",
    display_filter="tcap.otid == aabbccdd"
)
```

### File Extraction (Forensics)

```python
# Extract files transferred over HTTP in a capture
export_objects(
    file_path="/captures/traffic.pcap",
    protocol="http",
    output_dir="/tmp/extracted/"
)

# Extract SMB file transfers
export_objects(
    file_path="/captures/traffic.pcap",
    protocol="smb",
    output_dir="/tmp/smb_files/"
)
```

### Multi-PCAP Correlation

```python
# Merge two captures from different taps, analyze combined
merge_pcap_files(
    input_files="/captures/tap1.pcap,/captures/tap2.pcap",
    output_file="/captures/merged.pcap"
)

# With a display filter on the merged result
merge_pcap_files(
    input_files="/captures/tap1.pcap,/captures/tap2.pcap",
    output_file="/captures/merged.pcap",
    display_filter="tcp"
)
```

### TLS Decryption

```python
# Decrypt and reconstruct HTTPS stream
follow_tls_stream(
    file_path="/captures/traffic.pcap",
    keylog_file="C:/captures/keys.log",
    stream_index=0
)

# Extract HTTP fields from decrypted traffic
extract_fields(
    file_path="/captures/traffic.pcap",
    fields="ip.src,http.request.method,http.request.uri",
    display_filter="http.request",
    keylog_file="C:/captures/keys.log"
)

# Live capture + real-time TLS decryption
capture_and_decrypt(
    interface=r"\Device\NPF_{...}",
    keylog_file="C:/captures/keys.log",
    output_pcap="C:/captures/session.pcap",
    duration=30
)
```

### Process-Specific Capture

```python
# Find process PID
list_processes("chrome")
# → chrome.exe  PID 4812

# Capture traffic for that process
capture_process(
    pid=4812,
    interface=r"\Device\NPF_{...}",   # from list_interfaces()
    output_pcap="C:/captures/chrome.pcap",
    duration=30
)

# Capture + decrypt TLS in one step
capture_process(
    pid=4812,
    interface=r"\Device\NPF_{...}",
    output_pcap="C:/captures/chrome.pcap",
    duration=30,
    keylog_file="C:/captures/keys.log"   # set SSLKEYLOGFILE before launching Chrome
)
```

---

## Protocol Support Reference

| Protocol | Filter | Relevant Fields | Best Tool |
|----------|--------|-----------------|-----------|
| TCP | `tcp` | `tcp.srcport`, `tcp.dstport`, `tcp.stream` | `follow_stream`, `get_tcp_performance` |
| UDP | `udp` | `udp.srcport`, `udp.dstport` | `follow_stream`, `get_conversations` |
| **SCTP** | `sctp` | `sctp.srcport`, `sctp.dstport`, `sctp.chunk_type` | `get_conversations`, `follow_stream` |
| HTTP | `http` | `http.request.uri`, `http.response.code` | `extract_fields`, `export_objects` |
| TLS/HTTPS | `tls` | `tls.record.content_type` | `follow_tls_stream`, `capture_and_decrypt` |
| DNS | `dns` | `dns.qry.name`, `dns.flags.rcode`, `dns.time` | `analyze_dns` |
| TELNET | `telnet` | (follow TCP stream) | `follow_stream` (protocol=tcp) |
| **M3UA** | `m3ua` | `m3ua.protocol_data_opc`, `m3ua.protocol_data_dpc` | `extract_fields`, `aggregate_flows` |
| **SCCP** | `sccp` | `sccp.calling_party`, `sccp.called_party`, `sccp.ssn` | `aggregate_flows`, `extract_fields` |
| **TCAP** | `tcap` | `tcap.otid`, `tcap.dtid`, `tcap.MessageType` | `reconstruct_tcap_dialogue` |
| **MAP** | `gsm_map` | `gsm_map.opr.code`, `gsm_map.imsi`, `gsm_map.msisdn.digits` | `analyze_map_operations` |

---

## TLS Decryption Setup

TShark can decrypt TLS traffic when given the session keys written by the application. Set the `SSLKEYLOGFILE` environment variable **before** launching the target application:

```bash
# Windows
set SSLKEYLOGFILE=C:\captures\keys.log
start chrome

# Linux / macOS
export SSLKEYLOGFILE=/tmp/keys.log
google-chrome &
```

Supported runtimes: Chrome, Edge, Firefox, curl, Python (requests / httpx / aiohttp), Go `crypto/tls` (with `SSLKEYLOGFILE` patch), Node.js (`--tls-keylog`).

For applications that do **not** support `SSLKEYLOGFILE` (compiled binaries, custom TLS stacks), keys must be extracted from process memory using a debugger. Call `tshark_reading_manual` for the complete step-by-step workflow including x64dbg-based key extraction.

---

## Process-Specific Capture — How It Works

1. **`list_processes`** — find the PID of the target process.
2. **`capture_process`** — snapshots the process's open connections at capture start, builds a BPF filter from its local ports, then runs a timed capture saving to a PCAP file.

Because the filter is derived at capture start, connections opened later still get captured if they share a port already in the filter. For long-running captures or applications with many short-lived connections, re-run `capture_process` as needed, or use `capture_live` without a filter and post-filter with `filter_and_save`.

| Platform | Tool used internally | Notes |
|----------|---------------------|-------|
| Windows  | `netstat -ano` (built-in) | No extra installation needed |
| macOS    | `lsof` (built-in) | No extra installation needed |
| Linux    | `ss` (iproute2) | Usually pre-installed; `apt install iproute2` if missing |

---

## Development

```bash
git clone <repository-url>
cd tshark-mcp
uv sync

# Run during development
uv run server.py                                     # stdio
uv run server.py --transport http --port 8100        # HTTP
uv run tshark-mcp-http                               # HTTP (entry-point alias)

# Tests (no TShark installation required — subprocess is mocked)
uv run python -m pytest test_server.py -v

# Build a local wheel and install it as a uv tool (Windows service ready)
uv build
uv tool install --reinstall ".\dist\tshark_mcp-1.0.0-py3-none-any.whl[windows-service]"

# Clean build artifacts
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue dist, build, *.egg-info
```

## Project Policies

- License: see [LICENSE](LICENSE)
- Contributing: see [CONTRIBUTING.md](CONTRIBUTING.md)
- Code of conduct: see [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)
- Security: see [SECURITY.md](SECURITY.md)

## Release

Automated via [.github/workflows/release.yml](.github/workflows/release.yml). Pushing a `v*` tag builds the wheel and publishes to PyPI using the `PYPI_API_TOKEN` repo secret:

```bash
git tag v1.2.3
git push origin v1.2.3
```

- Pre-release check: `uv run python scripts/release_check.py`
- Full release process + one-time `PYPI_API_TOKEN` setup: see [RELEASE.md](RELEASE.md)

TDQS

A3.6/5.0

Scored across 25 tools

Disambiguation2/5

Several tools overlap significantly: analyze_pcap_file, extract_fields, export_to_json, and run_tshark_command all provide generic packet extraction; get_flow_matrix, aggregate_flows, and get_conversations all produce communication summaries. This creates selection ambiguity for agents.

Naming Consistency5/5

All tools follow a consistent verb_noun snake_case convention (get_, list_, analyze_, extract_, etc.), with only tshark_reading_manual deviating as a documentation helper.

Tool Count3/5

At 25 tools, the set sits at the high end of the borderline range. While many tools serve specialized purposes, several are redundant (e.g., multiple generic extraction tools), making the surface feel heavier than necessary.

Completeness5/5

The domain of PCAP analysis is thoroughly covered: capture, filtering, field extraction, JSON export, stream following, TLS decryption, DNS/TCP/SS7 analysis, object export, and merging. The presence of run_tshark_command also provides a fallback for any uncovered operation, eliminating dead ends.

Maintenance

ActivityInactive
ResponsivenessNo issues