@jagilber-org/index-server 1.22.1 → 1.26.4

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.
Files changed (190) hide show
  1. package/CHANGELOG.md +91 -2
  2. package/CODE_OF_CONDUCT.md +2 -0
  3. package/CONTRIBUTING.md +32 -2
  4. package/README.md +82 -19
  5. package/SECURITY.md +17 -5
  6. package/dist/config/dashboardConfig.d.ts +3 -0
  7. package/dist/config/dashboardConfig.js +3 -0
  8. package/dist/config/defaultValues.d.ts +1 -1
  9. package/dist/config/defaultValues.js +1 -1
  10. package/dist/config/featureConfig.d.ts +2 -0
  11. package/dist/config/featureConfig.js +6 -1
  12. package/dist/config/runtimeConfig.d.ts +1 -1
  13. package/dist/config/runtimeConfig.js +8 -9
  14. package/dist/dashboard/client/admin.html +170 -53
  15. package/dist/dashboard/client/css/admin.css +132 -0
  16. package/dist/dashboard/client/js/admin.auth.js +25 -11
  17. package/dist/dashboard/client/js/admin.config.js +1 -1
  18. package/dist/dashboard/client/js/admin.feedback.js +328 -0
  19. package/dist/dashboard/client/js/admin.graph.js +120 -18
  20. package/dist/dashboard/client/js/admin.instructions.js +27 -13
  21. package/dist/dashboard/client/js/admin.logs.js +1 -5
  22. package/dist/dashboard/client/js/admin.maintenance.js +53 -8
  23. package/dist/dashboard/client/js/admin.messaging.js +1 -4
  24. package/dist/dashboard/client/js/admin.overview.js +5 -1
  25. package/dist/dashboard/client/js/admin.sessions.js +1 -1
  26. package/dist/dashboard/client/js/admin.utils.js +43 -1
  27. package/dist/dashboard/client/js/mermaid.min.js +813 -537
  28. package/dist/dashboard/export/DataExporter.js +2 -1
  29. package/dist/dashboard/server/AdminPanel.d.ts +3 -0
  30. package/dist/dashboard/server/AdminPanel.js +132 -35
  31. package/dist/dashboard/server/ApiRoutes.js +40 -9
  32. package/dist/dashboard/server/DashboardServer.js +1 -1
  33. package/dist/dashboard/server/FileMetricsStorage.d.ts +19 -0
  34. package/dist/dashboard/server/FileMetricsStorage.js +52 -5
  35. package/dist/dashboard/server/HttpTransport.js +6 -0
  36. package/dist/dashboard/server/InstanceManager.js +7 -2
  37. package/dist/dashboard/server/KnowledgeStore.js +7 -2
  38. package/dist/dashboard/server/MetricsCollector.d.ts +16 -0
  39. package/dist/dashboard/server/MetricsCollector.js +113 -17
  40. package/dist/dashboard/server/legacyDashboardHtml.js +7 -2
  41. package/dist/dashboard/server/middleware/ensureLoadedMiddleware.d.ts +1 -1
  42. package/dist/dashboard/server/middleware/ensureLoadedMiddleware.js +8 -3
  43. package/dist/dashboard/server/routes/admin.feedback.routes.d.ts +15 -0
  44. package/dist/dashboard/server/routes/admin.feedback.routes.js +188 -0
  45. package/dist/dashboard/server/routes/admin.routes.js +35 -27
  46. package/dist/dashboard/server/routes/alerts.routes.js +4 -3
  47. package/dist/dashboard/server/routes/api.feedback.routes.js +2 -1
  48. package/dist/dashboard/server/routes/api.usage.routes.js +8 -7
  49. package/dist/dashboard/server/routes/embeddings.routes.d.ts +2 -1
  50. package/dist/dashboard/server/routes/embeddings.routes.js +18 -9
  51. package/dist/dashboard/server/routes/graph.routes.js +10 -13
  52. package/dist/dashboard/server/routes/index.d.ts +1 -0
  53. package/dist/dashboard/server/routes/index.js +74 -39
  54. package/dist/dashboard/server/routes/instances.routes.js +2 -1
  55. package/dist/dashboard/server/routes/instructions.routes.js +46 -27
  56. package/dist/dashboard/server/routes/knowledge.routes.js +4 -3
  57. package/dist/dashboard/server/routes/logs.routes.js +5 -4
  58. package/dist/dashboard/server/routes/messaging.routes.js +15 -14
  59. package/dist/dashboard/server/routes/metrics.routes.js +14 -13
  60. package/dist/dashboard/server/routes/scripts.routes.js +6 -3
  61. package/dist/dashboard/server/routes/status.routes.js +5 -4
  62. package/dist/dashboard/server/routes/synthetic.routes.js +3 -2
  63. package/dist/dashboard/server/routes/usage.routes.js +2 -1
  64. package/dist/dashboard/server/utils/escapeHtml.d.ts +1 -0
  65. package/dist/dashboard/server/utils/escapeHtml.js +11 -0
  66. package/dist/dashboard/server/utils/pathContainment.d.ts +1 -0
  67. package/dist/dashboard/server/utils/pathContainment.js +15 -0
  68. package/dist/dashboard/server/wsInit.js +2 -2
  69. package/dist/lib/mcpStdioLogging.d.ts +165 -0
  70. package/dist/lib/mcpStdioLogging.js +287 -0
  71. package/dist/schemas/index.d.ts +37 -2
  72. package/dist/schemas/index.js +27 -3
  73. package/dist/server/backgroundServicesStartup.d.ts +7 -1
  74. package/dist/server/backgroundServicesStartup.js +25 -8
  75. package/dist/server/certInit.d.ts +97 -0
  76. package/dist/server/certInit.js +359 -0
  77. package/dist/server/certInit.types.d.ts +92 -0
  78. package/dist/server/certInit.types.js +34 -0
  79. package/dist/server/handshake/fallbackFrames.d.ts +31 -0
  80. package/dist/server/handshake/fallbackFrames.js +38 -0
  81. package/dist/server/handshake/initializeDetector.d.ts +31 -0
  82. package/dist/server/handshake/initializeDetector.js +88 -0
  83. package/dist/server/handshake/protocol.d.ts +15 -0
  84. package/dist/server/handshake/protocol.js +37 -0
  85. package/dist/server/handshake/readyEmitter.d.ts +6 -0
  86. package/dist/server/handshake/readyEmitter.js +88 -0
  87. package/dist/server/handshake/safetyFallbacks.d.ts +1 -0
  88. package/dist/server/handshake/safetyFallbacks.js +134 -0
  89. package/dist/server/handshake/stdinSniffer.d.ts +1 -0
  90. package/dist/server/handshake/stdinSniffer.js +260 -0
  91. package/dist/server/handshake/tracing.d.ts +16 -0
  92. package/dist/server/handshake/tracing.js +95 -0
  93. package/dist/server/handshakeManager.d.ts +23 -23
  94. package/dist/server/handshakeManager.js +36 -466
  95. package/dist/server/index-server.d.ts +23 -0
  96. package/dist/server/index-server.js +194 -9
  97. package/dist/server/mcpReadOnlySurfaces.d.ts +44 -0
  98. package/dist/server/mcpReadOnlySurfaces.js +297 -0
  99. package/dist/server/sdkServer.js +69 -7
  100. package/dist/server/transport.d.ts +5 -6
  101. package/dist/server/transport.js +46 -64
  102. package/dist/server/transportFactory.d.ts +3 -9
  103. package/dist/server/transportFactory.js +18 -380
  104. package/dist/services/atomicFs.d.ts +3 -0
  105. package/dist/services/atomicFs.js +171 -13
  106. package/dist/services/auditLog.d.ts +17 -2
  107. package/dist/services/auditLog.js +75 -14
  108. package/dist/services/bootstrapGating.js +1 -1
  109. package/dist/services/categoryRules.d.ts +10 -0
  110. package/dist/services/categoryRules.js +17 -0
  111. package/dist/services/classificationService.js +7 -5
  112. package/dist/services/embeddingService.d.ts +27 -11
  113. package/dist/services/embeddingService.js +51 -14
  114. package/dist/services/feedbackStorage.d.ts +39 -0
  115. package/dist/services/feedbackStorage.js +88 -0
  116. package/dist/services/handlers/instructions.add.js +429 -317
  117. package/dist/services/handlers/instructions.groom.js +128 -31
  118. package/dist/services/handlers/instructions.import.js +56 -23
  119. package/dist/services/handlers/instructions.patch.js +43 -32
  120. package/dist/services/handlers/instructions.query.js +20 -29
  121. package/dist/services/handlers/instructions.shared.d.ts +54 -0
  122. package/dist/services/handlers/instructions.shared.js +126 -1
  123. package/dist/services/handlers.activation.js +83 -81
  124. package/dist/services/handlers.dashboardConfig.d.ts +2 -2
  125. package/dist/services/handlers.dashboardConfig.js +1 -2
  126. package/dist/services/handlers.diagnostics.js +75 -54
  127. package/dist/services/handlers.feedback.d.ts +4 -11
  128. package/dist/services/handlers.feedback.js +11 -333
  129. package/dist/services/handlers.gates.js +69 -37
  130. package/dist/services/handlers.graph.js +2 -2
  131. package/dist/services/handlers.help.js +2 -2
  132. package/dist/services/handlers.instructionSchema.js +4 -2
  133. package/dist/services/handlers.integrity.js +42 -22
  134. package/dist/services/handlers.messaging.js +1 -1
  135. package/dist/services/handlers.metrics.js +51 -6
  136. package/dist/services/handlers.prompt.js +10 -2
  137. package/dist/services/handlers.search.js +94 -44
  138. package/dist/services/handlers.trace.js +1 -1
  139. package/dist/services/handlers.usage.js +38 -7
  140. package/dist/services/indexContext.d.ts +21 -1
  141. package/dist/services/indexContext.js +263 -78
  142. package/dist/services/indexLoader.d.ts +1 -0
  143. package/dist/services/indexLoader.js +28 -8
  144. package/dist/services/instructionRecordValidation.d.ts +39 -0
  145. package/dist/services/instructionRecordValidation.js +388 -0
  146. package/dist/services/instructions.dispatcher.js +4 -4
  147. package/dist/services/loaderSchemaValidator.d.ts +15 -0
  148. package/dist/services/loaderSchemaValidator.js +69 -0
  149. package/dist/services/logger.js +11 -2
  150. package/dist/services/mcpLogBridge.d.ts +49 -0
  151. package/dist/services/mcpLogBridge.js +83 -0
  152. package/dist/services/ownershipService.js +18 -8
  153. package/dist/services/performanceBaseline.js +23 -22
  154. package/dist/services/promptReviewService.d.ts +3 -1
  155. package/dist/services/promptReviewService.js +41 -13
  156. package/dist/services/regexSafety.d.ts +6 -0
  157. package/dist/services/regexSafety.js +46 -0
  158. package/dist/services/seedBootstrap.js +1 -1
  159. package/dist/services/storage/factory.d.ts +14 -1
  160. package/dist/services/storage/factory.js +61 -1
  161. package/dist/services/storage/jsonEmbeddingStore.d.ts +15 -0
  162. package/dist/services/storage/jsonEmbeddingStore.js +83 -0
  163. package/dist/services/storage/jsonFileStore.d.ts +3 -1
  164. package/dist/services/storage/jsonFileStore.js +8 -6
  165. package/dist/services/storage/migrationEngine.d.ts +13 -0
  166. package/dist/services/storage/migrationEngine.js +31 -0
  167. package/dist/services/storage/sqliteEmbeddingStore.d.ts +30 -0
  168. package/dist/services/storage/sqliteEmbeddingStore.js +222 -0
  169. package/dist/services/storage/sqliteStore.d.ts +3 -1
  170. package/dist/services/storage/sqliteStore.js +2 -2
  171. package/dist/services/storage/types.d.ts +48 -1
  172. package/dist/services/toolRegistry.js +77 -67
  173. package/dist/services/toolRegistry.zod.js +89 -86
  174. package/dist/services/tracing.js +5 -4
  175. package/dist/utils/envUtils.d.ts +4 -0
  176. package/dist/utils/envUtils.js +7 -0
  177. package/dist/utils/memoryMonitor.js +11 -10
  178. package/package.json +12 -4
  179. package/schemas/instruction.schema.json +38 -1
  180. package/scripts/copy-dashboard-assets.mjs +1 -1
  181. package/scripts/dist/README.md +1 -1
  182. package/scripts/generate-certs.mjs +201 -0
  183. package/scripts/setup-wizard.mjs +781 -0
  184. package/server.json +20 -0
  185. package/dist/externalClientLib.d.ts +0 -1
  186. package/dist/externalClientLib.js +0 -2
  187. package/dist/portableClientWrapper.d.ts +0 -1
  188. package/dist/portableClientWrapper.js +0 -2
  189. package/dist/services/indexingService.d.ts +0 -1
  190. package/dist/services/indexingService.js +0 -2
