@octocodeai/freellama-mcp-server 0.10.0 → 0.12.0

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 (54) hide show
  1. package/CONFIGURATION.md +82 -3
  2. package/DEVELOPING.md +40 -9
  3. package/README.md +316 -213
  4. package/dist/agent-cli.js +16963 -0
  5. package/dist/index.js +4896 -4036
  6. package/dist/research/bash-agent.js +287 -108
  7. package/dist/research/coder-agent.js +455 -127
  8. package/dist/research/github-agent.js +276 -94
  9. package/dist/research/octocode-agent.js +276 -94
  10. package/docs/AGENT_CLI.md +234 -0
  11. package/docs/API.md +160 -0
  12. package/docs/ARCHITECTURE.md +158 -50
  13. package/docs/ASSESSMENT.md +131 -0
  14. package/docs/BENCHMARK.md +381 -0
  15. package/docs/BUILD_AND_NOTES.md +12 -3
  16. package/docs/CLI.md +62 -17
  17. package/docs/CPU_GPU_ROUTING.md +22 -9
  18. package/docs/DEFERRED_JOBS.md +17 -4
  19. package/docs/FEATURES.md +97 -43
  20. package/docs/LLAMACPP.md +133 -0
  21. package/docs/LOCAL_MODELS.md +26 -20
  22. package/docs/MODEL_FORMS_AND_RESULTS.md +14 -6
  23. package/docs/MODEL_INTROSPECTION.md +9 -2
  24. package/docs/MODEL_SELECTION.md +38 -9
  25. package/docs/MONITORING.md +110 -12
  26. package/docs/OLLAMA_REVIEW.md +226 -0
  27. package/docs/PRODUCTION.md +68 -25
  28. package/docs/PROMPTS.md +119 -0
  29. package/docs/README.md +22 -6
  30. package/docs/RELIABILITY.md +207 -0
  31. package/docs/RUST_RESOURCE_AUDIT.md +65 -0
  32. package/docs/SCOPES_AND_WARMING.md +12 -5
  33. package/docs/TESTING.md +112 -6
  34. package/docs/TUNING.md +12 -8
  35. package/docs/assets/benchmark-results-2026-11-14.html +4 -0
  36. package/docs/assets/tool-calling-2026-11-14-bonsai-9b/TABLE.md +14 -0
  37. package/docs/assets/tool-calling-2026-11-14-lfm3-vl/TABLE.md +14 -0
  38. package/docs/assets/tool-calling-table.md +14 -0
  39. package/docs/cookbooks/README.md +9 -2
  40. package/docs/cookbooks/batch-text.md +4 -2
  41. package/docs/cookbooks/classify.md +19 -3
  42. package/docs/cookbooks/coding.md +13 -4
  43. package/docs/cookbooks/find-code.md +8 -3
  44. package/docs/cookbooks/jobs.md +8 -8
  45. package/docs/cookbooks/memory-and-caching.md +2 -2
  46. package/docs/cookbooks/ocr.md +3 -3
  47. package/docs/cookbooks/research-agent.md +32 -2
  48. package/docs/cookbooks/speech-to-text.md +1 -1
  49. package/docs/cookbooks/sweep.md +4 -1
  50. package/docs/octocode/GITHUB.md +4 -4
  51. package/docs/octocode/LOCAL.md +5 -4
  52. package/native/index.d.ts +1 -1
  53. package/package.json +6 -6
  54. package/docs/COMPARISON.md +0 -40
