Skip to content

Releases: turbyho/fw-context-mcp

v0.22.3 — Manifest-based staleness, path normalization, daemon mode

Choose a tag to compare

@turbyho turbyho released this 14 Jul 22:06
v0.22.3

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.json in 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.
    The compile_commands.json config 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 verificationfw-context index records a
    manifest_verification status (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 rewrittenshared/stale.py now uses the manifest
    instead of .d files, with trusted-SDK-header and generated-header
    exclusion logic.
  • Config hash computationconfig_hash.py now 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 --project replaces project-init — the project-init
    command was removed in favor of init --project.
  • MCP server maintenance endpoint/maintenance returns 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.py and 4 fixtures/tests in test_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 workflow
  • docs/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 root

v0.22.2 — MCP server returns clear error for uninitialized projects

Choose a tag to compare

@turbyho turbyho released this 14 Jul 08:01
v0.22.2
dd6a647

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

Choose a tag to compare

@turbyho turbyho released this 14 Jul 07:33
v0.22.1
0cc26be

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 when fw-context init hasn't been run. Catches
    ProjectNotInitializedError and starts without database support.
  • Init fallback for headless environmentsfw-context init now
    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

Choose a tag to compare

@turbyho turbyho released this 13 Jul 23:08
v0.22.0

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 setupfw-context init now 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-init removed — use fw-context init instead
  • No read-only verify mode — init always applies fixes (config, .gitignore)

v0.21.0 — daemon staleness fixes, server split, prefer_project

Choose a tag to compare

@turbyho turbyho released this 13 Jul 22:03
v0.21.0

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.py module replaces
    ad-hoc checks in background.py. Uses PID-file based reindex detection,
    catches files modified before daemon startup, and deduplicates modified files
    by resolved absolute path. fw-context watch status now reports accurate
    Index state (running vs idle) and Modified count drops to 0 after clean
    reindex.
  • Server split — tool implementations moved from server.py to handler
    modules (handlers/maintenance.py, handlers/source.py), keeping the
    FastMCP server entry point focused on registration.
  • prefer_project orderinglookup_definition gets a new prefer_project
    parameter that inserts s.is_project DESC into 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_verification is
    "full", get_active_build now reports the count of TUs affected by stale
    dependency headers.
  • Shared dep-file parsingdep_files.py extracted as a shared utility
    used by both the index runner and query-time header staleness detection.

Fixes

  • False "Index: running"_is_bg_reindex_running no longer checks
    watcher.lock, which was always present when the daemon ran (idle included).
    Replaced with reindex.pid written 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_mtimes final pass catches remaining headers whose
    mtime drifted but were never updated (e.g. when .d files 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_check now calls
    _count_modified_files on 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

Choose a tag to compare

@turbyho turbyho released this 13 Jul 15:51
v0.20.2

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 — new preferred_kinds keyword 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_kinds parameter, 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

Choose a tag to compare

@turbyho turbyho released this 13 Jul 15:02
v0.20.1

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 detectionhandlers[irq](arg),
    obj->callbacks[idx](args), and similar patterns are now detected as
    indirect call sites. Previously cursor.referenced was None for
    ArraySubscriptExpr callees, so the call site was silently missed.
  • get_symbol_context for functionsindirect_call_sites field is
    now populated for function and method symbols (via from_usr
    query), not only for field and variable symbols.
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

Choose a tag to compare

@turbyho turbyho released this 13 Jul 13:46
v0.20.0
abdb8ab

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_file tool — 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

Choose a tag to compare

@turbyho turbyho released this 12 Jul 22:29
v0.19.2

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

Choose a tag to compare

@turbyho turbyho released this 12 Jul 20:45
v0.19.1

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.