fw-context-mcp
fw-context-mcp is an MCP server that gives AI coding agents build-aware, compiler-derived semantic context for embedded C/C++ firmware projects.
Project & environment discovery — list projects, get project info, check dependency/LLM/environment status, and inspect active build health, index state, variants, memory regions, and entry points.
Configuration & maintenance — configure local LLM/embedding settings, reindex single files, reset/delete the index, and validate the current build configuration.
Symbol lookup & search — exact/prefix symbol lookup, FTS5 search over symbol names/metadata, definition bodies, and full file content (all ifdef-filtered to the active build), plus semantic and natural-language smart search.
Call-graph analysis — direct and transitive callers/callees, call paths between functions, function-pointer assignment resolution, indirect call sites/targets, and all-reference lookup.
Firmware-specific insight — interrupt vector table analysis (handlers, unhandled slots, runtime-installed handlers), dead-code detection, hotspot ranking, wrapper/adapter detection, and data-flow tracing.
Source & symbol context — read ifdef-filtered files or exact function bodies, get rich symbol context (body + callers + callees + LLM analysis), and get plain-English symbol explanations.
C++/OOP awareness — class members, inheritance chains, virtual method overrides, template instantiations, and variable read/write tracing through the call graph.
Allows AI assistants to understand and navigate Arduino firmware codebases by indexing them via compile_commands.json.
Provides optional natural-language search and symbol explanation capabilities by leveraging local LLMs via Ollama.
Allows AI assistants to understand and navigate PlatformIO-based embedded firmware projects.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@fw-context-mcpWhat does modem_parser_oob_init do?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
fw-context
Build-aware code intelligence for 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 produced by the active build configuration.
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
grepand 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.
Related MCP server: Semantic Code Search MCP Server
Quick start
Prerequisites
Python 3.11 or newer
libclang
a project that can produce
compile_commands.jsonan MCP-capable coding agent such as Claude Code or OpenCode
Ollama is optional. It is used only for local semantic enrichment and symbol explanations; the core compiler-derived index does not require it.
Install via pip (recommended)
pip install fw-context-mcpInstall the current source version
git clone https://github.com/turbyho/fw-context-mcp.git ~/.fw-context/src
cd ~/.fw-context/src
make installRegister fw-context with the supported coding agents detected in your project:
cd /path/to/your/firmware
fw-context initBuild and index the firmware:
cd /path/to/your/firmware
fw-context index --buildThen 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 active build
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.
flowchart LR
CCJ[compile_commands.json] & SRC[(source files)] --> LIBCLANG[libclang<br/>AST parser]
LIBCLANG --> SYMBOLS[symbols<br/>name, kind, USR<br/>signature, source body<br/>docstring, tokens] & FILES[files<br/>path, language<br/>ifdef-filtered content<br/>project/SDK sources] & REFS[refs & call graph<br/>fp_assignments<br/>indirect_call_sites] & INHERIT[inheritance<br/>& overrides<br/>virtual dispatch] & MACROS[macros<br/>params, value<br/>& expanded value<br/>FTS5 searchable] & ENRICH[optional enrichment<br/>embeddings & 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.
Available Tools
39 toolscheck_dependenciesA
Run the full dependency audit. Read-only. Returns structured results.
Returns the raw per-check dicts (name, status, message,
fix_cmd, instructions, critical) — NOT the formatted
doctor table. Read status/fix_cmd/instructions per
issue; status="skipped" means a prerequisite is missing.
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, DepCheckResult fields via asdict.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | 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. | |
| project_root | No | Project root. Auto-detected if omitted. Pass explicitly when the project is not the server cwd. This field also accepts a project name or a project_id, but project is the clear field for those. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full burden. It explicitly declares 'Read-only,' describes the exact return shape, explains that 'status="skipped"' indicates a missing prerequisite, and clarifies the raw-versus-formatted result distinction. This is substantial behavioral disclosure, though it stops short of describing error behavior or potential delays.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well organized with a front-loaded summary, a prominent return-format warning, and clear Args/Returns sections. It is concise overall, though there is minor redundancy between the first paragraph listing the dict fields and the Returns section repeating 'DepCheckResult fields via asdict.'
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema exists and both parameters are fully documented in the schema, the description covers the essential additional context: read-only behavior, raw vs. formatted output, status interpretation, and parameter selection. It lacks edge-case guidance (e.g., what happens if both params are provided) but is complete enough for an agent to call it correctly in normal cases.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds useful context about mutual exclusivity ('Give one of the two, not both') and auto-detection of project_root from CWD, but the argument text closely mirrors what is already in the schema. It does not meaningfully compensate beyond the schema, so no higher score is warranted.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Run the full dependency audit.' It adds 'Read-only' and clarifies that it returns raw per-check dicts, not the formatted 'doctor' table, which distinguishes it from potential sibling tools like get_environment_status or check_ollama. The purpose is immediately recognizable and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage context is implied: call this when you need a dependency audit. It gives guidance on choosing between 'project' and 'project_root' and refers to list_projects for project names, but it never explicitly names alternatives or says when NOT to use this tool. No sibling differentiation is provided, so the agent must infer selection from the purpose.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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. 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),
configured_embed_model (str), embedding_installed (bool),
message (str, on error/disabled), model_details (list[dict], when
Ollama running), suggest_cloud (bool), vec_available (bool),
vec_error (str, optional), debug_log (str, optional — only when
debug logging is enabled)}
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | 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. | |
| project_root | No | Project root. Auto-detected if omitted. Used to locate LLM config. Falls back to auto-detection when omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure, and it meets it with 'Read-only: yes. No side effects.' It also exposes the complete status/return behavior, including error/disabled states, external chat API replacement, and conditional fields. It does not mention timeout or network-failure behavior explicitly, but the 'error' status and message field cover that outcome.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose and usage before moving to arguments and return values, which is good structure. The returns block is long but justified because there is no output schema to document the response shape. The only minor redundancy is repeating the schema parameter descriptions nearly verbatim.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description fully compensates for the missing output schema by listing the complete return dict with field types and meanings, including optional/conditional fields. It also documents parameter selection rules, auto-detection, and mutual exclusivity. Nothing essential for invoking check_ollama correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Both parameters are already fully documented in the input schema with 100% coverage, so the description adds little beyond restating the same project_root/project semantics. A baseline of 3 is appropriate because the schema carries the semantic weight and no additional syntax or format details are needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a specific verb ('Check') and resource ('LLM backend... embedding/chat model installed'), which makes the tool's purpose unmistakable. It also names the sibling tools it should precede, helping distinguish it from search/analysis tools. This goes beyond a vague restatement of the tool name.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'Call before smart_search, semantic_search, or explain_symbol' and includes the on-demand fallback condition, which is strong usage guidance. It does not explicitly discuss alternatives like check_dependencies or get_environment_status, so the when-not-to-use guidance is slightly incomplete. Overall, the timing and conditional exception are clear enough for correct agent routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
configure_llmA
Configure LLM settings for 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. After writing, tests the configuration
by making a simple API call (skipped when LLM is disabled).
IMPORTANT: When chat_api_base points to an external host, source
code snippets in chat prompts will be sent to that endpoint. Ensure
this complies with your organization's data security policies.
Consider using local Ollama or an internal API proxy 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. chat_api_base: Chat API URL (see description for format details). chat_api_key: Bearer token for cloud/proxy APIs. chat_api_format: Override auto-detection: "auto", "ollama", "openai". model: Chat model name. embed_model: Embedding model name (Ollama only). auto_pull: Whether to auto-pull models on 404. stream: Stream chat responses via SSE. True avoids reverse-proxy idle timeouts.
Returns: dict: {status ("ok"|"error"), chat_api (dict — configured, endpoint, format, model), model (str), auto_pull (bool), stream (bool), test_latency_s (float, on success), test_response (str, on success), compliance_warning (str, when chat_api_base is external), message (str)}
| Name | Required | Description | Default |
|---|---|---|---|
| model | No | Chat model name. None = keep current. | |
| stream | No | Stream chat responses via SSE (both OpenAI-compatible and Ollama-native). True = send stream:true, consume SSE chunks — avoids reverse-proxy idle timeouts (nginx 60s, Cloudflare 100s). None = keep current setting. | |
| project | No | 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. | |
| auto_pull | No | Auto-pull models on 404 (Ollama only). False for intranet. | |
| embed_model | No | Embedding model name (Ollama only). None = keep current. | |
| chat_api_key | No | API key for cloud/proxy APIs. None for local/no-auth. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. | |
| chat_api_base | No | Chat API URL. None = use local Ollama for chat. Auto-detects format: :11434 or /api/generate -> Ollama, /v1 or bare host -> OpenAI-compatible. Examples: 'https://api.deepseek.com/v1' (DeepSeek), 'http://localhost:4000' (LiteLLM), 'http://localhost:8080/v1' (llama.cpp). WARNING: external URLs send source code to that host. | |
| chat_api_format | No | Format override: 'auto' (default), 'ollama', or 'openai'. | auto |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and meets it: it discloses the write location, that it does NOT modify global/shared config, that it makes a test API call, that the call is skipped when LLM is disabled, and that external chat_api_base URLs send source-code snippets to that host.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured with a clear opening, security warning, Args list, and Returns dict. Despite covering nine parameters, it stays dense and front-loads the most important behavioral facts before the parameter list.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the absence of an output schema and annotations, this is complete: it explains side effects, conditional test behavior, security implications, and the full return dict shape with keys for success/error cases. An agent can invoke it without needing additional context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The Args block is mostly a condensed restatement of the schema's parameter descriptions; it adds a 'Bearer token' qualifier for chat_api_key, but for chat_api_base it even defers to 'description for format details' without including those details in the description body.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific action and resource — 'Configure LLM settings' — and immediately clarifies the precise mutation target: 'Writes to <project>/.fw-context/local.toml ONLY'. It also states what it does not affect, which clearly separates it from the surrounding read/search sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives clear context for when to call it (per-developer LLM configuration) and explicit non-targets (global config, shared config.toml). It also points to list_projects for project IDs and warns to prefer local Ollama/internal proxies; it stops short of naming an alternative configuration tool because none exists among the siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
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: Build variant (multi-build project). Omit to use
default_variant. One query answers for ONE build.
image: Sysbuild image within the variant. Required when the
variant holds several: each image is a separate program.
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
or #define NAME(a, b)), is_function_like, value (the
replacement text ALONE), and expanded_value.
A ``warning`` key means that the local LLM gave no explanation —
the request timed out, or the model is not available. The dict then
holds ``source`` and ``explain_prompt``: read the source, and answer
the prompt yourself.
When the file changed after the last index run, the dict adds
``stale`` (True) and ``stale_warning`` (str). ``stale_warning`` is
separate from ``warning``, which the LLM error paths use. A symbol
that moved gives its indexed body, not the code that now sits at the
stored line number.
An ``ambiguous_warning`` key means that *name* matched more than one
symbol, such as two classes with a method of the same name. This
answer is about ONE of them, and the key names it and lists the
others. Give the full qualified name to ask about one symbol only.
It is separate from ``warning``, which the LLM error paths use.
On failure the dict holds ``error`` with the reason. One failure
carries more than that: when the best match for *name* is in a file
outside the project root, the dict also holds ``candidates``,
``candidates_total`` and a ``hint``. Read them — a common name
matches many symbols, and one of the others is often inside the
project.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Symbol name to explain. E.g. 'uart_init', 'ModemMsg::send'. | |
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. | |
| context_lines | No | Lines of source context around the symbol definition. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so thoroughly. It states 'Read-only. No side effects,' explains the pre-computed versus on-demand LLM fallback, and details warning, stale, ambiguous, failure, and outside-root candidate behaviors.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a clear opening, routing section, Args list, and Returns breakdown. However, it repeats the pre-computed/on-demand fallback sentence twice and restates 'It is separate from warning, which the LLM error paths use' for both stale and ambiguous warnings, so a small amount of tightening was possible.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description must explain return values, and it does so comprehensively: dict keys, macro fallback fields, warning semantics, stale-file markers, ambiguous matches, and failure candidates. For a tool with this behavioral complexity, nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Though schema coverage is 100%, the description adds significant meaning beyond the schema: examples like 'uart_init' and 'ModemMsg::send', auto-detection of project_root, the mutual exclusivity of project and project_root, the conditional use of context_lines, and the per-build semantics of variant.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Explain what a C/C++ symbol does in plain English — libclang-aware analysis.' It distinguishes itself from sibling tools such as lookup_symbol and get_symbol_context by stating that it returns an explanation, not just metadata or raw context.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit routing is provided: 'For raw source code use get_source. For symbol metadata without explanation use lookup_symbol. For body + callers + callees use get_symbol_context.' It also gives concrete parameter guidance, such as when to use project versus project_root and when image is required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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, implicit constructors, and synthetic dispatch 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.
Edge types traversed: Includes call, indirect (function
pointers / ISRs), implicit_construct (constructors reachable through
file-scope global objects), and dispatch (synthetic edges through
event loops and thread starts).
Limitation — ambiguous name resolution: When a source-line fallback
cannot disambiguate which method is called (e.g. attach() matching
both Timeout::attach and SerialBase::attach), the edge is
conservatively omitted to avoid false callers. 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 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: Maximum results (default 50). variant: Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. image: Sysbuild image within the variant. Required when the variant holds several: each image is a separate program.
Returns: list of dicts, each with: name (str — the caller), qualified_name (str), kind (str), signature (str), depth (int — distance from the target), file (str — absolute).
This tool gives no line, because one caller can hold several call
sites. For the line of each call use ``find_callers`` on the name
that this tool reports.
When *name* matches more than one symbol, such as two classes with
a method of the same name, the answer holds the callers of all of
them. A ``warning`` dict then comes first and names the symbols,
and each result carries ``target_qualified_name``, which tells the
symbol that it calls. Give the full qualified name to ask about
one symbol only.
Never empty: one dict with ``error`` (cannot resolve) or ``info``
(no results) replaces the results. Check both keys first.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Symbol name to find transitive callers of. | |
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| limit | No | Maximum results (default 50). | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| max_depth | No | Maximum BFS depth for transitive search (default 5). | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and delivers richly: it discloses read-only/no side effects, BFS traversal, deduplication at shortest distance, the ambiguous-name resolution limitation, the error/info fallback dict, the absence of line numbers and why, and multi-match warning behavior. This goes far beyond a typical tool definition.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Although lengthy, the description is appropriately sized for a complex tool with 7 parameters and multiple edge cases. It is front-loaded with the core purpose and edge types, then flows logically into usage, limitations, parameters, and return format. Each section earns its place with no filler; bold headers and paragraphs improve scannability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite an output schema, the description adds vital context an agent needs: the warning/error/info dict shapes, the no-line-number behavior, deduplication, multi-symbol ambiguity resolution, and build/variant relationships. For a tool with this complexity, nothing essential is left unexplained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds meaningful semantic context beyond the schema: 'Give one of the two, not both' for project/project_root, 'One query answers for ONE build', and 'Required when the variant holds several' for image. It also clarifies auto-detection and qualification nuances. These additions push it above baseline but not to 5 since much of the Args section repeats schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Find all transitive C/C++ callers — who calls *name*, directly or indirectly', and details the traversal through libclang call graphs with specific edge types. It clearly differentiates itself from sibling tools by naming find_callers and find_callees_recursive and stating their different scopes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use the tool: 'Use for impact analysis: if I change this function, how far does the ripple go?' Then gives direct alternatives with conditions: 'For a flat, single-level caller list use find_callers (faster). For the reverse direction use find_callees_recursive.' Also recommends verification tools (search_bodies, find_indirect_targets) for a known limitation. This is model guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_callees_recursiveA
Find all transitive C/C++ callees — what name calls, directly or indirectly, through the libclang call graph including function-pointer edges, implicit constructors, and synthetic dispatch 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.
Edge types traversed: Includes call, indirect (function
pointers / ISRs), implicit_construct (constructors reachable through
file-scope global objects), and dispatch (synthetic edges through
event loops and thread starts).
Limitation — ambiguous name resolution: When a source-line fallback
cannot disambiguate which method is called, the edge is conservatively
omitted to avoid false callees. 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: Maximum results (default 50). variant: Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. image: Sysbuild image within the variant. Required when the variant holds several: each image is a separate program.
Returns: list of dicts, each with: name (str — the callee), qualified_name (str), kind (str), signature (str), depth (int — distance from the source), file (str — absolute).
This tool gives no line, because one function can call the same
callee several times. For the line of each call use
``find_callers`` on the name that this tool reports.
When *name* matches more than one symbol, the answer holds the
callees of all of them. A ``warning`` dict then comes first and
names the symbols, and each result carries
``target_qualified_name``, which tells the symbol that calls it.
Give the full qualified name to ask about one symbol only.
Never empty: one dict with ``error`` (cannot resolve) or ``info``
(no results) replaces the results. Check both keys first.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Symbol name to find transitive callees of. | |
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| limit | No | Maximum results (default 50). | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| max_depth | No | Maximum BFS depth for transitive search (default 5). | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does so thoroughly. It explicitly states 'Read-only. No side effects.', discloses the reference index requirement, details the ambiguous-name resolution limitation, notes deduplication by shortest distance, explains the warning dict for multiple matches, and describes the non-empty return behavior (error/info dicts). It also clarifies why no line is returned. These are rich behavioral disclosures beyond any structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured: purpose first, then usage, edge types, limitation, alternatives, args, returns. It is front-loaded and each section adds necessary detail for a complex tool. However, the Args section largely duplicates the input schema descriptions, adding redundancy that could be trimmed without losing information. Still, the organization earns a high score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 7 parameters, an output schema, and complex edge cases, the description is complete. It covers return value structure, error/info cases, multi-match warnings, depth semantics, and prerequisites. The output schema exists, but the description still explains anticipated edge cases and usage contexts, leaving no important gap for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the Args section repeats the schema descriptions almost verbatim (e.g., project_root, project, max_depth). The description does not add significant semantic value beyond the schema; it clarifies the alternative relationship between project and project_root, but that is already in the schema. Baseline 3 is appropriate because the schema already documents all parameters well.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Find all transitive C/C++ callees — what *name* calls, directly or indirectly'. It specifies the call graph engine (libclang) and edge types, distinguishing it clearly from siblings like find_callers (direct only), get_symbol_context (faster flat list for direct callees), and find_all_callers_recursive (reverse direction).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage guidance: 'Use for dependency analysis: "what does this function depend on to do its job?"' It names alternatives and when to use them: 'For direct callees only, get_symbol_context gives a faster flat list... For the reverse direction use find_all_callers_recursive.' It also advises fallback verification via search_bodies when a missing callee is suspected. This fully covers when-to-use and when-not-to-use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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 = &handlerVariable initializers:
static void (*fp)(int) = &handlerStruct/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.
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 call sites; the page notice names the offset to use.
variant: Build variant (multi-build project). Omit to use
default_variant. One query answers for ONE build.
image: Sysbuild image within the variant. Required when the
variant holds several: each image is a separate program.
Returns:
The page notice first — total, offset, shown, more
— then a dict per call site with: file, line, ref_kind ("call",
"indirect", "implicit_construct", or "macro_use"),
caller (enclosing function name), caller_kind ("function",
"method", …). Macro fallback puts a dict with kind="macro",
signature (#define free: NAME or NAME(a, b)),
is_function_like, value (the replacement text ALONE) and
expanded_value between the notice and the rows;
that answer pages too, and its total counts the uses in active
code only — a use inside a comment is not one.
When *name* matches more than one symbol, such as two classes with
a method of the same name, the answer holds the call sites of all
of them. A ``warning`` dict then comes first and names the
symbols, and each result carries ``target_qualified_name``. Give
the full qualified name to ask about one symbol only.
A virtual method with no call site of its own answers with the
call sites of the methods that override the same base method.
Those rows reach a PEER and not the symbol you named, and the page
notice counts them, thus a ``warning`` dict always leads such an
answer and says so. Read it before you report a caller count.
Never empty: one dict with ``error`` (symbol not resolved) or
``info`` (no references of this kind). Check both keys first.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Symbol name to find callers of. Returns direct call sites and indirect calls via function pointers. | |
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| limit | No | Maximum results of one page (default 50, max 200). | |
| offset | No | Skip this many results. Reads the next page of a symbol with many call sites. | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does so thoroughly: read-only/no side effects, index requirement, macro fallback behavior, pagination format, ambiguity warnings, virtual-method override behavior, and the never-empty error/info contract are all disclosed. This goes far beyond the structured fields and gives the agent a reliable model of what happens.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear sections and bullet-like formatting. Nearly every sentence earns its place given the complexity of the tool, though some repetition of schema parameter details could be trimmed. Front-loading the core purpose and usage guidance is effective.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite an output schema being present, the description adds a detailed Returns section covering pagination, macro results, ambiguity warnings, and virtual-method callers. It also documents the never-empty error/info contract. For a tool with this behavioral complexity and seven parameters, nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds meaningful extra context beyond the schema: the three-tier name resolution, the pagination notice naming the offset, the project vs project_root relationship, and the multi-build variant/image distinctions. It does not merely repeat the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource ('Find who calls a C/C++ function') and immediately distinguishes direct vs. indirect calls, explicitly naming sibling tools for other needs. This lets an agent separate find_callers from find_references, find_call_path, and find_all_callers_recursive without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit when-to-use guidance ('Use when you need a quick, flat list of immediate callers') and names the alternatives for transitive calls, all references, and path finding. It also states requirements such as the reference index and the one-hop limitation, leaving no ambiguity about when this tool is the right choice.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_call_pathA
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 synthetic dispatch edges (event loops, thread 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
shortest paths, 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), implicit_construct (global/static
object constructors), and dispatch (synthetic edges through event
loops like EventQueue::dispatch_forever and thread starts like
Thread::start).
Limitations:
Dispatch bridges: callbacks registered through
EventQueue::call_every,k_work_submit, orxTimerStartreach their dispatch entry point (dispatch_forever,z_work_q_main) through a built-in map for mbed-os, Zephyr, and FreeRTOS. Add other RTOS patterns in[call_graph.dispatch_bridges](.fw-context/config.toml); a bridge whose entry symbol is not in the index is skipped silently.Ambiguous fallback names: for a call that libclang cannot resolve (template-obscured
_timeout.attach(...)), a source-line regex matches the method name. When several methods share that unqualified name and neither the receiver field type nor the caller class disambiguates, fw-context creates NO edge — conservative, to avoid false paths.Global constructors: file-scope
implicit_constructedges hang off a synthetic<global ctors>node betweenmainand every global constructor. Any query that can reachmainuses it, not only a query that starts atmain.
On an empty result that you expected to hold a path: look for async
dispatch (search_bodies("call_every"), search_bodies("attach")),
trace the intermediate symbols with find_callers, raise
max_depth, and check the function-pointer wiring with
find_indirect_call_sites / find_indirect_targets.
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. 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 path search (default 10). No clamp holds this number. What bounds a deep search is the node budget of the walk — 5000 expansions — thus a large depth gives up on that budget and not on the depth. variant: Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. image: Sysbuild image within the variant. Required when the variant holds several: each image is a separate program.
Returns:
At most 5 paths, each a dict with: depth (edge count, int), chain (str —
e.g. "main → app_run → modem_init"), target_usr (str — the USR
of the symbol the path ends at, which tells two overloads apart).
When no path exists within the depth limit, the list holds one
info dict.
When *to_name* matches more than one symbol, the search reaches
all of them. A ``warning`` dict then comes first and names the
symbols, and each path carries ``target_qualified_name`` next to
``target_usr``. Give the full qualified name to ask about one
symbol only.
Never empty: one dict with ``error`` (cannot resolve) or ``info``
(no results) replaces the results. Check both keys first.
| Name | Required | Description | Default |
|---|---|---|---|
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| project | No | 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. | |
| to_name | Yes | Target symbol to find path to. | |
| variant | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| from_name | Yes | Starting symbol for path search. | |
| max_depth | No | Maximum BFS depth for path search (default 10). | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses read-only status, no side effects, and prerequisites (symbols in index, refs enabled). It details limitations (dispatch bridge skipping, ambiguous fallback name conservatism, global constructor synthetic node) and explains the node-budget behavior of max_depth. This is far beyond typical descriptions and leaves no critical behavioral ambiguity.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is lengthy but logically structured with headers (Edge types, Limitations, empty-result guidance, alternatives, args). Every section adds necessary detail for a complex tool. It is front-loaded with the core purpose and returns structure, and while a bit long, it is not bloated; each sentence earns its place. Slightly trimmed could earn a 5, but this is still strong.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description fully covers the return format (at most 5 paths, each with depth, chain, target_usr; warning and info dicts; never empty) and edge cases (overloaded symbols, ambiguous names). It also includes troubleshooting guidance, prerequisites, and limitations. For a tool with 7 parameters and no annotations, this is remarkably complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Even though schema coverage is 100%, the description adds substantial meaning: max_depth's lack of clamping and its interaction with the 5000-expansion node budget, project vs. project_root as mutual alternatives, image required when variant holds multiple images, and the note that one query answers for one build. These nuances are not in the schema and materially improve invocation correctness.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise verb+resource statement: 'Find call paths between two C/C++ functions via BFS in the libclang call graph.' It names the specific edge types (function pointers, ISRs, implicit constructors, dispatch) and contrasts with siblings like find_all_callers_recursive and find_callees_recursive, making the tool's unique scope unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states the intended use case ('how does A reach B?') and gives a concrete example. It also names alternatives for one-sided exploration (find_all_callers_recursive, find_callees_recursive) and exact verification (find_callers, find_references), and includes troubleshooting steps for empty results. This is exemplary when-to-use vs. when-not-to guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
What "dead" means: zero references in the index — no call, no
function-pointer assignment, no indirect call site. 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 (Phase 1ref_kind="indirect"), but no call site through that pointer resolved (Phase 3). Unindexed code or a type-erased API can still call it. Treat it as uncertain, and check each hit withfind_indirect_targetsbefore you delete anything.
fw-context detects a constructor call through global/static object and
member-field initialization as an implicit_construct reference.
Known false positives remain: constructors from factories, ISRs,
virtual method overrides, and weak-aliased symbols. Always verify
before you delete.
project_only=True (default) excludes the SDK and vendor paths
through the is_project column, which follows the vendor_paths
and project_paths config. Set project_only=False to see the
vendor results too.
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: Maximum results of one page (default 100, max 200).
offset: Skip this many results. Reads the next page; the page
notice names the offset to use.
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.
variant: Build variant (multi-build project). Omit to use
default_variant. One query answers for ONE build.
image: Sysbuild image within the variant. Required when the
variant holds several: each image is a separate program.
Returns:
list of dicts, each with: name, qualified_name, kind, signature,
file (str — absolute), line, status ("dead" or
"possibly_dead"), and reason (str — explains why the function
is classified as dead or possibly dead).
Never empty: one dict with ``info`` replaces an empty result.
Check that key first.
| Name | Required | Description | Default |
|---|---|---|---|
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| limit | No | Maximum results of one page (default 100, max 200). | |
| offset | No | Skip this many results. Reads the next page of a long report. | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| project_only | No | When True (default), auto-excludes SDK/vendor paths based on the detected build system and applies project config exclude_paths. Set False to see all results. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. | |
| exclude_paths | No | Additional LIKE patterns to exclude. Merged with defaults from config. E.g. ['lib/%']. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and succeeds: it states 'Read-only. No side effects', requires the reference index, defines the two statuses, and discloses known false positives and the single-layer non-reachability limitation. This is far beyond what structured annotations would provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized with bold headings, clear bullets, and front-loaded purpose. It is somewhat long and the Args section largely duplicates the input schema, but the tool is complex enough that the extra caveats and status semantics earn most of their place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex tool with no annotations, the description is remarkably complete: it covers output shape, the never-empty info replacement, prerequisites, read-only behavior, filtering semantics, pagination, and false positives. Nothing needed for safe invocation is materially missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds some genuinely useful clarifications beyond the schema: project_root and project are mutually exclusive, offset pagination references a page notice, and exclude_paths is a user-supplied parameter rather than config. These additions justify a small bump above baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Find C/C++ functions that are defined but never called', and frames the tool as global, index-based dead code detection. It also distinguishes itself from text-based search and names related siblings like find_callees_recursive and find_indirect_targets, so an agent can select it correctly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells the agent when to use this tool versus alternatives: for transitive reachability it should use find_callees_recursive, and for possibly_dead hits it should verify with find_indirect_targets. It also explains that text-based search cannot determine actual reachability, which is a strong when/why signal.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
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: Build variant (multi-build project). Omit to use
default_variant. One query answers for ONE build.
image: Sysbuild image within the variant. Required when the
variant holds several: each image is a separate program.
Returns: list of dicts, each with: name, qualified_name, kind, signature, file (str — absolute), line, caller_count (int — total number of call sites).
Never empty: one dict with ``info`` replaces an empty result.
Check that key first.
| Name | Required | Description | Default |
|---|---|---|---|
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| limit | No | Number of top-called functions per page (default 20, max 50). | |
| offset | No | Skip this many results. Reads further down the ranking. | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| project_only | No | When True (default), auto-excludes SDK/vendor paths so hotspots reflect project code. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. | |
| exclude_paths | No | Additional LIKE patterns to exclude. Merged with defaults. E.g. ['lib/%']. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full disclosure burden. It explicitly says 'Read-only. No side effects.', declares the reference index requirement, reveals the never-empty 'info' sentinel, and warns that one query answers for one build. These are substantive behavioral disclosures beyond the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but logically structured: purpose, usage, parameters, return format. It front-loads the main purpose and keeps related caveats in the parameter/return sections. Some repetition exists ('architectural weight' twice), but every block earns its place for a complex tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 8-parameter tool with no annotations, this description is unusually complete: it covers prerequisites, defaults, output shape, the empty-result sentinel, build/variant specifics, and follow-up paths. An agent has everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description mostly repeats schema text, adding minor context like the page-notice offset hint and the project/project_root mutual exclusivity. It confirms the schema but does not meaningfully extend parameter meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Find the most-called C/C++ functions ranked by caller count' and names the mechanism (libclang call-graph hotspot detection). It clearly distinguishes this from Text-based search and from sibling tools like find_callers, making selection unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states the intended use ('high-level impact assessment'), notes that text search cannot aggregate caller stats, and gives concrete follow-up alternatives (find_callers, find_all_callers_recursive). It does not enumerate all negative cases for every sibling, but the usage context is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
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).
variant: Build variant (multi-build project). Omit to use
default_variant. One query answers for ONE build.
image: Sysbuild image within the variant. Required when the
variant holds several: each image is a separate program.
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.
Never empty: one dict with ``error`` (cannot resolve) or ``info``
(no results) replaces the results. Check both keys first.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Name of the function pointer field or variable to find call sites of. E.g. 'onData' finds all calls through Driver::onData. | |
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| limit | No | Maximum results (default 50). | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| project_root | No | Project root directory. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are present, so the description carries the full burden. It discloses that the tool is read-only with no side effects, explains the libclang-backed mechanism and its limitation versus text search, and reveals the non-obvious return contract: results are never empty and may contain an `error` or `info` key that must be checked.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every sentence earns its place: purpose, examples, sibling differentiation, prerequisites, parameter semantics, and return format are each addressed without fluff or repetition. The most critical scoping information is front-loaded before the parameter details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (6 parameters, output schema, cross-tool distinctions), the description is remarkably complete. It covers prerequisites, parameter alternatives, error behavior, return dict fields, and expected usage, leaving no obvious gap an agent would need to guess about.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the schema already documents all parameters (100% coverage), the description adds substantial meaning: the three-tier resolution strategy for `name`, the mutual-exclusivity rule for `project` vs `project_root`, the note that one query answers for ONE build for `variant`, the per-image program semantics for `image`, and the maximum limit of 200. These details go well beyond the schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise verb+resource: 'Find indirect call sites where a C/C++ function pointer field or variable is invoked.' It further clarifies with concrete examples like `driver.onData(buf, len)` and explicitly differentiates this tool from `find_callers` and `find_references`, so an agent can immediately tell them apart.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states exactly when to use the tool ('where is this function pointer invoked?') and when not to, naming the alternatives: `find_callers` for 'who calls this function?' and `find_references` for 'where is this symbol read or assigned?'. It also directs the reverse query to `find_indirect_targets` and notes the prerequisite of the reference index.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
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).
variant: Build variant (multi-build project). Omit to use
default_variant. One query answers for ONE build.
image: Sysbuild image within the variant. Required when the
variant holds several: each image is a separate program.
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.
An entry can carry ``_note`` (str) when fw-context cannot resolve
the direct call site — the callee is template-obscured, or the call
site comes from the type-based fallback. Read that note before you
act on ``call_file`` and ``call_line``.
Never empty: one dict with ``error`` (cannot resolve) or ``info``
(no results) replaces the results. Check both keys first.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Name of the function pointer field, variable, or parameter. E.g. 'onData' — returns functions assigned to Driver::onData. | |
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| limit | No | Maximum results (default 50, max 200). | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden. It discloses read-only/no side effects, the reference-index requirement, null call_file/call_line for assignments without call sites, fallback notes via _note for template-obscured callees, and the never-empty error/info result convention. This is unusually transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well structured: a front-loaded purpose, followed by usage/parameter notes, then return semantics. Almost every sentence earns its place, though some redundancy exists (e.g. 'no side effects' vs 'read-only') and the return-list detail is extensive given an output schema exists.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex tool with no annotations, six parameters, and rich output semantics, the description is complete. It covers purpose, prerequisites, parameter relationships, output shape, special cases, error handling, and the reverse sibling tool. Nothing needed for correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents each parameter well. The description adds extra meaning beyond the schema: 'Uses three-tier resolution' for name, 'One query answers for ONE build' for variant, and the exclusive-alternative rule for project vs project_root. That pushes it above the baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Find functions assigned to a C/C++ function pointer field or variable'), explains the libclang/USR mechanism, and explicitly distinguishes itself from the sibling find_indirect_call_sites by naming the reverse query. An agent can tell exactly what this tool does compared to nearby tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear conditions: it uses the reference index, handles the reverse case by pointing to find_indirect_call_sites, and explains why text-based search cannot resolve these relations. Parameter guidance such as 'Give one of the two, not both' for project and project_root further clarifies when to use which alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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. 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: Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. image: Sysbuild image within the variant. Required when the variant holds several: each image is a separate program.
Returns:
The page notice first — total, offset, shown, more
— then a dict per reference 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), "macro_use" (macro usage
in file). Macro fallback puts a dict with kind="macro",
signature (NAME or NAME(a, b)), is_function_like,
value (the replacement text ALONE) and expanded_value
between the notice and the rows;
that answer pages too, and its total counts the uses in active
code only — a use inside a comment is not one.
When *name* matches more than one symbol, the answer holds the
references of all of them. A ``warning`` dict then comes first and
names the symbols, and each result carries
``target_qualified_name``. Give the full qualified name to ask
about one symbol only.
A virtual method with no reference of its own answers with the
references of the methods that override the same base method.
Those rows reach a PEER and not the symbol you named, and the page
notice counts them, thus a ``warning`` dict always leads such an
answer and says so. Read it before you report a reference count.
Never empty: one dict with ``error`` (symbol not resolved) or
``info`` (no references). Check both keys first.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Symbol name to find all references of — calls, reads, member accesses. | |
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| limit | No | Maximum results of one page. | |
| offset | No | Skip this many results. Reads the next page of a symbol with many references. | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden — and it does so thoroughly. It states 'Read-only. No side effects,' discloses the macro fallback, multi-symbol warnings, virtual-method peer behavior, paging semantics, and the always-nonempty error/info response. These are exactly the behavioral traits an agent needs to invoke and interpret the tool safely.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear sections for purpose, args, returns, and warnings. Some redundancy exists between the opening list of reference kinds and the later 'including call sites, variable reads...' sentence, so it is not maximally tight. Still, nearly every sentence carries operational value for a complex tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 7 parametersaint, no annotations, and an output schema, the description is remarkably complete. It covers required inputs, optional project selection, paging, all return shapes, ref_kind enumerations, macro fallback, ambiguity handling, virtual-method behavior, and error/info cases. An agent has enough context to call this correctly in almost any scenario.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3 even with no additional parameter info. The description does add a few useful details beyond the schema: limit has a documented max of 200, offset's page-notice mechanism is explained, and the project/project_root exclusivity is reinforced. Much of the Args section repeats schema text, which prevents a 5, but the added mechanics elevate it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource: 'Find ALL references to a C/C++ symbol.' It enumerates covered reference kinds (calls, reads, member accesses, function-pointer registrations, template references, macro usages), which distinguishes it from sibling tools like find_callers or find_variables. The libclang-powered distinction also clarifies why it goes beyond text search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly routes usage: '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.' It also explains when fallback macro lookup occurs, when to pass project vs project_root, and when image is required. This leaves little to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_variablesA
Find C/C++ variables by name or prefix 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 showing
every function that reads or writes the variable — the same
ref_kind values as find_references ("call", "ref",
"member").
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 prefix to search. Uses LIKE match
(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 alternative to project_root, which takes a root
path. Give one of the two, not both.
kind: Optional kind filter — "varglobal", "varlocal",
"field", or None (all). Default None. The legacy
"variable" is also accepted, for an index made before the
kind was split.
limit: Maximum results (default 20, max 100).
variant: Build variant (multi-build project). Omit to use
default_variant. One query answers for ONE build.
image: Sysbuild image within the variant. Required when the
variant holds several: each image is a separate program.
Returns:
list of dicts, each with: name (str), qualified_name (str),
kind (str — "varglobal", "varlocal", "field", or
"variable" on an index made before the kind was split),
file (str),
line (int), signature (str — e.g. "const IPAddress modbus_ip"),
enclosing_function (str — function name for varlocal,
"<file scope>" for varglobal), enclosing_class (str — class
name for static members, empty otherwise),
references (list[dict] — function, file, line,
ref_kind).
No match gives ``[]``. One dict with ``error`` means the query
failed — check that key first.
A ``warning`` key marks a partial result.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Filter by kind: 'varglobal', 'varlocal', 'field', or None for all. | |
| name | Yes | Variable name or prefix to search. Uses LIKE match (e.g. 'g_' finds g_debug_level, g_state). | |
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| limit | No | Maximum results (default 20, max 100). | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description fully carries the behavioral burden. It discloses that the tool is 'Read-only. No side effects,' explains legacy index handling, the global/local split, error and warning keys, and the reference list format. This is unusually complete behavioral disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but the tool is complex with 7 parameters and non-obvious return semantics. It is well organized with distinct sections for intro, usage, args, and returns. Some repetition exists between the Args section and the input schema, but the additional context earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers all essential calling context: matching behavior, kind filtering, project selection, build variant/image constraints, error/empty-result handling, and return shape. Even with no annotations and a large sibling list, an agent has enough information to decide when and how to call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds useful meaning beyond the schema: it documents that the legacy kind 'variable' is also accepted, emphasizes the project/project_root exclusivity, and explains the one-query-per-build behavior for variant/image. These extras justify a small uplift.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Find C/C++ variables by name or prefix and trace who reads or writes them through the call graph.' It clearly distinguishes itself from siblings like find_references, search_code, and lookup_symbol by stating its variable-tracing scope and its global/local split.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to use it ('Use when you need to understand shared state, find who modifies a global variable...') and names alternatives with conditions ('For general symbol search use search_code or lookup_symbol', 'For all references... use find_references'). It also explains the local-variable niche versus search_code in detail.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
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 method results (default 50, max 50).
variant: Build variant (multi-build project). Omit to use
default_variant. One query answers for ONE build.
image: Sysbuild image within the variant. Required when the
variant holds several: each image is a separate program.
Returns:
list of dicts, each with: wrapper_class (str — "(global)" for a
free function), method_count (int),
methods (list of dicts — each with method, qualified_name, kind,
file (str — absolute path of the file that holds the body of that
method), and calls (list of dicts — driver_method (str) and
line (int) of each call into the driver))).
The path sits on the method, not on the class, because one wrapper
class often spans several files.
Never empty: one dict with ``error`` (cannot resolve) or ``info``
(no results) replaces the results. Check both keys first.
| Name | Required | Description | Default |
|---|---|---|---|
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| limit | No | Maximum wrapper method results (default 50, max 50). | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| class_name | Yes | Driver class name to find wrappers for. E.g. 'UART_DRIVER' or 'hal::UART_DRIVER'. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses read-only behavior ('Read-only. No side effects.'), the requirement for the reference index, the non-empty result contract (error/info dicts replace results), and the rationale for path placement on methods rather than classes. It doesn't mention rate limits or failure modes beyond the error key, but the disclosed behaviors are substantial and useful.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections: purpose, example, return format, and usage notes. It is longer than minimal but every section earns its place — the return format detail is essential for a tool with a complex nested output. The front-loading of purpose and the sibling routing early in the text is effective. Slight redundancy exists ('adapter pattern detection' and 'adapter/wrapper architecture' are repeated), but it's not wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has 6 parameters, a complex nested output schema, and no annotations. The description covers the tool's purpose, prerequisites, parameter selection guidance, return structure, and edge-case behavior (error/info dicts). The output schema exists, so the description doesn't need to explain every field, but it adds the critical 'path sits on the method, not on the class' insight and the 'never empty' contract. Nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds value by explaining the relationship between project and project_root ('alternative to project_root... Give one of the two, not both'), clarifying that variant answers for ONE build, and giving concrete examples for class_name. The limit's max is already in the schema, but the description reinforces it. This exceeds the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Find C/C++ wrapper classes that call methods of a driver class' and immediately distinguishes it from text-based search and sibling tools. It names the exact pattern (adapter detection) and gives a concrete example (UART wraps UART_DRIVER), making the tool's purpose unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to use this tool vs alternatives: 'For the reverse perspective — finding who calls a specific driver method — use find_callers. For class member listing use get_class_members.' It also states the prerequisite (requires the reference index) and explains why text-based search is insufficient. This is exemplary routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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, and it spawns no subprocess — the startup daemon thread and the file watcher own the background reindex.
Act on status:
"ready"— up to date. Continue."reindexing"— background reindex running; queries stay accurate. Continue.reindex_progressholds its last log line."reindex_needed"— schema mismatch, an old row format, changed compile_commands.json, or a source file that compile_commands.json does not cover. Queries still work on existing data. Readreindex_reasons: a missing source file needsfw-context index --build, the others need onlyfw-context index.Read
bg_reindex_runningbefore you name any command here. A run already under way does the work, thus a second one only waits on the same lock, andindex_messageand the branch reason both say so. That field covers a run of the daemon AND a run the operator started — the arguments of neither are readable, thus a reason that needs--buildcan outlive a run without it. This status wins over"reindexing"deliberately: the answers of this moment come from the rows of the last FINISHED run."no_index"— initialized, never indexed. Runfw-context index."not_initialized"— runfw-context init.
A failure sets NO status. DB corruption, or no access to the
index, gives a dict that holds error alone. Read that key first:
a reader that waits for status == "error" waits for a value this
tool does not produce.
Four conditions set reindex_needed: an outdated schema, an outdated
ROW FORMAT, a changed compile_commands.json, and a source file that is
on disk but absent from compile_commands.json. The last one needs a
build, because only the build system writes that file — a plain reindex
has no translation unit for the file and skips it without a word.
Modified source files are something else: they are handled per-query,
and never set it.
row_format_mismatch means that the same columns hold text with an
older meaning. Take it seriously: an index written before
fw-context-rows/1 keeps every inactive #ifdef branch, thus a
body or a file from it can show code that the compiler never sees. An
index written before fw-context-rows/3 is wrong the other way: it
ANSWERS LESS than it should. A definition that begins and ends on one
line has no stored body there, thus search_bodies cannot reach an
inline accessor; no macro is marked function-like; and no instance links
to its template, thus get_template_instances gives an empty list for
every template. Each of those looks like a legitimate empty answer.
The value of a macro there also holds its parameter list glued to
its replacement text, thus neither can be read out of it.
client_restart_required is the OPPOSITE case, and no command repairs
it. The index carries a NEWER row format than this server process
reads, thus the index is the correct one and this process is the old
reader. A reindex makes it worse than useless: the indexer writes the
same new format again, and the message comes back over an index that had
nothing wrong with it. status therefore stays "ready" and
reindex_needed stays False — every query keeps working.
Do NOT run a reindex for this field. Tell the operator to restart the
LLM client — Claude Code, opencode, or whichever one is in use. The MCP
server is a child process of that client, thus nobody can restart the
server by itself. client_restart_reason holds the wording, and
index_message opens with it.
indexed_at and first_indexed_at are UTC; file mtimes are local
time. Never compare the two directly — in UTC+2 a correctly indexed
file looks 2 hours newer than indexed_at. Call with fast=False
to find modified files.
analysis splits the LLM-analysis coverage into project and vendor
symbols:
model— the model of the analysis, or None. One model only, even when several were used.analyze_vendor— the value at index time, not the current config.project/vendor—{analyzed, skipped, total}.skipped= tried, but not analyzable (body larger than the model context, an unparseable answer, or a body that was not readable).complete— no work left: every project symbol is analyzed or skipped. True exactly whenreindex_reasonsholds no "unanalyzed symbols" entry. Vendor symbols excluded byanalyze_vendor=Falsenever block it, thusvendor.totallarge withvendor.analyzed=0is expected, not a defect.
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.
fast: When True (default), the header check reuses the cached
manifest hashes. Both modes run the per-file scan, thus
modified_files_count is accurate either way — a tool that
reported "ready" while the search tools warned about the same
file gave the caller two readings and no way to choose.
False recomputes the header hashes and costs several times more.
Returns:
dict: {config_hash, project_id, project_root, build_system,
compile_commands, indexed_at (str — "YYYY-MM-DD HH:MM:SS" in UTC,
the completion time of the last full index), symbol_count, file_count,
reference_count, modified_files_count (int — files whose content no
longer matches the index; counted in both modes),
header_affected_tus (int — number of TUs with stale header
dependencies), manifest_verification (str —
"full" when manifest.json exists, "none" otherwise),
analysis (dict — LLM-analysis coverage split by project/vendor:
{model, analyze_vendor, project: {analyzed, skipped, total},
vendor: {analyzed, skipped, total}, complete}),
description (str), first_indexed_at (str — UTC, same format as
indexed_at),
vendor_paths (list[str] — config index.vendor_paths),
project_paths (list[str] — config index.project_paths),
effective_vendor_patterns (list[str] — the SQL LIKE patterns that
this build really used to mark vendor code, for example
["mbed-os/%"]; empty when the manifest cannot be read. The two
lists above hold what the config asks for, this one what the index
did),
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"|"not_initialized"; a failure sets no
status and gives error alone), reindex_needed (bool —
structural mismatch requiring a full reindex),
reindex_reasons (list[str] — why reindex is needed, empty when False.
One of them asks for fw-context index --build rather than a plain
reindex: when the tree is on a different branch than the index,
compile_commands.json belongs to the OLD branch and carries its file
list and its compiler flags, so only a build regenerates it. Read
the reason text — it names the command it needs),
stale (bool — True when reindex_needed or header_affected_tus > 0),
_warning (str, optional — when manifest verification is not "full"),
vec_available (bool), vec_error (str, optional),
index_message (str — human-readable summary of index state),
multi (bool — True for a multi-variant project),
variants (list[dict] — {name, description, board}),
images (list[dict] — {name, description, dir, type}),
variant_images (dict — variant name to its image names),
active_variant (str or None — [build] default_variant),
active_image (str or None — [build] default_image),
entry_point (str — the ENTRY() of the linker script of the build
that the other fields describe, empty when no script names one),
memory (list[dict] — the MEMORY regions of that build:
{name, attributes, origin, length, origin_value, length_value,
file_path, line})}
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)`. The end of a region is
``origin_value + length_value``.
``memory`` and ``entry_point`` describe ONE build. For a
multi-variant project they follow ``config_hash``, which is the
build named by ``[build] default_variant``, and both are empty when
the config names no default. Use ``list_variants`` for the map of
every build.
``memory`` is empty for a build system that records no linker
script. A PlatformIO project is the measured case: SCons writes no
ninja file and no link command the index can read, and the map file
never names the script. An empty list means "not recorded", never
"no memory".
``defines`` (dict — the `-D` flags of that build) and
``defines_varying`` (int). ``defines`` holds only the names that
EVERY translation unit of the build carries with the same value, so
the tool never shows the defines of one file as the defines of the
build. ``defines_varying`` counts the names left out, thus a name
absent from ``defines`` is either not defined at all or not defined
everywhere — measured on the Mbed project: 27 names in all 881 units, 59
in only some, where the three assembly files get a shorter set.
This is the configuration the BUILD states, not every macro the
preprocessor saw. The second is three orders of magnitude larger —
27800 distinct names on the STM32 project — and almost all of it comes from the
headers and the compiler. A Zephyr build keeps its real
configuration in ``autoconf.h`` (740 `CONFIG_*` names) and passes
few `-D` flags, so ``defines`` says little there and a great deal on
an mbed build, where it holds `APPLICATION_ADDR`,
`APPLICATION_SIZE`, and `CMSIS_VECTAB_VIRTUAL`.
For a project that is not initialized, the result holds only
``status``, ``project_root``, and ``index_message``. When no index
exists, the result adds ``project_id``.
| Name | Required | Description | Default |
|---|---|---|---|
| fast | No | When True (default), reuse the cached manifest hashes for the header check. Both modes count modified files. Pass False to recompute the header hashes, which is far slower. | |
| project | No | 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. | |
| project_root | No | Project root directory. Auto-detected from CWD if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full burden — and it discloses far beyond a typical definition: read-only and spawns no subprocess, the failure case sets NO status and returns error alone (explicitly warning a reader not to wait for status == 'error'), UTC-vs-local-time comparison traps, the row_format_mismatch semantics, and the meaning of empty memory lists ('not recorded, never no memory'). Nothing about behavior is hidden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Excellent front-loading — the purpose, role, and read-only/spawns-no-subprocess facts come first, and the status decision tree is the second block. The Returns section is clearly labeled and organized. However, the description is extremely long (several thousand words) with some redundancy, such as the 'Four conditions set reindex_needed' paragraph restating the status section, and the verbose defines/assembly-file measurement aside. Almost everything is substantive, but it is heavier than strictly necessary.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and a very rich return value, the description carries the full burden of documenting results, and it does so exhaustively: every status value, the error-only dict, the memory region origin/length semantics, the defines scope caveat, and the reduced result shape for uninitialized projects. Nothing an agent needs to interpret a response is left unexplained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema descriptions are already detailed, so baseline is 3. The description adds genuine value beyond the schema: the mutual-exclusivity rule ('Give one of the two, not both' for project vs project_root) and the correctness guarantee that modified_files_count is accurate in both fast modes. That interaction-level semantics pushes it above baseline, though not dramatically.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb-resource pair ('Return metadata about the most recently indexed build configuration') and adds an explicit role marker ('MANDATORY FIRST CALL... check index health before using any other fw-context tools'). This immediately distinguishes it from every sibling search/query tool and states what it is not (a search or mutation tool).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides exhaustive when-to-use guidance: it is the mandatory first call, and it gives a full decision tree on the status field — what command to run for 'no_index', 'not_initialized', and each 'reindex_needed' reason, plus explicit do-NOT guidance ('Do NOT run a reindex' for client_restart_required). It names sibling alternatives (list_projects, list_variants) for adjacent needs and tells when to pass fast=False.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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
'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.
variant: Build variant (multi-build project). Omit to use
default_variant. One query answers for ONE build.
image: Sysbuild image within the variant. Required when the
variant holds several: each image is a separate program.
Returns: dict: {name, qualified_name, kind, file, line, members: {kind: [{name, qualified_name, signature, is_virtual, is_pure_virtual, line}]}, member_count}
On failure the dict holds only ``error`` with the reason.
| Name | Required | Description | Default |
|---|---|---|---|
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| class_name | Yes | Class or struct name. E.g. 'ModemManager' or 'the Mbed project::ZMODEM'. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It states 'Read-only. No side effects.' and describes the return dict structure including an error field on failure. It also mentions that members are grouped by kind, which is a behavioral trait. However, it doesn't explicitly state what happens for a class that doesn't exist beyond the generic error, nor does it address potential size or performance considerations, so it's not fully exhaustive but quite transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than a simple one-liner but is well-structured with clear sections: purpose, grouping behavior, alternatives, arguments, and return format. It front-loads the core purpose and then provides necessary detail without redundancy. Each sentence earns its place, making it appropriately sized for a tool with 5 parameters and a nested return structure.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the return schema explicitly, including the error case, and explains the grouping logic. It also provides routing to sibling tools for different needs. Given that there is no output schema, the description fully compensates by detailing the dict structure. For a C/C++ codebase tool with this complexity, nothing essential is missing for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides descriptions for all parameters (100% coverage), so the baseline is 3. The description goes beyond by giving concrete examples for class_name, explaining the project vs project_root relationship with 'Give one of the two, not both,' and clarifying that variant and image are for multi-build projects. This adds meaningful usage semantics that the schema alone doesn't convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Return all methods, fields, and nested types of a C/C++ class/struct'. It clearly distinguishes itself from siblings by naming alternatives like get_inheritance_chain and get_symbol_context, and clarifies it works for C structs too. This leaves no ambiguity about what the tool does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use alternative tools: 'For inheritance hierarchy use get_inheritance_chain. For individual method details use get_symbol_context.' It also notes the tool works for C structs, implying when it is appropriate. It gives clear context and exclusions, so an agent knows when to pick this tool over others.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_environment_statusA
Return the complete project environment status in one call.
Read-only. Aggregates five domains into a single call so the LLM can see everything at session start without extra round-trips:
deps— dependency audit (run_full_check), each entry with an optionalaction(message+ shellcommand).status="skipped"means a prerequisite is missing (e.g.libclang-soskipped becauselibclang-pythonis absent) — not a failure.build_system— detected build system,Nonewhen unknown.compile_db— whether compile_commands.json exists and its entry count. Reported as{"exists": false, ...}before init (no config to resolve the path from, and loading one would create empty config files).index— the FULLget_active_build()result, unchanged (its action lives inindex_message).llm— LLM backend status with an optionalaction.
When the project is not initialized (index.status == "not_initialized"),
only the config-independent dependency subset runs (checks that do not need
a project config) — Ollama/model/db/build checks are skipped.
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:
dict: {init_status (str — "initialized" or "not_initialized"),
deps (list[dict] — name, status, message, and an optional action),
build_system (str or None),
compile_db (dict — {exists (bool), path (str or None),
entry_count (int or None — None before init, and when fw-context
cannot read the file)}),
index (dict — the full get_active_build result),
llm (dict — {enabled, ollama_running, chat_model, embed_model}, plus
ollama_enabled when the LLM check ran, plus an optional
action)}.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | 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. | |
| project_root | No | Project root. Auto-detected if omitted. Pass explicitly when the project is not the server cwd. This field also accepts a project name or a project_id, but project is the clear field for those. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations present, the description carries the full burden, and it does this well: it labels the tool 'Read-only', explains skipped-status semantics, documents the truncated dependency check when uninitialized, and discloses the before-init compile_db behavior. This goes far beyond a generic 'get status' phrasing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but necessarily so, given the complex aggregate output and absent output schema. It is well structured with a front-loaded summary, bullets for the five domains, and dedicated Args/Returns sections. Every sentence contributes useful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no output schema and a multi-domain return value, the description is remarkably complete: it documents every returned field, the uninitialized-project behavior, and optional action fields. An agent has enough to call it correctly and interpret its result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds meaningful conflict guidance: 'Give one of the two, not both,' and clarifies when to use project vs project_root. This is useful semantic information not fully enforced by the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description starts with a concrete verb and resource: 'Return the complete project environment status in one call.' It further defines the aggregation of five named domains, which clearly distinguishes it from narrower sibling tools like check_dependencies or check_ollama.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly frames the tool as the session-start aggregate call: 'so the LLM can see everything at session start without extra round-trips.' It also clarifies the project vs project_root alternatives. However, it never explicitly says to use individual sibling tools when only a specific domain is needed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
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). 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 signatures. Default: False. max_per_kind: Max items per kind group (default 30, 0 = unlimited). variant: Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. image: Sysbuild image within the variant. Required when the variant holds several: each image is a separate program.
Returns: dict: {file, total_symbols, symbols: {kind: {count, items[], subgroups?[]}}}
Each item holds ``name``, ``qualified_name``, and ``line``, plus
``end_line`` when the symbol is a definition. The two line numbers
are the extent, thus ``file:line-end_line`` is the citation.
On failure the dict holds only ``error`` with the reason.
| Name | Required | Description | Default |
|---|---|---|---|
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| file_path | Yes | Path to source file — relative to project root or just filename. | |
| signatures | No | Include full function signatures in output. | |
| max_per_kind | No | Max items per symbol kind group (default 30, 0 = unlimited). | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full behavioral disclosure. It explicitly states 'Read-only. No side effects.', explains the index's path-resolution and refusal behavior, describes the error dict on failure, and clarifies enum subgroup count semantics. This is well beyond what structured fields provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear sections (overview, index behavior, usage, args, returns). The purpose is front-loaded, and every sentence carries information—the metaphor is brief and the parameter discussion is tersely formatted. Nothing is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no output schema and no annotations, the description fully defines the return structure, failure mode, path semantics, parameter constraints, and side-effect profile. For a 7-parameter tool with complex multi-build concepts, an agent has everything it needs to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and schema descriptions are already rich, so baseline is 3. The description's Args section mostly repeats schema text, but adds non-obvious parameter behavior: the subgroup count 'reflects the real total even when max_per_kind limits the constants list,' which is not in the schema. It also reinforces the project/project_root exclusivity constraint, adding meaningful nuance.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Fast structural map of all C/C++ symbols in a file grouped by kind.' The table-of-contents metaphor concretely conveys the output natureencing. It also explicitly distinguishes from siblings by naming get_symbol_context and lookup_symbol as detailed alternatives, so the agent can tell the difference without opening their schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear usage context: 'Use before reading a large file to orient yourself.' It also gives an explicit alternative route: 'For detailed symbol information use get_symbol_context or lookup_symbol.' The path-resolution caveat tells the agent when a query may fail, so usage boundaries are unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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 '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.
variant: Build variant (multi-build project). Omit to use
default_variant. One query answers for ONE build.
image: Sysbuild image within the variant. Required when the
variant holds several: each image is a separate program.
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) }
On failure the dict holds only ``error`` with the reason.
| Name | Required | Description | Default |
|---|---|---|---|
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| max_depth | No | Maximum BFS depth for transitive walk (default 10). | |
| class_name | Yes | Class or struct name to get inheritance information for. E.g. 'UART_DRIVER' or 'comm::MODEM'. | |
| transitive | No | When True, walk the full inheritance tree both up (ancestors) and down (descendants). Default: False (direct bases and derived only). | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden, and it delivers: read-only/no side effects, cross-TU resolution, BFS with cycle detection for diamond inheritance, and refusal of out-of-range max_depth values. It also documents failure returns. This far exceeds minimal disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Despite being long, it is organized with an opener, Args, and Returns sections, and every sentence conveys either behavior, routing, or parameter/return semantics. The return-shape block is justified because no output schema exists. It is front-loaded with purpose and alternatives.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Complexity is high (7 params, no annotations, no output schema), but the description covers purpose, scope, parameter semantics, return format, and error behavior. No critical information appears missing for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already covers all 7 parameters, so the baseline is 3. The description adds one meaningful caveat not in the schema—max_depth outside 1–50 is refused, not clamped—and restates the project alternatives. Overall it is helpful but mostly mirrors the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Return') and a specific resource ('the C++ inheritance chain for a class or struct'), and explains the libclang-aware cross-translation-unit resolution. It also distinguishes itself from sibling tools by deferring to get_class_members and get_method_overrides for related queries.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes class-member queries to get_class_members and virtual-method override-chain queries to get_method_overrides. The transitive/max_depth guidance clarifies when to request the full hierarchy versus direct relations. The contrast with single-file reading and the read-only statement provide additional context for appropriate use.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
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: Build variant (multi-build project). Omit to use
default_variant. One query answers for ONE build.
image: Sysbuild image within the variant. Required when the
variant holds several: each image is a separate program.
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}] }
On failure the dict holds only ``error`` with the reason.
| Name | Required | Description | Default |
|---|---|---|---|
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| method_name | Yes | Method name to get override information for. Use qualified name for disambiguation, e.g. 'UART_DRIVER::write'. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It explicitly declares 'Read-only. No side effects', and discloses the underlying data source (the overrides table populated during indexing) and failure behavior (dict holds only error). It could go further by stating prerequisites like index freshness, but the provided behavioral disclosures are strong.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with Args and Returns sections, but it contains a near-verbatim redundancy: 'Shows what base-class method this method overrides...' appears in both the first and second paragraphs. This repetition wastes space. Other sentences earn their place, but the duplication prevents a higher score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given there is no output schema, the description compensates by detailing the return dict structure and failure mode. It covers all 5 parameters, names alternatives, and explains the index-derived nature of the data. Minor gaps like performance or index prerequisites exist, but for a tool of this complexity it is largely complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description's Args section largely duplicates the schema descriptions (e.g., qualified name example, project vs project_root guidance), adding little beyond what the input schema already states. No additional parameter clarification is provided, so a 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Return'), a specific resource ('C++ virtual method override information'), and explains the core mechanics (libclang-powered vtable analysis, resolving virtual dispatch across class hierarchies). It clearly differentiates itself from textual search and names sibling tools for alternative purposes, making it unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance is provided: 'For class-level inheritance, use get_inheritance_chain. For symbol details, use get_symbol_context.' It also explains why this tool is needed ('Text-based search cannot resolve virtual dispatch across translation units') and covers project selection constraints, enabling an agent to decide when to use this tool versus alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
On failure the dict holds only ``error`` with the reason.
| Name | Required | Description | Default |
|---|---|---|---|
| project_id | No | Project ID (UUID4 hex) to look up. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full transparency burden. It explicitly discloses the underlying data source ('~/.fw-context/projects.db'), states 'Read-only. No side effects.' and defines the failure contract ('On failure the dict holds only error with the reason'). This is excellent behavioral disclosure beyond the bare operation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well organized with a front-loaded summary, usage context, Args, and Returns sections. It is slightly redundant around failure behavior — the error dict is described both in Returns and again in the final sentence — but overall it is compact and scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter tool with no output schema and no annotations, the description covers the purpose, data source, side-effect profile, return fields, and error shape. The only notable gap is that it does not state what happens if project_id is empty or omitted, given the parameter has a default and is not marked required.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides 100% coverage by describing project_id as 'Project ID (UUID4 hex) to look up.' The description's Args section largely repeats this. It adds context that the ID must be registered, but does not explain behavior for an omitted or invalid project_id, so it provides only marginal additional semantic value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Return project metadata (name, type, root_path) for a project ID.' It clearly identifies this as a single-project lookup against a global registry, distinguishing it from sibling tools like list_projects and get_active_build by focusing on UUID4-based identification and build-system metadata.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear usage context: 'Use this to identify a project from its UUID4 — find out what build system it uses, its name, and where it was last indexed.' This tells the agent when the tool is appropriate, though it does not explicitly name alternatives or state when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
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
only when the file changed after the last index run, and
stale_warning says so.
For enums, includes a constants array listing all member constants
with their values. 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 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. 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: Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. image: Sysbuild image within the variant. Required when the variant holds several: each image is a separate program.
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 end_line (the last line of the extent),
template_usr, parent_usr, enum_value, constants
(list for enums), value (raw macro definition),
expanded_value (preprocessor-resolved macro value) when
applicable. A declaration has no extent, thus it gets no
end_line.
``line`` and ``end_line`` are the extent of the symbol, thus they
are the citation: quote ``file:line-end_line``. Do not count the
lines of ``source`` to find the end.
``source`` carries a line-number prefix on every line — four
columns, right-aligned, then two spaces (``" 20 bool ..."``).
This tool always numbers its text. ``read_file`` numbers its
``content`` when you pass ``line_numbers=True``, and the ``source``
of ``search_bodies`` is always bare. Strip the prefix before you
compare the text with anything.
When the file changed after the last index run, the dict adds
``stale`` (True) and ``stale_warning`` (str). ``source_origin`` then
tells where the body comes from: ``"disk"`` when the symbol did not
move, ``"index"`` when it did and the body comes from the index
instead. A moved symbol never gives the code of another symbol.
``_source_truncated`` (True) marks a body that a cap cut:
``index.max_symbol_body_lines`` bounds the number of lines, and a
second cap bounds the characters. The character cut lands in the
middle of a line, thus a body with this mark can end in an
unbalanced brace. Read the rest with ``read_file`` and a range.
An ``ambiguous_warning`` key means that *name* matched more than one
symbol, such as two classes with a method of the same name. This
body belongs to ONE of them, and the key names it and lists the
others. Give the full qualified name to get one symbol only. It is
separate from ``warning``, which reports a body that could not be
read from the disk.
On failure the dict holds ``error`` with the reason. One failure
carries more than that: when the best match for *name* is in a file
outside the project root, the dict also holds ``candidates``,
``candidates_total`` and a ``hint``. Read them — a common name
matches many symbols, and one of the others is often inside the
project.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Fully qualified symbol name. Returns exact function body via libclang extent. | |
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses read-only/no side effects, ifdef-filtering behavior, stale_warning and source_origin semantics, truncation caps, line-number prefixes, ambiguous_warning, and failure modes with candidates/hints. This is exceptionally transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-organized into purpose, filtering behavior, alternatives, args, and returns. Every section adds operational detail, though some redundancy with the schema's parameter descriptions keeps it from being maximally lean.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no annotations, the description fully explains return fields, special keys, truncation, line-number citation, stale data, ambiguity, and error handling. An agent has enough information to invoke the tool correctly and interpret its result without external documentation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the description's Args section mostly restates the parameter semantics already present in the schema (auto-detection, mutual exclusivity, list_projects). It adds little new meaning beyond the structured data, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb and resource: 'Read a C/C++ function/method/enum/macro body using libclang exact extents.' It also distinguishes this from generic file readers and explicitly names siblings ('get_symbol_context', 'normal file read'), so an agent can tell what this tool uniquely does.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage guidance is explicit and actionable: 'For rich context ... use get_symbol_context instead' and 'For the full file, use a normal file read.' It also gives parameter-selection rules such as 'Give one of the two, not both' for project vs project_root, leaving little to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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).
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, all direct callers and callees. 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: Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. image: Sysbuild image within the variant. Required when the variant holds several: each image is a separate program.
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", signature (#define NAME
or #define NAME(a, b)), is_function_like, value (the
replacement text ALONE) 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.
When the file changed after the last index run, the dict adds
``stale`` (True) and ``stale_warning`` (str), and ``source_origin``
tells where the body comes from: ``"disk"`` when the symbol did not
move, ``"index"`` when it did. The callers and callees come from the
index in all cases, thus a stale dict can hold an incomplete list.
The dict also carries the libclang flags of the symbol:
is_virtual, is_pure_virtual, is_template, parent_usr, and
template_usr. For a virtual method it adds ``overrides`` (the base
methods that this method overrides) and ``overridden_by`` (the
derived methods that override it) — use these two before you change
a virtual method.
An ``ambiguous_warning`` key means that *name* matched more than one
symbol, such as two classes with a method of the same name. Every
part of this answer — body, callers and callees — is about the ONE
symbol that the key names, and the key lists the others. Give the
full qualified name to ask about one symbol only.
On failure the dict holds ``error`` with the reason. One failure
carries more than that: when the best match for *name* is in a file
outside the project root, the dict also holds ``candidates``,
``candidates_total`` and a ``hint``. Read them — a common name
matches many symbols, and one of the others is often inside the
project.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Symbol name. Returns body, signature, all direct callers and callees. | |
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and does so admirably. It discloses read-only behavior, no side effects, ifdef-filtered body behavior, source_origin semantics, stale-result handling, ambiguous matches, and failure candidates. It even explains that callers/callees come from the index and may be incomplete when stale.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but densely informative and well-structured with clear sections (usage guidance, returns, failure modes, edge cases). Every sentence earns its place given the tool's complexity and the absence of an output schema. It is front-loaded with the core purpose and usage guidance before diving into return details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a complex 5-parameter tool with no annotations and no output schema, yet the description covers purpose, alternatives, all edge cases (stale, ambiguous, failure, macro fallback), return variants by symbol kind, and even hints for handling candidate matches. Nothing an agent needs to correctly select and invoke the tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The Args section essentially repeats the schema descriptions word-for-word (e.g., project, variant, image) without adding new parameter semantics. The broader description adds context, but not beyond what the schema already provides for parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Rich one-shot context for a C/C++ symbol: body, signature, all direct callers and callees.' It clearly answers the core question 'what does this do and how does it fit in the system?' and distinguishes itself from siblings like get_source and the recursive call-graph tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says 'Prefer this over get_source when you also need callers, callees, indirect call sites, or LLM analysis' and 'If you only need the raw function body... get_source is slightly faster.' It also names the transitive alternatives (find_all_callers_recursive, find_callees_recursive), giving clear when-to-use and when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
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).
variant: Build variant (multi-build project). Omit to use
default_variant. One query answers for ONE build.
image: Sysbuild image within the variant. Required when the
variant holds several: each image is a separate program.
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)}
No match gives ``[]``. One dict with ``error`` means the query
failed — check that key first.
| Name | Required | Description | Default |
|---|---|---|---|
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| limit | No | Maximum results (default 50, max 200). | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. | |
| template_name | Yes | Template name to find instantiations for. E.g. 'Callback' or 'mbed::Callback'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully carries the burden. It declares read-only behavior, no side effects, explains the internal mechanism (template_usr column, cursor.specialized_template), discloses reliability limitations for implicit instantiations, and specifies return behavior for no-match and error cases. No contradictions with annotations since none exist.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured and front-loaded: the purpose is stated first, then returns, limitations, and parameters. Despite length, every sentence adds essential information—no fluff. Sections are clearly separated, making it easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (6 params, 1 required, no annotations), the description is exceptionally complete. It covers parameter semantics, return format (with example signature), failure modes, limitations, and alternatives. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds value by giving concrete examples for template_name, clarifying the project_root vs. project relationship ('Give one of the two, not both'), explaining limit defaults and max, variant's single-build behavior, and image's requirement. This exceeds the schema by providing usage context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Find all template instantiations for a C/C++ class or function template') and distinguishes itself from text-based search and from lookup_symbol for finding the declaration. The purpose is unambiguous and clearly differentiates from sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly provides when to use (template-aware lookup for cross-TU specialization resolution) and when not to (for the declaration itself, use lookup_symbol). It also states the limitation that header-only templates may yield zero results, giving the agent a clear decision framework.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_vector_tableA
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. Code runs. When the index also holds the weak definition that this one replaced, the row hasoverriddenwith its file and line."assembly"— a strong assembly definition. Assembly services the interrupt."unhandled"— a weak assembly definition that nothing overrode. A CMSIS startup file makes this an alias ofDefault_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 callingNVIC_SetVector. A target that definesCMSIS_VECTAB_VIRTUALkeeps its vector table in RAM and fills it that way, so the interrupt IS serviced once the registering code has run — and not before it. The row holdsinstalled, one entry per call site with the handler name, its file and line, andat, where the registration happens. Followatto see WHEN it happens: on the Mbed projectus_ticker_irq_handlerreaches slot 25 fromus_ticker_init, so the tick source is unserviced until the ticker starts. A row with a real static definition keeps its own status and still carriesinstalled."data"— the slot holds an address BUILT from the symbol it names (.word z_main_stack + CONFIG_MAIN_STACK_SIZE), so the symbol is a base and nothing jumps to it. On Cortex-M this is slot 0 of a Zephyr table: the initial stack pointer. Do not read it as code."linker"— the linker script gives the address and no compiled file defines the name. Slot 0 holds the initial stack pointer, not a handler, and looks like this. When the index read the script,fileandlinename the assignment in it — on the Mbed project,__StackTopat.link_script.ld:148. Do not read this row as code: there is no function to follow."dispatcher"— the slot reaches a function that holds more than one slot of this table AND calls through a pointer. It cannot be servicing one particular interrupt; it decides at run time where to go. Zephyr fills every external IRQ slot with_isr_wrapper, which reads the interrupt number and jumps through_sw_isr_table. Follow it:get_symbol_contexton the name, thenfind_referenceson the table it uses. A handler that merely calls one registered callback is NOT this — it holds a single slot and keeps"c".
A "c" row with overridden is the CMSIS pattern: the startup
file defines each handler weakly, the project defines the same name
again, and the linker keeps the strong one.
Two sources are read, and source says which one a row came
from:
"assembly"— a table of address words,.wordor.longin a vector section, which is what a CMSIS startup file writes."c"— an array whose elements are addresses of functions, which is what a build that generates its table produces. Zephyr writes its external interrupts this way, withgen_isr_tables.py. These rows also carrytable_name, the array the slot belongs to."build"— the registration the build itself recorded, for a slot the other two could not name. A generator writes a resolved ADDRESS into every slot that is in use, so those slots have no name in the source at all — and they are the interrupts the firmware actually services. Measured on an nRF54L application: 284 of 290 slots name the spurious stub, and the 6 without a name are IRQ 89, 198, 219, 228, 269 and 270, which these rows fill in.Such a row can carry
argument, the symbol the build passes to the handler. Read it as an argument and not as a second handler: behind thenrfx_isrshim it is the real worker (nrfx_power_clock_irq_handler), while for another driver it is the device (__device_dts_ord_116). When the build enables run-time registration, a dict withinfosays so, because an interrupt connected at run time leaves nothing to read and the rows are then not all of them.
Recognition is by shape, never by name, so any array of function
addresses is reported and the row names its table. A table of
interrupt handlers and a table of state machine steps are the same
construct, and table_name is how they are told apart.
Slot numbers are not joined across tables. Each slot is the index
inside its own table, so two tables both start at 0 — read slot
together with table_name and source. They are not renumbered
into one run because the index does not hold the length of the
assembly table, only its occupied slots, and an offset derived from
that would be silently wrong for every entry of a 290-entry table.
A coverage row follows the slots for each table longer than the
number of slots that name a function. It says how many of the declared
elements were named and which slot numbers were not, because a name is
not always there to be read: an element can be a zero, or an address
the linker resolved before the table was written.
Read it in both directions. A hole in a table of handlers is a vector
nothing services. A hole in Zephyr's _sw_isr_table is the
opposite — measured on an nRF54L application, 284 of 290 slots name the
spurious stub and the 6 without a name are the interrupts in use. The
tool reports where to look; which meaning applies depends on the table.
An interrupts row answers "which are unserviced" wherever the
build recorded its registrations, and it is the answer under
unhandled_only too. The row-level unhandled status is read
from an alias edge, which a CMSIS startup writes and a generator does
not — measured, zero unhandled rows on all eleven images of a Zephyr
project against 39 to 72 on four CMSIS and Mbed ones. The
registrations settle it from the other side: what the build connected
is the whole list, so anything else has nothing servicing it, and no
handler has to be recognised by name.
The complement is taken over the length of the table, NOT over the
slots that hold a stub. Measured on an mcuboot image: its software
table names 44 of 48 slots, and one of those 44 is
uarte_0_direct_isr, an interrupt wired straight into the vector
table. It IS serviced, and counting stubs would report it as not.
What is still not covered: an architecture that builds its table from
branch instructions (arm64, Xtensa, MIPS) writes no table of
addresses in either form. A handler whose address the build resolved
at link time has no name to report either — coverage names its slot
but not the function. For an interrupt this tool cannot show,
find_references on the handler name still gives every reference
the index holds.
Read-only. No side effects. Requires an index of the assembly
(fw-context index).
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.
unhandled_only: When True, return only the "unhandled" slots.
limit: Maximum slots (default 400, max 1000).
variant: Build variant (multi-build project). Omit to use
default_variant. One query answers for ONE build.
image: Sysbuild image within the variant. Required when the
variant holds several: each image is a separate program.
Returns:
list of dicts sorted by source, then table, then slot. Each holds:
slot (int), name, file, line, source ("assembly", "c" or
"build"),
status ("c", "assembly", "unhandled", "runtime",
"data", "linker" or "dispatcher"), and table_file and table_line
(where the slot is written). A "c" source row also holds
table_name and table_usr. A "c" status row can hold
overridden, a dict with file and line. Any assembly row can hold
installed, a list of dicts with name, file, line and at.
Never empty: one dict with ``error`` (no index) or ``info`` (no
vector table in this build). Check both keys first. A dict with
``coverage`` follows the slots for each table that has unnamed
elements, and a dict with ``interrupts`` says which are connected
and which are not — the latter in both modes. Neither is subject
to ``limit``: they describe the whole table, and the longest table
is where they matter most. When more slots exist than ``limit``,
a dict with ``truncated`` sits between the slots and those two,
saying how many slots are not shown.
| Name | Required | Description | Default |
|---|---|---|---|
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| limit | No | Maximum slots (default 400). | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. | |
| unhandled_only | No | Return only the slots that reach the default handler. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden—and it delivers extensively. It declares 'Read-only. No side effects. Requires an index of the assembly', explains the meaning of every status value, describes the two sources and their implications, warns that slot numbers are not joined across tables, and details edge cases like coverage rows and runtime-installed handlers. No contradiction with annotations exists because none were provided.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but the tool is genuinely complex and the length is organized with bold headers, bullet-like status explanations, and a front-loaded purpose statement. Some measured examples are verbose and could be trimmed, but the structure makes the detail navigable and each major section addresses a distinct decision an agent must make.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is exceptionally complete for a complex tool: it covers all statuses, both sources, the unspecified-source 'build' rows, table boundaries, coverage holes, interrupts rows, limit/truncation behavior, and the non-empty error/info response contract. It even documents failure modes ('Never empty: one dict with error... or info...'). An agent has enough context to select and invoke the tool correctly in nearly any scenario.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds some meaning beyond the schema: it states the limit max is 1000 (schema only gives default 400), clarifies that 'One query answers for ONE build' for variant, and reinforces the project_root/project exclusivity. Most parameter text repeats the schema, but the extra constraints justify a 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Read the interrupt vector table, and say what services each interrupt.' It explains the conceptual role of the vector table and gives concrete use cases ('which interrupts does this firmware service', 'find the handler for one interrupt'), clearly distinguishing this tool from the sibling lookup tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit use cases are listed ('Use it to answer...'), and the description names fallback alternatives: 'get_symbol_context on the name, then find_references on the table it uses' for dispatcher rows, and 'find_references on the handler name' for interrupts this tool cannot show. It also states what is not covered (branch-instruction architectures, link-time-resolved addresses), giving clear when-to-use and when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
indexed_at and first_indexed_at are UTC, in "YYYY-MM-DD HH:MM:SS" format — the same format that get_active_build returns.
analysis holds the project and vendor counts only. For the
model, analyze_vendor, and complete fields, call
get_active_build for that project.
Args: project_root: Project root. Auto-detected if omitted. Pass to distinguish multiple indexed projects. 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), status (str — "ready" or "reindex_needed"), db (path to SQLite database file), variant_count (int — number of build variants), image_count (int — number of sysbuild images), analysis (dict — LLM-analysis coverage {project: {analyzed, skipped, total}, vendor: {analyzed, skipped, total}}, or None when no build is indexed).
When no project has an index, the result is a single dict with an
``info`` key. When fw-context cannot read a database, the result
holds a dict with ``db`` and ``error`` keys for that file.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | 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. | |
| project_root | No | Project root. Auto-detected if omitted. Pass to distinguish multiple indexed projects. This field also accepts a project name or a project_id, but project is the clear field for those. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden and meets it: it declares 'Read-only. No side effects.' It also discloses return behavior, UTC timestamp formats, and edge cases such as no indexed project or a database that cannot be read. This goes well beyond what structured fields would convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized and front-loaded: purpose, read-only note, usage guidance, then params and returns. It is long, but most content is useful; the main inefficiency is that the Args section partly duplicates the input-schema descriptions.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no annotations and no required parameters, this description is fully self-contained: it covers when to use the tool, how to choose between parameters, return shape, timestamp semantics, and unusual result cases. There is no critical gap an agent would need to guess at.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% description coverage and already explains both project and project_root, including the distinction between them. The description's Args section mostly mirrors the schema, adding no meaningful new parameter semantics beyond what is already available.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'List all indexed firmware projects with their statistics.' It also distinguishes itself from get_active_build by noting that the latter provides details on the currently active project, so an agent can tell the tools apart.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says to use this tool at session start to discover available projects and directs the agent to get_active_build for active-project details. It also explains when to pass project_root versus project and warns not to give both, which is clear routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_variantsA
List every indexed build with its (variant, image, board) identity.
Read-only diagnostic — shows what is actually indexed, not what the config
declares. Each row is one (variant, image) build with its own
config_hash and symbol count. For single-project indexes this returns
one row with variant/image empty.
This and get_active_build are the two tools that say what a query can
choose from. Both read the index, thus a build written by
fw-context index --build --variant X is listed even when config.toml
no longer declares X — and resolve_build fails closed on that same
fact, so the two never disagree about whether a choice must be made.
Use get_active_build for the mandatory first-call health check and the
human-readable variants/images discovery; use this tool to see the
per-build config_hash and symbol counts (authoritative per-build state).
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: dict: {builds (list[dict]), multi (bool — True when the config declares variants or a build has a non-empty variant name)}.
Each build dict holds: variant (str — empty for a single-project
index), image (str — empty for a single-project index), board (str),
config_hash (str), symbol_count (int), file_count (int),
manifest_verification (str — "full" or "none"),
entry_point (str — the `ENTRY()` of the linker script of this build,
empty when no script names one),
memory (list[dict] — the `MEMORY` regions of this build:
{name, attributes, origin, length, origin_value, length_value,
file_path, line}). `origin` and `length` are the expression the
script writes; `origin_value` and `length_value` are numbers, and
they are None for an expression that names a symbol such as
`ORIGIN(RAM) + LENGTH(RAM)`. Empty for a build whose system
records no linker script — see the note below.
THIS is where a per-build memory map lives, not in the `images`
list of ``get_active_build``: that list holds one entry per image
NAME, and one name can belong to two variants with different
addresses.
When the project is not initialized, or has no index, the result is
{builds: [], multi: False, error (str)}.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | 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. | |
| project_root | No | Project root directory. Auto-detected from CWD if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does so thoroughly. It discloses that this is a read-only diagnostic, that it reflects the actual index rather than config, that single-project indexes return empty variant/image, that memory maps live here rather than in get_active_build, and that uninitialized projects return the {builds: [], multi: False, error: ...} shape.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Long but dense and well-organized: purpose, read-only caveat, sibling differentiation, parameter docs, return shape, and cross-tool warning each earn their place. The opening line front-loads the core purpose, and the rest is structured under clear Args/Returns headings.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Since there is no output schema, the description exhaustively documents the return dict, each field, the memory sub-structure, and the error case. It also covers the single-project behavior and the distinction from get_active_build's images list, leaving no obvious gap for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both parameters well. The Args section essentially repeats the schema text without adding new meaning, so the description does not raise the value beyond the schema baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a precise verb-object statement ('List every indexed build') and immediately scopes it to the (variant, image, board) identity. It further distinguishes itself from configuration-declared state and from get_active_build, so an agent can tell exactly what this tool returns.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly contrasts this tool with get_active_build: use get_active_build for the mandatory first-call health check and human-readable variants/images discovery, and use this tool for per-build config_hash and symbol counts. It also explains how both relate to index state and resolve_build, giving clear selection criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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. 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.
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: Build variant (multi-build project). Omit to use
default_variant. One query answers for ONE build.
image: Sysbuild image within the variant. Required when the
variant holds several: each image is a separate program.
Returns:
list[dict]: The page notice leads the answer — total, offset,
shown, more — where total counts every symbol the name
matches. Read it before you conclude that a page holds them all.
Each symbol that follows has name, qualified_name, kind, file,
line, signature, docstring, is_definition, is_template, is_virtual,
is_pure_virtual fields, and class — the class, struct or union
that declares the symbol, absent for a free function. class is
what tells two same-name methods apart at a glance.
Enum constants include enum_value
with the integer value. Macro results include kind="macro",
signature (how the macro is invoked: #define NAME,
#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 value).
May also include template_usr,
parent_usr, and llm_analysis ({summary, inputs, outputs}) when available. A model wrote the text in
llm_analysis, and the code did not — use it to find a symbol,
and quote signature, docstring, or get_source instead.
When no results found, may include _did_you_mean with suggested
symbol names. When no symbol matches, the list is empty — there is
then no page notice, because there is no page. An info entry
comes back for one case only: an offset past the end of an answer
that does hold rows.
**Note:** C++ constructors share their name with the enclosing
class, so ``lookup_symbol("Foo")`` may return both ``class Foo``
and ``constructor Foo::Foo()``. Use the ``kind`` field to
filter when you need a specific symbol type.
A symbol that comes from the relaxed prefix fallback carries
``_fallback: True`` — the name is not an exact match of *name*.
A list with one dict that holds an ``error`` key means that the
project has no index, or that the lookup failed. Read that key
before you read the result fields.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Symbol name. Exact match if exact=True, prefix LIKE match otherwise. E.g. 'uart_init' or 'uart_'. | |
| exact | No | True = exact name match, False = prefix LIKE match (default). | |
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| limit | No | Maximum results returned (capped at 100, default 50). | |
| offset | No | Skip this many results. Pages through a name that many classes share, such as 'read' or 'write'. | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| project_root | No | Project root directory. Auto-detected from CWD if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden — and it does so comprehensively. It discloses the read-only nature ('Read-only: yes'), side effects ('May auto-reindex stale files (non-blocking)'), the error-key edge case, the empty-list case with no page notice, the _fallback flag, the C++ constructor name-collision quirk, and even flags that llm_analysis text was model-written ('A model wrote the text... the code did not').
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The structure is sound and front-loaded — purpose, then usage, then params, then returns — but the Returns section is verbose, repeating details an output schema would already carry (the full field list). Much of the length is justified by behavioral context (page-notice reading instruction, error key, llm_analysis caveat), but a trim of redundant field enumeration would tighten it without loss.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex tool — 8 parameters, 1 required, multi-case return format, error handling, pagination — the description is remarkably complete. It covers the page-notice semantics, empty-result behavior, error-key case, did_you_mean suggestions, fallback flag, and the C++ constructor quirk. With an output schema present, the return-format detail exceeds necessity but adds behavioral value an output schema cannot capture.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds genuine meaning beyond the schema: the offset parameter's pagination rationale with stable ordering guarantee ('two pages never overlap and never skip a symbol'), the image parameter's requirement rationale ('each image is a separate program'), and the project vs project_root mutual-exclusion guidance. These exceed what the schema documents.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb, resource, and mechanism: 'Look up a C/C++ symbol by name via libclang index — exact or prefix matching.' It clearly differentiates from search_code by naming what makes it unique ('Finds symbols text-based search can miss: build-conditional code, template instantiations, macro-expanded names') and explicitly names the sibling it should be preferred over.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use guidance: 'Prefer this over search_code when you know the exact symbol name or a prefix... Use search_code for keyword/concept search.' Also gives concrete routing examples (uart_ finds all UART symbols) and instructs calling list_projects for the project parameter. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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, 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 active build 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.
A comment and a preprocessor directive are part of the answer. Both
are text that the file holds and the build reads, thus both stay — an
include guard, a #define, and the description of a register in a
vendor header included. A blank line is therefore an inactive line, or
a line that is blank on disk, and nothing else.
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.
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.
line_numbers: Prefix every line with its number, right-aligned and
followed by two spaces, as get_source does. Default False.
start_line: First line to return, 1-based inclusive. 0 = file start.
end_line: Last line to return, 1-based inclusive. 0 = file end.
variant: Build variant (multi-build project). Omit to use
default_variant. One query answers for ONE build.
image: Sysbuild image within the variant. Required when the
variant holds several: each image is a separate program.
Returns:
dict: {file (str), language (str — "c" or "cpp"),
mtime (float), lines (int — total line count of the WHOLE file,
whatever range was asked for),
content (str — the ifdef-filtered text, bare unless
line_numbers was set),
warning (str, optional — when reading from raw disk instead of
indexed content, or when no line of the file is active),
all_lines_inactive (True, optional)}.
``all_lines_inactive`` marks a file that the active build compiles
no line of: every line is inside an inactive ``#if`` branch, thus
``content`` holds the correct number of lines and no text. Without
this field that answer reads as an empty file, and the two mean
opposite things.
A range adds ``start_line`` and ``end_line`` — the first and last
line the ``content`` really holds, after the end was clamped to the
length of the file.
On failure the dict holds only ``error`` with the reason: a
negative bound, an ``end_line`` before ``start_line``, or a
``start_line`` past the end of the file.
| Name | Required | Description | Default |
|---|---|---|---|
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| end_line | No | Last line to return, 1-based inclusive. 0 = to the end of the file. | |
| file_path | Yes | Path to source file — relative to project root or just filename. | |
| start_line | No | First line to return, 1-based inclusive. 0 = from the start of the file. | |
| line_numbers | No | Prefix every line with its line number, like get_source. Default False (bare text). | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden, and it delivers: read-only/no side effects, inactive branches replaced with blank lines preserving line numbers, fallback to raw disk with warning, all_lines_inactive semantics, inclusion of comments/preprocessor directives, range clamping, and failure conditions. Nothing important is hidden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded, but it is quite long and has some redundancy — the meaning of blank lines and all_lines_inactive is explained multiple times. Every sentence is useful in context, but tighter editing would make it cleaner without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a complex tool with 8 parameters, no output schema, and no annotations, yet the description covers the return dict fields, warning/all_lines_inactive flags, range clamping behavior, raw-disk fallback, legacy index caveat, and all error cases. An agent has everything needed to invoke it correctly and interpret results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds substantial meaning beyond the schema: file_path relative-or-filename, project vs project_root exclusivity, one query per build, image requirement for multi-image variants, detailed start/end_line semantics (1-based inclusive, 0 = unbounded), and the line_numbers output format. It also warns not to count lines and tells where to get line numbers.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a precise action — reading a C/C++ source file with ifdef-filtered, build-accurate content — and distinguishes itself from siblings by name (get_source, get_file_map, get_symbol_context, search_content). An agent can immediately tell what this tool does and how it differs from a generic file reader.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit use case ('read a file without leaving the fw-context ecosystem'), explains what makes it unique (build-accurate ifdef filtering), and explicitly lists alternatives for other needs: get_source for function bodies, get_symbol_context for body+callers+callees, get_file_map for structure, search_content for patterns. This is model guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
Use after editing a file to keep the index current without a full rebuild.
A source file must be listed in compile_commands.json. A header is
not listed there, thus it is re-parsed through one unit that includes
it. That answer covers a single compilation context, thus the result
carries a warning — only a full fw-context index covers every
unit that includes the header.
Also regenerates LLM analysis and method override relationships for affected symbols when those features are enabled in config. An unchanged symbol keeps its stored analysis.
Args: file_path: Path to the file to re-parse. A source file must be in compile_commands.json; a header goes through one including unit. 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.
Returns: dict: {file, translation_units, symbols_updated, elapsed_s, analysis_updated (if LLM enabled), or error}.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | 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. | |
| file_path | Yes | Path to the file to re-parse. A source file must be in compile_commands.json. A header goes through one translation unit that includes it, and the result then carries a warning about the other units. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It explicitly warns 'Not read-only', explains the warning for headers, and discloses that LLM analysis and method override relationships are regenerated when enabled, while unchanged symbols keep stored analysis. It does not detail failure modes or side effects on the broader index, but it covers the most important behavioral traits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a clear opening, a 'Not read-only' warning, usage context, and an Args section. It is somewhat long but every sentence earns its place, and the most important behavioral warning is front-loaded. Minor redundancy with the schema's parameter descriptions prevents a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers purpose, usage, constraints, side effects, and return value shape. It lacks an output schema, but the Returns section lists the dict keys. It doesn't explain error cases or what happens if the file is not in compile_commands.json, but for a tool with this complexity, the description is nearly complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all three parameters. The description adds value by explaining the header-vs-source distinction and the project/project_root mutual exclusivity, which goes beyond the schema. It doesn't add much beyond that, but the schema is already rich, so a 4 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('re-parse'), a specific resource ('a single source file with libclang'), and the outcome ('update its symbols in the index'). It also distinguishes itself from a full rebuild and from sibling tools like reindex_file_impl by clarifying it operates on a single file. The scope is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to use it ('after editing a file to keep the index current without a full rebuild'), and it explains the constraint that source files must be in compile_commands.json while headers are handled through an including unit. It also gives clear guidance on project vs project_root alternatives, including 'Give one of the two, not both.' This is strong usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reindex_file_implA
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.
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 that includes it, taken 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 seconds each.
Also regenerates LLM analysis and method override relationships for
affected symbols when with_analysis=True. The analysis is
content-addressed, thus an unchanged symbol is never re-analysed.
Args: file_path: Path to the file to re-parse. A source file must be in compile_commands.json; a header goes through one including unit. 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. with_analysis: When True (default), also regenerates LLM symbol analysis, method override relationships, PageRank, and embeddings. Set False for a fast symbol-only update (used by background auto-reindex).
Returns: dict: {file, translation_units, symbols_updated, elapsed_s, analysis_updated (if LLM enabled with analysis), or error}.
On failure the dict holds only ``error`` with the reason.
| Name | Required | Description | Default |
|---|---|---|---|
| project | No | 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. | |
| file_path | Yes | Absolute or project-relative path to the file to re-parse. A source file must have an entry in compile_commands.json. A header is re-parsed through one translation unit that includes it, and the result then carries a warning that other units can still hold stale symbols. | |
| project_root | No | Project root directory. Auto-detected from cwd if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. | |
| with_analysis | No | When True (default), also regenerates LLM symbol analysis and method override relationships — slower but produces a fully up-to-date index. Set False for a fast symbol-only update (used by background auto-reindex). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden of behavioral disclosure. It explicitly states 'Not read-only' and explains the use of compiler flags from compile_commands.json. It discloses the header re-parsing limitation and the resulting warning, the cost decision (up to 266 units), and the content-addressed analysis regeneration. It also describes the return dict and error handling, leaving no ambiguity about side effects or outcomes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every sentence earns its place. It is front-loaded with the core purpose, then systematically covers limitations, cost, parameter details, and return format. The structure is logical and the language is dense without being verbose, making it easy for an agent to extract the key facts quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (4 parameters, no output schema), the description is exceptionally complete. It explains the header edge case, the performance tradeoff, the meaning of each parameter, the return value format, and error behavior. Nothing an agent needs to decide whether to call this tool and how to use it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description adds substantial meaning beyond the schema. It clarifies the difference between source files and headers for file_path, explains the relationship between project and project_root (alternatives, not both), and details the performance tradeoff of with_analysis. These enrichments go well beyond the schema descriptions, helping the agent select the correct parameter values.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'Re-parse a single source file with libclang and update its symbols in the index.' It distinguishes itself from a full rebuild and provides specific details about file types. However, it does not explicitly differentiate from the sibling 'reindex_file' tool, leaving the agent to infer the difference from the name.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit guidance: 'Use after editing a file to keep the index current without a full rebuild.' It also explains when not to use it ('Only a full fw-context index covers every context') and notes the cost tradeoff of using a single translation unit. It further mentions the with_analysis=False fast path used by background auto-reindex, providing clear context for when to choose this tool over alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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. 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, symbol_count, indexed_at (dry-run)}.
A ``warning`` key means that the database is corrupt — the
integrity check failed, thus the counts can be incomplete.
On failure the dict holds only ``error`` with the reason.
| Name | Required | Description | Default |
|---|---|---|---|
| confirm | No | Must be True to execute. Call without confirm first as dry-run. | |
| project | No | 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. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral burden. It explicitly warns that the operation is not read-only, permanently deletes the SQLite database and WAL files, supports dry-run, handles corrupt databases gracefully, and documents the warning key and failure result shape.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is appropriately sized for a destructive tool. It front-loads the purpose and danger, then provides structured Args and Returns sections. Every sentence adds useful information, including the corrupt-database behavior and re-indexing follow-up.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the Returns section fully documents the response dict, dry-run vs deleted action, warning semantics, and error-only failure case. All parameters are covered by the schema, and the destructive side effects are clearly disclosed. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description mostly restates the schema: project_root auto-detection, project as an alternative to project_root, and confirm default false. It adds no material meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific action and resource: "Delete the entire symbol index for a project." This clearly distinguishes reset_index from sibling tools like reindex_file, which rebuild rather than delete the index.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear usage guidance: call with confirm=False first as a dry-run, pass confirm=True to execute, and re-index with fw-context index afterward. It does not explicitly contrast against sibling tools like reindex_file, so it falls short of full alternative-selection guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_bodiesA
Find patterns in the TEXT OF A DEFINITION — the code inside its extent.
Searches ifdef-filtered text — only the code that compiles for the
current build. 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. Call patterns (.attach(,.rise(,callback(&), ISR registration, onecaselabel of a longswitch.Types —
class,struct,union,enum,namespace. An enum constant, a bit field, a member declaration such asInterruptIn _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 DECLARES):self test,attach,SELF_TEST.search_code— symbols by NAME (what the code IS):modem init,interrupt handler.
The query goes to FTS5 as you wrote it. This tool alone adds no wildcard, and that is what keeps a pattern precise:
A space is an AND of two exact tokens, NOT an OR.
CommandType NUManswers with the definitions that hold both.No prefix is implied.
SELF_TESTmatches the tokensself testand missesSelf tester; writeSELF_TEST*to reach the second. Measured on one project, the wildcard added the one caller that the bare query missed.Punctuation is not searchable. FTS5 cannot parse
.attach(at all, thus the query is repaired into the phrase".attach("— and the tokenizer inside a phrase drops the punctuation too, so what runs is the wordattach. Such a result carries_fallback: "sanitized"and_query_used. The hits whose body really holds.attach(are the ones withmatch_lines.search_codeandsearch_contentbehave the OTHER way: each of their terms gets a trailing*and the terms are OR-joined.
Limitation — the extent of a definition is the boundary. Text that belongs to no definition is out of reach:
#include,#define,#ifdef— preprocessor directives.search_codecovers a macro name and value.search_contentcovers the directive as text.extern "C"— a linkage specifier is no symbol.A comment or a declaration at file scope, outside every definition.
For those, use search_content, which indexes the full file text.
Set project_only=True for a question about YOUR code ("where do we register interrupt handlers?"). Leave it False (default) when the
vendor SDK code — the framework or OS code that your team did not write
— is also relevant.
Results include _match_snippet — a highlighted excerpt that shows
each match in context (e.g. _timeout.<b>attach</b>(callback(...))) —
and match_lines, the line numbers of the matches inside the
definition. line is where the definition starts, which for a large
function is far from the match. Cite from match_lines instead.
Project code sorts before vendor code in the output.
Read-only: yes. Requires the FTS5 index. May auto-reindex stale files
(non-blocking) — see search_code.
Args:
query: FTS5 search terms, 1-3 words. A bare multi-word query is an
AND of exact tokens, and no wildcard is added — see the query
rules above. A single word is the broadest form: 'attach'
reaches every .attach(...) pattern. Add * for a prefix
('attach*'), and double quotes for a phrase
('"attach 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.
kind: Optional filter to return only symbols of this kind.
limit: Maximum results of one page (default 20, max 100).
offset: Skip this many results. Reads the next page of a pattern
with many hits; the page notice names the offset to use.
project_only: When True, exclude vendor SDK directories and return only
application code. Default False.
variant: Build variant (multi-build project). Omit to use
default_variant. One query answers for ONE build.
image: Sysbuild image within the variant. Required when the
variant holds several: each image is a separate program.
Returns:
list of dicts. The page notice leads the answer — total,
offset, shown, more — and each that follows holds:
name, qualified_name, kind, file, line (first line of the
definition), is_definition, signature, _match_snippet (excerpt
around the match), source (the text of the definition).
Also, when they carry an answer:
* ``match_lines`` (list[int]) — absolute line numbers of the
matches, up to 20. Computed from the full text, thus a match
after the cut below still has a number. Use these to cite
``file:line``, and not the ``line`` of the definition. The name
carries no leading underscore for a reason: a field the caller
must cite is an answer, while ``_``-prefixed fields
(``_match_snippet``, ``_fallback``, ``_source_truncated``) tell
where the answer came from.
* ``_source_truncated`` (True) — ``source`` is cut. A callable
keeps 2000 characters, any other kind 500, because the body of a
type is mostly members that the match has nothing to do with.
``get_source`` gives the whole text.
* ``_fallback`` (``"sanitized"``) with ``_query_used`` — FTS5 could
not parse the query as written, thus a repaired one ran. The
repair drops punctuation, so the answer is wider than the text
that was asked for. Every query FTS5 accepts runs untouched and
carries neither field.
``source`` here is bare text with no line-number prefix. Only
``get_source`` numbers its lines.
No match gives ``[]``. A dict with ``error`` means the query
failed. A stale index prepends a dict with ``warning`` + ``hint``,
and so does a query that FTS5 refuses to parse — an empty list
always means "no such code", never "bad query".
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Optional kind filter: function, method, class, etc. | |
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| limit | No | Maximum results of one page (default 20, max 100). | |
| query | Yes | FTS5 search terms for the body of a definition. 1-3 words. E.g. 'attach', 'callback', 'rise'. | |
| offset | No | Skip this many results. Reads the next page of a pattern with many hits. | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| project_only | No | Exclude vendor SDK code. When True, only application code. Default False. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the full burden falls on the description — and it delivers richly: explicit read-only declaration, ifdef-filtering semantics, FTS5 tokenizer behavior (AND not OR, no implied prefix, punctuation dropping), fallback sanitization with _query_used, source truncation limits, stale-index warnings, and the line-vs-match_lines citation distinction. Warning/error/empty-list conventions are also spelled out so an agent knows what each response shape means.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very long (1000+ words) but clearly sectioned with headers and bullets, with the core purpose front-loaded. Most sentences earn their place given the tool's subtle FTS5 semantics and conditional return fields; the measured-project anecdotes and some repeated wildcard reminders are illustrative but could be trimmed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With zero annotations and 9 parameters, the description covers everything needed to invoke correctly: query formation semantics, scope boundaries, return-field meanings (match_lines vs line for citation), truncation, pagination, error vs warning vs empty-list conventions, and sibling routing. The output schema exists, and the description still adds value by explaining the conditional fields' semantics rather than just their shape.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3, but the description adds non-inferable meaning: FTS5 query rules for the query param (add * for prefix, double quotes for phrases, single word is broadest), the mutual exclusivity of project and project_root, a use-case for project_only, and offset's page-navigation behavior. The value-add is real but concentrated on query plus cross-parameter relationships, so a 4 not a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence names a specific verb and resource — 'Find patterns in the TEXT OF A DEFINITION — the code inside its extent' — and the coverage enumeration (callables, types, data definitions) makes the scope concrete. The 'Only the text matches' paragraph explicitly negates what this tool is not (name/signature/docstring search), distinguishing it from search_code and search_content without needing their schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
An explicit 'When to use search_bodies and when search_code' section gives contrasting example queries ('self test' vs 'modem init'), names search_content for what falls outside definition extents, and advises project_only=True for questions about the team's own code. This exceeds the calibration example: it gives positive conditions, exclusions, and named alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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 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 initgoes to FTS5 asmodem* OR init*and answers with the symbols that hold EITHER word.search_bodiesdoes the opposite — it takes the query literally, where a space is an AND.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_initinto two tokens and looks for them NEXT TO EACH OTHER. That is a phrase and not an AND, thus the query missesmodem_parser_oob_init. Measured on one firmware index,serial_writegave 1 result andserial writegave 200. Writemodem initinstead.Punctuation is not searchable. The tokenizer drops it, thus
.attach(becomes a phrase that looks for the tokenattach. 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 there:
FTS5 with the
kindfilter. No_fallbackkey.FTS5 without the kind, when the kind matched nothing; operators often guess the wrong kind —
_fallback="fts5".name_tokenssubstring match over the pre-computed CamelCase / snake_case tokens (BuildTypeis indexed as"build type"). Needs N−1 of N query terms —"name_tokens_like".LIKE over the docstring column, for a single-term query that the token steps missed —
"docstring_like".FTS5 per query word, results merged —
"individual_terms".macros_ftsfor#definenames and values, kind="macro" —"macros_fts".
Kind filter values: function, method, constructor,
destructor, class, struct, union, enum, enum_constant,
typedef, varglobal, varlocal, variable, field,
namespace.
Local variables are out. FTS5 indexes the qualified name, thus a
local matches through the function that holds it: a query for
sensor used to answer with V, ret and tmp_value from
inside read_sensor_value, 4 of 20 results on one measured query.
A local is never the answer to "which symbol is about X", thus
varlocal and the legacy variable kind are excluded.
varglobal stays — a global carries architectural weight. Ask for
them explicitly with kind="varlocal", or use find_variables.
After fw-context index --analyze, a result also holds
llm_analysis — {summary, inputs, outputs}. A model wrote that
text, and the code did not. Treat it as a hint that points you at a
symbol, never as a fact to quote. Quote source from
get_source, signature, or docstring.
Read-only: yes. May auto-reindex stale files (non-blocking). When a file that the answer names changed on disk, this tool starts the watcher daemon in the background and answers from the index it has.
Args: query: FTS5 search terms. Keep queries short — 1–3 words. 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. kind: Optional filter to return only symbols of this kind. limit: Maximum results of one page (default 20, max 100). offset: Skip this many results. Reads the next page of a topic that many symbols carry; the page notice names the offset to use. One relaxation step owns the whole answer, thus a walk never changes the step under the reader. project_only: When True, exclude vendor SDK directories and return only application code. Default False. variant: Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. image: Sysbuild image within the variant. Required when the variant holds several: each image is a separate program.
Returns:
list of dicts. The page notice leads the answer — total,
offset, shown, more — where total counts the
answer of the step that answered. Each symbol that follows has
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, and llm_analysis
({summary, inputs, outputs} — written by a model, not by the
code. get_active_build().analysis.model names it). Fallback
results include _fallback with the method name.
No match gives ``[]``. A dict with ``error`` means the query
failed. A stale index prepends a dict with ``warning`` + ``hint``,
and that dict comes BEFORE the page notice — find the notice by
its keys, and not by its position.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Optional kind filter: function, method, constructor, destructor, class, struct, union, enum, enum_constant, typedef, varglobal, varlocal, variable, field, namespace. | |
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| limit | No | Maximum results of one page (default 20, max 100). | |
| query | Yes | FTS5 search terms. 1-3 words, omit underscores. E.g. 'modem init' not 'modem_init'. Supports trailing wildcard 'modem*'. | |
| offset | No | Skip this many results. Reads the next page of a topic that many symbols carry. | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| project_only | No | Exclude vendor SDK code. When True, only application code. Default False. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It states 'Read-only: yes,' explains auto-reindexing and the non-blocking watcher daemon, details the progressive relaxation fallback steps with '_fallback' keys, excludes local variables, and cautions that llm_analysis is model-generated and not factual. It also describes the page notice and error/warning dicts. This is thorough and transparent beyond basic read-only status.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with clear headings (FTS5 syntax, Progressive relaxation, Kind filter, Returns). Core purpose and contrasts are front-loaded. While there is some redundancy between the Args section and the schema (repeating descriptions), most sentences add value given the tool's complexity. The length is justified, but it could be tightened slightly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 9 parameters, many siblings, and an output schema, the description covers all critical aspects: usage context, query syntax pitfalls, fallback behavior, output format (including page notice and error cases), and safety (read-only). The output schema exists, so the description need not detail every return field, but it explains the page notice and fallback keys. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100% (baseline 3), the description adds critical semantics: it explains the FTS5 underscore pitfall with concrete examples, clarifies pagination and offset behavior, distinguishes project vs project_root, and notes varlocal exclusion. These insights are essential for correct invocation and go well beyond the schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Find C/C++ symbols by name' and clarifies scope ('searches function/class/enum NAMES'). It differentiates from siblings by explicitly noting what it does NOT search ('Does NOT search function bodies') and pointing to alternatives (search_bodies, lookup_symbol). This makes the purpose unambiguous and distinguishable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit usage guidance: 'Use when you know the concept but not the exact name' and 'Prefer lookup_symbol when you already know the exact or prefix name.' It also contrasts with search_bodies for patterns in code. Additionally, it warns against underscores and explains the relaxation steps, giving clear when-to-use and when-not-to-use context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_contentA
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 current build configuration. 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_bodiesanswers WHICH DEFINITION holds the pattern, and takes the query literally (no wildcard, space = AND).search_contentanswers 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_TESTfound 6 files here and the same word found 5 throughsearch_bodies, the extra file holding the commentSelf 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.
Read-only: yes. Requires the FTS5 index with file content. May
auto-reindex stale files (non-blocking) — see search_code.
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.
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 20, max 100).
offset: Skip this many results. Reads the next page of a topic
that many files touch; the page notice names the offset to use.
project_only: When True, filter to project code only (files with is_project = 1).
variant: Build variant (multi-build project). Omit to use
default_variant. One query answers for ONE build.
image: Sysbuild image within the variant. Required when the
variant holds several: each image is a separate program.
Returns:
list of dicts. The page notice leads the answer — total,
offset, shown, more — and each that follows holds:
file, language, mtime, _match_snippet (highlighted excerpt around
the match).
Also, when it carries an answer:
* ``match_lines`` (list[int]) — line numbers of the lines that hold
a query term, up to 20. They are the line numbers of the file
itself: an inactive ``#ifdef`` branch is a blank line, thus the
count never shifts. Cite ``file:line`` from here.
The field is absent when FTS5 matched a variant of the token that
the term is not a substring of — ``SELF_TEST`` matches the file
that writes ``Self tester``, and no line holds ``self_test``.
Read ``_match_snippet`` in that case.
No match gives ``[]``. A dict with ``error`` means the query
failed. A stale index prepends a dict with ``warning`` + ``hint``,
and so does a query that FTS5 refuses to parse — the answer then
comes from the LIKE path and carries ``_fallback: "like"``.
| Name | Required | Description | Default |
|---|---|---|---|
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| limit | No | Maximum results of one page (default 20, max 100). | |
| query | Yes | FTS5 search terms for full file content. 1-3 words. E.g. 'InterruptIn', 'extern C'. Bare multi-word = OR-joined. | |
| offset | No | Skip this many results. Reads the next page of a topic that many files touch. | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| project_only | No | Exclude vendor SDK code. When True, only application code. Default False. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and excels. It discloses ifdef-filtering behavior, line-number preservation via blank lines, file-level results, LIKE-fallback with '_fallback: like', stale-index auto-reindex, read-only nature, and the subtle case where match_lines are absent because FTS matched a token variant. This is far beyond what structured data could convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but structured with distinct sections (purpose, sibling contrast, Args, Returns) and front-loaded with the core scoping statement. Some redundancy exists—'Covers the text that belongs to no definition' is repeated in the contrast paragraph—but given the 8-parameter complexity and zero annotation coverage, the length is mostly earned.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for a complex search tool with 8 parameters and no annotations. It covers error shapes (dict with 'error'), warnings/hints for stale or unparseable queries, page-notice fields (total, offset, shown, more), match_lines semantics, and the no-match case ([]). Nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although schema coverage is 100%, the description adds meaning beyond the schema: it explains the OR-joining and prefix-wildcarding of bare multi-word queries ('every term gets a trailing *'), the project vs project_root mutual exclusion, pagination semantics with offset/page-notice, and variant/image build scoping. These details materially change how an agent should construct calls.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb, resource, and scope: 'Find patterns in FULL file content — the whole file, not only the text that belongs to a definition.' It explicitly differentiates from siblings by contrasting with search_code (finds by NAME) and search_bodies (definitions only), so an agent can pick the right tool immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use guidance and names alternatives with clear conditions: 'To find a symbol by NAME... use search_code' and 'search_bodies answers WHICH DEFINITION... search_content answers WHICH FILES.' It even advises running both for a feature footprint and explains the fallback path when files_fts is missing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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_tandModemMsg*classes."delivery box"findsset_shipmentandget_zrtdata."power consumption"findsget_load_powerand 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 precision0.55— balanced (~1000 results)0.60— precise: ~175 avg, high precision (default)0.65— strict: few results, may miss relevant symbols
Source-aware ranking: the similarity of a project symbol is
multiplied by 1.2, and the similarity of every other symbol by 0.85.
The index marks each file as project code or not, thus the two tiers
are all there are. _similarity in the result holds the multiplied
score, and not the raw cosine distance.
Requires an LLM with an embedding model.
Falls back to search_code with a warning if the LLM is unavailable.
This tool names no build. It takes neither variant nor
image, and it answers for the build that get_active_build
reports as the active one. On a project that holds several builds,
use search_code or search_bodies to ask about one named build.
Read-only: yes. The fallback to search_code may auto-reindex stale
files (non-blocking).
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. 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. 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").
When the best similarity is below the relevance floor (0.68), the
result is one dict with ``warning``, ``_best_similarity`` (float),
``_fallback_suggestion`` (``"search_code"``), and ``_results`` (the
low-similarity results). Treat those results as noise, and use
``search_code`` instead.
When the LLM is not running, or the embedding fails, this tool falls
back to ``search_code``. The results then carry
``_method: "search_code_fallback"``, and a leading dict holds a
``warning`` with the reason.
No match gives ``[]``. One dict with ``error`` means the query
failed — check that key first.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum results (default 20, max 100). | |
| query | Yes | Natural language description, 5-15 words. E.g. 'parcel locker state machine' or 'how does the modem connect?'. | |
| project | No | 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. | |
| threshold | No | Minimum cosine similarity (0.0-1.0). Default 0.60. Use 0.55 for exploratory, 0.50 for broad search. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description must carry the full behavioral burden, and it does: it discloses read-only semantics, LLM dependency, the silent fallback to search_code with a warning, non-blocking auto-reindex of stale files, that _similarity holds the multiplied score and not raw cosine distance, and the 1.2/0.85 source-aware ranking tiers. Nothing behavioral is left to inference.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Long but well-organized with clear section headers, front-loaded purpose, and worked examples. Nearly every section earns its place. Minor redundancy exists — the fallback behavior is described both in the 'Requires an LLM' section and again in the Returns section — which is the only structural blemish in an otherwise disciplined layout.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex 5-parameter tool, the description is exhaustive: it covers the normal return shape, the warning-dict path when similarity is below the relevance floor, the LLM-unavailable fallback variant, empty results, and the error dict, instructing to check the error key first. Even with an output schema present, the description's coverage of edge cases and failure modes leaves nothing an agent needs to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds genuine value beyond the schema: per-threshold outcome guidance (0.50 exploratory vs 0.65 strict), query length recommendation (5-15 words), and clarification that project vs project_root are alternatives ('Give one of the two, not both'). This materially improves parameter understanding over the raw schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb+resource ('semantic search using pre-computed libclang symbol embeddings') and explicitly distinguishes itself from siblings by meaning ('Finds symbols by meaning, not by text'). Concrete worked examples ('parcel locker state', 'cell modem') make the intent unmistakable, and the contrast with search_code is drawn directly. An agent can tell exactly what this tool does without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides explicit when-to-prefer sections ('When to prefer over search_code') with concept-vs-keyword criteria and named alternatives (search_code, search_bodies) with reasons ('FTS5 is faster and more precise'). It even covers the multi-build case, steering to search_code/search_bodies when a specific build is targeted. This is exemplary usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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: yes. Slow (10-30 s) — delegates to the full
SMART_SEARCH pipeline (translate → rough_search → llm_query →
fts5_search → refine → embedding → adaptive_fusion → deduplicate →
expand_context → format).
This tool names no build. It takes neither variant nor
image, and it answers for the build that get_active_build
reports as the active one. On a project that holds several builds,
use search_code or search_bodies to ask about one named build.
Multi-phase approach:
Translate non-English queries
Rough search to gather sample symbols for naming conventions
LLM sees those samples + query and generates FTS5 terms
FTS5 search with generated terms
Refine: LLM checks results and course-corrects query terms
Semantic embedding search (cosine similarity re-rank)
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. 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 number of results (default 20). The pipeline holds it between 5 and 100: a smaller number becomes 5, because the re-rank steps need a set to choose from.
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.
When the LLM stalls, the tool gives the FTS5 results that it has.
The leading dict then holds ``_partial: True``, a ``warning`` with
the timeout, and a ``hint``. The result is incomplete: make the
query more specific, or increase the LLM timeout.
When the index is stale, a leading dict holds a ``warning`` and a
``hint`` to reindex.
No match gives ``[]``. One dict with ``error`` means the query
failed — check that key first.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum results (default 20, max 100). | |
| query | Yes | Natural language description, 5-15 words. E.g. 'how does the modem connect?' or 'handle BLE pairing failure'. | |
| project | No | 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. | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure, and it does so thoroughly: it states read-only, the slow 10-30s runtime, the full pipeline it delegates to, the fallback when the LLM is unavailable, partial results on LLM stall, stale-index warnings, and error handling. This is exemplary transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with headers and a clear flow. It front-loads purpose and usage, then pipeline, parameters, and returns. There is some redundancy (the 'prefer this' guidance appears twice), and the multi-phase enumeration is detailed but arguably necessary for such a complex tool. It earns a high score, though not a perfect one due to the repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool this complex, the description covers every aspect an agent needs: purpose, when to use it, how it works, parameter semantics, return format, edge cases (LLM stall, stale index, no match, error), and even the absence of a build parameter. It is fully self-sufficient even without the output schema, and it goes beyond what the schema provides.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds substantial value beyond the schema: it advises query specificity ('5–15 words works best'), explains that limit is clamped to the 5–100 range with the reason (re-rank needs a set), and clarifies the mutual exclusivity of project vs project_root. This is far beyond baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise statement of what the tool does: an LLM generates FTS5 keywords and searches the libclang index to find concepts by meaning. It also names the key sibling (search_code) and explains the distinction: use this when you don't know exact keywords. That is a specific verb+resource with clear sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit guidance is given on when to prefer this tool ('when you don't know the exact keywords') and when not to use it ('on a project that holds several builds, use search_code or search_bodies'). It names alternatives directly and states the condition that selects them, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
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).
timeout_ms: Maximum total execution time in milliseconds
(default 30000). Clamped to 1000–300000.
variant: Build variant (multi-build project). Omit to use
default_variant. One query answers for ONE build.
image: Sysbuild image within the variant. Required when the
variant holds several: each image is a separate program.
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).
A source entry with ``timed_out: True`` means that the path search
stopped at the time limit for that source. Its ``reachable: False``
thus means "not proved reachable", not "proved unreachable".
Never empty: one dict with ``info`` replaces an empty result.
Check that key first.
| Name | Required | Description | Default |
|---|---|---|---|
| image | No | Sysbuild image within the variant. Required when the variant holds several: each image is a separate program. | |
| limit | No | Maximum source functions to trace (default 15, max 15). | |
| project | No | 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 | No | Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build. | |
| max_depth | No | Maximum call path depth (default 8, max 20). | |
| to_symbol | Yes | Target symbol name. E.g. 'uart_send' or 'UART_DRIVER::send'. | |
| type_name | Yes | Type name to trace. E.g. 'SensorData' or 'Config::SensorData'. | |
| timeout_ms | No | Maximum total execution time in milliseconds (default 30000). | |
| project_root | No | Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It states 'Read-only. No side effects. Requires the reference index', discloses timeout behavior ('timed_out: True means ... not proved reachable'), and warns about the never-empty result with an info dict. This is substantial behavioral disclosure beyond the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well organized: purpose, limitations, prerequisites, arguments, return semantics. It is front-loaded with the core purpose. Some redundancy exists because the Args section largely echoes the input schema, but the added examples and clarifications justify most of the length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 9-parameter tool with no annotations, the description is highly complete. It covers prerequisites, limitations, parameter disambiguation, timeout semantics, empty-result behavior, and return structure. An agent has enough context to call it correctly without external knowledge.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds value with concrete examples for type_name and to_symbol, the 'Give one of the two, not both' guidance for project/project_root, and the timeout clamp 'Clamped to 1000–300000' which is not present in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Trace how C/C++ data of a given type flows to a target function via libclang call paths.' It distinguishes the tool from text-based search ('which text-based search cannot trace across translation units') and from sibling tools by naming the find_* family and find_call_path.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit usage context: 'Works best for synchronous driver stacks' and 'Cannot follow async flows (message queues, interrupts, RS485 callbacks).' It also routes users to alternatives: 'For exact call-graph queries use the find_* family; verify specific paths with find_call_path.'
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
30 tool updates
v0.32.0- Changed
explain_symbol4 fields changed- added
Input schema / properties / context_lines / minimumAdded value: +0 - changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - added
Input schema / properties / name / minLengthAdded value: +1 - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
find_all_callers_recursive5 fields changed- changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / max_depth / minimumAdded value: +1 - added
Input schema / properties / name / minLengthAdded value: +1 - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
find_call_path5 fields changed- added
Input schema / properties / from_name / minLengthAdded value: +1 - changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - added
Input schema / properties / max_depth / minimumAdded value: +1 - added
Input schema / properties / to_name / minLengthAdded value: +1 - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
find_callees_recursive5 fields changed- changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / max_depth / minimumAdded value: +1 - added
Input schema / properties / name / minLengthAdded value: +1 - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
find_callers6 fields changed- changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - changed
Input schema / properties / limit / descriptionPrevious value: -"Maximum results."New value: +"Maximum results of one page (default 50, max 200)." - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / name / minLengthAdded value: +1 - added
Input schema / properties / offsetAdded value: +{ + "default": 0, + "description": "Skip this many results. Reads the next page of a symbol with many call sites.", + "minimum": 0, + "title": "Offset", + "type": "integer" +} - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
find_dead_code5 fields changed- changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - changed
Input schema / properties / limit / descriptionPrevious value: -"Maximum results (default 100)."New value: +"Maximum results of one page (default 100, max 200)." - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / offsetAdded value: +{ + "default": 0, + "description": "Skip this many results. Reads the next page of a long report.", + "minimum": 0, + "title": "Offset", + "type": "integer" +} - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
find_hotspots5 fields changed- changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - changed
Input schema / properties / limit / descriptionPrevious value: -"Number of top-called functions to return (default 20)."New value: +"Number of top-called functions per page (default 20, max 50)." - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / offsetAdded value: +{ + "default": 0, + "description": "Skip this many results. Reads further down the ranking.", + "minimum": 0, + "title": "Offset", + "type": "integer" +} - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
find_indirect_call_sites4 fields changed- changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / name / minLengthAdded value: +1 - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
find_indirect_targets4 fields changed- changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / name / minLengthAdded value: +1 - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
find_references6 fields changed- changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - changed
Input schema / properties / limit / descriptionPrevious value: -"Maximum results."New value: +"Maximum results of one page." - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / name / minLengthAdded value: +1 - added
Input schema / properties / offsetAdded value: +{ + "default": 0, + "description": "Skip this many results. Reads the next page of a symbol with many references.", + "minimum": 0, + "title": "Offset", + "type": "integer" +} - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
find_variables4 fields changed- changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / name / minLengthAdded value: +1 - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
find_wrapper_callers5 fields changed- added
Input schema / properties / class_name / minLengthAdded value: +1 - changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - changed
Input schema / properties / limit / descriptionPrevious value: -"Maximum wrapper method results (default 50)."New value: +"Maximum wrapper method results (default 50, max 50)." - added
Input schema / properties / limit / minimumAdded value: +1 - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
get_class_members3 fields changed- added
Input schema / properties / class_name / minLengthAdded value: +1 - changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
get_file_map4 fields changed- added
Input schema / properties / file_path / minLengthAdded value: +1 - changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - added
Input schema / properties / max_per_kind / minimumAdded value: +0 - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
get_inheritance_chain3 fields changed- added
Input schema / properties / class_name / minLengthAdded value: +1 - changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
get_method_overrides3 fields changed- changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - added
Input schema / properties / method_name / minLengthAdded value: +1 - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
get_source3 fields changed- changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - added
Input schema / properties / name / minLengthAdded value: +1 - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
get_symbol_context3 fields changed- changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - added
Input schema / properties / name / minLengthAdded value: +1 - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
get_template_instances5 fields changed- changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - changed
Input schema / properties / limit / descriptionPrevious value: -"Maximum results (default 50)."New value: +"Maximum results (default 50, max 200)." - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / template_name / minLengthAdded value: +1 - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
get_vector_table3 fields changed- changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - added
Input schema / properties / limit / minimumAdded value: +1 - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
lookup_symbol5 fields changed- changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / name / minLengthAdded value: +1 - added
Input schema / properties / offsetAdded value: +{ + "default": 0, + "description": "Skip this many results. Pages through a name that many classes share, such as 'read' or 'write'.", + "minimum": 0, + "title": "Offset", + "type": "integer" +} - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
read_file5 fields changed- added
Input schema / properties / end_line / minimumAdded value: +0 - added
Input schema / properties / file_path / minLengthAdded value: +1 - changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - added
Input schema / properties / start_line / minimumAdded value: +0 - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
reindex_file1 field changed- added
Input schema / properties / file_path / minLengthAdded value: +1
- Changed
reindex_file_impl1 field changed- added
Input schema / properties / file_path / minLengthAdded value: +1
- Changed
search_bodies6 fields changed- changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - changed
Input schema / properties / limit / descriptionPrevious value: -"Maximum results (default 20, max 100)."New value: +"Maximum results of one page (default 20, max 100)." - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / offsetAdded value: +{ + "default": 0, + "description": "Skip this many results. Reads the next page of a pattern with many hits.", + "minimum": 0, + "title": "Offset", + "type": "integer" +} - added
Input schema / properties / query / minLengthAdded value: +1 - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
search_code6 fields changed- changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - changed
Input schema / properties / limit / descriptionPrevious value: -"Maximum results (default 20, max 100)."New value: +"Maximum results of one page (default 20, max 100)." - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / offsetAdded value: +{ + "default": 0, + "description": "Skip this many results. Reads the next page of a topic that many symbols carry.", + "minimum": 0, + "title": "Offset", + "type": "integer" +} - added
Input schema / properties / query / minLengthAdded value: +1 - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
search_content6 fields changed- changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - changed
Input schema / properties / limit / descriptionPrevious value: -"Maximum results (default 20, max 100)."New value: +"Maximum results of one page (default 20, max 100)." - added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / offsetAdded value: +{ + "default": 0, + "description": "Skip this many results. Reads the next page of a topic that many files touch.", + "minimum": 0, + "title": "Offset", + "type": "integer" +} - added
Input schema / properties / query / minLengthAdded value: +1 - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
- Changed
semantic_search4 fields changed- added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / query / minLengthAdded value: +1 - added
Input schema / properties / threshold / maximumAdded value: +1 - added
Input schema / properties / threshold / minimumAdded value: +0
- Changed
smart_search2 fields changed- added
Input schema / properties / limit / minimumAdded value: +1 - added
Input schema / properties / query / minLengthAdded value: +1
- Changed
trace_data_flow9 fields changed- changed
Input schema / properties / image / descriptionPrevious value: -"Sysbuild image name within the variant (multi-project). Omit for all images of the variant."New value: +"Sysbuild image within the variant. Required when the variant holds several: each image is a separate program." - changed
Input schema / properties / limit / descriptionPrevious value: -"Maximum source functions to trace (default 15)."New value: +"Maximum source functions to trace (default 15, max 15)." - added
Input schema / properties / limit / minimumAdded value: +1 - changed
Input schema / properties / max_depth / descriptionPrevious value: -"Maximum call path depth (default 8)."New value: +"Maximum call path depth (default 8, max 20)." - added
Input schema / properties / max_depth / minimumAdded value: +1 - added
Input schema / properties / timeout_ms / minimumAdded value: +1 - added
Input schema / properties / to_symbol / minLengthAdded value: +1 - added
Input schema / properties / type_name / minLengthAdded value: +1 - changed
Input schema / properties / variant / descriptionPrevious value: -"Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants."New value: +"Build variant (multi-build project). Omit to use default_variant. One query answers for ONE build."
39 tool updates
v0.30.0- Changed
check_dependencies3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted. Pass explicitly when the project is not the server cwd."New value: +"Project root. Auto-detected if omitted. Pass explicitly when the project is not the server cwd. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
check_ollama3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted. Used to locate LLM config. Falls back to auto-detection when omitted."New value: +"Project root. Auto-detected if omitted. Used to locate LLM config. Falls back to auto-detection when omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
configure_llm3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
explain_symbol3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
find_all_callers_recursive3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
find_call_path3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
find_callees_recursive3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
find_callers3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
find_dead_code3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
find_hotspots3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
find_indirect_call_sites3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root directory. Auto-detected if omitted."New value: +"Project root directory. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
find_indirect_targets3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
find_references3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
find_variables3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
find_wrapper_callers3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
get_active_build4 fields changed- added
Input schema / additionalPropertiesAdded value: +false - changed
Input schema / properties / fast / descriptionPrevious value: -"When True (default), skip the per-file stat scan. modified_files_count is then always 0. header_affected_tus still comes from the cached manifest hashes when manifest_verification is 'full'."New value: +"When True (default), reuse the cached manifest hashes for the header check. Both modes count modified files. Pass False to recompute the header hashes, which is far slower." - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root directory. Auto-detected from CWD if omitted."New value: +"Project root directory. Auto-detected from CWD if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
get_class_members4 fields changed- added
Input schema / additionalPropertiesAdded value: +false - changed
Input schema / properties / class_name / descriptionPrevious value: -"Class or struct name. E.g. 'ModemManager' or 'zbox::ZMODEM'."New value: +"Class or struct name. E.g. 'ModemManager' or 'the Mbed project::ZMODEM'." - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
get_environment_status3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted. Pass explicitly when the project is not the server cwd."New value: +"Project root. Auto-detected if omitted. Pass explicitly when the project is not the server cwd. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
get_file_map3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
get_inheritance_chain3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
get_method_overrides3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
get_project_info1 field changed- added
Input schema / additionalPropertiesAdded value: +false
- Changed
get_source3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
get_symbol_context3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
get_template_instances3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Added
get_vector_table - Changed
list_projects3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted. Pass to distinguish multiple indexed projects."New value: +"Project root. Auto-detected if omitted. Pass to distinguish multiple indexed projects. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
list_variants3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root directory. Auto-detected from CWD if omitted."New value: +"Project root directory. Auto-detected from CWD if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
lookup_symbol3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root directory. Auto-detected from CWD if omitted."New value: +"Project root directory. Auto-detected from CWD if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
read_file6 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / end_lineAdded value: +{ + "default": 0, + "description": "Last line to return, 1-based inclusive. 0 = to the end of the file.", + "title": "End Line", + "type": "integer" +} - added
Input schema / properties / line_numbersAdded value: +{ + "default": false, + "description": "Prefix every line with its line number, like get_source. Default False (bare text).", + "title": "Line Numbers", + "type": "boolean" +} - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those." - added
Input schema / properties / start_lineAdded value: +{ + "default": 0, + "description": "First line to return, 1-based inclusive. 0 = from the start of the file.", + "title": "Start Line", + "type": "integer" +}
- Changed
reindex_file4 fields changed- added
Input schema / additionalPropertiesAdded value: +false - changed
Input schema / properties / file_path / descriptionPrevious value: -"Path to source file to re-parse. Must be in compile_commands.json."New value: +"Path to the file to re-parse. A source file must be in compile_commands.json. A header goes through one translation unit that includes it, and the result then carries a warning about the other units." - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
reindex_file_impl4 fields changed- added
Input schema / additionalPropertiesAdded value: +false - changed
Input schema / properties / file_path / descriptionPrevious value: -"Absolute or project-relative path to the source file to re-parse. Must have a matching entry in compile_commands.json."New value: +"Absolute or project-relative path to the file to re-parse. A source file must have an entry in compile_commands.json. A header is re-parsed through one translation unit that includes it, and the result then carries a warning that other units can still hold stale symbols." - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root directory. Auto-detected from cwd if omitted."New value: +"Project root directory. Auto-detected from cwd if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
reset_index3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
search_bodies4 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those." - changed
Input schema / properties / query / descriptionPrevious value: -"FTS5 search terms for function bodies. 1-3 words. E.g. 'attach', 'callback', 'rise'."New value: +"FTS5 search terms for the body of a definition. 1-3 words. E.g. 'attach', 'callback', 'rise'."
- Changed
search_code3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
search_content3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
semantic_search3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
smart_search3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
- Changed
trace_data_flow3 fields changed- added
Input schema / additionalPropertiesAdded value: +false - added
Input schema / properties / projectAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "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.", + "title": "Project" +} - changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted."New value: +"Project root. Auto-detected if omitted. This field also accepts a project name or a project_id, but project is the clear field for those."
1 tool update
v0.27.6- Changed
get_active_build1 field changed- changed
Input schema / properties / fast / descriptionPrevious value: -"When True (default), skip per-file stat scan — faster but modified_files_count and header_affected_tus may be 0."New value: +"When True (default), skip the per-file stat scan. modified_files_count is then always 0. header_affected_tus still comes from the cached manifest hashes when manifest_verification is 'full'."
30 tool updates
v0.25.3- Added
check_dependencies - Changed
check_ollama1 field changed- changed
Input schema / properties / project_root / descriptionPrevious value: -"Project root. Auto-detected if omitted. Ignored by this tool."New value: +"Project root. Auto-detected if omitted. Used to locate LLM config. Falls back to auto-detection when omitted."
- Added
configure_llm - Changed
explain_symbol2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
find_all_callers_recursive2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
find_call_path2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
find_callees_recursive2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
find_callers2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
find_dead_code2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
find_hotspots2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
find_indirect_call_sites2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
find_indirect_targets2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
find_references2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
find_variables2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
find_wrapper_callers2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
get_class_members2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Added
get_environment_status - Changed
get_file_map2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
get_inheritance_chain2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
get_method_overrides2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
get_source2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
get_symbol_context2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
get_template_instances2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Added
list_variants - Changed
lookup_symbol2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
read_file2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
search_bodies2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
search_code2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
search_content2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
- Changed
trace_data_flow2 fields changed- added
Input schema / properties / imageAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sysbuild image name within the variant (multi-project). Omit for all images of the variant.", + "title": "Image" +} - added
Input schema / properties / variantAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Build variant name (multi-project). Omit to use default_variant or fail-closed. Use '*' for all variants.", + "title": "Variant" +}
5 tool updates
v0.25.2- Added
find_variables - Changed
get_active_build1 field changed- added
Input schema / properties / fastAdded value: +{ + "default": true, + "description": "When True (default), skip per-file stat scan — faster but modified_files_count and header_affected_tus may be 0.", + "title": "Fast", + "type": "boolean" +}
- Changed
get_inheritance_chain1 field changed- changed
Input schema / properties / class_name / descriptionPrevious value: -"Class or struct name to get inheritance information for. E.g. 'UART_DRIVER' or 'zbox::ZMODEM'."New value: +"Class or struct name to get inheritance information for. E.g. 'UART_DRIVER' or 'comm::MODEM'."
- Changed
search_code1 field changed- changed
Input schema / properties / kind / descriptionPrevious value: -"Optional kind filter: function, method, class, struct, union, enum, typedef, variable, field, namespace."New value: +"Optional kind filter: function, method, constructor, destructor, class, struct, union, enum, enum_constant, typedef, varglobal, varlocal, variable, field, namespace."
- Changed
trace_data_flow1 field changed- added
Input schema / properties / timeout_msAdded value: +{ + "default": 30000, + "description": "Maximum total execution time in milliseconds (default 30000).", + "title": "Timeout Ms", + "type": "integer" +}
1 tool update
v0.24.0- Changed
get_symbol_context1 field changed- removed
Input schema / properties / project_onlyRemoved value: -{ - "default": true, - "description": "When True (default), filters callers and callees to project paths (excludes SDK/vendor).", - "title": "Project Only", - "type": "boolean" -}
2 tool updates
v0.22.1- Added
get_project_info - Added
read_file
4 tool updates
v0.18.2- Changed
find_dead_code1 field changed- changed
Input schema / properties / project_only / descriptionPrevious value: -"When True (default), auto-excludes SDK/vendor paths (mbed-os/%, .pio/%, zephyr/%, build/%) and applies project config exclude_paths. Set False to see all results."New value: +"When True (default), auto-excludes SDK/vendor paths based on the detected build system and applies project config exclude_paths. Set False to see all results."
- Changed
search_bodies2 fields changed- changed
Input schema / properties / project_only / descriptionPrevious value: -"Exclude vendor SDK code (mbed-os/, .pio/, zephyr/, build/). When True, only your application code (src/, lib/). Default False."New value: +"Exclude vendor SDK code. When True, only application code. Default False." - changed
Input schema / properties / query / descriptionPrevious value: -"FTS5 search terms for function bodies. 1-3 words. E.g. 'attach', 'NVIC_SetVector', 'rise'."New value: +"FTS5 search terms for function bodies. 1-3 words. E.g. 'attach', 'callback', 'rise'."
- Changed
search_code1 field changed- changed
Input schema / properties / project_only / descriptionPrevious value: -"Exclude vendor SDK code (mbed-os/, .pio/, zephyr/). When True, only application code (src/, lib/, app/). Default False."New value: +"Exclude vendor SDK code. When True, only application code. Default False."
- Changed
search_content1 field changed- changed
Input schema / properties / project_only / descriptionPrevious value: -"Exclude vendor SDK code (mbed-os/, .pio/, zephyr/, build/). When True, only your application code (src/, lib/). Default False."New value: +"Exclude vendor SDK code. When True, only application code. Default False."
TDQS
Scored across 39 tools
The search tools heavily overlap: search_code, search_bodies, search_content, semantic_search, smart_search, and lookup_symbol all find code but with subtly different scopes, requiring the agent to internalize lengthy 'when to use' rules. The reindex pair reindex_file and reindex_file_impl are nearly identical in name and description. Some tools are distinct (get_vector_table, find_dead_code), but the search family creates real selection risk.
Naming is a mix of get_*, find_*, search_*, lookup_, list_, reset_, reindex_, check_, and configure_ verbs. Within groups it is consistent (find_callers, find_callees_recursive, find_references), but find_all_callers_recursive vs find_callers_recursive vs find_callers and reindex_file vs reindex_file_impl break the pattern. The recurring shared args and project/variant/image suffixes are consistent, but verb style is not unified.
39 tools is on the heavy side for a code-intelligence server. The core domain — search, call graph, symbols, files, build/index management — is broad but the count is inflated by near-duplicate tools (reindex_file/reindex_file_impl, search_code/search_content overlapping bodies, six search tools). A well-scoped set would sit closer to 20-25 tools.
The surface covers the firmware-analysis domain very well: symbol lookup, text search, call graphs, references, data flow, inheritance, dead code, vector tables, file reading, index health, project discovery, and LLM config. Missing operations are minor — there is no tool to list all symbols in a namespace or to get diffs between build variants (only per-build querying), and no explicit index-trigger tool beyond reindex_file, but these are workaround-level gaps.
Maintenance
Related MCP Connectors
Ask a codebase what calls what: search, blast radius, paths between symbols, and diffs.
Code intelligence for coding agents: semantic, AST, graph, and full-text search. 279+ languages.
Code intelligence for LLMs. Analyze, search, and retrieve code from any public git repository.
Shared memory for coding agents. Stop re-explaining your codebase every session.
Related MCP Servers
- AlicenseAqualityAmaintenanceKnot is a semantic and structural codebase indexer designed for AI coding agents and developers navigating large projects. It combines vector search and graph traversal to find code by meaning, analyze impact via reverse dependencies, and explore file architectures.65MIT

Semantic Code Search MCPofficial
FlicenseNot gradedqualityDmaintenanceProvides AI coding agents with structured access to indexed codebases via semantic search, symbol analysis, and file reading tools.12-- FlicenseNot gradedqualityBmaintenanceBuilds a semantic knowledge graph of C++ code and exposes 9 MCP tools for AI assistants to search classes, functions, inheritance, callers, callees, overrides, and more.3-
- AlicenseNot gradedqualityBmaintenanceEnables LLM agents to efficiently understand and navigate a codebase by providing semantic search over symbols and a reference graph, replacing expensive grep/glob calls with structured tools like definition lookup, caller/callee queries, and change-impact analysis.2MIT