@@ -20,8 +20,10 @@ require("../services/toolHandlers");
20
20
  const registry_1 = require("./registry");
21
21
  const zod_1 = require("zod");
22
22
  const runtimeConfig_1 = require("../config/runtimeConfig");
23
+ const mcpLogBridge_1 = require("../services/mcpLogBridge");
23
24
  const handshakeManager_1 = require("./handshakeManager");
24
25
  const transportFactory_1 = require("./transportFactory");
26
+ const mcpReadOnlySurfaces_1 = require("./mcpReadOnlySurfaces");
25
27
  // ESM dynamic import used below for SDK modules.
26
28
  // We'll lazy-load ESM exports via dynamic import when starting.
27
29
  let StdioServerTransport;
@@ -50,8 +52,15 @@ function createSdkServer(ServerClass) {
50
52
  }
51
53
  catch { /* ignore */ }
52
54
  }
53
- const server = new ServerClass({ name: 'index', version }, { capabilities: { tools: { listChanged: true } } });
55
+ const serverCapabilities = {
56
+ tools: { listChanged: true },
57
+ logging: {},
58
+ ...(0, mcpReadOnlySurfaces_1.getReadOnlySurfaceCapabilities)(),
59
+ };
60
+ const server = new ServerClass({ name: 'index', version }, { capabilities: serverCapabilities });
54
61
  server.__declaredVersion = version;
