fw-context-mcp 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. fw_context_mcp-0.1.0/.claude/settings.local.json +15 -0
  2. fw_context_mcp-0.1.0/.fw-context/config.toml +14 -0
  3. fw_context_mcp-0.1.0/.gitignore +25 -0
  4. fw_context_mcp-0.1.0/.lean-ctx/graph.db +0 -0
  5. fw_context_mcp-0.1.0/.lean-ctx/graph.meta.json +10 -0
  6. fw_context_mcp-0.1.0/PKG-INFO +215 -0
  7. fw_context_mcp-0.1.0/README-MCP.md +160 -0
  8. fw_context_mcp-0.1.0/README.md +195 -0
  9. fw_context_mcp-0.1.0/docs/configuration.md +111 -0
  10. fw_context_mcp-0.1.0/docs/installation.md +162 -0
  11. fw_context_mcp-0.1.0/docs/tools.md +572 -0
  12. fw_context_mcp-0.1.0/plans/2026-06-05-code-review-findings.md +412 -0
  13. fw_context_mcp-0.1.0/pyproject.toml +70 -0
  14. fw_context_mcp-0.1.0/server.json +25 -0
  15. fw_context_mcp-0.1.0/src/fw_context_mcp/__init__.py +3 -0
  16. fw_context_mcp-0.1.0/src/fw_context_mcp/cli.py +683 -0
  17. fw_context_mcp-0.1.0/src/fw_context_mcp/config/__init__.py +5 -0
  18. fw_context_mcp-0.1.0/src/fw_context_mcp/config/settings.py +231 -0
  19. fw_context_mcp-0.1.0/src/fw_context_mcp/config/tools.py +392 -0
  20. fw_context_mcp-0.1.0/src/fw_context_mcp/indexer/__init__.py +1 -0
  21. fw_context_mcp-0.1.0/src/fw_context_mcp/indexer/compile_commands.py +211 -0
  22. fw_context_mcp-0.1.0/src/fw_context_mcp/indexer/config_hash.py +72 -0
  23. fw_context_mcp-0.1.0/src/fw_context_mcp/indexer/db.py +1091 -0
  24. fw_context_mcp-0.1.0/src/fw_context_mcp/indexer/ops.py +164 -0
  25. fw_context_mcp-0.1.0/src/fw_context_mcp/indexer/runner.py +316 -0
  26. fw_context_mcp-0.1.0/src/fw_context_mcp/indexer/symbols.py +307 -0
  27. fw_context_mcp-0.1.0/src/fw_context_mcp/llm/__init__.py +0 -0
  28. fw_context_mcp-0.1.0/src/fw_context_mcp/llm/ollama.py +210 -0
  29. fw_context_mcp-0.1.0/src/fw_context_mcp/mcp/__init__.py +1 -0
  30. fw_context_mcp-0.1.0/src/fw_context_mcp/mcp/server.py +1251 -0
  31. fw_context_mcp-0.1.0/src/fw_context_mcp/search/__init__.py +12 -0
  32. fw_context_mcp-0.1.0/src/fw_context_mcp/search/cache.py +51 -0
  33. fw_context_mcp-0.1.0/src/fw_context_mcp/search/context.py +108 -0
  34. fw_context_mcp-0.1.0/src/fw_context_mcp/search/phases/__init__.py +23 -0
  35. fw_context_mcp-0.1.0/src/fw_context_mcp/search/phases/base.py +28 -0
  36. fw_context_mcp-0.1.0/src/fw_context_mcp/search/phases/deduplicate.py +51 -0
  37. fw_context_mcp-0.1.0/src/fw_context_mcp/search/phases/embedding.py +166 -0
  38. fw_context_mcp-0.1.0/src/fw_context_mcp/search/phases/format.py +56 -0
  39. fw_context_mcp-0.1.0/src/fw_context_mcp/search/phases/fts5_search.py +61 -0
  40. fw_context_mcp-0.1.0/src/fw_context_mcp/search/phases/llm_query.py +121 -0
  41. fw_context_mcp-0.1.0/src/fw_context_mcp/search/phases/refine.py +100 -0
  42. fw_context_mcp-0.1.0/src/fw_context_mcp/search/phases/rough_search.py +87 -0
  43. fw_context_mcp-0.1.0/src/fw_context_mcp/search/phases/translate.py +52 -0
  44. fw_context_mcp-0.1.0/src/fw_context_mcp/search/pipeline.py +132 -0
  45. fw_context_mcp-0.1.0/src/fw_context_mcp/search/scoring.py +65 -0
  46. fw_context_mcp-0.1.0/src/fw_context_mcp/utils.py +47 -0
  47. fw_context_mcp-0.1.0/tests/__init__.py +0 -0
  48. fw_context_mcp-0.1.0/tests/conftest.py +118 -0
  49. fw_context_mcp-0.1.0/tests/test_compile_commands.py +209 -0
  50. fw_context_mcp-0.1.0/tests/test_config.py +121 -0
  51. fw_context_mcp-0.1.0/tests/test_config_hash.py +122 -0
  52. fw_context_mcp-0.1.0/tests/test_db.py +500 -0
  53. fw_context_mcp-0.1.0/tests/test_search_quality.py +477 -0
  54. fw_context_mcp-0.1.0/tests/test_server.py +254 -0
  55. fw_context_mcp-0.1.0/work/SMART_SEARCH_DEBUG.md +86 -0
  56. fw_context_mcp-0.1.0/work/fw_context.db +0 -0
  57. fw_context_mcp-0.1.0/work/plan-iterace3-opravy-vylepseni.md +281 -0
