Fw Context Mcp

io.github.turbyho由 GitHub 帳號 turbyho 發布v0.36.0更新於 Nov 8, 2026

Build-aware code intelligence for embedded C/C++ firmware — libclang, FTS5, call graphs, 37 tools

概覽

AI 產生的概覽

為編碼代理提供嵌入式 C/C++ 韌體的建置感知語意索引,讓它能查詢符號、呼叫圖、回呼與生效巨集,而不必讀完整份原始碼。

可以做什麼
fw-context 依據 compile_commands.json 與 libclang AST 建立持久索引,再透過 MCP 以精簡查詢的形式提供。代理可以詢問目前建置中哪個實作生效、誰直接或間接呼叫某個函式、回呼在哪裡註冊、哪些函式指標賦值能到達某個呼叫點、前置處理排除了哪些程式碼,以及修改某個 API 會影響什麼。README 描述了符號、參照、呼叫圖、巨集、繼承以及選用的嵌入向量資料;登錄描述提到 33 個工具,流程圖提到 39 個。
適用情境
當代理需要針對真實的嵌入式韌體建置(而非原始原始碼樹)推理時適用:審查韌體提交、追蹤從中斷服務常式經回呼的執行路徑、尋找呼叫者與參照、在修改函式簽名前做影響分析,或在不讀完整份檔案的情況下瀏覽陌生程式碼。它鎖定編譯產物與可見原始碼差異較大的韌體專案。
執行需求
以 Python 套件形式透過 stdio 在本機執行(pip install fw-context-mcp)。需要 Python 3.11 或更新版本、libclang、能產生 compile_commands.json 的專案,以及支援 MCP 的編碼代理。Ollama 為選用:沒有它時,語意搜尋與符號解說會退回全文搜尋或回傳原始提示。未宣告驗證、環境變數或標頭。
安裝前請注意
專案自述其介面與索引行為仍在演進,因此結果與工具名稱可能變動。它採本機優先設計,但可設定選用的外部服務,這會把資料送出本機之外。建立索引會執行專案建置以產生 compile_commands.json,因此會執行建置指令碼與工具鏈。未描述憑證、付費或寫入操作。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Fw Context Mcp,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

fw-context

Build-aware code intelligence for AI coding agents working on embedded C and C++ firmware.

fw-context builds a persistent semantic index from compile_commands.json and the libclang AST, then exposes it to coding agents through MCP. Instead of reconstructing your firmware through repeated file reads and text searches, the agent can query the program structure that one build produces.

It helps agents answer questions such as:

  • Which implementation is active in this build?
  • Who calls this function, directly or indirectly?
  • Where is this callback registered?
  • Which function-pointer assignments can reach this call site?
  • Which code is excluded by preprocessing?
  • What will be affected if this API changes?
  • How does execution flow from an ISR to application code?

The goal is not to give the model more source code. It is to give it the smallest useful, build-aware context needed for the current task.

Results from a real firmware review

In the included firmware review case study, fw-context was used on an nRF52/Mbed OS project containing approximately 67,000 lines of C and C++:

  • 115 changed files reviewed by 8 parallel subagents
  • 19 findings across memory safety, concurrency, API use and dead code
  • 9 findings that depended on semantic relationships not available from ordinary text search alone
  • approximately 54,000 context tokens used by fw-context queries
  • an estimated 5.8 million tokens for the equivalent broad grep and file-reading workflow

The case study includes the review output, methodology and per-tool token analysis so the claims can be inspected rather than treated as a black-box benchmark.

Quick start

Prerequisites

  • Python 3.11 or newer
  • libclang
  • a project that can produce compile_commands.json
  • an MCP-capable coding agent such as Claude Code or OpenCode

Ollama is optional for the core index: symbols, full-text search, call graph and source come from libclang and SQLite only. With the default configuration, Ollama also computes the vector embeddings (semantic_search, the re-rank step of smart_search) and the symbol analysis (explain_symbol, symbol descriptions). Without Ollama, these features fall back to full-text search or return raw prompts, and the status tools tell you that the embeddings are not complete. When you use no embedding model and no LLM, set [llm] enabled = false. See Ollama.

Install via pip (recommended)

bash
pip install fw-context-mcp

Install the current source version

bash
git clone https://github.com/turbyho/fw-context-mcp.git ~/.fw-context/srccd ~/.fw-context/srcmake install

Register fw-context with the supported coding agents detected in your project:

bash
cd /path/to/your/firmwarefw-context init

Build and index the firmware:

bash
cd /path/to/your/firmwarefw-context index --build

Then restart the coding agent and ask it questions about the project. The index is persistent and incremental; after the initial run, changed translation units are reprocessed instead of rebuilding the entire index.

See the Quick Start and Installation Guide for platform-specific setup and supported build systems.

What fw-context changes

Without a semantic project index, an AI coding agent usually starts by opening files, searching for names, following includes and trying to infer relationships that are implicit in the build. In embedded firmware this reconstruction is often the dominant part of the task.

That approach can fail in predictable ways:

  • reviewing source files that are not part of the build that you query
  • following the wrong preprocessor branch
  • missing callback registrations and indirect calls
  • selecting an inactive driver or platform implementation
  • treating declarations found by text search as reachable code
  • consuming large amounts of context on vendor code and unrelated files

fw-context moves much of that reconstruction into a reusable compiler-derived index. The agent can request exact symbol bodies, callers, callees, references, active macros, callback relationships, inheritance edges and other targeted information without reading whole source trees.

Why embedded firmware is different

In many application-level projects, the source files visible in the repository are reasonably close to the program being executed. Embedded C and C++ projects often have a much larger gap between the source tree and the resulting program.

The active firmware depends on factors such as:

  • compiler flags and preprocessor definitions
  • target, board and product configuration
  • include paths and generated headers
  • Kconfig and Devicetree selections
  • selected driver and HAL implementations
  • templates, inheritance and virtual dispatch
  • callbacks, interrupt handlers and function pointers
  • vendor SDK and RTOS configuration

A repository may therefore contain several plausible implementations of the same subsystem while only one is compiled for the selected target. An agent can reason convincingly about the wrong implementation unless it first reconstructs the build context correctly.

How it works

fw-context indexes the project through the same compilation database used by build tooling and language servers.

mermaid
flowchart LR    CCJ[compile_commands.json] & SRC[(source files)] --> LIBCLANG[libclang<br/>AST parser]    LIBCLANG --> SYMBOLS[symbols<br/>name, kind, USR<br/>signature, ifdef-filtered source body<br/>docstring, tokens] & FILES[files<br/>path, language<br/>ifdef-filtered content<br/>project/SDK sources] & REFS[refs &amp; call graph<br/>fp_assignments<br/>indirect_call_sites] & INHERIT[inheritance<br/>&amp; overrides<br/>virtual dispatch] & MACROS[macros<br/>params, value<br/>&amp; expanded value<br/>FTS5 searchable] & ENRICH[optional enrichment<br/>embeddings &amp; summaries<br/>hotspot cache]    SYMBOLS & FILES & REFS & INHERIT & MACROS & ENRICH --> MCP[MCP server<br/>37 tools]    MCP --> LLM[AI coding agent]

The index contains:

  • symbol definitions, signatures, source extents and documentation
  • references, direct call edges and recursive caller paths
  • function-pointer assignments and indirect call sites
  • callback registrations and invocation relationships
  • active, preprocessor-filtered file content
  • macro parameter lists, replacement text and expanded values
  • inheritance, overrides and virtual-dispatch relationships
  • translation-unit and project/vendor metadata
  • optional embeddings and LLM-generated summaries