62
+ // Register server with the MCP log bridge (activated later after ready)
63
+ (0, mcpLogBridge_1.registerMcpServer)(server);
55
64
  // Never emit tools/list_changed before ready. Wrap sendToolListChanged to enforce ordering.
56
65
  try {
57
66
  const origSendToolListChanged = server.sendToolListChanged?.bind(server);
@@ -102,14 +111,31 @@ function createSdkServer(ServerClass) {
102
111
  const result = {
103
112
  protocolVersion: negotiated,
104
113
  serverInfo: { name: 'index', version: versionDeclared },
105
- capabilities: { tools: { listChanged: true } },
106
- instructions: 'Use initialize -> tools/list -> tools/call { name, arguments }. Health: tools/call health_check. Metrics: tools/call metrics_snapshot. Ping: ping.'
114
+ capabilities: serverCapabilities,
115
+ instructions: 'Use initialize -> tools/list -> tools/call { name, arguments }. Prompts: prompts/list and prompts/get. Resources: resources/list and resources/read. Health: tools/call health_check. Metrics: tools/call metrics_snapshot. Ping: ping.'
107
116
  };
108
117
  (0, handshakeManager_1.initFrameLog)('handler_return', { negotiated });
118
+ setImmediate(() => {
119
+ try {
120
+ server.__initResponseSent = true;
121
+ (0, handshakeManager_1.initFrameLog)('ready_emit_scheduled', { reason: 'initialize-handler' });
122
+ (0, handshakeManager_1.emitReadyGlobal)(server, 'initialize-handler');
123
+ }
124
+ catch { /* ignore */ }
125
+ });
109
126
  return result;
110
127
  }
111
- catch {
112
- return { protocolVersion: handshakeManager_1.SUPPORTED_PROTOCOL_VERSIONS[0], serverInfo: { name: 'index', version: '0.0.0' }, capabilities: { tools: { listChanged: true } }, instructions: 'init fallback' };
128
+ catch (error) {
129
+ const message = error instanceof Error ? error.message : String(error);
130
+ try {
131
+ process.stderr.write(`[startup] initialize_handler_failed ${message}\n`);
132
+ }
133
+ catch { /* ignore */ }
134
+ throw {
135
+ code: -32603,
136
+ message: 'Initialize handler failure',
137
+ data: { message },
138
+ };
113
139
  }
114
140
  });
