ESP32 MCP Server
About
Allow AI models connect to ESP32 and read connected sensors NMEA2k, ODB/ODBII, NMEA0183. AI generated MCP server.
Details
- License
- MIT
Explore
| 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 |
---
- PlatformIO Core CLI or the PlatformIO IDE plugin for VS Code
- Python 3.8+
- Git
pip install platformio
---
pio pkg install
{"jsonrpc":"2.0","method":"bus/history/config/get","id":6}
{
"jsonrpc":"2.0","id":6,
"result":{
"canFrameCount":500,
"nmeaLineCount":1000,
"nmea2000Count":200,
"obdiiCount":300,
"ramBudgetBytes":1048576,
"safetyMarginBytes":65536,
"freeHeapBytes":2097152
}
}
All fields are optional; omitted fields retain their current values.
{
"jsonrpc":"2.0","method":"bus/history/config/set","id":7,
"params":{"canFrameCount":1000,"ramBudgetBytes":2097152}
}
{"jsonrpc":"2.0","id":7,"result":{"ok":true,"canFrameCount":1000,"nmeaLineCount":1000,"nmea2000Count":200,"obdiiCount":300,"ramBudgetBytes":2097152,"safetyMarginBytes":65536}}
> Set canFrameCount, nmeaLineCount, nmea2000Count, obdiiCount all to 0 to enable auto-sizing: the server splits ramBudgetBytes equally among the four buffer types based on the size of each record type.
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.

---
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
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.