The MCP server exposes this information as compact high-level queries optimized for repeated use by an AI agent.

Typical use cases

  • build-aware review of firmware commits
  • tracing execution across ISRs, work queues, tasks and callbacks
  • locating all callers and references of an API
  • identifying the implementation selected by the current build
  • impact analysis before changing a function signature or data type
  • navigating unfamiliar firmware without reading complete files
  • finding dead-code candidates and unreferenced symbols
  • separating project code from SDK and vendor code
  • reducing irrelevant source text sent to the model

fw-context supports Zephyr, PlatformIO, Mbed OS, Arduino, ESP-IDF, generic CMake, Makefile-based projects and custom builds that can provide a compilation database. Additional setup paths are documented for Keil, IAR, STM32CubeIDE and TI Code Composer Studio.

Why not just use clangd or another LSP?

clangd already uses compilation commands and is excellent at editor-oriented tasks such as diagnostics, completion, go-to-definition and reference lookup. fw-context does not replace it.

fw-context targets a different interface and workload:

  • persistent project-wide data prepared for repeated agent queries
  • MCP tools that return compact, structured semantic context
  • recursive caller and impact-analysis queries
  • callback and function-pointer relationship modelling
  • active source content suitable for targeted retrieval
  • project/vendor classification and firmware-specific workflows
  • optional cached enrichment shared across repeated analyses

Use clangd for interactive editing. Use fw-context when an AI agent needs structured, reusable context for reviewing, understanding or navigating the built firmware.

Documentation

Project maturity

fw-context is functional and is used on real embedded C and C++ projects, but its interfaces and indexing behaviour are still evolving. Bug reports, incorrect results, unsupported build configurations and reproducible edge cases are particularly valuable.

The project is local-first: source code and the compiler-derived index remain on the developer's machine unless optional external services are explicitly configured.

Background

The project grew from a recurring failure mode in AI-assisted firmware work: coding agents frequently spent more effort reconstructing the active program than reasoning about the engineering question itself.

For the longer explanation, read: Why AI Coding Agents Keep Making the Same Mistakes When Analyzing Embedded Firmware


The compiler has already reconstructed your program. Let your coding agent use it.

來源:README.md,提交 34f7f2b

工具

37

check_dependencies

Run the dependency audit of the installation. Read-only, and it creates no file. Call it when get_project_status or another tool reports a problem of the installation, or before the first ``fw-context init``. It is not a call for each session: it runs every check of the installation. Each entry gives what to do in ``action``: a ``message`` for a human, and the shell ``command`` that repairs it. ``status="skipped"`` means a prerequisite is missing (e.g. ``libclang-so`` skipped because ``libclang-python`` is absent) — not a failure. In a project that is not initialized, only the checks of the installation run: the Python packages, SQLite, libclang and its headers. The LLM, model, database and disk checks need the config. The check ``config`` names a config file that cannot be used. The checks that read the config are then ``skipped``. When a config file cannot be used, the tool cannot know if the project is initialized, thus it runs every check. Args: project_root: Project root directory. Auto-detected from CWD if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. Returns: list[dict]: one dict per check, each with ``name``, ``status``, ``critical`` (bool), ``message``, and an optional ``action`` ({message, command}).

輸入參數projectproject_root

check_ollama

Check whether the LLM backend is running and the configured embedding/chat model is installed. Read-only: yes. No side effects. Call before smart_search, semantic_search, or explain_symbol (when on-demand fallback is expected — pre-computed analysis returns instantly without the LLM backend). Args: project_root: Project root. Auto-detected if omitted. Used to locate the project's LLM configuration. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. Returns: dict: {ollama_enabled (bool), status (str — "ok"|"disabled"| "not_configured"|"model_missing"|"embedding_unavailable"|"error"), ollama_running (bool), ollama_url (str), configured_model (str), num_ctx (int), installed_models (list[str]), chat_api (dict — ``{configured (bool), model (str)}``: whether an external chat API replaces Ollama, and the model it names; a configured one adds endpoint, format, and compliance_warning for an external host), configured_embed_model (str), embedding_installed (bool), embedding_backend (str — "ollama", "local" for a sentence-transformers or ``ft://`` model, which needs no Ollama: it counts as installed, and with chat on an external API a stopped Ollama still gives "ok"; or the provider of an API profile of the embeddings, "openrouter" or "openai_compatible"), embedding_compliance_warning (str, when the embeddings go to an external API: the code and each search query leave the machine), message (str, when status is not "ok"), model_details (list[dict]), suggest_cloud (bool), vec_available (bool), vec_error (str, optional), debug_log (str, optional — onl

輸入參數projectproject_root

configure_llm

Select the LLM profile (and the embedding model) of the current project. Writes to ``<project>/.fw-context/local.toml`` ONLY (gitignored, per-developer). Does NOT modify the global config or the shared project ``config.toml``. The profiles themselves are in the global config, and only the operator writes them (``fw-context llm setup`` or ``fw-context init``): this tool takes no URL and no API key. After writing, tests the configuration by making a simple API call (skipped when LLM is disabled). When the test fails, the previous ``local.toml`` is restored and ``status`` is ``"error"``. A call with no change returns ``"error"`` and writes nothing. WHY no URL and no key here (since the profiles, 2026-10-20): a key that an MCP call writes passes through the conversation of the LLM client, and a URL that a tool call sets can send the source code to any host. Args: project_root: Project root directory. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. profile: The name of a profile of the global config. embed_model: Embedding model: an Ollama tag, a sentence-transformers name (``BAAI/...``, needs the ``st`` extra), or ``ft://``. Returns: dict: {status ("ok"|"error"), profile (str), provider (str), chat_api (dict — configured, endpoint, format, model), model (str), auto_pull (bool), stream (bool), context (int, for a profile of an API or of the ChatGPT plan: the context of the model in tokens), test_latency_s (float, on success), test_response (str, on success), compliance_warning (str, when the chat goes to another host), message (str)}

輸入參數profileprojectembed_modelproject_root

get_build_info

Return the detail of ONE build: its identity, its health, its memory map and its defines. Read-only with the two exceptions that ``get_project_status`` also has: it removes the marker of a missing build when it finds that build again, and a ``reindex.pid`` or a ``reindex.pending`` of a process that no longer runs. It spawns no subprocess. On a project of more than one build, give the arguments of one build as the refusal lists them: the ``variant``, the ``image``, or the two. ``get_project_status`` lists the builds in ``builds``. Without the arguments the answer is an error that lists the builds. A project of one build needs no selector. The health fields (``status``, ``reindex_state``, ``reindex_needed``, ``reindex_reasons``, ``index_message``, ``modified_files_count`` and the others) have the meaning that ``get_project_status`` gives them, for this build only. The version fields (``update_notice``, a restart after an upgrade) are in ``get_project_status``. About ``memory``: ``origin`` and ``length`` hold the expression the script writes, thus they differ by platform — an mbed script writes `0xefe00` and a Zephyr script writes `((673792) - 0xe6)`. ``origin_value`` and ``length_value`` hold the number, and both are None for an expression that names a symbol, such as `ORIGIN(RAM) + LENGTH(RAM)`. A name that the link command defines with ``--defsym`` counts as a number: the STM32 Arduino core writes `LENGTH = LD_MAX_DATA_SIZE` and gets ``length_value`` 98304. The end of a region is ``origin_value + length_value``. ``memory`` is empty for a build system that records no linker script, such as Keil or IAR. A PlatformIO project records its link only in ``fw-context index --build``: SCons writes no file with the link command, thus the build asks ``pio run -t envdump``. An empty list for PlatformIO means that no build recorded the link yet, and

