ipnet-mesh/meshcore-mcp
If you are the rightful owner of meshcore-mcp and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
MeshCore MCP Server is a Model Context Protocol server that facilitates interaction with MeshCore companion radio nodes via HTTP, enabling AI assistants and web-based tools to control and communicate with mesh network devices.
MeshCore MCP Server
[!CAUTION]
📦 This Project is Archived
This repository is no longer actively maintained. All future development has moved to the new unified repository:
👉 MeshCore Hub
Please use MeshCore Hub for all new projects and contributions. This repository remains available for reference only.
An MCP (Model Context Protocol) server that provides tools for interacting with MeshCore companion radio nodes via HTTP. This enables AI assistants and web-based tools to control and communicate with mesh network devices.
Example Usage
Here's a real conversation with Claude using the MeshCore MCP server:
👤 User: Are you connected to MeshCore?
🤖 Claude: Yes, I am connected to MeshCore. I can see the device information showing a Heltec V3 device running firmware version 8 (v1.10.0-9405e8b) built on November 13, 2025. The device supports up to 350 contacts and 40 channels.
👤 User: Do I have any messages?
🤖 Claude: No, you don't have any messages. Your message buffer is currently empty.
👤 User: Someone has sent a message. Can you check again?
🤖 Claude: You're right! You do have a message now. There's 1 message in your buffer:
Message Details:
- From: Unknown (Public Key:
2369759a4926) - Time: November 22, 2025 at 13:46:24
- Message: "Hello GitHub!"
It appears to be from an unknown contact, but you can see their public key identifier.
👤 User: Reply to that message saying "Hello World!"
🤖 Claude: I've successfully sent your reply! The message "Hello World!" has been sent to contact 2369759a4926. The system confirms the message was sent successfully.
Features
Core Tools:
meshcore_connect- Connect to devices via Serial, BLE, or TCPmeshcore_disconnect- Cleanly disconnect from devicesmeshcore_send_message- Send messages to contacts or channelsmeshcore_send_advert- Send advertisements to announce device presencemeshcore_get_contacts- List all contactsmeshcore_get_device_info- Query device informationmeshcore_get_battery- Check battery status
Clock Management Tools:
meshcore_get_time- Get current device timemeshcore_set_time- Set device time to specific Unix timestampmeshcore_sync_clock- Sync device clock to system time
Message Listening Tools:
meshcore_start_message_listening- Start receiving incoming messagesmeshcore_stop_message_listening- Stop receiving messagesmeshcore_get_messages- Retrieve received messages from buffermeshcore_clear_messages- Clear message buffer
Transport:
- HTTP with Streamable transport (MCP protocol 2025-03-26)
- Web-accessible for browser clients and agents
- Configurable host/port binding
Quick Start with Docker (Recommended)
The easiest way to run MeshCore MCP Server is using our official Docker image:
# Basic usage (port 8000)
docker run -d \
--name meshcore-mcp \
-p 8000:8000 \
ghcr.io/ipnet-mesh/meshcore-mcp:main
# With serial device access (Linux)
docker run -d \
--name meshcore-mcp \
-p 8000:8000 \
--device=/dev/ttyUSB0 \
ghcr.io/ipnet-mesh/meshcore-mcp:main \
--serial-port /dev/ttyUSB0 --baud-rate 115200
# With auto-connect and clock sync (recommended)
docker run -d \
--name meshcore-mcp \
-p 8000:8000 \
--device=/dev/ttyUSB0 \
ghcr.io/ipnet-mesh/meshcore-mcp:main \
--serial-port /dev/ttyUSB0 --sync-clock-on-startup
# Custom port
docker run -d \
--name meshcore-mcp \
-p 3000:8000 \
ghcr.io/ipnet-mesh/meshcore-mcp:main
Available tags:
main- Latest development buildlatest- Latest stable releasevX.Y.Z- Specific version tags
Docker Compose example:
version: '3.8'
services:
meshcore-mcp:
image: ghcr.io/ipnet-mesh/meshcore-mcp:main
ports:
- "8000:8000"
devices:
- /dev/ttyUSB0:/dev/ttyUSB0
command: ["--serial-port", "/dev/ttyUSB0", "--sync-clock-on-startup"]
restart: unless-stopped
Installation from Source
Prerequisites
- Python 3.10 or higher
- A MeshCore-compatible device (connected via Serial/BLE/TCP)
Install from source
# Clone the repository
git clone https://github.com/ipnet-mesh/meshcore-mcp.git
cd meshcore-mcp
# Create and activate virtual environment
python3 -m venv .venv
source .venv/bin/activate # Linux/macOS
# OR
.venv\Scripts\activate # Windows
# Install dependencies
pip install -e .
Usage
Starting the HTTP Server
With Docker (recommended): See Quick Start with Docker section above.
With Python (local development):
Default (localhost:8000):
python -m meshcore_mcp.server
Custom host/port:
python -m meshcore_mcp.server --host 0.0.0.0 --port 3000
With auto-connect to serial device (recommended):
python -m meshcore_mcp.server --serial-port /dev/ttyUSB0 --baud-rate 115200
This will connect to the device on startup and fail-fast if the connection fails. Debug mode can be enabled with --debug.
With auto-connect and clock sync (recommended for accurate timestamps):
python -m meshcore_mcp.server --serial-port /dev/ttyUSB0 --sync-clock-on-startup
This will connect to the device on startup and automatically synchronize the device clock to the system time, ensuring accurate message timestamps.
As an installed command:
meshcore-mcp --serial-port /dev/ttyUSB0 --debug
The server will print:
Starting MeshCore MCP Server on 0.0.0.0:8000
Server URL: http://0.0.0.0:8000
[STARTUP] Auto-connect enabled for /dev/ttyUSB0
[STARTUP] Server starting, connecting to device...
[STARTUP] Attempting to connect to /dev/ttyUSB0 at 115200 baud...
[STARTUP] Successfully connected to MeshCore device on /dev/ttyUSB0
[STARTUP] Syncing device clock to system time...
[STARTUP] Clock synced successfully to 2025-11-22 14:30:00
[STARTUP] Device connected. Starting message listening...
[STARTUP] Subscribed to contact messages
[STARTUP] Subscribed to channel messages
[STARTUP] Subscribed to advertisements
[STARTUP] Auto message fetching started
[STARTUP] Message listening active with 3 subscriptions
[STARTUP] Server ready.
(Clock sync messages only appear when using --sync-clock-on-startup)
The server automatically subscribes to incoming messages and advertisements, so it's ready to receive and buffer messages immediately.
With Claude Desktop
Add this configuration to your Claude Desktop config file:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
Linux: ~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"meshcore": {
"url": "http://localhost:8000"
}
}
}
For remote servers:
{
"mcpServers": {
"meshcore": {
"url": "http://your-server-ip:8000"
}
}
}
With OpenWebUI
OpenWebUI uses MCPO (MCP-to-OpenAPI proxy) to connect to MCP servers. Configure MCPO with:
1. Create a config.json file:
{
"mcpServers": {
"meshcore": {
"type": "streamable-http",
"url": "http://localhost:8000/mcp"
}
}
}
See examples/mcpo_config.json for a complete example.
For remote servers:
{
"mcpServers": {
"meshcore": {
"type": "streamable-http",
"url": "http://your-server-ip:8000/mcp"
}
}
}
2. Run MCPO with Docker:
# Note: MCPO runs on port 8080 to avoid conflict with the MCP server on 8000
docker run -d \
--name mcpo \
-p 8080:8000 \
-v $(pwd)/config.json:/app/config/config.json \
ghcr.io/open-webui/mcpo:main
Important: The MCP server runs on port 8000, while MCPO is exposed on port 8080 to avoid conflicts. Adjust ports as needed for your environment.
3. Configure OpenWebUI:
In OpenWebUI settings, add the MCPO endpoint as an OpenAPI server. The tools will then be available to your AI models.
See also: OpenWebUI MCP Documentation and MCPO GitHub
With Other MCP Clients
The HTTP server is compatible with any MCP client that supports the Streamable HTTP transport (MCP protocol 2025-03-26).
Server endpoint: http://localhost:8000/mcp
Note: The MCP endpoint requires proper MCP protocol handshaking with session management. Use an MCP-compatible client library (like the official MCP SDK) or a proxy like MCPO for integration with non-MCP tools.
Tool Examples
Connecting to a Device
Serial Connection:
{
"type": "serial",
"port": "/dev/ttyUSB0",
"baud_rate": 115200,
"debug": true
}
BLE Connection:
{
"type": "ble",
"address": "12:34:56:78:90:AB",
"pin": "123456"
}
TCP Connection:
{
"type": "tcp",
"host": "192.168.1.100",
"port": "4000",
"auto_reconnect": true
}
Sending a Message
{
"destination": "Alice",
"text": "Hello from MCP!"
}
Sending an Advertisement
Zero-hop advertisement (immediate neighbors only):
{
"flood": false
}
Flooded advertisement (multi-hop via repeaters):
{
"flood": true
}
Advertisements announce your device's presence to the mesh network. Use flood: false for zero-hop broadcasts to immediate neighbors, or flood: true for multi-hop broadcasts that are repeated by all network repeaters.
Getting Contacts
Call meshcore_get_contacts with no parameters to retrieve your contact list.
Querying Device Info
Call meshcore_get_device_info to get device name, version, and configuration details.
Checking Battery
Call meshcore_get_battery to get current battery level and status.
Managing Device Clock
Get device time:
{}
Call meshcore_get_time to retrieve the current time from the device.
Sync clock to system time:
{}
Call meshcore_sync_clock to synchronize the device clock with the current system time. This is the easiest way to ensure accurate timestamps.
Set specific time:
{
"timestamp": 1732276800
}
Call meshcore_set_time to set the device clock to a specific Unix timestamp (seconds since epoch).
Listening for Messages
Start listening:
{}
Call meshcore_start_message_listening to start receiving messages. Messages are stored in a buffer (up to 1000 messages).
Get received messages:
{
"limit": 10,
"message_type": "contact"
}
limit: Optional, number of most recent messages to retrievemessage_type: Optional, filter by "contact" or "channel"clear_after_read: Optional, set totrueto clear messages after reading
Stop listening:
{}
Call meshcore_stop_message_listening to stop receiving new messages (buffer is retained).
Clear message buffer:
{}
Call meshcore_clear_messages to empty the message buffer.
Example Conversation with Claude
You: Connect to my MeshCore device on /dev/ttyUSB0
Claude: I'll connect to your MeshCore device.
[Uses meshcore_connect tool]
Successfully connected to MeshCore device via serial
You: What's my battery level?
Claude: Let me check your battery status.
[Uses meshcore_get_battery tool]
Battery Level: 85%
You: Sync the device clock
Claude: I'll synchronize the device clock with the current system time.
[Uses meshcore_sync_clock tool]
Device clock synchronized successfully!
System Time: 2025-11-22 14:30:00
Unix Timestamp: 1732285800
You: Send a message to Bob saying "Meeting at 3pm"
Claude: I'll send that message to Bob.
[Uses meshcore_send_message tool]
Message sent to Bob: "Meeting at 3pm"
Result: MSG_SENT
You: Start listening for messages
Claude: I'll start listening for incoming messages.
[Uses meshcore_start_message_listening tool]
Started listening for messages. Messages will be buffered and can be retrieved with meshcore_get_messages.
You: Check if I have any messages
Claude: Let me check your messages.
[Uses meshcore_get_messages tool]
Messages (2 total):
============================================================
[1] CONTACT MESSAGE
Time: 2025-11-21T10:30:15
From: Alice
Public Key: a1b2c3
Message: Got it, see you at 3!
------------------------------------------------------------
[2] CHANNEL MESSAGE
Time: 2025-11-21T10:32:00
From: Bob
Public Key: d4e5f6
Channel: 0
Message: Weather looks good today
------------------------------------------------------------
The "Public Key" field is the sender's address and should be used as the destination when replying with meshcore_send_message.
Architecture
The server uses FastMCP with Streamable HTTP transport for web accessibility. Connection state is managed globally, and all tools validate connectivity before executing commands.
Key Components:
- HTTP Server: FastMCP with streamable-http transport (MCP 2025-03-26)
- Server State: Global
ServerStateclass maintains connection instance and message buffer - Message Buffer: Stores up to 1000 received messages with automatic overflow handling
- Event Subscriptions: Real-time message handling via meshcore event system
- Tool Decorators: Each tool uses
@mcp.tool()for automatic registration - Error Handling: All commands check for EventType.ERROR responses
- Connection Types: Supports Serial, BLE, and TCP with appropriate validation
Why HTTP?
- Web Accessible: Compatible with browser-based clients and agents
- Stateless Options: Can be scaled horizontally if needed
- Remote Access: Connect from anywhere on the network
- Standard Protocol: Uses MCP Streamable HTTP (latest standard)
Development
Building the Docker Image
# Build locally
docker build -t meshcore-mcp:local .
# Run your local build
docker run -p 8000:8000 meshcore-mcp:local
# With device access
docker run -p 8000:8000 --device=/dev/ttyUSB0 meshcore-mcp:local \
--serial-port /dev/ttyUSB0
Project Structure
meshcore-mcp/
├── src/
│ └── meshcore_mcp/
│ ├── __init__.py
│ └── server.py # FastMCP HTTP server
├── examples/
│ └── claude_desktop_config.json
├── Dockerfile # Docker image definition
├── pyproject.toml
├── README.md
└── LICENSE
Running Tests
# Activate virtual environment first
source .venv/bin/activate
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
Testing the Server
With Docker:
docker run -p 8000:8000 ghcr.io/ipnet-mesh/meshcore-mcp:main
With Python (local development):
# Activate virtual environment first
source .venv/bin/activate
# Start the server
python -m meshcore_mcp.server --port 8000
Testing with MCP Clients:
The server uses MCP Streamable HTTP protocol and requires proper MCP client libraries for testing. Direct curl testing is not recommended due to session management requirements.
For testing, use:
- Claude Desktop with the configuration shown above
- MCPO to expose as OpenAPI (see OpenWebUI section)
- MCP SDK client libraries in your preferred language
Quick verification that server is running:
# This should return an error about missing session ID (which confirms the MCP endpoint is active)
curl -X GET http://localhost:8000/mcp -H "Accept: text/event-stream"
Troubleshooting
Connection Issues:
- Verify device is powered on and accessible
- Check port/address permissions (Serial: user in
dialoutgroup) - Enable
debug: truein connect parameters for verbose logging
HTTP Server Issues:
- Check if port is already in use:
lsof -i :8000 - Try a different port:
--port 8080 - For remote access, ensure firewall allows the port
Tool Call Failures:
- Ensure you're connected before calling other tools
- Check that contact names/keys are correct
- Verify device firmware is compatible with meshcore_py 2.2.1+
BLE Pairing:
- Use the
pinparameter if your device requires pairing - Ensure Bluetooth is enabled on your system
- Check that BLE address format is correct (XX:XX:XX:XX:XX:XX)
OpenWebUI/MCPO Issues:
- Ensure the MCP server is running and accessible at the configured URL
- Verify MCPO can reach the MCP server (check Docker network settings)
- Confirm the URL includes
/mcpendpoint:http://localhost:8000/mcp - The server accepts both
/mcpand/mcp/(with or without trailing slash) without redirecting - Check MCPO logs:
docker logs mcpo - For remote servers, ensure firewall rules allow connections
- Verify the
typeis set to"streamable-http"in MCPO config - If using older versions of MCPO (< 0.0.18), ensure it's updated to avoid trailing slash issues
Command-Line Options
usage: server.py [-h] [--host HOST] [--port PORT] [--serial-port SERIAL_PORT]
[--baud-rate BAUD_RATE] [--debug]
MeshCore MCP Server - HTTP/Streamable transport
options:
-h, --help show this help message and exit
--host HOST Host to bind to (default: 0.0.0.0)
--port PORT Port to bind to (default: 8000)
--serial-port SERIAL_PORT
Serial port to auto-connect on startup (e.g.,
/dev/ttyUSB0). If specified, server will fail-fast if
connection fails.
--baud-rate BAUD_RATE
Baud rate for serial connection (default: 115200)
--debug Enable debug mode for MeshCore connection
Dependencies
- meshcore (>=2.2.1) - Python library for MeshCore devices
- mcp (>=1.0.0) - Model Context Protocol SDK with FastMCP
Security Considerations
Important: The HTTP server does not include authentication by default. For production use:
- Deploy behind a reverse proxy with authentication (nginx, Apache)
- Use HTTPS/TLS for encrypted connections
- Restrict network access with firewall rules
- Consider using SSH tunneling for remote access
- Do not expose directly to the internet without proper security
License
GPL-3.0-or-later - see LICENSE file for details
Contributing
Contributions welcome! Please feel free to submit issues or pull requests.