EmbPilot
Embedded device debugging via the Pilot (MCP) protocol.
EmbPilot is an MCP (Model Context Protocol) server that lets LLM agents connect to, control, and debug physical embedded devices over Serial, Telnet, or SSH.
Features
- Connect to devices via Serial UART, Telnet, or SSH
- Send commands and capture output with regular-expression interception (Expect)
- Browse recent live logs through MCP resources
- Persist sessions in SQLite (WAL mode) for RAG-backed historical search
- Local vector search (fastembed + LanceDB) over Datasheets, Error Code manuals, and KB articles
- Analyse crash logs and run hardware sanity checks with guided prompts
Quick Start
pip install embpilot
embpilot --help
Install local RAG support only when needed:
pip install "embpilot[rag]"
EmbPilot is a stdio MCP server, so starting embpilot directly waits for an
MCP client rather than opening an interactive terminal.
Command Line Interface
embpilot starts the stdio MCP server by default, and also exposes every MCP
tool through a thin CLI that shares the exact same dispatch layer:
embpilot --help # server by default; subcommands for tools
embpilot tools # list available tools
embpilot tool connect_serial --json '{"port":"COM3","baudrate":115200}'
embpilot tool send_command --json '{"command":"help","line_ending":"crlf"}'
embpilot tool list_sessions
embpilot shell # interactive REPL with a persistent session
embpilot batch # scripted JSONL mode: one request per stdin line
embpilot serve # persistent daemon sharing one session across calls
embpilot serve --daemon # detach into the background (writes daemon.pid)
embpilot --socket daemon.json tool list_sessions # talk to a running daemon
Agent Harness Installation
Wire EmbPilot into the agents you use — MCP config where the harness supports it, plus a marker-fenced instructions block (and the pi skill) where it does not. Modeled on CodeGraph's installer; the block lists both the MCP tools and their CLI equivalents, so an agent whose MCP server fails to start falls back to the CLI automatically:
embpilot install # interactive: pick targets/scope, confirm files
embpilot install --target pi # pi: AGENTS.md instructions + user skill
embpilot install --target claude # Claude Code: .mcp.json + CLAUDE.md
embpilot install --target dsh # DeepSeek Harness: MCP patch layer + instructions + skill
embpilot install --target agents # project AGENTS.md (Cursor/Codex/Gemini/...)
embpilot install --target all --location global --yes # non-interactive, no prompts
embpilot install --check # report state, write nothing (exit 0/1)
embpilot install --print-config claude # show the manual snippet, write nothing
embpilot uninstall --target pi # remove only what install wrote
With no --target, install/uninstall run interactively: harnesses are
detected and pre-checked, you pick targets and scope, and nothing is written
until you confirm the exact file list. --yes skips every prompt for
scripting.
Targets: claude (MCP + CLAUDE.md), zcode (MCP + skill +
AGENTS.md), opencode (MCP + AGENTS.md), codex (TOML MCP +
AGENTS.md, global), pi (CLI-only: AGENTS.md + skill copied into
~/.pi/agent/skills/), agents (project AGENTS.md), dsh
(DeepSeek Harness: MCP bridge merged into the $DSH_HOME/cordis.patch.yml
user patch layer that applies to every profile, instructions into
$DSH_HOME/AGENTS.md / project AGENTS.md, and the skill copied into
$DSH_HOME/skills/ globally or .dsh/skills/ locally; dsh exposes the
tools as mcp__embpilot__<name>).
--location local writes project files, --location global writes user-scope
files; --check reports state without writing and exits 0 when everything
selected is configured.
batch reads one request object per stdin line
({"tool": "connect_serial", "args": {"port": "COM3"}}) and prints one
result envelope per stdout line, without any banner; add --fail-fast to stop
at the first failing call. serve keeps a single session manager alive so
connect survives across separate invocations: start it once, then pass
--socket <daemon.json> (or a unix:PATH / tcp:HOST:PORT endpoint) to
tool / tools / batch. POSIX uses a unix socket; Windows falls back to a
TCP loopback bound to 127.0.0.1 because the standard library has no named-pipe
server API. The daemon refuses to bind any non-loopback TCP address: it is a
local-only, unauthenticated service — anything that can reach the socket can
send commands to the attached device.
read_output observes device output without sending any bytes; it returns
early when expect_regex matches or after duration_ms, which is how boot
logs and periodic device output are captured passively.
Tool arguments also accept schema-driven flags instead of inline JSON:
embpilot tool connect_serial --port COM3 --baudrate 115200 --line-ending crlf
embpilot help connect_serial # schema, examples, guidance for one tool
run connects, executes several commands, and disconnects in one call:
embpilot run --connect '{"port":"COM3"}' help version uname -a
search_history_logs accepts an optional session_id so closed sessions can
be searched after disconnection (list_sessions shows the ids).
One-shot tool calls exit 0 on success, 1 on tool failure, and 2 on usage
or argument errors. Pass --json-output to print the structured
ok/data/error envelope instead of readable text. In the shell, connect
once and then keep issuing tool calls against the same active session.
monitor streams new device log lines (prefixed [log]) while commands stay
usable (results prefixed [cmd]); type stop to leave monitor mode. Data
path options (--data-dir, etc.) must appear before the subcommand:
embpilot --data-dir ./.embpilot-data tool list_sessions
MCP Client Configuration
Configure the client to start the installed executable; do not copy a developer-specific absolute path:
{
"mcpServers": {
"embpilot": {
"command": "embpilot",
"args": ["--data-dir", "./.embpilot-data"]
}
}
}
Prefer connect_serial, connect_ssh, or connect_telnet. Arguments are JSON
objects, not JSON strings:
{"port":"COM3","baudrate":115200,"line_ending":"crlf"}
{"host":"192.168.1.10","username":"root","key_file":"~/.ssh/id_ed25519"}
send_command accepts line_ending, expect_regex, timeout_ms, and
max_output_chars. Results contain structured ok, data, or error fields
alongside readable text. SSH host-key verification is enabled by default.
Project Status
Alpha — active development.
Architecture
src/embpilot/
├── __main__.py # CLI entry point
├── cli.py # CLI subcommands: tools, one-shot tool calls
├── cli_shell.py # Interactive REPL reusing the MCP dispatch layer
├── cli_format.py # Terminal result formatting
├── config.py # Configuration (XDG paths, framing timeout)
├── server.py # MCP Tools / Resources / Prompts registration
├── core/
│ ├── engine.py # Frame assembly, ring buffer, Expect engine
│ ├── commands.py # Command line endings, expect, and output capture
│ ├── database.py # SQLite WAL layer
│ ├── rag.py # fastembed + LanceDB vector search
│ └── schema_*.sql # Main/session DDL
└── drivers/
├── base.py # Abstract device interface
├── serial_dev.py # pyserial-asyncio
├── telnet_dev.py # telnetlib3
└── ssh_dev.py # asyncssh
Agent routing guidance is bundled in
.agents/skills/embpilot-device-debugging/.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file embpilot-0.3.1.tar.gz.
File metadata
- Download URL: embpilot-0.3.1.tar.gz
- Upload date:
- Size: 90.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
31c961d44c16a1019812d4d27fed48606ce7f231f595fd6afe68c6fb0209bb25
|
|
| MD5 |
e3b9d65d586ae8192eca2872e54d1c77
|
|
| BLAKE2b-256 |
a48bca235d66c9a97780ba43e77ec6caa667f37efbddd0334e3c0ed5bc663668
|
File details
Details for the file embpilot-0.3.1-py3-none-any.whl.
File metadata
- Download URL: embpilot-0.3.1-py3-none-any.whl
- Upload date:
- Size: 77.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dd8d3cc3685d2746f2ed9bd236163a93375ee04f7a418ce059d29e77bc17f7aa
|
|
| MD5 |
078a075ae7e5a6eb8651d18372a1a76c
|
|
| BLAKE2b-256 |
ae867a9ad2d6c371dfacbd64c96602bfa68a975668861554d62a393a1a12816e
|