@zokizuan/satori-mcp 4.4.0 → 4.4.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/README.md +29 -5
- package/dist/cli/client.js +3 -1
- package/dist/cli/index.d.ts +15 -0
- package/dist/cli/index.js +5 -1
- package/dist/cli/install.js +7 -5
- package/dist/cli/package-installability.d.ts +14 -0
- package/dist/cli/package-installability.js +124 -0
- package/dist/config.js +5 -5
- package/package.json +7 -7
- package/assets/skills/satori-indexing/SKILL.md +0 -36
- package/assets/skills/satori-navigation/SKILL.md +0 -36
- package/assets/skills/satori-search/SKILL.md +0 -36
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ MCP server for Satori — agent-safe semantic code search and indexing.
|
|
|
17
17
|
- Zod-first tool schemas converted to MCP JSON Schema for `ListTools`
|
|
18
18
|
- Auto-generated tool docs from live tool schemas
|
|
19
19
|
- `read_file` line-range retrieval with default large-file truncation guard and optional `mode="annotated"` metadata envelope
|
|
20
|
-
- Optional proactive sync watcher mode (debounced filesystem events)
|
|
20
|
+
- Optional proactive sync watcher mode (debounced filesystem events for explicitly touched roots in the current session)
|
|
21
21
|
- Index-time AST scope breadcrumbs (TS/JS/Python) rendered in search output as `🧬 Scope`
|
|
22
22
|
- Fingerprint schema `dense_v3`/`hybrid_v3` with hard gate for all pre-v3 indexes
|
|
23
23
|
|
|
@@ -46,6 +46,7 @@ Tool surface is hard-broken to 6 tools. This keeps routing explicit while exposi
|
|
|
46
46
|
|
|
47
47
|
- Enabled by default. Set `MCP_ENABLE_WATCHER=false` to disable
|
|
48
48
|
- Debounce window via `MCP_WATCH_DEBOUNCE_MS` (default `5000`)
|
|
49
|
+
- Watchers are session-scoped: startup does not watch every indexed codebase, only roots touched by successful index/search/navigation/read flows in the current session
|
|
49
50
|
- Watch events reuse the same incremental sync pipeline (`reindexByChange`)
|
|
50
51
|
- Ignore control files (`.satoriignore`, root `.gitignore`) trigger no-reindex reconciliation:
|
|
51
52
|
- delete indexed paths now ignored by active rules
|
|
@@ -156,7 +157,7 @@ No parameters.
|
|
|
156
157
|
"mcpServers": {
|
|
157
158
|
"satori": {
|
|
158
159
|
"command": "npx",
|
|
159
|
-
"args": ["-y", "@zokizuan/satori-mcp@
|
|
160
|
+
"args": ["-y", "@zokizuan/satori-mcp@4.4.1"],
|
|
160
161
|
"timeout": 180000,
|
|
161
162
|
"env": {
|
|
162
163
|
"EMBEDDING_PROVIDER": "VoyageAI",
|
|
@@ -177,7 +178,7 @@ No parameters.
|
|
|
177
178
|
```toml
|
|
178
179
|
[mcp_servers.satori]
|
|
179
180
|
command = "npx"
|
|
180
|
-
args = ["-y", "@zokizuan/satori-mcp@
|
|
181
|
+
args = ["-y", "@zokizuan/satori-mcp@4.4.1"]
|
|
181
182
|
startup_timeout_ms = 180000
|
|
182
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" }
|
|
183
184
|
```
|
|
@@ -213,9 +214,30 @@ Never commit real API keys/tokens into repo config files.
|
|
|
213
214
|
pnpm --filter @zokizuan/satori-mcp start
|
|
214
215
|
```
|
|
215
216
|
|
|
216
|
-
## Shell CLI (
|
|
217
|
+
## Shell CLI (`@zokizuan/satori-cli`)
|
|
217
218
|
|
|
218
|
-
|
|
219
|
+
The shell-first installer/client now lives in a separate package: `@zokizuan/satori-cli`.
|
|
220
|
+
|
|
221
|
+
### Install / Uninstall
|
|
222
|
+
|
|
223
|
+
Supported installer targets in Phase 1:
|
|
224
|
+
- `codex`
|
|
225
|
+
- `claude`
|
|
226
|
+
- `all`
|
|
227
|
+
|
|
228
|
+
Examples:
|
|
229
|
+
|
|
230
|
+
```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
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Install and uninstall run before MCP session startup, only touch Satori-managed config, and copy/remove these packaged skills:
|
|
238
|
+
- `satori-search`
|
|
239
|
+
- `satori-navigation`
|
|
240
|
+
- `satori-indexing`
|
|
219
241
|
|
|
220
242
|
### Commands
|
|
221
243
|
|
|
@@ -271,6 +293,8 @@ pnpm --filter @zokizuan/satori-mcp build
|
|
|
271
293
|
pnpm --filter @zokizuan/satori-mcp typecheck
|
|
272
294
|
pnpm --filter @zokizuan/satori-mcp test
|
|
273
295
|
pnpm --filter @zokizuan/satori-mcp docs:check
|
|
296
|
+
pnpm --filter @zokizuan/satori-cli build
|
|
297
|
+
pnpm --filter @zokizuan/satori-cli test
|
|
274
298
|
```
|
|
275
299
|
|
|
276
300
|
`build` automatically runs docs generation from tool schemas.
|
package/dist/cli/client.js
CHANGED
|
@@ -39,6 +39,7 @@ export class CliMcpSession {
|
|
|
39
39
|
return createTimeout(this.client.callTool({ name, arguments: args }), this.callTimeoutMs, "E_CALL_TIMEOUT", `Timed out after ${this.callTimeoutMs}ms while calling tools/call for '${name}'.`);
|
|
40
40
|
}
|
|
41
41
|
async close() {
|
|
42
|
+
const stderr = this.transport.stderr;
|
|
42
43
|
try {
|
|
43
44
|
await this.client.close();
|
|
44
45
|
}
|
|
@@ -51,6 +52,7 @@ export class CliMcpSession {
|
|
|
51
52
|
catch {
|
|
52
53
|
// Best-effort close.
|
|
53
54
|
}
|
|
55
|
+
stderr?.removeAllListeners("data");
|
|
54
56
|
}
|
|
55
57
|
logProtocolFailure(error) {
|
|
56
58
|
if (error instanceof CliError) {
|
|
@@ -79,7 +81,7 @@ export async function connectCliMcpSession(options) {
|
|
|
79
81
|
});
|
|
80
82
|
const client = new Client({
|
|
81
83
|
name: "satori-cli",
|
|
82
|
-
version: "1.1.
|
|
84
|
+
version: "1.1.1",
|
|
83
85
|
});
|
|
84
86
|
const session = new CliMcpSession(client, transport, options.callTimeoutMs, options.writeStderr);
|
|
85
87
|
session.wireStderr();
|
package/dist/cli/index.d.ts
CHANGED
|
@@ -10,6 +10,21 @@ interface RunCliOptions {
|
|
|
10
10
|
startupTimeoutMs?: number;
|
|
11
11
|
callTimeoutMs?: number;
|
|
12
12
|
cwd?: string;
|
|
13
|
+
installabilityVerifier?: () => string | Promise<string>;
|
|
14
|
+
connectSession?: (options: {
|
|
15
|
+
command: string;
|
|
16
|
+
args: string[];
|
|
17
|
+
env: Record<string, string | undefined>;
|
|
18
|
+
cwd?: string;
|
|
19
|
+
startupTimeoutMs: number;
|
|
20
|
+
callTimeoutMs: number;
|
|
21
|
+
writeStderr: (text: string) => void;
|
|
22
|
+
}) => Promise<CliSession>;
|
|
23
|
+
}
|
|
24
|
+
interface CliSession {
|
|
25
|
+
listTools(): Promise<any>;
|
|
26
|
+
callTool(name: string, args: Record<string, unknown>): Promise<any>;
|
|
27
|
+
close(): Promise<void>;
|
|
13
28
|
}
|
|
14
29
|
export declare function runCli(argv: string[], options?: RunCliOptions): Promise<number>;
|
|
15
30
|
export declare function isExecutedDirectlyForPaths(moduleUrl: string, entryPath: string | undefined): boolean;
|
package/dist/cli/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import { connectCliMcpSession } from "./client.js";
|
|
|
7
7
|
import { asCliError, CliError } from "./errors.js";
|
|
8
8
|
import { emitError, emitJson, inferManageStatusState, parseStructuredEnvelope } from "./format.js";
|
|
9
9
|
import { executeInstallCommand } from "./install.js";
|
|
10
|
+
import { verifyManagedPackageInstallability } from "./package-installability.js";
|
|
10
11
|
import { resolveServerEntryPath } from "./resolve-server-entry.js";
|
|
11
12
|
const MANAGE_INDEX_MIN_POLL_TIMEOUT_MS = 10 * 60 * 1000;
|
|
12
13
|
function firstText(result) {
|
|
@@ -195,6 +196,9 @@ export async function runCli(argv, options = {}) {
|
|
|
195
196
|
return 0;
|
|
196
197
|
}
|
|
197
198
|
if (parsed.command.kind === "install" || parsed.command.kind === "uninstall") {
|
|
199
|
+
if (parsed.command.kind === "install") {
|
|
200
|
+
await (options.installabilityVerifier || verifyManagedPackageInstallability)();
|
|
201
|
+
}
|
|
198
202
|
const result = executeInstallCommand(parsed.command, {
|
|
199
203
|
homeDir: effectiveEnv.HOME,
|
|
200
204
|
});
|
|
@@ -204,7 +208,7 @@ export async function runCli(argv, options = {}) {
|
|
|
204
208
|
}
|
|
205
209
|
return 0;
|
|
206
210
|
}
|
|
207
|
-
const session = await connectCliMcpSession({
|
|
211
|
+
const session = await (options.connectSession || connectCliMcpSession)({
|
|
208
212
|
command: options.serverCommand || process.execPath,
|
|
209
213
|
args: options.serverArgs || resolveDefaultServerArgs(),
|
|
210
214
|
env: {
|
package/dist/cli/install.js
CHANGED
|
@@ -69,7 +69,7 @@ function buildCodexManagedBlock(packageSpecifier) {
|
|
|
69
69
|
MANAGED_BLOCK_START,
|
|
70
70
|
"[mcp_servers.satori]",
|
|
71
71
|
'command = "npx"',
|
|
72
|
-
`args = ["-y", "${packageSpecifier}"]`,
|
|
72
|
+
`args = ["-y", "--package", "${packageSpecifier}", "satori"]`,
|
|
73
73
|
`startup_timeout_ms = ${MANAGED_TIMEOUT_MS}`,
|
|
74
74
|
MANAGED_BLOCK_END,
|
|
75
75
|
"",
|
|
@@ -153,7 +153,7 @@ function parseJsonObject(filePath) {
|
|
|
153
153
|
function buildClaudeServerConfig(packageSpecifier) {
|
|
154
154
|
return {
|
|
155
155
|
command: "npx",
|
|
156
|
-
args: ["-y", packageSpecifier],
|
|
156
|
+
args: ["-y", "--package", packageSpecifier, "satori"],
|
|
157
157
|
timeout: MANAGED_TIMEOUT_MS,
|
|
158
158
|
};
|
|
159
159
|
}
|
|
@@ -168,12 +168,14 @@ function isManagedClaudeEntry(value) {
|
|
|
168
168
|
if (entry.timeout !== MANAGED_TIMEOUT_MS) {
|
|
169
169
|
return false;
|
|
170
170
|
}
|
|
171
|
-
if (!Array.isArray(entry.args) || entry.args.length !==
|
|
171
|
+
if (!Array.isArray(entry.args) || entry.args.length !== 4) {
|
|
172
172
|
return false;
|
|
173
173
|
}
|
|
174
174
|
return entry.args[0] === "-y"
|
|
175
|
-
&&
|
|
176
|
-
&&
|
|
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
179
|
}
|
|
178
180
|
function prepareClaudeInstall(filePath, packageSpecifier) {
|
|
179
181
|
const currentObject = parseJsonObject(filePath);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
type ExecFileSyncLike = typeof execFileSync;
|
|
3
|
+
export interface PackageInstallabilityOptions {
|
|
4
|
+
packageJsonPath?: string;
|
|
5
|
+
execFileSyncImpl?: ExecFileSyncLike;
|
|
6
|
+
}
|
|
7
|
+
export interface ReleaseSmokeOptions extends PackageInstallabilityOptions {
|
|
8
|
+
packageRoot?: string;
|
|
9
|
+
tempDir?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function verifyManagedPackageInstallability(options?: PackageInstallabilityOptions): string;
|
|
12
|
+
export declare function runPublishedPackageReleaseSmoke(options?: ReleaseSmokeOptions): void;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=package-installability.d.ts.map
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { execFileSync } from "node:child_process";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { CliError } from "./errors.js";
|
|
7
|
+
function resolveDefaultPackageJsonPath() {
|
|
8
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
9
|
+
return path.resolve(path.dirname(currentFile), "..", "..", "package.json");
|
|
10
|
+
}
|
|
11
|
+
function readPackageJson(packageJsonPath) {
|
|
12
|
+
return JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
13
|
+
}
|
|
14
|
+
function looksLikeExactVersion(value) {
|
|
15
|
+
return /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(value);
|
|
16
|
+
}
|
|
17
|
+
function npmOutput(error) {
|
|
18
|
+
if (!(error instanceof Error)) {
|
|
19
|
+
return String(error);
|
|
20
|
+
}
|
|
21
|
+
const stdout = "stdout" in error && typeof error.stdout === "string"
|
|
22
|
+
? error.stdout
|
|
23
|
+
: "";
|
|
24
|
+
const stderr = "stderr" in error && typeof error.stderr === "string"
|
|
25
|
+
? error.stderr
|
|
26
|
+
: "";
|
|
27
|
+
return `${stdout}\n${stderr}\n${error.message}`.trim();
|
|
28
|
+
}
|
|
29
|
+
function resolveWorkspaceDependencyVersion(packageJsonPath, dependencyName) {
|
|
30
|
+
const packageRoot = path.dirname(packageJsonPath);
|
|
31
|
+
const repoRoot = path.resolve(packageRoot, "..", "..");
|
|
32
|
+
const packagesRoot = path.join(repoRoot, "packages");
|
|
33
|
+
if (!fs.existsSync(packagesRoot)) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
for (const entry of fs.readdirSync(packagesRoot, { withFileTypes: true })) {
|
|
37
|
+
if (!entry.isDirectory()) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const candidatePath = path.join(packagesRoot, entry.name, "package.json");
|
|
41
|
+
if (!fs.existsSync(candidatePath)) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const candidate = readPackageJson(candidatePath);
|
|
45
|
+
if (candidate.name === dependencyName && looksLikeExactVersion(candidate.version)) {
|
|
46
|
+
return candidate.version;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
function assertPublishedVersion(packageName, version, ownerPackageName, ownerPackageVersion, execImpl, relation) {
|
|
52
|
+
try {
|
|
53
|
+
execImpl("npm", ["view", `${packageName}@${version}`, "version", "--json"], {
|
|
54
|
+
encoding: "utf8",
|
|
55
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if (relation === "self") {
|
|
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
|
+
}
|
|
62
|
+
throw new CliError("E_USAGE", `Cannot install ${ownerPackageName}@${ownerPackageVersion} because required dependency ${packageName}@${version} is not published on npm. Publish ${packageName}@${version} first, then rerun satori-cli install.`, 2);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export function verifyManagedPackageInstallability(options = {}) {
|
|
66
|
+
const packageJsonPath = options.packageJsonPath ?? resolveDefaultPackageJsonPath();
|
|
67
|
+
const execImpl = options.execFileSyncImpl ?? execFileSync;
|
|
68
|
+
const pkg = readPackageJson(packageJsonPath);
|
|
69
|
+
const packageSpecifier = `${pkg.name}@${pkg.version}`;
|
|
70
|
+
assertPublishedVersion(pkg.name, pkg.version, pkg.name, pkg.version, execImpl, "self");
|
|
71
|
+
for (const [dependencyName, rawDependencyVersion] of Object.entries(pkg.dependencies ?? {})) {
|
|
72
|
+
const dependencyVersion = looksLikeExactVersion(rawDependencyVersion)
|
|
73
|
+
? rawDependencyVersion
|
|
74
|
+
: rawDependencyVersion.startsWith("workspace:")
|
|
75
|
+
? resolveWorkspaceDependencyVersion(packageJsonPath, dependencyName)
|
|
76
|
+
: null;
|
|
77
|
+
if (!dependencyVersion) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
assertPublishedVersion(dependencyName, dependencyVersion, pkg.name, pkg.version, execImpl, "dependency");
|
|
81
|
+
}
|
|
82
|
+
return packageSpecifier;
|
|
83
|
+
}
|
|
84
|
+
export function runPublishedPackageReleaseSmoke(options = {}) {
|
|
85
|
+
const packageJsonPath = options.packageJsonPath ?? resolveDefaultPackageJsonPath();
|
|
86
|
+
const packageRoot = options.packageRoot ?? path.dirname(packageJsonPath);
|
|
87
|
+
const tempDir = options.tempDir ?? os.tmpdir();
|
|
88
|
+
const execImpl = options.execFileSyncImpl ?? execFileSync;
|
|
89
|
+
verifyManagedPackageInstallability({ packageJsonPath, execFileSyncImpl: execImpl });
|
|
90
|
+
const smokePackDir = fs.mkdtempSync(path.join(tempDir, "satori-release-smoke-"));
|
|
91
|
+
const smokeExecDir = fs.mkdtempSync(path.join(tempDir, "satori-release-exec-"));
|
|
92
|
+
const beforeFiles = new Set(fs.readdirSync(smokePackDir));
|
|
93
|
+
execImpl("pnpm", ["pack", "--pack-destination", smokePackDir], {
|
|
94
|
+
cwd: packageRoot,
|
|
95
|
+
encoding: "utf8",
|
|
96
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
97
|
+
});
|
|
98
|
+
const tarballName = fs.readdirSync(smokePackDir).find((entry) => entry.endsWith(".tgz") && !beforeFiles.has(entry));
|
|
99
|
+
if (!tarballName) {
|
|
100
|
+
throw new CliError("E_USAGE", "Release smoke failed: pnpm pack did not produce a tarball.", 2);
|
|
101
|
+
}
|
|
102
|
+
const tarballPath = path.join(smokePackDir, tarballName);
|
|
103
|
+
try {
|
|
104
|
+
execImpl("npm", ["exec", "--yes", "--package", tarballPath, "--", "satori", "--help"], {
|
|
105
|
+
cwd: smokeExecDir,
|
|
106
|
+
encoding: "utf8",
|
|
107
|
+
env: {
|
|
108
|
+
...process.env,
|
|
109
|
+
npm_config_package_lock: "false",
|
|
110
|
+
},
|
|
111
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
const output = npmOutput(error);
|
|
116
|
+
const pkg = readPackageJson(packageJsonPath);
|
|
117
|
+
throw new CliError("E_USAGE", `Release smoke failed for ${pkg.name}@${pkg.version}. The packed tarball did not start via 'npm exec --yes --package <tarball> -- satori --help'. ${output}`, 2);
|
|
118
|
+
}
|
|
119
|
+
finally {
|
|
120
|
+
fs.rmSync(smokePackDir, { recursive: true, force: true });
|
|
121
|
+
fs.rmSync(smokeExecDir, { recursive: true, force: true });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=package-installability.js.map
|
package/dist/config.js
CHANGED
|
@@ -169,7 +169,7 @@ export function showHelpMessage() {
|
|
|
169
169
|
console.log(`
|
|
170
170
|
Satori MCP Server
|
|
171
171
|
|
|
172
|
-
Usage: npx @zokizuan/satori-mcp@
|
|
172
|
+
Usage: npx -y @zokizuan/satori-mcp@4.4.1 [options]
|
|
173
173
|
|
|
174
174
|
Options:
|
|
175
175
|
--help, -h Show this help message
|
|
@@ -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 @zokizuan/satori-mcp@
|
|
209
|
+
OPENAI_API_KEY=sk-xxx MILVUS_ADDRESS=localhost:19530 npx -y @zokizuan/satori-mcp@4.4.1
|
|
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 @zokizuan/satori-mcp@
|
|
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
|
|
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 @zokizuan/satori-mcp@
|
|
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
|
|
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 @zokizuan/satori-mcp@
|
|
218
|
+
EMBEDDING_PROVIDER=Ollama EMBEDDING_MODEL=nomic-embed-text MILVUS_TOKEN=your-token npx -y @zokizuan/satori-mcp@4.4.1
|
|
219
219
|
`);
|
|
220
220
|
}
|
|
221
221
|
//# sourceMappingURL=config.js.map
|
package/package.json
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zokizuan/satori-mcp",
|
|
3
|
-
"version": "4.4.
|
|
3
|
+
"version": "4.4.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",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"bin": {
|
|
9
|
-
"satori": "dist/index.js"
|
|
10
|
-
"satori-cli": "dist/cli/index.js"
|
|
9
|
+
"satori": "dist/index.js"
|
|
11
10
|
},
|
|
12
11
|
"dependencies": {
|
|
13
12
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
@@ -15,7 +14,7 @@
|
|
|
15
14
|
"ignore": "^7.0.5",
|
|
16
15
|
"zod": "^3.25.55",
|
|
17
16
|
"zod-to-json-schema": "^3.25.1",
|
|
18
|
-
"@zokizuan/satori-core": "1.1.
|
|
17
|
+
"@zokizuan/satori-core": "1.1.1"
|
|
19
18
|
},
|
|
20
19
|
"devDependencies": {
|
|
21
20
|
"@types/node": "^20.0.0",
|
|
@@ -25,7 +24,6 @@
|
|
|
25
24
|
"files": [
|
|
26
25
|
"dist/**/*.js",
|
|
27
26
|
"dist/**/*.d.ts",
|
|
28
|
-
"assets/skills/**/*.md",
|
|
29
27
|
"README.md"
|
|
30
28
|
],
|
|
31
29
|
"repository": {
|
|
@@ -44,6 +42,7 @@
|
|
|
44
42
|
},
|
|
45
43
|
"scripts": {
|
|
46
44
|
"build": "pnpm clean && tsc --build --force && pnpm fix:bin-perms && pnpm docs:generate && pnpm manifest:generate",
|
|
45
|
+
"build:runtime": "pnpm clean && tsc --build --force && pnpm fix:bin-perms",
|
|
47
46
|
"dev": "tsx --watch src/index.ts",
|
|
48
47
|
"clean": "rimraf dist",
|
|
49
48
|
"lint": "eslint src --ext .ts",
|
|
@@ -55,7 +54,8 @@
|
|
|
55
54
|
"docs:check": "tsx scripts/generate-docs.ts --check",
|
|
56
55
|
"manifest:generate": "tsx scripts/generate-server-manifest.ts",
|
|
57
56
|
"manifest:check": "tsx scripts/generate-server-manifest.ts --check",
|
|
58
|
-
"
|
|
59
|
-
"
|
|
57
|
+
"release:smoke": "tsx scripts/release-smoke.ts",
|
|
58
|
+
"fix:bin-perms": "node -e \"const fs=require('fs');try{fs.chmodSync('dist/index.js',0o755);}catch(e){console.error(e);process.exit(1);}\"",
|
|
59
|
+
"test": "pnpm --filter @zokizuan/satori-core build && node --import tsx --test --test-concurrency=1 src/core/**/*.test.ts src/server/**/*.test.ts src/tools/**/*.test.ts src/cli/**/*.test.ts"
|
|
60
60
|
}
|
|
61
61
|
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: satori-indexing
|
|
3
|
-
description: Index lifecycle and remediation for Satori. Use when codebases are not indexed, stale, blocked, or need freshness recovery.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Satori Indexing
|
|
7
|
-
|
|
8
|
-
Use this skill when the task is to create, reindex, sync, inspect readiness, or recover from stale index state.
|
|
9
|
-
|
|
10
|
-
## Tools
|
|
11
|
-
|
|
12
|
-
Use only:
|
|
13
|
-
1. `list_codebases`
|
|
14
|
-
2. `manage_index`
|
|
15
|
-
|
|
16
|
-
## Workflow
|
|
17
|
-
|
|
18
|
-
1. Use `list_codebases` for a global view of tracked roots.
|
|
19
|
-
2. Use `manage_index(action="status", path=...)` for the specific codebase.
|
|
20
|
-
3. Use `manage_index(action="create", path=...)` when the codebase is not indexed.
|
|
21
|
-
4. Use `manage_index(action="reindex", path=...)` only for compatibility gates or explicit rebuilds.
|
|
22
|
-
5. Use `manage_index(action="sync", path=...)` for freshness convergence and ignore-rule updates.
|
|
23
|
-
|
|
24
|
-
## Rules
|
|
25
|
-
|
|
26
|
-
- If any tool returns `requires_reindex`, stop and reindex. Do not substitute `sync`.
|
|
27
|
-
- Never call `manage_index(action="clear")` unless the user explicitly requests destructive reset.
|
|
28
|
-
- Treat ignore-only churn as a `sync` problem first.
|
|
29
|
-
- Respect blocked and indexing states instead of forcing retries blindly.
|
|
30
|
-
|
|
31
|
-
## Status Handling
|
|
32
|
-
|
|
33
|
-
- `requires_reindex`: run `manage_index(action="reindex")`.
|
|
34
|
-
- `not_ready` with indexing reason: check status and wait for terminal completion.
|
|
35
|
-
- `not_indexed`: create the index.
|
|
36
|
-
- Ignore-rule noise mitigation: update `.satoriignore`, wait debounce, and run `sync` for immediate convergence.
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: satori-navigation
|
|
3
|
-
description: Deterministic symbol navigation with Satori. Use after search results are found to lock exact spans and inspect call relationships.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Satori Navigation
|
|
7
|
-
|
|
8
|
-
Use this skill after `search_codebase` has returned candidate results and you need exact symbol/file navigation.
|
|
9
|
-
|
|
10
|
-
## Tools
|
|
11
|
-
|
|
12
|
-
Use only:
|
|
13
|
-
1. `file_outline`
|
|
14
|
-
2. `call_graph`
|
|
15
|
-
3. `read_file`
|
|
16
|
-
|
|
17
|
-
## Workflow
|
|
18
|
-
|
|
19
|
-
1. Use grouped `search_codebase` results as the starting point.
|
|
20
|
-
2. If `callGraphHint.supported=true`, call `call_graph(path=..., symbolRef=..., direction="both", depth=1)`.
|
|
21
|
-
3. If `callGraphHint.supported=false`, execute `navigationFallback.readSpan.args` exactly.
|
|
22
|
-
4. Use `file_outline(resolveMode="exact", symbolIdExact|symbolLabelExact)` to lock the symbol span.
|
|
23
|
-
5. Use `read_file(path=..., open_symbol=...)` or deterministic line spans for the final read.
|
|
24
|
-
|
|
25
|
-
## Rules
|
|
26
|
-
|
|
27
|
-
- Treat `navigationFallback` as authoritative. Do not invent spans.
|
|
28
|
-
- `open_symbol` must resolve deterministically. Do not guess on ambiguity.
|
|
29
|
-
- `read_file(mode="annotated")` is preferred when outline metadata is useful.
|
|
30
|
-
- Follow continuation hints when plain reads are truncated.
|
|
31
|
-
|
|
32
|
-
## Remediation
|
|
33
|
-
|
|
34
|
-
- `requires_reindex`: reindex before retrying navigation.
|
|
35
|
-
- `not_ready`: wait for indexing to finish.
|
|
36
|
-
- `unsupported`: fall back to deterministic `read_file` spans when supplied by `navigationFallback`.
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: satori-search
|
|
3
|
-
description: Semantic-first code search with Satori. Use for intent-based code discovery before file reads or grep.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Satori Search
|
|
7
|
-
|
|
8
|
-
Use this skill when the task is to find where behavior lives, identify candidate symbols, or narrow the search space before deeper navigation.
|
|
9
|
-
|
|
10
|
-
## Tools
|
|
11
|
-
|
|
12
|
-
Use only:
|
|
13
|
-
1. `list_codebases`
|
|
14
|
-
2. `manage_index`
|
|
15
|
-
3. `search_codebase`
|
|
16
|
-
|
|
17
|
-
## Workflow
|
|
18
|
-
|
|
19
|
-
1. Check readiness with `manage_index(action="status", path=...)`.
|
|
20
|
-
2. If not indexed, use `manage_index(action="create", path=...)`.
|
|
21
|
-
3. If `requires_reindex` appears, stop and use `manage_index(action="reindex", path=...)`, then retry.
|
|
22
|
-
4. Search with `search_codebase(path=..., query=..., scope="runtime", resultMode="grouped", groupBy="symbol", rankingMode="auto_changed_first")`.
|
|
23
|
-
|
|
24
|
-
## Search Rules
|
|
25
|
-
|
|
26
|
-
- Start with natural-language intent, not filenames.
|
|
27
|
-
- Default to `scope="runtime"`.
|
|
28
|
-
- Use operators only when needed: `lang:`, `path:`, `-path:`, `must:`, `exclude:`.
|
|
29
|
-
- Treat warnings as usable-but-degraded results, not fatal errors.
|
|
30
|
-
- Use `debug=true` only when ranking or filter explanations are required.
|
|
31
|
-
|
|
32
|
-
## Remediation
|
|
33
|
-
|
|
34
|
-
- `requires_reindex`: run `manage_index(action="reindex")`, not `sync`.
|
|
35
|
-
- `not_ready` with indexing reason: wait or check `manage_index(action="status")`.
|
|
36
|
-
- Noise mitigation hint: update `.satoriignore`, wait debounce, rerun search, and use `manage_index(action="sync")` only for immediate convergence.
|