115
141
  // Legacy internal _oninitialize patch (will not trigger because we intercept initialize directly)
@@ -122,7 +148,7 @@ function createSdkServer(ServerClass) {
122
148
  const negotiated = (0, handshakeManager_1.negotiateProtocolVersion)(request?.params?.protocolVersion);
123
149
  result.protocolVersion = negotiated;
124
150
  if (result && typeof result === 'object' && !('instructions' in result)) {
125
- result.instructions = 'Use initialize -> tools/list -> tools/call { name, arguments }. Health: tools/call health_check. Metrics: tools/call metrics_snapshot. Ping: ping.';
151
+ result.instructions = 'Use initialize -> tools/list -> tools/call { name, arguments }. Prompts: prompts/list and prompts/get. Resources: resources/list and resources/read. Health: tools/call health_check. Metrics: tools/call metrics_snapshot. Ping: ping.';
126
152
  }
127
153
  this.__sawInitializeRequest = true;
128
154
  }
@@ -135,6 +161,43 @@ function createSdkServer(ServerClass) {
135
161
  const registry = (0, toolRegistry_1.getToolRegistry)();
136
162
  return { tools: registry.map(r => ({ name: r.name, description: r.description, inputSchema: r.inputSchema })) };
137
163
  });
164
+ server.setRequestHandler(requestSchema('prompts/list'), async () => {
165
+ return { prompts: (0, mcpReadOnlySurfaces_1.listReadOnlyPrompts)() };
166
+ });
167
+ server.setRequestHandler(zod_1.z.object({
168
+ jsonrpc: zod_1.z.literal('2.0'),
169
+ id: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]).optional(),
170
+ method: zod_1.z.literal('prompts/get'),
171
+ params: zod_1.z.object({
172
+ _meta: zod_1.z.any().optional(),
173
+ name: zod_1.z.string(),
174
+ arguments: zod_1.z.record(zod_1.z.string()).optional(),
175
+ }),
176
+ }), async (req) => {
177
+ const prompt = (0, mcpReadOnlySurfaces_1.getReadOnlyPrompt)(req.params.name, req.params.arguments);
178
+ if (!prompt) {
179
+ throw { code: -32602, message: `Unknown prompt: ${req.params.name}`, data: { message: `Unknown prompt: ${req.params.name}`, method: 'prompts/get', name: req.params.name } };
180
+ }
181
+ return prompt;
182
+ });
183
+ server.setRequestHandler(requestSchema('resources/list'), async () => {
184
+ return { resources: (0, mcpReadOnlySurfaces_1.listReadOnlyResources)() };
185
+ });
186
+ server.setRequestHandler(zod_1.z.object({
187
+ jsonrpc: zod_1.z.literal('2.0'),
188
+ id: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]).optional(),
189
+ method: zod_1.z.literal('resources/read'),
190
+ params: zod_1.z.object({
191
+ _meta: zod_1.z.any().optional(),
192
+ uri: zod_1.z.string(),
193
+ }),
194
+ }), async (req) => {
195
+ const resource = (0, mcpReadOnlySurfaces_1.readReadOnlyResource)(req.params.uri);
196
+ if (!resource) {
197
+ throw { code: -32602, message: `Unknown resource: ${req.params.uri}`, data: { message: `Unknown resource: ${req.params.uri}`, method: 'resources/read', uri: req.params.uri } };
198
+ }
199
+ return resource;
200
+ });
138
201
  // Raw handler for tools/call (MCP style) - returns content array
