Skip to main content

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)
  • Send arbitrary commands, including device-specific reboot commands
  • Guard risky operations with dangerous-command confirmation, delete confirmation, redacted audit history, rate limiting, and bounded exports
  • Expose active-session resources through MCP, including device://live_log and device://session_info
  • Persist sessions in SQLite (WAL mode) with FTS5-backed historical search
  • Search and export recorded sessions (by session id, keyword, or full export)
  • Local vector search tools (optional embpilot[rag]) over Datasheets, Error Code manuals, and KB articles
  • Analyse crash logs and run hardware sanity checks with guided prompts

Quick Start

uv tool install embpilot        # core: Serial/Telnet/SSH MCP server
uv tool install "embpilot[rag]" # + optional local RAG (fastembed + LanceDB)
embpilot install            # detect and configure supported agent harnesses
embpilot --help

uv tool install installs EmbPilot into an isolated environment and exposes the embpilot launcher on your PATH. If you prefer managing EmbPilot inside a virtual environment, the equivalent pip commands are pip install embpilot and pip install "embpilot[rag]".

embpilot install follows the explicit installer model used by agent tooling such as CodeGraph. It detects supported harnesses, lets you select targets and global/local scope, then idempotently installs MCP config and a marker-fenced EmbPilot routing block plus a detailed embpilot-device-debugging skill where the harness supports them. The short, always-loaded hook routes relevant tasks; the skill supplies the full workflow and safety contract only when needed. Existing instructions and other MCP servers are preserved. Run embpilot uninstall to remove only content still owned by EmbPilot. A skill edited by the user is left in place while its MCP entry and routing hook are still removed.

Run embpilot doctor for environment diagnostics (Python, core/RAG deps, drivers, storage, serial ports). The plain embpilot command starts the MCP stdio server and waits for an MCP client; it is not an interactive shell.

To configure another project without changing directories:

embpilot install --project-dir path/to/project

Non-interactive examples:

embpilot install --target claude,codex,zcode,opencode --location global
embpilot install --target claude,opencode --location local --project-dir .
embpilot install --yes  # auto-detect targets, global scope

Supported installation surfaces:

Harness Global Local project
Claude Code ~/.claude.json, ~/.claude/CLAUDE.md, ~/.claude/skills/embpilot-device-debugging/SKILL.md .mcp.json, .claude/CLAUDE.md, .claude/skills/embpilot-device-debugging/SKILL.md
Codex ~/.codex/config.toml, ~/.codex/AGENTS.md, ~/.codex/skills/embpilot-device-debugging/SKILL.md Not supported
ZCode ~/.zcode/cli/config.json + registered embpilot-device-debugging skill Not supported
OpenCode ~/.config/opencode/opencode.jsonc, AGENTS.md, skills/embpilot-device-debugging/SKILL.md opencode.jsonc, AGENTS.md, .opencode/skills/embpilot-device-debugging/SKILL.md

OpenCode follows XDG_CONFIG_HOME when set. ZCode installs its confirmed MCP entry plus an enabled embpilot-device-debugging skill; because no verified global instruction path is available, it does not receive a separate marker hook.

MCP Client Configuration

Configure your agent to start EmbPilot as an MCP server:

{
  "mcpServers": {
    "embpilot": {
      "command": "embpilot",
      "args": ["--data-dir", "./.embpilot-data"]
    }
  }
}

Agents should use EmbPilot before raw ssh, telnet, or serial clients. Pick the protocol-specific tool and pass an actual JSON object, not an encoded JSON string or a nested config object:

{"port":"COM3","baudrate":115200}
{"host":"192.168.1.10","username":"root","key_file":"~/.ssh/id_ed25519"}
{"host":"192.168.1.10","port":23}

These map to connect_serial, connect_ssh, and connect_telnet. Then use send_command; set expect_regex, timeout_ms, or line_ending when the target requires them. Connection successes and runtime failures include structured JSON for agents as well as readable text. Invalid arguments remain MCP invalid-parameter errors so clients can repair the call.

An empty command with line_ending="as-is" or "none" is rejected before it reaches a transport. To send only Enter/a blank line, use line_ending="lf", "crlf", or "cr" as required by the target.

