EmbedMCP
FreeNot checkedProvides easy-to-use kits that allow you to quickly create MCP servers Any embedded devices
About
Provides easy-to-use kits that allow you to quickly create MCP servers Any embedded devices
README
A lightweight C library for creating MCP (Model Context Protocol) servers that transforms your existing C functions into AI-accessible tools with minimal code changes.
License: MIT C Standard Platform MCP
Why EmbedMCP?
EmbedMCP bridges the gap between your existing C codebase and modern AI systems. Instead of rewriting your battle-tested C functions, EmbedMCP lets you expose them to AI models through the standardized Model Context Protocol (MCP) with minimal code changes.
Key Features
- 🚀 Simple Integration: Copy one folder, include one header file
- ⚡ High Performance: Direct C function calls with minimal overhead
- 🔧 Cross-Platform: Runs on 15+ platforms via Universal HAL
- 📦 Zero Dependencies: Self-contained library with no external requirements
- 🎯 Two Registration Methods: Magic macros for simple functions, full control for complex ones
- 🌐 Multiple Transports: Streamable HTTP and STDIO support for different use cases
- 🧠 Smart Memory Management: Automatic cleanup with clear ownership rules
- 📊 Array Support: Handle both simple parameters and complex data structures
Quick Start
Installation
Download EmbedMCP
git clone https://github.com/AaronWander/EmbedMCP.git cd EmbedMCPCopy to your project
cp -r embed_mcp/ your_project/
Basic Usage
#include "embed_mcp/embed_mcp.h"
// Your business function
double add_numbers(double a, double b) {
return a + b;
}
// Generate wrapper with macro
EMBED_MCP_WRAPPER(add_wrapper, add_numbers, DOUBLE, DOUBLE, a, DOUBLE, b)
int main() {
embed_mcp_config_t config = {
.name = "MathServer",
.version = "1.0.0",
.instructions = "Simple math operations server",
.port = 8080
};
embed_mcp_server_t *server = embed_mcp_create(&config);
// Register function
const char* names[] = {"a", "b"};
const char* descs[] = {"First number", "Second number"};
mcp_param_type_t types[] = {MCP_PARAM_DOUBLE, MCP_PARAM_DOUBLE};
embed_mcp_add_tool(server, "add", "Add two numbers",
names, descs, types, 2, MCP_RETURN_DOUBLE, add_wrapper, NULL);
embed_mcp_run(server, EMBED_MCP_TRANSPORT_HTTP);
embed_mcp_destroy(server);
return 0;
}
Build and Run
# Build
make
# Run Streamable HTTP server
./bin/mcp_server --transport http --port 8080
# Or run STDIO server
./bin/mcp_server --transport stdio
Function Registration
EmbedMCP supports two registration approaches:
Strict Parameter Access (Recommended for robust validation)
In addition to get_* helpers, you can use strict try_get_* accessors to distinguish between missing/invalid input and real zero/empty values.
int64_t user_id;
if (!params->try_get_int(params, "user_id", &user_id)) {
// handle missing or invalid type
}
double* values = NULL;
size_t count = 0;
if (params->try_get_double_array(params, "values", &values, &count)) {
// use values, then free(values)
}
Simple Functions (Recommended)
// Business function
double add_numbers(double a, double b) {
return a + b;
}
// One-line wrapper generation
EMBED_MCP_WRAPPER(add_wrapper, add_numbers, DOUBLE, DOUBLE, a, DOUBLE, b)
// Register
const char* names[] = {"a", "b"};
const char* descs[] = {"First number", "Second number"};
mcp_param_type_t types[] = {MCP_PARAM_DOUBLE, MCP_PARAM_DOUBLE};
embed_mcp_add_tool(server, "add", "Add two numbers",
names, descs, types, 2, MCP_RETURN_DOUBLE, add_wrapper, NULL);
Array Functions (Advanced)
// Business function
double sum_numbers(double* numbers, size_t count) {
double sum = 0.0;
for (size_t i = 0; i < count; i++) {
sum += numbers[i];
}
return sum;
}
// Manual wrapper (handles memory management)
void* sum_wrapper(mcp_param_accessor_t* params, void* user_data) {
size_t count;
double* numbers = params->get_double_array(params, "numbers", &count);
double result_val = sum_numbers(numbers, count);
free(numbers); // Clean up
double* result = malloc(sizeof(double));
*result = result_val;
return result;
}
// Register with array parameter
mcp_param_desc_t params[] = {
MCP_PARAM_ARRAY_DOUBLE_DEF("numbers", "Array of numbers", "A number", 1)
};
embed_mcp_add_tool(server, "sum", "Sum numbers", params, NULL, NULL, 1,
MCP_RETURN_DOUBLE, sum_wrapper, NULL);
Complex Nested Input (Schema-Based)
Use embed_mcp_add_tool_with_schema when your tool needs nested objects, arrays of objects, or strict schema constraints.
cJSON* submit_order_with_schema(const cJSON *args) {
const cJSON *customer = cJSON_GetObjectItem(args, "customer");
const cJSON *name = customer ? cJSON_GetObjectItem(customer, "name") : NULL;
const cJSON *items = cJSON_GetObjectItem(args, "items");
cJSON *result = cJSON_CreateObject();
cJSON_AddStringToObject(result, "status", "accepted");
cJSON_AddStringToObject(result, "customer",
(name && cJSON_IsString(name)) ? cJSON_GetStringValue(name) : "unknown");
cJSON_AddNumberToObject(result, "itemCount", cJSON_IsArray(items) ? cJSON_GetArraySize(items) : 0);
return result;
}
const char *schema_json =
"{\"type\":\"object\",\"properties\":{"
"\"customer\":{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\"}},\"required\":[\"name\"],\"additionalProperties\":false},"
"\"items\":{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"sku\":{\"type\":\"string\"},\"qty\":{\"type\":\"integer\"}},\"required\":[\"sku\",\"qty\"],\"additionalProperties\":false}}"
"},\"required\":[\"customer\",\"items\"],\"additionalProperties\":false}";
cJSON *schema = cJSON_Parse(schema_json);
embed_mcp_add_tool_with_schema(server, "submit_order", "Submit nested order payload", schema, submit_order_with_schema);
cJSON_Delete(schema);
Memory Management
EmbedMCP handles most memory management automatically:
- Parameters: All input parameters are automatically freed after your function returns
- JSON processing: Request/response parsing and cleanup is handled internally
- Arrays: Dynamic arrays are automatically allocated and freed
- Error handling: Memory is properly cleaned up even when errors occur
Your responsibility: String return values must use malloc():
char* get_weather(const char* city) {
char* result = malloc(200); // ✅ EmbedMCP will call free()
sprintf(result, "Weather for %s: Sunny", city);
return result;
}
Server Modes
Streamable HTTP Transport (Example)
./my_server --transport http --port 8080
- Multiple concurrent clients
- Session management with
MCP-Session-Idheaders - Protocol version negotiation via
MCP-Protocol-Versionheaders - Web application backends
- Development and testing
STDIO Transport
For MCP clients like Claude Desktop:
./my_server --transport stdio --quiet
- Claude Desktop integration
- AI assistant tools
- Command-line workflows
- Single client communication
--quietsuppresses business debug logs to keep stdio output cleaner for protocol tooling
🔧 Parameter Definition Macros
Powerful macros for complex parameter definitions
📊 Array Parameters
|
🎯 Simple Parameters
|
Example Server
Validation errors now include clearer field-level details (for example: missing required field, unexpected field, or invalid nested field type).
Smoke regression is available via:
make test-smoke
The included example demonstrates all EmbedMCP features:
# Build and run example
make && ./bin/mcp_server --transport stdio
Available Demo Tools
| Tool | Parameters | Description | Example |
|---|---|---|---|
add |
a: number, b: number |
Add two numbers | add(10, 20) → 30 |
sum_numbers |
numbers: number[] |
Sum array of numbers | sum_numbers([1,2,3]) → 6 |
join_strings |
strings: string[], separator: string |
Join string array | join_strings(["a","b"], ",") → "a,b" |
weather |
city: string |
Get weather info | weather("济南") → Weather report |
calculate_score |
base_points: int, grade: string, multiplier: number |
Calculate score with bonus | calculate_score(80, "A", 1.2) → 120 |
submit_order |
customer: object, items: object[], priority?: int |
Schema-based nested payload example | submit_order({...}) → accepted result |
Testing with MCP Inspector
- Start the server:
./bin/mcp_server --transport http --port 8080 - Open MCP Inspector
- Connect to:
http://localhost:8080/mcp - Test the available tools
Platform Support
EmbedMCP is designed for maximum portability across embedded systems:
Embedded Systems
- RTOS: FreeRTOS, Zephyr, ThreadX, embOS
- MCUs: STM32, ESP32, Nordic nRF series
- SBCs: Raspberry Pi, BeagleBone, Orange Pi
Requirements
- Minimum: C99 compiler, 64KB RAM, 100KB flash
- Recommended: 512KB RAM for complex applications
- Dependencies: None (self-contained)
Use Cases
Industrial IoT
- Sensor data processing: Expose C sensor drivers to AI models
- Equipment monitoring: Real-time analysis of machine data
- Predictive maintenance: AI-driven failure prediction
Embedded AI
- Edge computing: Run AI inference on embedded devices
- Smart devices: Voice assistants, smart cameras, IoT hubs
- Robotics: AI-controlled robotic systems
Troubleshooting
Common Issues
Build errors:
# Missing dependencies
make deps
# Clean build
make clean && make
Runtime errors:
# Enable debug logging
./bin/mcp_server --transport stdio --debug
# Check memory usage
valgrind ./bin/mcp_server --transport stdio
Connection issues:
- Ensure correct transport mode (Streamable HTTP vs STDIO)
- Check firewall settings for Streamable HTTP mode
- Verify MCP client configuration and protocol version headers
Contributing
At this time, we’re not accepting external code contributions (PRs).
Issues are welcome for bug reports and feature requests.
Development Setup
# Clone repository
git clone https://github.com/AaronWander/EmbedMCP.git
cd EmbedMCP
# Build debug version
make debug
# Run tests
make test
License
This project is licensed under the MIT License - see the LICENSE file for details.
👥 Community & Support
Community Resources
Contributing: At this time, we’re not accepting external code contributions (PRs).
Issues are welcome for bug reports and feature requests.
🐛 Report bugs via GitHub Issues
💡 Suggest features in Discussions
💬 Join our Discord for real-time community support
Stay Connected
- 🐦 Twitter: @Aaron_Wander
Installing EmbedMCP
This server has no published package — it is built from source. Open the repository and follow its README.
▸ github.com/AaronWander/EmbedMCPFAQ
Is EmbedMCP MCP free?
Yes, EmbedMCP MCP is free — one-click install via Unyly at no cost.
Does EmbedMCP need an API key?
No, EmbedMCP runs without API keys or environment variables.
Is EmbedMCP hosted or self-hosted?
Self-hosted: the server runs locally on your machine via the install command above.
How do I install EmbedMCP in Claude Desktop, Claude Code or Cursor?
Open EmbedMCP on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
Fetch
Web content fetching and conversion for efficient LLM usage.
AWS KB Retrieval
Retrieval from AWS Knowledge Base using Bedrock Agent Runtime.
by modelcontextprotocolSpring AI MCP Server
Provides auto-configuration for setting up an MCP server in Spring Boot applications.
llm-analysis-assistant
A very streamlined mcp client that supports calling and monitoring stdio/sse/streamableHttp, and can also view request responses through the /logs page. It also
by xuzexin-hzCompare EmbedMCP with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All ai MCPs