輸入參數fastimageprojectvariantproject_root

get_project_info

Return project metadata (name, type, root_path) for a project ID. Looks up the global project registry at ``~/.fw-context/projects.db``. Use this to identify a project from its UUID4 — find out what build system it uses, its name, and where it was last indexed. Read-only. No side effects. Args: project_id: Project ID (UUID4 hex) to look up. Returns: dict: {project_id, name, project_type, root_path, created_at, updated_at} or {"error": "..."} when the project_id is not registered. On failure the dict holds only ``error`` with the reason.

輸入參數project_id

get_project_status

MANDATORY FIRST CALL for C/C++ projects. Return the health of the index of the project, and the list of its builds — check it before you use any other fw-context tool, and call it again while you wait for a reindex. Read-only with two exceptions, and it spawns no subprocess — the startup daemon thread and the file watcher own the background reindex. The exceptions: the last index run can leave a marker that says that the build is not there, and when the tool finds that build again, it removes the marker. It also removes a ``reindex.pid`` or a ``reindex.pending`` of a process that no longer runs. It creates no ``.fw-context`` file in a project that is not initialized. It takes no ``variant`` and no ``image``: it reports every build. For the detail of one build (its ``config_hash``, memory map, defines), call ``get_build_info``. ``builds`` lists every build of the index. A project of more than one build has no active build: every query tool must get the parts of one entry that are not empty, its ``variant``, its ``image``, or the two. Select the build from the task, and ask the user when the task does not identify one. Act on ``reindex_state`` of the build that the task needs, in ``builds`` (a project of one build has it at the top level too): * ``null`` — the index of the build is current. Continue. * ``"reindexing"`` or ``"pending"`` — the index of the build is not current, and an index run is active or scheduled. Wait, and call this tool again after about 30 s. Continue with the old index only when the user tells you to. * ``"not_scheduled"`` — the index of the build is not current, and no run updates it. Tell the user the command that the reasons name. * ``"failed"`` — the last index run failed. Give its text to the user: it names the command that repairs it. Each query answer carries the state of its build as ``index_state``,

輸入參數fastprojectproject_root

list_projects

