@jshookmcp/jshook 0.2.7 → 0.2.9

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 (157) hide show
  1. package/README.md +36 -5
  2. package/README.zh.md +36 -5
  3. package/dist/{AntiCheatDetector-S8VRj-dD.mjs → AntiCheatDetector-BNk-EoBt.mjs} +3 -3
  4. package/dist/{CodeInjector-4Z3ngPoX.mjs → CodeInjector-Cq8q01kp.mjs} +5 -5
  5. package/dist/ConsoleMonitor-CPVQW1Y-.mjs +2201 -0
  6. package/dist/{DarwinAPI-B8hg_yhz.mjs → DarwinAPI-BNPxu0RH.mjs} +1 -1
  7. package/dist/DetailedDataManager-BQQcxh64.mjs +217 -0
  8. package/dist/EventBus-DgPmwpeu.mjs +141 -0
  9. package/dist/EvidenceGraphBridge-SFesNera.mjs +153 -0
  10. package/dist/{ExtensionManager-CZ6IveoV.mjs → ExtensionManager-CWYgw0YW.mjs} +13 -6
  11. package/dist/{FingerprintManager-BVxFJL2-.mjs → FingerprintManager-gzWtkKuf.mjs} +1 -1
  12. package/dist/{HardwareBreakpoint-DK1yjWkV.mjs → HardwareBreakpoint-B9gZCdFP.mjs} +3 -3
  13. package/dist/{HeapAnalyzer-CEbo10xU.mjs → HeapAnalyzer-BLDH0dCv.mjs} +4 -4
  14. package/dist/HookGeneratorBuilders.core.generators.storage-CtcdK78Q.mjs +639 -0
  15. package/dist/InstrumentationSession-CvPC7Jwy.mjs +244 -0
  16. package/dist/{MemoryController-DdtnBdD4.mjs → MemoryController-CbVdCIJF.mjs} +3 -3
  17. package/dist/{MemoryScanSession-RMixN3bX.mjs → MemoryScanSession-BsDZbLYm.mjs} +81 -78
  18. package/dist/{MemoryScanner-QjK4ld0B.mjs → MemoryScanner-Bcpml6II.mjs} +44 -18
  19. package/dist/{NativeMemoryManager.impl-CB6gJ0NM.mjs → NativeMemoryManager.impl-dZtA1ZGn.mjs} +14 -53
  20. package/dist/{NativeMemoryManager.utils-BML4q1ry.mjs → NativeMemoryManager.utils-B-FjA2mJ.mjs} +1 -1
  21. package/dist/{PEAnalyzer-CK0xe0Fs.mjs → PEAnalyzer-D1lzJ_VG.mjs} +2 -2
  22. package/dist/PageController-Bqm2kZ_X.mjs +417 -0
  23. package/dist/{PointerChainEngine-Cd73qu5b.mjs → PointerChainEngine-BOhyVsjx.mjs} +4 -4
  24. package/dist/PrerequisiteError-Dl33Svkz.mjs +20 -0
  25. package/dist/ResponseBuilder-D3iFYx2N.mjs +143 -0
  26. package/dist/ReverseEvidenceGraph-Dlsk94LC.mjs +269 -0
  27. package/dist/ScriptManager-aHHq0X7U.mjs +3000 -0
  28. package/dist/{Speedhack-CeF0XmEz.mjs → Speedhack-CqdIFlQl.mjs} +2 -2
  29. package/dist/{StructureAnalyzer-D4GkMduU.mjs → StructureAnalyzer-DhFaPvRO.mjs} +3 -3
  30. package/dist/ToolCatalog-C0JGZoOm.mjs +582 -0
  31. package/dist/ToolError-jh9whhMd.mjs +15 -0
  32. package/dist/ToolProbe-oC7aPrkv.mjs +45 -0
  33. package/dist/ToolRegistry-BjaF4oNz.mjs +131 -0
  34. package/dist/ToolRouter.policy-BWV67ZK-.mjs +304 -0
  35. package/dist/TraceRecorder-DgxyVbdQ.mjs +519 -0
  36. package/dist/{Win32API-Bc0QnQsN.mjs → Win32API-CePkipZY.mjs} +1 -1
  37. package/dist/{Win32Debug-DUHt9XUn.mjs → Win32Debug-BvKs-gxc.mjs} +2 -2
  38. package/dist/WorkflowEngine-CuvkZtWu.mjs +598 -0
  39. package/dist/analysis-CL9uACt9.mjs +463 -0
  40. package/dist/antidebug-CqDTB_uk.mjs +1081 -0
  41. package/dist/artifactRetention-CFEprwPw.mjs +591 -0
  42. package/dist/artifacts-Bk2-_uPq.mjs +59 -0
  43. package/dist/betterSqlite3-0pqusHHH.mjs +74 -0
  44. package/dist/binary-instrument-CXfpx6fT.mjs +979 -0
  45. package/dist/bind-helpers-xFfRF-qm.mjs +22 -0
  46. package/dist/boringssl-inspector-BH2D3VKc.mjs +180 -0
  47. package/dist/browser-BpOr5PEx.mjs +4082 -0
  48. package/dist/concurrency-Bt0yv1kJ.mjs +41 -0
  49. package/dist/{constants-CCvsN80K.mjs → constants-B0OANIBL.mjs} +88 -46
  50. package/dist/coordination-qUbyF8KU.mjs +259 -0
  51. package/dist/debugger-gnKxRSN0.mjs +1271 -0
  52. package/dist/definitions-6M-eejaT.mjs +53 -0
  53. package/dist/definitions-B18eyf0B.mjs +18 -0
  54. package/dist/definitions-B3QdlrHv.mjs +34 -0
  55. package/dist/definitions-B4rAvHNZ.mjs +63 -0
  56. package/dist/definitions-BB_4jnmy.mjs +37 -0
  57. package/dist/definitions-BMfYXoNC.mjs +43 -0
  58. package/dist/definitions-Beid2EB3.mjs +27 -0
  59. package/dist/definitions-C1UvM5Iy.mjs +126 -0
  60. package/dist/definitions-CXEI7QC72.mjs +216 -0
  61. package/dist/definitions-C_4r7Fo-2.mjs +14 -0
  62. package/dist/definitions-CkFDALoa.mjs +26 -0
  63. package/dist/definitions-Cke7zEb8.mjs +94 -0
  64. package/dist/definitions-ClJLzsJQ.mjs +25 -0
  65. package/dist/definitions-Cq-zroAU.mjs +28 -0
  66. package/dist/definitions-Cy3Sl6gV.mjs +34 -0
  67. package/dist/definitions-D3VsGcvz.mjs +47 -0
  68. package/dist/definitions-DVGfrn7y.mjs +96 -0
  69. package/dist/definitions-LKpC3-nL.mjs +9 -0
  70. package/dist/definitions-bAhHQJq9.mjs +359 -0
  71. package/dist/encoding-Bvz5jLRv.mjs +1065 -0
  72. package/dist/evidence-graph-bridge-C_fv9PuC.mjs +135 -0
  73. package/dist/{factory-CibqTNC8.mjs → factory-DxlGh9Xf.mjs} +37 -52
  74. package/dist/graphql-DYWzJ29s.mjs +1026 -0
  75. package/dist/handlers-9sAbfIg-.mjs +2552 -0
  76. package/dist/handlers-Bl8zkwz1.mjs +2716 -0
  77. package/dist/handlers-C67ktuRN.mjs +710 -0
  78. package/dist/handlers-C87g8oCe.mjs +276 -0
  79. package/dist/handlers-CTsDAO6p.mjs +681 -0
  80. package/dist/handlers-Cgyg6c0U.mjs +645 -0
  81. package/dist/handlers-D6j6yka7.mjs +2124 -0
  82. package/dist/handlers-DdFzXLvF.mjs +446 -0
  83. package/dist/handlers-DeLOCd5m.mjs +799 -0
  84. package/dist/handlers-DlCJN4Td.mjs +757 -0
  85. package/dist/handlers-DxGIq15_2.mjs +917 -0
  86. package/dist/handlers-U6L4xhuF.mjs +585 -0
  87. package/dist/handlers-tB9Mp9ZK.mjs +84 -0
  88. package/dist/handlers-tiy7EIBp.mjs +572 -0
  89. package/dist/handlers.impl-DS0d9fUw.mjs +761 -0
  90. package/dist/hooks-CzCWByww.mjs +898 -0
  91. package/dist/index.mjs +384 -155
  92. package/dist/{logger-BmWzC2lM.mjs → logger-Dh_xb7_2.mjs} +14 -6
  93. package/dist/maintenance-P7ePRXQC.mjs +830 -0
  94. package/dist/manifest-2ToTpjv8.mjs +106 -0
  95. package/dist/manifest-3g71z6Bg.mjs +79 -0
  96. package/dist/manifest-82baTv4U.mjs +45 -0
  97. package/dist/manifest-B3QVVeBS.mjs +82 -0
  98. package/dist/manifest-BB2J8IMJ.mjs +149 -0
  99. package/dist/manifest-BKbgbSiY.mjs +60 -0
  100. package/dist/manifest-Bcf-TJzH.mjs +848 -0
  101. package/dist/manifest-BmtZzQiQ2.mjs +45 -0
  102. package/dist/manifest-Bnd7kqEY.mjs +55 -0
  103. package/dist/manifest-BqQX6OQC2.mjs +65 -0
  104. package/dist/manifest-BqrQ4Tpj.mjs +81 -0
  105. package/dist/manifest-Br4RPFt5.mjs +370 -0
  106. package/dist/manifest-C5qDjysN.mjs +107 -0
  107. package/dist/manifest-C9RT5nk32.mjs +34 -0
  108. package/dist/manifest-CAhOuvSl.mjs +204 -0
  109. package/dist/manifest-CBYWCUBJ.mjs +51 -0
  110. package/dist/manifest-CFADCRa1.mjs +37 -0
  111. package/dist/manifest-CQVhavRF.mjs +114 -0
  112. package/dist/manifest-CT7zZBV1.mjs +48 -0
  113. package/dist/manifest-CV12bcrF.mjs +121 -0
  114. package/dist/manifest-CXsRWjjI.mjs +224 -0
  115. package/dist/manifest-CZLUCfG02.mjs +95 -0
  116. package/dist/manifest-D6phHKFd.mjs +131 -0
  117. package/dist/manifest-DCyjf4n2.mjs +294 -0
  118. package/dist/manifest-DHsnKgP6.mjs +60 -0
  119. package/dist/manifest-Df_dliIe.mjs +55 -0
  120. package/dist/manifest-Dh8WBmEW.mjs +129 -0
  121. package/dist/manifest-DhKRAT8_.mjs +92 -0
  122. package/dist/manifest-DlpTj4ic2.mjs +193 -0
  123. package/dist/manifest-DrbmZcFl2.mjs +253 -0
  124. package/dist/manifest-DuwHjUa5.mjs +70 -0
  125. package/dist/manifest-DzwvxPJX.mjs +38 -0
  126. package/dist/manifest-NXctwWQq.mjs +68 -0
  127. package/dist/manifest-Sc_0JQ13.mjs +418 -0
  128. package/dist/manifest-gZ4s_UtG.mjs +96 -0
  129. package/dist/manifest-qSleDqdO.mjs +1023 -0
  130. package/dist/modules-C184v-S9.mjs +11365 -0
  131. package/dist/mojo-ipc-B_H61Afw.mjs +525 -0
  132. package/dist/network-671Cw6hV.mjs +3346 -0
  133. package/dist/{artifacts-BbdOMET5.mjs → outputPaths-B1uGmrWZ.mjs} +219 -212
  134. package/dist/parse-args-BlRjqlkL.mjs +39 -0
  135. package/dist/platform-WmNn8Sxb.mjs +2070 -0
  136. package/dist/process-QcbIy5Zq.mjs +1401 -0
  137. package/dist/proxy-DqNs0bAd.mjs +170 -0
  138. package/dist/registry-D-6e18lB.mjs +34 -0
  139. package/dist/response-BQVP-xUn.mjs +28 -0
  140. package/dist/server/plugin-api.mjs +2 -2
  141. package/dist/shared-state-board-DV-dpHFJ.mjs +586 -0
  142. package/dist/sourcemap-Dq8ez8vS.mjs +650 -0
  143. package/dist/ssrf-policy-ZaUfvhq7.mjs +166 -0
  144. package/dist/streaming-BUQ0VJsg.mjs +725 -0
  145. package/dist/tool-builder-DCbIC5Eo.mjs +186 -0
  146. package/dist/transform-CiYJfNX0.mjs +1007 -0
  147. package/dist/types-Bx92KJfT.mjs +4 -0
  148. package/dist/wasm-DQTnHDs4.mjs +531 -0
  149. package/dist/workflow-f3xJOcjx.mjs +725 -0
  150. package/package.json +48 -78
  151. package/dist/ExtensionManager-DqUSOamB.mjs +0 -2
  152. package/dist/ToolCatalog-CnwmMIw3.mjs +0 -61483
  153. package/dist/{CacheAdapters-CzFNpD9a.mjs → CacheAdapters-CDe5WPSV.mjs} +0 -0
  154. package/dist/{StealthVerifier-BzBCFiwx.mjs → StealthVerifier-Bo4T3bz8.mjs} +0 -0
  155. package/dist/{VersionDetector-CNXcvD46.mjs → VersionDetector-CwVLVdDM.mjs} +0 -0
  156. package/dist/{formatAddress-ChCSIRWT.mjs → formatAddress-DVkj9kpI.mjs} +0 -0
  157. package/dist/{types-BBjOqye-.mjs → types-CPhOReNX.mjs} +1 -1
