Skip to main content
Glama

get_project_status

Returns the health of a C/C++ project's index and its builds, indicating if a reindex is needed. Call this before any other fw-context tool.

Instructions

MANDATORY FIRST CALL for C/C++ projects. Return the health of the index of the project, and the list of its builds — check it before you use any other fw-context tool, and call it again while you wait for a reindex.

Read-only with two exceptions, and it spawns no subprocess — the startup daemon thread and the file watcher own the background reindex. The exceptions: the last index run can leave a marker that says that the build is not there, and when the tool finds that build again, it removes the marker. It also removes a reindex.pid or a reindex.pending of a process that no longer runs. It creates no .fw-context file in a project that is not initialized. It takes no variant and no image: it reports every build. For the detail of one build (its config_hash, memory map, defines), call get_build_info.

builds lists every build of the index. A project of more than one build has no active build: every query tool must get the parts of one entry that are not empty, its variant, its image, or the two. Select the build from the task, and ask the user when the task does not identify one.

Act on reindex_state of the build that the task needs, in builds (a project of one build has it at the top level too):

  • null — the index of the build is current. Continue.

  • "reindexing" or "pending" — the index of the build is not current, and an index run is active or scheduled. Wait, and call this tool again after about 30 s. Continue with the old index only when the user tells you to.

  • "not_scheduled" — the index of the build is not current, and no run updates it. Tell the user the command that the reasons name.

  • "failed" — the last index run failed. Give its text to the user: it names the command that repairs it.

Each query answer carries the state of its build as index_state, from quick checks only. A query thus can miss a changed header, a changed file that its answer does not name, or a new source file when its answer is not empty. This tool does the full check.

status gives the state of the project:

  • "ready" — up to date. Continue.

  • "reindexing" — background reindex running or scheduled, or fw-context builds new source files on its own. reindex_state of a build tells whether that build waits for the run. reindex_progress holds the last log line of a running reindex.

  • "reindex_needed" — the last index run failed, the build is not there, schema mismatch, an old row format, a changed or missing compile_commands.json, a checkout of another branch, tag or commit since the index, or a source file that compile_commands.json does not cover and fw-context will not build itself. A changed compile_commands.json includes one that fw-context cannot compare with the index. Queries still work on existing data. Read reindex_reasons: each reason names the action that it needs.

    Read bg_reindex_running before you name any command here. A run already under way does the work, thus a second one only waits on the same lock, and index_message and the checkout reason both say so. That field covers a run of the daemon AND a run the operator started, and also work that the daemon has scheduled and not yet started — the arguments of no run are readable, thus a reason that needs --build can 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. Run fw-context index.

  • "not_initialized" — run fw-context init.

  • "config_error" — a config file cannot be used: it cannot be read, it is not UTF-8 or not valid TOML, a section is not a table, a key that selects the data or where data goes has a value of the wrong type, or a URL is not valid. config_file names it, and index_message gives the problem. Correct the file, or run fw-context doctor --fix --only config when the message names it: it removes each value that cannot be used. fw-context init cannot repair it.

A project of several builds gets the worst status of its builds. A reason that every build gives comes one time, and any other reason names its build: build <variant>/<image>: <reason>.

A failure sets NO status. An index with no build config 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. A database that fw-context cannot read (damage, no access) makes the call fail with the error of SQLite. The message of the check db-integrity of check_dependencies tells if it is damaged.

Seven conditions set reindex_needed: a failed last index run, a build that is not there, an outdated schema, an outdated ROW FORMAT, a changed or missing compile_commands.json, a checkout of another branch, tag or commit since the index, and a source file that is on disk but absent from compile_commands.json when fw-context will not build it on its own. A missing build, a missing compile_commands.json, a checkout and such a source file need the action that makes compile_commands.json again: a build, or for a database of the user ([index] compile_commands) a new file from the user. A plain reindex reads the same file again, and it has no translation unit for a new source file and skips it without a word. A failed run needs the repair that its reason names first. 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. An index written before fw-context-rows/4 parsed a GCC build with guessed toolchain headers and the macros of clang: an ESP32 or AVR index there holds host headers from /usr/include and takes the #if branches of the host, for example #if __XTENSA__ as false, and an ARM index saw __GNUC__ 4. A build whose GCC driver does not answer the query keeps that fault also after /4; the index run names such a compiler in a warning.

client_restart_required is the OPPOSITE case, and no command repairs it. This server process does not run the code that it must run. Two causes set it, and client_restart_reason names each one that applies:

  • The index carries a NEWER row format than this 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.

  • The operator installed a different fw-context after the LLM client started this process. This cause does not need an index, thus it shows also for not_initialized, no_index and config_error.

status therefore stays as it is 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.