package/CONFIGURATION.md CHANGED
@@ -11,6 +11,7 @@ server-launch config (for example `.mcp.json`'s `env` block) or the launching sh
11
11
  |---|---|---|
12
12
  | `FREELLAMA_OLLAMA_ENDPOINT` | `http://127.0.0.1:11434` | Default Ollama endpoint for `doctor`, the `models` detail/raw/library views, all `ollama_*` tools, and the autostarted serve's `--upstream` |
13
13
  | `FREELLAMA_SERVE_ENDPOINT` | `http://127.0.0.1:11435` | Default `endpoint` for serve-backed tools and `delegate_research` |
14
+ | `FREELLAMA_MCP_RECEIPT` | `text` | `structured` keeps `run_task` and `task_jobs` receipts inline as `structuredContent` (see [Where an answer goes](#where-an-answer-goes)) |
14
15
  | `FREELLAMA_MCP_DEFAULT_MODEL` | unset (routes to an installed coding model) | `delegate_research`'s default `model` |
15
16
  | `FREELLAMA_MCP_DEFAULT_ADAPTER` | `bash` | `delegate_research`'s adapter (`octocode` to switch) |
16
17
  | `FREELLAMA_MCP_MAX_TURNS` | `8` | Max agent turns for `delegate_research` |
@@ -27,12 +28,16 @@ server-launch config (for example `.mcp.json`'s `env` block) or the launching sh
27
28
  | `FREELLAMA_TASK_TIMEOUT_SECONDS` | `900` | Generation calls; read by the native client (`packages/rust-core/src/serve_client.rs`) |
28
29
  | `FREELLAMA_AUTH_TOKEN_FILE` | unset | Bearer-token file used by the native client and research adapters for all serve routes |
29
30
  | `FREELLAMA_AGENT_TOKEN_CALIBRATION_DIR` | platform data directory | Prompt-free, model-specific token-estimator calibration shared across adapter processes |
30
- | `FREELLAMA_MCP_AUTOSTART_SERVE` | `1` | When the default loopback serve endpoint does not answer, start `freellama serve` as a child of the MCP server (stopped with it): once in the background at launch, so other local clients find it, and again on a tool call if it is still down. `0` disables |
31
+ | `FREELLAMA_MCP_AUTOSTART_SERVE` | `1` | When the default loopback serve endpoint does not answer, start `freellama serve` as a child of the MCP server (stopped with it): once in the background at launch, so other local clients find it, and again on a tool call if it is still down. Under the agent commands (`freellama run`, `chat`…) it starts detached instead, logging to `$FREELLAMA_HOME/serve.log` (default `~/.octocode/freellama/serve.log`), and keeps running for later calls. `0` disables |
32
+ | `FREELLAMA_WORKFLOWS_DIR` | `$FREELLAMA_HOME/workflows` | Directory of your own workflow files (`NAME.md`), read when the MCP server or an agent command starts. A file named like a built-in replaces it; an invalid one is skipped and named by `freellama workflows` and `doctor`. Format: [your own workflows](../../docs/PROMPTS.md#your-own-workflows) |
33
+ | `FREELLAMA_EMBED_INDEX` | `1` | `0` turns off the persistent embedding index that lets a repeated `nearest` search over files (find-code, duplicates) embed only new or changed chunks. Vectors live in `$FREELLAMA_HOME/embedding-index/`, one file per model, digest and dimensions. |
34
+ | `FREELLAMA_OLLAMA_CLI` | `ollama` | Path of the `ollama` binary that `freellama chat` runs |
31
35
  | `FREELLAMA_SERVE_BINARY` | checkout `target/release`/`debug`, then the platform package | Binary used for serve autostart |
32
36
  | `FREELLAMA_AGENT_OS_SANDBOX` | `auto` | Bash adapter OS confinement: `bwrap` on Linux, `sandbox-exec` on macOS, when present. `off` keeps only the restricted shell |
33
37
  | `FREELLAMA_AGENT_OCTOCODE_PACKAGE` | `octocode@19.1.0` | Pinned npm spec the Octocode adapter runs through `npx` |
34
- | `FREELLAMA_MCP_ALLOW_CODER` | unset (off) | `1` enables `delegate_research` `adapter:"coder"`, which edits files and runs the caller's `agent.commands` in an isolated copy of the workspace (see [the coder adapter](README.md#the-coder-adapter)) |
38
+ | `FREELLAMA_MCP_ALLOW_CODER` | unset (off) | `1` enables `delegate_research` `adapter:"coder"`, which edits files and runs the caller's `agent.commands` in an isolated copy of the workspace and returns a patch for the caller to review and `git apply` (see [`src/research/coder-agent.ts`](https://github.com/bgauryy/FreeLlama/blob/main/packages/mcp/src/research/coder-agent.ts)) |
35
39
  | `FREELLAMA_CODER_RUN_TIMEOUT_SECONDS` | `300` (at most `1800`) | Timeout of one coder `run`; the whole call is still bounded by `agent.timeoutSeconds` (coder default at least 600 s) |
40
+ | `FREELLAMA_CODER_MAX_OUTPUT_BYTES` | `16777216` (16 MiB; at most 256 MiB) | Retained raw stdout/stderr cap per coder command. Overflow or a log-write error terminates the command and reports incomplete output. Model previews remain bounded separately; retained files have no aggregate cross-session quota |
36
41
  | `FREELLAMA_CODER_MAX_COPY_BYTES` | `209715200` (200 MB) | Size cap of a coder copy of a workspace that is not a git repository (`node_modules`, `target`, `dist` and `.git` excluded) |
37
42
  | `FREELLAMA_CODER_WRITABLE` | unset | Platform-separated extra directories the coder's allowed commands may write, such as `~/.cargo` for `cargo test`; an entry that holds or lies inside the workspace is refused |
38
43
  | `FREELLAMA_CODER_UNSANDBOXED_RUN` | unset | `1` lets the coder `run` without an OS sandbox (`sandbox-exec` or `bwrap`); without one, `run` is refused |
@@ -44,6 +49,8 @@ Serve-side placement settings (read by `freellama serve`, not the MCP process):
44
49
  | `FREELLAMA_EVICT_IDLE_MODELS` | on | Unload idle, unpinned models using reuse and load costs when a cold load needs room. `0` turns eviction off |
45
50
  | `FREELLAMA_CPU_NUM_THREAD` | half the logical cores (not set on macOS) | `num_thread` for CPU-placed tasks only; GPU tasks leave it to Ollama |
46
51
  | `FREELLAMA_MAX_QUEUE_WAIT_SECONDS` | `120` | How long a managed task queues for a slot or memory |
52
+ | `FREELLAMA_MAX_REQUEST_BYTES` | `67108864` (64 MiB) | Managed request/response byte cap; Ollama embedding, decision, error and NDJSON response bytes share it. Buffered terminal and rewritten gateway responses use the same per-response bound before UTF-8 decoding, including SSE/JSON/error bodies; fetch may already have decompressed them. Overflow fails without replay (502 before gateway headers, stream failure afterward, CLI exit 1); raw real-tag passthrough remains pull-driven |
53
+ | `FREELLAMA_DURABLE_JOBS` | off | `true`/`1` enables durable deferred receipts and idempotency with a file-backed store; prompts are not persisted or replayed. See [durable deferred jobs](../../docs/DEFERRED_JOBS.md) |
47
54
  | `OLLAMA_NUM_PARALLEL`, `OLLAMA_KV_CACHE_TYPE`, `OLLAMA_FLASH_ATTENTION` | Ollama's | Read as hints for the memory estimate: parallel slots multiply the KV cache, and `q8_0`/`q4_0` shrink it only with flash attention. Set them for serve the same way as for Ollama |
48
55
 
49
56
  Research-adapter settings are deployment defaults. The optional `delegate_research.agent` object
@@ -107,8 +114,80 @@ managed admission; it does not create Ollama
107
114
  slots or relax memory guards. Existing queued work keeps its captured cost. See
108
115
  [monitoring controls](https://github.com/bgauryy/FreeLlama/blob/main/docs/MONITORING.md#adaptive-concurrency).
109
116
 
110
- **No measurements are compiled in.** In a repository checkout, per-model research grades load from
117
+ Research-adapter grades load at runtime. In a repository checkout, per-model research grades load from
111
118
  `packages/mcp/evidence/model-evidence.json`. A published package does not include that repository
112
119
  file, so its evidence table is empty unless you set `FREELLAMA_MCP_MODEL_EVIDENCE`. An unmeasured
113
120
  model yields a `verify` verdict, and an unreadable evidence file is reported on stderr and treated
114
121
  as empty. Tool descriptions state the rules.
122
+
123
+ Job/workflow model selection first consumes the Rust router's machine-local throughput evidence,
124
+ then falls back to the portable installed-model catalog when that evidence is unavailable or
125
+ insufficient. Capable workflows and OCR also require a task-quality policy for a calibrated pick;
126
+ throughput alone does not establish job accuracy. The selected model and note remain visible, and
127
+ caller-supplied fields still win.
128
+
129
+ `freellama bench-all` explicitly measures installed models and writes
130
+ `$FREELLAMA_HOME/benchmark-report.json` by default (normally
131
+ `~/.octocode/freellama/benchmark-report.json`). On its next start, `serve` discovers that report;
132
+ `FREELLAMA_BENCHMARK_REPORT` can select another file. Only matching schema-2 host/hardware,
133
+ endpoint and artifact-digest evidence qualifies throughput. CPU-assigned runners do not reuse
134
+ the primary endpoint's report. See [machine calibration](../../docs/MODEL_SELECTION.md#turn-measurements-into-routing-evidence)
135
+ for the complete procedure, policy files and evidence limits.
136
+
137
+ Host-memory admission defaults to `require-memory` on Linux, macOS and Windows. Windows uses a
138
+ bounded PowerShell/CIM query; CPU load, OS pressure, thermal, swap and GPU telemetry remain
139
+ unavailable there. Failed memory observation holds local work, and `require-all` cannot be
140
+ satisfied by the Windows collector. See [resource controls](../../docs/CLI.md#bound-admission)
141
+ for explicit operator policy overrides.
142
+
143
+ ## Research model and sweeps
144
+
145
+ Without `model` (and without `FREELLAMA_MCP_DEFAULT_MODEL`), `delegate_research` uses the first
146
+ research-agent catalog pick (stronger, default, small) that is installed and fits in memory now;
147
+ GitHub research skips the small pick, which scored 1 of 6 there. When none fits, it takes the
148
+ installed default (then stronger) pick and lets serve's memory gate admit, wait or refuse the load;
149
+ with no pick installed it falls back to routing. The receipt's `researchModel` says which and why.
150
+ GitHub answers are grounded against the adapter's own `gh` results; local adapters check the workspace on disk. A sweep whose
151
+ server process exited reports `interrupted` with the `sweep{action:"resume", sweepId}` call, which
152
+ reuses saved chunk results; sweeps never resume on their own.
153
+
154
+ ## Where an answer goes
155
+
156
+ Every result is saved whole (`response_file`; read one part with `read_response{file, section}`).
157
+
158
+ `run_task` and `task_jobs` answer with **text alone**: the answer, its `check:` lines and a closing
159
+ `response_file: <path>` line, with no `structuredContent`. Hosts such as Claude Code show
160
+ `structuredContent` in place of the text when a result has it, which handed the agent the whole
161
+ receipt (1–3k tokens) around a two-line answer. The receipt (route, model, timings, placement,
162
+ tokens) stays in the response file, one `read_response` away; `receipt:"full"` on a call returns it
163
+ inline, and `FREELLAMA_MCP_RECEIPT=structured` restores inline receipts for every call (those two
164
+ tools then declare their output schema again). The other tools always return `structuredContent`.
165
+ `run_task` and `delegate_research` take two more fields that choose what comes back inline:
166
+
167
+ - `output`: `auto` (default) returns the answer inline up to 8,000 characters (about 2,000 tokens),
168
+ and above that a short view: the label line, the first lines of the answer, every `check:`,
169
+ `handoff_file:`, `verification:` and `cited:` line unchanged, and the file holding the whole
170
+ answer. `inline` always returns the whole text; `file` always returns the short view. The
171
+ default exists because hosts limit tool output (Claude Code warns above 10,000 tokens and caps
172
+ it at 25,000 by default) and every inline character costs the calling agent tokens.
173
+ A shortened view also replaces the answer's text inside `structuredContent` with
174
+ `answer moved: <output_file or read_response location>` and adds `output: {mode, chars, file}`.
175
+ - `outputPath`: also write the answer there as Markdown (the `saveAs` handoff format), returned as
176
+ `output_file`. The caller owns the path: a new file is created and an existing one replaced. It
177
+ must resolve inside the readable roots (the project, the temp directory, `FREELLAMA_FILE_ROOTS`),
178
+ outside any `.git` directory, and not be a directory. It is checked before the model runs, so it
179
+ is refused with `preview` or `defer`; with `tasks` one file holds the combined text. A failed
180
+ write keeps the whole answer inline and names the error.
181
+
182
+ A shortened view without an `outputPath` writes the answer to a new
183
+ `${FREELLAMA_HOME}/tmp/<timestamp>-<pid>-<n>.md` (default `~/.octocode/freellama`) and ends with
184
+ `output_file: <path> (the full answer, N chars)`; a later `run_task{files:[output_file]}` can read
185
+ it. Those files are deleted after `FREELLAMA_RESPONSE_TTL_DAYS` (default 7; `0` keeps them). If
186
+ that write fails, the view points at the saved response
187
+ (`read_response{file, section:"/result/content/0/text"}`); with neither, the whole answer is
188
+ returned with a note.
189
+
190
+ `task_jobs{action:"get"}` shapes a finished deferred job the same way (its own `output`, default
191
+ `auto`). Receipts keep the routing, timing and token counts inline; telemetry and nested metrics move
192
+ to the saved `response_file`. `models{view:"installed"}` and `resident` return a slim per-model set;
193
+ `includeVerbose:true` returns the full records.
package/DEVELOPING.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  Build, test, and release notes for the [FreeLlama MCP server](README.md).
4
4
 
5
+ Published npm installs require Node.js 22+ and use a prebuilt platform package; they do not compile
6
+ Rust. This guide's build commands are for repository development. Use the repository's pinned
7
+ Rust toolchain and Node.js 22.12+ with Corepack for source builds.
8
+
5
9
  ## Build
6
10
 
7
11
  Build the native addon from the repository root and this package in place.
@@ -13,11 +17,14 @@ yarn install
13
17
  yarn build
14
18
  ```
15
19
 
16
- `yarn build` writes the MCP server, `packages/mcp/dist/index.js` (shebang, executable). During
20
+ `yarn build` writes the MCP server, `packages/mcp/dist/index.js` (shebang, executable), and the
21
+ agent CLI, `dist/agent-cli.js` (the `freellama run`, `chat`, `gateway`… commands, which the CLI package's launcher runs). During
17
22
  checkout development it loads `native/freellama.<triple>.node`. Published installs resolve the
18
23
  matching `@octocodeai/freellama-native-<target>` optional package instead, so the base MCP package remains
19
- portable. The research adapters compile to `dist/research/{bash-agent,octocode-agent}.js`, and the
20
- repository `docs/` guides are copied into `docs/`.
24
+ portable. The research adapters compile to `dist/research/{bash,octocode,github,coder}-agent.js`, and the
25
+ repository `docs/` guides are copied into `docs/`. MCP tools are registered from
26
+ `src/tools/registrations.ts`, which both `src/index.ts` and the agent CLI registry
27
+ (`src/agent-cli/registry.ts`) use, so the two surfaces expose the same tools.
21
28
 
22
29
  Piecewise, if you are iterating on one layer:
23
30
 
@@ -25,7 +32,7 @@ Piecewise, if you are iterating on one layer:
25
32
  # 1. Native addon → packages/mcp/native/freellama.<triple>.node
26
33
  yarn build:native
27
34
 
28
- # 2. This server → dist/index.js and dist/research/*.js via esbuild, plus docs/
35
+ # 2. This server → dist/index.js, dist/agent-cli.js and dist/research/*.js via esbuild, plus docs/
29
36
  yarn workspace @octocodeai/freellama-mcp-server build
30
37
  ```
31
38
 
@@ -45,12 +52,26 @@ Vitest, in three tiers (all TypeScript, under `test/`):
45
52
  |---|---|---|---|
46
53
  | `test/unit/` | `yarn test` (watch: `yarn test:watch`) | pure functions straight from `src/*.ts` — no build step, this is the TDD loop | nothing, a few seconds |
47
54
  | `test/integration/` | `yarn test:integration` | the built server over the real MCP protocol: tool contract, structured content, guardrails; rebuilds `dist/` itself | Ollama at `FREELLAMA_OLLAMA_ENDPOINT` (default :11434) |
48
- | `test/e2e/` | `yarn test:e2e` | every tool against the live system: real routing/execution, pull → delete round trip (net-zero), a real delegated research run | serve + Ollama + models, ~40s |
55
+ | `test/e2e/` | `yarn test:e2e` | live routing/execution, delegated research and an explicitly approved pull → delete round trip | serve + Ollama + models; lifecycle test additionally requires exact tag/size opt-in |
49
56
 
50
57
  The same commands work from the repository root (`yarn test` there also runs the CLI package's tests
51
58
  and the Rust suite).
52
59
  The integration/e2e tiers fail fast with a readable message when Ollama is down, and the lifecycle
53
- test refuses to delete a model already installed on the test system.
60
+ test refuses to delete a model already installed on the test system. The lifecycle opt-in variables
61
+ and readiness skips are documented in [test tiers](../../docs/TESTING.md#run-the-test-tiers).
62
+
63
+ [CI](../../.github/workflows/ci.yml) configures build, typecheck and Rust contracts on Ubuntu,
64
+ macOS and Windows. Ubuntu/macOS run the full JS/evaluation suite; Windows runs an explicit portable
65
+ CLI/protocol/checker allowlist, excluding the POSIX research/coder and script suites. This does not
66
+ qualify native Windows research/coder execution. Strict Rust lint runs on Ubuntu; release packaging
67
+ contracts run on Ubuntu/macOS; Windows adds a read-only PowerShell/CIM memory smoke. Inspect the hosted run before
68
+ claiming a lane passed. The local macOS checks recorded in [Testing](../../docs/TESTING.md#continuous-integration)
69
+ do not replace those runs or live inference qualification.
70
+
71
+ The Rust benchmark unit tests now live in `packages/rust-core/src/model_bench/tests.rs`; Windows
72
+ parser fixtures and resource panic/poison tests have separate modules. `job-calibration.test.ts`
73
+ checks calibrated-first selection and fallback without inference. The
74
+ [resource audit](../../docs/RUST_RESOURCE_AUDIT.md) states the lock review's scope and gaps.
54
75
 
55
76
  For default-endpoint autostart, the server starts `freellama serve` in the background at launch and
56
77
  logs a failure to stderr. On a tool call, a spawn failure, early exit, or readiness timeout rejects the
@@ -65,11 +86,15 @@ package has one npm optional dependency per platform in `scripts/release-platfor
65
86
  arm64, Linux arm64/x64 with glibc, Windows arm64/x64 with MSVC). `native/index.js` tries the checkout artifact first,
66
87
  then the host's optional package. A release is supported only when every artifact package passes
67
88
  the publish verifier; an installation made with `--omit=optional` cannot load the addon. `engines`
68
- requires Node >= 20.
89
+ requires Node >= 22. The matrix currently contains five targets; macOS x64 and Linux musl are not
90
+ published targets. A successful host build does not validate another target or registry install.
69
91
 
70
92
  Machine discovery distinguishes total host memory (`memory_bytes`) from known unified memory
71
93
  (`memory_kind: "unified"`). Library-tag `fitsInMemory` is a conservative host-memory preflight and
72
94
  includes `fitScope: "host_memory_budget_only"`; inspect `/api/ps` for actual accelerator placement.
95
+ Windows host admission now requires bounded CIM memory telemetry by default; missing pressure,
96
+ CPU-load, thermal and GPU measurements stay unknown. Parser fixtures run on every host, while the
97
+ Windows CI smoke exercises the real collector.
73
98
 
74
99
  Start the serve-backed tools' dependency from the repository root:
75
100
 
@@ -80,6 +105,10 @@ cargo run --release -- serve
80
105
  `freellama proxy` only forwards raw `/api/*` calls; only `serve` has the `/_freellama/v1/*` routes
81
106
  these tools call.
82
107
 
108
+ Automatic job calibration remains Ollama-backed. The optional managed llama.cpp adapter accepts
109
+ only explicitly configured bounded text tasks and does not supply observed placement, throughput
110
+ qualification or automatic job picks. See the [engine contract](../../docs/LLAMACPP.md).
111
+
83
112
  ## Publish
84
113
 
85
114
  `packages/mcp/` is the portable JavaScript package. Its `package.json` lists the platform packages
@@ -102,8 +131,10 @@ Treat `npm publish` as a public release action. Follow the
102
131
  - **No routing reimplementation.** `run_task`, `run_task {preview:true}`, and the installed-model list are HTTP
103
132
  calls into a running `freellama serve`, matching the CLI requests in `packages/cli/src/requests.rs`. `doctor` talks to Ollama
104
133
  and the host's portable machine-discovery layer directly. `ollama_manage` / `ollama_delete` hit Ollama's HTTP API. `delegate_research`
105
- is a subprocess. Routing decisions still live in exactly one place — the Rust core; see
106
- [what the MCP layer computes](README.md#what-the-mcp-layer-computes).
134
+ is a subprocess. Routing decisions still live in exactly one place — the Rust core; the MCP layer validates
135
+ request shapes and derives display fields such as answer text, resident placement labels, library
136
+ `fitsInMemory` and the research verdict. See the
137
+ [responsibility boundary](https://github.com/bgauryy/FreeLlama/blob/main/docs/ARCHITECTURE.md#responsibility-boundary).
107
138
  - **One connection pool.** `packages/rust-core/src/serve_client.rs` holds a single `reqwest::Client` in a
108
139
  `OnceLock` and clones the handle per request; `napi.rs` and the CLI share it.
109
140
  - **`unsafe_code` stays isolated.** The crate is `deny(unsafe_code)` except `napi.rs`, which