Protocol Specification
Overview
Section titled “Overview”MCP/U uses JSON-RPC 2.0 over a newline-delimited stream (Serial or TCP). Each message is a single JSON object terminated by \n.
Transport
Section titled “Transport”| Transport | Notes |
|---|---|
| Serial UART | Primary. 115200 baud default. |
| TCP (WiFi) | MCU listens on a configurable port. |
| Framing | Each message ends with \n. No embedded newlines. |
Request Format
Section titled “Request Format”{"jsonrpc": "2.0", "id": 1, "method": "gpio_write", "params": {"pin": 2, "value": true}}| Field | Type | Required | Description |
|---|---|---|---|
jsonrpc | "2.0" | Yes | JSON-RPC version |
id | integer | Yes | Request ID (echoed in response) |
method | string | Yes | Tool/method name |
params | object | No | Method parameters |
Response Format
Section titled “Response Format”Success:
{"jsonrpc": "2.0", "id": 1, "result": {"pin": 2, "name": "led", "value": true}}Error:
{"jsonrpc": "2.0", "id": 1, "error": {"code": -32602, "message": "Bad params"}}Error Codes
Section titled “Error Codes”| Code | Meaning | When |
|---|---|---|
-32700 | Parse error | Invalid JSON received |
-32600 | Invalid request | Missing jsonrpc or method |
-32601 | Method not found | Unknown method name |
-32602 | Invalid params | Missing or wrong-typed parameter |
Built-in Methods
Section titled “Built-in Methods”get_info
Section titled “get_info”Returns device metadata.
Request:
{"jsonrpc":"2.0","id":1,"method":"get_info"}Response:
{ "jsonrpc": "2.0", "id": 1, "result": { "device": "esp32-demo", "version": "1.0.0", "platform": "arduino", "pin_count": 3 }}list_tools
Section titled “list_tools”Discovery endpoint. Returns all tools with JSON Schema + pin registry.
Request:
{"jsonrpc":"2.0","id":1,"method":"list_tools"}Response:
{ "jsonrpc": "2.0", "id": 1, "result": { "device": "esp32-demo", "version": "1.0.0", "tools": [ { "name": "gpio_write", "description": "Write HIGH or LOW to a digital output pin", "inputSchema": { "type": "object", "properties": { "pin": { "type": "integer", "description": "GPIO pin number" }, "value": { "type": "boolean", "description": "true = HIGH, false = LOW" } }, "required": ["pin", "value"] } }, { "name": "read_touch", "description": "Read capacitive touch sensor buffer on GPIO4", "inputSchema": { "type": "object", "properties": {}, "required": [] }, "polling": { "enabled": true, "interval_ms": 2000 } } ], "pins": [ { "pin": 2, "name": "led", "type": "digital_output", "description": "Onboard LED" }, { "pin": 34, "name": "sensor", "type": "adc_input", "description": "Analog Sensor", "capabilities": { "summary": true, "buffer": true, "events": false }, "sampling": { "interval_ms": 500, "buffer_size": 20 } } ] }}polling field (custom tools)
Section titled “polling field (custom tools)”When a tool is registered with McpPolling(ms) in firmware, the polling object appears in its list_tools entry. The client reads this and auto-schedules periodic calls — no client-side configuration needed.
| Field | Type | Description |
|---|---|---|
polling.enabled | boolean | Always true when present |
polling.interval_ms | integer | Suggested call interval in milliseconds |
Pin capabilities and sampling fields
Section titled “Pin capabilities and sampling fields”Input pins registered with sampling options include extra metadata the client uses to configure automatic buffer draining.
| Field | Description |
|---|---|
capabilities.buffer | Ring buffer is enabled |
capabilities.summary | Rolling statistics (min/max/avg) are enabled |
sampling.interval_ms | Milliseconds between samples |
sampling.buffer_size | Number of samples in the ring buffer |
gpio_write
Section titled “gpio_write”Params: { "pin": <integer>, "value": <boolean> }
Response: { "pin": 2, "name": "led", "value": true }
gpio_read
Section titled “gpio_read”Params: { "pin": <integer> }
Response: { "pin": 2, "name": "led", "value": true }
pwm_write
Section titled “pwm_write”Uses analogWrite — default 5 kHz. For custom frequency use a custom LEDC tool.
Params: { "pin": <integer>, "duty": <0–255> }
Response: { "pin": 18, "name": "led_pwm", "duty": 128 }
adc_read
Section titled “adc_read”Params: { "pin": <integer> }
Response (ESP32 / ESP8266): { "pin": 34, "name": "sensor", "value": 2048, "volts": 1.65 }
Response (AVR — Uno/Mega/Nano): { "pin": 0, "name": "sensor", "value": 512, "mv": 1651 }
Pin Types
Section titled “Pin Types”| Type string | Meaning | Valid operations |
|---|---|---|
digital_output | Digital write pin | gpio_write, gpio_read |
digital_input | Digital read pin | gpio_read |
pwm_output | PWM output pin | pwm_write |
adc_input | Analog input pin | adc_read |
Discovery Sequence
Section titled “Discovery Sequence”sequenceDiagram participant Client participant MCU
Client->>MCU: connect (serial/TCP) Client->>MCU: get_info MCU-->>Client: {device, version, ...} Client->>MCU: list_tools MCU-->>Client: {tools[], pins[]} Note over Client: register MCP tools Client->>MCU: gpio_write {pin:2, val:1} MCU-->>Client: {pin:2, name:"led", ...}