Skip to main content
Glama

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault

No arguments

Capabilities

Features and capabilities supported by this server

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
check_ollamaA

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. Ignored by this tool.

Returns: dict: {ollama_enabled (bool), status (str — "ok"|"disabled"|"error"|"model_missing"), ollama_running (bool), ollama_url (str), configured_model (str), num_ctx (int), installed_models (list[str]), configured_embed_model (str), embedding_installed (bool), message (str, on error/disabled), available_code_models (list[str], when model missing), debug_log (str, optional — only when debug logging is enabled)}

get_active_buildA

MANDATORY FIRST CALL for C/C++ projects. Return metadata about the most recently indexed build configuration — check index health before using any other fw-context tools.

Read-only: yes. Call at session start to check if the index exists, how many symbols it contains, and whether a reindex is needed.

Use the status field for decision-making:

  • "ready" — fully up to date, no issues. Continue normally.

  • "reindexing" — background reindex in progress. Index is still usable — all queries return accurate results. Continue normally.

  • "reindex_needed" — compile_commands.json changed or schema mismatch. Run fw-context index, but queries still work on existing data.

  • "no_index" — no build config indexed. Use other tools.

  • "error" — DB corruption or access error. Use other tools.

reindex_needed is True when a structural mismatch exists: schema version outdated or compile_commands.json changed since indexing. Modified source files are auto-handled per-query and do NOT cause reindex_needed=True.

index_message is a human-readable summary of the index state.

When modified_files_count > 0, a background fw-context index subprocess is spawned automatically (non-blocking, at most one at a time). Queries continue to be served from the existing index while the new one is being built. reindex_progress contains the last log line from the reindex subprocess when bg_reindex_running is True.

Args: project_root: Project root directory. Auto-detected from CWD if omitted.

Returns: dict: {config_hash, project_id, project_root, build_system, compile_commands, indexed_at (ISO timestamp), symbol_count, file_count, reference_count, modified_files_count (int), header_affected_tus (int — number of TUs with stale header dependencies), manifest_verification (str — "full" when manifest.json exists, "none" otherwise), analyzed_symbols (int), unanalyzed_symbols (int — definition symbols still needing LLM analysis), analysis_model (str or None), vendor_paths (list[str] — config index.vendor_paths), project_paths (list[str] — config index.project_paths), bg_reindex_running (bool), reindex_progress (str or None — last log line when reindex is running), schema_version (int — DB schema version), current_schema (int — code expects), status (str — "ready"|"reindexing"| "reindex_needed"|"no_index"|"error"), reindex_needed (bool — structural mismatch requiring a full reindex), reindex_reasons (list[str] — why reindex is needed, empty when False), index_message (str — human-readable summary of index state)}

get_project_infoA

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.

list_projectsA

List all indexed firmware projects with their statistics.

Read-only. No side effects. Use at session start to discover available projects; use get_active_build for details on the currently active project.

Args: project_root: Project root. Auto-detected if omitted. Pass to distinguish multiple indexed projects.

Returns: list of dicts, each with: project_id, name, root_path, build_system, symbol_count, file_count, indexed_at, schema_version, current_schema, reindex_needed (bool), status (str), db (path to SQLite database file).

reindex_fileA

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. The file must be listed in compile_commands.json (headers are re-indexed via the translation unit that includes them). Use after editing a file to keep the index current without a full rebuild.

Also regenerates LLM analysis and method override relationships for affected symbols when those features are enabled in config.

Args: file_path: Path to source file to re-parse. Must be in compile_commands.json. project_root: Project root directory. Auto-detected if omitted.

Returns: dict: {file, translation_units, symbols_updated, elapsed_s, analysis_updated (if LLM enabled), or error}.

reindex_file_implA

Re-parse a single source file with libclang and update its symbols in the index.

Shared implementation used by reindex_file (public tool, full analysis) and _auto_reindex_stale (background fast path, no LLM). Prefer reindex_file for interactive use; call this directly only when you need to control with_analysis explicitly.

Requires an existing index (fw-context index must have been run first). The file must appear in compile_commands.json — header-only files are re-indexed via the .cpp translation unit that includes them.

