triflux 10.3.4 → 10.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. package/LICENSE +21 -21
  2. package/bin/tfx-doctor-tui.mjs +1 -1
  3. package/bin/tfx-doctor.mjs +6 -1
  4. package/bin/tfx-profile.mjs +1 -1
  5. package/bin/tfx-setup-tui.mjs +1 -1
  6. package/bin/tfx-setup.mjs +6 -1
  7. package/bin/triflux.mjs +2396 -1140
  8. package/hooks/agent-route-guard.mjs +12 -8
  9. package/hooks/cross-review-tracker.mjs +21 -8
  10. package/hooks/error-context.mjs +19 -7
  11. package/hooks/hook-adaptive-collector.mjs +18 -16
  12. package/hooks/hook-manager.mjs +93 -32
  13. package/hooks/hook-orchestrator.mjs +108 -24
  14. package/hooks/hook-registry.json +11 -0
  15. package/hooks/keyword-rules.json +6 -10
  16. package/hooks/lib/resolve-root.mjs +1 -1
  17. package/hooks/mcp-config-watcher.mjs +6 -2
  18. package/hooks/pipeline-stop.mjs +3 -6
  19. package/hooks/safety-guard.mjs +99 -28
  20. package/hooks/session-start-fast.mjs +143 -0
  21. package/hooks/subagent-verifier.mjs +5 -4
  22. package/hub/account-broker.mjs +256 -60
  23. package/hub/adaptive-diagnostic.mjs +75 -48
  24. package/hub/adaptive-inject.mjs +95 -57
  25. package/hub/adaptive-memory.mjs +156 -42
  26. package/hub/adaptive.mjs +60 -31
  27. package/hub/assign-callbacks.mjs +67 -30
  28. package/hub/bridge.mjs +0 -1
  29. package/hub/cli-adapter-base.mjs +200 -48
  30. package/hub/codex-adapter.mjs +76 -96
  31. package/hub/codex-compat.mjs +3 -3
  32. package/hub/codex-preflight.mjs +63 -37
  33. package/hub/delegator/contracts.mjs +19 -23
  34. package/hub/delegator/index.mjs +3 -3
  35. package/hub/delegator/service.mjs +88 -64
  36. package/hub/delegator/tool-definitions.mjs +5 -5
  37. package/hub/fullcycle.mjs +33 -17
  38. package/hub/gemini-adapter.mjs +69 -94
  39. package/hub/hitl.mjs +89 -30
  40. package/hub/intent.mjs +161 -38
  41. package/hub/lib/cache-guard.mjs +43 -17
  42. package/hub/lib/mcp-response-cache.mjs +66 -32
  43. package/hub/lib/memory-store.mjs +285 -111
  44. package/hub/lib/path-utils.mjs +35 -37
  45. package/hub/lib/process-utils.mjs +106 -37
  46. package/hub/lib/spawn-trace.mjs +527 -0
  47. package/hub/lib/ssh-command.mjs +34 -4
  48. package/hub/lib/ssh-retry.mjs +5 -1
  49. package/hub/lib/uuidv7.mjs +4 -3
  50. package/hub/memory-doctor.mjs +266 -106
  51. package/hub/middleware/request-logger.mjs +61 -34
  52. package/hub/paths.mjs +9 -9
  53. package/hub/pipeline/gates/confidence.mjs +34 -15
  54. package/hub/pipeline/gates/consensus.mjs +27 -15
  55. package/hub/pipeline/gates/index.mjs +7 -3
  56. package/hub/pipeline/gates/selfcheck.mjs +57 -19
  57. package/hub/pipeline/index.mjs +77 -42
  58. package/hub/pipeline/state.mjs +10 -10
  59. package/hub/pipeline/transitions.mjs +40 -23
  60. package/hub/platform.mjs +57 -48
  61. package/hub/promote-penalties.mjs +25 -7
  62. package/hub/quality/deslop.mjs +70 -49
  63. package/hub/research.mjs +32 -25
  64. package/hub/router.mjs +240 -107
  65. package/hub/routing/complexity.mjs +132 -29
  66. package/hub/routing/index.mjs +17 -12
  67. package/hub/routing/q-learning.mjs +76 -28
  68. package/hub/server.mjs +4 -4
  69. package/hub/session-fingerprint.mjs +126 -60
  70. package/hub/state.mjs +84 -43
  71. package/hub/store-adapter.mjs +59 -26
  72. package/hub/store.mjs +356 -153
  73. package/hub/team/agent-map.json +22 -7
  74. package/hub/team/ansi.mjs +186 -122
  75. package/hub/team/backend.mjs +28 -10
  76. package/hub/team/cli/commands/attach.mjs +29 -9
  77. package/hub/team/cli/commands/control.mjs +29 -8
  78. package/hub/team/cli/commands/debug.mjs +32 -11
  79. package/hub/team/cli/commands/focus.mjs +38 -11
  80. package/hub/team/cli/commands/interrupt.mjs +18 -6
  81. package/hub/team/cli/commands/kill.mjs +16 -5
  82. package/hub/team/cli/commands/list.mjs +11 -4
  83. package/hub/team/cli/commands/send.mjs +19 -6
  84. package/hub/team/cli/commands/start/index.mjs +154 -31
  85. package/hub/team/cli/commands/start/parse-args.mjs +38 -11
  86. package/hub/team/cli/commands/start/start-headless.mjs +112 -36
  87. package/hub/team/cli/commands/start/start-in-process.mjs +12 -2
  88. package/hub/team/cli/commands/start/start-mux.mjs +70 -21
  89. package/hub/team/cli/commands/start/start-wt.mjs +29 -12
  90. package/hub/team/cli/commands/status.mjs +43 -14
  91. package/hub/team/cli/commands/stop.mjs +11 -4
  92. package/hub/team/cli/commands/task.mjs +8 -3
  93. package/hub/team/cli/commands/tasks.mjs +1 -1
  94. package/hub/team/cli/index.mjs +2 -2
  95. package/hub/team/cli/manifest.mjs +38 -8
  96. package/hub/team/cli/render.mjs +30 -8
  97. package/hub/team/cli/services/attach-fallback.mjs +31 -11
  98. package/hub/team/cli/services/hub-client.mjs +42 -14
  99. package/hub/team/cli/services/member-selector.mjs +11 -4
  100. package/hub/team/cli/services/native-control.mjs +48 -21
  101. package/hub/team/cli/services/runtime-mode.mjs +2 -1
  102. package/hub/team/cli/services/state-store.mjs +25 -8
  103. package/hub/team/cli/services/task-model.mjs +16 -6
  104. package/hub/team/conductor-mesh-bridge.mjs +24 -23
  105. package/hub/team/conductor.mjs +8 -4
  106. package/hub/team/dashboard-anchor.mjs +4 -5
  107. package/hub/team/dashboard-layout.mjs +3 -1
  108. package/hub/team/dashboard-open.mjs +41 -21
  109. package/hub/team/dashboard.mjs +76 -28
  110. package/hub/team/event-log.mjs +18 -10
  111. package/hub/team/handoff.mjs +31 -15
  112. package/hub/team/headless.mjs +2 -1
  113. package/hub/team/health-probe.mjs +69 -54
  114. package/hub/team/launcher-template.mjs +16 -13
  115. package/hub/team/native-supervisor.mjs +65 -21
  116. package/hub/team/native.mjs +74 -35
  117. package/hub/team/nativeProxy.mjs +184 -113
  118. package/hub/team/notify.mjs +119 -76
  119. package/hub/team/orchestrator.mjs +9 -4
  120. package/hub/team/pane.mjs +12 -7
  121. package/hub/team/process-cleanup.mjs +25 -16
  122. package/hub/team/psmux.mjs +491 -201
  123. package/hub/team/remote-probe.mjs +68 -52
  124. package/hub/team/remote-session.mjs +117 -59
  125. package/hub/team/remote-watcher.mjs +61 -33
  126. package/hub/team/routing.mjs +51 -25
  127. package/hub/team/runtime-strategy.mjs +3 -1
  128. package/hub/team/session.mjs +98 -34
  129. package/hub/team/staleState.mjs +72 -30
  130. package/hub/team/swarm-locks.mjs +15 -13
  131. package/hub/team/swarm-planner.mjs +32 -21
  132. package/hub/team/swarm-reconciler.mjs +48 -23
  133. package/hub/team/tui-lite.mjs +266 -68
  134. package/hub/team/tui-remote-adapter.mjs +14 -10
  135. package/hub/team/tui-viewer.mjs +99 -43
  136. package/hub/team/tui.mjs +708 -271
  137. package/hub/team/worktree-lifecycle.mjs +152 -58
  138. package/hub/team/wt-manager.mjs +24 -14
  139. package/hub/token-mode.mjs +71 -71
  140. package/hub/tray.mjs +66 -23
  141. package/hub/workers/claude-worker.mjs +162 -118
  142. package/hub/workers/codex-mcp.mjs +192 -141
  143. package/hub/workers/delegator-mcp.mjs +507 -333
  144. package/hub/workers/factory.mjs +8 -8
  145. package/hub/workers/gemini-worker.mjs +115 -84
  146. package/hub/workers/interface.mjs +6 -1
  147. package/hub/workers/worker-utils.mjs +21 -14
  148. package/hud/colors.mjs +27 -9
  149. package/hud/constants.mjs +162 -26
  150. package/hud/context-monitor.mjs +82 -41
  151. package/hud/hud-qos-status.mjs +129 -49
  152. package/hud/mission-board.mjs +6 -3
  153. package/hud/providers/claude.mjs +226 -115
  154. package/hud/providers/codex.mjs +62 -22
  155. package/hud/providers/gemini.mjs +168 -56
  156. package/hud/renderers.mjs +384 -119
  157. package/hud/terminal.mjs +101 -31
  158. package/hud/utils.mjs +78 -38
  159. package/mesh/index.mjs +11 -5
  160. package/mesh/mesh-budget.mjs +18 -9
  161. package/mesh/mesh-heartbeat.mjs +1 -1
  162. package/mesh/mesh-queue.mjs +3 -5
  163. package/mesh/mesh-router.mjs +5 -4
  164. package/package.json +2 -1
  165. package/scripts/__tests__/gen-skill-docs.test.mjs +36 -7
  166. package/scripts/__tests__/keyword-detector.test.mjs +77 -28
  167. package/scripts/__tests__/mcp-guard-engine.test.mjs +58 -20
  168. package/scripts/__tests__/remote-spawn-transfer.test.mjs +30 -19
  169. package/scripts/__tests__/remote-spawn.test.mjs +10 -4
  170. package/scripts/__tests__/session-start-fast.test.mjs +36 -0
  171. package/scripts/__tests__/skill-template.test.mjs +98 -50
  172. package/scripts/__tests__/smoke.test.mjs +1 -1
  173. package/scripts/__tests__/spawn-trace.test.mjs +102 -0
  174. package/scripts/__tests__/tfx-doctor-diagnose.test.mjs +48 -0
  175. package/scripts/cache-doctor.mjs +11 -4
  176. package/scripts/cache-warmup.mjs +96 -37
  177. package/scripts/claudemd-sync.mjs +27 -17
  178. package/scripts/codex-gateway-preflight.mjs +52 -37
  179. package/scripts/codex-mcp-gateway-sync.mjs +59 -39
  180. package/scripts/completions/tfx.bash +47 -47
  181. package/scripts/completions/tfx.fish +44 -44
  182. package/scripts/completions/tfx.zsh +83 -83
  183. package/scripts/config-audit.mjs +232 -0
  184. package/scripts/convert-to-tmpl.mjs +54 -0
  185. package/scripts/cross-review-gate.mjs +35 -12
  186. package/scripts/cross-review-tracker.mjs +21 -8
  187. package/scripts/demo.mjs +35 -17
  188. package/scripts/doctor-diagnose.mjs +284 -0
  189. package/scripts/gen-skill-docs.mjs +7 -2
  190. package/scripts/gen-skill-manifest.mjs +2 -1
  191. package/scripts/headless-guard.mjs +86 -48
  192. package/scripts/hub-ensure.mjs +45 -26
  193. package/scripts/keyword-detector.mjs +41 -20
  194. package/scripts/keyword-rules-expander.mjs +47 -30
  195. package/scripts/lib/claudemd-scanner.mjs +6 -1
  196. package/scripts/lib/context.mjs +3 -3
  197. package/scripts/lib/cross-review-utils.mjs +6 -3
  198. package/scripts/lib/env-probe.mjs +47 -28
  199. package/scripts/lib/gemini-profiles.mjs +44 -10
  200. package/scripts/lib/handoff.mjs +33 -17
  201. package/scripts/lib/hook-utils.mjs +8 -6
  202. package/scripts/lib/keyword-rules.mjs +43 -19
  203. package/scripts/lib/logger.mjs +24 -24
  204. package/scripts/lib/mcp-filter.mjs +377 -239
  205. package/scripts/lib/mcp-guard-engine.mjs +194 -79
  206. package/scripts/lib/mcp-manifest.mjs +23 -13
  207. package/scripts/lib/mcp-server-catalog.mjs +300 -63
  208. package/scripts/lib/psmux-info.mjs +11 -6
  209. package/scripts/lib/remote-spawn-transfer.mjs +44 -14
  210. package/scripts/lib/skill-template.mjs +30 -7
  211. package/scripts/mcp-check.mjs +58 -39
  212. package/scripts/mcp-gateway-config.mjs +83 -39
  213. package/scripts/mcp-gateway-ensure.mjs +43 -35
  214. package/scripts/mcp-gateway-integration-test.mjs +70 -58
  215. package/scripts/mcp-gateway-start.mjs +126 -60
  216. package/scripts/mcp-gateway-verify.mjs +24 -22
  217. package/scripts/mcp-safety-guard.mjs +44 -11
  218. package/scripts/notion-read.mjs +199 -84
  219. package/scripts/pack.mjs +94 -89
  220. package/scripts/preflight-cache.mjs +27 -10
  221. package/scripts/preinstall.mjs +42 -13
  222. package/scripts/remote-spawn.mjs +309 -94
  223. package/scripts/run.cjs +8 -5
  224. package/scripts/session-spawn-helper.mjs +130 -39
  225. package/scripts/session-stale-cleanup.mjs +123 -0
  226. package/scripts/setup.mjs +941 -492
  227. package/scripts/test-lock.mjs +20 -7
  228. package/scripts/test-tfx-route-no-claude-native.mjs +16 -12
  229. package/scripts/tfx-batch-stats.mjs +32 -11
  230. package/scripts/tfx-gate-activate.mjs +11 -4
  231. package/scripts/tfx-route-post.mjs +87 -20
  232. package/scripts/tfx-route-worker.mjs +57 -51
  233. package/scripts/tfx-route.sh +41 -124
  234. package/scripts/tmp-cleanup.mjs +21 -7
  235. package/scripts/token-snapshot.mjs +204 -85
  236. package/skills/.omc/state/agent-replay-8f0e10a9-9693-4410-96f5-a6b07e8ed995.jsonl +1 -0
  237. package/skills/.omc/state/idle-notif-cooldown.json +3 -0
  238. package/skills/.omc/state/last-tool-error.json +7 -0
  239. package/skills/.omc/state/subagent-tracking.json +7 -0
  240. package/skills/_templates/base.md +1 -6
  241. package/skills/merge-worktree/SKILL.md.tmpl +144 -0
  242. package/skills/shared/telemetry-segment.md +6 -0
  243. package/skills/star-prompt/SKILL.md.tmpl +222 -0
  244. package/skills/tfx-analysis/SKILL.md.tmpl +107 -0
  245. package/skills/tfx-analysis/skill.json +1 -6
  246. package/skills/tfx-auto/SKILL.md +1 -0
  247. package/skills/tfx-auto-codex/SKILL.md.tmpl +106 -0
  248. package/skills/tfx-auto-codex/skill.json +1 -3
  249. package/skills/tfx-autopilot/SKILL.md.tmpl +116 -0
  250. package/skills/tfx-autopilot/skill.json +1 -5
  251. package/skills/tfx-autoresearch/SKILL.md.tmpl +136 -0
  252. package/skills/tfx-autoroute/SKILL.md.tmpl +189 -0
  253. package/skills/tfx-autoroute/skill.json +1 -7
  254. package/skills/tfx-codex/SKILL.md +1 -0
  255. package/skills/tfx-codex/skill.json +1 -3
  256. package/skills/tfx-codex-swarm/SKILL.md.tmpl +16 -0
  257. package/skills/tfx-codex-swarm/evals/evals.json +1 -1
  258. package/skills/tfx-codex-swarm/skill.json +1 -4
  259. package/skills/tfx-codex-swarm-workspace/iteration-1/benchmark.json +54 -12
  260. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/with_skill/grading.json +35 -7
  261. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/without_skill/grading.json +35 -7
  262. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/with_skill/grading.json +25 -5
  263. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/without_skill/grading.json +25 -5
  264. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/with_skill/grading.json +20 -4
  265. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/without_skill/grading.json +16 -4
  266. package/skills/tfx-consensus/SKILL.md.tmpl +146 -0
  267. package/skills/tfx-debate/SKILL.md.tmpl +192 -0
  268. package/skills/tfx-debate/skill.json +1 -7
  269. package/skills/tfx-deep-analysis/SKILL.md.tmpl +228 -0
  270. package/skills/tfx-deep-analysis/skill.json +1 -5
  271. package/skills/tfx-deep-interview/SKILL.md.tmpl +203 -0
  272. package/skills/tfx-deep-plan/SKILL.md.tmpl +282 -0
  273. package/skills/tfx-deep-qa/SKILL.md.tmpl +165 -0
  274. package/skills/tfx-deep-qa/skill.json +1 -6
  275. package/skills/tfx-deep-research/SKILL.md.tmpl +217 -0
  276. package/skills/tfx-deep-review/SKILL.md.tmpl +179 -0
  277. package/skills/tfx-doctor/SKILL.md +21 -0
  278. package/skills/tfx-doctor/SKILL.md.tmpl +172 -0
  279. package/skills/tfx-doctor/skill.json +1 -3
  280. package/skills/tfx-find/SKILL.md +1 -0
  281. package/skills/tfx-forge/SKILL.md.tmpl +187 -0
  282. package/skills/tfx-fullcycle/SKILL.md.tmpl +286 -0
  283. package/skills/tfx-fullcycle/skill.json +1 -6
  284. package/skills/tfx-gemini/SKILL.md.tmpl +91 -0
  285. package/skills/tfx-gemini/skill.json +1 -3
  286. package/skills/tfx-hooks/SKILL.md.tmpl +216 -0
  287. package/skills/tfx-hooks/skill.json +1 -3
  288. package/skills/tfx-hub/SKILL.md.tmpl +212 -0
  289. package/skills/tfx-hub/skill.json +1 -3
  290. package/skills/tfx-index/SKILL.md +1 -0
  291. package/skills/tfx-index/skill.json +1 -6
  292. package/skills/tfx-interview/SKILL.md.tmpl +285 -0
  293. package/skills/tfx-multi/SKILL.md.tmpl +183 -0
  294. package/skills/tfx-multi/skill.json +1 -3
  295. package/skills/tfx-panel/SKILL.md.tmpl +189 -0
  296. package/skills/tfx-panel/skill.json +1 -7
  297. package/skills/tfx-persist/SKILL.md.tmpl +270 -0
  298. package/skills/tfx-persist/skill.json +1 -7
  299. package/skills/tfx-plan/SKILL.md +1 -0
  300. package/skills/tfx-plan/skill.json +1 -6
  301. package/skills/tfx-profile/SKILL.md.tmpl +239 -0
  302. package/skills/tfx-profile/skill.json +1 -3
  303. package/skills/tfx-prune/SKILL.md.tmpl +200 -0
  304. package/skills/tfx-prune/skill.json +1 -7
  305. package/skills/tfx-psmux-rules/SKILL.md.tmpl +326 -0
  306. package/skills/tfx-psmux-rules/skill.json +1 -4
  307. package/skills/tfx-qa/SKILL.md +1 -0
  308. package/skills/tfx-qa/skill.json +1 -6
  309. package/skills/tfx-ralph/SKILL.md.tmpl +28 -0
  310. package/skills/tfx-ralph/skill.json +1 -4
  311. package/skills/tfx-remote-setup/SKILL.md.tmpl +576 -0
  312. package/skills/tfx-remote-setup/skill.json +1 -3
  313. package/skills/tfx-remote-spawn/SKILL.md.tmpl +263 -0
  314. package/skills/tfx-remote-spawn/references/hosts.json +16 -0
  315. package/skills/tfx-remote-spawn/skill.json +1 -4
  316. package/skills/tfx-research/SKILL.md +1 -0
  317. package/skills/tfx-review/SKILL.md +1 -0
  318. package/skills/tfx-review/skill.json +1 -6
  319. package/skills/tfx-setup/SKILL.md.tmpl +504 -0
  320. package/skills/tfx-setup/skill.json +1 -3
  321. package/skills/tfx-swarm/SKILL.md +22 -0
  322. package/skills/tfx-swarm/SKILL.md.tmpl +218 -0
  323. package/tui/codex-profile.mjs +88 -33
  324. package/tui/core.mjs +45 -15
  325. package/tui/doctor.mjs +75 -28
  326. package/tui/gemini-profile.mjs +74 -29
  327. package/tui/monitor-data.mjs +8 -4
  328. package/tui/monitor.mjs +71 -27
  329. package/tui/setup.mjs +133 -42
