ESP32 MCP Server

by navado

49 stars
627 downloads
Not rated
GitHub

About

Allow AI models connect to ESP32 and read connected sensors NMEA2k, ODB/ODBII, NMEA0183. AI generated MCP server.

Details

Author
navado
GitHub stars
49
Downloads
627
Categories
Other

- MCP protocol (JSON‑RPC 2.0 over WebSocket) with resource discovery and subscriptions
- I2C sensor auto‑scan and drivers for BME280, MPU6050, ADS1115, SHT31, BH1750, INA219
- NMEA 0183 parser (GGA, RMC, VTG, GSV, MWV, DBT, DPT, HDG, HDT) with XOR checksum validation
- NMEA 2000 / CAN decoding (position, heading, speed, depth, wind, attitude, water temperature)
- OBD‑II / CAN decoding (60+ PIDs, service 01/09)
- Persistent ring buffers for bus history (CAN, NMEA, NMEA 2000, OBD‑II) queryable via MCP
- WiFi setup UI + STA mode; mDNS and UDP discovery; web dashboard and HTTP endpoints

Clone the repository, install library dependencies with PlatformIO, build and flash the firmware, then upload web assets to LittleFS (optional). On first run, connect to the board’s WiFi AP (ESP32_XXXXXX), open http://192.168.4.1, enter your WiFi credentials, and the board will join your network. Connect any MCP client to ws://<IP>:9000 to start querying sensors, bus data, and bus history.

ESP32 MCP Server

Build & Test

A Model Context Protocol (MCP) server running on ESP32 (and Nordic nRF52840 in sensor-only mode), exposing real-world sensor data and bus protocols to AI assistants and automation tooling over WebSocket / JSON-RPC 2.0.

Connect an AI agent directly to your hardware: query I2C sensors, parse NMEA 0183 GPS/marine data, decode NMEA 2000 and OBD-II CAN frames, replay bus history — all through a standard MCP interface.

architecture

---

Features

| Capability | Details |
|---|---|
| MCP Protocol | JSON-RPC 2.0 over WebSocket, resource discovery & subscriptions |
| I2C Sensors | Auto-scan + drivers for BME280, MPU6050, ADS1115, SHT31, BH1750, INA219 |
| NMEA 0183 | GGA, RMC, VTG, GSV, MWV, DBT, DPT, HDG, HDT with XOR checksum validation |
| NMEA 2000 / CAN | 29-bit PGNs: position, heading, speed, depth, wind, attitude, water temp |
| OBD-II / CAN | Standard 11-bit OBD-II service 01/09 PID decoding (60+ PIDs) |
| Bus History | Persistent ring buffers for CAN, NMEA, NMEA 2000, OBD-II — queryable via MCP |
| Bus Readers | Time-bounded serial and CAN reads, raw or parsed mode, JSON output |
| WiFi | AP setup UI + STA mode; credentials stored in NVS |
| Discovery | mDNS (_mcp._tcp) + UDP capability broadcast |
| Metrics | Heap, uptime, RSSI, histogram stats with boot persistence |
| Multi-board | ESP32-S3, ESP32-C3, ESP32, Adafruit HUZZAH32, M5Stack, Nordic nRF52840-DK, Adafruit Feather nRF52840 |
| Testing | Native unit tests (Unity), mock I2C / CAN / Serial / LittleFS |

---

Supported Boards

ESP32 Boards — Full MCP Server (WiFi + WebSocket + CAN)