Args: file_path: Absolute or project-relative path to the source file to re-parse. Must have a matching entry in compile_commands.json. project_root: Project root directory. Auto-detected from cwd if omitted. with_analysis: When True (default), also regenerates LLM symbol analysis and method override relationships — slower but produces a fully up-to-date index. Set to False for a fast symbol-only update (used by background auto-reindex).

Returns: On success — dict with keys: file (str): Resolved absolute path to the re-indexed file. translation_units (int): Number of TUs that include this file. symbols_updated (int): Number of symbols written/updated. elapsed_s (float): Parse + store time in seconds. analysis_updated (int, optional): Symbol count with fresh LLM analysis (only present when LLM analysis is enabled and with_analysis=True). analysis_warning (str, optional): Reason LLM analysis was skipped. overrides_warning (str, optional): Reason override analysis was skipped. warning (str, optional): Header re-indexed via a single TU — other TUs including this header may still have stale symbols; run fw-context index for full accuracy. On error — dict with key: error (str): Human-readable reason (no index found, file not found, file not in compile_commands.json, no build config indexed).

reset_indexA

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. confirm: Must be True to execute. Call without first as dry-run.

Returns: dict: {project_root, db, project_id, action: "dry_run"|"deleted", message, symbol_count, indexed_at (dry-run)}.

lookup_symbolA

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. Prefer this when you know the exact symbol name or prefix. Falls back to macro lookup.

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 active build config. 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.

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. exact: True = exact name match, False = prefix LIKE match (default). limit: Maximum results (default 50).

Returns: list[dict]: Symbols with name, qualified_name, kind, file, line, signature, docstring, is_definition, is_template, is_virtual, is_pure_virtual fields. Enum constants include enum_value with the integer value. Macro results include kind="macro", value (raw definition), and expanded_value (preprocessor- resolved value). May also include template_usr, parent_usr, summary, inputs, outputs when available. When no results found, may include _did_you_mean with suggested symbol names. Empty list if not found.

search_codeA

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 include names, file locations, signatures, and docstrings — the metadata about each symbol, not the symbol's implementation code.

FTS5 syntax:

  • init* matches init, init_uart, initialize (trailing wildcard)

  • "spi init" matches the exact phrase "spi init"

  • Do NOT use underscore in queries — modem_init is split into modem AND init. Write modem init instead.

Progressive relaxation: when the initial FTS5 search returns nothing, the tool automatically broadens the search in up to six steps:

  1. FTS5 with kind filter — the original query with the user-provided kind constraint.

  2. FTS5 without kind filter — drops the kind constraint (users often guess the wrong kind for a symbol).

  3. name_tokens substring match — searches the pre-computed CamelCase/ snake_case token column (e.g. BuildType is indexed as "build type"). Requires at least N‑1 of N query terms to match.

  4. Single-term docstring LIKE — when only one query term was given and the token-based steps found nothing, does a raw LIKE over the docstring column to catch terms the FTS5 tokeniser may have missed.

  5. Individual term FTS5 — searches each query word separately and merges the results.

  6. Macro FTS5 fallback — searches the macros_fts table for matching #define names and values (kind="macro", _fallback="macros_fts").

Results from fallback steps carry _fallback indicating which method succeeded ("fts5", "name_tokens_like", "docstring_like", "individual_terms", "macros_fts").

Kind filter values: function, method, constructor, destructor, class, struct, union, enum, enum_constant, typedef, variable, field, namespace.

Each result may include summary, inputs, outputs when LLM analysis has been generated (fw-context index --analyze). These provide structured descriptions: what the symbol does, what parameters/data it receives, and what it returns/produces.

Read-only. No side effects.

Args: query: FTS5 search terms. Keep queries short — 1–3 words. project_root: Project root directory. Auto-detected from CWD if omitted. kind: Optional filter to return only symbols of this kind. limit: Maximum results (default 20, max 100). project_only: When True, exclude vendor SDK directories and return only application code. Default False.