@@ -2,27 +2,27 @@
2
2
  // mcp-gateway-integration-test.mjs — P0 integration test for MCP Gateway
3
3
  // Usage: node scripts/mcp-gateway-integration-test.mjs
4
4
 
5
- import { execSync } from 'node:child_process';
6
- import { join, dirname } from 'node:path';
7
- import { fileURLToPath } from 'node:url';
5
+ import { execSync } from "node:child_process";
6
+ import { dirname, join } from "node:path";
7
+ import { fileURLToPath } from "node:url";
8
8
 
9
9
  const SCRIPTS_DIR = dirname(fileURLToPath(import.meta.url));
10
- const START_SCRIPT = join(SCRIPTS_DIR, 'mcp-gateway-start.mjs');
11
- const CONFIG_SCRIPT = join(SCRIPTS_DIR, 'mcp-gateway-config.mjs');
10
+ const START_SCRIPT = join(SCRIPTS_DIR, "mcp-gateway-start.mjs");
11
+ const CONFIG_SCRIPT = join(SCRIPTS_DIR, "mcp-gateway-config.mjs");
12
12
 
13
13
  const HEALTH_TIMEOUT_MS = 3000;
14
14
  const STARTUP_WAIT_MS = 12000;
15
15
  const POLL_INTERVAL_MS = 500;