| Board | PlatformIO env | MCU | Flash | RAM | WiFi | BLE | CAN | RGB LED |
|---|---|---|---|---|---|---|---|---|
| ESP32-S3-DevKitC-1 | esp32-s3-devkitc-1 | Xtensa LX7 × 2 @ 240 MHz | 8 MB | 512 KB + 8 MB PSRAM | ✓ | 5.0 | ✓ | GPIO48 |
| ESP32-DevKitC V4 | esp32-devkitc | Xtensa LX6 × 2 @ 240 MHz | 4 MB | 520 KB | ✓ | 4.2 | ✓ | — |
| ESP32-C3-DevKitM-1 | esp32-c3-devkitm-1 | RISC-V @ 160 MHz | 4 MB | 400 KB | ✓ | 5.0 | ✓ | GPIO8 |
| Adafruit HUZZAH32 | adafruit-huzzah32 | Xtensa LX6 × 2 @ 240 MHz | 4 MB | 520 KB | ✓ | 4.2 | ✓ | — |
| M5Stack Core ESP32 | m5stack-core | Xtensa LX6 × 2 @ 240 MHz | 16 MB | 520 KB | ✓ | 4.2 | ✗ | — |

nRF52840 Boards — Sensor Only (I2C + Serial, no WiFi)

| Board | PlatformIO env | MCU | Flash | RAM | BLE |
|---|---|---|---|---|---|
| Nordic nRF52840-DK | nrf52840-dk | Cortex-M4F @ 64 MHz | 1 MB | 256 KB | 5.0 + 802.15.4 |
| Adafruit Feather nRF52840 | nrf52840-feather | Cortex-M4F @ 64 MHz | 1 MB | 256 KB | 5.0 |

> nRF52840 targets run a separate main_nrf.cpp entry point: sensors + I2C + Serial output only. No WiFi, no MCP WebSocket, no LittleFS, no bus history. For full MCP-over-WiFi, bridge via an ESP32-C3 in AT-command mode connected to UART1.

Board Feature Matrix

| Feature | ESP32-S3 | ESP32 V4 | ESP32-C3 | HUZZAH32 | M5Stack | nRF52840-DK | nRF52840-Feather |
|---|---|---|---|---|---|---|---|
| WiFi | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ |
| BLE | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| CAN / TWAI | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ |
| I2C | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| UART (ext) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| LittleFS | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ |
| MCP Server | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ |
| Bus History | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ |
| mDNS / UDP discovery | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ |

---

Architecture

flowchart TD
    Client[AI Agent / MCP Client] -->|WebSocket :9000 JSON-RPC 2.0| MCPServer

