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.
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.
- 🚀 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
-
Download EmbedMCP
git clone https://github.com/AaronWander/EmbedMCP.git cd EmbedMCP
-
Copy to your project
cp -r embed_mcp/ your_project/
#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_STREAMABLE_HTTP);
embed_mcp_destroy(server);
return 0;
}
# Build
make
# Run Streamable HTTP server
./bin/mcp_server --transport streamable-http --port 8080
# Or run STDIO server
./bin/mcp_server --transport stdio
EmbedMCP supports two registration approaches:
// 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);
// 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);
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;
}
./my_server --transport streamable-http --port 8080
- Multiple concurrent clients
- Session management with
Mcp-Session-Id
headers - Protocol version negotiation via
Mcp-Protocol-Version
headers - Web application backends
- Development and testing
For MCP clients like Claude Desktop:
./my_server --transport stdio
- Claude Desktop integration
- AI assistant tools
- Command-line workflows
- Single client communication
Powerful macros for complex parameter definitions
// Double array
MCP_PARAM_ARRAY_DOUBLE_DEF(
"numbers",
"Array of numbers",
"A numeric value",
1 // required
)
// String array
MCP_PARAM_ARRAY_STRING_DEF(
"items",
"List of items",
"An item name",
1 // required
) |
// Double parameter
MCP_PARAM_DOUBLE_DEF(
"temperature",
"Temperature in Celsius",
1 // required
)
// String parameter
MCP_PARAM_STRING_DEF(
"city",
"City name",
0 // optional
) |
The included example demonstrates all EmbedMCP features:
# Build and run example
make && ./bin/mcp_server --transport stdio
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 |
- Start the server:
./bin/mcp_server --transport streamable-http --port 8080
- Open MCP Inspector
- Connect to:
http://localhost:8080/mcp
- Test the available tools
EmbedMCP is designed for maximum portability across embedded systems:
- RTOS: FreeRTOS, Zephyr, ThreadX, embOS
- MCUs: STM32, ESP32, Nordic nRF series
- SBCs: Raspberry Pi, BeagleBone, Orange Pi
- Minimum: C99 compiler, 64KB RAM, 100KB flash
- Recommended: 512KB RAM for complex applications
- Dependencies: None (self-contained)
- Sensor data processing: Expose C sensor drivers to AI models
- Equipment monitoring: Real-time analysis of machine data
- Predictive maintenance: AI-driven failure prediction
- Edge computing: Run AI inference on embedded devices
- Smart devices: Voice assistants, smart cameras, IoT hubs
- Robotics: AI-controlled robotic systems
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
We welcome contributions! Please see our contribution guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Test on multiple platforms
- Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
# Clone repository
git clone https://github.com/AaronWander/EmbedMCP.git
cd EmbedMCP
# Build debug version
make debug
# Run tests
make test
This project is licensed under the MIT License - see the LICENSE file for details.
- Issues: GitHub Issues
- Discussions: GitHub Discussions