Returns: list of dicts, each with: name, qualified_name, kind, file, line, is_definition, signature, docstring, is_template, is_virtual, is_pure_virtual. Enum constants include enum_value with the integer value. May also include template_usr, parent_usr, summary, inputs, outputs when available. Fallback results include _fallback with the method name.

search_bodiesA

Find patterns in C/C++ function BODIES — the implementation code inside { }.

Searches ONLY the text between { and } of function/method definitions. Does NOT search file-scope constructs (see Limitations below).

When to use search_bodies vs search_code:

  • search_bodies — patterns in function BODIES (what the code DOES): function call patterns (.attach(, .rise(, .fall(, callback(&), ISR registration code.

  • search_code — find symbols by NAME (what the code IS): modem init, interrupt handler, uart send.

Limitations — what search_bodies CANNOT find:

Only function/method definition bodies are indexed (is_definition=1 symbols with source text). The following are at FILE SCOPE and are NEVER in the source column:

  • extern "C" — linkage specifier at file scope

  • Type declarations in headers — InterruptIn _pin; in class bodies

  • #include, #define, #ifdef — preprocessor directives

  • Global/static variable definitions outside functions

  • Namespace declarations

  • Any code outside { } of a function definition

LIMITATION — search_bodies ONLY searches function bodies ({ }): If your pattern might be at file scope (class member declarations like InterruptIn _pin, function declarations, #define, extern "C", global variables), use search_content instead. search_bodies returns empty for any pattern outside function bodies.

For these patterns, use search_content which indexes full file content (not limited to function bodies).

When to set project_only=True: Your project contains two kinds of code:

  • Application code — code your team wrote.

  • Vendor SDK — framework/OS code shipped by a vendor, NOT written by your team.

Set project_only=True when the question is about YOUR code ("where do we register interrupt handlers?", "which functions call .attach()?"). Leave it False (default) when the vendor code is also relevant.

Results include _match_snippet — a highlighted excerpt showing each match in context (e.g. _timeout.<b>attach</b>(callback(...))). Project code sorts before vendor code in the output.

Read-only. No side effects. Requires the FTS5 index.

Args: query: FTS5 search terms. 1-3 words. Bare multi-word queries are OR-joined (each term prefixed with *). Prefer single-word queries for broad matching: 'attach' finds .attach(...) patterns including callback attachments, timer registrations, etc. For exact phrases wrap in double quotes: '"attach callback"'. project_root: Project root. Auto-detected if omitted. kind: Optional filter to return only symbols of this kind. limit: Maximum results (default 20, max 100). project_only: When True, exclude vendor SDK directories and return only application code. Default False.

Returns: list of dicts, each with: name, qualified_name, kind, file, line, is_definition, signature, _match_snippet (excerpt around match), source (function body, truncated at 2000 chars).

search_contentA

Find patterns in FULL file content — not limited to function bodies.

Searches ifdef-filtered file text — only code that actually compiles for the current build configuration. Inactive #ifdef branches are replaced with blank lines (preserving original line numbers).

Covers file-scope constructs that search_bodies cannot see: extern "C", type declarations in headers, #include, #define, global variables, namespace blocks. Also covers function bodies, but search_bodies is preferred for body-level patterns (per-function context, snippet highlights per match).

When to use search_content vs search_bodies vs search_code:

  • search_content — patterns anywhere in FILES (file scope + bodies): extern "C", InterruptIn, #define, type declarations.

  • search_bodies — patterns in function BODIES only: .attach(, callback(&, ISR registration patterns.

  • search_code — find symbols by NAME: interrupt handler, modem init.

project_only=True filters to files with is_project = 1 (project code, excluding vendor/SDK). Default False includes vendor SDK files.

Results are file-level (one entry per matching file) — use search_bodies for per-function granularity.

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.

Read-only. No side effects. Requires the FTS5 index with file content.

Args: query: FTS5 search terms. 1-3 words. Bare multi-word queries are OR-joined (prefix-wildcarded). Prefer single-word queries. E.g. 'InterruptIn', 'extern C', '#define'. project_root: Project root. Auto-detected if omitted. limit: Maximum results (default 20, max 100). project_only: When True, filter to project code only (files with is_project = 1).

Returns: list of dicts, each with: file, language, mtime, _match_snippet (highlighted excerpt around the match).

semantic_searchA

Semantic search using pre-computed libclang symbol embeddings. Finds symbols by meaning, not by text — matches concepts even when query words don't appear literally in the code. Uses cosine similarity over variable-dimension embeddings generated during fw-context index. Dimensions vary by model: mxbai-embed-large → 1024, qwen3-embedding → 4096.

When to prefer over search_code: When you're describing a concept rather than searching for a known keyword. Examples:

  • "parcel locker state" finds door-state and shipment methods even though "parcel" and "locker" don't appear in their names.

  • "cell modem" finds _socket_t and ModemMsg* classes.

  • "delivery box" finds set_shipment and get_zrtdata.

  • "power consumption" finds get_load_power and INA260 class.

When to prefer search_code instead: When you know the exact keyword or symbol name ("fram_write", "cbor encode"). FTS5 is faster and more precise for lexical matches.

Threshold guidance (mxbai-embed-large model):

  • 0.50 — exploratory: more results, lower precision

  • 0.55 — balanced (~1000 results)

  • 0.60 — precise: ~175 avg, high precision (default)

  • 0.65 — strict: few results, may miss relevant symbols

Source-aware ranking: Project code boosted 1.2×, library code 1.1×, vendored SDK code 0.85×.

Requires an LLM with an embedding model. Falls back to search_code with a warning if the LLM is unavailable.

Read-only. No side effects.

Args: query: Natural language description of what you're looking for. Be specific — 5–15 words works best. project_root: Project root. Auto-detected if omitted. threshold: Minimum cosine similarity (0.0-1.0). Default 0.60. limit: Maximum number of results (default 20, max 100).

Returns: list of dicts, each with: name, qualified_name, kind, file, line, is_definition, signature, docstring, plus _similarity (cosine similarity score) and _method ("embedding" or "search_code_fallback").

smart_searchA

Natural-language search: an LLM generates FTS5 keywords, then searches the libclang index. Finds concepts by meaning rather than exact text match. Prefer this when you don't know the exact keywords and want to describe what you're looking for ("how does the modem connect?", "handle BLE pairing failure").

Read-only. No side effects. Slow (10-30 s) — delegates to the full SMART_SEARCH pipeline (translate → rough_search → llm_query → fts5_search → refine → embedding → rrf_fusion → deduplicate → expand_context → format).

Multi-phase approach:

  1. Translate non-English queries

  2. Rough search to gather sample symbols for naming conventions

  3. LLM sees those samples + query and generates FTS5 terms

  4. FTS5 search with generated terms

  5. Refine: LLM checks results and course-corrects query terms

  6. Semantic embedding search (cosine similarity re-rank)

  7. Deduplicate, score, and format results

When to prefer over search_code: When you don't know the exact keywords and want to describe what you're looking for ("how does the modem connect?", "handle BLE pairing failure").

Fallback: When LLM is unavailable, falls back to direct FTS5 search with word-split terms from the query.

Args: query: Natural language description of what you're looking for. Be specific — 5–15 words works best. project_root: Project root directory. Auto-detected from CWD if omitted. limit: Maximum number of results (default 20, max 100).

Returns: list of dicts with metadata entries (_generated_queries, _rough_queries, _translated_from) followed by symbol results with name, qualified_name, kind, file, line, is_definition, signature, docstring.

find_all_callers_recursiveA

Find all transitive C/C++ callers — who calls name, directly or indirectly, through the libclang call graph including function-pointer edges. 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.

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. max_depth: Maximum BFS depth for transitive search (default 5). limit: Maximum results (default 50).

Returns: list of dicts, each with: caller (str — caller name), caller_qualified_name (str), depth (int — distance from target), file (str), line (int), ref_kind ("call" or "indirect").

find_call_pathA

Find call paths between two C/C++ functions via BFS in the libclang call graph, including function-pointer edges and ISR vector registrations. 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 shortest paths, each with depth (edge count) and chain (e.g. "main → app_run → modem_init").

For one-sided exploration use find_all_callers_recursive (who reaches this?) or find_callees_recursive (what does this reach?). For exact call-graph verification use find_callers or find_references.

Read-only. No side effects. Requires both symbols to be in the index and refs enabled (fw-context index — refs on by default).

Args: from_name: Starting symbol for path search. to_name: Target symbol to find path to. project_root: Project root. Auto-detected if omitted. max_depth: Maximum BFS depth for path search (default 10).

Returns: list of dicts, each with: depth (edge count, int), chain (str — e.g. "main → app_run → modem_init"). Empty list when no path exists within the depth limit.

find_callees_recursiveA

Find all transitive C/C++ callees — what name calls, directly or indirectly, through the libclang call graph including function-pointer edges. 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.

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. max_depth: Maximum BFS depth for transitive search (default 5). limit: Maximum results (default 50).

Returns: list of dicts, each with: callee (str — callee name), callee_qualified_name (str), depth (int — distance from source), file (str), line (int), ref_kind ("call" or "indirect").

find_callersA

Find who calls a C/C++ function — direct calls AND indirect via function pointers, callbacks, interrupt vector registrations, and struct init lists. libclang-powered: detects function-pointer assignments and ISR vector registrations 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 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 (exact name, exact qualified, suffix LIKE). project_root: Project root directory. Auto-detected if omitted. limit: Maximum results (default 50).

Returns: list of dicts, each with: file, line, ref_kind ("call", "indirect", "implicit_construct", or "macro_use"), caller (enclosing function name), caller_kind ("function", "method", …). Macro fallback includes a leading dict with kind="macro", value, and expanded_value.

find_dead_codeA

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.

Returns two categories of results, each with a status field:

  • "dead" — no references at all (neither calls nor function pointer assignments). Likely unused.

  • "possibly_dead" — the function is assigned to a function pointer (Phase 1 ref_kind="indirect") but no call site through that pointer was resolved (Phase 3). This means the function MIGHT be called through unindexed code or a type-erased API. LLM should treat this as uncertain, not as confirmed dead code. Verify each hit with find_indirect_targets before deleting.

Implicit constructor calls through global/static object and member-field initialization are detected as implicit_construct references. Known remaining false positives: constructors called via factories, ISRs, virtual method overrides, and weak-aliased symbols. Always verify before deleting.

By default, SDK/vendor paths are auto-excluded via the is_project column (which respects project config vendor_paths and project_paths). Use project_only=False to see all results including vendor code.

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. limit: Maximum results (default 100). exclude_paths: Additional LIKE patterns to exclude (user-supplied tool parameter, not config). E.g. ['lib/%']. project_only: When True (default), filters to is_project = 1 symbols. Set False to see all results.

Returns: list of dicts, each with: name, qualified_name, kind, file, line, status ("dead" or "possibly_dead"), and reason (str — explains why the function is classified as dead or possibly dead).

find_hotspotsA

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. limit: Number of top-called functions to return (default 20). 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/%'].

Returns: list of dicts, each with: name, qualified_name, kind, file, line, caller_count (int — total number of call sites), signature.

find_indirect_call_sitesA

Find indirect call sites where a C/C++ function pointer field or variable is invoked. libclang-powered: resolves calls through function pointers (e.g. driver.onData(buf, len)), which text-based search cannot detect.

Returns locations where a function pointer is called through a field access (driver.onData(buf, len)) or variable dereference (stored_callback(42)).

Read-only. No side effects. Use this to answer "where is this function pointer invoked?" as opposed to find_callers which answers "who calls this function?" and find_references which answers "where is this symbol read or assigned?"

For the reverse query — which functions are assigned to a given field or parameter — use find_indirect_targets.

Requires the reference index (fw-context index — refs on by default).

Args: name: Name of the function pointer field or variable. E.g. "onData" finds every call through a field named onData. Uses three-tier resolution: exact name, exact qualified, suffix LIKE. project_root: Project root directory. Auto-detected if omitted. limit: Maximum results (default 50, max 200).

Returns: list of dicts, each with: file, line, expr_text (the callee expression, e.g. "driver.onData"), target_usr, target_name, fn_ptr_type (the function pointer type signature), caller (enclosing function name), caller_kind.

find_indirect_targetsA

Find functions assigned to a C/C++ function pointer field or variable. libclang-powered: links assignment sites to call sites via the field's unique symbol reference, which text-based search cannot resolve.

Links assignment sites (driver.onData = &handler) to call sites (driver.onData(buf, len)) via the field's USR.

Returns each function that could be invoked through the named function pointer, showing both the assignment location and the call site(s). When a function is assigned but no call site is found, call_file and call_line are null — the assignment exists but the invocation may be in unindexed code.

For the reverse query — where is this field or parameter called — use find_indirect_call_sites.

Read-only. No side effects. Requires the reference index (fw-context index — refs on by default).

Args: name: Name of the function pointer field, variable, or parameter. E.g. "onData" finds every function assigned to a field named onData. Uses three-tier resolution. project_root: Project root directory. Auto-detected if omitted. limit: Maximum results (default 50, max 200).

Returns: list of dicts, each with: rhs_name (assigned function), rhs_qname, fn_ptr_type, method (assignment/call_arg/var_init/ init_list), assign_file, assign_line, assign_caller, call_file, call_line, call_expr_text.

find_referencesA

Find ALL references to a C/C++ symbol — calls, reads, member accesses, function pointer registrations, template references, and macro usages. libclang-powered: detects function-pointer registrations (interrupt vector table writes, callback attachments, ISR handler assignments) 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. limit: Maximum results (default 50, max 200).

Returns: list of dicts, each with: file, line, ref_kind, caller, caller_kind. ref_kind is one of: "call", "ref", "member", "indirect" (function-pointer reference in arguments, assignments, initializers, or init lists), "implicit_construct" (implicit constructor call from global/static object or member-field initialization), "template_ref", "macro_use" (macro usage in file). Macro fallback includes a leading dict with kind="macro", value, and expanded_value.

find_wrapper_callersA

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'. project_root: Project root. Auto-detected if omitted. limit: Maximum wrapper method results (default 50).

Returns: list of dicts, each with: wrapper_class (str), method_count (int), methods (list of dicts — each with method, qualified_name, kind, and calls (list of driver methods called)).

trace_data_flowA

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 functions whose signature mentions type_name, then looks for call paths from those functions 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. max_depth: Maximum call path depth (default 8). limit: Maximum source functions to trace (default 15).

Returns: list of dicts with a leading _summary entry: {_summary (str), _type (str), _target (str)}, followed by source entries each with: source_name, source_qualified_name, source_kind, source_file, source_line, caller_count, reachable (bool), and paths (list of call path dicts — empty when unreachable).

explain_symbolA

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, ModemMsg::send. project_root: Project root directory. Auto-detected if omitted. context_lines: Lines of source context around the symbol definition (default 40, max 200). Only used when no pre-computed analysis exists.

Returns: dict: {name, kind, file, line, signature, explanation, llm_analysis (if pre-computed)}, plus source/explain_prompt on fallback. Macro fallback returns kind="macro", signature (as #define NAME), value (raw definition), and expanded_value.

get_file_mapA

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.

Pass a path relative to the project root (src/main.cpp) or just the filename (main.cpp). 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. signatures: Include full function signatures. Default: False. max_per_kind: Max items per kind group (default 30, 0 = unlimited).

Returns: dict: {file, total_symbols, symbols: {kind: {count, items[], subgroups?[]}}}

get_sourceA

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.

For enums, includes a constants array listing all member constants with their values. For macros, returns kind="macro" with value (raw definition) 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 a normal file read.

Read-only. No side effects.

Args: name: Fully qualified symbol name. Returns exact function body via libclang extent. project_root: Project root. Auto-detected if omitted.

Returns: dict: {name, qualified_name, kind, file, line, signature, docstring, is_definition, is_template, is_virtual, is_pure_virtual, source (str — the function/enum/macro body, truncated at 8000 chars), warning (str, optional — when source file cannot be read)}. May also include template_usr, parent_usr, enum_value, constants (list for enums), value (raw macro definition), expanded_value (preprocessor-resolved macro value) when applicable.

get_symbol_contextA

Rich one-shot context for a C/C++ symbol: body, signature, all 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.

Returns ALL callers and callees including vendor/SDK code — the call graph naturally spans project and vendor boundaries in both directions (project → vendor API, vendor callback → project handler).

Read-only. No side effects.

Args: name: Symbol name. Returns body, signature, all direct callers and callees. project_root: Project root. Auto-detected if omitted.

Returns: dict with: name, qualified_name, kind, file, line, signature, docstring (raw Doxygen comment text), is_definition, callers (list), callees (list), source (body text), indirect_call_sites (list, for field/variable symbols — where the function pointer is actually invoked). For field and variable symbols that have function pointer type, also includes resolution: {assignments_found, call_sites_found, resolved, note} indicating whether assignments and call sites are linked (Phase 3). resolved=False with a note when parts are missing — LLM can detect uncertainty. For enums also returns constants and enum_value. For macros returns kind="macro", value (raw definition), and expanded_value (preprocessor-resolved). When LLM analysis has been generated (fw-context index --analyze), includes llm_analysis: {summary, inputs, outputs, model, analyzed_at} with a structured description of the symbol's purpose, parameters, and return values/side effects.

read_fileA

Read a complete C/C++ source file with ifdef-filtered content — only code that actually compiles for the current build configuration. 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.

For reading a single function body with libclang exact extents use get_source. For body + callers + callees in one call use get_symbol_context. For a structural overview without content use get_file_map. For searching patterns across files use search_content.

Read-only. No side effects. Falls back to raw disk content (with a warning) when the indexed files.content column is empty — e.g. on a legacy index that predates this feature. Run fw-context index to populate the ifdef-filtered content.

Args: file_path: Path relative to project root, or just the filename. E.g. src/main.cpp or main.cpp. project_root: Project root. Auto-detected if omitted.

Returns: dict: {file (str), language (str — "c" or "cpp"), mtime (float), lines (int — total line count), content (str — the complete ifdef-filtered file text), warning (str, optional — when reading from raw disk instead of indexed content)}.

get_class_membersA

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 'zbox::ZMODEM'. project_root: Project root. Auto-detected if omitted.

Returns: dict: {name, qualified_name, kind, file, line, members: {kind: [{name, qualified_name, signature, is_virtual, is_pure_virtual, line}]}, member_count}

get_inheritance_chainA

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 'zbox::ZMODEM'. project_root: Project root. Auto-detected if omitted. 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, clamped to 1–50).

Returns: dict: { name, qualified_name, kind, file, line, bases: [{name, usr, access, is_virtual, file}], derived: [{name, usr, access, is_virtual, file}], all_bases: [...] (when transitive=True, ancestors sorted by depth), all_derived: [...] (when transitive=True, descendants sorted by depth) }

get_method_overridesA

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 which is populated during fw-context index via post-processing of the inheritance graph and virtual method signatures.

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.

Returns: dict: { name, qualified_name, kind, file, line, signature, overrides: [{usr, name, qualified_name, kind, file, line}], overridden_by: [{usr, name, qualified_name, kind, file, line}] }

get_template_instancesA

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)>). The template declaration itself is also returned as the first result when found.

Uses the template_usr column populated during indexing via libclang's cursor.specialized_template.

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. limit: Maximum results (default 50).

Returns: list[dict] with one element wrapping the template declaration: {name, qualified_name, kind, file, line, is_definition, signature, instances (list of dicts, each with name, qualified_name, kind, file, line, signature, is_definition), instance_count (int)}

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription
resource_statsReturn a human-readable markdown summary of all indexed projects. Read-only. Aggregates stats from every project database found under the configured index directory.
resource_projectsReturn project list as a JSON string. Read-only. Uses the same data as ``list_projects``, serialized as indented JSON.
resource_embedded_review_skillReturn the fw-review SKILL.md as an MCP resource. Read-only. Makes the embedded firmware review methodology available to any MCP client via a well-known resource URI.

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