Add comprehensive README with ESP32 capabilities and E2E testing guide

- Project overview and architecture diagram
- ESP32 hardware requirements and capabilities
- Full MCP tool reference (connection, classic BT, BLE/GATT, events)
- Quick start guide and Claude Code integration
- E2E testing instructions with latest results (v5: 76/76 PASS)
- Links to detailed documentation
This commit is contained in:
Ryan Malloy 2026-02-03 12:11:11 -07:00
parent 88d006e9c4
commit 5dcacc23ab

221
README.md Normal file
View File

@ -0,0 +1,221 @@
# mcbluetooth-esp32
ESP32 Bluetooth test harness MCP server — UART-controlled peripheral for automated E2E Bluetooth testing.
## Overview
This project turns an ESP32 into a programmable Bluetooth peripheral that can be controlled via MCP (Model Context Protocol). Combined with [mcbluetooth](https://github.com/supported-systems/mcbluetooth) (Linux BlueZ MCP server), it enables fully automated end-to-end Bluetooth testing orchestrated by an LLM.
```
┌─────────────────────────────────────────────────────────────────┐
│ LLM (Claude, etc.) │
│ Orchestrates both MCP servers │
└─────────────────────────┬───────────────────────────────────────┘
┌───────────────┴───────────────┐
│ │
┌───────┴───────┐ ┌───────┴────────┐
│ mcbluetooth │ │mcbluetooth-esp32│
│ (bt_* tools)│ │ (esp32_* tools) │
└───────┬───────┘ └───────┬────────┘
│ │
D-Bus/BlueZ Serial/UART
│ │
┌───────┴───────┐ ┌───────┴────────┐
│ Linux Host │◄── Bluetooth ──►│ ESP32 │
│ (hci0/1) │ (over air) │ (peripheral) │
└───────────────┘ └────────────────┘
```
## ESP32 Capabilities
The ESP32 can emulate various Bluetooth devices for testing:
| Capability | Description |
|------------|-------------|
| **Classic BT Pairing** | All 4 SSP modes: Just Works, Numeric Comparison, Passkey Entry, Legacy PIN |
| **BLE GATT Server** | Dynamic service/characteristic creation at runtime |
| **Device Personas** | Presets for headset, speaker, keyboard, sensor, phone |
| **IO Capabilities** | Configurable: `no_io`, `display_only`, `display_yesno`, `keyboard_only`, `keyboard_display` |
| **Event Reporting** | Real-time events: pair_request, pair_complete, gatt_read, gatt_write, gatt_subscribe |
### Hardware Requirements
- **Original ESP32** (ESP32-D0WD or similar) — must have Classic Bluetooth support
- ESP32-S3, C3, H2, S2 will NOT work (no BR/EDR radio)
- USB cable for serial communication
### Verified Hardware
| Property | Value |
|----------|-------|
| Chip | ESP32-D0WD-V3 (rev 3.1) |
| Features | Wi-Fi, BT Classic + BLE, Dual Core 240MHz |
| Flash | 4MB |
| Protocol | NDJSON over UART @ 115200 baud |
## Quick Start
### 1. Flash the firmware
```bash
# Install ESP-IDF v5.x first (see docs/hardware-setup.md)
cd firmware
idf.py set-target esp32
idf.py -p /dev/ttyUSB0 flash
```
### 2. Run the MCP server
```bash
# Install and run
uvx mcbluetooth-esp32
# Or with explicit port
ESP32_SERIAL_PORT=/dev/ttyUSB0 uvx mcbluetooth-esp32
```
### 3. Add to Claude Code
```bash
claude mcp add mcbluetooth-esp32 -- uvx mcbluetooth-esp32
```
### 4. Verify connection
```python
esp32_connect() # → connected=true, ready=true
esp32_ping() # → {pong: true}
esp32_get_info() # → chip, fw_version, bt_mac
```
## MCP Tools
### Connection & System
| Tool | Description |
|------|-------------|
| `esp32_connect` | Open serial connection to ESP32 |
| `esp32_disconnect` | Close serial connection |
| `esp32_ping` | Verify UART link is alive |
| `esp32_status` | Get current BT/BLE state |
| `esp32_get_info` | Get chip model, firmware version, MAC |
| `esp32_reset` | Reboot the ESP32 |
### Configuration
| Tool | Description |
|------|-------------|
| `esp32_configure` | Set device name, IO capabilities, PIN |
| `esp32_set_ssp_mode` | Configure SSP pairing mode with optional auto-accept |
| `esp32_load_persona` | Load preset device profile (headset, speaker, etc.) |
### Classic Bluetooth
| Tool | Description |
|------|-------------|
| `esp32_classic_enable` | Enable BR/EDR radio |
| `esp32_classic_disable` | Disable BR/EDR radio |
| `esp32_classic_set_discoverable` | Make device visible for pairing |
| `esp32_classic_pair_respond` | Accept/reject incoming pairing |
### BLE / GATT
| Tool | Description |
|------|-------------|
| `esp32_ble_enable` | Enable BLE radio |
| `esp32_ble_disable` | Disable BLE radio |
| `esp32_ble_advertise` | Start/stop BLE advertising |
| `esp32_ble_set_adv_data` | Configure advertisement data |
| `esp32_gatt_add_service` | Create GATT service |
| `esp32_gatt_add_characteristic` | Add characteristic to service |
| `esp32_gatt_set_value` | Set characteristic value |
| `esp32_gatt_notify` | Send notification to subscribers |
| `esp32_gatt_clear` | Remove all GATT services |
### Events
| Tool | Description |
|------|-------------|
| `esp32_get_events` | Retrieve event history |
| `esp32_wait_event` | Block until specific event occurs |
| `esp32_clear_events` | Clear event history |
## E2E Testing
Run automated tests using Claude CLI in headless mode:
```bash
# Setup test environment
mkdir -p /tmp/bt-e2e-test && cd /tmp/bt-e2e-test
git init
# Create MCP config with both servers
cat > .mcp.json << 'EOF'
{
"mcpServers": {
"esp32": {
"type": "stdio",
"command": "uvx",
"args": ["mcbluetooth-esp32"],
"env": {"ESP32_SERIAL_PORT": "/dev/ttyUSB0"}
},
"bluez": {
"type": "stdio",
"command": "uvx",
"args": ["mcbluetooth"]
}
}
}
EOF
# Run test suite
PROMPT=$(cat tests/prompts/test-prompt-v5.md)
claude -p "$PROMPT" \
--mcp-config .mcp.json \
--allowedTools "mcp__esp32__*,mcp__bluez__*" \
--output-format json
```
### Test Coverage (v5 - 76 tests)
| Phase | Tests | Coverage |
|-------|-------|----------|
| ESP32 Connection | 1-4 | connect, ping, info, status |
| BlueZ Adapter | 5-8 | list, info, pairable, discoverable |
| Classic BT + SSP | 9-24 | Full pairing workflow with auto-accept |
| BLE GATT Setup | 30-42 | Battery Service, Environmental Sensing |
| HCI Capture | 43-55 | btsnoop capture and analysis |
| GATT Operations | 56-63 | read, write, notify, subscribe |
| Cleanup | 64-76 | Adapter management, reset |
### Recent Test Results
| Version | Tests | Result | Duration |
|---------|-------|--------|----------|
| v4 | 71 | 66 PASS, 5 PARTIAL | 8.6 min |
| v5 | 76 | **76/76 PASS (100%)** | 7.6 min |
## Documentation
| Document | Description |
|----------|-------------|
| [hardware-setup.md](docs/hardware-setup.md) | ESP-IDF installation, flashing, wiring |
| [protocol-spec.md](docs/protocol-spec.md) | NDJSON UART protocol specification |
| [test-scenarios.md](docs/test-scenarios.md) | Manual E2E test procedures |
| [automated-e2e-testing.md](docs/automated-e2e-testing.md) | Claude CLI headless testing guide |
## Development
```bash
# Install dev dependencies
uv sync --all-extras
# Run unit tests
uv run pytest tests/ -v --ignore=tests/integration
# Run integration tests (requires ESP32)
ESP32_SERIAL_PORT=/dev/ttyUSB0 uv run pytest tests/integration/ -v
# Lint
uv run ruff check src/
```
## License
MIT