fw-context-mcp
Allows AI assistants to understand and navigate Arduino firmware codebases by indexing them via compile_commands.json.
Provides optional natural-language search and symbol explanation capabilities by leveraging local LLMs via Ollama.
Allows AI assistants to understand and navigate PlatformIO-based embedded firmware projects.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@fw-context-mcpWhat does modem_parser_oob_init do?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
fw-context
Build-aware code intelligence for embedded firmware — a tool that lets AI
assistants understand your C/C++ codebase without hallucinating function
names, missing overloads, or guessing which #ifdef branch is active.
What it does
fw-context parses your actual build (compile_commands.json) with
libclang — the same parser your IDE uses — and
stores every C/C++ symbol in a full-text-searchable SQLite + FTS5 database
on disk. An MCP server then exposes this index as tools that AI assistants
(Claude Code, OpenCode) can call directly: sub-millisecond lookups, zero
hallucination, real C/C++ understanding.
Once indexed, your AI assistant can answer questions like:
"What does
modem_parser_oob_initdo and who calls it?""Find all functions related to BLE pairing failure handling."
"Show me the definition of
ZCfgDataManager— not the declaration, the actual implementation.""Is the index up to date, or did I forget to re-index after my last edit?"
"Where is
reset_slot_error_lockused across the entire project?"
The assistant resolves these by querying the index — no grepping through files, no guessing from training data, no reading 8000 Mbed OS headers into context.
Why not just use LSP?
LSP servers (clangd, ccls) are designed for interactive editing — go-to-definition, autocomplete, hover info. They're excellent at that. But they have limitations for AI-assisted code exploration:
No full-text search across the codebase. LSP can find a symbol by name, but not "all functions related to modem initialization."
No persistent index. The LSP index lives in memory; restart the server and it rebuilds from scratch. fw-context's index is a SQLite file — it survives reboots, and your AI assistant reads it in milliseconds.
No AI-oriented interface. LSP speaks a protocol designed for editors, not for AI agents. fw-context's MCP tools are purpose-built for the assistant's workflow: lookup, search, explain, re-index.
Grep is blind to build context.
grep -rdoesn't know which translation units are actually compiled, which#ifdefbranch is active, or whether a match is a definition or just a forward declaration. fw-context knows all three.
fw-context doesn't replace LSP — it complements it. Use clangd for editing, fw-context for AI-assisted exploration.
Three components
Component | Runs as | Purpose |
CLI ( | User command | Index build, status checks, project management |
Indexer | Called by CLI | libclang parses every translation unit from |
MCP server ( | Subprocess started by AI assistant | Exposes 12 tools over JSON-RPC 2.0 (stdin/stdout); optionally calls a local Ollama model for natural-language search and symbol explanation |
Key characteristics
Zero daemon. No background process — the index is a file on disk that the MCP server reads on-demand. Each tool call opens the DB, runs a query, and closes.
Ollama is optional.
explain_symbolandsmart_searchcan use a local LLM for natural-language queries, but when Ollama is disabled, the AI assistant processes results with its own model. Everything else works without any LLM at all.Incremental by default. After the first index, only files with changed modification time are re-parsed. Editing one file and running
fw-context indextakes under a second.Auto-reindex on query.
search_codeandlookup_symboldetect stale files in their results and re-index them on the fly — so the typical edit→search workflow requires no manual steps.Offline-first. The index lives at
~/.fw-context/index/. No cloud account needed. Ollama runs locally if you choose to use it.
Supported ecosystems
Works with any embedded build system that produces compile_commands.json:
Mbed OS, Zephyr RTOS, PlatformIO (Arduino, ESP-IDF, STM32Cube),
FreeRTOS, bare-metal ARM, and anything else compiled with GCC or Clang.
No LSP server, no c_cpp_properties.json, no manual configuration — it uses
the real compiler flags, so it sees what your compiler sees, #ifdefs and all.
First indexing depends on project size — from seconds for small bare-metal
projects (50–200 files) to 15–20 minutes for large Mbed OS codebases with
thousands of framework headers pulled in through #include. Subsequent runs
are incremental — only changed files are re-parsed, so they finish in
seconds.
Supported ecosystems
fw-context auto-detects your build system and source roots from the project
structure. The only hard requirement is compile_commands.json — if your
toolchain can produce one, fw-context can index it.
Ecosystem | Auto-detection | Typical indexed scope | Index time (first run) | Notes |
Mbed OS |
| 2 000–9 000 files 20 000–80 000 symbols | 5–20 min | Framework + your code; |
Zephyr RTOS |
| 1 000–15 000 files 10 000–100 000+ symbols | 3–20 min | West workspace includes modules, drivers, subsystems |
PlatformIO |
| 500–10 000 files 5 000–80 000 symbols | 1–15 min | Arduino (~500 files), ESP-IDF (~10 000), STM32Cube, Teensy… |
Bare-metal / FreeRTOS | Any build with | 50–2 000 files 500–20 000 symbols | 5 s–3 min | No OS framework overhead; only your code + RTOS kernel headers |
Custom / in-house RTOS | Any build with | Scales to 10 000+ files 100 000+ symbols | 10–30 min | Proprietary toolchains that emit compile_commands.json work too |
The indexer auto-detects source directories (src, lib, app, include,
drivers, modules, zephyr, mbed-os) from your project structure and
compile_commands.json entries. Framework symbols your code actually
#includes are indexed automatically — no manual configuration needed.
What problem it solves
AI coding assistants are great at Python, JavaScript, and Go — languages with mature LSP servers, static analysis, and training data. Embedded firmware is different:
Proprietary codebases the model has never seen — no training data.
Massive dependency trees — Mbed OS ships ~8 000 C++ files, Zephyr workspace contains 15 000+ source files across subsystems and drivers, and ESP-IDF adds ~10 000 more. Too large to read into context.
Build-time macros and
#ifdefs that change which code is actually compiled.Custom build systems (
mbed compile,west build,pio run) whose include paths, defines, and compiler flags are opaque until you run them.
Without an index, the assistant resorts to grep — slow, imprecise, and blind to which translation units are actually part of the build. It hallucinates function names, misses overloads, and can't tell a definition from a declaration.
fw-context solves this by parsing your actual build. It reads
compile_commands.json (the exact same compilation database your build system
produces), parses every translation unit with libclang (the same parser as
your IDE), and stores the extracted symbols in a SQLite + FTS5 database on
disk. Your AI assistant then queries this database through an MCP server —
sub-millisecond lookups, zero hallucination, real C/C++ understanding.
How it works, at a glance
1. Your build system 2. fw-context index 3. AI assistant
┌──────────────────┐ ┌─────────────────────┐ ┌──────────────────┐
│ bear / west / pio │ ──→ │ libclang parses │ ──→ │ lookup_symbol(…) │
│ compile_commands │ │ every .c/.cpp in TU │ │ search_code(…) │
│ .json │ │ SQLite + FTS5 db │ │ explain_symbol(…)│
└──────────────────┘ └─────────────────────┘ └──────────────────┘Key technologies
Tool | Role |
C/C++ parser — traverses AST for each translation unit, extracts symbols with their qualified names, signatures, docstrings, and location. Uses the exact compiler flags from | |
Storage and full-text search. The | |
JSON-RPC 2.0 server framework. Handles protocol initialization, message framing, and tool registration. The server is stateless between calls — each tool invocation opens the DB, runs the query, and closes. | |
Async HTTP client for calling Ollama's REST API ( | |
Ollama (optional) | Local or cloud LLM. Powers natural-language search (translates "how does the modem connect?" → FTS5 keywords |
LD_PRELOAD-based build interception. Wraps your build command ( |
What gets indexed
The indexer extracts every definition and declaration from the translation
units in compile_commands.json:
Symbol kind | Example |
Function |
|
Method |
|
Constructor / Destructor |
|
Class / Struct |
|
Enum |
|
Enum constant |
|
Typedef / Using |
|
Variable / Field |
|
Namespace |
|
All have qualified names (e.g. zbox::BleManager::start_advertising),
signatures, and file + line locations.
Each symbol is stored in the FTS5 index with 6 searchable columns:
FTS5 column | Content |
| Original C++ name |
| Full |
| Parameter types |
| Documentation comments |
| Relative path from project root (module context) |
| camelCase/snake_case split — |
Source roots are auto-detected from your project structure (src, lib, app,
include, modules, zephyr, mbed-os) and compile_commands.json entries —
OS and framework symbols your project actually #includes are indexed
automatically. No manual configuration needed.
Quick start
# 1. Clone and install
git clone git@github.com:turbyho/fw-context-mcp.git ~/.fw-context/src
# or from the primary server:
# git clone git@git.montyho.com:turbyho/fw-context-mcp.git ~/.fw-context/src
uv venv ~/.fw-context/.venv --python 3.12
uv pip install --python ~/.fw-context/.venv/bin/python ~/.fw-context/src/
echo 'export PATH="$HOME/.fw-context/.venv/bin:$PATH"' >> ~/.bashrc
# 2. Register with your AI assistant
fw-context init
# 3. Generate compile_commands.json, then index
cd your-firmware-project
bear --output compile_commands.json -- python3 build_app.py --profile release # Mbed OS
fw-context index compile_commands.json
# Set as default for the project:
echo 'compile_commands = "compile_commands.json"' >> .fw-context/config.toml
# Done. Restart your AI assistant and start asking it about your code.Installation & setup
For detailed prerequisites, installation steps, Ollama setup, and AI assistant integration, see Installation guide.
The short version:
git clone git@github.com:turbyho/fw-context-mcp.git ~/.fw-context/src
uv venv ~/.fw-context/.venv --python 3.12
uv pip install --python ~/.fw-context/.venv/bin/python ~/.fw-context/src/
echo 'export PATH="$HOME/.fw-context/.venv/bin:$PATH"' >> ~/.zshrc
fw-context initDay-to-day workflow
compile_commands.json ──→ fw-context index ──→ AI assistant tools
↑ │
bear / west / pio │
│ lookup · search · explain
your build system1. Generate compile_commands.json
Mbed OS:
bear -- python3 build_app.py --profile release --type DEVZephyr:
west build -b <board> -- -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
fw-context index build/compile_commands.jsonPlatformIO:
pio run --target compiledb2. Index the project
Run from the project root:
fw-context indexFirst run depends on project size — small projects finish in seconds, large Mbed OS codebases with 50 000+ symbols can take 15–20 minutes. Subsequent runs are incremental — only files with changed modification time are re-parsed.
Source roots are auto-detected by default. The indexer scans your project
for common source directories (src, lib, app, include, modules) and
OS/framework directories (zephyr, mbed-os), then supplements with
directories discovered from compile_commands.json. This means OS symbols
your project actually uses are indexed automatically — no manual config needed.
# Custom source roots (override auto-detection)
fw-context index --source-roots src lib vendor
# Index a different project
fw-context index --project /path/to/other/project
# Verbose output — shows per-file progress
fw-context index -v3. Use with your AI assistant
Once indexed, your assistant can:
"What does
modem_parser_oob_initdo?" →lookup_symbol+explain_symbol"Find functions related to BLE advertising" →
search_codeorsmart_search"Is the index up to date?" →
get_active_build"I changed
main.cpp, re-index it" →reindex_file
4. Keep the index current
After editing source files, the index stays accurate in three ways:
Automatic re-index —
search_codeandlookup_symboldetect stale files in their results and re-index them on the fly (up to 5 files, 30 s timeout), then re-run the query. No manual steps needed for typical edit→search workflows.Automatic staleness detection — if
compile_commands.jsonitself changed, or auto-reindex failed, tools return a clear warning with next steps.On-demand re-index — run
fw-context index(incremental, fast) or usereindex_file("src/main.cpp")via the MCP tool.
# Check if the index is stale
fw-context status
# Re-index changed files only
fw-context index
# Fresh start (after toolchain change, compiler upgrade, etc.)
fw-context reset
fw-context indexCLI & MCP tools
Full CLI reference, MCP tool catalog, and a detailed walkthrough of how each tool works internally: see Tools Reference.
Configuration
Complete configuration reference — global defaults, per-project overrides,
source root auto-detection, and all [index] / [llm] / [project] settings:
see Configuration.
Ollama & AI assistant setup
For Ollama installation, model selection (local and cloud), and AI assistant integration (Claude Code, OpenCode): see Installation guide.
Troubleshooting
"No index found"
Run fw-context index from the project root first. The index is per-project and
stored under ~/.fw-context/index/.
Index is stale
Run fw-context index — it's incremental and picks up only changed files.
Symbols missing or incomplete
By default source roots are auto-detected from your project structure and
compile_commands.json. If symbols from certain directories are missing:
Check
.fw-context/config.toml— explicitsource_rootsoverrides auto-detection. Remove it to restore auto-detection, or add the missing directories.Make sure the file is listed in
compile_commands.json.For PlatformIO frameworks (Arduino, ESP-IDF) whose sources live outside the project root (e.g.
~/.platformio/packages/), add them explicitly:source_roots = ["src", "lib", "/home/user/.platformio/packages/framework-arduinoespressif32"]
"Cannot connect to Ollama"
Ollama is optional. If you don't have it (no GPU, no cloud account), disable it in config:
# ~/.fw-context/config.toml
[llm]
enabled = falseThen explain_symbol returns the source code and prompt for the AI assistant
to answer itself, and smart_search falls back to direct keyword search —
no Ollama connection needed.
To use Ollama instead, install it from ollama.com and pull a model:
ollama pull qwen2.5-coder:14bThen verify:
fw-context check_ollamaclang.cindex error / libclang not found
# Ubuntu/Debian
sudo apt install libclang-dev
# macOS
brew install llvm
echo 'export PATH="/opt/homebrew/opt/llvm/bin:$PATH"' >> ~/.zshrc"No module named fw_context_mcp" after install
Make sure ~/.fw-context/.venv/bin is in your PATH:
export PATH="$HOME/.fw-context/.venv/bin:$PATH"Reset after toolchain upgrade
Delete the old index and rebuild:
fw-context reset -y
fw-context indexDirectory layout
~/.fw-context/
├── config.toml # global defaults (LLM model, db path)
├── .venv/ # Python virtual environment
│ └── bin/
│ ├── fw-context # CLI entry point
│ └── fw-context-mcp # MCP server entry point
└── index/
└── <project-id>/
└── index.db # SQLite database with FTS5 indexProject-level:
your-firmware/
├── .fw-context/
│ └── config.toml # per-project overrides (source roots, excludes)
└── compile_commands.jsonThis server cannot be installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/turbyho/fw-context-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server