package/dist/index.mjs CHANGED
@@ -1,22 +1,31 @@
1
1
  #!/usr/bin/env node
2
- import { t as logger } from "./logger-BmWzC2lM.mjs";
3
- import { $t as SEARCH_BM25_K1, A as COMPOUND_EVENT_WINDOW_MS, At as PREDICTIVE_MAX_HISTORY, Cn as SEARCH_VECTOR_LEARN_TOP_N, Dn as SHUTDOWN_TIMEOUT_MS, En as SEARCH_WORKFLOW_DOMAIN_BOOST_MULTIPLIER, Ft as RUNTIME_ERROR_WINDOW_MS, Ot as PREDICTIVE_CONFIDENCE_THRESHOLD, Pt as RUNTIME_ERROR_THRESHOLD, Qt as SEARCH_BM25_B, Sn as SEARCH_VECTOR_LEARN_DOWN, Xt as SEARCH_AFFINITY_BOOST_FACTOR, Yt as SEARCH_AFFINITY_BASE_WEIGHT, Zt as SEARCH_AFFINITY_TOP_N, _n as SEARCH_TRIGRAM_THRESHOLD, a as ACTIVATION_TTL_MINUTES, an as SEARCH_PARAM_TOKEN_WEIGHT, cn as SEARCH_RECENCY_MAX_BOOST, dn as SEARCH_RRF_BM25_BLEND, en as SEARCH_CACHE_VECTOR_WEIGHT_TOLERANCE, fn as SEARCH_RRF_K, gn as SEARCH_TIER_PENALTY, gt as MCP_HTTP_REQUEST_TIMEOUT_MS, h as AUTOPRUNE_MANUAL_INACTIVITY_MS, hn as SEARCH_TFIDF_COSINE_WEIGHT, ht as MCP_HTTP_KEEPALIVE_TIMEOUT_MS, i as ACTIVATION_EVENT_HISTORY_MAX, in as SEARCH_EXACT_NAME_MATCH_MULTIPLIER, j as COMPOUND_LONG_WINDOW_MS, jt as PREDICTIVE_MAX_SECOND_ORDER_KEYS, kt as PREDICTIVE_DECAY_FACTOR, ln as SEARCH_RECENCY_TRACKER_MAX, m as AUTOPRUNE_CHECK_INTERVAL_MS, mn as SEARCH_SYNONYM_EXPANSION_LIMIT, mt as MCP_HTTP_HEADERS_TIMEOUT_MS, n as ACTIVATION_COMPOUND_EVAL_EVERY, nn as SEARCH_DOMAIN_HUB_BOOST_MULTIPLIER, on as SEARCH_PREFIX_MATCH_MULTIPLIER, ot as HTTP_CLEANUP_INTERVAL_MS, p as AUTOPRUNE_AUTO_INACTIVITY_MS, pn as SEARCH_RRF_RESCALE_FACTOR, pt as MCP_HTTP_FORCE_CLOSE_TIMEOUT_MS, r as ACTIVATION_COOLDOWN_MS, rn as SEARCH_DOMAIN_HUB_THRESHOLD, sn as SEARCH_QUERY_CACHE_CAPACITY, st as HTTP_RATE_LIMIT_MAX_IPS, t as ACTIVATION_BOOST_WINDOW_MS, tn as SEARCH_COVERAGE_PRECISION_FACTOR, un as SEARCH_RECENCY_WINDOW_MS, vn as SEARCH_TRIGRAM_WEIGHT, wn as SEARCH_VECTOR_LEARN_UP, xn as SEARCH_VECTOR_ENABLED, yn as SEARCH_VECTOR_COSINE_WEIGHT } from "./constants-CCvsN80K.mjs";
4
- import { A as validateToolNameArray, B as asTextResponse, C as getAvailableToolNames, D as getToolInputSchema, E as getToolDomainFromContext, F as createServerEventBus, H as UnifiedCacheManager, I as getInjectionInstructions, L as generateAntiDebugBypass, M as isBrowserOrNetworkTask, N as isMaintenanceTask, O as isToolActive, P as matchWorkflowRoute, R as ToolError, S as rerankResultsForContext, T as getToolDescription, U as TokenBudgetManager, V as DetailedDataManager, _ as buildPresetRecommendations, a as getToolsForProfile, b as buildWorkflowToolSequence, c as getAllDomains, d as initRegistry, h as startArtifactRetentionScheduler, i as getToolsByDomains, j as detectWorkflowIntent, k as normalizeToolName, l as getAllManifests, m as getArtifactRetentionConfig, n as getProfileDomains, o as parseToolDomains, p as cleanupArtifacts, r as getToolDomain, s as buildHandlerMapFromRegistry, t as allTools, u as getAllRegistrations, v as buildRouteMatchMetadata, w as getRoutingState, x as getEffectivePrerequisites, y as buildWorkflowRouteRecommendation, z as asErrorResponse } from "./ToolCatalog-CnwmMIw3.mjs";
5
- import { f as getConfig, h as DEFAULT_SEARCH_CONFIG, m as validateConfig } from "./artifacts-BbdOMET5.mjs";
6
- import { n as listExtensions, r as reloadExtensions, t as ensureWorkflowsLoaded } from "./ExtensionManager-CZ6IveoV.mjs";
2
+ import { t as logger } from "./logger-Dh_xb7_2.mjs";
3
+ import { $n as SEARCH_WORKFLOW_DOMAIN_BOOST_MULTIPLIER, $t as PREDICTIVE_DECAY_FACTOR, A as COMPOUND_EVENT_WINDOW_MS, An as SEARCH_PREFIX_MATCH_MULTIPLIER, Bn as SEARCH_TIER_PENALTY_FULL, Cn as SEARCH_BM25_K1, Ct as MCP_HTTP_REQUEST_TIMEOUT_MS, Dn as SEARCH_DOMAIN_HUB_THRESHOLD, En as SEARCH_DOMAIN_HUB_BOOST_MULTIPLIER, Fn as SEARCH_RRF_BM25_BLEND, Gn as SEARCH_VECTOR_BM25_SKIP_THRESHOLD, Hn as SEARCH_TIER_PENALTY_WORKFLOW, In as SEARCH_RRF_K, Jn as SEARCH_VECTOR_ENABLED, Kn as SEARCH_VECTOR_COSINE_WEIGHT, Ln as SEARCH_RRF_RESCALE_FACTOR, Mn as SEARCH_RECENCY_MAX_BOOST, Nn as SEARCH_RECENCY_TRACKER_MAX, On as SEARCH_EXACT_NAME_MATCH_MULTIPLIER, Pn as SEARCH_RECENCY_WINDOW_MS, Qt as PREDICTIVE_CONFIDENCE_THRESHOLD, Rn as SEARCH_SYNONYM_EXPANSION_LIMIT, Sn as SEARCH_BM25_B, St as MCP_HTTP_KEEPALIVE_TIMEOUT_MS, Tn as SEARCH_COVERAGE_PRECISION_FACTOR, Un as SEARCH_TRIGRAM_THRESHOLD, Vn as SEARCH_TIER_PENALTY_SEARCH, Wn as SEARCH_TRIGRAM_WEIGHT, Xn as SEARCH_VECTOR_LEARN_TOP_N, Yn as SEARCH_VECTOR_LEARN_DOWN, Zn as SEARCH_VECTOR_LEARN_UP, a as ACTIVATION_TTL_MINUTES, an as RUNTIME_ERROR_WINDOW_MS, bn as SEARCH_AFFINITY_BOOST_FACTOR, bt as MCP_HTTP_FORCE_CLOSE_TIMEOUT_MS, en as PREDICTIVE_MAX_HISTORY, er as SHUTDOWN_TIMEOUT_MS, h as AUTOPRUNE_MANUAL_INACTIVITY_MS, i as ACTIVATION_EVENT_HISTORY_MAX, in as RUNTIME_ERROR_THRESHOLD, j as COMPOUND_LONG_WINDOW_MS, jn as SEARCH_QUERY_CACHE_CAPACITY, kn as SEARCH_PARAM_TOKEN_WEIGHT, lt as HTTP_CLEANUP_INTERVAL_MS, m as AUTOPRUNE_CHECK_INTERVAL_MS, n as ACTIVATION_COMPOUND_EVAL_EVERY, p as AUTOPRUNE_AUTO_INACTIVITY_MS, r as ACTIVATION_COOLDOWN_MS, t as ACTIVATION_BOOST_WINDOW_MS, tn as PREDICTIVE_MAX_SECOND_ORDER_KEYS, ut as HTTP_RATE_LIMIT_MAX_IPS, wn as SEARCH_CACHE_VECTOR_WEIGHT_TOLERANCE, xn as SEARCH_AFFINITY_TOP_N, xt as MCP_HTTP_HEADERS_TIMEOUT_MS, yn as SEARCH_AFFINITY_BASE_WEIGHT, yt as MCP_COMPACT_SCHEMA, zn as SEARCH_TIER_PENALTY } from "./constants-B0OANIBL.mjs";
4
+ import { a as TokenBudgetManager, i as UnifiedCacheManager, n as getArtifactRetentionConfig, r as startArtifactRetentionScheduler, t as cleanupArtifacts } from "./artifactRetention-CFEprwPw.mjs";
5
+ import { t as DetailedDataManager } from "./DetailedDataManager-BQQcxh64.mjs";
6
+ import { r as asTextResponse, t as asErrorResponse } from "./response-BQVP-xUn.mjs";
7
+ import { a as getToolsForProfile, c as ensureAllDomainsLoaded, d as getAllKnownDomains, f as getAllManifests, h as getLoaderMetadata, i as getToolsByDomains, l as ensureDomainLoaded, m as initRegistry, n as getProfileDomains, o as parseToolDomains, p as getAllRegistrations, r as getToolDomain, s as buildHandlerMapFromRegistry, t as allTools, u as getAllDomains } from "./ToolCatalog-C0JGZoOm.mjs";
8
+ import { t as ToolError } from "./ToolError-jh9whhMd.mjs";
9
+ import { i as generateAntiDebugBypass, l as ProcessRegistry, r as getInjectionInstructions } from "./HookGeneratorBuilders.core.generators.storage-CtcdK78Q.mjs";
10
+ import { c as getConfig, d as DEFAULT_SEARCH_CONFIG, u as validateConfig } from "./outputPaths-B1uGmrWZ.mjs";
11
+ import { i as reloadExtensions, n as ensureWorkflowsLoaded, r as listExtensions } from "./ExtensionManager-CWYgw0YW.mjs";
12
+ import { _ as isMaintenanceTask, a as getEffectivePrerequisites, c as getRoutingState, d as getToolInputSchema, f as isToolActive, g as isBrowserOrNetworkTask, h as detectWorkflowIntent, i as buildWorkflowToolSequence, l as getToolDescription, m as validateToolNameArray, n as buildRouteMatchMetadata, o as rerankResultsForContext, p as normalizeToolName, r as buildWorkflowRouteRecommendation, s as getAvailableToolNames, t as buildPresetRecommendations, u as getToolDomainFromContext, v as matchWorkflowRoute } from "./ToolRouter.policy-BWV67ZK-.mjs";
13
+ import { n as createServerEventBus } from "./EventBus-DgPmwpeu.mjs";
7
14
  import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
