@zokizuan/satori-mcp 4.6.0 → 4.9.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 CHANGED
@@ -157,7 +157,7 @@ No parameters.
157
157
  "mcpServers": {
158
158
  "satori": {
159
159
  "command": "npx",
160
- "args": ["-y", "@zokizuan/satori-mcp@4.4.1"],
160
+ "args": ["-y", "@zokizuan/satori-mcp@4.9.0"],
161
161
  "timeout": 180000,
162
162
  "env": {
163
163
  "EMBEDDING_PROVIDER": "VoyageAI",
@@ -178,11 +178,13 @@ No parameters.
178
178
  ```toml
179
179
  [mcp_servers.satori]
180
180
  command = "npx"
181
- args = ["-y", "@zokizuan/satori-mcp@4.4.1"]
181
+ args = ["-y", "@zokizuan/satori-mcp@4.9.0"]
182
182
  startup_timeout_ms = 180000
183
183
  env = { EMBEDDING_PROVIDER = "VoyageAI", EMBEDDING_MODEL = "voyage-4-large", EMBEDDING_OUTPUT_DIMENSION = "1024", VOYAGEAI_API_KEY = "your-api-key", VOYAGEAI_RERANKER_MODEL = "rerank-2.5", MILVUS_ADDRESS = "your-milvus-endpoint", MILVUS_TOKEN = "your-milvus-token" }
184
184
  ```
185
185
 
186
+ `MILVUS_TOKEN` is optional auth for endpoints that require it; local unauthenticated Milvus only needs `MILVUS_ADDRESS`.
187
+
186
188
  ### Local development (when working on this repo)
187
189
 
188
190
  ```json
@@ -228,10 +230,11 @@ Supported installer targets in Phase 1:
228
230
  Examples:
229
231
 
230
232
  ```bash
231
- npx -y @zokizuan/satori-cli@0.1.1 install --client codex
232
- npx -y @zokizuan/satori-cli@0.1.1 install --client claude
233
- npx -y @zokizuan/satori-cli@0.1.1 install --client all --dry-run
234
- npx -y @zokizuan/satori-cli@0.1.1 uninstall --client codex
233
+ npx -y @zokizuan/satori-cli@0.3.0 install --client codex
234
+ npx -y @zokizuan/satori-cli@0.3.0 install --client claude
235
+ npx -y @zokizuan/satori-cli@0.3.0 install --client all --dry-run
236
+ npx -y @zokizuan/satori-cli@0.3.0 uninstall --client codex
237
+ npx -y @zokizuan/satori-cli@0.3.0 doctor
235
238
  ```
236
239
 
237
240
  Install and uninstall run before MCP session startup, only touch Satori-managed config, and copy/remove these packaged skills:
@@ -286,6 +289,10 @@ When spawned by `satori-cli`, server process mode is `SATORI_RUN_MODE=cli`:
286
289
 
287
290
  `SATORI_CLI_STDOUT_GUARD=drop|redirect` controls accidental non-protocol stdout handling (`drop` default).
288
291
 
292
+ ### Startup vs Provider Setup
293
+
294
+ MCP startup does not require provider credentials, network access, or a live Milvus backend. The server should complete `initialize` and expose the six tools with an empty provider environment. Provider-backed calls (`manage_index create|reindex|sync|clear` and `search_codebase`) validate their required environment at call time and return `MISSING_PROVIDER_CONFIG` when setup is incomplete.
295
+
289
296
  ## Development
290
297
 
291
298
  ```bash
@@ -69,7 +69,7 @@ function buildCodexManagedBlock(packageSpecifier) {
69
69
  MANAGED_BLOCK_START,
70
70
  "[mcp_servers.satori]",
71
71
  'command = "npx"',
72
- `args = ["-y", "--package", "${packageSpecifier}", "satori"]`,
72
+ `args = ["-y", "${packageSpecifier}"]`,
73
73
  `startup_timeout_ms = ${MANAGED_TIMEOUT_MS}`,
74
74
  MANAGED_BLOCK_END,
75
75
  "",
@@ -153,10 +153,13 @@ function parseJsonObject(filePath) {
153
153
  function buildClaudeServerConfig(packageSpecifier) {
154
154
  return {
155
155
  command: "npx",
156
- args: ["-y", "--package", packageSpecifier, "satori"],
156
+ args: ["-y", packageSpecifier],
157
157
  timeout: MANAGED_TIMEOUT_MS,
158
158
  };
159
159
  }
160
+ function isManagedPackageSpecifier(value) {
161
+ return typeof value === "string" && /^@zokizuan\/satori-mcp@.+$/.test(value);
162
+ }
160
163
  function isManagedClaudeEntry(value) {
161
164
  if (!value || typeof value !== "object" || Array.isArray(value)) {
162
165
  return false;
@@ -168,14 +171,19 @@ function isManagedClaudeEntry(value) {
168
171
  if (entry.timeout !== MANAGED_TIMEOUT_MS) {
169
172
  return false;
170
173
  }
171
- if (!Array.isArray(entry.args) || entry.args.length !== 4) {
174
+ if (!Array.isArray(entry.args)) {
172
175
  return false;
173
176
  }
174
- return entry.args[0] === "-y"
175
- && entry.args[1] === "--package"
176
- && typeof entry.args[2] === "string"
177
- && /^@zokizuan\/satori-mcp@.+$/.test(entry.args[2])
178
- && entry.args[3] === "satori";
177
+ if (entry.args.length === 2) {
178
+ return entry.args[0] === "-y" && isManagedPackageSpecifier(entry.args[1]);
179
+ }
180
+ if (entry.args.length === 4) {
181
+ return entry.args[0] === "-y"
182
+ && entry.args[1] === "--package"
183
+ && isManagedPackageSpecifier(entry.args[2])
184
+ && entry.args[3] === "satori";
185
+ }
186
+ return false;
179
187
  }
180
188
  function prepareClaudeInstall(filePath, packageSpecifier) {
181
189
  const currentObject = parseJsonObject(filePath);
@@ -55,7 +55,7 @@ function assertPublishedVersion(packageName, version, ownerPackageName, ownerPac
55
55
  stdio: ["ignore", "pipe", "pipe"],
56
56
  });
57
57
  }
58
- catch (error) {
58
+ catch {
59
59
  if (relation === "self") {
60
60
  throw new CliError("E_USAGE", `Cannot install ${ownerPackageName}@${ownerPackageVersion} because that package version is not published on npm. Publish ${ownerPackageName}@${ownerPackageVersion} first or use a local dev server config instead.`, 2);
61
61
  }
package/dist/config.d.ts CHANGED
@@ -42,6 +42,10 @@ export interface CodebaseIndexManifest {
42
42
  indexedPaths: string[];
43
43
  updatedAt: string;
44
44
  }
45
+ export interface CodebaseClearTombstone {
46
+ clearedAt: string;
47
+ collectionName?: string;
48
+ }
45
49
  export interface CodebaseSnapshotV1 {
46
50
  indexedCodebases: string[];
47
51
  indexingCodebases: string[] | Record<string, number>;
@@ -94,6 +98,7 @@ export interface CodebaseSnapshotV2 {
94
98
  export interface CodebaseSnapshotV3 {
95
99
  formatVersion: 'v3';
96
100
  codebases: Record<string, CodebaseInfo>;
101
+ clearTombstones?: Record<string, CodebaseClearTombstone>;
97
102
  lastUpdated: string;
98
103
  }
99
104
  export type CodebaseSnapshot = CodebaseSnapshotV1 | CodebaseSnapshotV2 | CodebaseSnapshotV3;
package/dist/config.js CHANGED
@@ -119,8 +119,8 @@ export function createMcpConfig() {
119
119
  // Ollama configuration
120
120
  ollamaEncoderModel: envManager.get('OLLAMA_MODEL'),
121
121
  ollamaEndpoint: envManager.get('OLLAMA_HOST'),
122
- // Vector database configuration - address can be auto-resolved from token
123
- milvusEndpoint: envManager.get('MILVUS_ADDRESS'), // Optional, can be resolved from token
122
+ // Vector database configuration
123
+ milvusEndpoint: envManager.get('MILVUS_ADDRESS'),
124
124
  milvusApiToken: envManager.get('MILVUS_TOKEN'),
125
125
  // Reranker configuration
126
126
  rankerModel,
@@ -139,7 +139,7 @@ export function logConfigurationSummary(config) {
139
139
  console.log(`[MCP] Server: ${config.name} v${config.version}`);
140
140
  console.log(`[MCP] Embedding Provider: ${config.encoderProvider}`);
141
141
  console.log(`[MCP] Embedding Model: ${config.encoderModel}`);
142
- console.log(`[MCP] Milvus Address: ${config.milvusEndpoint || (config.milvusApiToken ? '[Auto-resolve from token]' : '[Not configured]')}`);
142
+ console.log(`[MCP] Milvus Address: ${config.milvusEndpoint || '[Not configured]'}`);
143
143
  console.log(`[MCP] Proactive Watcher: ${config.watchSyncEnabled ? `enabled (${config.watchDebounceMs || DEFAULT_WATCH_DEBOUNCE_MS}ms debounce)` : 'disabled'}`);
144
144
  // Log provider-specific configuration without exposing sensitive data
145
145
  switch (config.encoderProvider) {
@@ -169,7 +169,7 @@ export function showHelpMessage() {
169
169
  console.log(`
170
170
  Satori MCP Server
171
171
 
172
- Usage: npx -y @zokizuan/satori-mcp@4.4.1 [options]
172
+ Usage: npx -y @zokizuan/satori-mcp@4.9.0 [options]
173
173
 
174
174
  Options:
175
175
  --help, -h Show this help message
@@ -194,8 +194,8 @@ Environment Variables:
194
194
  OLLAMA_MODEL Ollama model name (alternative to EMBEDDING_MODEL for Ollama)
195
195
 
196
196
  Vector Database Configuration:
197
- MILVUS_ADDRESS Milvus address (optional, can be auto-resolved from token)
198
- MILVUS_TOKEN Milvus token (optional, used for authentication and address resolution)
197
+ MILVUS_ADDRESS Milvus address (required for index/search/clear tool calls)
198
+ MILVUS_TOKEN Milvus token (optional, used for authenticated endpoints)
199
199
 
200
200
  Read File Configuration:
201
201
  READ_FILE_MAX_LINES Max lines returned by read_file when no explicit range is provided (default: 1000)
@@ -206,16 +206,16 @@ Environment Variables:
206
206
 
207
207
  Examples:
208
208
  # Start MCP server with OpenAI and explicit Milvus address
209
- OPENAI_API_KEY=sk-xxx MILVUS_ADDRESS=localhost:19530 npx -y @zokizuan/satori-mcp@4.4.1
209
+ OPENAI_API_KEY=sk-xxx MILVUS_ADDRESS=localhost:19530 npx -y @zokizuan/satori-mcp@4.9.0
210
210
 
211
211
  # Start MCP server with VoyageAI and specific model
212
- EMBEDDING_PROVIDER=VoyageAI VOYAGEAI_API_KEY=pa-xxx EMBEDDING_MODEL=voyage-4-large MILVUS_TOKEN=your-token npx -y @zokizuan/satori-mcp@4.4.1
212
+ EMBEDDING_PROVIDER=VoyageAI VOYAGEAI_API_KEY=pa-xxx EMBEDDING_MODEL=voyage-4-large MILVUS_ADDRESS=https://your-zilliz-endpoint MILVUS_TOKEN=your-token npx -y @zokizuan/satori-mcp@4.9.0
213
213
 
214
214
  # Start MCP server with Gemini and specific model
215
- EMBEDDING_PROVIDER=Gemini GEMINI_API_KEY=xxx EMBEDDING_MODEL=gemini-embedding-001 MILVUS_TOKEN=your-token npx -y @zokizuan/satori-mcp@4.4.1
215
+ EMBEDDING_PROVIDER=Gemini GEMINI_API_KEY=xxx EMBEDDING_MODEL=gemini-embedding-001 MILVUS_ADDRESS=https://your-zilliz-endpoint MILVUS_TOKEN=your-token npx -y @zokizuan/satori-mcp@4.9.0
216
216
 
217
217
  # Start MCP server with Ollama and specific model
218
- EMBEDDING_PROVIDER=Ollama EMBEDDING_MODEL=nomic-embed-text MILVUS_TOKEN=your-token npx -y @zokizuan/satori-mcp@4.4.1
218
+ EMBEDDING_PROVIDER=Ollama EMBEDDING_MODEL=nomic-embed-text MILVUS_ADDRESS=localhost:19530 npx -y @zokizuan/satori-mcp@4.9.0
219
219
  `);
220
220
  }
221
221
  //# sourceMappingURL=config.js.map
@@ -15,7 +15,7 @@ export class CapabilityResolver {
15
15
  else {
16
16
  performanceProfile = 'standard';
17
17
  }
18
- const hasVectorStore = Boolean(this.config.milvusEndpoint || this.config.milvusApiToken);
18
+ const hasVectorStore = Boolean(this.config.milvusEndpoint);
19
19
  const hasReranker = Boolean(this.config.voyageKey);
20
20
  const defaultSearchLimit = performanceProfile === 'fast' ? 50 :
21
21
  performanceProfile === 'standard' ? 25 :
@@ -0,0 +1,24 @@
1
+ import type { IndexFingerprint } from "../config.js";
2
+ export type CompletionProofOutcome = "valid" | "stale_local" | "fingerprint_mismatch" | "probe_failed";
3
+ export type CompletionProofReason = "missing_marker_doc" | "invalid_marker_kind" | "path_mismatch" | "invalid_payload" | "fingerprint_mismatch" | "probe_failed";
4
+ export type CompletionProofValidationResult = {
5
+ outcome: CompletionProofOutcome;
6
+ reason?: CompletionProofReason;
7
+ marker?: {
8
+ kind?: string;
9
+ codebasePath?: string;
10
+ fingerprint?: unknown;
11
+ indexedFiles?: number;
12
+ totalChunks?: number;
13
+ completedAt?: string;
14
+ runId?: string;
15
+ };
16
+ };
17
+ export type CompletionMarkerReader = (codebasePath: string) => Promise<unknown>;
18
+ export declare function validateCompletionProof(args: {
19
+ codebasePath: string;
20
+ runtimeFingerprint?: IndexFingerprint;
21
+ getIndexCompletionMarker?: CompletionMarkerReader;
22
+ onProbeError?: (error: unknown) => void;
23
+ }): Promise<CompletionProofValidationResult>;
24
+ //# sourceMappingURL=completion-proof.d.ts.map
@@ -0,0 +1,106 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ function trimTrailingSeparators(inputPath) {
4
+ const normalized = path.normalize(inputPath);
5
+ const parsedRoot = path.parse(normalized).root;
6
+ if (normalized === parsedRoot) {
7
+ return normalized;
8
+ }
9
+ return normalized.replace(/[\\/]+$/, "");
10
+ }
11
+ function canonicalizeCodebasePath(codebasePath) {
12
+ const resolved = path.resolve(codebasePath);
13
+ try {
14
+ const realPath = typeof fs.realpathSync.native === "function"
15
+ ? fs.realpathSync.native(resolved)
16
+ : fs.realpathSync(resolved);
17
+ return trimTrailingSeparators(realPath);
18
+ }
19
+ catch {
20
+ return trimTrailingSeparators(resolved);
21
+ }
22
+ }
23
+ function markerMatchesRuntimeFingerprint(marker, runtimeFingerprint) {
24
+ if (!runtimeFingerprint || typeof runtimeFingerprint !== "object") {
25
+ return true;
26
+ }
27
+ const fingerprint = marker?.fingerprint;
28
+ if (!fingerprint || typeof fingerprint !== "object") {
29
+ return false;
30
+ }
31
+ const record = fingerprint;
32
+ return record.embeddingProvider === runtimeFingerprint.embeddingProvider
33
+ && record.embeddingModel === runtimeFingerprint.embeddingModel
34
+ && Number(record.embeddingDimension) === Number(runtimeFingerprint.embeddingDimension)
35
+ && record.vectorStoreProvider === runtimeFingerprint.vectorStoreProvider
36
+ && record.schemaVersion === runtimeFingerprint.schemaVersion;
37
+ }
38
+ function isNonNegativeInteger(value) {
39
+ return typeof value === "number"
40
+ && Number.isInteger(value)
41
+ && value >= 0;
42
+ }
43
+ function validateMarkerShape(expectedCodebasePath, marker) {
44
+ if (!marker || typeof marker !== "object") {
45
+ return { ok: false, reason: "invalid_payload" };
46
+ }
47
+ const record = marker;
48
+ if (record.kind !== "satori_index_completion_v1") {
49
+ return { ok: false, reason: "invalid_marker_kind" };
50
+ }
51
+ if (typeof record.codebasePath !== "string" || record.codebasePath.trim().length === 0) {
52
+ return { ok: false, reason: "invalid_payload" };
53
+ }
54
+ if (!record.fingerprint || typeof record.fingerprint !== "object") {
55
+ return { ok: false, reason: "invalid_payload" };
56
+ }
57
+ if (!isNonNegativeInteger(record.indexedFiles) || !isNonNegativeInteger(record.totalChunks)) {
58
+ return { ok: false, reason: "invalid_payload" };
59
+ }
60
+ if (typeof record.completedAt !== "string" || Number.isNaN(Date.parse(record.completedAt))) {
61
+ return { ok: false, reason: "invalid_payload" };
62
+ }
63
+ const expectedCanonical = canonicalizeCodebasePath(expectedCodebasePath);
64
+ const markerCanonical = canonicalizeCodebasePath(record.codebasePath);
65
+ if (expectedCanonical !== markerCanonical) {
66
+ return { ok: false, reason: "path_mismatch" };
67
+ }
68
+ return { ok: true };
69
+ }
70
+ export async function validateCompletionProof(args) {
71
+ const { codebasePath, runtimeFingerprint, getIndexCompletionMarker, onProbeError } = args;
72
+ if (typeof getIndexCompletionMarker !== "function") {
73
+ return { outcome: "probe_failed", reason: "probe_failed" };
74
+ }
75
+ let marker;
76
+ try {
77
+ marker = await getIndexCompletionMarker(codebasePath);
78
+ }
79
+ catch (error) {
80
+ onProbeError?.(error);
81
+ return { outcome: "probe_failed", reason: "probe_failed" };
82
+ }
83
+ if (!marker) {
84
+ return { outcome: "stale_local", reason: "missing_marker_doc" };
85
+ }
86
+ const markerShape = validateMarkerShape(codebasePath, marker);
87
+ if (!markerShape.ok) {
88
+ return {
89
+ outcome: "stale_local",
90
+ reason: markerShape.reason,
91
+ marker: marker
92
+ };
93
+ }
94
+ if (!markerMatchesRuntimeFingerprint(marker, runtimeFingerprint)) {
95
+ return {
96
+ outcome: "fingerprint_mismatch",
97
+ reason: "fingerprint_mismatch",
98
+ marker: marker
99
+ };
100
+ }
101
+ return {
102
+ outcome: "valid",
103
+ marker: marker
104
+ };
105
+ }
106
+ //# sourceMappingURL=completion-proof.js.map
@@ -33,10 +33,6 @@ export declare class ToolHandlers {
33
33
  private isIndexingStateStale;
34
34
  private recoverStaleIndexingStateIfNeeded;
35
35
  private buildManageActionBlockedMessage;
36
- private markerMatchesRuntimeFingerprint;
37
- private trimTrailingSeparators;
38
- private canonicalizeCodebasePath;
39
- private validateMarkerShape;
40
36
  private buildStaleLocalHint;
41
37
  private buildStaleLocalMessage;
42
38
  private withProofDebugHint;
@@ -72,6 +68,8 @@ export declare class ToolHandlers {
72
68
  private classifyNoiseCategory;
73
69
  private roundRatio;
74
70
  private normalizeRelativePathForIgnoreCheck;
71
+ private trimTrailingSeparators;
72
+ private canonicalizeCodebasePath;
75
73
  private loadRootGitignoreMatcher;
76
74
  private patternMatchesAnyPath;
77
75
  private filterNoiseHintPatternsByRootGitignore;