Skip to content

Stephen-Arsenault/usb-sniffer-MCP

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

USB Sniffer Lite — MCP Edition

A low-cost USB protocol sniffer for Raspberry Pi RP2040, extended with a Model Context Protocol (MCP) server so that AI assistants can autonomously operate the hardware.

This is a fork of Alex Taradov's usb-sniffer-lite. The MCP extension was architected and implemented through a collaborative session with Claude (Anthropic), with the goal of making low-level USB hardware directly accessible to AI agents for debugging and reverse engineering workflows.

What this means in practice: Claude (or any MCP-capable assistant) can initiate a capture, stop it after a chosen duration, and ingest the results — either as a compact token-efficient summary or as a fully decoded transaction view — without any manual terminal interaction. The assistant observes raw USB traffic and reasons about it directly.

Supports Low Speed (1.5 Mbit/s) and Full Speed (12 Mbit/s) capture. The firmware enumerates as a USB CDC virtual COM port (no driver needed on any OS) plus a vendor bulk endpoint for high-throughput binary streaming.


How It Works

The sniffer taps the D+ and D- lines of a USB cable. The RP2040 runs a PIO state machine that decodes NRZI signalling in real time on Core 1, while Core 0 handles USB device enumeration and data transfer to the host.

The MCP extension adds three layers on top of the original firmware:

  1. EP0 vendor control channel — four new USB control requests (GET_STATUS, SET_MODE, SET_SPEED, START, STOP) added to the firmware, callable without claiming any interface or installing a driver.
  2. sniffer_device.py — a thin Python wrapper around those control requests.
  3. sniffer_mcp.py — a FastMCP server that exposes capture and analysis as tools.

Hardware

Wiring

Splice a short USB cable and connect D+ and D- directly to the RP2040 GPIO pins. No level shifting is needed; USB FS/LS signal levels are within the RP2040's tolerance.

RP2040 Pin Function USB Cable Colour Required
GND Ground Black Yes
GPIO 10 D+ Green Yes
GPIO 11 D− White Yes
GPIO 12 Start (internal) No
GPIO 18 Trigger No
GPIO 25 Status LED No
GPIO 26 Error LED No

The trigger input is internally pulled up; active low. When enabled in the settings, capture pauses until the trigger pin is pulled low — useful for marking a specific point of interest from the target device itself.

The spliced cable does not need to be pretty. Below is one that took under ten minutes:

USB Cable

Dedicated PCB

A dedicated board integrating a FE8.1 USB hub is available, so only one host port is needed for both the sniffer and the target. Schematics and Gerber files are in the hardware directory.

USB Sniffer Lite PCB

More photos of a clean build on a custom RP2040 breakout are in doc/Hardware.md.


Firmware

Building

cd firmware
mkdir build && cd build
PICO_SDK_PATH=/path/to/pico-sdk cmake ..
make -j$(nproc)
python3 ../patch_uf2_crc.py UsbSnifferLite.uf2 UsbSnifferLite_patched.uf2

The patch_uf2_crc.py step is required — the custom boot sector needs its CRC recalculated after linking.

Flashing

Hold BOOTSEL and plug in (or tap reset while holding BOOTSEL), then:

# With picotool (recommended):
picotool load -f UsbSnifferLite_patched.uf2 --update -x

# Or copy to the mass storage drive:
cp UsbSnifferLite_patched.uf2 /Volumes/RPI-RP2/

A pre-built binary is available in bin/.


Interactive Use (CDC serial)

Connect to the virtual COM port with any serial terminal (115200 baud, though baud rate is irrelevant for CDC). The following single-key commands are supported:

Key Action
h Print help and current settings
s Start capture
p Stop capture
b Display current buffer
e Toggle capture speed (Low / Full)
d Cycle stream mode (Disabled → Text/CDC → Raw/Bulk)
g Toggle trigger (Enabled / Disabled)
l Cycle capture limit
t Cycle time display format
a Cycle data display format
f Toggle empty frame folding

Example capture logs: USB FS enumeration · data transfer.

For decoding standard descriptors and requests, the USB Descriptor and Request Parser is very useful.


MCP Server (AI Assistant Integration)

Installation

Requirements: pip install pyusb mcp

Add the server to your AI assistant's MCP configuration. Adjust the path to match where you cloned this repository.

Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%\Claude\claude_desktop_config.json on Windows):

