Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

zephyr-mcp

An MCP (Model Context Protocol) server that gives AI coding assistants real, structured introspection into Zephyr RTOS and nRF Connect SDK workspaces — not just shell wrappers around west.

It's designed to be invoked by AI clients (Claude Desktop, Claude Code, Cursor, etc.) over stdio. Once registered, you can ask in plain language "why isn't CONFIG_BT_PERIPHERAL enabled in my nrf5340 build?" and the assistant walks the resolved Kconfig, finds provenance from the .config-trace.pickle, and points you at the .conf file to edit.

Design philosophy

A tool earns its place here when one of these is true:

  1. It returns structured, agent-consumable data that would otherwise force the LLM to parse pages of CLI output (build errors, devicetree, Kconfig dependency graphs, ELF size reports).
  2. It encapsulates a multi-step workflow that's error-prone to chain by hand (build + parse errors + suggest fix; query DT + cross-ref ELF).
  3. It uses Zephyr's own build artifacts rather than re-deriving them: zephyr/edt.pickle, zephyr/.config, zephyr/.config-trace.pickle (when available), build_info.yml, CMakeCache.txt.

We deliberately do not ship one tool per west flag. Agents already have a shell. We expose the interesting commands (build) with structured output, plus a run_west escape hatch for everything else.

Tools

Tool Purpose
workspace_info One-call workspace introspection: Zephyr version, SDK, manifest, counts.
open_build Inspect a build directory; sysbuild-aware (multi-image trees).
query_devicetree Filter the resolved DT by compatible / label / status / chosen / alias / path.
list_dt_chosen_and_aliases Enumerate /chosen and /aliases — first step for "why isn't this driver picked up."
get_dt_memory_regions List zephyr,memory-region nodes; optionally cross-reference ELF allocation.
find_kconfig_resolved Symbol value + provenance (assigned / default / select / imply / unset).
find_kconfig_definition Cheap "does this symbol exist" — no build needed.
verify_kconfigs Bulk-check CONFIG_* names, sorted into enabled / disabled / missing.
build_project west build with parsed, categorized errors, sysbuild-attributed.
search_workspace Content search across the manifest (west grep); tracked source only, structured {project, file, line, text} hits.
find_workspace_files Filename search across the manifest (west forall + git ls-files); tracked files, {project, path}.
run_west Escape hatch for west subcommands without dedicated tools.

What's structurally different from prior MCP servers for Zephyr

Domain-aware. For nRF53/54/91 (and any board using MCUboot, TF-M, or multi-core), the build tree is sysbuild: domains.yaml indexes per-image build dirs. Every tool takes an optional domain parameter. The same tools handle single-image and multi-image trees uniformly.

Capability honesty. Kconfig provenance depends on .config-trace.pickle, which is produced by the Kconfig traceconfig feature — present in NCS ≥ 3.2.1 and recent upstream Zephyr (4.x with the traceconfig contribution), but not in earlier trees (e.g. NCS 3.1.0 and older, Zephyr 3.7 LTS). build_info.yml is likewise recent. Tools detect what's available and degrade gracefully: on a tree without the trace, find_kconfig_resolved still returns the authoritative value read from .config, but with provenance_available: false and no "why" (provenance/set_at) data — rather than silently producing partial output.

No CMake env reconstruction. Older approaches tried to fake the ~20 environment variables Zephyr's kconfig.cmake sets, then re-run Kconfig. That's unsound — generated paths, board-revision configs, shield Kconfigs all rely on CMake having run. We read the resolved .config instead. The build already did the work.

West Python API. Workspace discovery, manifest parsing, and config reading all go through west.util, west.manifest, and west.configuration rather than shelling out to west or hand-rolling INI parsers.

Installation

The intended distribution channel is the vfox-zephyr-sdk mise plugin, which installs zephyr-mcp as a single uv-managed script alongside the Zephyr SDK and west itself:

mise install vfox-zephyr-sdk:mcp@<version>

For development on this repo:

git clone https://github.com/ale-alfaro/zephyr-rtos-mcp
cd zephyr-rtos-mcp
uv venv && source .venv/bin/activate
uv pip install -e ".[dev]"

Wiring to an AI client

After mise install vfox-zephyr-sdk:mcp@<version>:

Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "zephyr": {
      "command": "mise",
      "args": ["x", "vfox-zephyr-sdk:mcp@<version>", "--", "zephyr-mcp"],
      "env": {
        "ZEPHYR_BASE": "/path/to/your/zephyrproject/zephyr"
      }
    }
  }
}

ZEPHYR_BASE is how the server finds your workspace — it runs west topdir from it. Every Zephyr environment sets this; the server errors if it's missing and no workspace_path is passed. (You can still override per call with the workspace_path argument to any tool.)

Claude Code:

claude mcp add zephyr --env ZEPHYR_BASE=/path/to/your/zephyrproject/zephyr \
  -- mise x vfox-zephyr-sdk:mcp@<version> -- zephyr-mcp

Running via mise x inherits the full Zephyr toolchain environment, so when the MCP server's build_project tool shells out to west, it finds the right SDK and toolchain.

Debugging

Before wiring to an LLM, exercise the tools directly with the MCP Inspector — it's a browser UI that lists tools and lets you call them by hand:

npx @modelcontextprotocol/inspector mise x vfox-zephyr-sdk:mcp@<version> -- zephyr-mcp

When the LLM gives a wrong answer, work through:

  1. Did it call any tools? (If not, improve the tool docstring.)
  2. Does the same call in the Inspector return the right data? (If no, bug in Python.)
  3. If both are fine, the LLM may have misread the response — usually means the summary line + JSON payload could be clearer.

Server logs go to stderr; on macOS, Claude Desktop captures them at ~/Library/Logs/Claude/mcp-server-zephyr.log.

Compatibility

  • Python ≥ 3.10
  • Zephyr ~3.7 through 4.x / NCS 2.6 through 3.x (we test against the artifact shapes from this range)
  • Kconfig provenance ("why is CONFIG_X set?") additionally requires the Kconfig trace artifact: NCS ≥ 3.2.1 or recent upstream Zephyr 4.x. On older trees every tool still works, but find_kconfig_resolved reports value-only (provenance_available: false).
  • Linux, macOS, Windows (via uv-managed environment)

Project status

Alpha. The tool list and response shapes are stable but may evolve based on real-world use. The artifact-reading foundation (zephyr_mcp/artifacts.py) and the domain/sysbuild model are unlikely to change.

Architecture map

zephyr_mcp/
├── artifacts.py     ← BuildArtifacts + BuildTree; sysbuild detection.
│                     The keystone — everything else reads through this.
├── workspace.py     ← Workspace discovery via west.util; manifest via
│                     west.manifest; config via west.configuration.
├── dts_tools.py     ← edt.pickle loader; query_devicetree;
│                     get_dt_memory_regions with ELF cross-reference.
├── kconfig_tools.py ← Two-tier Kconfig: definition-only (cheap) and
│                     resolved-with-provenance (needs build context).
├── build_tools.py   ← west build wrapper with structured error parsing,
│                     sysbuild domain attribution.
├── server.py        ← FastMCP entry point; tool registration.
├── models.py        ← Pydantic models for all responses.
├── cache.py         ← Mtime-keyed cache for expensive parses.
├── errors.py        ← Domain exceptions.
└── __init__.py

License

Apache-2.0

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages