δΈζζζ‘£ | English
An ESP32 component that implements the Model Context Protocol (MCP) server, providing a standardized way for AI applications to integrate with ESP32 devices. This component enables your ESP32 to expose tools and resources that can be discovered and used by AI agents and applications.
- π Simple API: Clean, intuitive interface for registering tools and resources
- π§ Dynamic Registration: Register tools and resources at runtime
- π¦ Modular Design: Standalone component, easy to integrate into existing projects
- π HTTP Transport: JSON-RPC 2.0 over HTTP for maximum compatibility
- π URI Templates: Support for parameterized resource URIs (e.g.,
sensor://{type}/{id}
) - π Real-time Monitoring: Built-in server statistics and health monitoring
- π‘οΈ Memory Safe: Automatic memory management and cleanup
- β Schema Validation: Built-in parameter validation using JSON schemas (similar to Zod)
- π― MCP Compliant: Fully compliant with MCP specification 2025-06-18
The ESP32 MCP Server follows the standard MCP architecture:
βββββββββββββββββββ HTTP/JSON-RPC βββββββββββββββββββ
β MCP Client β βββββββββββββββββββΊ β ESP32 MCP β
β (AI Agent) β β Server β
βββββββββββββββββββ βββββββββββββββββββ
β
βββββββββββββββββββ
β Your ESP32 β
β Application β
β (Tools & Data) β
βββββββββββββββββββ
idf.py add-dependency "0x1abin/esp_mcp_server"
- Clone this repository into your project's
components
directory:
cd your_project/components
git clone https://github.com/0x1abin/esp-mcp-server.git esp_mcp_server
- Include the component in your main
CMakeLists.txt
:
idf_component_register(
SRCS "main.c"
INCLUDE_DIRS "."
REQUIRES esp_mcp_server
)
#include "esp_mcp_server.h"
// Tool handler function
static cJSON* echo_tool_handler(const cJSON *arguments, void *user_data) {
cJSON *message = cJSON_GetObjectItem(arguments, "message");
cJSON *result = cJSON_CreateObject();
cJSON *content_array = cJSON_CreateArray();
cJSON *content = cJSON_CreateObject();
cJSON_AddStringToObject(content, "type", "text");
cJSON_AddStringToObject(content, "text", message->valuestring);
cJSON_AddItemToArray(content_array, content);
cJSON_AddItemToObject(result, "content", content_array);
return result;
}
void app_main(void) {
// Initialize WiFi (using ESP-IDF examples common)
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
ESP_ERROR_CHECK(example_connect());
// Configure MCP server
esp_mcp_server_config_t config = ESP_MCP_SERVER_DEFAULT_CONFIG();
config.port = 80;
config.server_name = "ESP32 MCP Server";
config.server_version = "1.0.0";
// Initialize server
esp_mcp_server_handle_t server;
ESP_ERROR_CHECK(esp_mcp_server_init(&config, &server));
// Create input schema for validation
cJSON *schema = schema_builder_create_object();
schema_builder_add_string(schema, "message", "Message to echo", true);
// Register echo tool
esp_mcp_tool_config_t tool_config = {
.name = "echo",
.description = "Echoes back the provided message",
.input_schema = schema,
.handler = echo_tool_handler,
.user_data = NULL
};
ESP_ERROR_CHECK(esp_mcp_server_register_tool(server, &tool_config));
// Start the server
ESP_ERROR_CHECK(esp_mcp_server_start(server));
ESP_LOGI("MAIN", "MCP Server started on port %d", config.port);
}
// GPIO control tool with schema validation
static cJSON* gpio_control_handler(const cJSON *arguments, void *user_data) {
cJSON *pin = cJSON_GetObjectItem(arguments, "pin");
cJSON *state = cJSON_GetObjectItem(arguments, "state");
// SDK layer guarantees parameters are validated
int gpio_num = pin->valueint;
bool gpio_state = cJSON_IsTrue(state);
gpio_set_level(gpio_num, gpio_state ? 1 : 0);
cJSON *result = cJSON_CreateObject();
cJSON *content_array = cJSON_CreateArray();
cJSON *content = cJSON_CreateObject();
cJSON_AddStringToObject(content, "type", "text");
char response[100];
snprintf(response, sizeof(response), "GPIO %d set to %s",
gpio_num, gpio_state ? "HIGH" : "LOW");
cJSON_AddStringToObject(content, "text", response);
cJSON_AddItemToArray(content_array, content);
cJSON_AddItemToObject(result, "content", content_array);
return result;
}
// Register GPIO control tool with schema validation
cJSON *gpio_schema = schema_builder_create_object();
schema_builder_add_integer(gpio_schema, "pin", "GPIO pin number", 0, 39, true);
schema_builder_add_boolean(gpio_schema, "state", "GPIO state (true=HIGH, false=LOW)", true);
esp_mcp_tool_config_t gpio_tool = {
.name = "gpio_control",
.description = "Control ESP32 GPIO pins",
.input_schema = gpio_schema,
.handler = gpio_control_handler,
.user_data = NULL
};
ESP_ERROR_CHECK(esp_mcp_server_register_tool(server, &gpio_tool));
// Initialize server (does not start HTTP server)
esp_err_t esp_mcp_server_init(const esp_mcp_server_config_t *config,
esp_mcp_server_handle_t *server_handle);
// Start HTTP server after registering tools/resources
esp_err_t esp_mcp_server_start(esp_mcp_server_handle_t server_handle);
// Stop HTTP server (can be restarted later)
esp_err_t esp_mcp_server_stop(esp_mcp_server_handle_t server_handle);
// Cleanup and free all resources
esp_err_t esp_mcp_server_deinit(esp_mcp_server_handle_t server_handle);
// Register a tool with optional schema validation
esp_err_t esp_mcp_server_register_tool(esp_mcp_server_handle_t server_handle,
const esp_mcp_tool_config_t *tool_config);
// Tool handler signature
typedef cJSON* (*esp_mcp_tool_handler_t)(const cJSON *arguments, void *user_data);
// Register a resource
esp_err_t esp_mcp_server_register_resource(esp_mcp_server_handle_t server_handle,
const esp_mcp_resource_config_t *resource_config);
// Resource handler signature
typedef char* (*esp_mcp_resource_handler_t)(const char *uri, void *user_data);
// Create schema objects
cJSON* schema_builder_create_object(void);
// Add typed fields with validation
esp_err_t schema_builder_add_string(cJSON *schema, const char *name,
const char *description, bool required);
esp_err_t schema_builder_add_integer(cJSON *schema, const char *name,
const char *description, int min, int max, bool required);
esp_err_t schema_builder_add_boolean(cJSON *schema, const char *name,
const char *description, bool required);
This component fully implements the MCP specification:
- Tools: Execute actions with side effects (returns JSON)
- Resources: Provide data content (returns string/binary)
- Prompts: Reusable templates (planned)
- JSON-RPC 2.0: Complete protocol compliance
- Error Handling: Standard error codes and messages
- Schema Validation: Input parameter validation
Method | Description | Status |
---|---|---|
initialize |
Server initialization and capability negotiation | β |
tools/list |
List available tools | β |
tools/call |
Execute a tool | β |
resources/list |
List available resources | β |
resources/read |
Read resource content | β |
ping |
Health check | β |
The component includes a comprehensive example in examples/simple/
that demonstrates:
- WiFi connection setup
- MCP server initialization and configuration
- Tool registration with schema validation
- Resource registration with URI templates
- GPIO control integration
- ADC reading functionality
- Real-time server statistics
cd examples/simple
idf.py set-target esp32
idf.py menuconfig # Configure WiFi credentials
idf.py build flash monitor
typedef struct {
uint16_t port; // HTTP server port (default: 8080)
const char *server_name; // Server identification
const char *server_version; // Server version
size_t max_connections; // Max concurrent connections
size_t stack_size; // HTTP server stack size
int task_priority; // HTTP server task priority
} esp_mcp_server_config_t;
// Default configuration macro
#define ESP_MCP_SERVER_DEFAULT_CONFIG() { \
.port = 8080, \
.server_name = "ESP32 MCP Server", \
.server_version = "1.0.0", \
.max_connections = 4, \
.stack_size = 8192, \
.task_priority = 5 \
}
- Parameter Validation: All tool inputs are validated against JSON schemas
- Memory Safety: Automatic cleanup of JSON objects and strings
- Error Handling: Comprehensive error reporting with standard HTTP/JSON-RPC codes
- Resource Limits: Configurable connection limits and timeouts
Test your MCP server using any MCP-compatible client:
# Using curl to test tools/list
curl -X POST http://your-esp32-ip/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
# Using curl to call a tool
curl -X POST http://your-esp32-ip/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"echo","arguments":{"message":"Hello World"}}}'
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
This project is licensed under the MIT License - see the LICENSE file for details.
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- ESP32 Forum: Espressif Forum
Made with β€οΈ for the ESP32 and AI community