{
  "mcpServers": {
    "sniffer": {
      "command": "python3",
      "args": ["/path/to/usb-sniffer-MCP/firmware/sniffer_mcp.py"]
    }
  }
}

Cursor — Settings → Features → MCP Servers → Add New:

  • Type: command
  • Name: sniffer
  • Command: python3 /path/to/usb-sniffer-MCP/firmware/sniffer_mcp.py

Zed (~/.config/zed/settings.json):

{
  "experimental.mcp_servers": {
    "sniffer": {
      "command": "python3",
      "args": ["/path/to/usb-sniffer-MCP/firmware/sniffer_mcp.py"]
    }
  }
}

Restart the application after editing the config.

Available Tools

Device control

Tool Description
sniffer_get_status() Read stream mode, capture speed, running state, and frame count
sniffer_set_speed(speed) Set bus speed: "low" or "full". Safe while running; takes effect on next start
sniffer_set_mode(mode) Set stream mode: "disabled", "text", or "raw" (raw auto-starts capture)
sniffer_start() Start capture with current settings
sniffer_stop() Stop an active capture
sniffer_capture(output_path, duration_seconds, speed) High-level: configure, capture for N seconds, stop, return summary

Capture ingestion — two modes

Once a .bin file has been written by sniffer_capture(), the assistant can read it back in one of two modes depending on the task and token budget:

sniffer_read_raw(capture_path, max_frames, fold_sof)low-token mode

One compact line per frame, SOFs folded into a count. Good for large captures, timeline reconstruction, and "what happened" queries. Approximately 25–40 tokens per frame.

--- 47 SOF frames ---
#0048  SETUP   addr=0x05/ep=0
#0049  DATA0   [8B: 80 06 00 01 00 00 12 00]
#0050  ACK
#0051  IN      addr=0x05/ep=0
#0052  DATA1   [18B: 12 01 00 02 00 00 00 40 66 66 10 66 01 01 ...]
#0053  ACK

sniffer_read_decoded(capture_path, max_transactions, fold_sof, filter_addr, filter_ep)full-flavor mode

Groups frames into logical token→data→handshake transactions. Expands SETUP packets into named fields. Decodes standard USB descriptors (Device, Configuration, Interface, Endpoint, String). Supports filtering by device address and endpoint. Good for deep protocol analysis and unknown-device identification. Approximately 80–150 tokens per transaction.

#0048  SETUP  addr=0x05  ep=0
  bmRequestType = 0x80  (IN, Standard, Device)
  bRequest      = GET_DESCRIPTOR
  wValue        = 0x0100  (type=Device, index=0)
  wIndex        = 0x0000
  wLength       = 18
  → ACK
#0051  IN  addr=0x05  ep=0
  DATA1  [18B]  12 01 00 02 00 00 00 40 66 66 10 66 01 01 01 02 03 01
  [Device Descriptor]
  bcdUSB    = 2.00
  idVendor  = 0x6666
  idProduct = 0x6610
  bcdDevice = 1.01
  → ACK

Typical AI workflow

1. sniffer_set_speed("full")
2. sniffer_capture("session.bin", duration_seconds=10)
3. sniffer_read_raw("session.bin")          # get the lay of the land
4. sniffer_read_decoded("session.bin",      # drill into enumeration
       filter_addr=0, max_transactions=50)

File Reference

firmware/
  capture.c / capture.h      — PIO capture engine (Core 1)
  usb_mcp.c / usb_mcp.h      — EP0 vendor control request handler (new)
  usb_bulk.c / usb_bulk.h    — EP4 IN bulk streaming ring buffer
  sniffer_device.py           — USB control layer (pyusb wrapper)
  sniffer_mcp.py              — MCP server (FastMCP, 8 tools)
  frame_parser.py             — Binary frame reassembly and field extraction
  packet_decoder.py           — USB protocol interpretation (transactions, descriptors)
  capture.py                  — Standalone bulk capture script

Credits

Original firmware and hardware design by Alex Taradov — BSD-3-Clause.

MCP extension developed by Stephen Arsenault in collaboration with Claude (Anthropic).

About

A simple USB sniffer based on Raspberry Pi RP2040 with MCP Support

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • C 97.4%
  • Python 2.5%
  • Other 0.1%