List all indexed firmware projects with their statistics. Read-only. No side effects. Use it to find another project; call ``get_project_status`` for the builds and the health of one project. ``indexed_at`` and ``first_indexed_at`` are UTC, in ``"YYYY-MM-DD HH:MM:SS"`` format — the same format that ``get_project_status`` returns. ``indexed_at`` is the time of the newest build. A project of several builds gets no counts here (``symbol_count``, ``file_count``, ``description`` and ``analysis`` are None): a file that two images compile is in the index of each, thus a sum counts shared code once for each build. ``get_project_status`` gives the counts of each build. ``analysis`` holds the ``project`` and ``vendor`` counts only. For the ``model``, ``analyze_vendor``, and ``complete`` fields, call ``get_build_info`` for that build. Args: project_root: Project root whose config names the index directory (``index.db_dir``). Omitted, the global config does. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. Returns: list of dicts, each with: project_id, name, root_path, build_system, symbol_count, file_count, indexed_at (str — UTC), description (str), first_indexed_at (str — UTC), schema_version, current_schema, reindex_needed (bool — the schema is outdated, the compile_commands.json of a build changed or is missing, or a build holds rows of an older row format; each (variant, image) build counts), status (str — "ready" or "reindex_needed"), db (path to SQLite database file), build_count (int — number of builds, each a (variant, image) pair), analysis (dict — LLM-analysis covera

輸入參數projectproject_root

reindex_file

Re-parse a single source file with libclang and update its symbols in the index. Not read-only — uses the exact compiler flags from ``compile_commands.json``. Use after editing a file to keep the index current without a full rebuild. Without ``variant`` and ``image`` the file is re-parsed in EACH build of the project that compiles it: an edit on disk changes the file for every build of the tree. A build that does not compile the file is named in ``builds_without_file``. With the two arguments of one build, as ``get_project_status`` lists them, only that build is re-parsed; a part of a pair gets an error that lists the builds. The call runs in a thread of the server and sends a notice each 5 s. It holds the lock of the query tools: another query waits 5 s, then gets "server busy". After 300 s the call returns an ``error``, and a part of the work can continue or fail. Call ``get_project_status`` for the state of each build, and repeat the call for a build that is not current. The answer holds no ``index_state``, except when a manual ``fw-context index`` run holds the index (see Returns). A source file must be listed in ``compile_commands.json``. A header is not listed there — compile_commands.json names translation units — so it is re-parsed through one unit of each build. A header goes to the unit that owns it in the index (the unit that wrote its rows in the last index run). Only a header without an owner goes to an including unit from the manifest. That answer describes a single compilation context, thus the result carries a ``warning``: another unit can see the header under a different set of ``#define`` values and still hold stale symbols. Only a full ``fw-context index`` covers every context. One unit and not all of them is a cost decision — an application header reaches a median of 3 units but as many as 266 on a real project, at tens of se

輸入參數imageprojectvariantfile_path必填project_rootwith_analysis

reset_index

Delete the entire symbol index for a project. Not read-only — permanently deletes the SQLite database and WAL files. Call with ``confirm=False`` first (dry-run) to see what would be deleted. Re-index with ``fw-context index`` afterwards. Handles corrupt databases gracefully — you can delete a corrupt index without needing to open it first. Args: project_root: Project root directory. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. confirm: Must be True to execute. Call without first as dry-run. Returns: dict: {project_root, db, project_id, action: "dry_run"|"deleted", message, build_count, symbol_count, indexed_at}. ``build_count`` counts the completed builds of the project, as ``get_project_status`` lists them. ``symbol_count`` counts every symbol row in the database, the rows that the reset deletes: also the rows of a build that an index run writes now, and of an older build of a pair that an interrupted run left behind. ``indexed_at`` is the time of the newest build. The three are present only when a build config is readable. A ``warning`` key means that the database is corrupt — the integrity check or a read of the database failed, thus the tool counts nothing and the three count fields are absent. On failure the dict holds only ``error`` with the reason. When another process holds the index of the project, the tool does nothing and ``error`` names it. A manual ``fw-context index`` run adds ``index_state: "reindexing"``: wait for its end, then call again. For ``fw-context analyze``: call again after the analysis.

輸入參數confirmprojectproject_root

lookup_symbol

Look up a C/C++ symbol by name via libclang index — exact or prefix matching. Finds symbols text-based search can miss: build-conditional code, template instantiations, macro-expanded names. Macros are extracted via ``clang -dM -E`` during indexing so ``#ifdef``-conditional macros resolve correctly for the build of the query. Prefer this over search_code when you know the exact symbol name or a prefix (``uart_`` finds all UART symbols). Use search_code for keyword/concept search. *name* matches the name or the qualified name. A name with ``::`` that matches nothing is tried once more by its last part, kept where the qualified name ends with *name*: ``Foo::bar`` finds ``ns::Foo::bar``. Macros are searched only when no symbol matches. Read-only: yes. May auto-reindex stale files (non-blocking). Args: name: Symbol name (exact match) or prefix (set exact=False). E.g. 'uart_init' finds the exact function; 'uart_' finds all symbols starting with 'uart_'. project_root: Project directory. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. exact: True = exact name match, False = prefix LIKE match (default). limit: Maximum results of one page (default 50, max 100). offset: Skip this many results (default 0). A common method name lives in many classes — ``read`` and ``write`` match dozens of symbols — and this walks past the ones already seen. The page notice names the offset to use. The order is stable (a definition first, then the line, then the file and the USR), thus two pages never overlap and never skip a symbol. variant: Va

輸入參數name必填exactimagelimitoffsetprojectvariantproject_root

search_code

Find C/C++ symbols by name — searches function/class/enum NAMES. Searches symbol names, qualified names, signatures, docstrings, and pre-computed name tokens (CamelCase/snake_case split). Does NOT search function bodies — for patterns in code like ``.attach(``, interrupt handler registrations, callback attachments use ``search_bodies`` instead. Use when you know the concept but not the exact name (``"interrupt handler"``, ``"modem init"``). Prefer ``lookup_symbol`` when you already know the exact or prefix name. Results hold the metadata of each symbol — name, location, signature, docstring — not its implementation code. **FTS5 syntax:** - Every bare term gets a trailing ``*`` and the terms are OR-joined: ``modem init`` goes to FTS5 as ``modem* OR init*`` and answers with the symbols that hold EITHER word. ``search_bodies`` does the opposite — it takes the query literally, where a space is an AND. A query that holds a double quote, ``AND``, ``OR``, ``NEAR`` or a column filter goes to FTS5 as written. - ``init*`` matches init, init_uart, initialize (trailing wildcard) - ``"spi init"`` matches the exact phrase "spi init" - Do NOT use an underscore in a query. The tokenizer splits ``modem_init`` into two tokens and looks for them NEXT TO EACH OTHER. That is a phrase and not an AND, thus the query misses ``modem_parser_oob_init``. Measured on one firmware index, ``serial_write`` gave 1 result and ``serial write`` gave 200. Write ``modem init`` instead. - Punctuation is not searchable. The tokenizer drops it, thus ``.attach(`` becomes a phrase that looks for the token ``attach``. The query is repaired, never rejected. **Progressive relaxation:** when a step matches nothing, the next one runs. Six steps can run. Step 1 is the primary path and its results carry NO ``_fallback`` key; each step after it names itself the

輸入參數kindimagelimitquery必填offsetprojectvariantproject_onlyproject_root

search_bodies

Find patterns in the TEXT OF A DEFINITION — the code inside its extent. Searches **ifdef-filtered** text — only the code that compiles for the build of the query. A line of an inactive ``#if`` branch holds nothing, thus a pattern that lives only in a dead branch gives no result here. That empty answer is the correct one: the code does not compile. Searches the stored text of every definition (``is_definition=1``), and a definition is not only a callable. Measured on one project of 60,877 symbols, the text covers: - Callables — ``function``, ``method``, ``constructor``, ``destructor``, ``lambda``. Call patterns (``.attach(``, ``.rise(``, ``callback(&``), ISR registration, one ``case`` label of a long ``switch``. - Types — ``class``, ``struct``, ``union``, ``enum``, ``namespace``. An enum constant, a bit field, a member declaration such as ``InterruptIn _pin;`` — all inside the body of the type that holds them. - Definitions of data — ``varglobal``, ``varlocal``, ``typedef``. A table with a multi-line initializer is found by its content. A match on a type reports the type as the result, thus a query for one enum constant answers with the enum, and ``match_lines`` gives the line of the constant itself. **Only the text matches.** The query is bound to the stored body: a hit in the NAME, the signature, the docstring or the ``llm_analysis`` of a symbol is not a hit here. Measured on one project, ``sensor`` used to give 36 results of which 22 matched only through a summary that a model wrote — untrusted text that cannot be cited, and a ``_match_snippet`` with no match in it. Use ``search_code`` to reach a name or a concept. A column filter you write yourself (``summary : sensor``) overrides the binding. **When to use ``search_bodies`` and when ``search_code``:** - ``search_bodies`` — patterns in the code (what the code DOES or

輸入參數kindimagelimitquery必填offsetprojectvariantproject_onlyproject_root

search_content

Find patterns in FULL file content — the whole file, not only the text that belongs to a definition. Searches **ifdef-filtered** file text — only code that actually compiles for the build of the query. Inactive ``#ifdef`` branches are replaced with blank lines (preserving original line numbers). A pattern that lives only in a dead branch therefore gives no result, and that empty answer is the correct one: the code does not compile. Covers the text that belongs to no definition, which is what ``search_bodies`` cannot see: ``#include``, ``#define``, ``#ifdef``, ``extern "C"``, and a comment or declaration at file scope. It covers the text of definitions too. To find a symbol by NAME (``modem init``, ``interrupt handler``), use ``search_code``. **Not a fallback of ``search_bodies`` — its complement.** The two answer different questions and reach different text: - ``search_bodies`` answers WHICH DEFINITION holds the pattern, and takes the query literally (no wildcard, space = AND). - ``search_content`` answers WHICH FILES the topic touches, and widens the query: every term gets a trailing ``*`` and the terms are OR-joined. The wider query reaches text the literal one misses — measured on one project, ``SELF_TEST`` found 6 files here and the same word found 5 through ``search_bodies``, the extra file holding the comment ``Self tester``. For the footprint of one feature, run both. Results are file-level — one entry per matching file, with ``match_lines`` for the lines that hold a query term. ``project_only=True`` filters to ``is_project = 1`` files; the default False includes the vendor SDK files. When ``files_fts`` is missing (legacy index), falls back to LIKE search on ``files.content`` — results include ``_fallback: "like"`` and no snippet highlighting. Run ``fw-context index`` to upgrade. The LIKE search splits the query on s

輸入參數imagelimitquery必填offsetprojectvariantproject_onlyproject_root

find_all_callers_recursive

Find all transitive C/C++ callers — who calls *name*, directly or indirectly, through the libclang call graph including function-pointer edges, implicit constructors, and the edges of the SDK model. libclang-powered: follows function-pointer assignments and ISR vector registrations across the full call tree. Use for impact analysis: "if I change this function, how far does the ripple go?" Returns callers at depth 1 (direct), depth 2 (callers of callers), up to ``max_depth`` (default 5). Results are deduplicated — each caller appears once at its shortest distance to the target. **Edge types traversed:** Includes ``call``, ``indirect`` (function pointers / ISRs), ``implicit_construct`` (the constructors of the objects at namespace or class scope). A ``call`` edge with the origin ``sdk`` comes from the SDK model: the registration function (``xTaskCreate``) calls the task. **Limitation — calls without a target:** a call that libclang cannot resolve (a dependent call in a template that is never instantiated) has no edge, because fw-context does not take a target from a name. A construction that the source does not write has no edge either: the default construction of a member, and the member constructions of an implicit constructor. If you suspect a missing caller, verify with ``search_bodies("target_name")`` and ``find_indirect_targets``. For a flat, single-level caller list use ``find_callers`` (faster). For the reverse direction use ``find_callees_recursive``. Read-only. No side effects. Requires the reference index (``fw-context index`` — refs on by default). BFS from the target outward; performance scales with call-graph fan-out. Args: name: Symbol name to find transitive callers of. project_root: Project root. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask

輸入參數name必填imagelimitoffsetprojectvariantmax_depthproject_root

find_call_path

Find call paths between two C/C++ functions via BFS in the libclang call graph, including function-pointer edges, ISR vector registrations, implicit constructors, and the edges of the SDK model (a task that the scheduler starts). libclang-powered: follows function-pointer edges and ISR vector registrations that text-based search cannot resolve. Use to answer "how does A reach B?" — e.g. tracing how a high-level event handler eventually calls a low-level driver. Returns up to 5 distinct paths in BFS order (short paths first), each with ``depth`` (edge count) and ``chain`` (e.g. ``"main → app_run → modem_init"``). **Edge types traversed:** The BFS includes ``call``, ``indirect`` (function pointers / ISRs), and ``implicit_construct`` (the constructors of the objects at namespace or class scope). A ``call`` edge with the origin ``sdk`` comes from the SDK model: the registration function (``xTaskCreate``) calls the task. **Limitations:** - **SDK entry points:** an SDK can start a task, a thread or a callback from data that the call graph cannot follow (a stack frame, a library without source, an event in memory through ``void *``). Such a function gets its caller from the SDK model. The built-in rules cover FreeRTOS, ESP-IDF, lwIP, POSIX ``pthread_once``, the NVM of Nanostack, the stdio of picolibc and avr-libc, Zephyr threads, CMSIS and the mbed ``EventQueue`` (``call``, ``call_in``, ``call_every``). A handler of ``queue.event(handler)`` gets no caller from the model. Add the rules of another SDK in ``[[call_graph.sdk]]`` (``.fw-context/config.toml``). - **Calls without a target:** a call that libclang cannot resolve (a dependent call in a template that is never instantiated) has NO call edge. fw-context does not take a target from the name of the call: that once gave false paths through a method of the same nam

輸入參數imageprojectto_name必填variantfrom_name必填max_depthproject_root

get_vector_table

Read the interrupt vector table, and say what services each interrupt. The vector table is how an interrupt reaches code. Nothing CALLS a handler — the hardware reads a slot and jumps — so a handler has no caller, and every other tool shows it as unreferenced. This tool reads the table itself, from the assembly the build compiles. Use it to answer "which interrupts does this firmware service", to find the handler for one interrupt, or to find the interrupts that reach the trap loop. **The slot number is the position in the table.** What that position means belongs to the architecture, not to the index. On Cortex-M slots 0 to 15 are the system exceptions and slot 16 + n is external interrupt n, so ``TIM2_IRQHandler`` in slot 44 is ``TIM2_IRQn = 28``. On other architectures the same position means something else. The ``status`` field says what services the interrupt: * ``"c"`` — a definition outside assembly, or a C declaration of a function that a library defines (then ``file`` is the header). Code runs. When the index also holds the weak definition that this one replaced, the row has ``overridden`` with its file and line. * ``"assembly"`` — an assembly definition that is not an alias. Assembly services the interrupt. * ``"unhandled"`` — an assembly name that is an alias (``.thumb_set``) of another symbol, and nothing overrode it. The row holds ``aliases``, the name, file and line of the alias target. A CMSIS startup file aliases each unserviced interrupt to ``Default_Handler``, which is an infinite loop. If the interrupt fires, the device stops. * ``"runtime"`` — the image holds that same alias, and the code installs a real handler into this slot by calling ``NVIC_SetVector``. A target that defines ``CMSIS_VECTAB_VIRTUAL`` keeps its vector table in RAM and fills it that way, so the interrupt IS serviced

輸入參數imagelimitoffsetprojectvariantproject_rootunhandled_only

find_callees_recursive

Find all transitive C/C++ callees — what *name* calls, directly or indirectly, through the libclang call graph including function-pointer edges, implicit constructors, and the edges of the SDK model. libclang-powered: follows function-pointer calls and indirect invocations across the full dependency tree. Use for dependency analysis: "what does this function depend on to do its job?" Returns callees at depth 1 (direct), depth 2 (callees of callees), up to ``max_depth`` (default 5). Results are deduplicated by shortest distance. **Edge types traversed:** Includes ``call``, ``indirect`` (function pointers / ISRs), ``implicit_construct`` (the constructors of the objects at namespace or class scope). A ``call`` edge with the origin ``sdk`` comes from the SDK model: the registration function (``xTaskCreate``) calls the task. **Limitation — calls without a target:** a call that libclang cannot resolve (a dependent call in a template that is never instantiated) has no edge, because fw-context does not take a target from a name. If you suspect a missing callee, verify with ``search_bodies("target_name")``. For direct callees only, ``get_symbol_context`` gives a faster flat list along with the function body and callers. For the reverse direction use ``find_all_callers_recursive``. Read-only. No side effects. Requires the reference index (``fw-context index`` — refs on by default). Args: name: Symbol name to find transitive callees of. project_root: Project root. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. max_depth: Maximum BFS depth for transitive search (default 5). limit:

輸入參數name必填imagelimitoffsetprojectvariantmax_depthproject_root

find_callers

Find who calls a C/C++ function — direct calls AND indirect via function pointers, callbacks, and struct/array init lists (such as a vector table that the build generates in C). libclang-powered: detects function-pointer assignments that text-based search cannot see. A slot of an assembly vector table (``ref_kind`` ``"vector"``) and an ``NVIC_SetVector`` install (``"runtime_vector"``) are not callers: use ``find_references`` or ``get_vector_table`` for those. The SDK model gives the handler of an ``NVIC_SetVector`` install a ``"call"`` row from ``NVIC_SetVector`` too (origin ``"sdk"``, entry ``"an interrupt"``). Falls back to macro lookup when the symbol is not found as a function/method: returns the macro definition (kind="macro") and files that use it (ref_kind="macro_use"). Use when you need a quick, flat list of immediate callers. For the full transitive call tree (who calls this indirectly through other functions), use ``find_all_callers_recursive``. For all references including reads and member accesses, use ``find_references``. For a path between two specific symbols, use ``find_call_path``. Read-only. No side effects. Requires the reference index (``fw-context index`` — refs are on by default). Only direct call sites are returned; callers more than one hop away are not included. Indirect edges (``ref_kind: "indirect"``) are detected when a function pointer references a function through: - **Call arguments**: ``callback(&Class::method, this)``, ``EventQueue::call_every(ms, obj, &handler)`` - **Assignments**: ``driver.onData = &handleData``, ``global_cb = &handler`` - **Variable initializers**: ``static void (*fp)(int) = &handler`` - **Struct/array init lists**: ``{.on_data = &handler}``, ``{&fn_a, &fn_b}`` Args: name: Symbol name to find callers of. Uses the same three-tier resolution as ``find_references`

輸入參數name必填imagelimitoffsetprojectvariantproject_root

find_dead_code

Find C/C++ functions that are defined but never called — libclang-powered dead code detection across the entire indexed codebase. Distinguishes called from uncalled symbols globally, not just within a single file — text-based search cannot determine whether a function is actually reachable. **What "dead" means:** zero references of any ``ref_kind`` in the index — no call, no read, no function-pointer use, no vector slot. Only functions, methods, constructors, and destructors with a definition are checked. This is a single-layer reference check, NOT a reachability analysis from the entry points (main, ISR, exported symbols): a function that only a second dead function calls still has a reference, thus this tool does not mark it. For transitive reachability, trace from your entry points with ``find_callees_recursive``. The ``status`` field splits the results: * ``"dead"`` — no reference at all. Likely unused. * ``"possibly_dead"`` — assigned to a function pointer (``ref_kind="indirect"``) and never called directly, but no call site through that pointer resolved. Unindexed code or a type-erased API can still call it. Treat it as uncertain, and check each hit with ``find_indirect_targets`` before you delete anything. A call that reaches a function by its type only (origin ``"type_only"`` in ``find_callers``) is a call too: the function is not reported, also when no code really calls it through that pointer. fw-context records the constructor call of an object at namespace or class scope as an ``implicit_construct`` reference, and the constructor call of a local object, a new-expression or a member initializer as a ``call``. A construction that the source does not write has no reference: the default construction of a member that a constructor does not name, and the member constructions of an implicit constructor. A constructor that o

輸入參數imagelimitoffsetprojectvariantproject_onlyproject_rootexclude_paths

find_hotspots

Find the most-called C/C++ functions ranked by caller count — libclang call-graph hotspot detection. Identifies functions with the most architectural weight — good targets for refactoring, optimization, or extra testing. Text-based search cannot aggregate caller statistics across the full call graph. Use for high-level impact assessment: changing a hotspot affects many call sites. The result tells you which functions carry the most "architectural weight" across the entire codebase. By default, SDK/vendor paths are auto-excluded so hotspots reflect project code. Use ``project_only=False`` to see all results including vendor code. For the callers of a specific hotspot, follow up with ``find_callers`` or ``find_all_callers_recursive``. Read-only. No side effects. Requires the reference index (``fw-context index`` — refs on by default). Args: project_root: Project root. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. limit: Number of top-called functions per page (default 20, max 50). offset: Skip this many results. Reads further down the ranking; the page notice names the offset to use. project_only: When True (default), filters to ``is_project = 1`` symbols so hotspots reflect project code. exclude_paths: Additional LIKE patterns to exclude (user-supplied tool parameter). E.g. ``['lib/%']``. variant: Variant of the build (a board, or a PlatformIO environment). On a project of more than one build, give the arguments of one build as the refusal lists them: the variant, the image, or the two. fw-context does not select a

輸入參數imagelimitoffsetprojectvariantproject_onlyproject_rootexclude_paths

find_indirect_call_sites

Find the indirect calls through a C/C++ function pointer field or variable, or the indirect calls that a function makes, with the functions that each call reaches. An indirect call goes through a slot: a field, a variable, a parameter or the return value of a function that holds a function (``driver.onData(buf, len)``, ``g_cb(42)``, ``handlers[i](x)``), or the ``operator()`` of a ``std::function`` or another callable object. For a field or a variable, the answer holds each call through it, also through a copy of its value (``cb_t f = dev->on_rx; f(1);``). Read-only. No side effects. Use this to answer "where is this function pointer invoked, and what does it call?" as opposed to ``find_callers`` which answers "who calls this function?" (an indirect call that reaches it is a ``"call"`` row there, origin ``"slot"`` or ``"type_only"``). For the functions that a pointer can hold, and where the code stores them, use ``find_indirect_targets``. Requires the reference index (``fw-context index`` — refs on by default). Args: name: A function pointer field or variable, or a function, method or lambda. Resolved as every symbol tool resolves a name (qualified name, bare name, suffix); a name of several symbols answers for each of them. A parameter is no symbol: ask with its function. project_root: Project root directory. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. limit: Maximum results (default 50, max 200). offset: Skip this many results. Reads the next page; the page notice names the offset to use. variant: Variant of the build (a board, or a

輸入參數name必填imagelimitoffsetprojectvariantproject_root

find_indirect_targets

Find the functions that a C/C++ function pointer field or variable can hold, and where the code stores each of them; or, for a function, where the code stores its address and which indirect calls reach it. The answer comes from the data flow of the build, not from names: a function reaches a field when the code stores it there, or stores it in a slot whose value flows there (an argument of ``set_cb(h)`` into the parameter, the parameter into the field), in any file of the build. For the calls through the pointer, use ``find_indirect_call_sites``. Read-only. No side effects. Requires the reference index (``fw-context index`` — refs on by default). Args: name: A function pointer field or variable, or a function, method or lambda. Resolved as every symbol tool resolves a name; a name of several symbols answers for each of them. project_root: Project root directory. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. limit: Maximum results (default 50, max 200). offset: Skip this many results. Reads the next page; the page notice names the offset to use. variant: Variant of the build (a board, or a PlatformIO environment). On a project of more than one build, give the arguments of one build as the refusal lists them: the variant, the image, or the two. fw-context does not select a build. One query answers for ONE build. image: Image of the build: a separate program, such as the application or the bootloader. Give it when the build has an image name. Returns: For a field or a variable, one dict per f

輸入參數name必填imagelimitoffsetprojectvariantproject_root

find_references

Find ALL references to a C/C++ symbol — calls, reads, member accesses, function pointer registrations, vector table slots, and macro usages. libclang-powered: detects function-pointer registrations (vector table entries, callback attachments, ``NVIC_SetVector`` installs) that text-based search cannot see. Falls back to macro lookup when the symbol is not found as a function/method: returns the macro definition (kind="macro") and files that reference it (ref_kind="macro_use"). Read-only. No side effects. Returns every reference in the indexed codebase, including call sites, variable reads, struct member accesses, indirect function-pointer references, and macro usages. Requires the reference index (``fw-context index`` — refs on by default). For direct callers only use ``find_callers``. For transitive callers use ``find_all_callers_recursive``. For call paths between two symbols use ``find_call_path``. Args: name: Symbol name to find all references of. project_root: Project root directory. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. limit: Maximum results of one page (default 50, max 200). offset: Skip this many results. Reads the next page of a symbol with many references; the page notice names the offset to use. variant: Variant of the build (a board, or a PlatformIO environment). On a project of more than one build, give the arguments of one build as the refusal lists them: the variant, the image, or the two. fw-context does not select a build. One query answers for ONE build. image: Image of the build: a separate program, such as

輸入參數name必填imagelimitoffsetprojectvariantproject_root

find_wrapper_callers

Find C/C++ wrapper classes that call methods of a driver class — libclang-powered adapter pattern detection. Traces method ownership across class boundaries to reveal the wrapper/adapter architecture (e.g. ``UART`` wraps ``UART_DRIVER``). Text-based search cannot distinguish which class owns each method call. Returns wrapper methods grouped by wrapper class, showing which driver methods each wrapper calls. Useful for understanding the adapter/wrapper architecture (e.g. ``UART`` wraps ``UART_DRIVER``). For the reverse perspective — finding who calls a specific driver method — use ``find_callers``. For class member listing use ``get_class_members``. Read-only. No side effects. Requires the reference index (``fw-context index`` — refs on by default). Args: class_name: Driver class name to find wrappers for. E.g. ``'UART_DRIVER'`` or ``'hal::UART_DRIVER'``. The name is case-sensitive. A bare name that names no top-level class matches the class of that name in each namespace, but not a class whose name only ends with it. The methods of a class nested in the driver class count as driver methods. project_root: Project root. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. limit: Maximum wrapper classes on one page (default 20, max 100). Each class comes with all of its methods and calls into the driver (``call`` and ``indirect`` references), thus a class is never split over two pages. offset: Skip this many wrapper classes. Reads the next page; the page notice names the offset to use. variant: Variant of the

輸入參數imagelimitoffsetprojectvariantclass_name必填project_root

trace_data_flow

Trace how C/C++ data of a given type flows to a target function via libclang call paths. libclang-powered: finds functions by type signature and maps call paths through the full call graph, which text-based search cannot trace across translation units. Finds definitions whose signature mentions *type_name* (substring match, any symbol kind, most-called first), then looks for call paths from those to *to_symbol*. Returns a data flow map — useful for understanding how a data structure travels through the system to its destination. Works best for synchronous driver stacks (e.g. sensor read → I2C write). Cannot follow async flows (message queues, interrupts, RS485 callbacks). For exact call-graph queries use the ``find_*`` family; verify specific paths with ``find_call_path``. Read-only. No side effects. Requires the reference index (``fw-context index`` — refs on by default). Args: type_name: Type name to trace. E.g. ``'SensorData'`` or ``'Config::SensorData'``. to_symbol: Target symbol name. E.g. ``'uart_send'`` or ``'UART_DRIVER::send'``. project_root: Project root. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. max_depth: Maximum call path depth (default 8, max 20). limit: Maximum source functions to trace (default 15, max 15). offset: Skip this many source functions. Reads the next page; the page notice names the offset to use. timeout_ms: Maximum total execution time in milliseconds (default 30000). Clamped to 1000–300000. The budget is for one page. variant: Variant of the build (a board, or a PlatformIO

輸入參數imagelimitoffsetprojectvariantmax_depthto_symbol必填type_name必填timeout_msproject_root

explain_symbol

Explain what a C/C++ symbol does in plain English — libclang-aware analysis. Uses pre-computed LLM analysis when available (instant), falls back to on-demand LLM. Falls back to macro explanation when the name matches a ``#define``. Read-only. No side effects — uses pre-computed LLM analysis when available (instant, generated during ``fw-context index --analyze``), falls back to calling an LLM on-demand. Returns the symbol's purpose, inputs, outputs, and side effects. For raw source code use ``get_source``. For symbol metadata without explanation use ``lookup_symbol``. For body + callers + callees use ``get_symbol_context``. Args: name: Symbol name to explain. E.g. ``uart_init``, ``Modem::send``. project_root: Project root directory. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. context_lines: Lines of source context around the symbol definition (default 40, max 200). Only used when no pre-computed analysis exists. variant: Variant of the build (a board, or a PlatformIO environment). On a project of more than one build, give the arguments of one build as the refusal lists them: the variant, the image, or the two. fw-context does not select a build. One query answers for ONE build. image: Image of the build: a separate program, such as the application or the bootloader. Give it when the build has an image name. Returns: dict: {name, kind, file, line, signature, explanation, llm_analysis (if pre-computed)}. With no pre-computed analysis and no LLM (disabled), the dict holds ``explain_prompt`` and no `

輸入參數name必填imageprojectvariantproject_rootcontext_lines

get_file_map

Fast structural map of all C/C++ symbols in a file grouped by kind — libclang-powered table of contents. Like a table of contents before reading a chapter: see what functions, classes, and enums a file defines at a glance. The index decides which file a path may reach: a path that no file of this build answers for is refused, and a header of the SDK that the build compiles is reachable like any file of the application. Pass a path relative to the project root (``src/main.cpp``) or just the filename (``main.cpp``). The exact path wins; else the path matches whole trailing path segments (``config.h`` matches ``src/config.h``, not ``hw_config.h``), a project file before a vendor file, then the shortest path. Returns symbols keyed by kind (function, method, class, struct, enum, ...). Each kind has count (total) and items (first N, default 30). Set max_per_kind=0 for unlimited, signatures=true for full sigs. Enum constants (``enum_constant``) are grouped into ``subgroups`` by parent enum. Each subgroup has ``name``, ``count``, and ``constants`` (list of ``{name, qualified_name, line, enum_value}``). The subgroup count reflects the real total even when ``max_per_kind`` limits the constants list. For detailed symbol information use ``get_symbol_context`` or ``lookup_symbol``. Read-only. No side effects. Use before reading a large file to orient yourself — see what functions, classes, and enums it defines. Args: file_path: Path relative to project root, or just the filename. project_root: Project directory. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. signatures: Include full function signa

輸入參數kindimageoffsetprojectvariantfile_path必填signaturesmax_per_kindproject_root

get_source

Read a C/C++ function/method/enum/macro body using libclang exact extents — no guessing line numbers. Uses AST-precise {start, end} extents so you get exactly the function body. Generic file readers don't know where a function actually ends — libclang tracks exact {start, end} from the AST. The body is **ifdef-filtered**: a line of an inactive ``#if`` branch comes back blank, thus the text holds only the code that compiles for this build. The line numbers do not move. ``source_origin`` says where the text came from — ``"index"`` is the filtered copy, ``"disk"`` is the file itself and holds EVERY branch. A body reaches you from the disk when the file changed after the last index run (``stale_warning`` says so), or when the index holds no body for the symbol, such as a declaration. For enums, includes a ``constants`` array of the member constants with their values (at most 200; ``constants_total`` counts them all, and ``constants_hint`` names the call that pages them). For macros, returns kind="macro" with ``signature`` (``#define NAME`` or ``#define NAME(a, b)``), ``is_function_like``, ``value`` (the replacement text ALONE — the parameter list is not part of it) and ``expanded_value`` (preprocessor-resolved). For rich context (who calls this, what does it call) use ``get_symbol_context`` instead — it returns body, callers, and callees in a single call. For the full file, use ``read_file``. Read-only. No side effects. Args: name: Symbol name, or qualified name (``Class::method``) to select one symbol. Returns exact function body via libclang extent. project_root: Project root. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which t

輸入參數name必填imageprojectvariantproject_root

get_symbol_context

Rich one-shot context for a C/C++ symbol: body, signature, the direct callers and callees. Answers "what does this do and how does it fit in the system?" in a single response — libclang powers the call graph, not regex. Falls back to macro display when the symbol is not found. Prefer this over ``get_source`` when you also need callers, callees, indirect call sites, or LLM analysis — all returned in a single call. If you only need the raw function body (no metadata), ``get_source`` is slightly faster. For transitive call-graph exploration use ``find_all_callers_recursive`` or ``find_callees_recursive``. The callers and callees include vendor/SDK code — the call graph naturally spans project and vendor boundaries in both directions (project → vendor API, vendor callback → project handler). Each list is cut (callers at 50, callees at 100), and its ``*_total`` says how many there are; ``*_hint`` names the tool that pages a cut list. The body is **ifdef-filtered**, the same as in ``get_source``: a line of an inactive ``#if`` branch comes back blank and the line numbers do not move. ``source_origin`` says whether the text is the filtered copy (``"index"``) or the file itself (``"disk"``, every branch present). Read-only. No side effects. Args: name: Symbol name. Returns body, signature, the direct callers and callees (each list with its total). project_root: Project root. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. variant: Variant of the build (a board, or a PlatformIO environment). On a project of more than one build, give the arguments of one build as the refusal

輸入參數name必填imageprojectvariantproject_root

read_file

Read a C/C++ source file, one page at a time, with **ifdef-filtered** content — only code that actually compiles for the build of the query. Inactive ``#ifdef`` branches are replaced with blank lines (preserving original line numbers). Use this to read a file without leaving the fw-context ecosystem. Unlike generic file readers, this tool returns build-accurate content: code gated behind ``#ifdef BOARD_V2`` stays visible only when ``BOARD_V2`` is actually defined for this build. Line numbers match the original file — inactive branches appear as blank lines, and the text spans the whole file, thus ``lines`` is the length of the file. A blank line is an answer, and not a defect: it says that the line is in a branch the build does not take. When EVERY line of the file is blank, the dict carries ``all_lines_inactive`` and a ``warning`` — such a file holds code, and the build of the query compiles none of it. ``content`` is bare text by default and carries NO line-number prefix — unlike the ``source`` of ``get_source``, which numbers every line. Never count the lines here to find a number. Take it from a field instead: the ``match_lines`` of ``search_bodies`` or ``search_content``, the ``line`` / ``end_line`` of ``get_source`` and ``get_file_map``, or pass ``line_numbers=True`` and read the number off the line. ``start_line`` and ``end_line`` cut a window out of the file (1-based, both ends inclusive, 0 = no bound on that side). Reading around a known line costs a fraction of the whole file — 40 lines around a match instead of 2000 lines of a header. Without ``end_line`` the answer is ONE PAGE of at most 2000 lines from ``start_line`` on, and ``page`` holds the page notice: ``total`` is the number of lines of the file, ``offset`` the number of lines before the page, ``shown`` the lines on it. When ``more`` is true, the ``hint`` names the ``read_file``

輸入參數imageprojectvariantend_linefile_path必填start_lineline_numbersproject_root

get_class_members

Return all methods, fields, and nested types of a C/C++ class/struct — libclang-powered member table. Groups members by kind (method, constructor, field, enum, etc.), distinguishing class members from free functions across the entire codebase. Members are grouped by kind (method, constructor, destructor, field, enum, typedef, class, struct). Each member includes its signature, virtual flags, and source line. Works for C structs too — they just won't have methods. For inheritance hierarchy use ``get_inheritance_chain``. For individual method details use ``get_symbol_context``. Read-only. No side effects. Args: class_name: Class or struct name. E.g. ``'ModemManager'`` or ``'comm::MODEM'``. project_root: Project root. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. limit: Maximum members on one page (default 200, max 500). offset: Skip this many members. Reads the next page; ``page`` names the offset to use. variant: Variant of the build (a board, or a PlatformIO environment). On a project of more than one build, give the arguments of one build as the refusal lists them: the variant, the image, or the two. fw-context does not select a build. One query answers for ONE build. image: Image of the build: a separate program, such as the application or the bootloader. Give it when the build has an image name. Returns: dict: {name, qualified_name, kind, file, line, members: {kind: [{name, qualified_name, signature, is_virtual, is_pure_virtual, line}]}, member_count (int — every member), page}

輸入參數imagelimitoffsetprojectvariantclass_name必填project_root

get_inheritance_chain

Return the C++ inheritance chain for a class or struct — libclang-aware hierarchy. Resolves base/derived class relationships across all translation units, which single-file reading cannot do. Shows direct base classes (what this inherits from) and direct derived classes (what inherits from this), along with access level and virtual flag for each edge. When ``transitive=True``, walks the full hierarchy up to all ancestors and down to all descendants (bounded by ``max_depth``). Uses BFS with cycle detection to handle diamond inheritance. For class members use ``get_class_members``. For virtual method override chains use ``get_method_overrides``. Read-only. No side effects. Args: class_name: Class or struct name to get inheritance information for. E.g. ``'UART_DRIVER'`` or ``'comm::MODEM'``. project_root: Project root. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. transitive: When True, walk the full inheritance tree both up (ancestors) and down (descendants). Default: False (direct bases and derived only). max_depth: Maximum BFS depth for transitive walk (default 10). The schema holds it between 1 and 50, thus a number outside that range is REFUSED and not cut down to fit. limit: Maximum classes in ``all_bases`` and in ``all_derived`` on one page (default 100, max 500). Only with ``transitive=True``. offset: Skip this many classes in ``all_bases`` and in ``all_derived``. One offset pages the two lists together. variant: Variant of the build (a board, or a PlatformIO environment). On a project of more t

輸入參數imagelimitoffsetprojectvariantmax_depthclass_name必填transitiveproject_root

get_method_overrides

Return C++ virtual method override information — libclang-powered vtable analysis. Resolves virtual dispatch across class hierarchies: shows which base-class method this overrides, and which derived-class methods override this one. Text-based search cannot resolve virtual dispatch across translation units. Shows what base-class method this method overrides, and what derived-class methods override this one. Built from the ``overrides`` table: the compiler records each override when ``fw-context index`` parses a translation unit, thus an alias of a parameter type and a base that is an instance of a class template do not hide one. For class-level inheritance, use ``get_inheritance_chain``. For symbol details, use ``get_symbol_context``. Read-only. No side effects. Args: method_name: Method name to get override information for. Use qualified name for disambiguation, e.g. ``'UART_DRIVER::write'``. project_root: Project root. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. variant: Variant of the build (a board, or a PlatformIO environment). On a project of more than one build, give the arguments of one build as the refusal lists them: the variant, the image, or the two. fw-context does not select a build. One query answers for ONE build. image: Image of the build: a separate program, such as the application or the bootloader. Give it when the build has an image name. Returns: dict: { name, qualified_name, kind, file, line, signature, overrides: [{usr, name, qualified_name, kind, file, line}]

輸入參數imageprojectvariantmethod_name必填project_root

get_template_instances

Find all template instantiations for a C/C++ class or function template — libclang template-aware lookup. Finds concrete instantiations spread across all translation units, each with its full type signature. Text-based search cannot resolve template specializations across translation units. Returns concrete instantiations of the template — each with its full type signature (e.g. ``Callback<void(int)>``). They are nested in the ``instances`` list of one dict that describes the template itself. Uses the ``template_usr`` column populated during indexing via libclang's ``cursor.specialized_template``. **Known limitation:** libclang's ``specialized_template`` does not reliably resolve implicit instantiations or template methods of template classes. Header-only templates (e.g. ``RingBuffer<T>``) may report zero instances even when used in the codebase. Explicit specializations and class/struct instantiations are detected more reliably than method-level instantiations. For finding the template declaration itself use ``lookup_symbol``. Read-only. No side effects. Args: template_name: Template name to find instantiations for. E.g. ``'Callback'`` or ``'mbed::Callback'``. project_root: Project root. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alternative to project_root, which takes a root path. Give one of the two, not both. limit: Maximum results (default 50, max 200). offset: Skip this many instances. Reads the next page; the page notice names the offset to use. variant: Variant of the build (a board, or a PlatformIO environment). On a project of more than one build, give the arguments of one build as the refusal lists them:

輸入參數imagelimitoffsetprojectvariantproject_roottemplate_name必填

find_variables

Find C/C++ variables by name or part of it and trace who reads or writes them through the call graph. libclang-powered: splits variables into global (``varglobal`` — file/namespace/class-scope) and local (``varlocal`` — inside a function body). Each result includes a type signature (``bool timeSet``, ``const IPAddress modbus_ip``), the enclosing function for locals (``"<file scope>"`` for globals), and a ``references`` list of the functions that read or write the variable — the same ``ref_kind`` values as ``find_references`` (``"call"``, ``"ref"``, ``"member"``). The list is capped at 30 per variable, and holds only references of the selected build; ``references_total`` gives the whole count. Only definitions are returned, globals first, then by name. Use when you need to understand shared state, find who modifies a global variable, trace side effects, or distinguish important globals from loop counters. For general symbol search use ``search_code`` or ``lookup_symbol``. For all references to a specific variable (including reads in expressions), use ``find_references``. This tool is the way to a LOCAL variable: ``search_code`` drops the ``varlocal`` kind, because a local matches every topic query aimed at the function around it. ``search_code(..., kind="varlocal")`` reaches them as well. Legacy indexes with ``kind="variable"`` (pre-split) are detected and included in results — reindex to fully benefit from the split. Read-only. No side effects. Args: name: Variable name or part of it. Substring match on name and qualified name (e.g. ``g_`` finds ``g_debug_level``, ``g_state``). project_root: Project root directory. Auto-detected if omitted. project: Project name or project_id — call list_projects to get them. Use it to ask about a project that is not the project of the current directory. It is an alter

輸入參數kindname必填imagelimitoffsetprojectvariantproject_root

版本歷史

1
  1. v0.23.0Sep 16, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分