8
15
  import { CompleteRequestSchema, ErrorCode, McpError } from "@modelcontextprotocol/sdk/types.js";
9
16
  import { promises } from "fs";
10
17
  import { join } from "path";
11
18
  import { createHash } from "crypto";
12
- import { fileURLToPath } from "node:url";
13
- import { ZodError, z } from "zod";
14
- import { randomUUID, timingSafeEqual } from "node:crypto";
15
- import { readFileSync as readFileSync$1 } from "node:fs";
16
19
  import { createServer } from "node:http";
20
+ import { randomUUID, timingSafeEqual } from "node:crypto";
17
21
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
18
22
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
19
23
  import { Worker } from "worker_threads";
24
+ import { ZodError, z } from "zod";
25
+ import { readFileSync as readFileSync$1 } from "node:fs";
26
+ import { dirname, resolve } from "node:path";
27
+ import { fileURLToPath } from "node:url";
28
+ import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
20
29
  //#region src/utils/cache.ts
21
30
  var CacheManager = class {
22
31
  config;
@@ -404,7 +413,7 @@ var ToolCallContextGuard = class {
404
413
  if (!this.isContextSensitive(toolName)) return response;
405
414
  if (response.isError) return response;
406
415
  const provider = this.getProvider();
407
- if (!provider) return response;
416
+ if (!provider || typeof provider.getContextMeta !== "function") return response;
408
417
  const meta = provider.getContextMeta();
409
418
  if (!meta.pageId && meta.tabIndex === null) return response;
410
419
  const content = response.content;
@@ -1024,6 +1033,16 @@ async function closeServer(ctx) {
1024
1033
  if (ctx.shutdownStarted) return ctx.shutdownPromise ?? Promise.resolve();
1025
1034
  ctx.shutdownStarted = true;
1026
1035
  ctx.shutdownPromise = (async () => {
1036
+ const getInst = typeof ctx.getDomainInstance === "function" ? ctx.getDomainInstance.bind(ctx) : null;
1037
+ if (getInst) {
1038
+ const scheduler = getInst("snapshotScheduler");
1039
+ if (scheduler) try {
1040
+ await scheduler.flushAll();
1041
+ scheduler.dispose();
1042
+ } catch (error) {
1043
+ logger.warn("snapshot flush on shutdown failed:", error);
1044
+ }
1045
+ }
1027
1046
  for (const [, entry] of ctx.domainTtlEntries) clearTimeout(entry.timer);
1028
1047
  ctx.domainTtlEntries.clear();
1029
1048
  ctx.detailedData.shutdown();
@@ -1097,6 +1116,11 @@ async function closeServer(ctx) {
1097
1116
  } catch (error) {
1098
1117
  logger.warn("MCP server close failed:", error);
1099
1118
  }
1119
+ try {
1120
+ await ProcessRegistry.terminateAll();
1121
+ } catch (error) {
1122
+ logger.warn("ProcessRegistry cleanup failed:", error);
1123
+ }
1100
1124
  logger.success("MCP server closed");
1101
1125
  })();
1102
1126
  return ctx.shutdownPromise;
@@ -1757,7 +1781,10 @@ var EmbeddingEngine = class {
1757
1781
  }
1758
1782
  ensureWorker() {
1759
1783
  if (this.worker) return;
1760
- this.worker = new Worker(new URL("./EmbeddingWorker.js", import.meta.url));
1784
+ const workerPath = new URL("./EmbeddingWorker.js", import.meta.url);
1785
+ this.worker = new Worker(workerPath);
1786
+ if (typeof this.worker.unref === "function") this.worker.unref();
1787
+ ProcessRegistry.register(this.worker);
1761
1788
  this.worker.on("message", (msg) => {
1762
1789
  const req = this.pending.get(msg.id);
1763
1790
  if (!req) return;
@@ -1865,7 +1892,7 @@ var TrigramIndex = class TrigramIndex {
1865
1892
  * @param threshold Minimum Jaccard similarity to include in results (default 0.3).
1866
1893
  * @returns Map from document index to similarity score (0–1).
1867
1894
  */
1868
- search(query, threshold = .3) {
1895
+ search(query, threshold = SEARCH_TRIGRAM_THRESHOLD) {
1869
1896
  const queryTrigrams = TrigramIndex.extractTrigrams(query);
1870
1897
  if (queryTrigrams.size === 0) return /* @__PURE__ */ new Map();
1871
1898
  const results = /* @__PURE__ */ new Map();
@@ -2022,6 +2049,13 @@ const PARAM_DESCRIPTION_STOP_WORDS = new Set([
2022
2049
  * and tool metadata for indexing.
2023
2050
  */
2024
2051
  const QueryNormalizer = {
2052
+ /**
2053
+ * Extract parameter names and description tokens from a tool's inputSchema.
2054
+ * Handles both simple flat properties and nested object properties.
2055
+ *
2056
+ * @param inputSchema The tool's inputSchema object
2057
+ * @returns Array of normalized tokens from parameter names and descriptions
2058
+ */
2025
2059
  extractParamTokens(inputSchema) {
2026
2060
  const tokens = [];
2027
2061
  if (!inputSchema || typeof inputSchema !== "object") return tokens;
@@ -2043,6 +2077,13 @@ const QueryNormalizer = {
2043
2077
  }
2044
2078
  return tokens;
2045
2079
  },
2080
+ /**
2081
+ * Extract a short description from a full tool description.
2082
+ * Takes the first sentence and truncates to 120 characters if needed.
2083
+ *
2084
+ * @param description The full tool description
2085
+ * @returns A shortened description suitable for display
2086
+ */
2046
2087
  extractShortDescription(description) {
2047
2088
  if (!description) return "";
2048
2089
  const firstSentence = description.match(/^[^.!?\n]+[.!?]?/);
@@ -2052,9 +2093,21 @@ const QueryNormalizer = {
2052
2093
  }
2053
2094
  return description.length > 120 ? description.slice(0, 117) + "..." : description;
2054
2095
  },
2096
+ /**
2097
+ * Check if a query contains CJK (Chinese, Japanese, Korean) characters.
2098
+ *
2099
+ * @param query The search query
2100
+ * @returns true if the query contains CJK characters
2101
+ */
2055
2102
  containsCJK(query) {
2056
2103
  return /[\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff\uac00-\ud7af]/.test(query);
2057
2104
  },
2105
+ /**
2106
+ * Normalize a tool name for comparison (lowercase, underscores to hyphens/spaces).
2107
+ *
2108
+ * @param query The search query
2109
+ * @returns Normalized query string
2110
+ */
2058
2111
  normalizeToolName(query) {
2059
2112
  return query.toLowerCase().replace(/[\s-]+/g, "_");
2060
2113
  }
@@ -2065,10 +2118,10 @@ const QueryNormalizer = {
2065
2118
  * Hybrid BM25 + RRF multi-signal tool search engine for progressive tool discovery.
2066
2119
  *
2067
2120
  * Enhancements:
2068
- * - BM25 keyword scoring with synonym-expanded queries
2069
- * - TF-IDF cosine similarity as an independent RRF signal
2121
+ * - BM25 keyword scoring with synonym-expanded queries and field weights
2070
2122
  * - Trigram fuzzy matching for typo tolerance
2071
2123
  * - RRF (Reciprocal Rank Fusion) combining all signals
2124
+ * - Dense vector similarity (384-dim embeddings) as semantic signal
2072
2125
  * - Tool affinity graph with prefix-group expansion (§4.1.4 dependency hull)
2073
2126
  * - Query category adaptive domain weights (§4.1.3 task-type encoding)
2074
2127
  * - Parameter name indexing for schema-aware search
@@ -2127,8 +2180,6 @@ var ToolSearchEngine = class {
2127
2180
  domainOverrides;
2128
2181
  domainScoreMultipliers;
2129
2182
  toolScoreMultipliers;
2130
- /** IDF values per term, used for TF-IDF cosine computation. */
2131
- idfMap;
2132
2183
  /** Name → doc index for O(1) lookup during affinity expansion. */
2133
2184
  docNameIndex = /* @__PURE__ */ new Map();
2134
2185
  /** Prefix-group affinity graph: docIndex → neighbor edges. */
@@ -2157,7 +2208,8 @@ var ToolSearchEngine = class {
2157
2208
  this.toolScoreMultipliers = toolScoreMultipliers;
2158
2209
  this.docCount = source.length;
2159
2210
  this.bm25Scorer = new BM25ScorerImpl(searchConfig);
2160
- this.embeddingEngine = searchConfig?.vectorEnabled ?? SEARCH_VECTOR_ENABLED ? new EmbeddingEngine() : null;
2211
+ const vectorEnabled = searchConfig?.vectorEnabled ?? SEARCH_VECTOR_ENABLED;
2212
+ this.embeddingEngine = vectorEnabled ? new EmbeddingEngine() : null;
2161
2213
  this.feedbackTracker = new FeedbackTracker(searchConfig);
2162
2214
  this.intentBoost = new IntentBoostImpl(searchConfig?.intentToolBoostRules);
2163
2215
  let totalLength = 0;
@@ -2186,9 +2238,7 @@ var ToolSearchEngine = class {
2186
2238
  length: allTokens.length,
2187
2239
  nameTokens,
2188
2240
  nameTokenSet,
2189
- nameTokenCount: nameTokenSet.size,
2190
- tfidfWeights: /* @__PURE__ */ new Map(),
2191
- tfidfMagnitude: 0
2241
+ nameTokenCount: nameTokenSet.size
2192
2242
  };
2193
2243
  this.docs.push(doc);
2194
2244
  this.docNameIndex.set(tool.name, i);
@@ -2245,31 +2295,30 @@ var ToolSearchEngine = class {
2245
2295
  }
2246
2296
  this.avgDocLength = this.docCount > 0 ? totalLength / this.docCount : 1;
2247
2297
  this.sortedKeys = [...this.invertedIndex.keys()].toSorted();
2248
- const idfMap = /* @__PURE__ */ new Map();
2249
- for (const [term, postings] of this.invertedIndex) idfMap.set(term, Math.log(1 + this.docCount / postings.length));
2250
- this.idfMap = idfMap;
2251
- for (let i = 0; i < this.docCount; i++) {
2252
- const doc = this.docs[i];
2253
- const rawTf = /* @__PURE__ */ new Map();
2254
- for (const token of doc.tokens) rawTf.set(token, (rawTf.get(token) ?? 0) + 1);
2255
- const tfidfWeights = /* @__PURE__ */ new Map();
2256
- let magnitudeSq = 0;
2257
- for (const [term, tf] of rawTf) {
2258
- const idf = idfMap.get(term) ?? 0;
2259
- const w = (1 + Math.log(tf)) * idf;
2260
- tfidfWeights.set(term, w);
2261
- magnitudeSq += w * w;
2262
- }
2263
- doc.tfidfWeights = tfidfWeights;
2264
- doc.tfidfMagnitude = Math.sqrt(magnitudeSq);
2265
- }
2266
2298
  this.affinityGraph = this.buildAffinityGraph();
2267
2299
  this.trigramIndex = new TrigramIndex(this.docs.map((d) => d.name));
2268
2300
  this.queryCache = new LRUCache(SEARCH_QUERY_CACHE_CAPACITY);
2269
2301
  }
2270
- async search(query, topK = 10, activeToolNames, visibleDomains) {
2271
- const queryTokens = this.bm25Scorer.tokenise(query, { expandSynonyms: true });
2302
+ async search(query, topK = 10, activeToolNames, visibleDomains, profile) {
2303
+ let queryTokens = this.bm25Scorer.tokenise(query);
2272
2304
  if (queryTokens.length === 0) return [];
2305
+ if (queryTokens.length > 6) {
2306
+ const inVocab = queryTokens.filter((t) => this.invertedIndex.has(t));
2307
+ if (inVocab.length >= 3) {
2308
+ const scored = inVocab.map((t) => {
2309
+ const df = this.invertedIndex.get(t).length;
2310
+ return {
2311
+ token: t,
2312
+ idf: Math.log((this.docCount - df + .5) / (df + .5) + 1)
2313
+ };
2314
+ });
2315
+ scored.sort((a, b) => b.idf - a.idf);
2316
+ const kept = new Set(scored.slice(0, 6).map((s) => s.token));
2317
+ queryTokens = queryTokens.filter((t) => kept.has(t));
2318
+ }
2319
+ }
2320
+ const synonymTokens = this.bm25Scorer.tokenise(queryTokens.join(" "), { expandSynonyms: true }).filter((t) => !queryTokens.includes(t));
2321
+ queryTokens.push(...synonymTokens);
2273
2322
  const explicitToolMention = (() => {
2274
2323
  const lower = query.toLowerCase();
2275
2324
  if (!/(?:\b(?:call|use|run|invoke|execute)\b|调用|执行|使用|运行)/i.test(lower)) return null;
@@ -2340,11 +2389,10 @@ var ToolSearchEngine = class {
2340
2389
  const toolMultiplier = this.toolScoreMultipliers?.get(doc.name) ?? 1;
2341
2390
  if (toolMultiplier !== 1) scores[i] *= toolMultiplier;
2342
2391
  }
2343
- this.applyAffinityExpansion(scores);
2344
- this.applyDomainHubExpansion(scores);
2392
+ this.applyGraphExpansion(scores);
2345
2393
  this.applyIntentBonusBand(scores, intentToolBonuses);
2346
2394
  this.applyRecencyBoost(scores);
2347
- this.applyTierPenalty(scores, visibleDomains);
2395
+ this.applyTierPenalty(scores, visibleDomains, profile);
2348
2396
  if (explicitToolMention) {
2349
2397
  const explicitIdx = this.docNameIndex.get(explicitToolMention);
2350
2398
  if (explicitIdx !== void 0) {
@@ -2414,9 +2462,9 @@ var ToolSearchEngine = class {
2414
2462
  * tier. The penalty is a soft multiplier in [0, 1]; 1 disables the feature.
2415
2463
  * Tools without a resolved domain are left untouched.
2416
2464
  */
2417
- applyTierPenalty(scores, visibleDomains) {
2465
+ applyTierPenalty(scores, visibleDomains, profile) {
2418
2466
  if (!visibleDomains || visibleDomains.size === 0) return;
2419
- const penalty = SEARCH_TIER_PENALTY;
2467
+ const penalty = profile ? profile === "full" ? SEARCH_TIER_PENALTY_FULL : profile === "workflow" ? SEARCH_TIER_PENALTY_WORKFLOW : SEARCH_TIER_PENALTY_SEARCH : SEARCH_TIER_PENALTY;
2420
2468
  if (penalty >= 1 || penalty <= 0) return;
2421
2469
  for (let i = 0; i < this.docCount; i++) {
2422
2470
  if (scores[i] <= 0) continue;
@@ -2489,28 +2537,34 @@ var ToolSearchEngine = class {
2489
2537
  * independently contribute — a document with BM25=0 but high trigram
2490
2538
  * similarity can still surface.
2491
2539
  */
2492
- async applyRRFFusion(queryTokens, query, scores) {
2540
+ async applyRRFFusion(_queryTokens, query, scores) {
2493
2541
  const k = SEARCH_RRF_K;
2494
2542
  const trigramWeight = SEARCH_TRIGRAM_WEIGHT;
2495
- const tfidfWeight = SEARCH_TFIDF_COSINE_WEIGHT;
2496
2543
  const bm25Ranked = this.rankByScores(scores);
2497
- const cosineScores = this.computeTfidfCosineScores(queryTokens);
2498
- const cosineRanked = this.rankByMap(cosineScores);
2499
2544
  const trigramScores = this.trigramIndex.search(query, SEARCH_TRIGRAM_THRESHOLD);
2500
2545
  const trigramRanked = this.rankByMap(trigramScores);
2501
- const vectorScores = await this.computeVectorCosineScores(query);
2502
- const vectorRanked = this.rankByMap(vectorScores);
2503
- if (vectorRanked.size > 0) {
2504
- const ranking = /* @__PURE__ */ new Map();
2505
- for (const [docIdx, rank] of vectorRanked) ranking.set(this.docs[docIdx].name, rank);
2506
- this.feedbackTracker.recordVectorRanking(ranking);
2546
+ let vectorScores;
2547
+ let vectorRanked;
2548
+ if (SEARCH_VECTOR_BM25_SKIP_THRESHOLD > 0 && bm25Ranked.size > 0) {
2549
+ const topBm25Idx = [...bm25Ranked.entries()].find(([, r]) => r === 0)?.[0];
2550
+ if ((topBm25Idx !== void 0 ? scores[topBm25Idx] : 0) >= SEARCH_VECTOR_BM25_SKIP_THRESHOLD) {
2551
+ vectorScores = /* @__PURE__ */ new Map();
2552
+ vectorRanked = /* @__PURE__ */ new Map();
2553
+ } else {
2554
+ vectorScores = await this.computeVectorCosineScores(query);
2555
+ vectorRanked = this.rankByMap(vectorScores);
2556
+ }
2557
+ } else {
2558
+ vectorScores = await this.computeVectorCosineScores(query);
2559
+ vectorRanked = this.rankByMap(vectorScores);
2507
2560
  }
2561
+ const ranking = /* @__PURE__ */ new Map();
2562
+ for (const [docIdx, rank] of vectorRanked) ranking.set(this.docs[docIdx].name, rank);
2563
+ this.feedbackTracker.recordVectorRanking(ranking);
2508
2564
  for (let i = 0; i < this.docCount; i++) {
2509
2565
  let rrfScore = 0;
2510
2566
  const bm25Rank = bm25Ranked.get(i);
2511
2567
  if (bm25Rank !== void 0) rrfScore += 1 / (k + bm25Rank);
2512
- const cosineRank = cosineRanked.get(i);
2513
- if (cosineRank !== void 0 && tfidfWeight > 0) rrfScore += tfidfWeight * (1 / (k + cosineRank));
2514
2568
  const trigramRank = trigramRanked.get(i);
2515
2569
  if (trigramRank !== void 0 && trigramWeight > 0) rrfScore += trigramWeight * (1 / (k + trigramRank));
2516
2570
  const vectorRank = vectorRanked.get(i);
@@ -2524,38 +2578,6 @@ var ToolSearchEngine = class {
2524
2578
  }
2525
2579
  }
2526
2580
  /**
2527
- * Compute raw TF-IDF cosine similarity scores for each document.
2528
- * Returns Map<docIndex, cosineScore>.
2529
- */
2530
- computeTfidfCosineScores(queryTokens) {
2531
- const queryTf = /* @__PURE__ */ new Map();
2532
- for (const token of queryTokens) queryTf.set(token, (queryTf.get(token) ?? 0) + 1);
2533
- const queryWeights = /* @__PURE__ */ new Map();
2534
- let queryMagSq = 0;
2535
- for (const [term, tf] of queryTf) {
2536
- const idf = this.idfMap.get(term) ?? 0;
2537
- if (idf === 0) continue;
2538
- const w = (1 + Math.log(tf)) * idf;
2539
- queryWeights.set(term, w);
2540
- queryMagSq += w * w;
2541
- }
2542
- if (queryMagSq === 0) return /* @__PURE__ */ new Map();
2543
- const queryMagnitude = Math.sqrt(queryMagSq);
2544
- const results = /* @__PURE__ */ new Map();
2545
- for (let i = 0; i < this.docCount; i++) {
2546
- const doc = this.docs[i];
2547
- if (doc.tfidfMagnitude === 0) continue;
2548
- let dot = 0;
2549
- for (const [term, qw] of queryWeights) {
2550
- const dw = doc.tfidfWeights.get(term);
2551
- if (dw !== void 0) dot += qw * dw;
2552
- }
2553
- if (dot <= 0) continue;
2554
- results.set(i, dot / (queryMagnitude * doc.tfidfMagnitude));
2555
- }
2556
- return results;
2557
- }
2558
- /**
2559
2581
  * Rank documents by Float64Array scores.
2560
2582
  * Returns Map<docIndex, rank> (0-based, lower = better).
2561
2583
  */
@@ -2697,51 +2719,41 @@ var ToolSearchEngine = class {
2697
2719
  return graph;
2698
2720
  }
2699
2721
  /**
2700
- * Boost affinity neighbors of top results (§4.1.4).
2701
- * For each of the top-N scored documents, add a fraction of its score
2702
- * to its prefix-group neighbors, encouraging co-retrieval.
2722
+ * Combined graph-based expansion: affinity (prefix-group co-retrieval) +
2723
+ * domain hub (coherence boost for well-represented domains).
2724
+ * Single sort of scored documents feeds both expansion strategies.
2703
2725
  */
2704
- applyAffinityExpansion(scores) {
2705
- if (this.affinityGraph.size === 0) return;
2706
- const topN = SEARCH_AFFINITY_TOP_N;
2726
+ applyGraphExpansion(scores) {
2707
2727
  const scored = [];
2708
2728
  for (let i = 0; i < this.docCount; i++) if (scores[i] > 0) scored.push({
2709
2729
  idx: i,
2710
2730
  score: scores[i]
2711
2731
  });
2732
+ if (scored.length === 0) return;
2712
2733
  scored.sort((a, b) => b.score - a.score);
2713
- const boostFactor = SEARCH_AFFINITY_BOOST_FACTOR;
2714
- const limit = Math.min(topN, scored.length);
2715
- for (let rank = 0; rank < limit; rank++) {
2716
- const { idx, score } = scored[rank];
2717
- const neighbors = this.affinityGraph.get(idx);
2718
- if (!neighbors) continue;
2719
- const rankDecay = 1 / (1 + rank);
2720
- for (const { docIndex, weight } of neighbors) if (scores[docIndex] > 0) scores[docIndex] += score * weight * rankDecay * boostFactor;
2734
+ if (this.affinityGraph.size > 0) {
2735
+ const topN = SEARCH_AFFINITY_TOP_N;
2736
+ const boostFactor = SEARCH_AFFINITY_BOOST_FACTOR;
2737
+ const limit = Math.min(topN, scored.length);
2738
+ for (let rank = 0; rank < limit; rank++) {
2739
+ const { idx, score } = scored[rank];
2740
+ const neighbors = this.affinityGraph.get(idx);
2741
+ if (!neighbors) continue;
2742
+ const rankDecay = 1 / (1 + rank);
2743
+ for (const { docIndex, weight } of neighbors) if (scores[docIndex] > 0) scores[docIndex] += score * weight * rankDecay * boostFactor;
2744
+ }
2721
2745
  }
2722
- }
2723
- /**
2724
- * Domain hub expansion (§4.1.4): when a domain is heavily represented
2725
- * in top results, slightly boost remaining tools from that domain.
2726
- */
2727
- applyDomainHubExpansion(scores) {
2728
2746
  const threshold = SEARCH_DOMAIN_HUB_THRESHOLD;
2729
- if (threshold <= 0) return;
2730
- const scored = [];
2731
- for (let i = 0; i < this.docCount; i++) if (scores[i] > 0) scored.push({
2732
- idx: i,
2733
- score: scores[i]
2734
- });
2735
- if (scored.length < threshold) return;
2736
- scored.sort((a, b) => b.score - a.score);
2737
- const top10 = scored.slice(0, 10);
2738
- const domainCounts = /* @__PURE__ */ new Map();
2739
- for (const { idx } of top10) {
2740
- const domain = this.docs[idx].domain;
2741
- if (domain) domainCounts.set(domain, (domainCounts.get(domain) ?? 0) + 1);
2742
- }
2743
- for (const [domain, count] of domainCounts) if (count >= threshold) {
2744
- for (let i = 0; i < this.docCount; i++) if (scores[i] > 0 && this.docs[i].domain === domain) scores[i] *= SEARCH_DOMAIN_HUB_BOOST_MULTIPLIER;
2747
+ if (threshold > 0 && scored.length >= threshold) {
2748
+ const top10 = scored.slice(0, 10);
2749
+ const domainCounts = /* @__PURE__ */ new Map();
2750
+ for (const { idx } of top10) {
2751
+ const domain = this.docs[idx].domain;
2752
+ if (domain) domainCounts.set(domain, (domainCounts.get(domain) ?? 0) + 1);
2753
+ }
2754
+ for (const [domain, count] of domainCounts) if (count >= threshold) {
2755
+ for (let i = 0; i < this.docCount; i++) if (scores[i] > 0 && this.docs[i].domain === domain) scores[i] *= SEARCH_DOMAIN_HUB_BOOST_MULTIPLIER;
2756
+ }
2745
2757
  }
2746
2758
  }
2747
2759
  };
@@ -2781,18 +2793,22 @@ function getVisibleDomainsForTier(ctx) {
2781
2793
  }
2782
2794
  return visible;
2783
2795
  }
2796
+ function getBaseTier(ctx) {
2797
+ return ctx.baseTier;
2798
+ }
2784
2799
  function getExtensionDomainMap(ctx) {
2785
2800
  const map = /* @__PURE__ */ new Map();
2786
2801
  for (const record of ctx.extensionToolsByName.values()) map.set(record.name, record.domain);
2787
2802
  return map;
2788
2803
  }
2789
- function getCombinedTools(ctx) {
2804
+ async function getCombinedTools(ctx) {
2805
+ await ensureAllDomainsLoaded();
2790
2806
  const tools = new Map(allTools.map((tool) => [tool.name, tool]));
2791
2807
  for (const record of ctx.extensionToolsByName.values()) tools.set(record.name, record.tool);
2792
2808
  return [...tools.values()];
2793
2809
  }
2794
- function getToolByName(ctx) {
2795
- return new Map(getCombinedTools(ctx).map((tool) => [tool.name, tool]));
2810
+ async function getToolByName(ctx) {
2811
+ return new Map((await getCombinedTools(ctx)).map((tool) => [tool.name, tool]));
2796
2812
  }
2797
2813
  const searchEngineCache = /* @__PURE__ */ new WeakMap();
2798
2814
  /**
@@ -2805,11 +2821,12 @@ function buildSearchSignature(ctx) {
2805
2821
  extParts.sort();
2806
2822
  return [ctx.extensionWorkflowRuntimeById.size, extParts.join("|")].join("::");
2807
2823
  }
2808
- function getSearchEngine(ctx) {
2824
+ async function getSearchEngine(ctx) {
2825
+ await ensureAllDomainsLoaded();
2809
2826
  const signature = buildSearchSignature(ctx);
2810
2827
  const cached = searchEngineCache.get(ctx);
2811
2828
  if (cached?.signature === signature) return cached.engine;
2812
- const tools = getCombinedTools(ctx);
2829
+ const tools = await getCombinedTools(ctx);
2813
2830
  const extensionDomains = getExtensionDomainMap(ctx);
2814
2831
  const domainScoreMultipliers = /* @__PURE__ */ new Map();
2815
2832
  const toolScoreMultipliers = /* @__PURE__ */ new Map();
@@ -2826,14 +2843,14 @@ function getSearchEngine(ctx) {
2826
2843
  });
2827
2844
  return engine;
2828
2845
  }
2829
- /** Generate domain summary description from discovered manifests. */
2846
+ /** Generate domain summary description. Uses metadata when not all domains are loaded. */
2830
2847
  function buildDomainDescription(ctx) {
2831
2848
  const groups = {};
2832
2849
  for (const r of getAllRegistrations()) groups[r.domain] = (groups[r.domain] ?? 0) + 1;
2833
2850
  for (const record of ctx.extensionToolsByName.values()) groups[record.domain] = (groups[record.domain] ?? 0) + 1;
2834
- const totalTools = getAllRegistrations().length + ctx.extensionToolsByName.size;
2835
- const parts = Object.entries(groups).toSorted((a, b) => b[1] - a[1]).map(([domain, count]) => `${domain} (${count})`).join(" | ");
2836
- return `Search ${totalTools} tools across ${Object.keys(groups).length} capability domains. This includes built-in tools plus any loaded plugin/workflow tools (${ctx.extensionToolsByName.size} currently loaded). In search-tier sessions, call this before assuming a capability is unavailable. Use activate_tools for exact matches, activate_domain for an entire domain. Domains: ${parts}.`;
2851
+ const loadedCount = getAllRegistrations().length;
2852
+ const extensionCount = ctx.extensionToolsByName.size;
2853
+ return `Search ${loadedCount + extensionCount} tools across ${Object.keys(groups).length} capability domains. This includes built-in tools plus any loaded plugin/workflow tools (${extensionCount} currently loaded). In search-tier sessions, call this before assuming a capability is unavailable. Use activate_tools for exact matches, activate_domain for an entire domain. Domains: ${Object.entries(groups).toSorted((a, b) => b[1] - a[1]).map(([domain, count]) => `${domain} (${count})`).join(" | ")}. Query tip: before searching, distill your intent into key concepts (action verb + target + domain). Pass distilled keywords, not full sentences — the search engine works on token matching, not semantic understanding.`;
2837
2854
  }
2838
2855
  //#endregion
2839
2856
  //#region src/server/MCPServer.search.handlers.domain.ts
@@ -2846,12 +2863,13 @@ async function handleActivateDomain(ctx, args) {
2846
2863
  success: false,
2847
2864
  error: "domain must be a non-empty string"
2848
2865
  }));
2849
- const validDomains = new Set(getAllDomains());
2866
+ const validDomains = new Set(getAllKnownDomains());
2850
2867
  for (const record of ctx.extensionToolsByName.values()) validDomains.add(record.domain);
2851
2868
  if (!validDomains.has(domain)) return asTextResponse(JSON.stringify({
2852
2869
  success: false,
2853
2870
  error: `Unknown domain "${domain}". Valid: ${[...validDomains].join(", ")}`
2854
2871
  }));
2872
+ await ensureDomainLoaded(domain);
2855
2873
  const ttlMinutes = typeof args.ttlMinutes === "number" ? args.ttlMinutes : ACTIVATION_TTL_MINUTES;
2856
2874
  const domainTools = [...getToolsByDomains([domain]), ...[...ctx.extensionToolsByName.values()].filter((record) => record.domain === domain).map((record) => record.tool)];
2857
2875
  const activeNames = getActiveToolNames(ctx);
@@ -3409,7 +3427,8 @@ var ActivationController = class {
3409
3427
  this.boostRules = [...DEFAULT_BOOST_RULES, ...customRules].toSorted((a, b) => b.priority - a.priority);
3410
3428
  this.compoundEngine = new CompoundConditionEngine();
3411
3429
  this.predictiveBooster = new PredictiveBooster();
3412
- this.autoPruner = new AutoPruner(eventBus, new Set(getProfileDomains(ctx.baseTier)), (domain) => {
3430
+ const baseDomains = new Set(getProfileDomains(ctx.baseTier));
3431
+ this.autoPruner = new AutoPruner(eventBus, baseDomains, (domain) => {
3413
3432
  logger.info(`[ActivationController] Auto-pruning domain "${domain}"`);
3414
3433
  });
3415
3434
  this.subscribe();
@@ -3641,10 +3660,27 @@ function handleToolError(toolName, error) {
3641
3660
  logger.error(`Tool execution failed: ${toolName}`, error);
3642
3661
  throw new McpError(ErrorCode.InternalError, `Execution Failed in ${toolName}: ${error instanceof Error ? error.message : String(error)}`);
3643
3662
  }
3663
+ function stripParamDescriptions(schema) {
3664
+ const clone = { ...schema };
3665
+ if (clone.properties) {
3666
+ const props = {};
3667
+ for (const [key, val] of Object.entries(clone.properties)) {
3668
+ const { description: _d, ...rest } = val;
3669
+ props[key] = stripParamDescriptions(rest);
3670
+ }
3671
+ clone.properties = props;
3672
+ }
3673
+ if (clone.items && typeof clone.items === "object") {
3674
+ const { description: _d, ...rest } = clone.items;
3675
+ clone.items = stripParamDescriptions(rest);
3676
+ }
3677
+ if (clone.additionalProperties && typeof clone.additionalProperties === "object" && !Array.isArray(clone.additionalProperties)) clone.additionalProperties = stripParamDescriptions(clone.additionalProperties);
3678
+ return clone;
3679
+ }
3644
3680
  function registerSingleTool(ctx, toolDef) {
3645
3681
  const builtTool = toolDef;
3646
3682
  if (builtTool.__autocomplete) ctx.toolAutocompleteHandlers.set(toolDef.name, builtTool.__autocomplete);
3647
- const rawSchema = toolDef.inputSchema;
3683
+ const rawSchema = MCP_COMPACT_SCHEMA && toolDef.inputSchema ? stripParamDescriptions(toolDef.inputSchema) : toolDef.inputSchema;
3648
3684
  const shape = rawSchema && typeof rawSchema === "object" ? buildZodShape(rawSchema) : {};
3649
3685
  const description = toolDef.description ?? toolDef.name;
3650
3686
  if (Object.keys(shape).length > 0) {
@@ -3730,7 +3766,7 @@ async function routeToolRequest(request, ctx, searchEngine) {
3730
3766
  const availableToolNames = getAvailableToolNames(ctx);
3731
3767
  const routeMatch = matchWorkflowRoute(task, ctx);
3732
3768
  let presetPlannedToolNames = null;
3733
- const searchResults = await searchEngine.search(task, maxRecommendations * 2, activeNames, visibleDomains);
3769
+ const searchResults = await searchEngine.search(task, maxRecommendations * 2, activeNames, visibleDomains, getBaseTier(ctx));
3734
3770
  let finalResults = [];
3735
3771
  if (routeMatch?.workflow.route.kind === "preset") {
3736
3772
  const presetTools = buildPresetRecommendations(routeMatch, routingState, ctx, availableToolNames);
@@ -3897,10 +3933,10 @@ async function routeToolRequest(request, ctx, searchEngine) {
3897
3933
  async function handleSearchTools(ctx, args) {
3898
3934
  const query = args.query;
3899
3935
  const topK = args.top_k ?? 10;
3900
- const engine = getSearchEngine(ctx);
3936
+ const engine = await getSearchEngine(ctx);
3901
3937
  const activeNames = getActiveToolNames(ctx);
3902
3938
  const visibleDomains = getVisibleDomainsForTier(ctx);
3903
- const results = await engine.search(query, topK, activeNames, visibleDomains);
3939
+ const results = await engine.search(query, topK, activeNames, visibleDomains, getBaseTier(ctx));
3904
3940
  const topResult = results[0];
3905
3941
  const topTool = topResult ? describeTool(topResult.name, ctx) : null;
3906
3942
  const topExampleArgs = topTool ? generateExampleArgs(topTool.inputSchema) : void 0;
@@ -3927,12 +3963,14 @@ async function handleSearchTools(ctx, args) {
3927
3963
  exampleArgs: topExampleArgs,
3928
3964
  description: `Call ${topResult.name} directly. Use describe_tool("${topResult.name}") only if you need the full schema.`
3929
3965
  });
3966
+ const baseHint = "For guided tool discovery with workflow detection, use route_tool instead. Use activate_tools to enable specific tools, activate_domain for entire domains.";
3967
+ const refinementHint = results.length < 3 ? " Few results — try distilling your query to key concepts (e.g. \"hook fetch\" instead of \"how to intercept fetch requests\")." : "";
3930
3968
  const response = {
3931
3969
  query,
3932
3970
  resultCount: results.length,
3933
3971
  results,
3934
3972
  nextActions: searchNextActions,
3935
- hint: "For guided tool discovery with workflow detection, use route_tool instead. Use activate_tools to enable specific tools, activate_domain for entire domains."
3973
+ hint: baseHint + refinementHint
3936
3974
  };
3937
3975
  return asTextResponse(JSON.stringify(response, null, 2));
3938
3976
  }
@@ -3950,6 +3988,7 @@ async function notifyToolListChanged(ctx, changed) {
3950
3988
  }
3951
3989
  }
3952
3990
  async function activateToolNames(ctx, names) {
3991
+ await ensureAllDomainsLoaded();
3953
3992
  const activeNames = getActiveToolNames(ctx);
3954
3993
  const activated = [];
3955
3994
  const alreadyActive = [];
@@ -3960,7 +3999,7 @@ async function activateToolNames(ctx, names) {
3960
3999
  alreadyActive.push(name);
3961
4000
  continue;
3962
4001
  }
3963
- const toolDef = getToolByName(ctx).get(name);
4002
+ const toolDef = (await getToolByName(ctx)).get(name);
3964
4003
  if (!toolDef) {
3965
4004
  notFound.push(name);
3966
4005
  continue;
@@ -4060,7 +4099,7 @@ async function handleRouteTool(ctx, args) {
4060
4099
  success: false,
4061
4100
  error: "task must be a non-empty string"
4062
4101
  }));
4063
- const engine = getSearchEngine(ctx);
4102
+ const engine = await getSearchEngine(ctx);
4064
4103
  const autoActivate = context?.autoActivate === true;
4065
4104
  let response = populateCallCommands(await routeToolRequest({
4066
4105
  task,
@@ -4174,7 +4213,7 @@ async function handleCallTool(ctx, args) {
4174
4213
  try {
4175
4214
  const response = await ctx.executeToolWithTracking(name, toolArgs);
4176
4215
  try {
4177
- getSearchEngine(ctx).recordToolCallFeedback(name, "");
4216
+ (await getSearchEngine(ctx)).recordToolCallFeedback(name, "");
4178
4217
  } catch {}
4179
4218
  return attachCallToolMetadata(response, callMetadata);
4180
4219
  } catch (error) {
@@ -4199,7 +4238,7 @@ function buildMetaToolDefinitions(ctx) {
4199
4238
  properties: {
4200
4239
  query: {
4201
4240
  type: "string",
4202
- description: "Search query: keywords, tool name, domain name, or description fragment"
4241
+ description: "Before calling, distill your intent into 2-5 key concepts: what action, on what target, in which domain. Pass only those distilled keywords — not the original user request."
4203
4242
  },
4204
4243
  top_k: {
4205
4244
  type: "number",
@@ -4475,7 +4514,164 @@ Generally, you have three options to deploy hooks:
4475
4514
  }] }));
4476
4515
  }
4477
4516
  //#endregion
4517
+ //#region src/server/persistence/RuntimeSnapshotScheduler.ts
4518
+ var RuntimeSnapshotScheduler = class {
4519
+ sources = [];
4520
+ debounceTimer = null;
4521
+ periodicTimer = null;
4522
+ debounceMs;
4523
+ periodicMs;
4524
+ disposed = false;
4525
+ started = false;
4526
+ constructor(options) {
4527
+ this.debounceMs = options?.debounceMs ?? 2e3;
4528
+ this.periodicMs = options?.periodicMs ?? 3e4;
4529
+ }
4530
+ register(filePath, source) {
4531
+ const existing = this.sources.find((entry) => entry.filePath === filePath || entry.source === source);
4532
+ if (existing) {
4533
+ if (existing.filePath !== filePath || existing.source !== source) logger.warn(`skipping conflicting snapshot registration for ${filePath}`);
4534
+ return;
4535
+ }
4536
+ const entry = {
4537
+ source,
4538
+ filePath
4539
+ };
4540
+ this.sources.push(entry);
4541
+ if (this.started) this.restoreOne(entry).catch((err) => logger.warn(`snapshot restore failed for ${entry.filePath}:`, err));
4542
+ }
4543
+ async start() {
4544
+ if (this.started || this.disposed) return;
4545
+ this.started = true;
4546
+ await this.restoreAll();
4547
+ if (this.disposed || this.periodicTimer) return;
4548
+ this.periodicTimer = setInterval(() => {
4549
+ this.scheduleFlush().catch((err) => logger.warn("periodic snapshot failed:", err));
4550
+ }, this.periodicMs);
4551
+ }
4552
+ notifyDirty() {
4553
+ if (this.disposed) return;
4554
+ if (this.debounceTimer) clearTimeout(this.debounceTimer);
4555
+ this.debounceTimer = setTimeout(() => {
4556
+ this.scheduleFlush().catch((err) => logger.warn("debounce snapshot failed:", err));
4557
+ }, this.debounceMs);
4558
+ }
4559
+ async flushAll() {
4560
+ if (this.debounceTimer) {
4561
+ clearTimeout(this.debounceTimer);
4562
+ this.debounceTimer = null;
4563
+ }
4564
+ await this.writeDirtySources();
4565
+ }
4566
+ dispose() {
4567
+ this.disposed = true;
4568
+ if (this.debounceTimer) {
4569
+ clearTimeout(this.debounceTimer);
4570
+ this.debounceTimer = null;
4571
+ }
4572
+ if (this.periodicTimer) {
4573
+ clearInterval(this.periodicTimer);
4574
+ this.periodicTimer = null;
4575
+ }
4576
+ }
4577
+ async restoreAll() {
4578
+ for (const entry of this.sources) await this.restoreOne(entry);
4579
+ }
4580
+ async restoreOne(entry) {
4581
+ try {
4582
+ const data = await readFile(entry.filePath, "utf-8");
4583
+ const parsed = JSON.parse(data);
4584
+ entry.source.restoreSnapshot(parsed);
4585
+ logger.info(`restored snapshot from ${entry.filePath}`);
4586
+ } catch {}
4587
+ }
4588
+ async scheduleFlush() {
4589
+ await this.writeDirtySources();
4590
+ }
4591
+ async writeDirtySources() {
4592
+ for (const entry of this.sources) {
4593
+ if (!entry.source.isPersistDirty()) continue;
4594
+ try {
4595
+ await this.writeSnapshot(entry);
4596
+ } catch (err) {
4597
+ logger.warn(`snapshot write failed for ${entry.filePath}:`, err);
4598
+ }
4599
+ }
4600
+ }
4601
+ async writeSnapshot(entry) {
4602
+ await mkdir(dirname(entry.filePath), { recursive: true });
4603
+ const data = JSON.stringify(entry.source.exportSnapshot());
4604
+ const tmpPath = entry.filePath + ".tmp";
4605
+ await writeFile(tmpPath, data, "utf-8");
4606
+ await rename(tmpPath, entry.filePath);
4607
+ entry.source.markPersisted();
4608
+ }
4609
+ };
4610
+ function getStateDir(baseDir) {
4611
+ return resolve(baseDir, ".jshookmcp", "state");
4612
+ }
4613
+ //#endregion
4478
4614
  //#region src/server/MCPServer.ts
4615
+ function shouldCollectExecutionMetrics() {
4616
+ return process.env.E2E_COLLECT_PERFORMANCE === "1";
4617
+ }
4618
+ function captureExecutionMetricMemory() {
4619
+ const memory = process.memoryUsage();
4620
+ return {
4621
+ source: "server",
4622
+ rssBytes: memory.rss,
4623
+ privateBytes: null,
4624
+ virtualBytes: null,
4625
+ heapUsedBytes: memory.heapUsed,
4626
+ heapTotalBytes: memory.heapTotal,
4627
+ externalBytes: memory.external,
4628
+ arrayBuffersBytes: memory.arrayBuffers
4629
+ };
4630
+ }
4631
+ function buildExecutionMetrics(startedAt, startTime, timeoutMs, cpuStart, memoryBefore) {
4632
+ const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
4633
+ const cpuUsage = process.cpuUsage(cpuStart);
4634
+ const memoryAfter = captureExecutionMetricMemory();
4635
+ return {
4636
+ source: "server",
4637
+ startedAt,
4638
+ finishedAt,
4639
+ elapsedMs: Number((performance.now() - startTime).toFixed(2)),
4640
+ timeoutMs,
4641
+ serverPid: process.pid,
4642
+ cpuUserMicros: cpuUsage.user,
4643
+ cpuSystemMicros: cpuUsage.system,
4644
+ memoryBefore,
4645
+ memoryAfter,
4646
+ memoryDelta: {
4647
+ rssBytes: memoryAfter.rssBytes - memoryBefore.rssBytes,
4648
+ privateBytes: null,
4649
+ virtualBytes: null,
4650
+ heapUsedBytes: memoryAfter.heapUsedBytes - memoryBefore.heapUsedBytes,
4651
+ heapTotalBytes: memoryAfter.heapTotalBytes - memoryBefore.heapTotalBytes,
4652
+ externalBytes: memoryAfter.externalBytes - memoryBefore.externalBytes,
4653
+ arrayBuffersBytes: memoryAfter.arrayBuffersBytes - memoryBefore.arrayBuffersBytes
4654
+ }
4655
+ };
4656
+ }
4657
+ function appendExecutionMetrics(response, metrics) {
4658
+ const content = response.content;
4659
+ if (!Array.isArray(content)) return response;
4660
+ const firstText = content.find((entry) => typeof entry === "object" && entry !== null && entry.type === "text" && typeof entry.text === "string");
4661
+ if (!firstText) return response;
4662
+ try {
4663
+ const parsed = JSON.parse(firstText.text);
4664
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return response;
4665
+ const record = parsed;
4666
+ if (!("_executionMetrics" in record)) {
4667
+ record._executionMetrics = metrics;
4668
+ firstText.text = JSON.stringify(record);
4669
+ }
4670
+ } catch {
4671
+ return response;
4672
+ }
4673
+ return response;
4674
+ }
4479
4675
  var MCPServer = class {
4480
4676
  config;
4481
4677
  server;
@@ -4531,12 +4727,32 @@ var MCPServer = class {
4531
4727
  this.enabledDomains = this.resolveEnabledDomains(this.selectedTools);
4532
4728
  const depsEntries = [];
4533
4729
  const manifests = getAllManifests();
4534
- for (const m of manifests) depsEntries.push([m.depKey, createDomainProxy(this, m.domain, `${m.domain}:${m.depKey}`, () => m.ensure(this))]);
4535
- for (const m of manifests) if (m.secondaryDepKeys) {
4536
- for (const key of m.secondaryDepKeys) if (!depsEntries.some(([k]) => k === key)) depsEntries.push([key, createDomainProxy(this, m.domain, `${m.domain}:${key}`, async () => {
4537
- await m.ensure(this);
4538
- return this[key];
4539
- })]);
4730
+ const loadedByDomain = new Map(manifests.map((m) => [m.domain, m]));
4731
+ const allMeta = getLoaderMetadata();
4732
+ if (!Array.isArray(allMeta)) logger.warn("[MCPServer] getLoaderMetadata returned non-array, skipping domain proxy setup");
4733
+ else for (const meta of allMeta) {
4734
+ const loaded = loadedByDomain.get(meta.domain);
4735
+ if (loaded) {
4736
+ depsEntries.push([meta.depKey, createDomainProxy(this, meta.domain, `${meta.domain}:${meta.depKey}`, () => loaded.ensure(this))]);
4737
+ if (loaded.secondaryDepKeys) {
4738
+ for (const key of loaded.secondaryDepKeys) if (!depsEntries.some(([k]) => k === key)) depsEntries.push([key, createDomainProxy(this, meta.domain, `${meta.domain}:${key}`, async () => {
4739
+ await loaded.ensure(this);
4740
+ return this[key];
4741
+ })]);
4742
+ }
4743
+ } else {
4744
+ depsEntries.push([meta.depKey, createDomainProxy(this, meta.domain, `${meta.domain}:${meta.depKey}`, async () => {
4745
+ const manifest = await ensureDomainLoaded(meta.domain);
4746
+ if (!manifest) throw new Error(`Failed to load domain ${meta.domain}`);
4747
+ return manifest.ensure(this);
4748
+ })]);
4749
+ for (const key of meta.secondaryDepKeys) if (!depsEntries.some(([k]) => k === key)) depsEntries.push([key, createDomainProxy(this, meta.domain, `${meta.domain}:${key}`, async () => {
4750
+ const manifest = await ensureDomainLoaded(meta.domain);
4751
+ if (!manifest) throw new Error(`Failed to load domain ${meta.domain}`);
4752
+ await manifest.ensure(this);
4753
+ return this[key];
4754
+ })]);
4755
+ }
4540
4756
  }
4541
4757
  this.handlerDeps = Object.fromEntries(depsEntries);
4542
4758
  const selectedToolNames = new Set(this.selectedTools.map((t) => t.name));
@@ -4573,6 +4789,11 @@ var MCPServer = class {
4573
4789
  this.samplingBridge = new LLMSamplingBridge(this.server);
4574
4790
  this.elicitationBridge = new ElicitationBridge(this.server);
4575
4791
  this.setDomainInstance("activationController", new ActivationController(this.eventBus, this));
4792
+ const stateDir = getStateDir(process.cwd());
4793
+ const snapshotScheduler = new RuntimeSnapshotScheduler();
4794
+ this.setDomainInstance("snapshotScheduler", snapshotScheduler);
4795
+ this.setDomainInstance("snapshotStateDir", stateDir);
4796
+ snapshotScheduler.start().catch((err) => logger.warn("snapshot scheduler start failed:", err));
4576
4797
  this.eventBus.on("tool:progress", async (payload) => {
4577
4798
  try {
4578
4799
  await this.server.server.notification({
@@ -4651,7 +4872,7 @@ var MCPServer = class {
4651
4872
  }
4652
4873
  this.cacheRegistrationPromise = (async () => {
4653
4874
  try {
4654
- const { createCacheAdapters } = await import("./CacheAdapters-CzFNpD9a.mjs");
4875
+ const { createCacheAdapters } = await import("./CacheAdapters-CDe5WPSV.mjs");
4655
4876
  const codeCache = this.collector.getCache();
4656
4877
  const codeCompressor = this.collector.getCompressor();
4657
4878
  const adapters = createCacheAdapters(this.detailedData, codeCache, codeCompressor);
@@ -4672,6 +4893,12 @@ var MCPServer = class {
4672
4893
  }
4673
4894
  async executeToolWithTracking(name, args) {
4674
4895
  let timeoutTimer;
4896
+ const timeoutMs = 3e4;
4897
+ const collectExecutionMetrics = shouldCollectExecutionMetrics();
4898
+ const executionStartedAt = collectExecutionMetrics ? (/* @__PURE__ */ new Date()).toISOString() : null;
4899
+ const executionStartTime = collectExecutionMetrics ? performance.now() : 0;
4900
+ const executionCpuStart = collectExecutionMetrics ? process.cpuUsage() : null;
4901
+ const executionMemoryBefore = collectExecutionMetrics ? captureExecutionMetricMemory() : null;
4675
4902
  try {
4676
4903
  timeoutTimer = setTimeout(() => {
4677
4904
  try {
@@ -4680,7 +4907,7 @@ var MCPServer = class {
4680
4907
  } catch {
4681
4908
  logger.warn(`Telemetry Alert [ERR-03]: Tool execution hung (>30s) for '${name}'.`);
4682
4909
  }
4683
- }, 3e4);
4910
+ }, timeoutMs);
4684
4911
  timeoutTimer.unref();
4685
4912
  let response;
4686
4913
  try {
@@ -4689,7 +4916,8 @@ var MCPServer = class {
4689
4916
  if (timeoutTimer) clearTimeout(timeoutTimer);
4690
4917
  }
4691
4918
  this.contextGuard.recordCall(name);
4692
- const enriched = this.contextGuard.enrichResponse(name, response);
4919
+ let enriched = this.contextGuard.enrichResponse(name, response);
4920
+ if (collectExecutionMetrics && executionStartedAt && executionCpuStart && executionMemoryBefore) enriched = appendExecutionMetrics(enriched, buildExecutionMetrics(executionStartedAt, executionStartTime, timeoutMs, executionCpuStart, executionMemoryBefore));
4693
4921
  try {
4694
4922
  this.tokenBudget.recordToolCall(name, args, enriched);
4695
4923
  } catch (trackingError) {
@@ -4903,7 +5131,8 @@ async function main() {
4903
5131
  if (cleanup.removedFiles > 0) logger.info(`[artifacts] Startup cleanup removed ${cleanup.removedFiles} files (${cleanup.removedBytes} bytes)`);
4904
5132
  }
4905
5133
  logger.info("Creating MCP server instance...");
4906
- await initRegistry();
5134
+ const explicitProfile = (process.env.MCP_TOOL_PROFILE ?? "").trim().toLowerCase();
5135
+ await initRegistry(explicitProfile === "full" || explicitProfile === "workflow" || explicitProfile === "search" ? explicitProfile : "search");
4907
5136
  const server = new MCPServer(config);
4908
5137
  const stopArtifactRetentionScheduler = startArtifactRetentionScheduler();
4909
5138
  const recoveryWindowMs = Math.max(1e3, RUNTIME_ERROR_WINDOW_MS);