@zokizuan/satori-mcp 4.11.0 → 4.11.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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 ham-zax
3
+ Copyright (c) 2026 Hamza (@ham-zax)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -7,8 +7,8 @@ Read-only MCP server for Satori. It gives coding agents six deterministic tools
7
7
  Use the CLI installer for normal setup:
8
8
 
9
9
  ```bash
10
- npx -y @zokizuan/satori-cli@0.4.0 install --client all
11
- npx -y @zokizuan/satori-cli@0.4.0 doctor
10
+ npx -y @zokizuan/satori-cli@0.4.1 install --client all
11
+ npx -y @zokizuan/satori-cli@0.4.1 doctor
12
12
  ```
13
13
 
14
14
  The CLI installer supports `codex`, `claude`, `opencode`, and `all`. It creates the runtime cache, writes the stable launcher, and writes client config for you. Avoid using `npx` as the resident MCP server command; first-run package resolution can exceed normal MCP startup timeouts.
@@ -16,9 +16,11 @@ The CLI installer supports `codex`, `claude`, `opencode`, and `all`. It creates
16
16
  Advanced direct execution is available through the package bin:
17
17
 
18
18
  ```bash
19
- npx -y @zokizuan/satori-mcp@4.11.0 --help
19
+ npx -y @zokizuan/satori-mcp@4.11.1 --help
20
20
  ```
21
21
 
22
+ Use direct package execution for inspection, smoke tests, or unsupported harnesses. For supported clients, prefer `satori-cli install` so startup does not depend on package-manager resolution.
23
+
22
24
  ## Agent Workflow
23
25
 
24
26
  ```text
@@ -42,6 +44,27 @@ Important defaults:
42
44
 
43
45
  Configure an embedding provider and Milvus-compatible backend before indexing. Supported embedding providers are OpenAI, VoyageAI, Gemini, and Ollama. Changing provider, model, dimension, vector store, or schema requires a reindex because those values are part of the index fingerprint.
44
46
 
47
+ MCP startup, `tools/list`, and installer operations are lazy with respect to provider credentials. Missing provider values become `MISSING_PROVIDER_CONFIG` only when a provider-backed tool call needs them.
48
+
49
+ Installer-managed client config starts the resident launcher. Runtime provider settings come from the MCP client's environment and are exposed in native client config:
50
+
51
+ - Codex writes active `env_vars` forwarding plus an optional commented `[mcp_servers.satori.env]` template in `~/.codex/config.toml`.
52
+ - Claude Code writes `mcpServers.satori.env` in `~/.claude.json` with `${VAR:-}` pass-through values.
53
+ - OpenCode writes `mcp.satori.environment` in `~/.config/opencode/opencode.json` with `{env:VAR}` pass-through values.
54
+
55
+ Users who want literal values in a client config can replace the generated pass-through value for that client. In Codex, uncomment or add this table outside the installer-managed launcher block so reinstalls keep edits:
56
+
57
+ ```toml
58
+ [mcp_servers.satori.env]
59
+ EMBEDDING_PROVIDER = "VoyageAI"
60
+ EMBEDDING_MODEL = "voyage-4-large"
61
+ EMBEDDING_OUTPUT_DIMENSION = "1024"
62
+ VOYAGEAI_API_KEY = "pa-..."
63
+ VOYAGEAI_RERANKER_MODEL = "rerank-2.5"
64
+ MILVUS_ADDRESS = "https://your-zilliz-endpoint"
65
+ MILVUS_TOKEN = "your-zilliz-token"
66
+ ```
67
+
45
68
  Cloud-quality setup:
46
69
 
47
70
  ```bash
@@ -7,12 +7,47 @@ import { applyEdits, modify, parse as parseJsonc } from "jsonc-parser";
7
7
  import { CliError } from "./errors.js";
8
8
  const MANAGED_BLOCK_START = "# >>> satori-cli managed satori start >>>";
9
9
  const MANAGED_BLOCK_END = "# <<< satori-cli managed satori end <<<";