Current resource direction:

  • device://live_log exposes the active session's recent log snapshot and is currently a snapshot resource. EmbPilot does not advertise subscriptions until it sends MCP notifications/resources/updated events.
  • device://session_info exposes honest session metadata for the current connection instead of pretending EmbPilot can issue one generic sysinfo probe across all targets.

Safety defaults:

  • SSH uses AsyncSSH host-key defaults unless known_hosts: null is explicitly passed in the connection config.
  • Destructive actions such as dangerous commands, session deletion, and RAG document deletion require explicit confirmation flags.
  • Operation audit export redacts sensitive config keys and inline command secrets such as passwords, tokens, Authorization headers, and AT Wi-Fi passwords.
  • Safety limits can be tuned from the CLI with flags such as --command-timeout-max-ms, --export-limit-max, and --tool-rate-limit-per-minute; MCP tool schemas are generated from those configured limits.

Project Status

Alpha — active development.

Architecture

src/embpilot/
├── __main__.py        # Python module entry point
├── cli.py             # CLI argument parsing and startup wiring
├── mcp_app.py         # MCP app assembly and stdio server runner
├── config.py          # Configuration (XDG paths, framing timeout, retention)
├── server.py          # Compatibility wrapper over the new MCP runner
├── runtime/
│   ├── __init__.py
│   ├── models.py      # SessionInfo plus canonical log/ring exports
│   ├── pipeline.py    # Dispatcher-based log fan-out and framing
│   ├── expect.py      # Command windows and expect matching
│   ├── resources.py   # device://live_log and device://session_info payloads
│   └── session.py     # Session lifecycle and active connection state
├── core/
│   ├── engine.py      # Canonical LogLine/RingBuffer types
│   ├── database.py    # SQLite WAL layer and schema loading
│   ├── rag.py         # fastembed + LanceDB vector search
│   ├── schema_main.sql
│   └── schema_session.sql
└── drivers/
    ├── base.py        # Abstract device interface
    ├── serial_dev.py  # pyserial-asyncio
    ├── telnet_dev.py  # telnetlib3
    └── ssh_dev.py     # asyncssh
  • mcp_app.py owns MCP protocol registration and delegates runtime behavior to the runtime/ package.
  • runtime/pipeline.py now uses explicit dispatcher fan-out instead of the old implicit multi-consumer queue description.
  • Driver implementations expose a byte-oriented runtime contract. Text-mode transports such as Telnet and SSH adapt their library streams internally, so the log pipeline always receives bytes before frame assembly. send_command accepts an explicit line_ending strategy (as-is, none, lf, crlf, cr) for targets which require a specific terminator.
  • Session logs store inferred level and tag metadata and are indexed through SQLite FTS5 for historical search. search_history_logs defaults to mode="fts" and also supports mode="substring" for literal partial-token searches such as register names, paths, and abbreviated error fragments.

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

embpilot-0.2.1.tar.gz (56.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

embpilot-0.2.1-py3-none-any.whl (55.0 kB view details)

Uploaded Python 3

File details

Details for the file embpilot-0.2.1.tar.gz.

File metadata

  • Download URL: embpilot-0.2.1.tar.gz
  • Upload date:
  • Size: 56.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.10

File hashes

Hashes for embpilot-0.2.1.tar.gz
Algorithm Hash digest
SHA256 f0b2bdb3b73d6d7376118bb0fb36a4547eb364c43de3cbe6a26a67306467cb21
MD5 85624fd256f9ea631cd34af21fbc0fd9
BLAKE2b-256 b77cf9741e64adb5d76b651d9f5622f6cb917982faa0d2278743b2e166371f9d

See more details on using hashes here.

File details

Details for the file embpilot-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: embpilot-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 55.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.10

File hashes

Hashes for embpilot-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ecb0cd6f2efa074ca343764013deb26178c4c6c68ccf6992a7fe226f31116d2a
MD5 5710199af38669fa8ffc1e7b2bfb5079
BLAKE2b-256 878ffe92cb5816bffdb2f4ae5217c2ebfbeb38003c7c0d86d3c27fe5ba69a313

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page