@octocodeai/freellama-mcp-server 0.5.0 → 0.6.1

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.
package/docs/CLI.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  The `freellama` command starts and inspects the local management layer that agents use to offload
4
4
  work. It exposes diagnostics, model routing, managed execution, resource controls, benchmarking,
5
- and Ollama-compatible passthrough. Use the [README quick start](../README.md#quick-start) for first
5
+ and Ollama-compatible passthrough. Use the [README CLI section](https://github.com/bgauryy/FreeLlama/blob/main/README.md#from-the-terminal) for first
6
6
  use and this reference to look up commands and controls.
7
7
 
8
8
  ## Choose a command
@@ -12,13 +12,12 @@ flowchart TD
12
12
  Q{"What do you need?"}
13
13
  Q -->|"Prepare first use"| I["init"]
14
14
  Q -->|"Inspect this machine"| D["doctor or machine"]
15
- Q -->|"Inspect or choose a model"| M["models, route, or recommend"]
16
- Q -->|"Execute a managed request"| T["session, natural-route, or task"]
15
+ Q -->|"Inspect or choose a model"| M["models or route"]
16
+ Q -->|"Execute a managed request"| T["session or task"]
17
17
  Q -->|"Run the control plane"| S["serve"]
18
18
  Q -->|"Preserve only Ollama APIs"| P["proxy"]
19
- Q -->|"Measure or compare"| B["bench-all, run, or eval"]
20
- Q -->|"Create a routing policy"| E["policy-from-eval"]
21
- Q -->|"Compare CLI and MCP"| L["tools"]
19
+ Q -->|"Measure models"| B["bench-all"]
20
+ Q -->|"Write a routing policy"| PE["policy from-eval"]
22
21
  ```
23
22
 
24
23
  | Command | Purpose | Needs `freellama serve` |
@@ -35,17 +34,12 @@ flowchart TD
35
34
  | `scope` | Create, inspect, fork, or delete bounded message history | Yes |
36
35
  | `warm` | Warm an installed model through managed admission | Yes |
37
36
  | `route` | Choose a model and request profile without executing it | Yes |
38
- | `recommend` | Return an installed route or a reviewed installation plan | Yes |
39
- | `natural-route` | Convert natural language to a route intent locally, then route it | Yes |
40
37
  | `task` | Route and execute one nonstreaming task | Yes |
41
38
  | `jobs` | List, inspect, cancel, or remove deferred tasks and warming operations | Yes |
42
39
  | `proxy` | Run only the Ollama-compatible retry and telemetry sidecar | No |
43
40
  | `bench-all` | Measure installed models by capability group | No |
44
- | `policy-from-eval` | Generate policy from quality-evaluation pass rates | No |
45
- | `tools` | Print MCP tools and their CLI equivalents | No |
41
+ | `policy from-eval` | Write a task policy (`platform.toml`) from a quality-evaluation aggregate and the installed tags | No |
46
42
  | `doctor` | Inspect Ollama, hardware, versions, and effective settings | No |
47
- | `run` | Run a frozen suite against one Ollama build | No |
48
- | `eval` | Compare the same frozen suite against stock and candidate builds | No |
49
43
 
50
44
  Run `npx @octocodeai/freellama <command> --help` for every accepted flag and enum value. The executable's help
51
45
  is authoritative; this page explains how the commands fit together.
@@ -53,13 +47,16 @@ is authoritative; this page explains how the commands fit together.
53
47
  ## Start the control plane
54
48
 
55
49
  ```bash
56
- npx @octocodeai/freellama serve --recommendation-catalog recommendations.example.toml
50
+ npx @octocodeai/freellama serve
57
51
  ```
58
52
 
59
53
  The default listener is `http://127.0.0.1:11435`, and the default Ollama upstream is
60
54
  `http://127.0.0.1:11434`. Use `--listen` and `--upstream` to change them. Nonloopback listeners
61
55
  require `--allow-remote` and a token from `--auth-token-file` or
62
- `FREELLAMA_AUTH_TOKEN_FILE`. Authentication applies to managed and passthrough routes.
56
+ `FREELLAMA_AUTH_TOKEN_FILE`. Authentication applies to managed and passthrough routes. The token
57
+ file must be a regular file, not a symlink, and hold one token of at least 32 bytes; surrounding
58
+ whitespace is trimmed. On Unix it must also be owner-only (mode 0600). Windows file permissions
59
+ (ACLs) are not checked, so protect the file with your user profile's permissions there.
63
60
 
64
61
  `serve` persists bounded adaptive feedback under the platform data directory by default. Override
65
62
  the path with `--feedback-file`; use `--ephemeral-feedback` only for disposable runs. See the
@@ -81,8 +78,9 @@ npx @octocodeai/freellama serve \
81
78
  --cpu-model nomic-embed-text:latest
82
79
  ```
83
80
 
84
- FreeLlama rejects a CPU upstream with no assignments, nonloopback upstreams, and endpoints that are
85
- aliases for the same socket. It also sets `options.num_gpu=0` on CPU-assigned managed requests.
81
+ FreeLlama rejects a CPU upstream with no assignments, `--cpu-model` without `--cpu-upstream`, and a
82
+ CPU upstream that is the same Ollama endpoint as `--upstream`, including loopback aliases on one port.
83
+ It also sets `options.num_gpu=0` on CPU-assigned managed requests.
86
84
  Read [CPU and GPU model routing](CPU_GPU_ROUTING.md) before deploying this layout.
87
85
 
88
86
  After startup, require `contracts.placement_observation` and `placement_evidence_gate`, then inspect
@@ -98,8 +96,8 @@ placement.
98
96
 
99
97
  ### Bound admission
100
98
 
101
- `--max-concurrent-tasks` is the primary/GPU cost budget, not a request count. Without a flag,
102
- environment variable, or runtime-file value it defaults to 2 units per `OLLAMA_NUM_PARALLEL` slot of
99
+ `--max-concurrent-tasks` is the primary/GPU cost budget, not a request count. Without a flag or
100
+ runtime-file value it defaults to 2 units per `OLLAMA_NUM_PARALLEL` slot of
103
101
  the Ollama server (read from its process environment where visible; Ollama's own default is 1, so 2).
104
102
  `freellama config` shows the effective value and where it came from.
105
103
  `--cpu-max-concurrent-tasks` controls the independent CPU pool and defaults to 1. Default base costs
@@ -133,27 +131,39 @@ context sizing, can also live in a runtime file (`--runtime-config`) that `serve
133
131
  changes. See [Monitoring and live tuning](MONITORING.md). The standalone
134
132
  `proxy` command keeps its cap opt-in for compatibility.
135
133
 
136
- The local host-pressure gate defaults to holding below 15% available RAM and resuming above 20%
137
- after two healthy samples; minimum reserves are 1 GiB and 2 GiB, respectively. Tune the percentages
138
- with `--resource-hold-available-percent` and `--resource-resume-available-percent`; the hold value
139
- must be lower than the resume value, and neither can exceed 100. Health reports the policy, sampled
140
- signals, unknown measurements, and reserved memory. These flags do not change Ollama or OS settings.
141
-
142
- The reserve applies to every new managed load, not only to the pressure gate: a task is admitted
143
- when effective available RAM covers already-reserved bytes, the task's estimated bytes, and the
144
- reserve (the hold reserve normally; the larger resume reserve while capacity is recovering).
145
- Effective available RAM is free memory plus a bounded reclaimable estimate, so it can be far lower
146
- than the OS "free" percentage. A refusal reports `assessment.status: "held_insufficient_capacity"`
147
- with `required_with_reserve_bytes` and `effective_available_bytes`; free memory, choose a smaller
148
- model, or lower the percentages deliberately.
134
+ The local host-pressure gate reports low available RAM below 15% and clears it above 20% after two
135
+ healthy samples; minimum reserves are 1 GiB and 2 GiB, respectively. Tune the percentages with
136
+ `--resource-hold-available-percent` and `--resource-resume-available-percent`; the hold value must be
137
+ lower than the resume value, and neither can exceed 100. Health reports the policy, sampled signals,
138
+ unknown measurements, and reserved memory. These flags do not change Ollama or OS settings.
139
+
140
+ On macOS, low available RAM is advisory and never refuses a task. Effective available RAM is free
141
+ memory plus a bounded reclaimable estimate, so it can be far lower than what the OS can actually
142
+ reclaim. When it does not cover already-reserved bytes, the task's estimated bytes, and the reserve,
143
+ FreeLlama first unloads idle unpinned runners, then dispatches anyway: the receipt reports
144
+ `status: "admitted_low_memory_estimate"` and `assessment.memory_advisory: "below_reserve"` with
145
+ `required_with_reserve_bytes` and `effective_available_bytes`. Ollama and the OS decide whether the
146
+ load fits. On Linux, Windows, and other platforms, where available RAM already counts reclaimable
147
+ cache (and is the hard cap in a container), the same shortfall unloads idle runners and then holds the
148
+ new load with `held_insufficient_capacity` until capacity returns, refusing with 503 at its deadline.
149
+ OS memory pressure holds all work where the OS reports it (macOS, and Linux when the kernel
150
+ exposes `/proc/pressure/memory`; Windows has no host collector yet). Active swapping and low RAM hold new loads only:
151
+ an already-resident runner adds no memory and stays admitted. CPU-load (one-minute load at or above
152
+ 1.5 per logical CPU) and thermal-throttling holds apply to CPU-assigned work and to cold loads, which
153
+ decode weights on the host cores and add a new heat source; a bounded request on a runner already
154
+ resident on the GPU neither waits for the cores nor cools the package by waiting, so it proceeds. The receipt's `resource_admission.assessment.held_by`
155
+ lists the holds that applied to the request.
149
156
  Both `serve` and `proxy` accept `--resource-telemetry-policy`:
150
157
 
151
- - `require-memory` (default): wait or refuse local inference when available RAM is unknown, including
152
- raw requests with zero forecast bytes. Missing thermal data alone does not block this policy.
153
- - `require-all`: require all signals applicable to the collector. The built-in Linux collector does
154
- not provide OS pressure or thermal signals and marks those as unsupported; custom collectors must
155
- provide them. Unsupported signals are not evidence of healthy hardware.
156
- - `best-effort`: explicitly permit unknown telemetry unless an observed pressure hold is active.
158
+ - `require-memory` (default on Linux and macOS): wait or refuse local inference when available RAM is
159
+ unknown, including raw requests with zero forecast bytes. Missing thermal data alone does not block
160
+ this policy.
161
+ - `require-all`: require all signals applicable to the collector. The built-in Linux collector reads
162
+ OS memory pressure from `/proc/pressure/memory` when the kernel provides it, but has no thermal
163
+ signal and marks it as unsupported; custom collectors must provide it. Unsupported signals are not
164
+ evidence of healthy hardware.
165
+ - `best-effort`: explicitly permit unknown telemetry unless an observed pressure hold is active. This
166
+ is the default on Windows, which has no built-in memory collector.
157
167
 
158
168
  Remote upstreams bypass local host policy. Raw metadata and empty unload requests remain available
159
169
  during a hold. Route receipts separate `queue_readiness` from `resource_readiness`, and include
@@ -163,7 +173,7 @@ its phase and omits estimates that were not obtained.
163
173
 
164
174
  See [resource admission](ARCHITECTURE.md#managed-task-execution) for scope and limitations.
165
175
 
166
- `route`, `recommend`, and `task` accept
176
+ `route` and `task` accept
167
177
  `--execution-preference auto|prefer-cpu|prefer-gpu`. This is a fallback-capable hint over models
168
178
  already assigned by the operator; it never rewrites raw passthrough and never makes an ineligible
169
179
  model eligible. Preview the route and inspect the `execution` receipt to confirm whether the hint
@@ -203,13 +213,6 @@ without them it falls back to capability/context-compatible models and reports l
203
213
  and missing quality evidence. `quality` requires a policy unless you supply an explicit model.
204
214
  An explicit minimum-confidence gate still refuses insufficient evidence in every objective.
205
215
 
206
- `recommend` is side-effect-free. If no installed model qualifies, it can return an installation
207
- plan from the reviewed recommendation catalog, but it never pulls a model.
208
-
209
- `natural-route` asks the configured local intent model to produce structured intent, validates that
210
- intent, and then invokes the same deterministic router as `route`. It does not let the intent model
211
- choose the final model directly.
212
-
213
216
  ## Execute tasks
214
217
 
215
218
  The prompt for `task` is positional:
@@ -233,6 +236,8 @@ Useful task options include:
233
236
  - `--priority interactive|normal|background` for fair admission scheduling.
234
237
  - `--max-wait-seconds` for a shorter admission/resource wait budget.
235
238
  - `--timeout-seconds` for a total deadline including discovery, waiting, loading, and inference.
239
+ - `--stop-on-repetition` to stream the task and stop once the output repeats itself, keeping all
240
+ generated text.
236
241
  - `--defer` to return a job ID immediately.
237
242
 
238
243
  Inspect deferred work with `jobs`, retrieve a result with `jobs --id <uuid>`, and cancel one task
@@ -266,7 +271,7 @@ benchmark record for the selected model.
266
271
 
267
272
  ```mermaid
268
273
  flowchart LR
269
- Q["Quality evaluation aggregate"] --> P["policy-from-eval"]
274
+ Q["Quality evaluation aggregate"] --> P["freellama policy from-eval"]
270
275
  P --> PF["platform.toml"]
271
276
  T["Local throughput benchmark"] --> BR["benchmark-report.json"]
272
277
  PF --> S["freellama serve"]
@@ -274,36 +279,62 @@ flowchart LR
274
279
  S --> C["Medium confidence for configured, measured routes"]
275
280
  ```
276
281
 
277
- Generate the policy from correctness data and the benchmark report from local runtime data:
282
+ Generate the policy from correctness data with `policy from-eval` and the benchmark report from
283
+ local runtime data:
278
284
 
279
285
  ```bash
280
- npx @octocodeai/freellama policy-from-eval \
281
- --aggregate benchmark/local/results/MODEL/aggregate.json \
286
+ npx @octocodeai/freellama policy from-eval \
287
+ --aggregate aggregate.json \
282
288
  --task coding \
283
289
  --min-pass 0.8 \
284
290
  --out platform.toml
285
291
 
286
292
  npx @octocodeai/freellama bench-all --output benchmark-report.json
287
- npx @octocodeai/freellama serve --recommendation-catalog recommendations.example.toml
293
+ npx @octocodeai/freellama serve
288
294
  ```
289
295
 
290
- `serve` discovers `platform.toml` and `benchmark-report.json` in its working directory. Explicit
291
- `--policy-file` and `--benchmark-report` values take precedence.
296
+ `serve` resolves each file in this order: the explicit flag, its environment variable, the working
297
+ directory, then the per-user config directory (`$XDG_CONFIG_HOME/freellama/` or
298
+ `~/.config/freellama/`; `%APPDATA%\FreeLlama\` on Windows).
292
299
 
293
- Replace `MODEL` with the directory containing your completed quality-evaluation aggregate.
300
+ | File | Flag | Environment variable | Discovered name |
301
+ |---|---|---|---|
302
+ | Task policy | `--policy-file` | `FREELLAMA_POLICY_FILE` | `platform.toml` |
303
+ | Benchmark report | `--benchmark-report` | `FREELLAMA_BENCHMARK_REPORT` | `benchmark-report.json` |
294
304
 
295
- `policy-from-eval` reads `pass_at_1`, not the throughput produced by `bench-all`. It refuses expired
296
- aggregates and fewer than three trials unless `--allow-smoke` is explicit, and it skips models that
297
- are not installed. This prevents speed data from being mislabeled as quality evidence.
305
+ A task policy file has this shape:
298
306
 
299
- ## Compare the CLI and MCP surfaces
307
+ ```toml
308
+ schema_version = 1
300
309
 
301
- ```bash
302
- npx @octocodeai/freellama tools
310
+ [policies.code_repair]
311
+ qualified_models = ["qwen3.8:27b-mlx"] # best first; quality-qualified only
312
+
313
+ # Optional request defaults for one exact tag on this task: think and num_predict (>= 1).
314
+ [policies.code_repair.model_options."qwen3.8:27b-mlx"]
315
+ think = false
316
+ num_predict = 512
303
317
  ```
304
318
 
305
- The command prints the maintained parity map. MCP-only operations are `delegate_research` and the
306
- online `models { view: "library" }` view. CLI-only operations include `serve`, `proxy`,
307
- `recommend`, `natural-route`, `bench-all`, `policy-from-eval`, `run`, and `eval`.
319
+ `serve` rejects unknown fields, including `num_ctx`: context size is routing-owned, so set
320
+ `context_tokens` per request instead. Caller request options win over `model_options`, and
321
+ `think = true` applies only to models with the thinking capability. See the annotated
322
+ [platform.example.toml](https://github.com/bgauryy/FreeLlama/blob/main/platform.example.toml).
323
+
324
+ The MCP server autostarts `serve` with its own environment and an arbitrary working directory, so
325
+ put a machine-wide policy in the config directory or set the variables in the MCP client's `env`.
326
+ `serve` prints each file it picked up.
327
+
328
+ `policy from-eval` reads `pass_at_1`, not the throughput produced by `bench-all`. It refuses
329
+ expired aggregates and fewer than three trials unless `--allow-smoke` is explicit, and it skips
330
+ models that are not installed on `--ollama-endpoint` (default `FREELLAMA_OLLAMA_ENDPOINT`, then
331
+ `http://127.0.0.1:11434`). This prevents speed data from being mislabeled as quality evidence.
332
+ It accepts the task kinds `route` accepts, with `-` or `_` (`code-repair` or `code_repair`), writes
333
+ to stdout unless `--out` is given, and reports a refusal as one `error: ...` line with exit status 1.
334
+
335
+ ## Compare the CLI and MCP surfaces
336
+
337
+ MCP-only operations are `delegate_research` and the online `models { view: "library" }` view.
338
+ CLI-only operations include `serve`, `proxy`, `bench-all`, `policy from-eval`, and `auth-token`.
308
339
 
309
- For the MCP tool contracts, read the [MCP package reference](../packages/mcp/README.md).
340
+ For the MCP tool contracts, read the [MCP package reference](https://github.com/bgauryy/FreeLlama/blob/main/packages/mcp/README.md).
@@ -9,7 +9,7 @@ memory checks, and model transitions for each backend; the operator configures t
9
9
  eligible tags. A configured CPU backend is intent: inspect the placement observation before
10
10
  treating it as proof of CPU execution.
11
11
 
12
- This configuration is useful for embeddings, intent interpretation, and other small helper models.
12
+ This configuration is useful for embeddings, short classification, and other small helper models.
13
13
  Benchmark large CPU workloads before adopting them. Apple silicon shares memory bandwidth; systems
14
14
  with discrete GPUs have different contention and transfer costs, so neither result transfers
15
15
  without measurement.
@@ -28,7 +28,9 @@ machine-specific:
28
28
 
29
29
  `doctor` reports `machine.memory_bytes` on macOS, Linux, and Windows. It reports
30
30
  `machine.unified_memory_bytes` only when unified memory is known; that compatibility field is not a
31
- VRAM estimate on discrete-GPU hosts. Model-library fit is therefore a host-memory preflight, and
31
+ VRAM estimate on discrete-GPU hosts. `machine.gpu` names the accelerator when the OS reports it
32
+ (Apple model and core count, or NVIDIA name and memory on Linux), and `performance_cpus` /
33
+ `efficiency_cpus` split hybrid CPUs on macOS. These are identity facts, not placement proof. Model-library fit is therefore a host-memory preflight, and
32
34
  actual accelerator placement must come from Ollama's resident-runner report.
33
35
 
34
36
  An agent can choose `auto`, `prefer_cpu`, or `prefer_gpu`, but it cannot invent topology. The
@@ -54,7 +56,7 @@ flowchart TB
54
56
  CP --> CPU["CPU runner"]
55
57
  ```
56
58
 
57
- FreeLlama does not inspect or rewrite raw passthrough request bodies. A direct Ollama client that
59
+ FreeLlama does not rewrite raw passthrough request bodies or route them by model. A direct Ollama client that
58
60
  needs model-aware CPU placement must use the managed task endpoint instead.
59
61
 
60
62
  ## Start the backends
@@ -115,7 +117,7 @@ unsafe or ambiguous configurations:
115
117
  - A CPU model assignment without `--cpu-upstream`
116
118
  - Empty model names
117
119
  - The same socket expressed through aliases such as `localhost:11434` and `127.0.0.1:11434`
118
- - A nonloopback upstream
120
+ - An upstream that points back to the FreeLlama listener, or an unspecified host such as `0.0.0.0`
119
121
 
120
122
  A nonloopback FreeLlama listener requires `--allow-remote` and bearer-token authentication.
121
123
  See the [production runbook](PRODUCTION.md) for remote ingress requirements.
@@ -214,7 +216,7 @@ curl --silent http://127.0.0.1:11436/api/ps | jq '.models[] | {name, size, size_
214
216
  A fully CPU-loaded model reports `size_vram:0`; a fully GPU-loaded model reports positive VRAM
215
217
  covering its resident `size`. Compare both values from the same `/api/ps` entry. Installed `/api/tags`
216
218
  file bytes can differ from resident memory and cannot prove a mixed placement. Positive VRAM without
217
- total resident size stays unknown. `observation.status` is `verified`, `mismatch`, or unavailable. Unknown, mixed, and mismatched
219
+ total resident size stays unknown. `observation.status` is `verified`, `mismatch`, `not_resident`, or `unavailable`. Unknown, mixed, and mismatched
218
220
  samples are reported but excluded from adaptive feedback.
219
221
 
220
222
  ## Understand concurrency
@@ -250,17 +252,18 @@ FreeLlama can overlap requests across the two servers even when each Ollama proc
250
252
  `OLLAMA_NUM_PARALLEL=1`. Raising `OLLAMA_NUM_PARALLEL` affects parallel requests within one server
251
253
  and multiplies K/V-cache memory; it is a separate tuning decision. `OLLAMA_MAX_QUEUE` likewise
252
254
  bounds each Ollama process after FreeLlama admission. It does not replace either backend's weighted
253
- FreeLlama budget, bounded waiter count, or queue-wait deadline. Raw passthrough uses a separate
254
- one-stream default cap in `serve`; its permit is held until the streamed response ends or is dropped.
255
+ FreeLlama budget, bounded waiter count, or queue-wait deadline. Raw generation passthrough uses a
256
+ separate one-stream default cap in `serve`; its permit is held until the streamed response ends or is dropped.
255
257
 
256
258
  The runtime file's `[task_costs]` table can tune individual task-kind weights without increasing
257
259
  the entire pool's ceiling. Default vision weight four can serialize two vision requests under a
258
260
  four-unit budget even when Ollama has two slots. A lower weight requires a qualified workload;
259
261
  it does not add engine slots or relax memory checks. See
260
262
  [monitoring controls](MONITORING.md#adaptive-concurrency).
261
- Mutating raw requests also require exclusive access to the primary backend's managed transition
262
- lock and receive 503 while it is busy. Metadata GET/HEAD calls remain available. This prevents raw
263
- inference or model lifecycle calls from overlapping a managed generation on that backend.
263
+ Raw generation requests also require exclusive access to the primary backend's managed transition
264
+ lock and receive 503 if it stays busy past the raw queue wait. Metadata GET/HEAD, `/api/show`,
265
+ model-store calls (pull, push, copy, delete), and empty `keep_alive:0` unloads remain available.
266
+ This prevents raw inference from overlapping a managed generation on that backend.
264
267
 
265
268
  ## Understand automatic feedback
266
269
 
@@ -352,7 +355,6 @@ and `execution.lifecycle`; a failed unload is reported without discarding the co
352
355
  Prefer the following assignments:
353
356
 
354
357
  - Small embedding models
355
- - Lightweight intent models
356
358
  - Short extraction or classification helpers with measured CPU behavior
357
359
 
358
360
  Benchmark these assignments before adopting them:
@@ -381,9 +383,8 @@ A configured but unreachable CPU backend causes model discovery to fail closed.
381
383
  can also be unavailable until the secondary server returns. Raw passthrough to the primary server
382
384
  continues to work because it does not depend on catalog discovery.
383
385
 
384
- For the surrounding runtime settings, see
385
- [Ollama and FreeLlama optimization](dev/OLLAMA_SYSTEM_OPTIMIZATION.md). For all `serve` flags, see the
386
- [CLI reference](CLI.md).
386
+ For the surrounding Ollama settings, see [Production](PRODUCTION.md#configure-ollama-explicitly). For
387
+ all `serve` flags, see the [CLI reference](CLI.md).
387
388
 
388
389
  ## Upstream sources
389
390
 
@@ -10,8 +10,7 @@ are not compiled into routing. Re-run
10
10
  `doctor.machine.memory_bytes` is host RAM; a discrete GPU's usable VRAM must be observed separately.
11
11
 
12
12
  For supported features and sourced publisher use-case guidance, inspect
13
- `models {view:"installed", includeLibrary:true}` through MCP. The
14
- [Ollama metadata reference](MODEL_METADATA.md) explains digest matching, variant capabilities,
13
+ `models {view:"installed", includeLibrary:true}` through MCP. [Model metadata](#model-metadata) explains digest matching, variant capabilities,
15
14
  custom-model fallbacks, and how to read family claims without treating them as quality measurements.
16
15
 
17
16
  ```mermaid
@@ -33,10 +32,16 @@ flowchart TD
33
32
  grounded research, image description, OCR, and summarization. Using one large multimodal model also
34
33
  avoided contention between separate heavy text and vision runners.
35
34
 
36
- Read the [retained model profile](../skills/freellama/references/model-profile-qwen3.8-27b-mlx.md)
37
- and [delegation measurements](../skills/freellama/references/task-delegation.md) for scope and limits.
35
+ In those evaluations it was strong at grounded lookup, long-context retrieval and strict instruction
36
+ following, needed `think:true` and a generous output budget for multi-step reasoning, and about a
37
+ third of its unsupervised code-review findings were false or context-limited.
38
38
  These examples do not establish that a tag is installed or suitable on your host.
39
39
 
40
+ Dedicated OCR models answer best to the prompts their model card documents; send them with base64
41
+ `images` in `run_task`. A model that repeats its answer until the output cap can run with
42
+ `stopOnRepetition:true`. See [Route images](https://github.com/bgauryy/FreeLlama/blob/main/packages/mcp/README.md#route-images)
43
+ for the early stop and the `output_check` receipt.
44
+
40
45
  `muse-glimmer:30b-mlx` was a credible alternative and answered 29 of 30 questions correctly
41
46
  (96.7%) with the Bash adapter, but it was slower and did not add a required capability in this
42
47
  workload.
@@ -61,7 +66,7 @@ keywords, repository search was both faster and more accurate in the measured sa
61
66
 
62
67
  ## Place helper models on CPU when useful
63
68
 
64
- A small embedding or intent model can be assigned to a second CPU Ollama process while a large
69
+ A small embedding or helper model can be assigned to a second CPU Ollama process while a large
65
70
  generation model remains resident on the primary GPU-capable process. This can overlap independent
66
71
  work, but it does not make CPU inference fast. Apple silicon shares memory bandwidth; discrete-GPU
67
72
  systems have different transfer and contention costs and need their own benchmark.
@@ -76,3 +81,109 @@ this machine and workload, not a universal model-placement rule. Follow
76
81
  `bench-all` measures local performance. A quality benchmark measures correctness. FreeLlama needs
77
82
  both the generated task policy and local benchmark data before grading a route medium confidence.
78
83
  See the [CLI reference](CLI.md#earn-medium-routing-confidence) for the commands.
84
+
85
+ ## Model metadata
86
+
87
+ The MCP `models` tool reads your Ollama instance and can enrich results with Ollama's public model
88
+ library. Supported features and advertised use cases are metadata: they do not change routing
89
+ confidence, and exact-model benchmarks and policy remain the quality evidence. The CLI's `models`
90
+ command reports the core catalog and does not expose these enrichment flags.
91
+
92
+ | Request | Result | External access |
93
+ |---|---|---|
94
+ | `models {view:"installed"}` | Managed inventory with a `knowledge` object for each model | Local backend data only |
95
+ | `models {view:"installed", includeLibrary:true}` | Inventory enriched with public guidance for verified local tags | Fetches model family and tag pages from ollama.com |
96
+ | `models {view:"detail", model:"gemma3:1b"}` | Ollama details, maximum context, and supported-use explanations | Selected Ollama endpoint only |
97
+ | `models {view:"detail", model:"gemma3:1b", includeLibrary:true}` | Details plus public guidance after a tag and digest check | Selected Ollama endpoint and ollama.com |
98
+ | `models {view:"library", query:"coding"}` | Public family search with descriptions and advertised feature chips | ollama.com and optional local inventory/profile reads |
99
+ | `models {view:"library", model:"gemma3"}` | All public tags with size, digest prefix, context, modalities, and cloud status | ollama.com and optional local inventory/profile reads |
100
+
101
+
102
+ | Option | Valid views | Default | Meaning |
103
+ |---|---|---|---|
104
+ | `includeLibrary` | `installed`, `detail` | `false` | Requests public metadata; the default makes no website calls |
105
+ | `includeReadme` | Library step 2, or `detail` with `includeLibrary:true` | `false` | Returns README text, capped at 65,536 characters, with its format and truncation flag |
106
+ | `includeVerbose` | `detail` | `false` | Returns Ollama's license and Modelfile fields independently of README enrichment |
107
+ | `limit`, `cursor` | `raw`, library tag listings; `limit` also applies to library search | Tag/raw page size 20; search limit 10 | Pages large lists; the tag cursor rejects a changed tag list |
108
+ | `ollamaEndpoint` | Direct Ollama views and library inventory reads | Configured Ollama endpoint | Chooses the Ollama instance; enriched managed inventory uses each model's assigned backend |
109
+
110
+ An incompatible option returns an error before any lookup. Installed enrichment omits full READMEs;
111
+ request one model's detail to read its README.
112
+
113
+ ### Supported features
114
+
115
+ `knowledge.supportedFeatures` preserves the feature strings from the selected source
116
+ (`supportedFeaturesSource`: `ollama_api` or `freellama_catalog`). Unknown future strings stay visible
117
+ but do not create routing requirements. `knowledge.supportedUseCases` explains each recognized
118
+ feature with `capability`, `use`, `reason`, and `basis:"supported_feature"`;
119
+ `knowledge.quality` stays `"metadata_only"`.
120
+
121
+ | Feature | Supported workflow | What to evaluate separately |
122
+ |---|---|---|
123
+ | `completion` | Text generation | Coding, summarization, reasoning, and instruction-following accuracy |
124
+ | `tools` | Tool calls | Argument correctness, tool selection, and agent-loop reliability |
125
+ | `vision` | Image input | OCR and visual understanding accuracy |
126
+ | `audio` | Audio workflows advertised by the model | Supported audio task and accuracy |
127
+ | `embedding` | Retrieval and similarity vectors | Retrieval quality on your documents |
128
+ | `thinking` | A thinking mode | Reasoning accuracy, latency, and token cost |
129
+ | `insert` | Suffix-based text insertion | Completion accuracy in the target code or text |
130
+ | `image` | Image generation | Output quality and supported controls |
131
+
132
+
133
+ ### Public guidance and provenance
134
+
135
+ For a verified installed model, `knowledge.library` contains the source page, tag-page URL,
136
+ `fetchedAt`, `expiresAt`, `cached`, exact public tag metadata, and:
137
+
138
+ | Field | Meaning |
139
+ |---|---|
140
+ | `description` | The public family description |
141
+ | `advertisedFamilyCapabilities` | Family feature chips; these do not extend the local tag's capabilities |
142
+ | `advertisedUseCases` | Recognized coding, tool-calling, image-understanding/OCR, reasoning, embedding, summarization, question-answering, translation, and long-context claims |
143
+ | `advertisedUseCases[].evidence` | A bounded source excerpt, source URL, and fetch timestamp |
144
+ | `usageNotes` | Bounded excerpts about requirements, restrictions, context, memory, languages, or query prefixes |
145
+ | `readmeAvailable` | Whether a README was extracted |
146
+ | `readme` | Requested text with `format` (`markdown` or `text`) and `truncated` |
147
+
148
+
149
+ Advertised uses have `basis:"advertised"`, `scope:"family"`, and `quality:"unmeasured"`. Extraction
150
+ skips fenced code and negative statements; an omitted use means no recognized claim, not absence.
151
+ These labels are not the `run_task` task enum. Local capabilities filter advertised uses: a family
152
+ vision chip cannot make `gemma3:1b` a vision candidate.
153
+
154
+ Installed enrichment requires the exact public tag and a digest-prefix match of at least 12 hex
155
+ characters. Custom names are never mapped by architecture or guessed base model; without a verified
156
+ match, public guidance is withheld. Library step 2 describes public models before installation, so
157
+ its guidance stays family-scoped; each `tags[]` entry carries its own modalities, context, digest
158
+ prefix, and `cloud` flag. Search's `cloudAvailable` badge does not prove local downloads are absent.
159
+
160
+ ### Lookup states
161
+
162
+ | `library.status` | Meaning | Next action |
163
+ |---|---|---|
164
+ | `not_requested` | Website enrichment was not requested | Set `includeLibrary:true` if external lookup is useful |
165
+ | `matched` | Installed tag and public digest prefix match | Read the sourced guidance, then evaluate the exact tag |
166
+ | `available` | Public family and tag pages were parsed in library step 2 | Inspect the exact tag before recommending a download |
167
+ | `unverified` | Digest or current backend inventory could not be verified | Recheck local inventory; retain local feature information |
168
+ | `digest_mismatch` | The public tag differs from the installed digest | Treat public guidance as unavailable for this installed model |
169
+ | `tag_not_found` | The parsed public tag list has no exact matching tag | Check the source and custom-model provenance |
170
+ | `unmatched` | The name cannot resolve to an exact public Ollama name | Keep use-case suitability unknown until provenance is verified |
171
+ | `not_found` | A requested public page returned HTTP 404 | Check the source URL or custom name |
172
+ | `unavailable` | Transport, timeout, HTTP refusal, or page-size limit prevented lookup | Retry later; local results remain available |
173
+ | `parse_error` | HTML content or tag rows were not recognized | Inspect the source; do not conclude the model is absent |
174
+ | `remote_model`, `remote_tag` | Remote Ollama fields or a hosted tag identify cloud execution | Select a local download tag for local execution |
175
+
176
+
177
+ `localModel:false` flags detected remote entries; cloud tags never become local trial
178
+ recommendations. This metadata is not processor-placement evidence.
179
+
180
+ ### Cache and request bounds
181
+
182
+ Each MCP process caches at most 128 families: successes for one hour, failures for one minute;
183
+ concurrent requests share one lookup and a restart clears the cache. Installed enrichment runs at
184
+ most four family lookups concurrently. Requests use GET, refuse redirects, cap each page at 2 MiB,
185
+ and time out after the smaller of 10 seconds and `FREELLAMA_MCP_FETCH_TIMEOUT_SECONDS`. They disclose
186
+ the requested public family name to ollama.com. Download size does not establish runtime memory
187
+ fit, placement, or quality, and model discovery never authorizes a pull. Sources:
188
+ [model details API](https://docs.ollama.com/api-reference/show-model-details),
189
+ [model-list API](https://docs.ollama.com/api/tags).
@@ -38,7 +38,9 @@ token and keeps it only for the browser tab.
38
38
  whether the model is pinned.
39
39
  - **`host`**: available and reserved RAM, whether the pressure gate is holding, and discrete-GPU
40
40
  total and free memory (`nvidia-smi` or amdgpu sysfs) when available. Optional `gpu_activity`
41
- reports driver counters separately from resident memory.
41
+ reports driver counters separately from resident memory. On macOS, `thermal_pressure` is the
42
+ system thermal pressure level (`nominal`, `moderate`, `heavy`, `trapping`, `sleeping`); `heavy`
43
+ or worse holds CPU-assigned work and cold loads. Other platforms report `null`.
42
44
  - **`ollama`**: the Ollama server's effective `OLLAMA_*` settings with a source for each — the
43
45
  running process's environment (Linux `/proc/<pid>/environ`, macOS `ps eww` for a same-user
44
46
  process), `launchctl getenv` for the macOS app, FreeLlama's own environment, or Ollama's default.
@@ -72,7 +74,8 @@ FreeLlama admission limits remain governed by its runtime configuration.
72
74
 
73
75
  `host.gpu_activity` is nullable. When available, it identifies its `source`,
74
76
  `scope: "observed_devices_all_processes"`, `window: "driver_defined"`, and individual `devices`.
75
- Each device has an identity, nullable `busy_percent`, and nullable `memory_busy_percent`.
77
+ Each device has an identity, nullable `busy_percent`, and nullable `memory_busy_percent`. Apple
78
+ devices may add `allocated_memory_bytes`, the driver's allocated memory across all processes.
76
79
  An observed zero means the driver reported zero; a missing or malformed counter remains unknown.
77
80
  Use `host.sample_age_ms` to check freshness.
78
81
 
@@ -115,8 +118,9 @@ The ledger lives next to the feedback file in the platform data directory. Choos
115
118
  `/metrics` exposes counters (`freellama_tasks_total`, `freellama_prompt_tokens_total`,
116
119
  `freellama_output_tokens_total`, `freellama_task_seconds_total`, `freellama_queue_wait_seconds_total`,
117
120
  `freellama_load_seconds_total`, `freellama_raw_requests_total`, `freellama_evictions_total`,
118
- `freellama_circuit_open_total`, `freellama_concurrency_limit_changes_total`) labelled by model,
119
- backend, task, and outcome, plus gauges for admission, queues, the raw proxy, host and GPU memory,
121
+ `freellama_circuit_open_total`, `freellama_concurrency_limit_changes_total`); task counters are
122
+ labelled by model, backend, task, and outcome, raw requests by kind and outcome, and the rest by
123
+ backend. Gauges cover admission, queues, the raw proxy, host and GPU memory,
120
124
  loaded models, and `freellama_ollama_num_parallel`. Point Prometheus, Grafana Agent, or any
121
125
  OpenMetrics-compatible scraper at it.
122
126
 
@@ -129,12 +133,13 @@ FreeLlama waits for safe capacity within a deadline and bounds the retained back
129
133
  | Managed queue full | `429` | `admission_queue_full` |
130
134
  | Raw proxy over its cap after `raw_queue_wait_seconds` | `429` | |
131
135
  | Managed wait exceeded `max_queue_wait_seconds` (or the task's `max_wait_seconds`) | `503` | `admission_timeout` |
132
- | Host resources remain held when the waiting budget expires | `503` | `resource_admission_unavailable` |
136
+ | OS pressure, swapping, CPU, thermal, or required telemetry still holds when the waiting budget expires (low available RAM alone only warns on macOS; low RAM and swapping never hold an already-resident runner, and CPU load and thermal never hold one on the GPU) | `503` | `resource_admission_unavailable` |
133
137
  | Backend circuit open | `503` | `upstream_circuit_open` |
134
138
 
135
139
  These capacity refusals carry a `Retry-After` header and `retry_after_seconds` in the body. For a queue it
136
- is estimated from the queue depth, the current limit, and the backend's recent average task time
137
- (1 to 120 seconds). A task can ask for a shorter wait with `max_wait_seconds` (`maxWaitSeconds`
140
+ is estimated from the queue depth, the lanes that can run at once (current limit divided by the
141
+ task's cost), and the backend's recent average service time, which excludes queue wait (1 to 120
142
+ seconds). A task can ask for a shorter wait with `max_wait_seconds` (`maxWaitSeconds`
138
143
  in MCP); the server caps it at the configured maximum.
139
144
 
140
145
  ## Circuit breaker
@@ -166,7 +171,7 @@ costs, and execution receipts use the resolved policy. Health retains its summar
166
171
  exposes the complete task-kind map under `admission.costs.base_by_task`. Task kinds remain
167
172
  caller-declared; these weights are cooperative scheduling policy, not workload classification.
168
173
  See the
169
- [runtime example](../freellama.runtime.example.toml) for the table syntax.
174
+ [runtime example](https://github.com/bgauryy/FreeLlama/blob/main/freellama.runtime.example.toml) for the table syntax.
170
175
 
171
176
  With `adaptive_concurrency = "cpu"` (the default) or `"all"`, each pool's limit moves between 1 and
172
177
  its configured ceiling:
@@ -263,9 +268,10 @@ out-of-memory shrink-and-retry only applies when the context was not requested e
263
268
 
264
269
  With `context_mode = "ollama_default"` (the default), FreeLlama sizes the context as before but
265
270
  omits `num_ctx` when Ollama's own default for the model is known, covers the request, and is at most
266
- `auto_context_max` (32768). The default is resolved in Ollama's order: the Modelfile's `num_ctx`,
267
- then `OLLAMA_CONTEXT_LENGTH`, then (discrete GPU only) Ollama's VRAM tier — 4096 below 24 GiB, 32768
268
- below 48 GiB, 262144 above. Receipts show `context_sizing.num_ctx_sent` and the default used.
271
+ `auto_context_max` (32768). The default is the Modelfile's `num_ctx`, then the
272
+ runtime file's `ollama_default_context`, then `OLLAMA_CONTEXT_LENGTH`, then (primary backend
273
+ on a discrete GPU only) Ollama's VRAM tier, from total VRAM minus `OLLAMA_GPU_OVERHEAD` — 4096 below
274
+ 23 GiB, 32768 below 47 GiB, 262144 from 47 GiB. Receipts show `context_sizing.num_ctx_sent` and the default used.
269
275
  Memory estimates always use the context Ollama can allocate. Use `"explicit"` to always
270
276
  send `num_ctx`.
271
277
 
@@ -273,13 +279,17 @@ send `num_ctx`.
273
279
 
274
280
  Put any of the settings above in a TOML file and start `serve --runtime-config <file>` (or set
275
281
  `FREELLAMA_RUNTIME_CONFIG`). Start from
276
- [`freellama.runtime.example.toml`](../freellama.runtime.example.toml). `serve` checks the file every
282
+ [`freellama.runtime.example.toml`](https://github.com/bgauryy/FreeLlama/blob/main/freellama.runtime.example.toml). `serve` checks the file every
277
283
  two seconds and applies changes to live admission pools; a waiting task sees the new limit at once.
278
284
 
279
- Precedence for every setting, strongest first: CLI flag, `FREELLAMA_*` environment variable, the
280
- runtime file, the built-in default. A flag or variable pins a value, so editing the file cannot
281
- override it; `freellama config` shows which source won. A malformed file or an unknown key is
282
- rejected at reload and the previous values stay in force.
285
+ Precedence for every setting, strongest first: CLI flag, environment variable (where one exists),
286
+ the runtime file, the built-in default. Only these settings have an environment variable:
287
+ `FREELLAMA_MAX_QUEUE_WAIT_SECONDS`, `FREELLAMA_EVICT_IDLE_MODELS`, `FREELLAMA_USAGE_QUEUE_CAPACITY`,
288
+ and the individual `FREELLAMA_SCOPE_*` and `FREELLAMA_KEEP_ALIVE_*` limits. Set every other key in
289
+ the runtime file or with its CLI flag. A flag or variable pins a value, so editing the file cannot
290
+ override it; `freellama config` shows which source won: `cli`, `env`, `file`, a default source
291
+ such as `default` or `ollama_num_parallel`, or `env_invalid` when a set variable failed validation.
292
+ A malformed file or an unknown key is rejected at reload and the previous values stay in force.
283
293
 
284
294
  The default GPU budget follows the Ollama server: 2 units per `OLLAMA_NUM_PARALLEL` slot (one chat
285
295
  per decoding slot), read from the running Ollama process where visible.