16
16
 
17
17
  const SERVERS = [
18
- { name: 'context7', port: 8100 },
19
- { name: 'brave-search', port: 8101 },
20
- { name: 'exa', port: 8102 },
21
- { name: 'tavily', port: 8103 },
22
- { name: 'jira', port: 8104 },
23
- { name: 'serena', port: 8105 },
24
- { name: 'notion', port: 8106 },
25
- { name: 'notion-guest', port: 8107 },
18
+ { name: "context7", port: 8100 },
19
+ { name: "brave-search", port: 8101 },
20
+ { name: "exa", port: 8102 },
21
+ { name: "tavily", port: 8103 },
22
+ { name: "jira", port: 8104 },
23
+ { name: "serena", port: 8105 },
24
+ { name: "notion", port: 8106 },
25
+ { name: "notion-guest", port: 8107 },
26
26
  ];
27
27
 
28
28
  // ── utilities ──
@@ -43,10 +43,10 @@ async function checkHealth(port) {
43
43
  }
44
44
 
45
45
  function runScript(scriptPath, ...args) {
46
- execSync(`node "${scriptPath}" ${args.join(' ')}`, {
47
- stdio: 'inherit',
46
+ execSync(`node "${scriptPath}" ${args.join(" ")}`, {
47
+ stdio: "inherit",
48
48
  timeout: 30000,
49
- env: { ...process.env, MSYS_NO_PATHCONV: '1' },
49
+ env: { ...process.env, MSYS_NO_PATHCONV: "1" },
50
50
  });
51
51
  }
52
52
 
@@ -57,10 +57,10 @@ function countSupergateways() {
57
57
  `$procs = Get-CimInstance Win32_Process -Filter "Name='node.exe' OR Name='cmd.exe'"`,
58
58
  `$hits = $procs | Where-Object { $_.CommandLine -match 'supergateway' }`,
59
59
  `Write-Output $hits.Count`,
60
- ].join('\n');
60
+ ].join("\n");
61
61
  const out = execSync(
62
- `powershell -NoProfile -Command "${ps1.replace(/\n/g, '; ')}"`,
63
- { encoding: 'utf8', timeout: 10000, stdio: ['pipe', 'pipe', 'ignore'] },
62
+ `powershell -NoProfile -Command "${ps1.replace(/\n/g, "; ")}"`,
63
+ { encoding: "utf8", timeout: 10000, stdio: ["pipe", "pipe", "ignore"] },
64
64
  );
65
65
  return parseInt(out.trim(), 10) || 0;
66
66
  } catch {
@@ -80,7 +80,7 @@ function pass(label) {
80
80
  passed++;
81
81
  }
82
82
 
83
- function fail(label, detail = '') {
83
+ function fail(label, detail = "") {
84
84
  const msg = detail ? `${label} — ${detail}` : label;
85
85
  console.log(` [FAIL] ${msg}`);
86
86
  results.push({ label, ok: false, detail });
@@ -88,45 +88,45 @@ function fail(label, detail = '') {
88
88
  }
89
89
 
90
90
  function printSummary() {
91
- console.log('\n' + '='.repeat(56));
92
- console.log('Integration Test Summary');
93
- console.log('='.repeat(56));
91
+ console.log("\n" + "=".repeat(56));
92
+ console.log("Integration Test Summary");
93
+ console.log("=".repeat(56));
94
94
  for (const r of results) {
95
- const mark = r.ok ? '\u2713' : '\u2717';
96
- const detail = r.detail ? ` (${r.detail})` : '';
95
+ const mark = r.ok ? "\u2713" : "\u2717";
96
+ const detail = r.detail ? ` (${r.detail})` : "";
97
97
  console.log(` ${mark} ${r.label}${detail}`);
98
98
  }
99
- console.log('='.repeat(56));
99
+ console.log("=".repeat(56));
100
100
  const total = passed + failed;
101
101
  console.log(`Result: ${passed}/${total} passed, ${failed} failed`);
102
102
  if (failed > 0) {
103
- console.log('\n[FAIL] Integration test FAILED');
103
+ console.log("\n[FAIL] Integration test FAILED");
104
104
  process.exitCode = 1;
105
105
  } else {
106
- console.log('\n[PASS] Integration test PASSED');
106
+ console.log("\n[PASS] Integration test PASSED");
107
107
  }
108
108
  }
109
109
 
110
110
  // ── main ──
111
111
 
112
112
  async function main() {
113
- console.log('\nMCP Gateway Integration Test');
114
- console.log('='.repeat(56));
113
+ console.log("\nMCP Gateway Integration Test");
114
+ console.log("=".repeat(56));
115
115
 
116
116
  // STEP 1: Start gateways
117
- console.log('\n[STEP 1] Starting gateways...');
117
+ console.log("\n[STEP 1] Starting gateways...");
118
118
  try {
119
119
  runScript(START_SCRIPT);
120
- pass('Gateway start script ran without error');
120
+ pass("Gateway start script ran without error");
121
121
  } catch (err) {
122
- fail('Gateway start script', err.message);
123
- console.log('\n[ABORT] Cannot continue without gateways running');
122
+ fail("Gateway start script", err.message);
123
+ console.log("\n[ABORT] Cannot continue without gateways running");
124
124
  printSummary();
125
125
  return;
126
126
  }
127
127
 
128
128
  // STEP 2: Wait for health checks to pass (up to 12s)
129
- console.log('\n[STEP 2] Waiting for health checks (up to 12s)...');
129
+ console.log("\n[STEP 2] Waiting for health checks (up to 12s)...");
130
130
  const deadline = Date.now() + STARTUP_WAIT_MS;
131
131
  const pending = new Set(SERVERS.map((s) => s.port));
132
132
 
@@ -147,35 +147,42 @@ async function main() {
147
147
  healthOk++;
148
148
  } else {
149
149
  // Servers that stay down are expected when env vars (API keys) are missing
150
- console.log(` [skip] ${srv.name.padEnd(16)} :${srv.port} (not running — likely missing env)`);
150
+ console.log(
151
+ ` [skip] ${srv.name.padEnd(16)} :${srv.port} (not running — likely missing env)`,
152
+ );
151
153
  healthSkipped++;
152
154
  }
153
155
  }
154
156
 
155
157
  if (healthOk === 0) {
156
- fail('Health check — no servers responded', `0/${SERVERS.length} up`);
158
+ fail("Health check — no servers responded", `0/${SERVERS.length} up`);
157
159
  } else {
158
- pass(`Health check — ${healthOk} server(s) responding (${healthSkipped} skipped)`);
160
+ pass(
161
+ `Health check — ${healthOk} server(s) responding (${healthSkipped} skipped)`,
162
+ );
159
163
  }
160
164
 
161
165
  // STEP 3: Switch Claude Code config to SSE
162
- console.log('\n[STEP 3] Switching Claude Code config to SSE mode...');
166
+ console.log("\n[STEP 3] Switching Claude Code config to SSE mode...");
163
167
  try {
164
- runScript(CONFIG_SCRIPT, '--enable');
165
- pass('Config switch to SSE (--enable)');
168
+ runScript(CONFIG_SCRIPT, "--enable");
169
+ pass("Config switch to SSE (--enable)");
166
170
  } catch (err) {
167
- fail('Config switch to SSE', err.message);
171
+ fail("Config switch to SSE", err.message);
168
172
  }
169
173
 
170
174
  // STEP 4: Verify SSE endpoints respond on each active port
171
- console.log('\n[STEP 4] Verifying SSE endpoints (/healthz)...');
175
+ console.log("\n[STEP 4] Verifying SSE endpoints (/healthz)...");
172
176
  const sseResults = await Promise.allSettled(
173
- SERVERS.map(async (srv) => ({ ...srv, alive: await checkHealth(srv.port) })),
177
+ SERVERS.map(async (srv) => ({
178
+ ...srv,
179
+ alive: await checkHealth(srv.port),
180
+ })),
174
181
  );
175
182
 
176
183
  let sseOk = 0;
177
184
  for (const r of sseResults) {
178
- if (r.status !== 'fulfilled') continue;
185
+ if (r.status !== "fulfilled") continue;
179
186
  const { name, port, alive } = r.value;
180
187
  if (alive) {
181
188
  console.log(` [ok] ${name.padEnd(16)} :${port}`);
@@ -186,40 +193,45 @@ async function main() {
186
193
  }
187
194
 
188
195
  if (sseOk === 0 && healthOk > 0) {
189
- fail('SSE endpoint verification — servers went down after config switch');
196
+ fail("SSE endpoint verification — servers went down after config switch");
190
197
  } else if (sseOk > 0) {
191
198
  pass(`SSE endpoint verification — ${sseOk} endpoint(s) healthy`);
192
199
  } else {
193
- pass('SSE endpoint verification — no servers running (all skipped due to missing env)');
200
+ pass(
201
+ "SSE endpoint verification — no servers running (all skipped due to missing env)",
202
+ );
194
203
  }
195
204
 
196
205
  // STEP 5: Restore stdio config
197
- console.log('\n[STEP 5] Restoring stdio config...');
206
+ console.log("\n[STEP 5] Restoring stdio config...");
198
207
  try {
199
- runScript(CONFIG_SCRIPT, '--disable');
200
- pass('Config restore to stdio (--disable)');
208
+ runScript(CONFIG_SCRIPT, "--disable");
209
+ pass("Config restore to stdio (--disable)");
201
210
  } catch (err) {
202
- fail('Config restore to stdio', err.message);
211
+ fail("Config restore to stdio", err.message);
203
212
  }
204
213
 
205
214
  // STEP 6: Stop gateways
206
- console.log('\n[STEP 6] Stopping gateways...');
215
+ console.log("\n[STEP 6] Stopping gateways...");
207
216
  try {
208
- runScript(START_SCRIPT, '--stop');
209
- pass('Gateway stop script ran without error');
217
+ runScript(START_SCRIPT, "--stop");
218
+ pass("Gateway stop script ran without error");
210
219
  } catch (err) {
211
- fail('Gateway stop script', err.message);
220
+ fail("Gateway stop script", err.message);
212
221
  }
213
222
 
214
223
  // STEP 7: Orphan check — brief settle, then verify no supergateway processes remain
215
- console.log('\n[STEP 7] Checking for orphan supergateway processes...');
224
+ console.log("\n[STEP 7] Checking for orphan supergateway processes...");
216
225
  await sleep(2000);
217
226
 
218
227
  const orphanCount = countSupergateways();
219
228
  if (orphanCount === 0) {
220
- pass('No orphan supergateway processes (WMI/tasklist clean)');
229
+ pass("No orphan supergateway processes (WMI/tasklist clean)");
221
230
  } else {
222
- fail('Orphan processes found', `${orphanCount} supergateway process(es) still running`);
231
+ fail(
232
+ "Orphan processes found",
233
+ `${orphanCount} supergateway process(es) still running`,
234
+ );
223
235
  }
224
236
 
225
237
  printSummary();
@@ -4,27 +4,67 @@
4
4
  // node mcp-gateway-start.mjs --stop # 중지
5
5
  // node mcp-gateway-start.mjs --status # 상태 확인
6
6
 
7
- import { execSync } from 'node:child_process';
8
- import { existsSync, readFileSync, writeFileSync, unlinkSync } from 'node:fs';
9
- import { join } from 'node:path';
10
- import { tmpdir } from 'node:os';
11
- import { createConnection } from 'node:net';
12
- import { isServerEnabled } from './lib/mcp-manifest.mjs';
13
-
14
- const PID_FILE = join(tmpdir(), 'tfx-gateway-pids.json');
7
+ import { execSync } from "node:child_process";
8
+ import { existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
9
+ import { createConnection } from "node:net";
10
+ import { tmpdir } from "node:os";
11
+ import { join } from "node:path";
12
+ import { isServerEnabled } from "./lib/mcp-manifest.mjs";
13
+
14
+ const PID_FILE = join(tmpdir(), "tfx-gateway-pids.json");
15
15
  const STARTUP_WAIT_MS = 8000;
16
16
  const POLL_INTERVAL_MS = 500;
17
17
  const HEALTH_TIMEOUT_MS = 3000;
18
18
 
19
19
  const SERVERS = [
20
- { name: 'context7', port: 8100, cmd: 'npx -y @upstash/context7-mcp@latest', envVars: [] },
21
- { name: 'brave-search', port: 8101, cmd: 'npx -y @brave/brave-search-mcp-server', envVars: ['BRAVE_API_KEY'] },
22
- { name: 'exa', port: 8102, cmd: 'npx -y exa-mcp-server', envVars: ['EXA_API_KEY'] },
23
- { name: 'tavily', port: 8103, cmd: 'npx -y tavily-mcp@latest', envVars: ['TAVILY_API_KEY'] },
24
- { name: 'jira', port: 8104, cmd: 'npx -y mcp-jira-cloud@latest', envVars: ['JIRA_API_TOKEN', 'JIRA_EMAIL', 'JIRA_INSTANCE_URL'] },
25
- { name: 'serena', port: 8105, cmd: 'uvx --from git+https://github.com/oraios/serena serena start-mcp-server', envVars: [] },
26
- { name: 'notion', port: 8106, cmd: 'npx -y @notionhq/notion-mcp-server', envVars: ['NOTION_TOKEN'] },
27
- { name: 'notion-guest', port: 8107, cmd: 'npx -y @notionhq/notion-mcp-server', envVars: ['NOTION_TOKEN'] },
20
+ {
21
+ name: "context7",
22
+ port: 8100,
23
+ cmd: "npx -y @upstash/context7-mcp@latest",
24
+ envVars: [],
25
+ },
26
+ {
27
+ name: "brave-search",
28
+ port: 8101,
29
+ cmd: "npx -y @brave/brave-search-mcp-server",
30
+ envVars: ["BRAVE_API_KEY"],
31
+ },
32
+ {
33
+ name: "exa",
34
+ port: 8102,
35
+ cmd: "npx -y exa-mcp-server",
36
+ envVars: ["EXA_API_KEY"],
37
+ },
38
+ {
39
+ name: "tavily",
40
+ port: 8103,
41
+ cmd: "npx -y tavily-mcp@latest",
42
+ envVars: ["TAVILY_API_KEY"],
43
+ },
44
+ {
45
+ name: "jira",
46
+ port: 8104,
47
+ cmd: "npx -y mcp-jira-cloud@latest",
48
+ envVars: ["JIRA_API_TOKEN", "JIRA_EMAIL", "JIRA_INSTANCE_URL"],
49
+ },
50
+ {
51
+ name: "serena",
52
+ port: 8105,
53
+ cmd: "uvx --from git+https://github.com/oraios/serena serena start-mcp-server",
54
+ envVars: [],
55
+ },
56
+ {
57
+ name: "notion",
58
+ port: 8106,
59
+ cmd: "npx -y @notionhq/notion-mcp-server",
60
+ envVars: ["NOTION_TOKEN"],
61
+ },
62
+ {
63
+ name: "notion-guest",
64
+ port: 8107,
65
+ cmd: "npx -y @notionhq/notion-mcp-server",
66
+ envVars: ["NOTION_TOKEN"],
67
+ },
28
68
  ];
29
69
 
30
70
  export { SERVERS };
@@ -33,10 +73,16 @@ export { SERVERS };
33
73
 
34
74
  function isPortInUse(port) {
35
75
  return new Promise((resolve) => {
36
- const sock = createConnection({ host: '127.0.0.1', port });
37
- sock.once('connect', () => { sock.destroy(); resolve(true); });
38
- sock.once('error', () => resolve(false));
39
- sock.setTimeout(1000, () => { sock.destroy(); resolve(false); });
76
+ const sock = createConnection({ host: "127.0.0.1", port });
77
+ sock.once("connect", () => {
78
+ sock.destroy();
79
+ resolve(true);
80
+ });
81
+ sock.once("error", () => resolve(false));
82
+ sock.setTimeout(1000, () => {
83
+ sock.destroy();
84
+ resolve(false);
85
+ });
40
86
  });
41
87
  }
42
88
 
@@ -65,31 +111,38 @@ function spawnGateway(srv) {
65
111
 
66
112
  // PowerShell Start-Process: Windows Job Object에서 벗어나 부모 종료 후 생존
67
113
  execSync(
68
- `powershell -NoProfile -Command "Start-Process -WindowStyle Hidden -FilePath cmd.exe -ArgumentList '/c','${cmdFile.replaceAll("'", "''")}'"`
69
- , { stdio: 'ignore', timeout: 10000 });
114
+ `powershell -NoProfile -Command "Start-Process -WindowStyle Hidden -FilePath cmd.exe -ArgumentList '/c','${cmdFile.replaceAll("'", "''")}'"`,
115
+ { stdio: "ignore", timeout: 10000 },
116
+ );
70
117
  }
71
118
 
72
119
  function ensureFirewallRule() {
73
- if (process.platform !== 'win32') return;
74
- const ports = SERVERS.map((s) => s.port).join(',');
75
- const ruleName = 'TFX-MCP-Gateway-Block-External';
120
+ if (process.platform !== "win32") return;
121
+ const ports = SERVERS.map((s) => s.port).join(",");
122
+ const ruleName = "TFX-MCP-Gateway-Block-External";
76
123
  try {
77
124
  // 기존 규칙 있으면 스킵
78
125
  const check = execSync(
79
126
  `netsh advfirewall firewall show rule name="${ruleName}" 2>&1`,
80
- { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'], timeout: 5000 },
127
+ { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"], timeout: 5000 },
81
128
  );
82
129
  if (check.includes(ruleName)) return;
83
- } catch { /* 규칙 없음 — 생성 */ }
130
+ } catch {
131
+ /* 규칙 없음 — 생성 */
132
+ }
84
133
 
85
134
  try {
86
135
  execSync(
87
136
  `netsh advfirewall firewall add rule name="${ruleName}" dir=in action=block protocol=tcp localport=${ports} remoteip=any profile=any`,
88
- { stdio: 'ignore', timeout: 5000 },
137
+ { stdio: "ignore", timeout: 5000 },
138
+ );
139
+ console.log(
140
+ `[SEC] Firewall rule added: block external access to ports ${ports}`,
89
141
  );
90
- console.log(`[SEC] Firewall rule added: block external access to ports ${ports}`);
91
142
  } catch {
92
- console.log(`[SEC] WARNING: Could not add firewall rule — run as admin or manually block ports ${ports}`);
143
+ console.log(
144
+ `[SEC] WARNING: Could not add firewall rule — run as admin or manually block ports ${ports}`,
145
+ );
93
146
  }
94
147
  }
95
148
 
@@ -113,7 +166,9 @@ async function startAll() {
113
166
  // 필수 환경변수 체크
114
167
  const missing = srv.envVars.filter((k) => !process.env[k]);
115
168
  if (missing.length > 0) {
116
- console.log(`[WARN] ${srv.name} skipped — missing env: ${missing.join(', ')}`);
169
+ console.log(
170
+ `[WARN] ${srv.name} skipped — missing env: ${missing.join(", ")}`,
171
+ );
117
172
  continue;
118
173
  }
119
174
 
@@ -123,7 +178,7 @@ async function startAll() {
123
178
  }
124
179
 
125
180
  if (launched.length === 0) {
126
- console.log('\n[gateway] No servers started (all running or skipped)');
181
+ console.log("\n[gateway] No servers started (all running or skipped)");
127
182
  return;
128
183
  }
129
184
 
@@ -140,22 +195,27 @@ async function startAll() {
140
195
  }
141
196
 
142
197
  // 결과 출력
143
- console.log('\nHealth Check');
144
- console.log('='.repeat(50));
198
+ console.log("\nHealth Check");
199
+ console.log("=".repeat(50));
145
200
  const pidEntries = [];
146
201
  for (const srv of launched) {
147
202
  const healthy = !pending.has(srv.port);
148
- const mark = healthy ? '\u2713' : '\u2717';
149
- const status = healthy ? 'ok' : 'down';
203
+ const mark = healthy ? "\u2713" : "\u2717";
204
+ const status = healthy ? "ok" : "down";
150
205
  console.log(` ${srv.name.padEnd(16)} :${srv.port} ${mark} ${status}`);
151
206
  if (healthy) pidEntries.push({ name: srv.name, port: srv.port });
152
207
  }
153
208
 
154
209
  // PID 파일 대신 포트 매니페스트 저장 (프로세스 찾기는 포트 기반)
155
210
  const existing = loadManifest();
156
- const merged = [...existing.filter((e) => !pidEntries.some((p) => p.port === e.port)), ...pidEntries];
211
+ const merged = [
212
+ ...existing.filter((e) => !pidEntries.some((p) => p.port === e.port)),
213
+ ...pidEntries,
214
+ ];
157
215
  writeFileSync(PID_FILE, JSON.stringify(merged, null, 2));
158
- console.log(`\n[gateway] ${launched.length - pending.size}/${launched.length} healthy. Manifest: ${PID_FILE}`);
216
+ console.log(
217
+ `\n[gateway] ${launched.length - pending.size}/${launched.length} healthy. Manifest: ${PID_FILE}`,
218
+ );
159
219
  }
160
220
 
161
221
  // ── 중지 ──
@@ -164,26 +224,32 @@ function stopAll() {
164
224
  // supergateway + 하위 MCP 프로세스를 포트 기반으로 찾아 종료
165
225
  try {
166
226
  // temp .ps1 파일로 bash/cmd 쿼팅 충돌 회피
167
- const psFile = join(tmpdir(), 'tfx-sg-stop.ps1');
168
- writeFileSync(psFile, [
169
- `Get-CimInstance Win32_Process -Filter "Name='node.exe' OR Name='cmd.exe'" |`,
170
- ` Where-Object { $_.CommandLine -match 'supergateway' } |`,
171
- ` ForEach-Object { taskkill /F /T /PID $_.ProcessId 2>$null; Write-Output "[STOP] PID $($_.ProcessId)" }`,
172
- ].join('\n'));
173
- const output = execSync(`powershell -NoProfile -ExecutionPolicy Bypass -File "${psFile}"`, {
174
- encoding: 'utf8',
175
- timeout: 10000,
176
- stdio: ['pipe', 'pipe', 'ignore'],
177
- });
227
+ const psFile = join(tmpdir(), "tfx-sg-stop.ps1");
228
+ writeFileSync(
229
+ psFile,
230
+ [
231
+ `Get-CimInstance Win32_Process -Filter "Name='node.exe' OR Name='cmd.exe'" |`,
232
+ ` Where-Object { $_.CommandLine -match 'supergateway' } |`,
233
+ ` ForEach-Object { taskkill /F /T /PID $_.ProcessId 2>$null; Write-Output "[STOP] PID $($_.ProcessId)" }`,
234
+ ].join("\n"),
235
+ );
236
+ const output = execSync(
237
+ `powershell -NoProfile -ExecutionPolicy Bypass -File "${psFile}"`,
238
+ {
239
+ encoding: "utf8",
240
+ timeout: 10000,
241
+ stdio: ["pipe", "pipe", "ignore"],
242
+ },
243
+ );
178
244
  if (output.trim()) console.log(output.trim());
179
- else console.log('[gateway] No supergateway processes found');
245
+ else console.log("[gateway] No supergateway processes found");
180
246
  } catch {
181
- console.log('[gateway] No supergateway processes found');
247
+ console.log("[gateway] No supergateway processes found");
182
248
  }
183
249
 
184
250
  if (existsSync(PID_FILE)) {
185
251
  unlinkSync(PID_FILE);
186
- console.log('[gateway] Manifest removed');
252
+ console.log("[gateway] Manifest removed");
187
253
  }
188
254
  }
189
255
 
@@ -192,15 +258,15 @@ function stopAll() {
192
258
  async function showStatus() {
193
259
  const manifest = loadManifest();
194
260
  if (manifest.length === 0) {
195
- console.log('[gateway] No manifest — checking all ports...');
261
+ console.log("[gateway] No manifest — checking all ports...");
196
262
  }
197
263
 
198
- console.log('\nMCP Gateway Status');
199
- console.log('='.repeat(50));
264
+ console.log("\nMCP Gateway Status");
265
+ console.log("=".repeat(50));
200
266
  for (const srv of SERVERS) {
201
267
  const healthy = await checkHealth(srv.port);
202
- const mark = healthy ? '\u2713' : '\u2717';
203
- const status = healthy ? 'ok' : 'down';
268
+ const mark = healthy ? "\u2713" : "\u2717";
269
+ const status = healthy ? "ok" : "down";
204
270
  console.log(` ${srv.name.padEnd(16)} :${srv.port} ${mark} ${status}`);
205
271
  }
206
272
  }
@@ -208,7 +274,7 @@ async function showStatus() {
208
274
  function loadManifest() {
209
275
  if (!existsSync(PID_FILE)) return [];
210
276
  try {
211
- return JSON.parse(readFileSync(PID_FILE, 'utf8'));
277
+ return JSON.parse(readFileSync(PID_FILE, "utf8"));
212
278
  } catch {
213
279
  return [];
214
280
  }
@@ -217,9 +283,9 @@ function loadManifest() {
217
283
  // ── main ──
218
284
 
219
285
  const flag = process.argv[2];
220
- if (flag === '--stop') {
286
+ if (flag === "--stop") {
221
287
  stopAll();
222
- } else if (flag === '--status') {
288
+ } else if (flag === "--status") {
223
289
  await showStatus();
224
290
  } else {
225
291
  await startAll();
@@ -1,28 +1,28 @@
1
1
  #!/usr/bin/env node
2
2
  // mcp-gateway-verify.mjs — supergateway SSE 엔드포인트 헬스체크
3
3
 
4
- import { readManifest } from './lib/mcp-manifest.mjs';
4
+ import { readManifest } from "./lib/mcp-manifest.mjs";
5
5
 
6
6
  const ALL_ENDPOINTS = [
7
- { name: 'context7', port: 8100 },
8
- { name: 'brave-search', port: 8101 },
9
- { name: 'exa', port: 8102 },
10
- { name: 'tavily', port: 8103 },
11
- { name: 'jira', port: 8104 },
12
- { name: 'serena', port: 8105 },
13
- { name: 'notion', port: 8106 },
14
- { name: 'notion-guest', port: 8107 },
7
+ { name: "context7", port: 8100 },
8
+ { name: "brave-search", port: 8101 },
9
+ { name: "exa", port: 8102 },
10
+ { name: "tavily", port: 8103 },
11
+ { name: "jira", port: 8104 },
12
+ { name: "serena", port: 8105 },
13
+ { name: "notion", port: 8106 },
14
+ { name: "notion-guest", port: 8107 },
15
15
  ];
16
16
 
17
17
  const manifest = readManifest();
18
18
  if (!manifest) {
19
- console.log('gateway: not configured (no manifest)');
19
+ console.log("gateway: not configured (no manifest)");
20
20
  process.exit(0);
21
21
  }
22
22
  const enabled = new Set(manifest.enabled || []);
23
23
  const ENDPOINTS = ALL_ENDPOINTS.filter((e) => enabled.has(e.name));
24
24
  if (ENDPOINTS.length === 0) {
25
- console.log('gateway: no enabled servers');
25
+ console.log("gateway: no enabled servers");
26
26
  process.exit(0);
27
27
  }
28
28
 
@@ -34,12 +34,12 @@ async function checkHealth(name, port) {
34
34
  });
35
35
  const latencyMs = Date.now() - start;
36
36
  return res.ok
37
- ? { name, port, status: 'ok', latencyMs, error: null }
38
- : { name, port, status: 'down', latencyMs, error: `HTTP ${res.status}` };
37
+ ? { name, port, status: "ok", latencyMs, error: null }
38
+ : { name, port, status: "down", latencyMs, error: `HTTP ${res.status}` };
39
39
  } catch (err) {
40
40
  const latencyMs = Date.now() - start;
41
- const message = err?.cause?.code || err?.message || 'unknown';
42
- return { name, port, status: 'down', latencyMs, error: message };
41
+ const message = err?.cause?.code || err?.message || "unknown";
42
+ return { name, port, status: "down", latencyMs, error: message };
43
43
  }
44
44
  }
45
45
 
@@ -49,22 +49,24 @@ async function main() {
49
49
  );
50
50
 
51
51
  const entries = results.map((r) =>
52
- r.status === 'fulfilled' ? r.value : { name: '?', port: 0, status: 'down', error: r.reason },
52
+ r.status === "fulfilled"
53
+ ? r.value
54
+ : { name: "?", port: 0, status: "down", error: r.reason },
53
55
  );
54
56
 
55
- console.log('\nMCP Gateway Health Check');
56
- console.log('='.repeat(56));
57
+ console.log("\nMCP Gateway Health Check");
58
+ console.log("=".repeat(56));
57
59
 
58
60
  let downCount = 0;
59
61
  for (const e of entries) {
60
- const mark = e.status === 'ok' ? '\u2713' : '\u2717';
61
- const detail = e.status === 'ok' ? `(${e.latencyMs}ms)` : `(${e.error})`;
62
+ const mark = e.status === "ok" ? "\u2713" : "\u2717";
63
+ const detail = e.status === "ok" ? `(${e.latencyMs}ms)` : `(${e.error})`;
62
64
  const line = ` ${e.name.padEnd(16)} :${String(e.port).padEnd(6)} ${mark} ${e.status.padEnd(6)} ${detail}`;
63
65
  console.log(line);
64
- if (e.status !== 'ok') downCount++;
66
+ if (e.status !== "ok") downCount++;
65
67
  }
66
68
 
67
- console.log('='.repeat(56));
69
+ console.log("=".repeat(56));
68
70
  console.log(
69
71
  downCount === 0
70
72
  ? `All ${entries.length} gateways healthy`