Raspberry Pi 5 stack for running clawdbot, Arduino MCP, and Edge Impulse MCP together.
| Mode | Best for | EI MCP source | Start command |
|---|---|---|---|
mcp-image (Recommended) |
New users, fastest setup | docker.io/eoinedge/ei-agentic-claude-mcp:test image |
docker compose --profile mcp-image up -d --build |
mcp-local |
Developing ei-agentic-claude locally |
Mounted repo path (EI_AGENTIC_CLAUDE_PATH) |
docker compose --profile mcp-local up -d --build |
mcp |
No prebuilt MCP image | npm install inside bridge image | docker compose --profile mcp up -d --build |
Use only one EI bridge mode at a time (mcp, mcp-local, or mcp-image).
Arduino MCP uses prebuilt image docker.io/eoinedge/arduino-mcp:latest by default (ARDUINO_MCP_IMAGE in .env).
git clone https://github.com/eoinjordan/pi-openclaw-mcp-stack.git
cd pi-openclaw-mcp-stack
bash scripts/pi5-quickstart.sh mcp-imageThen set keys in .env:
TELEGRAM_TOKENEI_API_KEY- optional:
OPENAI_API_KEY(remote provider) orOPENAI_BASE_URL(local Ollama)
Re-run:
bash scripts/pi5-quickstart.sh mcp-imageThis stack is designed to work with the official Edge Impulse MCP repo:
https://github.com/edgeimpulse/ei-agentic-claude
If you already keep keys in ei-agentic-claude/.env.test, point the stack to it:
cd ~/pi-openclaw-mcp-stack
echo "EI_AGENTIC_ENV_TEST_PATH=$HOME/ei-agentic-claude/.env.test" >> .env
bash scripts/pi5-quickstart.sh mcp-imageThe quickstart script imports these keys into stack .env when present:
ANTHROPIC_API_KEYEI_API_KEY,EI_ORG_API_KEY,EI_ORG_ID,EI_PROJECT_ID,EI_RUN_TRAININGPROJECT_*_ID,PROJECT_*_URLDSP_BLOCK_IDS,LEARN_BLOCK_IDS,EI_IMPULSE_ID
Use this when you want to cleanly rebuild .env and re-apply settings from ei-agentic-claude/.env.test.
cd ~/pi-openclaw-mcp-stack
docker compose --profile mcp-image down --remove-orphans
cp .env .env.backup.$(date +%Y%m%d-%H%M%S)
cp .env.example .env
echo "EI_AGENTIC_ENV_TEST_PATH=$HOME/ei-agentic-claude/.env.test" >> .env
nano .envSet/confirm at least:
TELEGRAM_TOKENEI_RUN_TRAINING=1
Rebuild and start:
bash scripts/pi5-quickstart.sh mcp-image
docker compose --profile mcp-image up -d --force-recreateOptional hard reset (re-download Arduino core/tools on next run):
rm -rf ~/pi-openclaw-mcp-stack/workspace/.arduino15
mkdir -p ~/pi-openclaw-mcp-stack/workspace/.arduino15Minimum values you should set in ei-agentic-claude/.env.test for project execution:
EI_API_KEYEI_PROJECT_IDEI_RUN_TRAINING=1(enables write/post flows)
Verify:
curl -s http://127.0.0.1:3000/health
curl -s http://127.0.0.1:3000/health/upstreamsIf you are testing on Docker Desktop (Windows/macOS), network_mode: host does not expose 127.0.0.1:3000 on the host the same way as Pi/Linux.
Use in-container checks instead:
docker exec openclaw-gateway node -e "fetch('http://127.0.0.1:3000/health').then(async r=>console.log(r.status, await r.text()))"
docker exec openclaw-gateway node -e "fetch('http://127.0.0.1:3000/health/upstreams').then(async r=>console.log(r.status, await r.text()))"Run this after the stack is up:
cd ~/pi-openclaw-mcp-stack
docker compose --profile mcp-image ps
curl -s http://127.0.0.1:3000/health
curl -s http://127.0.0.1:3000/health/upstreams
curl -s -X POST http://127.0.0.1:3000/arduino/validate -H "Content-Type: application/json" -d '{"projectRoot":"/workspace/Blink"}'
curl -s -X POST http://127.0.0.1:3000/arduino/build -H "Content-Type: application/json" -d '{"projectRoot":"/workspace/Blink"}'Optional EI tool-chain checks:
# Account-level listing (JWT/HMAC mode)
curl -s -X POST http://127.0.0.1:3000/ei/run -H "Content-Type: application/json" -d '{"name":"get_current_user_projects","params":{}}'
# Project-level read (API key mode)
curl -s -X POST http://127.0.0.1:3000/ei/run -H "Content-Type: application/json" -d '{"name":"project_information","apiKey":"'"$EI_API_KEY"'","params":{"projectId":'"$EI_PROJECT_ID"'}}'Notes:
- First
validate/buildcan take several minutes on fresh installs (core/toolchain download + first compile). - Default gateway/bot timeouts are set to 20 minutes (
ARDUINO_VALIDATE_TIMEOUT_MS,ARDUINO_BUILD_TIMEOUT_MS). - Arduino MCP compile timeout is also set to 20 minutes (
ARDUINO_COMPILE_TIMEOUT_MS). - If
health/upstreamsreturnsdegraded, tail logs:docker compose --profile mcp-image logs --tail 120 arduino-mcp ei-mcp-bridge-image.
For a new-user, step-by-step flow from Edge Impulse project config to Nano 33 BLE flash on Pi 5, use:
docs/pi5-ei-to-nano33ble.md
Flash helper script:
scripts/flash-nano33ble.sh
If you use inference led|servo or flash inference ..., set the EI library header in .env:
HEADER="$(unzip -Z1 outputs/ei_arduino_deployment.zip | grep -m1 -E '_inferencing\.h$' | awk -F/ '{print $NF}')"
echo "Detected header: $HEADER"
sed -i "s|^EI_LIBRARY_HEADER_DEFAULT=.*|EI_LIBRARY_HEADER_DEFAULT=$HEADER|" .env
docker compose --profile mcp-image up -d --force-recreate gateway clawdbotIf EI_LIBRARY_HEADER_DEFAULT is still placeholder text, gateway will return HTTP 400 for /arduino/inference.
Keep your deployment ZIP at outputs/ei_arduino_deployment.zip (or set EI_LIBRARY_ZIP_PATH), because /arduino/flash now attempts one automatic arduino-cli lib install --zip-path ... retry when compile fails on a missing *_inferencing.h.
Gateway and arduino-mcp share ./workspace/ArduinoLibraries so auto-installed libraries are available to /arduino/validate, /arduino/build, and /arduino/flash.
Run these from repo root (~/pi-openclaw-mcp-stack). Use one profile at a time.
Start selected mode:
docker compose --profile mcp-image up -d --build
# or
# docker compose --profile mcp-local up -d --build
# docker compose --profile mcp up -d --buildRestart everything in active mode:
docker compose --profile mcp-image restartRestart individual services:
docker compose restart openclaw-gateway clawdbot
docker compose restart arduino-mcp
docker compose restart ei-mcp-bridge-imageReload after .env changes:
docker compose --profile mcp-image up -d --force-recreateStop or remove stack:
docker compose --profile mcp-image stop
docker compose --profile mcp-image downIf first boot prints curl: (7) Failed to connect to 127.0.0.1 port 3000:
sudo systemctl enable --now docker
systemctl is-active docker
docker compose --profile mcp-image up -d --build
docker compose --profile mcp-image ps
docker compose --profile mcp-image logs --tail 120 gateway
curl -s http://127.0.0.1:3000/health
curl -s http://127.0.0.1:3000/health/upstreamsNotes:
- On first run, startup can take longer while containers install dependencies.
- In
mcp-localormcpmode, replacemcp-imagewith your active profile. - If
ei-mcp-bridge-imageshowsRestarting (127)with repeatedNo such file or directory, set:EI_MCP_BASE_IMAGE=docker.io/eoinedge/ei-agentic-claude-mcp:test- then run
docker compose --profile mcp-image up -d --build --force-recreate
- If build fails with
docker.io/eoinedge/ei-agentic-claude-mcp:latest: not found, use:EI_MCP_BASE_IMAGE=docker.io/eoinedge/ei-agentic-claude-mcp:test
Some Raspberry Pi OS images do not include docker-buildx-plugin or docker-compose-plugin packages by name.
The quickstart script handles package fallbacks and prints a clear error path if Compose is still unavailable.
Telegram -> clawdbot -> openclaw-gateway
|- /arduino/validate|build -> arduino-mcp
|- /arduino/example|inference|flash -> gateway local arduino-cli
|- /ei/run -> ei-mcp-bridge* -> ei-agentic-claude MCP (stdio) -> Edge Impulse API
ei-mcp-bridge* is one of:
ei-mcp-bridge(mcp)ei-mcp-bridge-local(mcp-local)ei-mcp-bridge-image(mcp-image)
- Target: Raspberry Pi 5 (
linux/arm64, Raspberry Pi OS 64-bit Bookworm). - Windows/macOS Docker Desktop is useful for flow checks, but images there are typically
amd64. - Gateway now needs hardware access for flash workflow (
/dev+ workspace mounts). Restrict bot access to trusted users only.
- LLM docs index for this repo:
llms.txt - Pi setup and package fallback details:
docs/pi5-setup.md - Mode-specific setup (
mcp,mcp-local,mcp-image):docs/modes.md - Observability and flow tracing:
docs/observability.md - Architecture deep dive:
docs/architecture.md - EI to Nano 33 BLE deployment flow:
docs/ei-arduino-deploy.md - Full first-project to flash flow:
docs/pi5-ei-to-nano33ble.md - UNO Q MWC custom sensor demo setup:
docs/unoq-mwc-demo.md - Local Ollama setup for Pi 5:
docs/ollama.md - Jetson + Rubik Pi hardware setup scripts:
docs/hardware-acceleration-host-setup.md - Kubernetes distributed deployment + hardware acceleration guide:
docs/kubernetes-distributed-acceleration.md - Edge Impulse docs index (for deployment and project settings):
https://docs.edgeimpulse.com/llms.txt
helphealthexample blinkexample servo [360] [on d12]inference led [label] [threshold]inference servo [label] [threshold] [360] [on d12]validate arduinobuild arduinoflash arduino [/dev/ttyACM0]flash example blink|servo [360] [on d12] [/dev/ttyACM0]flash inference led|servo [label] [threshold] [360] [on d12] [/dev/ttyACM0]ei projectsei project [projectId]ei build arduino [projectId] [impulseId]ei job <jobId> [projectId]models
If OPENAI_API_KEY is set, non-command messages are forwarded to OpenAI chat.
If using Ollama, set OPENAI_MODEL to an installed model (for example qwen2.5:3b-instruct).
- In Telegram, open
@BotFather. - Create bot:
/newbot
- Set a bot name and username (username must end with
bot). - Copy the token from BotFather (
123456789:AA...). - On Pi, set token in
.env:
cd ~/pi-openclaw-mcp-stack
nano .envTELEGRAM_TOKEN=123456789:AA...- Optional command menu in Telegram:
/setcommands
Paste:
help - Show commands
health - Check stack health
example blink - Generate Blink sketch in default project
example servo - Generate Servo sketch (supports "360 on d12")
inference led - Generate EI inference sketch for LED output
inference servo - Generate EI inference sketch for servo output
validate arduino - Validate default sketch
build arduino - Build default sketch
flash arduino - Compile and upload default sketch
flash example - Generate and flash example sketch
flash inference - Generate and flash inference sketch
ei projects - List Edge Impulse projects (JWT lane)
ei project - Show Edge Impulse project information
ei build arduino - Start Edge Impulse Arduino deployment build
ei job - Get Edge Impulse deployment job status
- Restart and test:
docker compose restart clawdbot
docker logs --tail 100 clawdbotThen in Telegram send:
/starthelphealth
Install and run Ollama:
curl -fsSL https://ollama.com/install.sh | sh
ollama serve
ollama pull qwen2.5:3b-instructSet .env for local chat via OpenAI-compatible endpoint:
OPENAI_BASE_URL=http://127.0.0.1:11434/v1
OPENAI_API_KEY=ollama
OPENAI_MODEL=qwen2.5:3b-instructThen restart:
docker compose restart clawdbotCheck installed models:
ollama listBy default the agentic coding CLIs (OpenCode, Claude Code) connect to cloud-hosted LLMs. If you need fully offline operation — no API keys, no internet — you can serve a local LLM via llama.cpp and point the CLI at it instead.
A Q4_K_M GGUF of the fine-tuned Qwen2.5-Coder-0.5B-Instruct adapter (trained on 1,794 Edge Impulse documentation files) is published at eoinedge/edgeai-docs-qwen2.5-coder-0.5b-lora.
Fast path — download the pre-built GGUF (~398 MB):
wget -P ~ https://huggingface.co/eoinedge/edgeai-docs-qwen2.5-coder-0.5b-lora/resolve/main/qwen-edgeai-q4_k_m.ggufBuild from source (optional — only if you need a different quantisation)
Run inside the Ubuntu VM (the stack's sandbox container already has Python 3.12 and pip available):
pip install transformers peft torch sentencepiece
sudo apt install -y cmake build-essential
git clone https://github.com/ggerganov/llama.cpp ~/llama.cpp
cd ~/llama.cpp && cmake -B build && cmake --build build --config Release -j$(nproc)
# Clone the repo over HTTPS (no SSH key needed)
# Skip if already cloned — cd in and git pull instead
git clone https://github.com/edgeimpulse/ei-agentic-stack.git ~/ei-agentic-stack
cd ~/ei-agentic-stack
python3 scripts/merge_qwen_to_gguf.py \
--llama-cpp-dir ~/llama.cpp \
--output-dir ~/qwen-edgeai-merged \
--gguf-out ~/qwen-edgeai-q4.ggufThe script merges the LoRA adapter into the base model, converts to F16 GGUF, then quantizes to Q4_K_M via llama-quantize.
# Build (skip if already done)
sudo apt install -y cmake build-essential
git clone https://github.com/ggerganov/llama.cpp ~/llama.cpp
cd ~/llama.cpp && cmake -B build && cmake --build build --config Release -j$(nproc)
# Start
~/llama.cpp/build/bin/llama-server \
--model ~/qwen-edgeai-q4_k_m.gguf \
--host 127.0.0.1 --port 8081 \
--ctx-size 4096 \
--n-predict 512This exposes an OpenAI-compatible API at http://localhost:8081/v1.
OpenCode (opencode/opencode.json):
{
"model": "local/qwen-edgeai",
"provider": {
"openai": {
"baseURL": "http://localhost:8081/v1",
"apiKey": "local"
}
}
}The MCP server itself is unaffected — it still connects to the Edge Impulse API through the proxy. Only the LLM that drives tool-calling decisions is replaced by the local model.
Note
The 0.5B model handles straightforward Edge Impulse API and docs questions well. For multi-step agentic tasks requiring complex reasoning, consider a larger quantized model (3B+) at the cost of slower inference on CPU.
See the full setup guide (Raspberry Pi and Rubik Pi 3 walkthrough, RAG extension, Arduino companion adapter) at: eoinjordan/pi-openclaw-mcp-stack
- Add full examples for Cursor and Copilot configuration once the upstream docs are published.
- Provide automated build/test scripts for the Docker images.
- Include architecture diagrams and sample
curlsmoke tests for the/mcpendpoint.
In Telegram, send models to verify what clawdbot sees.
If you see no configuration file provided: not found, run compose commands from the repo root:
cd ~/pi-openclaw-mcp-stackThis repo includes Codex skills for Pi users under skills/.
$pi-openclaw-pi5-quickstartfor first-time setup and mode selection.$pi-openclaw-flow-auditfor routing and health troubleshooting.$pi-openclaw-chat-providersfor Telegram and Ollama/OpenAI provider setup.$pi-openclaw-ei-arduino-deployfor Edge Impulse to Arduino deployment flow with Arduino MCP build handoff.$pi-openclaw-arduino-flashfor serial-port-aware firmware upload to hardware after build/deploy handoff.
Skill discovery rules are in AGENTS.md.
New project is a custom docs llm that will integrate and be used locally:

For deeper background on the concepts and structures used in this repo:
- LLM docs index format (
llms.txt):https://llmstxt.org/ - This repo LLM index file:
llms.txt - Edge Impulse LLM docs index:
https://docs.edgeimpulse.com/llms.txt - Edge Impulse MCP/CLI repo:
https://github.com/edgeimpulse/ei-agentic-claude - Model Context Protocol (MCP):
https://modelcontextprotocol.io/introduction - Docker Compose profiles:
https://docs.docker.com/compose/profiles/ - Docker host networking:
https://docs.docker.com/engine/network/drivers/host/ - Docker Buildx:
https://docs.docker.com/build/buildx/ - Kubernetes Deployments:
https://kubernetes.io/docs/concepts/workloads/controllers/deployment/ - Kubernetes Services:
https://kubernetes.io/docs/concepts/services-networking/service/ - Kubernetes ConfigMaps:
https://kubernetes.io/docs/concepts/configuration/configmap/ - Kubernetes Secrets:
https://kubernetes.io/docs/concepts/configuration/secret/ - Kubernetes Persistent Volumes:
https://kubernetes.io/docs/concepts/storage/persistent-volumes/ - Kubernetes HPA:
https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/ - NVIDIA Container Toolkit:
https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html - NVIDIA Kubernetes device plugin:
https://github.com/NVIDIA/k8s-device-plugin - AMD ROCm docs:
https://rocm.docs.amd.com/ - Qualcomm docs portal (platform-specific runtime/plugin docs):
https://docs.qualcomm.com/