10
+ const CODEX_ENV_TEMPLATE_START = "# >>> satori-cli optional satori env template >>>";
11
+ const CODEX_ENV_TEMPLATE_END = "# <<< satori-cli optional satori env template <<<";
10
12
  const INSTRUCTIONS_BLOCK_START = "<!-- satori-mcp:start -->";
11
13
  const INSTRUCTIONS_BLOCK_END = "<!-- satori-mcp:end -->";
12
14
  const OWNED_SKILL_DIRS = ["satori"];
13
15
  const MANAGED_RUNTIME_DIR = "mcp-runtime";
14
16
  const MANAGED_BIN_DIR = "bin";
15
17
  const MANAGED_LAUNCHER_FILE = "satori-mcp.js";
18
+ const SATORI_RUNTIME_ENV_VARS = [
19
+ "EMBEDDING_PROVIDER",
20
+ "EMBEDDING_MODEL",
21
+ "EMBEDDING_OUTPUT_DIMENSION",
22
+ "OPENAI_API_KEY",
23
+ "OPENAI_BASE_URL",
24
+ "VOYAGEAI_API_KEY",
25
+ "VOYAGEAI_RERANKER_MODEL",
26
+ "GEMINI_API_KEY",
27
+ "GEMINI_BASE_URL",
28
+ "OLLAMA_HOST",
29
+ "OLLAMA_MODEL",
30
+ "MILVUS_ADDRESS",
31
+ "MILVUS_TOKEN",
32
+ "READ_FILE_MAX_LINES",
33
+ "MCP_ENABLE_WATCHER",
34
+ "MCP_WATCH_DEBOUNCE_MS",
35
+ ];
36
+ const CODEX_ENV_TEMPLATE_LINES = [
37
+ CODEX_ENV_TEMPLATE_START,
38
+ "# Optional direct Codex env values. Uncomment/fill these if you prefer",
39
+ "# ~/.codex/config.toml to store Satori runtime settings directly.",
40
+ "# This template is outside the launcher block so reinstall keeps edits.",
41
+ "# [mcp_servers.satori.env]",
42
+ "# EMBEDDING_PROVIDER = \"VoyageAI\"",
43
+ "# EMBEDDING_MODEL = \"voyage-4-large\"",
44
+ "# EMBEDDING_OUTPUT_DIMENSION = \"1024\"",
45
+ "# VOYAGEAI_API_KEY = \"pa-...\"",
46
+ "# VOYAGEAI_RERANKER_MODEL = \"rerank-2.5\"",
47
+ "# MILVUS_ADDRESS = \"https://your-zilliz-endpoint\"",
48
+ "# MILVUS_TOKEN = \"your-zilliz-token\"",
49
+ CODEX_ENV_TEMPLATE_END,
50
+ ];
16
51
  const OPENCODE_INSTRUCTIONS = `# Satori MCP
17
52
 
18
53
  This project uses Satori MCP for semantic code search, deterministic navigation, and index lifecycle management.
@@ -60,7 +95,7 @@ function resolveClientTargets(homeDir) {
60
95
  },
61
96
  {
62
97
  client: "claude",
63
- configPath: path.join(homeDir, ".claude", "settings.json"),
98
+ configPath: path.join(homeDir, ".claude.json"),
64
99
  companion: {
65
100
  kind: "skills",
66
101
  path: path.join(homeDir, ".claude", "skills"),
@@ -107,6 +142,21 @@ function toTomlString(value) {
107
142
  function buildTomlArray(values) {
108
143
  return `[${values.map(toTomlString).join(", ")}]`;
109
144
  }
145
+ function runtimeEnvMap(valueForName) {
146
+ return Object.fromEntries(SATORI_RUNTIME_ENV_VARS.map((name) => [name, valueForName(name)]));
147
+ }
148
+ function objectValue(value) {
149
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
150
+ return undefined;
151
+ }
152
+ return value;
153
+ }
154
+ function mergeRuntimeEnv(existing, defaults) {
155
+ return {
156
+ ...defaults,
157
+ ...(objectValue(existing) ?? {}),
158
+ };
159
+ }
110
160
  function packageNameFromSpecifier(packageSpecifier) {
111
161
  if (packageSpecifier.startsWith("@")) {
112
162
  const versionMarker = packageSpecifier.indexOf("@", 1);
@@ -262,10 +312,25 @@ function buildCodexManagedBlock(runtimeCommand) {
262
312
  "[mcp_servers.satori]",
263
313
  `command = ${toTomlString(runtimeCommand.command)}`,
264
314
  `args = ${buildTomlArray(runtimeCommand.args)}`,
315
+ "# Satori reads provider/vector settings from environment at MCP startup.",
316
+ "# env_vars forwards these names from Codex's parent environment when set.",
317
+ `env_vars = ${buildTomlArray([...SATORI_RUNTIME_ENV_VARS])}`,
265
318
  MANAGED_BLOCK_END,
266
319
  "",
267
320
  ].join("\n");
268
321
  }
322
+ function buildCodexEnvTemplateBlock() {
323
+ return `${CODEX_ENV_TEMPLATE_LINES.join("\n")}\n`;
324
+ }
325
+ function codexHasSatoriEnvTable(content) {
326
+ return /^\s*\[mcp_servers\.satori\.env\]\s*$/m.test(content);
327
+ }
328
+ function ensureCodexEnvTemplate(content) {
329
+ if (content.includes(CODEX_ENV_TEMPLATE_START) || codexHasSatoriEnvTable(content)) {
330
+ return content;
331
+ }
332
+ return `${normalizeTrailingNewline(content)}\n${buildCodexEnvTemplateBlock()}`;
333
+ }
269
334
  function codexHasUnmanagedSatoriSection(content) {
270
335
  if (!content.includes("[mcp_servers.satori]")) {
271
336
  return false;
@@ -288,6 +353,7 @@ function prepareCodexInstall(filePath, runtimeCommand) {
288
353
  else {
289
354
  next = `${normalizeTrailingNewline(current)}\n${managedBlock}`;
290
355
  }
356
+ next = ensureCodexEnvTemplate(next);
291
357
  return {
292
358
  changed: next !== current,
293
359
  apply: () => {
@@ -341,10 +407,12 @@ function parseJsonObject(filePath) {
341
407
  }
342
408
  return parsed;
343
409
  }
344
- function buildClaudeServerConfig(runtimeCommand) {
410
+ function buildClaudeServerConfig(runtimeCommand, existing) {
345
411
  return {
412
+ type: "stdio",
346
413
  command: runtimeCommand.command,
347
414
  args: runtimeCommand.args,
415
+ env: mergeRuntimeEnv(existing?.env, runtimeEnvMap((name) => `\${${name}:-}`)),
348
416
  };
349
417
  }
350
418
  function isManagedLauncherPath(value) {
@@ -370,7 +438,8 @@ function isManagedClaudeEntry(value) {
370
438
  function prepareClaudeInstall(filePath, runtimeCommand) {
371
439
  const currentObject = parseJsonObject(filePath);
372
440
  const currentSerialized = JSON.stringify(currentObject);
373
- const desiredServer = buildClaudeServerConfig(runtimeCommand);
441
+ const existingSatori = objectValue(currentObject.mcpServers?.satori);
442
+ const desiredServer = buildClaudeServerConfig(runtimeCommand, existingSatori);
374
443
  const mcpServersValue = currentObject.mcpServers;
375
444
  let mcpServers;
376
445
  if (mcpServersValue === undefined) {
@@ -382,8 +451,7 @@ function prepareClaudeInstall(filePath, runtimeCommand) {
382
451
  else {
383
452
  throw new CliError("E_USAGE", `Expected mcpServers to be an object in ${filePath}.`, 2);
384
453
  }
385
- const existingSatori = mcpServers.satori;
386
- if (existingSatori !== undefined && !isManagedClaudeEntry(existingSatori)) {
454
+ if (mcpServers.satori !== undefined && !isManagedClaudeEntry(mcpServers.satori)) {
387
455
  throw new CliError("E_USAGE", `Refusing to overwrite unmanaged Satori config in ${filePath}. Remove mcpServers.satori manually or align it to the managed Satori form first.`, 2);
388
456
  }
389
457
  mcpServers.satori = {
@@ -443,11 +511,12 @@ function parseJsoncObject(filePath, content) {
443
511
  }
444
512
  return parsed;
445
513
  }
446
- function buildOpenCodeServerConfig(runtimeCommand) {
514
+ function buildOpenCodeServerConfig(runtimeCommand, existing) {
447
515
  return {
448
516
  enabled: true,
449
517
  type: "local",
450
518
  command: [runtimeCommand.command, ...runtimeCommand.args],
519
+ environment: mergeRuntimeEnv(existing?.environment, runtimeEnvMap((name) => `{env:${name}}`)),
451
520
  };
452
521
  }
453
522
  function isManagedOpenCodeEntry(value) {
@@ -492,7 +561,7 @@ function prepareOpenCodeInstall(filePath, runtimeCommand) {
492
561
  if (existingSatori !== undefined && !isManagedOpenCodeEntry(existingSatori)) {
493
562
  throw new CliError("E_USAGE", `Refusing to overwrite unmanaged Satori config in ${filePath}. Remove mcp.satori manually or align it to the managed Satori form first.`, 2);
494
563
  }
495
- return mutateJsonc(filePath, current, ["mcp", "satori"], buildOpenCodeServerConfig(runtimeCommand));
564
+ return mutateJsonc(filePath, current, ["mcp", "satori"], buildOpenCodeServerConfig(runtimeCommand, objectValue(existingSatori)));
496
565
  }
497
566
  function prepareOpenCodeUninstall(filePath) {
498
567
  const current = readTextIfExists(filePath);
package/dist/config.js CHANGED
@@ -209,7 +209,7 @@ Environment Variables:
209
209
 
210
210
  Examples:
211
211
  # Install resident MCP config without package-manager startup on every client launch
212
- npx -y @zokizuan/satori-cli@0.4.0 install --client all
212
+ npx -y @zokizuan/satori-cli@0.4.1 install --client all
213
213
 
214
214
  # Start MCP server with OpenAI and explicit Milvus address
215
215
  OPENAI_API_KEY=sk-xxx MILVUS_ADDRESS=localhost:19530 satori
@@ -3541,6 +3541,7 @@ To force rebuild from scratch: call manage_index with {"action":"create","path":
3541
3541
  rerankerFailurePhase = 'parse_results';
3542
3542
  throw new Error('reranker_parse_failed');
3543
3543
  }
3544
+ let rerankerUpdatedCandidates = 0;
3544
3545
  for (let idx = 0; idx < rerankSlice.length; idx++) {
3545
3546
  const rank = rerankRanks.get(idx);
3546
3547
  if (!rank) {
@@ -3549,9 +3550,10 @@ To force rebuild from scratch: call manage_index with {"action":"create","path":
3549
3550
  const rerankRrf = 1 / (SEARCH_RERANK_RRF_K + rank);
3550
3551
  rerankSlice[idx].fusionScore += SEARCH_RERANK_WEIGHT * rerankRrf;
3551
3552
  rerankSlice[idx].finalScore = (rerankSlice[idx].fusionScore + rerankSlice[idx].lexicalScore) * rerankSlice[idx].pathMultiplier * rerankSlice[idx].changedFilesMultiplier;
3553
+ rerankerUpdatedCandidates++;
3552
3554
  }
3553
3555
  exactMatchPinningApplied = this.sortSearchCandidates(scored, rerankDecision.exactMatchPinningEnabled, parsedOperators.must.length > 0) || exactMatchPinningApplied;
3554
- rerankerApplied = true;
3556
+ rerankerApplied = rerankerUpdatedCandidates > 0;
3555
3557
  }
3556
3558
  catch {
3557
3559
  if (!rerankerFailurePhase) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zokizuan/satori-mcp",
3
- "version": "4.11.0",
3
+ "version": "4.11.1",
4
4
  "description": "MCP server for Satori with agent-safe semantic search and indexing",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -15,7 +15,7 @@
15
15
  "jsonc-parser": "^3.3.1",
16
16
  "zod": "^3.25.55",
17
17
  "zod-to-json-schema": "^3.25.1",
18
- "@zokizuan/satori-core": "1.6.0"
18
+ "@zokizuan/satori-core": "1.6.1"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@types/node": "^20.0.0",