subgraph ESP32
MCPServer -->|resources/list| Resources
MCPServer -->|sensors/i2c/scan| SensorMgr
MCPServer -->|sensors/read| SensorMgr
MCPServer -->|buses/serial/read| BusReader
MCPServer -->|buses/can/read| BusReader
MCPServer -->|bus/history/read| BusHistory
MCPServer -->|bus/history/config/*| BusHistory

SensorMgr -->|Wire I2C| I2CSensors[BME280 · MPU6050 · ADS1115\nSHT31 · BH1750 · INA219]
BusReader -->|UART| NMEAParser[NMEA 0183 Parser]
BusReader -->|CAN TWAI| CANParser[NMEA 2000 / OBD-II Parser]
BusReader -->|feed| BusHistory[Bus History\nRing Buffers]
BusHistory --> LittleFS

NetworkMgr[Network Manager] --> WiFi
NetworkMgr --> WebSetup[Setup UI :80]
DiscoveryMgr[Discovery Manager] -->|mDNS + UDP| Network
Metrics[Metrics System] --> LittleFS
uLogger --> LittleFS
end

MCPServer --> Metrics
MCPServer --> uLogger

---

Hardware

Pin Assignments (ESP32-S3-DevKitC-1)

| GPIO | Function | Connected to |
|---|---|---|
| IO8 | I2C SDA | All I2C sensors |
| IO9 | I2C SCL | All I2C sensors |
| IO16 | UART1 RX | GPS / chart plotter TX |
| IO17 | UART1 TX | GPS / chart plotter RX (optional) |
| IO4 | CAN RX | TJA1050 / SN65HVD230 CRXD |
| IO5 | CAN TX | TJA1050 / SN65HVD230 CTXD |

nRF52840-DK Pin Assignments

| Pin | Function |
|---|---|
| P0.26 / D6 | I2C SDA |
| P0.27 / D7 | I2C SCL |
| P0.06 / TX | UART1 TX |
| P0.08 / RX | UART1 RX |

Bill of Materials

| # | Part | Purpose |
|---|---|---|
| 1 | ESP32-S3-DevKitC-1 | Main MCU |
| 1 | BME280 breakout | Temperature / Humidity / Pressure |
| 1 | MPU6050 breakout | 6-axis IMU (optional) |
| 1 | TJA1050 or SN65HVD230 | CAN bus transceiver (optional) |
| 1 | GPS module (3.3 V UART) | NMEA 0183 position/time (optional) |
| 2 | 4.7 kΩ resistors | I2C pull-ups |
| — | Breadboard + jumpers | |

ESP32-S3-DevKitC-1 Wiring

                    ┌──────────────────────────────────────┐
                    │         ESP32-S3-DevKitC-1            │
                    │                                       │
             3V3 ───┤ 3V3                          GND ├─── GND
             GND ───┤ GND                          IO0 ├
                    │                                   │
  I2C SDA ── IO8 ───┤ IO8  ┌──────────┐       IO17 ├─── UART1 TX → GPS
  I2C SCL ── IO9 ───┤ IO9  │  ESP32   │       IO16 ├─── UART1 RX ← GPS
                    │ IO10 │    S3    │       IO15 ├
                    │ IO11 └──────────┘       IO14 ├
                    │ IO12                    IO13 ├
                    │ IO3                      IO4 ├─── CAN RX ← TJA1050
                    │ IO46                     IO5 ├─── CAN TX → TJA1050
                    │                               │
                    │    USB (flash / serial log)   │
                    └───────────────────────────────┘

I2C Sensor Wiring

All sensors share one bus. Add 4.7 kΩ pull-ups from SDA and SCL to 3V3.

ESP32-S3      BME280       MPU6050      ADS1115      INA219
─────────     ───────      ───────      ───────      ───────
IO8 (SDA)─────SDA──────────SDA──────────SDA──────────SDA
IO9 (SCL)─────SCL──────────SCL──────────SCL──────────SCL
3V3  ──────────VCC──────────VCC──────────VCC──────────VCC
GND  ──────────GND──────────GND──────────GND──────────GND
               SDO→GND      AD0→GND      ADDR→GND
               (0x76)       (0x68)       (0x48)       (0x40)

Other supported sensors (same bus wiring): SHT31 (0x44), BH1750 (0x23).

NMEA 0183 Wiring (GPS / Chart Plotter)

GPS / chart plotter              ESP32-S3
───────────────────              ────────
TX  (3.3 V TTL NMEA out) ─────── IO16 (UART1 RX)
RX  (optional NMEA in)   ─────── IO17 (UART1 TX)
GND                      ─────── GND
VCC (3.3 V)              ─────── 3V3

> If the device outputs RS-232 levels, use a MAX3232 level shifter. Never connect RS-232 directly to ESP32 GPIO.

CAN Bus Wiring (NMEA 2000 / OBD-II)

TJA1050 / SN65HVD230             ESP32-S3
────────────────────             ────────
CTXD                  ─────────── IO5 (CAN TX)
CRXD                  ─────────── IO4 (CAN RX)
VCC (5 V for TJA1050) ─────────── VIN / external 5 V
GND                   ─────────── GND
CANH ──────────────── NMEA 2000 backbone / OBD-II CANH
CANL ──────────────── NMEA 2000 backbone / OBD-II CANL

> NMEA 2000 runs at 250 kbps. OBD-II runs at 500 kbps. Set the baud rate in your CANBusReader configuration accordingly.

---

Software Prerequisites

- PlatformIO Core CLI or the PlatformIO IDE plugin for VS Code
- Python 3.8+
- Git

pip install platformio

---

Build & Flash

```bash

No reviews yet — be the first

Sign in to leave a review

Use Google, GitHub, or an email account so ratings stay tied to real people.

Email sign in

No reviews posted yet.