update_notice is not a status either. It shows when PyPI has a newer fw-context than the installed one. Tell the operator one time, and do NOT upgrade fw-context yourself: the operator knows the tool that installed it. After a request that succeeded, the server asks PyPI again only after 24 hours. The request runs in a background thread, and no tool waits for it. [updates] check = false in the global config, or FW_CONTEXT_NO_UPDATE_CHECK=1, stops 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. Read modified_files_count 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, and every vendor symbol too when analyze_vendor is True. Vendor symbols excluded by analyze_vendor=False never block it, thus vendor.total large with vendor.analyzed=0 is expected, not a defect. index_message ends with the same counts as text.

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: {project_id, project_root, build_system, schema_version (int — DB schema version), current_schema (int — code expects), vendor_paths (list[str] — config index.vendor_paths), project_paths (list[str] — config index.project_paths), status (str — "ready"|"reindexing"|"reindex_needed"|"no_index"| "not_initialized"|"config_error"; a failure sets no status and gives error alone), config_file (str — only with "config_error": the file that cannot be used), reindex_needed (bool), reindex_reasons (list[str] — why a reindex is needed, empty when False, except that a new source file that fw-context builds on its own is listed while reindex_needed is False. Some of them ask for a build rather than a plain reindex. For example, after a checkout of another branch, tag or commit, compile_commands.json belongs to the OLD checkout 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 a build needs a reindex or has stale header dependencies), index_message (str — human-readable summary of index state), builds (list[dict] — every build: {variant, image, board, symbol_count, file_count, indexed_at, status, reindex_state (str or None — "reindexing", "pending", "not_scheduled", "failed", or None for a current index), reindex_needed, stale, modified_files_count, header_affected_tus, reasons}, and manifest_verification on a build whose manifest is not "full"), declared_not_indexed (list[dict], optional — each variant that the config declares and the index does not hold: {variant, command}; no query reaches it until the command ran), bg_reindex_running (bool), reindex_progress (str or None — last log line when reindex is running), _warning (str, optional — when the manifest verification of a build is not "full"), vec_available (bool), vec_error (str, optional), client_restart_required (bool, optional — only when True), client_restart_reason (str, optional — with the field above), update_notice (str, optional — a newer release is on PyPI)}

A project of ONE build also gets the fields of that build at the
top level: indexed_at (str — "YYYY-MM-DD HH:MM:SS" in UTC, the
completion time of the last full index), first_indexed_at,
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 source files with
stale header dependencies; a file that compile_commands.json lists
more than once counts once), manifest_verification (str — "full"
when manifest.json exists, "partial" when it exists and the
embeddings are not complete, "none" without one), analysis (dict — LLM
analysis coverage split by project/vendor: {model, analyze_vendor,
project: {analyzed, skipped, total}, vendor: {analyzed, skipped,
total}, complete}), description (str).  A project of several
builds gets no sums: the counts of each build are in ``builds``,
and ``reference_count``, ``analysis``, ``description`` and
``first_indexed_at`` of a build are in ``get_build_info``.

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``.  For ``"config_error"``, it
adds ``config_file``.  The two version fields
(``client_restart_*`` for an upgrade, ``update_notice``) can come
with every result, these two included.  ``config_warnings`` (a
list) can come with each result that has a ``status`` other than
``"config_error"``: values of a config file that fw-context did not
use.  Tell the user each line.

Input Schema

NameRequiredDescriptionDefault
fastNoWhen 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.
projectNoProject 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_rootNoProject 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.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Addedv0.32.1

TDQS

A4.4/5.0
Behavior5/5

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 exhaustively: read-only except for two named side effects (removing a stale 'not there' marker, removing orphaned reindex.pid/reindex.pending), no subprocess spawned, no .fw-context file created on uninitialized projects. It also discloses failure behavior ('A failure sets NO status', a dict holding 'error' alone), SQLite failure modes, and that client_restart_required cannot be repaired by any command.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose and usage guidance are correctly front-loaded, but the body is massively over-long and repetitive — the seven reindex_needed conditions are enumerated twice ('Seven conditions set reindex_needed' after an earlier full list), and the status/reindex_state semantics are restated in multiple places. Much of the volume is a Returns dump that could be trimmed or made uniform.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with many status states, no annotations, and no output schema, the description is complete enough to act on: every status value, every reindex_state value, the error-only shape, and the per-build vs single-build result split are all documented, along with the UTC-vs-local-time caveat for indexed_at and modified_files_count.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

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 largely restates the schema for project/project_root and fast, adding only a light clarification that project_root also accepts a project name/id. It does not add format or edge-case detail beyond what the structured fields already provide.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening states a specific verb and resource ('Return the health of the index of the project, and the list of its builds') and marks its position in the workflow ('MANDATORY FIRST CALL for C/C++ projects'). It explicitly distinguishes itself from siblings, routing single-build detail to get_build_info and project names to list_projects.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit when-to-use ('check it before you use any other fw-context tool, and call it again while you wait for a reindex') and names concrete alternatives with the conditions that select them ('For the detail of one build ... call get_build_info'). It also tells the agent what NOT to do, e.g. 'Do NOT run a reindex for this field' and 'do NOT upgrade fw-context yourself'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.