Releases: turbyho/fw-context-mcp
Release list
v0.22.3 — Manifest-based staleness, path normalization, daemon mode
Overview
Release 0.22.3 replaces the legacy .d dependency-tracking files with a
manifest.json manifest, fixes duplicate file-path entries in the database,
adds daemon mode for background auto-reindexing, and ensures all test fixtures
clean up their index directories after tests.
IMPORTANT: After upgrading, run fw-context index --force on each project
to rebuild the index with the new manifest format and correctly normalized
file paths.
Changes
Features
- manifest.json replaces .d files — a single
manifest.jsonin the index
directory tracks every translation unit: source hashes, header hashes,
generated/SDK markers, and staleness checks. This replaces per-TU.d
files that were scattered across the build tree and often stale.
Thecompile_commands.jsonconfig hash is now the manifest hash, making
staleness detection consistent and reliable. - Daemon mode for background auto-reindex — the MCP server can now run a
background daemon that watches for file changes and reindexes stale
translation units automatically. Controlled via the[daemon]config
section. - manifest.json verification —
fw-context indexrecords a
manifest_verificationstatus (full/partial/unverified) in the
build config, giving tooling visibility into index completeness.
Fixes
- Normalize file paths in files table to prevent duplicates — file paths
are now consistently normalized to project-relative form, preventing the
same file from appearing under both an absolute and relative path in the
files table. - _normalize_file_path resolves project_root before relativizing — fixes
an edge case where a non-resolved root produced incorrect relative paths.
Applied consistently across ops, maintenance, and fallback modules.
Refactoring
- dep_files.py removed (151 lines) — replaced by
indexer/manifest.py
(503 lines). The new module uses content hashing over the source file +
its transitive project headers, with SDK and generated headers excluded
from staleness checks. - All 11 builders updated — each builder (
arduino,cmake,esp_idf,
iar,keil,makefile,manual,mbed_os,platformio,zephyr,
stubs) now generates entries for the manifest during the build step. - Staleness detection rewritten —
shared/stale.pynow uses the manifest
instead of.dfiles, with trusted-SDK-header and generated-header
exclusion logic. - Config hash computation —
config_hash.pynow derives the hash from the
manifest (compiler arguments, source file set), excluding source content
hashes so formatting-only changes don't trigger a full reindex. fw-context init --projectreplaces project-init — theproject-init
command was removed in favor ofinit --project.- MCP server maintenance endpoint —
/maintenancereturns manifest
verification status and stale file details for health-check tooling.
Maintenance
- Test fixtures clean up index directories — 8 class-scoped fixtures in
test_system_indexing.pyand 4 fixtures/tests intest_index_integrity.py
now delete their~/.fw-context/index/<project_id>/directories after
tests finish, preventing accumulation of stale multi-GB test indexes.
Documentation
docs/installation.md— updated for manifest-based workflowdocs/tools.md— updated tool descriptions to reflect new capabilities
New files
| File | Purpose |
|---|---|
src/fw_context_mcp/indexer/manifest.py |
Manifest generation, loading, staleness checks |
tests/test_manifest.py |
335-line test suite for manifest operations |
Removed files
| File | Reason |
|---|---|
src/fw_context_mcp/indexer/dep_files.py |
Replaced by manifest.py |
tests/test_dep_file.py |
Replaced by test_manifest.py |
src/fw_context_mcp/mcp/shared/context.py |
Unused shared context helpers |
Changed files
| File | Change |
|---|---|
src/fw_context_mcp/cli.py |
init --project, daemon control |
src/fw_context_mcp/indexer/builders/*.py |
All 11 builders emit manifest entries |
src/fw_context_mcp/indexer/config_hash.py |
Manifest-based hash |
src/fw_context_mcp/indexer/db.py |
Schema for manifest metadata |
src/fw_context_mcp/indexer/ops.py |
Path normalization, manifest integration |
src/fw_context_mcp/indexer/runner.py |
Manifest generation pipeline |
src/fw_context_mcp/indexer/validator.py |
Manifest-aware validation |
src/fw_context_mcp/mcp/daemon.py |
Background auto-reindex daemon |
src/fw_context_mcp/mcp/handlers/maintenance.py |
Manifest verification, reindex with normalization |
src/fw_context_mcp/mcp/handlers/search.py |
Manifest-aware staleness |
src/fw_context_mcp/mcp/shared/stale.py |
Manifest-based staleness detection |
src/fw_context_mcp/utils.py |
Shared helpers for path ops |
tests/test_incremental_reindex.py |
Expanded reindex coverage with manifest |
tests/test_index_integrity.py |
Manifest verification in integrity tests |
tests/test_system_indexing.py |
Manifest verification + index cleanup |
tests/test_builders/*.py |
Updated for manifest-based builder protocol |
pyproject.toml, server.json, glama.json |
Bump to 0.22.3 |
docs/installation.md, docs/tools.md |
Manifest workflow docs |
Breaking changes
None. The manifest.json is created alongside the existing index database
and is backward-compatible. Existing indexes continue to work, but a
reindex (fw-context index --force) is required to get manifest-based
staleness detection and corrected file paths.
Upgrade instructions
pip install --upgrade fw-context-mcp
fw-context index --force # run in each project rootv0.22.2 — MCP server returns clear error for uninitialized projects
Overview
Fixes the self-bootstrapping issue where the MCP server would crash or return cryptic errors when the project had not been initialized with 'fw-context init' or indexed with 'fw-context index'. All MCP tools now return a clear, actionable error message instructing the user to run the required CLI commands.
Fixes
- Self-bootstrapping: MCP server no longer crashes on uninitialized projects. Server startup explicitly validates project initialization and index existence, setting a sentinel that all tool handlers check before attempting database access.
- Clear error messages: All 33 tools return consistent, numbered instructions (fw-context init, fw-context index --build, restart) when the project is not ready.
| File | Change |
|---|---|
src/fw_context_mcp/mcp/server.py |
Startup test for project_id + index DB existence before mcp.run() |
src/fw_context_mcp/mcp/shared/context.py |
New sentinel mechanism (_set_server_init_error, _check_server_ready) checked in _db_path() and _resolve_context() |
Breaking changes
None.
v0.22.1 — Fix MCP server crash, init fallback for headless environments
Overview
Patch release fixing two issues that prevented fw-context from working
in minimal environments (Docker, CI, headless servers) where no AI
assistants are installed.
Changes
Fixes
- MCP server crash on uninitialized project — server no longer crashes
at startup whenfw-context inithasn't been run. Catches
ProjectNotInitializedErrorand starts without database support. - Init fallback for headless environments —
fw-context initnow
falls back to Claude Code configuration when no AI assistants are
detected, ensuring full project initialization succeeds in Docker
containers, CI, and headless build servers.
| File | Change |
|---|---|
src/fw_context_mcp/mcp/server.py |
Wrap _db_path() in try/except, catch ProjectNotInitializedError |
src/fw_context_mcp/cli.py |
Fall back to Claude Code when no AI tools detected |
glama.json, pyproject.toml, server.json |
Version bump 0.22.0 → 0.22.1 |
Breaking changes
None.
v0.22.0 — Consolidated project setup
Overview
fw-context project-init has been merged into fw-context init. A single command now handles everything: MCP registration, instruction injection, config file creation, .gitignore management, and diagnostic output (build system, compile_commands.json status, index health).
Changes
Features
- Unified project setup —
fw-context initnow creates config files, manages .gitignore, validates config keys, and prints diagnostics in one step - Diagnostic output — build system detection, compile_commands.json status, and index health are shown after setup, even when no AI tools are detected
- Auto-fix mode — missing config keys and .gitignore entries are fixed automatically during init
Fixes
- DB connection properly closed — connection cleanup moved to finally block
- Consistent project_root resolution — uses resolve_project_root() like other commands
- No duplicate build system scan — detect_build_system() called once
| File | Change |
|---|---|
src/fw_context_mcp/cli.py |
Merged project-init into init, removed cmd_project_init |
docs/tools.md |
Removed project-init section |
docs/configuration.md |
Updated reference from project-init to init |
tests/test_system_indexing.py |
Fallback to manual config in CI without AI tools |
Breaking changes
fw-context project-initremoved — usefw-context initinstead- No read-only verify mode —
initalways applies fixes (config, .gitignore)
v0.21.0 — daemon staleness fixes, server split, prefer_project
Overview
v0.21.0 delivers a new daemon architecture for fw-context watch with correct
staleness detection, server code reorganization into handler modules, a new
prefer_project parameter for lookup_definition, and shared dep-file parsing.
All users of the watch daemon should upgrade — stale detection is now reliable.
Changes
Features
- Daemon staleness detection overhaul — new
daemon.pymodule replaces
ad-hoc checks inbackground.py. Uses PID-file based reindex detection,
catches files modified before daemon startup, and deduplicates modified files
by resolved absolute path.fw-context watch statusnow reports accurate
Index state (running vs idle) and Modified count drops to 0 after clean
reindex. - Server split — tool implementations moved from
server.pyto handler
modules (handlers/maintenance.py,handlers/source.py), keeping the
FastMCP server entry point focused on registration. - prefer_project ordering —
lookup_definitiongets a newprefer_project
parameter that insertss.is_project DESCinto the ORDER BY clause so
project-code symbols sort before vendor/SDK symbols when both share the same
name. - Header staleness in get_active_build — when
deps_verificationis
"full",get_active_buildnow reports the count of TUs affected by stale
dependency headers. - Shared dep-file parsing —
dep_files.pyextracted as a shared utility
used by both the index runner and query-time header staleness detection.
Fixes
- False "Index: running" —
_is_bg_reindex_runningno longer checks
watcher.lock, which was always present when the daemon ran (idle included).
Replaced withreindex.pidwritten only during active index subprocess. - Stale header mtimes after git checkout — Tier 1 mtime fast-path now
always updates TU stored mtimes and refreshes dependency header mtimes.
A new_refresh_header_mtimesfinal pass catches remaining headers whose
mtime drifted but were never updated (e.g. when.dfiles are absent). - Duplicate entries in
_count_modified_files— deduplicated by resolved
absolute path, keeping the maximum stored mtime. Fixes duplicates from
files indexed under both absolute and relative path formats. - Missed startup files — daemon
_staleness_checknow calls
_count_modified_fileson startup so files modified before the watcher
started trigger an immediate index run.
| File | Change |
|---|---|
CLAUDE.md |
Add GPG-signed commits requirement |
src/fw_context_mcp/cli.py |
Write/remove reindex.pid for standalone index runs |
src/fw_context_mcp/config/tools.py |
Streamline BASE_INSTRUCTIONS (160 to 90 lines) |
src/fw_context_mcp/indexer/dep_files.py |
New — shared dep-file parsing utility |
src/fw_context_mcp/indexer/runner.py |
Tier 1 mtime updates, _refresh_header_mtimes pass |
src/fw_context_mcp/mcp/background.py |
Replace watcher.lock with reindex.pid check |
src/fw_context_mcp/mcp/daemon.py |
New — daemon with correct staleness detection |
src/fw_context_mcp/mcp/handlers/maintenance.py |
Header staleness check in get_active_build |
src/fw_context_mcp/mcp/handlers/source.py |
prefer_project param in lookup_definition |
src/fw_context_mcp/mcp/server.py |
Move tool impls to handler modules |
src/fw_context_mcp/mcp/shared/stale.py |
Deduplicate modified files, drop pathlib resolve |
tests/test_incremental_reindex.py |
Update for new staleness behavior |
tests/test_lookup_definition.py |
New — prefer_project ordering tests |
Breaking changes
None.
v0.20.2 — preferred_kinds refactor for _lookup_definition
Overview
Refactors the class/constructor collision fix from v0.20.1 (commit 594058c) into a clean, parameterised API. The internal _lookup_definition function now accepts a preferred_kinds parameter instead of a hardcoded CASE s.kind expression.
Changes
Fixes
_lookup_definition— newpreferred_kindskeyword parameter replaces hardcoded class/struct priority. Each caller declares which symbol kinds it prefers:get_inheritance_chain,get_class_members:("class", "struct")get_method_overrides:("method", "destructor")get_template_instances:None(supports both class and function templates)- Callgraph tools:
None(existence checks only)
- Added input validation to guard against future SQL injection through kind values.
- 24 new tests covering class/constructor collision, namespace fallback,
preferred_kindsparameter, and integration tests.
| File | Change |
|---|---|
src/fw_context_mcp/mcp/handlers/source.py |
Add preferred_kinds param with validation, dynamic CASE building |
src/fw_context_mcp/mcp/handlers/inheritance.py |
Pass explicit preferred_kinds in all 4 tools |
src/fw_context_mcp/mcp/handlers/callgraph.py |
Pass preferred_kinds=None in all 6 existence checks |
tests/test_lookup_definition.py |
24 tests (new file) |
Breaking changes
None.
v0.20.1 — fix indirect call detection for array subscript expressions
Overview
Patch release fixing find_indirect_call_sites for array-subscript
function pointer calls — the primary dispatch pattern in embedded
firmware (ISR vector tables, callback arrays, state machine dispatch).
Also surfaces indirect call sites in get_symbol_context for function
and method symbols.
Changes
Fixes
- Array subscript indirect call detection —
handlers[irq](arg),
obj->callbacks[idx](args), and similar patterns are now detected as
indirect call sites. Previouslycursor.referencedwas None for
ArraySubscriptExprcallees, so the call site was silently missed. - get_symbol_context for functions —
indirect_call_sitesfield is
now populated forfunctionandmethodsymbols (viafrom_usr
query), not only forfieldandvariablesymbols.
| File | Change |
|---|---|
src/fw_context_mcp/indexer/symbols.py |
_first_child_unwrapped helper + ArraySubscriptExpr fallback in indirect call site extraction |
src/fw_context_mcp/mcp/handlers/source.py |
from_usr query for function/method indirect call sites in get_symbol_context |
tests/test_db.py |
4 tests: array subscript, struct array member, no false positives, member access regression |
Breaking changes
None.
v0.20.0 — read_file tool for ifdef-filtered file content
Overview
Adds read_file, a new MCP tool that returns the complete ifdef-filtered content of a C/C++ source file. Only code that actually compiles for the current build configuration is returned — inactive #ifdef branches are replaced with blank lines (preserving original line numbers).
This bridges a gap in the API: get_source reads one symbol body, search_content returns snippets around matches, but there was no way to read a complete file without leaving the fw-context ecosystem. LLMs were already attempting to call read_file even though it did not exist.
Changes
Features
read_filetool — read complete C/C++ source files with ifdef-filtered, build-accurate content. Falls back to raw disk content for legacy indexes.
| File | Change |
|---|---|
src/fw_context_mcp/mcp/handlers/source.py |
read_file implementation |
src/fw_context_mcp/mcp/server.py |
tool registration, instructions update, tool count fix |
docs/tools.md |
read_file documentation |
pyproject.toml |
version 0.19.2 → 0.20.0 |
server.json |
version + description tool count |
glama.json |
version + description tool count |
CLAUDE.md |
tool count fix |
AGENTS.md |
tool count fix |
README-MCP.md |
tool count fix, read_file in Understanding row |
Breaking changes
None.
v0.19.2 — Extend content fill to framework headers outside project root
Overview
Fixes _build_filtered_file_content to store ifdef-filtered content for files
outside the project root (PlatformIO framework headers, ESP-IDF components,
Zephyr modules). Previously these files were registered in the files table but
never had their content column filled, causing search_content to miss
framework-level declarations and triggering unnecessary re-tokenization on
every reindex.
Changes
Fixes
- Content fill for external files — framework headers outside project root
are now stored with absolute paths, matching the fallback already used by
store_symbols_for_unit
| File | Change |
|---|---|
src/fw_context_mcp/indexer/ops.py |
Use absolute path as fallback instead of skipping files outside project root |
Breaking changes
None.
v0.19.1 — Fix sdist build: exclude tests/builds/ from distribution
Overview
v0.19.1 is a hotfix on top of v0.19.0 that excludes tests/builds/ from the source distribution. The test fixtures contain absolute symlinks (ESP-IDF, Zephyr SDK paths) that caused python -m build to fail with AbsoluteLinkError. Wheel builds and all functionality are unaffected — this only matters for PyPI publishing.
Changes
| File | Change |
|---|---|
pyproject.toml |
Added [tool.hatch.build.targets.sdist] exclude = ["tests/builds/"] |
Breaking changes
None.