@zokizuan/satori-mcp 4.11.1 → 4.11.2

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
@@ -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.1 install --client all
11
- npx -y @zokizuan/satori-cli@0.4.1 doctor
10
+ npx -y @zokizuan/satori-cli@0.4.2 install --client all
11
+ npx -y @zokizuan/satori-cli@0.4.2 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,7 +16,7 @@ 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.1 --help
19
+ npx -y @zokizuan/satori-mcp@4.11.2 --help
20
20
  ```
21
21
 
22
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.
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.1 install --client all
212
+ npx -y @zokizuan/satori-cli@0.4.2 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
@@ -116,6 +116,7 @@ export declare class ToolHandlers {
116
116
  private collapseDuplicateDeclarationGroups;
117
117
  private buildFallbackGroupId;
118
118
  private isCallGraphLanguageSupported;
119
+ private loadCallGraphSidecarForSearch;
119
120
  private buildCallGraphHint;
120
121
  private sanitizeIndexedRelativeFilePath;
121
122
  private buildNavigationFallback;
@@ -1905,20 +1905,60 @@ export class ToolHandlers {
1905
1905
  }
1906
1906
  return false;
1907
1907
  }
1908
- buildCallGraphHint(file, span, language, symbolId, symbolLabel) {
1908
+ loadCallGraphSidecarForSearch(codebaseRoot) {
1909
+ const loadSidecar = this.callGraphManager?.loadSidecar;
1910
+ if (typeof loadSidecar !== 'function') {
1911
+ return null;
1912
+ }
1913
+ const sidecar = loadSidecar.call(this.callGraphManager, codebaseRoot);
1914
+ if (!sidecar || !Array.isArray(sidecar.nodes)) {
1915
+ return null;
1916
+ }
1917
+ return {
1918
+ builtAt: typeof sidecar.builtAt === 'string' ? sidecar.builtAt : undefined,
1919
+ nodes: sidecar.nodes,
1920
+ };
1921
+ }
1922
+ buildCallGraphHint(file, language, sidecar, symbolId, symbolLabel) {
1909
1923
  if (!symbolId) {
1910
1924
  return { supported: false, reason: 'missing_symbol' };
1911
1925
  }
1912
1926
  if (!this.isCallGraphLanguageSupported(language, file)) {
1913
1927
  return { supported: false, reason: 'unsupported_language' };
1914
1928
  }
1929
+ if (!sidecar) {
1930
+ return { supported: false, reason: 'missing_sidecar' };
1931
+ }
1932
+ const normalizedFile = this.sanitizeIndexedRelativeFilePath(file);
1933
+ if (!normalizedFile) {
1934
+ return { supported: false, reason: 'stale_symbol_ref' };
1935
+ }
1936
+ const sidecarNode = sidecar.nodes.find((node) => node.symbolId === symbolId);
1937
+ const normalizedSidecarFile = sidecarNode ? this.sanitizeIndexedRelativeFilePath(sidecarNode.file) : undefined;
1938
+ const sidecarSpan = sidecarNode?.span;
1939
+ if (!sidecarNode ||
1940
+ normalizedSidecarFile !== normalizedFile ||
1941
+ !sidecarSpan ||
1942
+ !Number.isFinite(sidecarSpan.startLine) ||
1943
+ !Number.isFinite(sidecarSpan.endLine)) {
1944
+ return { supported: false, reason: 'stale_symbol_ref' };
1945
+ }
1946
+ const safeStartLine = Math.max(1, Number(sidecarSpan.startLine));
1947
+ const safeEndLine = Math.max(safeStartLine, Number(sidecarSpan.endLine));
1948
+ const validatedAt = new Date(this.now()).toISOString();
1915
1949
  return {
1916
1950
  supported: true,
1951
+ validated: true,
1952
+ validatedAt,
1953
+ sidecarBuiltAt: sidecar.builtAt || validatedAt,
1917
1954
  symbolRef: {
1918
- file,
1955
+ file: normalizedSidecarFile,
1919
1956
  symbolId,
1920
- symbolLabel: symbolLabel || undefined,
1921
- span
1957
+ symbolLabel: sidecarNode.symbolLabel || symbolLabel || undefined,
1958
+ span: {
1959
+ startLine: safeStartLine,
1960
+ endLine: safeEndLine
1961
+ }
1922
1962
  }
1923
1963
  };
1924
1964
  }
@@ -1978,12 +2018,13 @@ export class ToolHandlers {
1978
2018
  if (!callGraphHint.supported) {
1979
2019
  return undefined;
1980
2020
  }
1981
- const normalizedFile = this.sanitizeIndexedRelativeFilePath(relativeFilePath);
2021
+ const normalizedFile = this.sanitizeIndexedRelativeFilePath(callGraphHint.symbolRef.file || relativeFilePath);
1982
2022
  if (!normalizedFile) {
1983
2023
  return undefined;
1984
2024
  }
1985
- const safeStartLine = Number.isFinite(span.startLine) ? Math.max(1, Number(span.startLine)) : 1;
1986
- const safeEndLine = Number.isFinite(span.endLine) ? Math.max(safeStartLine, Number(span.endLine)) : safeStartLine;
2025
+ const actionSpan = callGraphHint.symbolRef.span || span;
2026
+ const safeStartLine = Number.isFinite(actionSpan.startLine) ? Math.max(1, Number(actionSpan.startLine)) : 1;
2027
+ const safeEndLine = Number.isFinite(actionSpan.endLine) ? Math.max(safeStartLine, Number(actionSpan.endLine)) : safeStartLine;
1987
2028
  const absolutePath = path.resolve(codebaseRoot, normalizedFile);
1988
2029
  const symbolRef = {
1989
2030
  ...callGraphHint.symbolRef,
@@ -3730,6 +3771,7 @@ To force rebuild from scratch: call manage_index with {"action":"create","path":
3730
3771
  ? this.snapshotManager.getCodebaseCallGraphSidecar(effectiveRoot)
3731
3772
  : undefined;
3732
3773
  const sidecarReadyForOutline = Boolean(sidecarInfo && sidecarInfo.version === 'v3');
3774
+ const callGraphSidecar = sidecarReadyForOutline ? this.loadCallGraphSidecarForSearch(effectiveRoot) : null;
3733
3775
  const groupedResults = [];
3734
3776
  for (const group of groups.values()) {
3735
3777
  exactMatchPinningApplied = this.sortSearchCandidates(group.chunks, queryPlan.exactMatchPinningEnabled, parsedOperators.must.length > 0) || exactMatchPinningApplied;
@@ -3750,7 +3792,7 @@ To force rebuild from scratch: call manage_index with {"action":"create","path":
3750
3792
  const repSymbolId = typeof representative.result.symbolId === 'string' ? representative.result.symbolId : null;
3751
3793
  const repSymbolLabel = typeof representative.result.symbolLabel === 'string' ? representative.result.symbolLabel : null;
3752
3794
  const groupId = repSymbolId || this.buildFallbackGroupId(representative.result.relativePath, span);
3753
- const callGraphHint = this.buildCallGraphHint(representative.result.relativePath, span, representative.result.language || 'unknown', repSymbolId || undefined, repSymbolLabel || undefined);
3795
+ const callGraphHint = this.buildCallGraphHint(representative.result.relativePath, representative.result.language || 'unknown', callGraphSidecar, repSymbolId || undefined, repSymbolLabel || undefined);
3754
3796
  const navigationFallback = this.buildNavigationFallback(effectiveRoot, representative.result.relativePath, span, callGraphHint, sidecarReadyForOutline);
3755
3797
  const nextActions = this.buildSearchNextActions(effectiveRoot, representative.result.relativePath, span, callGraphHint, sidecarReadyForOutline);
3756
3798
  groupedResults.push({
@@ -4063,6 +4105,7 @@ To force rebuild from scratch: call manage_index with {"action":"create","path":
4063
4105
  const endsAfterWindowStart = windowStart === undefined || node.span.endLine >= windowStart;
4064
4106
  return startsBeforeWindowEnd && endsAfterWindowStart;
4065
4107
  });
4108
+ const outlineValidatedAt = new Date(this.now()).toISOString();
4066
4109
  const symbols = this.sortFileOutlineSymbols(windowed.map((node) => {
4067
4110
  const symbolLabel = (typeof node.symbolLabel === 'string' && node.symbolLabel.trim().length > 0)
4068
4111
  ? node.symbolLabel
@@ -4076,6 +4119,9 @@ To force rebuild from scratch: call manage_index with {"action":"create","path":
4076
4119
  },
4077
4120
  callGraphHint: {
4078
4121
  supported: true,
4122
+ validated: true,
4123
+ validatedAt: outlineValidatedAt,
4124
+ sidecarBuiltAt: sidecar.builtAt,
4079
4125
  symbolRef: {
4080
4126
  file: normalizedFile,
4081
4127
  symbolId: node.symbolId,
@@ -15,9 +15,12 @@ export interface CallGraphSymbolRef {
15
15
  export type CallGraphHint = {
16
16
  supported: true;
17
17
  symbolRef: CallGraphSymbolRef;
18
+ validated: true;
19
+ validatedAt: string;
20
+ sidecarBuiltAt: string;
18
21
  } | {
19
22
  supported: false;
20
- reason: "missing_symbol" | "unsupported_language";
23
+ reason: "missing_symbol" | "unsupported_language" | "missing_sidecar" | "stale_symbol_ref";
21
24
  };
22
25
  export interface SearchNextActionReadSymbol {
23
26
  tool: "read_file";
@@ -334,10 +337,9 @@ export interface FileOutlineSymbolResult {
334
337
  symbolId: string;
335
338
  symbolLabel: string;
336
339
  span: SearchSpan;
337
- callGraphHint: {
340
+ callGraphHint: Extract<CallGraphHint, {
338
341
  supported: true;
339
- symbolRef: CallGraphSymbolRef;
340
- };
342
+ }>;
341
343
  }
342
344
  export interface FileOutlineResponseEnvelope {
343
345
  status: FileOutlineStatus;
@@ -2,6 +2,7 @@ import { installCliStdoutRedirect, installConsoleToStderrPatch } from "./stdio-s
2
2
  export function installBootstrapStdioSafety(options) {
3
3
  const restoreConsole = installConsoleToStderrPatch({
4
4
  writeToStderr: options.writeToStderr,
5
+ methods: options.runMode === "mcp" ? ["warn", "error"] : undefined,
5
6
  });
6
7
  let restoreStdout = () => { };
7
8
  if (options.guardMode !== "off") {
@@ -1,6 +1,8 @@
1
1
  export type StdoutGuardMode = "drop" | "redirect";
2
+ type ConsoleMethodName = "log" | "info" | "warn" | "error" | "debug";
2
3
  interface ConsolePatchOptions {
3
4
  writeToStderr?: (text: string) => void;
5
+ methods?: ConsoleMethodName[];
4
6
  }
5
7
  interface CliStdoutRedirectOptions {
6
8
  mode?: StdoutGuardMode;
@@ -37,6 +37,7 @@ export function installConsoleToStderrPatch(options = {}) {
37
37
  const writeToStderr = options.writeToStderr || ((text) => {
38
38
  process.stderr.write(text);
39
39
  });
40
+ const methods = options.methods || ["log", "info", "warn", "error", "debug"];
40
41
  const original = {};
41
42
  const patchMethod = (method) => {
42
43
  original[method] = console[method];
@@ -44,11 +45,9 @@ export function installConsoleToStderrPatch(options = {}) {
44
45
  writeToStderr(ensureTrailingNewline(args.map(toLogString).join(" ")));
45
46
  };
46
47
  };
47
- patchMethod("log");
48
- patchMethod("info");
49
- patchMethod("warn");
50
- patchMethod("error");
51
- patchMethod("debug");
48
+ for (const method of methods) {
49
+ patchMethod(method);
50
+ }
52
51
  return () => {
53
52
  for (const method of Object.keys(original)) {
54
53
  const fn = original[method];
@@ -72,10 +71,11 @@ export function installCliStdoutRedirect(options = {}) {
72
71
  writeToStderr(ensureTrailingNewline(`[STDOUT_BLOCKED] ${text}`));
73
72
  return;
74
73
  }
75
- writeToStderr(ensureTrailingNewline(`[STDOUT_BLOCKED] dropped len=${text.length}`));
76
74
  return;
77
75
  }
78
- writeToStderr(ensureTrailingNewline(`[STDOUT_BLOCKED_BINARY len=${chunkLength(chunk)}]`));
76
+ if (mode === "redirect") {
77
+ writeToStderr(ensureTrailingNewline(`[STDOUT_BLOCKED_BINARY len=${chunkLength(chunk)}]`));
78
+ }
79
79
  };
80
80
  const patch = (methodName, replacement) => {
81
81
  const original = stdout[methodName];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zokizuan/satori-mcp",
3
- "version": "4.11.1",
3
+ "version": "4.11.2",
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.1"
18
+ "@zokizuan/satori-core": "1.6.2"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@types/node": "^20.0.0",