139
202
  server.setRequestHandler(requestSchema('tools/call'), async (req) => {
140
203
  const p = req?.params ?? {};
@@ -254,7 +317,6 @@ async function startSdkServer() {
254
317
  }
255
318
  (0, transportFactory_1.setupKeepalive)();
256
319
  (0, handshakeManager_1.setupSafetyFallbacks)(server);
257
- (0, transportFactory_1.wrapTransportSend)(server, transport);
258
320
  return;
259
321
  }
260
322
  // Secondary path: StdioServerTransport already loaded
@@ -9,22 +9,21 @@ interface MetricRecord {
9
9
  */
10
10
  export declare function getMetrics(): Record<string, MetricRecord>;
11
11
  /**
12
- * Register a method handler in the stdio transport's handler table.
13
- * Unlike the SDK registry, this does not add wrapping (metrics, audit, etc.).
12
+ * Register a transport-exposed method handler via the canonical registry.
14
13
  * @param method - JSON-RPC method name
15
14
  * @param handler - Handler function invoked with the parsed params
16
15
  */
17
16
  export declare function registerHandler<TParams = unknown>(method: string, handler: Handler<TParams>): void;
18
17
  /**
19
- * Return a sorted list of all registered method names in the stdio transport.
18
+ * Return a sorted list of transport-exposed method names.
20
19
  * @returns Array of method name strings in alphabetical order
21
20
  */
22
21
  export declare function listRegisteredMethods(): string[];
23
22
  /**
24
- * Look up a registered handler by method name.
23
+ * Look up a canonical registered handler by method name.
25
24
  * @param method - JSON-RPC method name to look up
26
- * @returns The handler function, or `undefined` if not registered
27
- */
25
+ * @returns The handler function, or `undefined` if not registered
26
+ */
28
27
  export declare function getHandler(method: string): Handler | undefined;
29
28
  export interface TransportOptions {
30
29
  input?: NodeJS.ReadableStream;
@@ -22,6 +22,7 @@ exports.startTransport = startTransport;
22
22
  const readline_1 = require("readline");
23
23
  const validationService_1 = require("../services/validationService");
24
24
  const runtimeConfig_1 = require("../config/runtimeConfig");
25
+ const registry_1 = require("./registry");
25
26
  const fs_1 = __importDefault(require("fs"));
26
27
  const path_1 = __importDefault(require("path"));
27
28
  // Robust version resolution: attempt cwd + relative to compiled dist location
@@ -42,50 +43,48 @@ for (const p of versionCandidates) {
42
43
  }
43
44
  catch { /* ignore */ }
44
45
  }
45
- const handlers = {
46
- 'health_check': () => {
47
- // Minimal fallback health; enriched version registered by handlers.metrics.ts overwrites this
48
- let instances = [];
49
- try {
50
- // Dynamic require avoids circular dependency at module load time
51
- // eslint-disable-next-line @typescript-eslint/no-require-imports
52
- const { getActiveInstances } = require('../dashboard/server/InstanceManager');
53
- instances = getActiveInstances().map(i => ({ pid: i.pid, port: i.port, host: i.host, startedAt: i.startedAt, current: i.current }));
54
- }
55
- catch { /* fail-open */ }
56
- return { status: 'ok', timestamp: new Date().toISOString(), version: VERSION, pid: process.pid, uptime: Math.round(process.uptime()), instances };
57
- }
58
- };
59
- const metrics = {};
60
46
  /** Return the in-memory per-method metrics map (count, totalMs, maxMs).
61
47
  * @returns Reference to the live metrics map keyed by method name
62
48
  */
63
- function getMetrics() { return metrics; }
64
- const handlerMeta = {};
49
+ function getMetrics() {
50
+ return (0, registry_1.getMetricsRaw)();
51
+ }
65
52
  /**
66
- * Register a method handler in the stdio transport's handler table.
67
- * Unlike the SDK registry, this does not add wrapping (metrics, audit, etc.).
53
+ * Register a transport-exposed method handler via the canonical registry.
68
54
  * @param method - JSON-RPC method name
69
55
  * @param handler - Handler function invoked with the parsed params
70
56
  */
71
57
  function registerHandler(method, handler) {
72
- handlers[method] = handler;
73
- handlerMeta[method] = { method };
58
+ (0, registry_1.registerHandler)(method, handler);
74
59
  }
75
60
  /**
76
- * Return a sorted list of all registered method names in the stdio transport.
61
+ * Return a sorted list of transport-exposed method names.
77
62
  * @returns Array of method name strings in alphabetical order
78
63
  */
79
64
  function listRegisteredMethods() {
80
- return Object.keys(handlerMeta).sort();
65
+ return (0, registry_1.listRegisteredMethods)();
81
66
  }
82
67
  /**
83
- * Look up a registered handler by method name.
68
+ * Look up a canonical registered handler by method name.
84
69
  * @param method - JSON-RPC method name to look up
85
- * @returns The handler function, or `undefined` if not registered
86
- */
70
+ * @returns The handler function, or `undefined` if not registered
71
+ */
87
72
  function getHandler(method) {
88
- return handlers[method];
73
+ return (0, registry_1.getHandler)(method);
74
+ }
75
+ function getFallbackHealth() {
76
+ let instances = [];
77
+ try {
78
+ // Dynamic require avoids circular dependency at module load time
79
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
80
+ const { getActiveInstances } = require('../dashboard/server/InstanceManager');
81
+ instances = getActiveInstances().map(i => ({ pid: i.pid, port: i.port, host: i.host, startedAt: i.startedAt, current: i.current }));
82
+ }
83
+ catch { /* fail-open */ }
84
+ return { status: 'ok', timestamp: new Date().toISOString(), version: VERSION, pid: process.pid, uptime: Math.round(process.uptime()), instances };
85
+ }
86
+ if (!(0, registry_1.getHandler)('health_check')) {
87
+ (0, registry_1.registerHandler)('health_check', () => getFallbackHealth());
89
88
  }
90
89
  function makeError(id, code, message, data) {
91
90
  return { jsonrpc: '2.0', id: id ?? null, error: { code, message, data } };
@@ -132,6 +131,23 @@ function startTransport(opts = {}) {
132
131
  const msg = typeof reason === 'object' && reason && 'message' in reason ? reason.message : String(reason);
133
132
  log('error', 'unhandledRejection', { reason: msg });
134
133
  });
134
+ const transportHandlers = {
135
+ 'initialize': (params) => {
136
+ const p = params;
137
+ return {
138
+ protocolVersion: p?.protocolVersion || '2025-06-18',
139
+ serverInfo: { name: 'index', version: VERSION },
140
+ capabilities: { roots: { listChanged: true }, tools: { listChanged: true } }
141
+ };
142
+ },
143
+ 'notifications/initialized': () => ({ acknowledged: true }),
144
+ 'shutdown': () => ({ shuttingDown: true }),
145
+ 'exit': () => { setTimeout(() => process.exit(0), 0); return { exiting: true }; }
146
+ };
147
+ const getAvailableMethods = () => Array.from(new Set([
148
+ ...Object.keys(transportHandlers),
149
+ ...(0, registry_1.listRegisteredMethods)(),
150
+ ])).sort();
135
151
  // Handshake state & helpers (deterministic: initialize result flushes, then server/ready)
136
152
  let initialized = false;
137
153
  let readyEmitted = false;
@@ -145,20 +161,6 @@ function startTransport(opts = {}) {
145
161
  }
146
162
  catch { /* ignore */ }
147
163
  }
148
- // Replace initialize handler with direct interception below to control write callback ordering.
149
- registerHandler('initialize', (params) => {
150
- // This body will be bypassed by explicit fast-path in line reader (kept for compatibility if called indirectly)
151
- const p = params;
152
- return {
153
- protocolVersion: p?.protocolVersion || '2025-06-18',
154
- serverInfo: { name: 'index', version: VERSION },
155
- capabilities: { roots: { listChanged: true }, tools: { listChanged: true } }
156
- };
157
- });
158
- // Accept notification some clients send post-initialize; respond benignly (single registration)
159
- registerHandler('notifications/initialized', () => ({ acknowledged: true }));
160
- registerHandler('shutdown', () => ({ shuttingDown: true }));
161
- registerHandler('exit', () => { setTimeout(() => process.exit(0), 0); return { exiting: true }; });
162
164
  // Use readline only for input parsing; do NOT set output to avoid echoing client-sent
163
165
  // JSON-RPC request lines back to stdout (which confused tests expecting only server
164
166
  // responses and caused false negatives when matching initialize/result frames).
@@ -208,8 +210,7 @@ function startTransport(opts = {}) {
208
210
  }
209
211
  initialized = true;
210
212
  // Reuse registered initialize handler so future shared logic (capability changes, root listing, etc.) stays centralized.
211
- const initHandler = handlers['initialize'];
212
- const start = Date.now();
213
+ const initHandler = transportHandlers['initialize'];
213
214
  let resultPayload;
214
215
  try {
215
216
  resultPayload = initHandler ? initHandler(req.params) : {
@@ -224,12 +225,6 @@ function startTransport(opts = {}) {
224
225
  }
225
226
  // Support promise return from handler
226
227
  Promise.resolve(resultPayload).then(resolved => {
227
- const dur = Date.now() - start;
228
- const rec = metrics['initialize'] || (metrics['initialize'] = { count: 0, totalMs: 0, maxMs: 0 });
229
- rec.count++;
230
- rec.totalMs += dur;
231
- if (dur > rec.maxMs)
232
- rec.maxMs = dur;
233
228
  const initResult = { jsonrpc: '2.0', id: req.id ?? 1, result: resolved };
234
229
  try {
235
230
  if (protocolLog) {
@@ -249,10 +244,10 @@ function startTransport(opts = {}) {
249
244
  });
250
245
  return;
251
246
  }
252
- const handler = handlers[req.method];
247
+ const handler = transportHandlers[req.method] ?? (0, registry_1.getHandler)(req.method);
253
248
  if (!handler) {
254
249
  // Provide richer context for missing method to help client authors.
255
- const available = listRegisteredMethods();
250
+ const available = getAvailableMethods();
256
251
  log('debug', 'method_not_found', { requested: req.method, availableCount: available.length });
257
252
  respondFn(makeError(req.id ?? null, -32601, 'Method not found', { method: req.method, available }));
258
253
  return;
@@ -266,19 +261,12 @@ function startTransport(opts = {}) {
266
261
  }
267
262
  }
268
263
  catch { /* fail-open on validator issues */ }
269
- const start = Date.now();
270
264
  Promise.resolve()
271
265
  .then(() => handler(req.params))
272
266
  .then(result => {
273
267
  if (!initialized) {
274
268
  log('debug', 'call_before_initialize', { method: req.method });
275
269
  }
276
- const dur = Date.now() - start;
277
- const rec = metrics[req.method] || (metrics[req.method] = { count: 0, totalMs: 0, maxMs: 0 });
278
- rec.count++;
279
- rec.totalMs += dur;
280
- if (dur > rec.maxMs)
281
- rec.maxMs = dur;
282
270
  if (req.id !== undefined && req.id !== null) {
283
271
  try {
284
272
  if (protocolLog || verbose)
@@ -289,12 +277,6 @@ function startTransport(opts = {}) {
289
277
  }
290
278
  })
291
279
  .catch(e => {
292
- const dur = Date.now() - start;
293
- const rec = metrics[req.method] || (metrics[req.method] = { count: 0, totalMs: 0, maxMs: 0 });
294
- rec.count++;
295
- rec.totalMs += dur;
296
- if (dur > rec.maxMs)
297
- rec.maxMs = dur;
298
280
  const maybeErr = e;
299
281
  if (maybeErr && typeof maybeErr === 'object' && Number.isSafeInteger(maybeErr.code)) {
300
282
  log('error', 'handler_error', { method: req.method, message: maybeErr.message, code: maybeErr.code });
@@ -1,19 +1,13 @@
1
1
  export declare const dynamicImport: (specifier: string) => any;
2
2
  /**
3
- * Set up stdout diagnostics wrapper for backpressure monitoring.
3
+ * Emit a lightweight diagnostic marker without intercepting stdout writes.
4
4
  * Enabled via INDEX_SERVER_TRACE=healthMixed.
5
5
  */
6
6
  export declare function setupStdoutDiagnostics(): Promise<void>;
7
7
  /**
8
- * Override the internal request dispatcher to retain error.data & emit diagnostics.
9
- * The upstream SDK has used both `_onRequest` (camel) and `_onrequest` (lower) across versions;
10
- * we defensively hook whichever exists and assign our wrapper to BOTH names.
8
+ * Keep diagnostics on public surfaces only; private SDK dispatcher hooks are no longer patched.
11
9
  */
12
- export declare function setupDispatcherOverride(server: any): void;
13
- /**
14
- * Wrap transport.send to detect initialize response flush and emit ready.
15
- */
16
- export declare function wrapTransportSend(server: any, transport: any): void;
10
+ export declare function setupDispatcherOverride(_server: any): void;
17
11
  /**
18
12
  * Explicit keepalive to avoid premature process exit before first client request.
19
13
  * @param label - Optional label for diagnostic log messages (e.g. 'secondary')