@octocodeai/freellama-mcp-server 0.1.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.
- package/README.md +426 -0
- package/adapters/agent_context.py +663 -0
- package/adapters/agent_transport.py +84 -0
- package/adapters/bash_agent.py +370 -0
- package/adapters/octocode_agent.py +394 -0
- package/dist/index.js +22971 -0
- package/docs/ADR_RESOURCE_AWARE_BACKEND_ROUTING.md +55 -0
- package/docs/ARCHITECTURE.md +416 -0
- package/docs/CLI.md +219 -0
- package/docs/CPU_GPU_ROUTING.md +352 -0
- package/docs/ECONOMICS.md +105 -0
- package/docs/INDEX.md +15 -0
- package/docs/MODEL_SELECTION.md +65 -0
- package/docs/OLLAMA_SIDECAR.md +76 -0
- package/docs/OLLAMA_SYSTEM_OPTIMIZATION.md +254 -0
- package/docs/PRODUCTION.md +195 -0
- package/docs/PRODUCT_POSITIONING.md +291 -0
- package/docs/TESTING.md +125 -0
- package/native/index.d.ts +158 -0
- package/native/index.js +45 -0
- package/native/package.json +7 -0
- package/package.json +69 -0
package/README.md
ADDED
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
# FreeLlama MCP server
|
|
2
|
+
|
|
3
|
+
Exposes FreeLlama's local-LLM control plane, and Ollama's lifecycle, as
|
|
4
|
+
[MCP](https://modelcontextprotocol.io) tools, built on the official
|
|
5
|
+
[TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk).
|
|
6
|
+
|
|
7
|
+
## Understand the eight tools
|
|
8
|
+
|
|
9
|
+
- `doctor`, `models`, `run_task`, `run_task_batch` — thin wrappers over the native NAPI bindings into the
|
|
10
|
+
Rust core (`../rust-core/src/napi.rs`); no CLI subprocess, no reimplemented routing logic.
|
|
11
|
+
`run_task { preview: true }` is the free decision-only form (the former `route` tool).
|
|
12
|
+
Preview and execution are separate calls: preview accepts routing fields only and rejects task
|
|
13
|
+
payloads or runtime controls instead of silently ignoring them.
|
|
14
|
+
`models { view: "library" }` queries the public `ollama.com` library (the former `search_models` tool).
|
|
15
|
+
- `session` — creates and releases a bounded, idle-expiring model-affinity handle for related
|
|
16
|
+
route/task calls. It does not store messages, prompt history, or Ollama's runner KV cache.
|
|
17
|
+
- `ollama_manage`, `ollama_delete` — Ollama's HTTP API for lifecycle operations the routing layer
|
|
18
|
+
doesn't cover.
|
|
19
|
+
- `delegate_research` — offloads a grounded code-research question to a local model and returns a
|
|
20
|
+
verdict computed from what the run did.
|
|
21
|
+
|
|
22
|
+
Use the smallest tool that owns the operation:
|
|
23
|
+
|
|
24
|
+
```mermaid
|
|
25
|
+
flowchart TD
|
|
26
|
+
Q{"What does the client need?"}
|
|
27
|
+
Q -->|"Diagnose the local runtime"| D["doctor"]
|
|
28
|
+
Q -->|"Inspect installed, resident, detailed, raw, or online models"| M["models"]
|
|
29
|
+
Q -->|"Choose or execute one task"| R["run_task"]
|
|
30
|
+
Q -->|"Fan out independent tasks"| B["run_task_batch"]
|
|
31
|
+
Q -->|"Keep/release related-task model affinity"| S["session"]
|
|
32
|
+
Q -->|"Pull or stop a model"| O["ollama_manage"]
|
|
33
|
+
Q -->|"Permanently remove a named model"| X["ollama_delete"]
|
|
34
|
+
Q -->|"Ground an answer in workspace files"| G["delegate_research"]
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
| Tool | Why it exists |
|
|
38
|
+
|---|---|
|
|
39
|
+
| `doctor` | Makes runtime, version, memory, and configuration drift visible before work starts. |
|
|
40
|
+
| `models` | Separates installed, resident, detailed, raw, and public-library questions instead of guessing from model names. |
|
|
41
|
+
| `run_task` | Applies the same deterministic routing, confidence, admission, and execution contract as the Rust control plane. |
|
|
42
|
+
| `run_task_batch` | Executes only caller-declared independent tasks. Stable IDs, a bounded dispatcher, 3:2:1 fair priority classes, and per-item errors make fan-out inspectable rather than implicit. |
|
|
43
|
+
| `session` | Lets an agent explicitly own the lifetime of a bounded affinity handle without misrepresenting it as conversation or KV storage. |
|
|
44
|
+
| `ollama_manage` | Exposes additive lifecycle operations that FreeLlama routing intentionally does not perform. |
|
|
45
|
+
| `ollama_delete` | Keeps irreversible deletion separate and explicit so a client can guard it. |
|
|
46
|
+
| `delegate_research` | Gives a local model bounded read-only tools and returns citations plus an independently computed verification verdict. |
|
|
47
|
+
|
|
48
|
+
## Follow the agent workflow
|
|
49
|
+
|
|
50
|
+
The server sends this workflow to every MCP client in its initialization instructions:
|
|
51
|
+
|
|
52
|
+
1. Start with `models {view:"installed"}`, then `models {view:"resident"}`. This gives a routing
|
|
53
|
+
agent the smallest current inventory first.
|
|
54
|
+
2. Call `doctor` only for runtime or configuration diagnosis. It returns `summary` by default;
|
|
55
|
+
use `view:"scheduler"` for configured/snapshot scheduling evidence or `view:"full"` for the
|
|
56
|
+
complete diagnostic. If Ollama is missing or unreachable, ask the operator to install or start it.
|
|
57
|
+
3. Classify the task. Offload embeddings, OCR/vision, bulk transforms, and sufficiently large
|
|
58
|
+
grounded lookups; retain small lookups and high-stakes judgment in the calling agent.
|
|
59
|
+
4. Prefer a qualified installed model and preview consequential work.
|
|
60
|
+
5. If none fits, collect the operator's modality, quality, context, latency, privacy, disk/download,
|
|
61
|
+
and memory constraints. Search the Ollama library, inspect exact tags and host-memory fit, and
|
|
62
|
+
present at most two candidates.
|
|
63
|
+
6. Ask the operator to approve one exact tag and its reported size before calling
|
|
64
|
+
`ollama_manage {action:"pull"}`. Searching or recommending never authorizes a download.
|
|
65
|
+
7. Execute, inspect the route/execution/admission receipt, and verify the result at the returned
|
|
66
|
+
confidence level.
|
|
67
|
+
|
|
68
|
+
### Use context and delegation deliberately
|
|
69
|
+
|
|
70
|
+
FreeLlama reduces the **calling agent's context burden**. It does not make an Ollama response more
|
|
71
|
+
accurate or eliminate the local model tokens needed to produce it. Its compact text cue avoids a
|
|
72
|
+
second serialized copy of the canonical `structuredContent`; its delegated adapter keeps full tool
|
|
73
|
+
observations on disk and presents them in pages when requested.
|
|
74
|
+
|
|
75
|
+
Use this economical sequence:
|
|
76
|
+
|
|
77
|
+
1. Request `models {view:"installed"}` before `doctor`; inventory is normally the smaller and
|
|
78
|
+
more relevant first decision.
|
|
79
|
+
2. Preview consequential generation with `run_task {preview:true}`. Preview is decision-only: it
|
|
80
|
+
neither generates nor reserves capacity.
|
|
81
|
+
3. Execute in a separate `run_task` call. Set `contextTokens` for the complete Ollama window and
|
|
82
|
+
`options.num_predict` for its output cap. A lower cap or window can lower cost **and** damage a
|
|
83
|
+
difficult answer, so choose it from the task rather than a global default.
|
|
84
|
+
4. Use `delegate_research` only for a self-contained question requiring files under
|
|
85
|
+
`workspacePath`. Bound `agent.maxTurns`, `agent.contextTokens`, and `agent.outputTokens`.
|
|
86
|
+
5. Keep the compact text cue in the active conversation; inspect `structuredContent`, a paged tool
|
|
87
|
+
result, or a bundled documentation resource only when its detail changes the next action.
|
|
88
|
+
|
|
89
|
+
For a delegated agent, estimated usable input is `contextTokens - outputTokens - safetyMarginTokens`
|
|
90
|
+
(the default margin is 256). The adapter pins the system instruction and question, preserves the
|
|
91
|
+
newest observations, compacts older observations into breadcrumbs, and refuses a pinned overflow
|
|
92
|
+
by default. `pinnedOverflow:"clip"` is a deliberate quality-risk override. Initial token counting
|
|
93
|
+
is conservative; successful Ollama calls calibrate later estimates.
|
|
94
|
+
|
|
95
|
+
Do not confuse operational evidence with answer quality. A receipt can prove admission, token
|
|
96
|
+
counts, placement, or unloading. It cannot prove research correctness, coding judgment, sustained
|
|
97
|
+
throughput, or fairness from one run. Check the returned confidence, policy evidence, and benchmark
|
|
98
|
+
evidence before accepting a consequential answer.
|
|
99
|
+
|
|
100
|
+
### Measure avoided external cost
|
|
101
|
+
|
|
102
|
+
Every successful `run_task`, batch item, and `delegate_research` result includes `telemetry.local`
|
|
103
|
+
when Ollama reports input/output token counts. To add `telemetry.externalEquivalent`, configure one
|
|
104
|
+
operator-owned rate card when starting the MCP server:
|
|
105
|
+
|
|
106
|
+
```text
|
|
107
|
+
FREELLAMA_EXTERNAL_COST_MODEL=EXTERNAL_MODEL_LABEL
|
|
108
|
+
FREELLAMA_EXTERNAL_COST_INPUT_USD_PER_M=INPUT_USD_PER_MILLION
|
|
109
|
+
FREELLAMA_EXTERNAL_COST_OUTPUT_USD_PER_M=OUTPUT_USD_PER_MILLION
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The receipt multiplies observed local input/output counts by those configured rates. It is an
|
|
113
|
+
equivalent avoided-API-cost estimate only when the local result replaces an external call. It
|
|
114
|
+
excludes provider caching and reasoning-token differences, retries, local electricity, and hardware
|
|
115
|
+
amortization; it is not a provider bill or net-profit calculation. Partial or invalid rate-card
|
|
116
|
+
configuration stops the MCP server at startup instead of emitting a misleading estimate.
|
|
117
|
+
|
|
118
|
+
### Route images and OCR
|
|
119
|
+
|
|
120
|
+
Use `run_task` for supplied image bytes, not `delegate_research`. Preview
|
|
121
|
+
`{task:"vision", requiredCapabilities:["vision"], preview:true}` before a consequential image
|
|
122
|
+
task. Execute separately with a prompt and base64 `images` values without data-URI prefixes. The
|
|
123
|
+
`images` field requires an explicitly trialed vision model; inspect the execution receipt for
|
|
124
|
+
admission and observed placement.
|
|
125
|
+
|
|
126
|
+
FreeLlama can prove that it routed and ran a request. It cannot infer OCR or visual-reasoning
|
|
127
|
+
quality from a capability tag, a model name, or GPU placement. Quality depends on the exact
|
|
128
|
+
installed model build, prompt and decoding settings, context/output budget, and available host
|
|
129
|
+
memory and accelerator performance. Validate representative held-out images on the target machine
|
|
130
|
+
and supply policy/benchmark evidence before automatically accepting a quality-sensitive result.
|
|
131
|
+
|
|
132
|
+
The caller owns task decomposition and concurrent submission. The operator owns endpoints, exact
|
|
133
|
+
CPU assignments, runtime settings, and lifecycle approval. FreeLlama owns qualification, managed
|
|
134
|
+
placement and admission. Ollama and the OS/driver own runner loading and physical CPU/GPU execution.
|
|
135
|
+
|
|
136
|
+
## Follow the architecture
|
|
137
|
+
|
|
138
|
+
```mermaid
|
|
139
|
+
flowchart TD
|
|
140
|
+
C["MCP client"] -->|"stdio JSON-RPC"| B["dist/index.js: eight tool registrations"]
|
|
141
|
+
B --> N["native/index.js and platform addon"]
|
|
142
|
+
N -->|"doctor"| L["Rust diagnostics"]
|
|
143
|
+
N -->|"models installed/resident; run_task"| S["freellama serve"]
|
|
144
|
+
S --> G["Primary Ollama"]
|
|
145
|
+
S --> U["Optional CPU Ollama"]
|
|
146
|
+
B -->|"detail, raw; manage; delete"| G
|
|
147
|
+
B -->|"library view"| W["ollama.com library"]
|
|
148
|
+
B -->|"delegate_research"| A["allowlisted local adapter subprocess"]
|
|
149
|
+
A --> S
|
|
150
|
+
C -->|"resources/read on demand"| D["packaged docs/*.md"]
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`doctor`, the installed/resident model views, and `run_task` use the NAPI binding instead of a CLI
|
|
154
|
+
subprocess. Direct lifecycle and no-serve model views use Ollama HTTP. `delegate_research` starts a
|
|
155
|
+
bounded adapter against an allowlisted workspace; each adapter model turn re-enters managed
|
|
156
|
+
`run_task` as `coding`, so it shares routing, admission, and placement evidence. Routing logic is
|
|
157
|
+
not duplicated in TypeScript.
|
|
158
|
+
|
|
159
|
+
## Read packaged documentation through MCP
|
|
160
|
+
|
|
161
|
+
The published MCP package includes every Markdown file from the repository `docs/` directory. The
|
|
162
|
+
repository directory remains the source of truth; the package build copies it into `docs/` and
|
|
163
|
+
creates `docs/INDEX.md`.
|
|
164
|
+
|
|
165
|
+
MCP clients can list resources and read `freellama://docs/index`, then fetch exactly one relevant
|
|
166
|
+
guide such as `freellama://docs/PRODUCTION`, `freellama://docs/CLI`, or
|
|
167
|
+
`freellama://docs/OLLAMA_SYSTEM_OPTIMIZATION`. Resources are deliberately lazy: do not load every
|
|
168
|
+
guide into an agent context. The server fails on startup if the generated index is absent, and the
|
|
169
|
+
release verifier checks that the packed documents match the root `docs/` set.
|
|
170
|
+
|
|
171
|
+
## Build
|
|
172
|
+
|
|
173
|
+
Build the native addon from the repository root and this package in place.
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# From the repository root (yarn workspaces — one install for every package)
|
|
177
|
+
yarn install
|
|
178
|
+
yarn build
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
`yarn build` writes **one** MCP file, `packages/mcp/dist/index.js` (shebang, executable). During
|
|
182
|
+
checkout development it loads `native/freellama.<triple>.node`. Published installs resolve the
|
|
183
|
+
matching `@octocodeai/freellama-native-<target>` optional package instead, so the base MCP package remains
|
|
184
|
+
portable. Research adapters are copied into `adapters/` for packed installs.
|
|
185
|
+
|
|
186
|
+
Piecewise, if you are iterating on one layer:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
# 1. Native addon → packages/mcp/native/freellama.<triple>.node
|
|
190
|
+
yarn build:native
|
|
191
|
+
|
|
192
|
+
# 2. This server → dist/index.js via esbuild (then copies the research adapters into adapters/)
|
|
193
|
+
yarn workspace @octocodeai/freellama-mcp-server build
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
`yarn start` needs `dist/index.js` and the compiled `.node` addon — `yarn build` from the repository
|
|
197
|
+
root produces both in a checkout. `dist/index.js` loads `native/index.js`, which loads a local addon
|
|
198
|
+
first and then a matching optional platform package. The `.node` binary is gitignored (a build
|
|
199
|
+
artifact); `native/index.js` and `native/index.d.ts` are hand-written and checked in.
|
|
200
|
+
|
|
201
|
+
## Run
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
node dist/index.js
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
The server speaks MCP over stdio — launch it from an MCP client (for example, Claude Desktop's
|
|
208
|
+
`claude_desktop_config.json`), not interactively.
|
|
209
|
+
|
|
210
|
+
## Test
|
|
211
|
+
|
|
212
|
+
Vitest, in three tiers (all TypeScript, under `test/`):
|
|
213
|
+
|
|
214
|
+
| Tier | Command (from this package) | Checks | Needs |
|
|
215
|
+
|---|---|---|---|
|
|
216
|
+
| `test/unit/` | `yarn test` (watch: `yarn test:watch`) | pure functions straight from `src/*.ts` — no build step, this is the TDD loop | nothing, ~0.5s |
|
|
217
|
+
| `test/integration/` | `yarn test:integration` | the built server over the real MCP protocol: tool contract, structured content, guardrails; rebuilds `dist/` itself | live Ollama on :11434, ~5s |
|
|
218
|
+
| `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 |
|
|
219
|
+
|
|
220
|
+
The same commands work from the repository root (`yarn test` there also runs the CLI package's tests).
|
|
221
|
+
The integration/e2e tiers fail fast with a readable message when Ollama is down, and the lifecycle
|
|
222
|
+
test refuses to delete a model already installed on the test system.
|
|
223
|
+
|
|
224
|
+
## Tools
|
|
225
|
+
|
|
226
|
+
| Tool | Needs `freellama serve`? | What it does |
|
|
227
|
+
|---|---|---|
|
|
228
|
+
| `doctor` | No | Runtime/configuration diagnostic. `summary` (default) returns endpoint, version, resident count, host/profile signals, and next step; `scheduler` adds configured/snapshot admission data; `config` returns categorized settings; `full` adds all non-duplicated diagnostics. The report distinguishes an observed same-user macOS process from configuration hints and never claims remote process visibility. |
|
|
229
|
+
| `models` | `installed` (default) and `resident` do; `detail`/`raw`/`library` don't | Views: `installed` (capabilities, derived `model_type`, VRAM, context, policy_rank), `resident` (loaded now + managed GPU/CPU split), `detail` (one model, real max context), paged `raw` (`GET /api/tags`), `library` (two-step ollama.com search: omit `model` for families, pass `model:"<family>"` for tags/`fitsInMemory`) |
|
|
230
|
+
| `run_task` | Yes | **Routes or executes** a chat/generate/embed call. `preview: true` accepts routing fields only and returns a decision without generation. Execution omits preview and supplies the payload. Embedding results withhold raw vectors by default (`returnEmbeddings: true` to get them) |
|
|
231
|
+
| `run_task_batch` | Yes | Executes only typed `{id, independent:true, task}` items. The nested `task` exposes the same task, routing, payload, and runtime controls as `run_task`; `maxParallelism` bounds fan-out. It is not a dependency graph scheduler. |
|
|
232
|
+
| `ollama_manage` | No (direct to Ollama) | `action: "pull"` downloads a model; `action: "stop"` force-unloads it. Both additive and idempotent |
|
|
233
|
+
| `ollama_delete` | No (direct to Ollama) | **Destructive**: permanently removes a model. Call only on an explicit human instruction naming the exact model |
|
|
234
|
+
| `delegate_research` | Yes (and spawns the adapter) | Answers a grounded question from files under `workspacePath`; managed coding turns return placement receipts, citations, and an independent verification verdict |
|
|
235
|
+
|
|
236
|
+
### Preserve Ollama request controls
|
|
237
|
+
|
|
238
|
+
All eight tools declare an MCP object `outputSchema`. Schemas type the stable fields FreeLlama owns
|
|
239
|
+
(such as route decision, page, answer, and session identifiers) while leaving Ollama-owned nested
|
|
240
|
+
payloads forward-compatible. `structuredContent` is canonical; normal text is a concise cue. For
|
|
241
|
+
the narrow `delegate_research` legacy case, set `legacyText:true` to receive serialized JSON text.
|
|
242
|
+
|
|
243
|
+
Use `models {view:"raw", limit:20}` and continue with its opaque `page.next_cursor`; a cursor
|
|
244
|
+
refuses continuation if the live model list changed. Library tag responses use the same paging
|
|
245
|
+
shape. Do not request `doctor {view:"full"}` in an agent loop: use `summary`, `scheduler`, or
|
|
246
|
+
`config` for the smallest diagnostic that answers the question.
|
|
247
|
+
|
|
248
|
+
`run_task` has two deliberately exclusive request shapes:
|
|
249
|
+
|
|
250
|
+
- Preview: set `preview: true`; pass routing fields such as `task`, `objective`, `model`,
|
|
251
|
+
`contextTokens`, `requiredCapabilities`, and placement/confidence gates. To preview tool use,
|
|
252
|
+
pass `requiredCapabilities: ["tools"]` rather than function definitions.
|
|
253
|
+
- Execution: omit `preview` (or set it to `false`) and pass `prompt`/`messages` for generative
|
|
254
|
+
tasks or `input` for embeddings, plus any applicable Ollama runtime controls.
|
|
255
|
+
|
|
256
|
+
Preview rejects `prompt`, `messages`, `input`, `images`, `tools`, `keepAlive`, `format`, `think`,
|
|
257
|
+
`options`, `logprobs`, `topLogprobs`, and `returnEmbeddings`. This prevents a client from attaching
|
|
258
|
+
work to a decision-only call and mistakenly assuming it ran.
|
|
259
|
+
|
|
260
|
+
`run_task.messages` preserves Ollama message fields beyond `role` and `content`, including images,
|
|
261
|
+
thinking, tool calls, and tool names. Managed requests also accept `format`, `think`, `options`,
|
|
262
|
+
`logprobs`, and `topLogprobs`. Use `contextTokens` for `num_ctx`; placement owns `num_gpu`, so both
|
|
263
|
+
keys are rejected inside `options`. The raw proxy remains available when a caller needs an Ollama
|
|
264
|
+
endpoint or feature that the managed MCP tool does not expose, including streaming.
|
|
265
|
+
|
|
266
|
+
`model_type` is a display-oriented value derived from Ollama's additive capabilities:
|
|
267
|
+
`generative`, `multimodal`, `embedding_only`, or `unknown`. Routing continues to use the original
|
|
268
|
+
capability set, not this summary label. Unknown future Ollama capabilities are omitted from the
|
|
269
|
+
typed routing set instead of being treated as a known capability.
|
|
270
|
+
|
|
271
|
+
### Use CPU assignments through MCP
|
|
272
|
+
|
|
273
|
+
`run_task` delegates to `freellama serve`, so it honors the server's `--cpu-upstream` and
|
|
274
|
+
`--cpu-model` configuration. Exact assigned models can execute on the CPU process while other
|
|
275
|
+
managed tasks execute on the primary GPU-capable process.
|
|
276
|
+
|
|
277
|
+
Set `executionPreference` on `run_task` to `auto` (default), `prefer_cpu`, or `prefer_gpu`. This is a
|
|
278
|
+
guarded hint: only exact operator-assigned CPU models are eligible, explicit model/session pins win,
|
|
279
|
+
and `preview: true` returns `execution.preference_satisfied`, placement, upstream, admission, and a
|
|
280
|
+
reason without generating. Automatic feedback normalizes work by tokens, waits for three successful
|
|
281
|
+
warm, physically verified samples per task on both backends, requires a 10% advantage, and never
|
|
282
|
+
steers the `quality` objective. `minPlacementEvidence:"observed"` fails closed unless resident
|
|
283
|
+
`/api/ps` evidence matches the configured processor; warm cold models once with `"configured"`.
|
|
284
|
+
`keepAlive:"0"` uses an observe-then-unload transaction: FreeLlama retains the runner long enough
|
|
285
|
+
to inspect `/api/ps`, accepts feedback only for verified placement, requests an explicit unload,
|
|
286
|
+
then reports the unload verification in `execution.lifecycle`.
|
|
287
|
+
|
|
288
|
+
`models {view: "resident"}` uses the managed catalog, so it includes resident models from both
|
|
289
|
+
Ollama processes and labels explicitly assigned CPU models instead of querying only the primary
|
|
290
|
+
server.
|
|
291
|
+
|
|
292
|
+
Before relying on that placement, query `/_freellama/v1/health` and require
|
|
293
|
+
`contracts.placement_observation:"ollama_api_ps_after_execution"` and
|
|
294
|
+
`contracts.placement_evidence_gate:"configured_or_observed"`. A missing contract means the running server
|
|
295
|
+
predates the dual-backend build even if the MCP package itself is current.
|
|
296
|
+
|
|
297
|
+
The direct Ollama tools do not infer that assignment. `ollama_manage`, `ollama_delete`, and the
|
|
298
|
+
no-serve model views target their explicit `ollamaEndpoint` or `FREELLAMA_OLLAMA_ENDPOINT`, which
|
|
299
|
+
defaults to the primary Ollama server. Point them at the CPU endpoint only when you intend to
|
|
300
|
+
inspect or modify that separate server. Read
|
|
301
|
+
[CPU and GPU model routing](docs/CPU_GPU_ROUTING.md) for the complete contract.
|
|
302
|
+
|
|
303
|
+
## Configuration
|
|
304
|
+
|
|
305
|
+
Every default is overridable through an environment variable — set them in the MCP client's
|
|
306
|
+
server-launch config (for example `.mcp.json`'s `env` block) or the launching shell.
|
|
307
|
+
|
|
308
|
+
| Variable | Default | Affects |
|
|
309
|
+
|---|---|---|
|
|
310
|
+
| `FREELLAMA_OLLAMA_ENDPOINT` | `http://127.0.0.1:11434` | `doctor` and all `ollama_*` tools' default Ollama endpoint |
|
|
311
|
+
| `FREELLAMA_SERVE_ENDPOINT` | `http://127.0.0.1:11435` | Default `endpoint` for serve-backed tools and `delegate_research` |
|
|
312
|
+
| `FREELLAMA_MCP_DEFAULT_MODEL` | `qwen3.8:27b-mlx` | `delegate_research`'s default `model` |
|
|
313
|
+
| `FREELLAMA_MCP_DEFAULT_ADAPTER` | `bash` | `delegate_research`'s adapter (`octocode` to switch) |
|
|
314
|
+
| `FREELLAMA_MCP_MAX_TURNS` | `8` | Max agent turns for `delegate_research` |
|
|
315
|
+
| `FREELLAMA_MCP_DELEGATE_TIMEOUT_SECONDS` | `180` | Whole-subprocess timeout for `delegate_research` |
|
|
316
|
+
| `FREELLAMA_MCP_PULL_TIMEOUT_SECONDS` | `1200` | Default `ollama_manage` `"pull"` timeout |
|
|
317
|
+
| `FREELLAMA_MCP_FETCH_TIMEOUT_SECONDS` | `30` | Timeout for other direct Ollama HTTP calls |
|
|
318
|
+
| `FREELLAMA_MCP_ALLOWED_ROOTS` | checkout: this repository; published: must be set | Platform-separated allowlist of directories `delegate_research` may read (`:` on macOS/Linux, `;` on Windows) |
|
|
319
|
+
| `FREELLAMA_MCP_MODEL_EVIDENCE` | checkout: `benchmark/evidence/model-evidence.json`; published: unset | Path to per-model research grades (see "Runtime evidence") |
|
|
320
|
+
| `FREELLAMA_EXTERNAL_COST_MODEL` | unset | External-model label in estimated avoided-cost telemetry; set all three cost variables or none |
|
|
321
|
+
| `FREELLAMA_EXTERNAL_COST_INPUT_USD_PER_M` | unset | External input USD per million tokens |
|
|
322
|
+
| `FREELLAMA_EXTERNAL_COST_OUTPUT_USD_PER_M` | unset | External output USD per million tokens |
|
|
323
|
+
| `FREELLAMA_CONTROL_TIMEOUT_SECONDS` | `30` | Decision-only serve calls; read by `../rust-core/src/napi.rs` |
|
|
324
|
+
| `FREELLAMA_TASK_TIMEOUT_SECONDS` | `900` | Generation calls; read by `../rust-core/src/napi.rs` |
|
|
325
|
+
| `FREELLAMA_AUTH_TOKEN_FILE` | unset | Bearer-token file used by the native client and research adapters for all serve routes |
|
|
326
|
+
| `FREELLAMA_AGENT_TOKEN_CALIBRATION_DIR` | platform data directory | Prompt-free, model-specific token-estimator calibration shared across adapter processes |
|
|
327
|
+
|
|
328
|
+
Research-adapter settings are deployment defaults. The optional `delegate_research.agent` object
|
|
329
|
+
exposes the same values per call using camelCase; explicit per-call fields win.
|
|
330
|
+
|
|
331
|
+
| Variable | Default | Affects |
|
|
332
|
+
|---|---:|---|
|
|
333
|
+
| `FREELLAMA_AGENT_NUM_CTX` | `8192` | Ollama context window |
|
|
334
|
+
| `FREELLAMA_AGENT_EXECUTION_PREFERENCE` | `auto` | Managed coding-agent backend hint |
|
|
335
|
+
| `FREELLAMA_AGENT_MIN_PLACEMENT_EVIDENCE` | `configured` | Set `observed` to fail closed on cold/mismatched placement |
|
|
336
|
+
| `FREELLAMA_AGENT_NUM_PREDICT` | `512` | Reserved output budget |
|
|
337
|
+
| `FREELLAMA_AGENT_TEMPERATURE` / `FREELLAMA_AGENT_SEED` | `0` / `42` | Repeatable decoding |
|
|
338
|
+
| `FREELLAMA_AGENT_THINK` / `FREELLAMA_AGENT_KEEP_ALIVE` | `false` / `5m` | Ollama reasoning and residency |
|
|
339
|
+
| `FREELLAMA_AGENT_REQUEST_TIMEOUT_SECONDS` | `600` | Each Ollama chat attempt |
|
|
340
|
+
| `FREELLAMA_AGENT_TOOL_TIMEOUT_SECONDS` | Bash `30`, Octocode `45` | Each local tool call |
|
|
341
|
+
| `FREELLAMA_AGENT_RETRY_ATTEMPTS` / `FREELLAMA_AGENT_RETRY_BACKOFF_SECONDS` | `2` / `5` | Conversation-level retry |
|
|
342
|
+
| `FREELLAMA_AGENT_MAX_PARSE_REPAIRS` / `FREELLAMA_AGENT_PARSE_REPAIR_ECHO_CHARS` | `2` / `500` | Invalid JSON correction limit and retained reply text |
|
|
343
|
+
| `FREELLAMA_AGENT_CHARS_PER_TOKEN` | `4` | First-call token estimate; later calibrated from Ollama |
|
|
344
|
+
| `FREELLAMA_AGENT_SAFETY_MARGIN_TOKENS` | `256` | Input headroom beyond `num_predict` |
|
|
345
|
+
| `FREELLAMA_AGENT_IMAGE_TOKEN_ESTIMATE` | `1024` | Bounded charge per image |
|
|
346
|
+
| `FREELLAMA_AGENT_KEEP_RECENT` | `2` | Recent observations preserved verbatim |
|
|
347
|
+
| `FREELLAMA_AGENT_COMPACT_PREVIEW_CHARS` | `180` | Old-observation breadcrumb size |
|
|
348
|
+
| `FREELLAMA_AGENT_COMPACT_RETAIN_RATIO` | `0.8` | Current payload retained per emergency pass |
|
|
349
|
+
| `FREELLAMA_AGENT_CLIP_HEAD_RATIO` | `0.667` | Head share when an emergency clip preserves both ends |
|
|
350
|
+
| `FREELLAMA_AGENT_OBSERVATION_PAGE_CHARS` | `3000` | Lossless observation page target |
|
|
351
|
+
| `FREELLAMA_AGENT_PINNED_OVERFLOW` | `error` | Preserve system/task bytes; `clip` is explicit opt-in |
|
|
352
|
+
|
|
353
|
+
Invalid values fail before an Ollama request. Each successful result returns
|
|
354
|
+
`contextManagement` with the resolved policy, calibration source/scale, estimated input budget,
|
|
355
|
+
and compaction count. Ollama has no stable preflight tokenizer endpoint, so “exact before the first
|
|
356
|
+
call” is not claimed. Model-specific calibration persists after successful calls, so later
|
|
357
|
+
processes start conservatively from prior `prompt_eval_count` evidence without sharing estimates
|
|
358
|
+
between model templates.
|
|
359
|
+
|
|
360
|
+
**Security:** `delegate_research` grants a local model read access to `workspacePath`. The path is
|
|
361
|
+
confined to `FREELLAMA_MCP_ALLOWED_ROOTS` (default: this repository in a checkout; unset in a published
|
|
362
|
+
install until you set it), resolved through symlinks so a link inside an allowed root can't escape
|
|
363
|
+
it. The default `bash` adapter also rejects home-directory paths, `..`, and absolute paths outside
|
|
364
|
+
that workspace. Production deployments should generate a permission-restricted token with
|
|
365
|
+
`freellama auth-token`, start `serve` with `--auth-token-file`, and set
|
|
366
|
+
`FREELLAMA_AUTH_TOKEN_FILE` for MCP. Authentication covers managed and raw passthrough routes; use
|
|
367
|
+
an external TLS and authorization layer for untrusted or multi-tenant networks.
|
|
368
|
+
|
|
369
|
+
### Runtime evidence
|
|
370
|
+
|
|
371
|
+
**No measurements are compiled in.** In a repository checkout, per-model research grades load from
|
|
372
|
+
`benchmark/evidence/model-evidence.json`. A published package does not include that repository
|
|
373
|
+
file, so its evidence table is empty unless you set `FREELLAMA_MCP_MODEL_EVIDENCE`. An unmeasured
|
|
374
|
+
model yields a `verify` verdict. Tool descriptions state the rules; measurement details live in
|
|
375
|
+
`skills/freellama/references/` and `.octocode/evals/`.
|
|
376
|
+
|
|
377
|
+
## Platform support
|
|
378
|
+
|
|
379
|
+
The native addon is named by target triple (`freellama.<platform>-<arch>[-<abi>].node`). The base
|
|
380
|
+
package has eight npm optional dependencies, one each for macOS arm64/x64, Linux arm64/x64 with
|
|
381
|
+
glibc or musl, and Windows arm64/x64 with MSVC. `native/index.js` tries the checkout artifact first,
|
|
382
|
+
then the host's optional package. A release is supported only when all eight artifact packages pass
|
|
383
|
+
the publish verifier; an installation made with `--omit=optional` cannot load the addon. `engines`
|
|
384
|
+
requires Node >= 20.
|
|
385
|
+
|
|
386
|
+
Machine discovery distinguishes total host memory (`memory_bytes`) from known unified memory
|
|
387
|
+
(`unified_memory_bytes`). Library-tag `fitsInMemory` is a conservative host-memory preflight and
|
|
388
|
+
includes `fitScope: "host_memory_budget_only"`; inspect `/api/ps` for actual accelerator placement.
|
|
389
|
+
|
|
390
|
+
Start the serve-backed tools' dependency from the repository root:
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
cargo run --release -- serve --recommendation-catalog recommendations.example.toml
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
See `skills/freellama/references/proxy-vs-serve.md` for the `proxy` vs `serve` distinction (only
|
|
397
|
+
`serve` has the `/_freellama/v1/*` routes these tools call).
|
|
398
|
+
|
|
399
|
+
## Publish
|
|
400
|
+
|
|
401
|
+
`packages/mcp/` is the portable JavaScript package. Its `package.json` lists the platform packages
|
|
402
|
+
as exact-version optional dependencies; it intentionally does not embed a `.node` binary. Publish
|
|
403
|
+
the eight `packages/native/*` packages first, then publish `@octocodeai/freellama` and `@octocodeai/freellama-mcp-server`
|
|
404
|
+
at the same version. `yarn release:verify:publish` refuses a release if any platform package has a
|
|
405
|
+
missing, empty, or unpacked executable/addon pair.
|
|
406
|
+
|
|
407
|
+
```bash
|
|
408
|
+
cd packages/mcp
|
|
409
|
+
npm pack --dry-run # confirm exactly what a publish would ship
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
Version 0.1.0 is not published to a registry. Treat `npm publish` as a real, irreversible public
|
|
413
|
+
action, and confirm with the repository owner first.
|
|
414
|
+
|
|
415
|
+
## Why native bindings
|
|
416
|
+
|
|
417
|
+
- **No reimplementation.** `run_task`, `route`/`preview`, and the installed-model list are HTTP
|
|
418
|
+
calls into a running `freellama serve`, matching `../cli/src/main.rs`. `doctor` talks to Ollama
|
|
419
|
+
and the host's portable machine-discovery layer directly. `ollama_manage` / `ollama_delete` hit Ollama's HTTP API. `delegate_research`
|
|
420
|
+
is a subprocess. Routing logic still lives in exactly one place — the Rust core.
|
|
421
|
+
- **One connection pool.** `../rust-core/src/napi.rs` holds a single `reqwest::Client` in a
|
|
422
|
+
`OnceLock` and clones the handle per request, matching the server side.
|
|
423
|
+
- **`unsafe_code` stays isolated.** The crate is `deny(unsafe_code)` except `napi.rs`, which
|
|
424
|
+
carries an explicit `#[allow(unsafe_code)]` for napi-derive's FFI glue.
|
|
425
|
+
- **The napi build is off by default** (`cargo build` never touches it); the addon is built with
|
|
426
|
+
`napi build --features napi` from the repo root.
|