@@ -0,0 +1,15 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "mcp__fw-context__test_sampling",
5
+ "mcp__fw-context__search_code",
6
+ "mcp__lean-ctx__ctx_search",
7
+ "mcp__lean-ctx__ctx_read",
8
+ "mcp__lean-ctx__ctx_tree",
9
+ "mcp__lean-ctx__ctx_multi_read",
10
+ "mcp__lean-ctx__ctx_shell",
11
+ "WebSearch",
12
+ "mcp__fw-context__check_ollama"
13
+ ]
14
+ }
15
+ }
@@ -0,0 +1,14 @@
1
+ [project]
2
+ # name = "my-project" # defaults to directory name
3
+
4
+ [index]
5
+ compile_commands = "compile_commands.json"
6
+ source_roots = ["src", "lib"]
7
+ exclude_paths = ["build", "BUILD"]
8
+
9
+ # [llm]
10
+ # enabled = false # disable Ollama, return raw prompts for the agent to answer
11
+ # ollama_url = "http://localhost:11434"
12
+ # model = "qwen2.5-coder:7b-q4_K_M" # override global model for this project
13
+ # num_ctx = 8192
14
+ # debug_log = "~/.fw-context/llm-debug.jsonl" # write LLM prompts/responses to JSONL
@@ -0,0 +1,25 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .venv/
8
+ venv/
9
+ .env
10
+
11
+ # fw-context runtime data
12
+ .fw-context/
13
+
14
+ .lean-ctx
15
+
16
+ # IDE
17
+ .vscode/
18
+ .idea/
19
+
20
+ # Tests
21
+ .pytest_cache/
22
+ .coverage
23
+ htmlcov/
24
+ .lean-ctx/
25
+ work/
Binary file
@@ -0,0 +1,10 @@
1
+ {
2
+ "schema_version": 1,
3
+ "built_at": "2026-06-04T21:20:18.237550534+00:00",
4
+ "git_head": "cdd73bf",
5
+ "git_dirty": false,
6
+ "nodes": 96,
7
+ "edges": 148,
8
+ "files_indexed": 38,
9
+ "build_time_ms": 82
10
+ }
@@ -0,0 +1,215 @@
1
+ Metadata-Version: 2.4
2
+ Name: fw-context-mcp
3
+ Version: 0.1.0
4
+ Summary: Build-aware code intelligence MCP server for embedded C/C++ firmware (Mbed OS, Zephyr, PlatformIO)
5
+ License: MIT
6
+ Keywords: c++,call-graph,code-intelligence,embedded,firmware,libclang,mcp
7
+ Requires-Python: >=3.11
8
+ Requires-Dist: httpx>=0.27.0
9
+ Requires-Dist: libclang>=18.1.1
10
+ Requires-Dist: mcp[cli]>=1.0.0
11
+ Requires-Dist: sqlite-vec>=0.1.0
12
+ Requires-Dist: tomli>=2.0.0; python_version < '3.11'
13
+ Provides-Extra: dev
14
+ Requires-Dist: mypy>=1.10; extra == 'dev'
15
+ Requires-Dist: pytest>=8; extra == 'dev'
16
+ Requires-Dist: ruff>=0.4; extra == 'dev'
17
+ Provides-Extra: watch
18
+ Requires-Dist: watchfiles>=0.21; extra == 'watch'
19
+ Description-Content-Type: text/markdown
20
+
21
+ # fw-context
22
+ <!-- mcp-name: io.github.turbyho/fw-context-mcp -->
23
+ mcp-name: io.github.turbyho/fw-context-mcp
24
+
25
+ **MCP server for embedded C/C++ firmware** — gives AI assistants (Claude Code,
26
+ Cursor, OpenCode, etc.) real understanding of your codebase. Parses your actual build
27
+ with [libclang](https://clang.llvm.org/), extracts every symbol, and builds a
28
+ persistent index with full-text search, call graph, and vector embeddings.
29
+
30
+ No hallucination. No grepping. No reading thousands of framework headers into context.
31
+
32
+ ## What it does
33
+
34
+ Your AI assistant goes from guessing to knowing:
35
+
36
+ > *"What does `uart_init` do and who calls it?"*
37
+ > → `get_symbol_context("uart_init")` — body, callers, callees in one call.
38
+ >
39
+ > *"Find all BLE advertising functions and how they're connected."*
40
+ > → `search_code("ble advertising", kind="function")` → `find_call_path("gap_init", "start_advertising")`
41
+ >
42
+ > *"Show me the implementation of `adc_read` — not the declaration."*
43
+ > → `get_source("adc_read")` — exact body via libclang, no file reading.
44
+ >
45
+ > *"What would break if I change `spi_transfer`?"*
46
+ > → `find_all_callers_recursive("spi_transfer")` — every caller, direct and indirect.
47
+ >
48
+ > *"Give me a map of `modem_msg.cpp` before I read it."*
49
+ > → `get_file_map("src/modem_msg.cpp")` — 426 symbols grouped by kind.
50
+
51
+ **19 MCP tools** — symbol search, source reading, call-graph traversal, hotspot
52
+ analysis, dead code detection, vector search. All backed by real compiler flags
53
+ from `compile_commands.json` — `#ifdef`-aware, not grep.
54
+
55
+ ## Quick start
56
+
57
+ ```bash
58
+ # 1. Install
59
+ git clone git@github.com:turbyho/fw-context-mcp.git ~/.fw-context/src
60
+ uv venv ~/.fw-context/.venv --python 3.12
61
+ uv pip install --python ~/.fw-context/.venv/bin/python ~/.fw-context/src/
62
+ echo 'export PATH="$HOME/.fw-context/.venv/bin:$PATH"' >> ~/.zshrc
63
+
64
+ # 2. Register with your AI assistant
65
+ fw-context init
66
+
67
+ # 3. Generate compile_commands.json and index
68
+ cd your-firmware-project
69
+
70
+ # Mbed OS:
71
+ bear -- mbed compile --profile release
72
+
73
+ # Zephyr:
74
+ west build -b <board> -- -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
75
+ fw-context index build/compile_commands.json
76
+
77
+ # PlatformIO:
78
+ pio run --target compiledb
79
+ fw-context index
80
+
81
+ # CMake / Make:
82
+ bear -- make
83
+ # or: bear -- cmake --build build
84
+
85
+ fw-context index
86
+
87
+ # 4. Restart your assistant and start asking about your code
88
+ ```
89
+
90
+ For detailed prerequisites, Ollama setup, and AI assistant integration:
91
+ **[Installation guide →](docs/installation.md)**
92
+
93
+ ## Why not just use LSP?
94
+
95
+ LSP servers (clangd, ccls) are excellent for interactive editing.
96
+ But they have limitations for AI-assisted exploration:
97
+
98
+ | Limitation | fw-context solution |
99
+ |-----------|---------------------|
100
+ | No full-text search across the codebase | FTS5 over 6 columns — find "all functions related to modem init" |
101
+ | Index dies with the server — rebuild from scratch | Persistent SQLite file — survives reboots, reads in milliseconds |
102
+ | Editor protocol, not AI protocol | MCP tools purpose-built for AI assistant workflow |
103
+ | Blind to which `#ifdef` branch is active | Uses real compiler flags from `compile_commands.json` |
104
+
105
+ Use **clangd for editing**, **fw-context for AI-assisted exploration**.
106
+
107
+ ## Architecture
108
+
109
+ ### Data flow
110
+
111
+ ```
112
+ BUILD INDEX QUERY
113
+ ===== ===== =====
114
+ bear / west / pio libclang parses each TU AI assistant calls
115
+ cmake / make extracts symbols + refs MCP tools over
116
+ │ generates embeddings JSON-RPC (stdio)
117
+ ▼ │ │
118
+ compile_commands SQLite db on disk lookup_symbol(…)
119
+ .json ~/.fw-context/index/ search_code(…)
120
+ │ │ find_callers(…)
121
+ ▼ ▼ explain_symbol(…)
122
+ symbols + refs vec0 get_symbol_context(…)
123
+ (FTS5 index) (vector KNN) │
124
+
125
+ AI assistant answers
126
+ your question about
127
+ the code
128
+ ```
129
+
130
+ ### Components
131
+
132
+ ```
133
+ CLI (fw-context) MCP server (fw-context-mcp) Ollama (optional)
134
+ ================ =========================== ==================
135
+ fw-context index exposes 19 tools over local LLM runtime
136
+ fw-context export JSON-RPC (stdio) HTTP :11434
137
+ fw-context watch │ │
138
+ fw-context status search_code ───────────── lookup smart_search ──▶ translates NL → FTS5 terms
139
+ fw-context reset lookup_symbol ─────────── prefix explain_symbol ─▶ explains function
140
+ fw-context init smart_search ──────────── NL embeddings ────▶ mxbai-embed-large
141
+ fw-context search get_file_map ──────────── file structure by kind
142
+ get_source ────────────── body
143
+ get_symbol_context ────── body+callers+callees
144
+ find_callers ──────────── direct callers
145
+ find_references ───────── all uses
146
+ find_call_path ────────── BFS in call graph
147
+ find_all_callers_recursive transitive callers
148
+ find_callees_recursive ── transitive callees
149
+ find_dead_code ────────── never called
150
+ find_hotspots ─────────── most-called
151
+ get_active_build ──────── index health
152
+ reindex_file ──────────── re-parse one file
153
+ reset_index ───────────── delete + rebuild
154
+ list_projects ─────────── all indexed projects
155
+ check_ollama ──────────── verify LLM
156
+ ```
157
+
158
+ | Component | Runs as | Purpose |
159
+ |-----------|---------|---------|
160
+ | **CLI** (`fw-context`) | User command | Index, export, watch, status, reset, init, search |
161
+ | **Indexer** | Called by CLI | libclang parses every TU, stores in SQLite + FTS5 + vec0 |
162
+ | **MCP server** (`fw-context-mcp`) | Subprocess (AI assistant) | 19 tools over JSON-RPC — search, graph, source, maintenance |
163
+ | **Ollama** *(optional)* | Local daemon | NL search, symbol explanation, embedding generation |
164
+
165
+ ## Key capabilities
166
+
167
+ - **Fast lookups** — FTS5 full-text search, prefix/exact symbol lookup, call-graph traversal
168
+ - **Natural-language search** — *"how does the modem connect?"* → finds `network_registration`, `modem_attach`, … (Ollama, optional)
169
+ - **Vector search** — semantic similarity via `sqlite-vec` + Ollama embeddings, hybrid FTS5+vector re-ranking
170
+ - **Graph analytics** — call paths, transitive callers/callees, dead code detection, hotspot analysis
171
+ - **Incremental indexing** — only changed files re-parsed; auto-reindex on query detects and fixes staleness
172
+ - **Offline-first** — index is a file on disk at `~/.fw-context/index/`. No daemon, no cloud, no network.
173
+ - **`#ifdef`-aware** — uses real compiler flags; sees exactly what your compiler sees
174
+
175
+ ## Supported ecosystems
176
+
177
+ Works with **any build system** that produces `compile_commands.json`:
178
+
179
+ | Ecosystem | Auto-detection |
180
+ |-----------|---------------|
181
+ | **Mbed OS** | `mbed-os/` directory or `mbed_app.json` |
182
+ | **Zephyr RTOS** | `west.yml` or `prj.conf` |
183
+ | **PlatformIO** | `platformio.ini` |
184
+ | **Bare-metal / FreeRTOS** | Any build with `bear` |
185
+ | **Custom toolchain** | Any build with `bear` |
186
+
187
+ Subsequent runs are **incremental** — seconds for a few changed files.
188
+
189
+ ## Documentation
190
+
191
+ | Document | Covers |
192
+ |----------|--------|
193
+ | **[Installation](docs/installation.md)** | Prerequisites, install, upgrade, Ollama setup, AI assistant integration |
194
+ | **[Tools Reference](docs/tools.md)** | All 18 MCP tools, 8 CLI commands, internal workings, search pipeline |
195
+ | **[Configuration](docs/configuration.md)** | `.fw-context/config.toml` — global defaults, per-project overrides, every setting |
196
+ | **[MCP Server](README-MCP.md)** | JSON-RPC protocol, tool schemas, error handling, debugging |
197
+
198
+ ## Directory layout
199
+
200
+ ```
201
+ ~/.fw-context/
202
+ ├── config.toml # global defaults
203
+ ├── .venv/ # Python virtual environment
204
+ │ └── bin/
205
+ │ ├── fw-context # CLI
206
+ │ └── fw-context-mcp # MCP server
207
+ └── index/
208
+ └── <project-id>/
209
+ └── index.db # SQLite + FTS5 + vec0 + refs
210
+
211
+ your-firmware/
212
+ ├── .fw-context/
213
+ │ └── config.toml # per-project overrides
214
+ └── compile_commands.json
215
+ ```
@@ -0,0 +1,160 @@
1
+ # fw-context-mcp — MCP Server
2
+
3
+ MCP (Model Context Protocol) server that exposes the fw-context symbol index
4
+ as tools for AI assistants. Communicates over **JSON-RPC 2.0 via stdio**.
5
+
6
+ ## What it is
7
+
8
+ A persistent subprocess started by your AI assistant (Claude Code, OpenCode, …)
9
+ that provides **19 tools** for navigating embedded firmware codebases:
10
+
11
+ | Category | Tools |
12
+ |----------|-------|
13
+ | **Search & lookup** | `search_code`, `lookup_symbol`, `smart_search` |
14
+ | **Understanding** | `get_file_map`, `get_source`, `explain_symbol`, `get_symbol_context` |
15
+ | **Call graph** | `find_callers`, `find_references`, `find_call_path`, `find_all_callers_recursive`, `find_callees_recursive`, `find_dead_code`, `find_hotspots` |
16
+ | **Maintenance** | `get_active_build`, `reindex_file`, `reset_index`, `list_projects` |
17
+ | **Setup** | `check_ollama` |
18
+
19
+ Full tool reference with schemas and examples: **[Tools Reference](docs/tools.md)**
20
+
21
+ ## Protocol
22
+
23
+ JSON-RPC 2.0 over stdin/stdout. One JSON object per line, terminated by `\n`.
24
+
25
+ ### Initialization
26
+
27
+ ```
28
+ Client → Server:
29
+ {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05",…}}
30
+
31
+ Server → Client:
32
+ {"jsonrpc":"2.0","id":1,"result":{…}}
33
+
34
+ Client → Server:
35
+ {"jsonrpc":"2.0","method":"notifications/initialized"}
36
+ ```
37
+
38
+ ### Calling a tool
39
+
40
+ ```
41
+ Client → Server:
42
+ {"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"search_code","arguments":{"query":"uart init"}}}
43
+
44
+ Server → Client:
45
+ {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"<json>"}],"isError":false}}
46
+ ```
47
+
48
+ The `text` field is a JSON-encoded string — parse it to get the return value.
49
+
50
+ ### Listing tools
51
+
52
+ ```
53
+ Client → Server: {"jsonrpc":"2.0","id":99,"method":"tools/list","params":{}}
54
+ Server → Client: {"jsonrpc":"2.0","id":99,"result":{"tools":[{…},…]}}
55
+ ```
56
+
57
+ ## Integration
58
+
59
+ ### Claude Code
60
+
61
+ ```bash
62
+ claude mcp add --scope user fw-context ~/.fw-context/.venv/bin/fw-context-mcp
63
+ ```
64
+
65
+ Run `fw-context init` to do this automatically and inject usage instructions
66
+ into `~/.claude/CLAUDE.md`.
67
+
68
+ ### OpenCode
69
+
70
+ Add to `~/.config/opencode/opencode.json`:
71
+
72
+ ```json
73
+ {
74
+ "mcp": {
75
+ "fw-context": {
76
+ "command": ["/home/<user>/.fw-context/.venv/bin/fw-context-mcp"],
77
+ "enabled": true,
78
+ "type": "local"
79
+ }
80
+ }
81
+ }
82
+ ```
83
+
84
+ ### Other MCP clients
85
+
86
+ Start the server as a subprocess:
87
+
88
+ ```bash
89
+ /path/to/.fw-context/.venv/bin/fw-context-mcp
90
+ ```
91
+
92
+ Send JSON-RPC on stdin, read responses from stdout. The server has no CLI
93
+ interface — it only speaks MCP.
94
+
95
+ ## Error handling
96
+
97
+ **JSON-RPC errors** (protocol level):
98
+ ```json
99
+ {"jsonrpc":"2.0","id":1,"error":{"code":-32602,"message":"Invalid request parameters"}}
100
+ ```
101
+
102
+ **Tool-level errors** (tool ran but couldn't complete):
103
+ ```json
104
+ {"result":{"content":[{"type":"text","text":"{\"error\": \"No index found for …\"}"}],"isError":false}}
105
+ ```
106
+
107
+ Tool errors use `isError: false` — the tool call succeeded, but returned an
108
+ error field. Only JSON-RPC protocol errors use the top-level `error` key.
109
+
110
+ ### Staleness and auto-reindex
111
+
112
+ `search_code` and `lookup_symbol` automatically detect stale files in results,
113
+ re-index them (up to 5 files, 30 s timeout), and re-run the query. When
114
+ auto-reindex fails or `compile_commands.json` itself is stale, a warning
115
+ entry is included:
116
+
117
+ ```json
118
+ [
119
+ {"warning": "Auto-reindex failed for 1 file(s): …"},
120
+ {"name": "spi_init", …}
121
+ ]
122
+ ```
123
+
124
+ ### Database corruption
125
+
126
+ The server runs `PRAGMA integrity_check` on every database open. If corruption
127
+ is detected, tools return a structured error:
128
+
129
+ ```json
130
+ {
131
+ "error": "Database corruption detected: …",
132
+ "action": "reset_index",
133
+ "hint": "Run reset_index() then fw-context index to rebuild."
134
+ }
135
+ ```
136
+
137
+ Call `reset_index(confirm=true)` to delete the database, then `fw-context index`
138
+ to rebuild.
139
+
140
+ ## Environment
141
+
142
+ - **CWD:** The server resolves project root from `$PWD` when `project_root`
143
+ is not provided. Launch it from the firmware project root.
144
+ - **No network required** for core tools (search, lookup, source, graph).
145
+ `smart_search` and `explain_symbol` optionally use local Ollama.
146
+ - **Stateless** between calls — each tool opens the DB, queries, closes.
147
+
148
+ ## Debugging
149
+
150
+ ```bash
151
+ # Manual tool listing
152
+ echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \
153
+ | /path/to/.fw-context/.venv/bin/fw-context-mcp
154
+
155
+ # Verbose logging
156
+ FW_CONTEXT_LOG_LEVEL=DEBUG /path/to/.fw-context/.venv/bin/fw-context-mcp
157
+
158
+ # Ollama debug log (when debug_log is set in config)
159
+ tail -f ~/.fw-context/llm-debug.jsonl
160
+ ```
@@ -0,0 +1,195 @@
1
+ # fw-context
2
+ <!-- mcp-name: io.github.turbyho/fw-context-mcp -->
3
+ mcp-name: io.github.turbyho/fw-context-mcp
4
+
5
+ **MCP server for embedded C/C++ firmware** — gives AI assistants (Claude Code,
6
+ Cursor, OpenCode, etc.) real understanding of your codebase. Parses your actual build
7
+ with [libclang](https://clang.llvm.org/), extracts every symbol, and builds a
8
+ persistent index with full-text search, call graph, and vector embeddings.
9
+
10
+ No hallucination. No grepping. No reading thousands of framework headers into context.
11
+
12
+ ## What it does
13
+
14
+ Your AI assistant goes from guessing to knowing:
15
+
16
+ > *"What does `uart_init` do and who calls it?"*
17
+ > → `get_symbol_context("uart_init")` — body, callers, callees in one call.
18
+ >
19
+ > *"Find all BLE advertising functions and how they're connected."*
20
+ > → `search_code("ble advertising", kind="function")` → `find_call_path("gap_init", "start_advertising")`
21
+ >
22
+ > *"Show me the implementation of `adc_read` — not the declaration."*
23
+ > → `get_source("adc_read")` — exact body via libclang, no file reading.
24
+ >
25
+ > *"What would break if I change `spi_transfer`?"*
26
+ > → `find_all_callers_recursive("spi_transfer")` — every caller, direct and indirect.
27
+ >
28
+ > *"Give me a map of `modem_msg.cpp` before I read it."*
29
+ > → `get_file_map("src/modem_msg.cpp")` — 426 symbols grouped by kind.
30
+
31
+ **19 MCP tools** — symbol search, source reading, call-graph traversal, hotspot
32
+ analysis, dead code detection, vector search. All backed by real compiler flags
33
+ from `compile_commands.json` — `#ifdef`-aware, not grep.
34
+
35
+ ## Quick start
36
+
37
+ ```bash
38
+ # 1. Install
39
+ git clone git@github.com:turbyho/fw-context-mcp.git ~/.fw-context/src
40
+ uv venv ~/.fw-context/.venv --python 3.12
41
+ uv pip install --python ~/.fw-context/.venv/bin/python ~/.fw-context/src/
42
+ echo 'export PATH="$HOME/.fw-context/.venv/bin:$PATH"' >> ~/.zshrc
43
+
44
+ # 2. Register with your AI assistant
45
+ fw-context init
46
+
47
+ # 3. Generate compile_commands.json and index
48
+ cd your-firmware-project
49
+
50
+ # Mbed OS:
51
+ bear -- mbed compile --profile release
52
+
53
+ # Zephyr:
54
+ west build -b <board> -- -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
55
+ fw-context index build/compile_commands.json
56
+
57
+ # PlatformIO:
58
+ pio run --target compiledb
59
+ fw-context index
60
+
61
+ # CMake / Make:
62
+ bear -- make
63
+ # or: bear -- cmake --build build
64
+
65
+ fw-context index
66
+
67
+ # 4. Restart your assistant and start asking about your code
68
+ ```
69
+
70
+ For detailed prerequisites, Ollama setup, and AI assistant integration:
71
+ **[Installation guide →](docs/installation.md)**
72
+
73
+ ## Why not just use LSP?
74
+
75
+ LSP servers (clangd, ccls) are excellent for interactive editing.
76
+ But they have limitations for AI-assisted exploration:
77
+
78
+ | Limitation | fw-context solution |
79
+ |-----------|---------------------|
80
+ | No full-text search across the codebase | FTS5 over 6 columns — find "all functions related to modem init" |
81
+ | Index dies with the server — rebuild from scratch | Persistent SQLite file — survives reboots, reads in milliseconds |
82
+ | Editor protocol, not AI protocol | MCP tools purpose-built for AI assistant workflow |
83
+ | Blind to which `#ifdef` branch is active | Uses real compiler flags from `compile_commands.json` |
84
+
85
+ Use **clangd for editing**, **fw-context for AI-assisted exploration**.
86
+
87
+ ## Architecture
88
+
89
+ ### Data flow
90
+
91
+ ```
92
+ BUILD INDEX QUERY
93
+ ===== ===== =====
94
+ bear / west / pio libclang parses each TU AI assistant calls
95
+ cmake / make extracts symbols + refs MCP tools over
96
+ │ generates embeddings JSON-RPC (stdio)
97
+ ▼ │ │
98
+ compile_commands SQLite db on disk lookup_symbol(…)
99
+ .json ~/.fw-context/index/ search_code(…)
100
+ │ │ find_callers(…)
101
+ ▼ ▼ explain_symbol(…)
102
+ symbols + refs vec0 get_symbol_context(…)
103
+ (FTS5 index) (vector KNN) │
104
+
105
+ AI assistant answers
106
+ your question about
107
+ the code
108
+ ```
109
+
110
+ ### Components
111
+
112
+ ```
113
+ CLI (fw-context) MCP server (fw-context-mcp) Ollama (optional)
114
+ ================ =========================== ==================
115
+ fw-context index exposes 19 tools over local LLM runtime
116
+ fw-context export JSON-RPC (stdio) HTTP :11434
117
+ fw-context watch │ │
118
+ fw-context status search_code ───────────── lookup smart_search ──▶ translates NL → FTS5 terms
119
+ fw-context reset lookup_symbol ─────────── prefix explain_symbol ─▶ explains function
120
+ fw-context init smart_search ──────────── NL embeddings ────▶ mxbai-embed-large
121
+ fw-context search get_file_map ──────────── file structure by kind
122
+ get_source ────────────── body
123
+ get_symbol_context ────── body+callers+callees
124
+ find_callers ──────────── direct callers
125
+ find_references ───────── all uses
126
+ find_call_path ────────── BFS in call graph
127
+ find_all_callers_recursive transitive callers
128
+ find_callees_recursive ── transitive callees
129
+ find_dead_code ────────── never called
130
+ find_hotspots ─────────── most-called
131
+ get_active_build ──────── index health
132
+ reindex_file ──────────── re-parse one file
133
+ reset_index ───────────── delete + rebuild
134
+ list_projects ─────────── all indexed projects
135
+ check_ollama ──────────── verify LLM
136
+ ```
137
+
138
+ | Component | Runs as | Purpose |
139
+ |-----------|---------|---------|
140
+ | **CLI** (`fw-context`) | User command | Index, export, watch, status, reset, init, search |
141
+ | **Indexer** | Called by CLI | libclang parses every TU, stores in SQLite + FTS5 + vec0 |
142
+ | **MCP server** (`fw-context-mcp`) | Subprocess (AI assistant) | 19 tools over JSON-RPC — search, graph, source, maintenance |
143
+ | **Ollama** *(optional)* | Local daemon | NL search, symbol explanation, embedding generation |
144
+
145
+ ## Key capabilities
146
+
147
+ - **Fast lookups** — FTS5 full-text search, prefix/exact symbol lookup, call-graph traversal
148
+ - **Natural-language search** — *"how does the modem connect?"* → finds `network_registration`, `modem_attach`, … (Ollama, optional)
149
+ - **Vector search** — semantic similarity via `sqlite-vec` + Ollama embeddings, hybrid FTS5+vector re-ranking
150
+ - **Graph analytics** — call paths, transitive callers/callees, dead code detection, hotspot analysis
151
+ - **Incremental indexing** — only changed files re-parsed; auto-reindex on query detects and fixes staleness
152
+ - **Offline-first** — index is a file on disk at `~/.fw-context/index/`. No daemon, no cloud, no network.
153
+ - **`#ifdef`-aware** — uses real compiler flags; sees exactly what your compiler sees
154
+
155
+ ## Supported ecosystems
156
+
157
+ Works with **any build system** that produces `compile_commands.json`:
158
+
159
+ | Ecosystem | Auto-detection |
160
+ |-----------|---------------|
161
+ | **Mbed OS** | `mbed-os/` directory or `mbed_app.json` |
162
+ | **Zephyr RTOS** | `west.yml` or `prj.conf` |
163
+ | **PlatformIO** | `platformio.ini` |
164
+ | **Bare-metal / FreeRTOS** | Any build with `bear` |
165
+ | **Custom toolchain** | Any build with `bear` |
166
+
167
+ Subsequent runs are **incremental** — seconds for a few changed files.
168
+
169
+ ## Documentation
170
+
171
+ | Document | Covers |
172
+ |----------|--------|
173
+ | **[Installation](docs/installation.md)** | Prerequisites, install, upgrade, Ollama setup, AI assistant integration |
174
+ | **[Tools Reference](docs/tools.md)** | All 18 MCP tools, 8 CLI commands, internal workings, search pipeline |
175
+ | **[Configuration](docs/configuration.md)** | `.fw-context/config.toml` — global defaults, per-project overrides, every setting |
176
+ | **[MCP Server](README-MCP.md)** | JSON-RPC protocol, tool schemas, error handling, debugging |
177
+
178
+ ## Directory layout
179
+
180
+ ```
181
+ ~/.fw-context/
182
+ ├── config.toml # global defaults
183
+ ├── .venv/ # Python virtual environment
184
+ │ └── bin/
185
+ │ ├── fw-context # CLI
186
+ │ └── fw-context-mcp # MCP server
187
+ └── index/
188
+ └── <project-id>/
189
+ └── index.db # SQLite + FTS5 + vec0 + refs
190
+
191
+ your-firmware/
192
+ ├── .fw-context/
193
+ │ └── config.toml # per-project overrides
194
+ └── compile_commands.json
195
+ ```