@defai.digital/ax-cli 3.2.0 → 3.4.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 (239) hide show
  1. package/.ax-cli/memory.json +8 -1
  2. package/README.md +118 -2
  3. package/config/models.yaml +13 -0
  4. package/config/settings.yaml +6 -0
  5. package/dist/agent/context-manager.d.ts +5 -5
  6. package/dist/agent/context-manager.js +19 -9
  7. package/dist/agent/context-manager.js.map +1 -1
  8. package/dist/agent/dependency-resolver.js +2 -1
  9. package/dist/agent/dependency-resolver.js.map +1 -1
  10. package/dist/agent/llm-agent.d.ts +3 -2
  11. package/dist/agent/llm-agent.js +64 -58
  12. package/dist/agent/llm-agent.js.map +1 -1
  13. package/dist/agent/subagent.js +2 -1
  14. package/dist/agent/subagent.js.map +1 -1
  15. package/dist/analyzers/architecture/anti-pattern-detectors/god-object-detector.d.ts +29 -0
  16. package/dist/analyzers/architecture/anti-pattern-detectors/god-object-detector.js +103 -0
  17. package/dist/analyzers/architecture/anti-pattern-detectors/god-object-detector.js.map +1 -0
  18. package/dist/analyzers/architecture/architecture-analyzer.d.ts +58 -0
  19. package/dist/analyzers/architecture/architecture-analyzer.js +276 -0
  20. package/dist/analyzers/architecture/architecture-analyzer.js.map +1 -0
  21. package/dist/analyzers/architecture/index.d.ts +12 -0
  22. package/dist/analyzers/architecture/index.js +14 -0
  23. package/dist/analyzers/architecture/index.js.map +1 -0
  24. package/dist/analyzers/architecture/pattern-detectors/base-detector.d.ts +27 -0
  25. package/dist/analyzers/architecture/pattern-detectors/base-detector.js +31 -0
  26. package/dist/analyzers/architecture/pattern-detectors/base-detector.js.map +1 -0
  27. package/dist/analyzers/architecture/pattern-detectors/clean-architecture-detector.d.ts +11 -0
  28. package/dist/analyzers/architecture/pattern-detectors/clean-architecture-detector.js +57 -0
  29. package/dist/analyzers/architecture/pattern-detectors/clean-architecture-detector.js.map +1 -0
  30. package/dist/analyzers/architecture/pattern-detectors/mvc-detector.d.ts +11 -0
  31. package/dist/analyzers/architecture/pattern-detectors/mvc-detector.js +43 -0
  32. package/dist/analyzers/architecture/pattern-detectors/mvc-detector.js.map +1 -0
  33. package/dist/analyzers/architecture/pattern-detectors/repository-detector.d.ts +11 -0
  34. package/dist/analyzers/architecture/pattern-detectors/repository-detector.js +49 -0
  35. package/dist/analyzers/architecture/pattern-detectors/repository-detector.js.map +1 -0
  36. package/dist/analyzers/architecture/project-structure-scanner.d.ts +54 -0
  37. package/dist/analyzers/architecture/project-structure-scanner.js +200 -0
  38. package/dist/analyzers/architecture/project-structure-scanner.js.map +1 -0
  39. package/dist/analyzers/best-practices/base-rule.d.ts +45 -0
  40. package/dist/analyzers/best-practices/base-rule.js +45 -0
  41. package/dist/analyzers/best-practices/base-rule.js.map +1 -0
  42. package/dist/analyzers/best-practices/best-practice-validator.d.ts +35 -0
  43. package/dist/analyzers/best-practices/best-practice-validator.js +181 -0
  44. package/dist/analyzers/best-practices/best-practice-validator.js.map +1 -0
  45. package/dist/analyzers/best-practices/rules/index.d.ts +7 -0
  46. package/dist/analyzers/best-practices/rules/index.js +56 -0
  47. package/dist/analyzers/best-practices/rules/index.js.map +1 -0
  48. package/dist/analyzers/best-practices/rules/typescript/consistent-naming.d.ts +17 -0
  49. package/dist/analyzers/best-practices/rules/typescript/consistent-naming.js +41 -0
  50. package/dist/analyzers/best-practices/rules/typescript/consistent-naming.js.map +1 -0
  51. package/dist/analyzers/best-practices/rules/typescript/function-complexity.d.ts +27 -0
  52. package/dist/analyzers/best-practices/rules/typescript/function-complexity.js +76 -0
  53. package/dist/analyzers/best-practices/rules/typescript/function-complexity.js.map +1 -0
  54. package/dist/analyzers/best-practices/rules/typescript/index.d.ts +15 -0
  55. package/dist/analyzers/best-practices/rules/typescript/index.js +16 -0
  56. package/dist/analyzers/best-practices/rules/typescript/index.js.map +1 -0
  57. package/dist/analyzers/best-practices/rules/typescript/max-file-length.d.ts +18 -0
  58. package/dist/analyzers/best-practices/rules/typescript/max-file-length.js +25 -0
  59. package/dist/analyzers/best-practices/rules/typescript/max-file-length.js.map +1 -0
  60. package/dist/analyzers/best-practices/rules/typescript/no-any-type.d.ts +17 -0
  61. package/dist/analyzers/best-practices/rules/typescript/no-any-type.js +27 -0
  62. package/dist/analyzers/best-practices/rules/typescript/no-any-type.js.map +1 -0
  63. package/dist/analyzers/best-practices/rules/typescript/no-implicit-any.d.ts +18 -0
  64. package/dist/analyzers/best-practices/rules/typescript/no-implicit-any.js +39 -0
  65. package/dist/analyzers/best-practices/rules/typescript/no-implicit-any.js.map +1 -0
  66. package/dist/analyzers/best-practices/rules/typescript/no-magic-numbers.d.ts +17 -0
  67. package/dist/analyzers/best-practices/rules/typescript/no-magic-numbers.js +32 -0
  68. package/dist/analyzers/best-practices/rules/typescript/no-magic-numbers.js.map +1 -0
  69. package/dist/analyzers/best-practices/rules/typescript/no-unused-vars.d.ts +17 -0
  70. package/dist/analyzers/best-practices/rules/typescript/no-unused-vars.js +36 -0
  71. package/dist/analyzers/best-practices/rules/typescript/no-unused-vars.js.map +1 -0
  72. package/dist/analyzers/best-practices/rules/typescript/prefer-const.d.ts +17 -0
  73. package/dist/analyzers/best-practices/rules/typescript/prefer-const.js +33 -0
  74. package/dist/analyzers/best-practices/rules/typescript/prefer-const.js.map +1 -0
  75. package/dist/analyzers/best-practices/rules/typescript/prefer-readonly.d.ts +17 -0
  76. package/dist/analyzers/best-practices/rules/typescript/prefer-readonly.js +34 -0
  77. package/dist/analyzers/best-practices/rules/typescript/prefer-readonly.js.map +1 -0
  78. package/dist/analyzers/best-practices/rules/typescript/proper-error-handling.d.ts +17 -0
  79. package/dist/analyzers/best-practices/rules/typescript/proper-error-handling.js +27 -0
  80. package/dist/analyzers/best-practices/rules/typescript/proper-error-handling.js.map +1 -0
  81. package/dist/analyzers/best-practices/types.d.ts +86 -0
  82. package/dist/analyzers/best-practices/types.js +7 -0
  83. package/dist/analyzers/best-practices/types.js.map +1 -0
  84. package/dist/analyzers/cache/analysis-cache.d.ts +41 -0
  85. package/dist/analyzers/cache/analysis-cache.js +84 -0
  86. package/dist/analyzers/cache/analysis-cache.js.map +1 -0
  87. package/dist/analyzers/errors.d.ts +51 -0
  88. package/dist/analyzers/errors.js +79 -0
  89. package/dist/analyzers/errors.js.map +1 -0
  90. package/dist/commands/doctor.js +3 -2
  91. package/dist/commands/doctor.js.map +1 -1
  92. package/dist/commands/frontend.d.ts +9 -0
  93. package/dist/commands/frontend.js +645 -0
  94. package/dist/commands/frontend.js.map +1 -0
  95. package/dist/commands/mcp.js +652 -3
  96. package/dist/commands/mcp.js.map +1 -1
  97. package/dist/commands/models.js +2 -2
  98. package/dist/commands/models.js.map +1 -1
  99. package/dist/commands/setup.js +100 -41
  100. package/dist/commands/setup.js.map +1 -1
  101. package/dist/constants.d.ts +4 -0
  102. package/dist/constants.js +4 -0
  103. package/dist/constants.js.map +1 -1
  104. package/dist/hooks/use-enhanced-input.js +16 -3
  105. package/dist/hooks/use-enhanced-input.js.map +1 -1
  106. package/dist/hooks/use-input-handler.js +9 -4
  107. package/dist/hooks/use-input-handler.js.map +1 -1
  108. package/dist/index.js +5 -2
  109. package/dist/index.js.map +1 -1
  110. package/dist/llm/client.d.ts +1 -0
  111. package/dist/llm/tools.js +86 -0
  112. package/dist/llm/tools.js.map +1 -1
  113. package/dist/llm/types.d.ts +49 -22
  114. package/dist/llm/types.js +12 -8
  115. package/dist/llm/types.js.map +1 -1
  116. package/dist/mcp/client.d.ts +5 -0
  117. package/dist/mcp/client.js +55 -0
  118. package/dist/mcp/client.js.map +1 -1
  119. package/dist/mcp/config.d.ts +1 -1
  120. package/dist/mcp/config.js +2 -2
  121. package/dist/mcp/config.js.map +1 -1
  122. package/dist/mcp/health.d.ts +120 -0
  123. package/dist/mcp/health.js +267 -0
  124. package/dist/mcp/health.js.map +1 -0
  125. package/dist/mcp/reconnection.d.ts +93 -0
  126. package/dist/mcp/reconnection.js +216 -0
  127. package/dist/mcp/reconnection.js.map +1 -0
  128. package/dist/mcp/registry.d.ts +71 -0
  129. package/dist/mcp/registry.js +257 -0
  130. package/dist/mcp/registry.js.map +1 -0
  131. package/dist/mcp/resources.d.ts +53 -0
  132. package/dist/mcp/resources.js +135 -0
  133. package/dist/mcp/resources.js.map +1 -0
  134. package/dist/mcp/templates.d.ts +52 -0
  135. package/dist/mcp/templates.js +624 -0
  136. package/dist/mcp/templates.js.map +1 -0
  137. package/dist/mcp/validation.d.ts +25 -0
  138. package/dist/mcp/validation.js +209 -0
  139. package/dist/mcp/validation.js.map +1 -0
  140. package/dist/memory/context-generator.js +1 -2
  141. package/dist/memory/context-generator.js.map +1 -1
  142. package/dist/planner/types.d.ts +2 -2
  143. package/dist/schemas/api-schemas.d.ts +2 -1
  144. package/dist/schemas/api-schemas.js +6 -4
  145. package/dist/schemas/api-schemas.js.map +1 -1
  146. package/dist/schemas/index.d.ts +4 -4
  147. package/dist/schemas/tool-schemas.d.ts +2 -2
  148. package/dist/schemas/yaml-schemas.d.ts +15 -0
  149. package/dist/schemas/yaml-schemas.js +3 -0
  150. package/dist/schemas/yaml-schemas.js.map +1 -1
  151. package/dist/sdk/index.d.ts +138 -0
  152. package/dist/sdk/index.js +173 -0
  153. package/dist/sdk/index.js.map +1 -0
  154. package/dist/sdk/types.d.ts +53 -0
  155. package/dist/sdk/types.js +8 -0
  156. package/dist/sdk/types.js.map +1 -0
  157. package/dist/tools/analysis-tools/architecture-tool.d.ts +46 -0
  158. package/dist/tools/analysis-tools/architecture-tool.js +124 -0
  159. package/dist/tools/analysis-tools/architecture-tool.js.map +1 -0
  160. package/dist/tools/analysis-tools/validation-tool.d.ts +51 -0
  161. package/dist/tools/analysis-tools/validation-tool.js +121 -0
  162. package/dist/tools/analysis-tools/validation-tool.js.map +1 -0
  163. package/dist/tools/bash.js +25 -10
  164. package/dist/tools/bash.js.map +1 -1
  165. package/dist/tools/web-search/cache.d.ts +62 -0
  166. package/dist/tools/web-search/cache.js +105 -0
  167. package/dist/tools/web-search/cache.js.map +1 -0
  168. package/dist/tools/web-search/engines/brave.d.ts +16 -0
  169. package/dist/tools/web-search/engines/brave.js +99 -0
  170. package/dist/tools/web-search/engines/brave.js.map +1 -0
  171. package/dist/tools/web-search/engines/crates.d.ts +19 -0
  172. package/dist/tools/web-search/engines/crates.js +87 -0
  173. package/dist/tools/web-search/engines/crates.js.map +1 -0
  174. package/dist/tools/web-search/engines/npm.d.ts +18 -0
  175. package/dist/tools/web-search/engines/npm.js +86 -0
  176. package/dist/tools/web-search/engines/npm.js.map +1 -0
  177. package/dist/tools/web-search/engines/pypi.d.ts +18 -0
  178. package/dist/tools/web-search/engines/pypi.js +75 -0
  179. package/dist/tools/web-search/engines/pypi.js.map +1 -0
  180. package/dist/tools/web-search/engines/tavily.d.ts +17 -0
  181. package/dist/tools/web-search/engines/tavily.js +73 -0
  182. package/dist/tools/web-search/engines/tavily.js.map +1 -0
  183. package/dist/tools/web-search/index.d.ts +13 -0
  184. package/dist/tools/web-search/index.js +13 -0
  185. package/dist/tools/web-search/index.js.map +1 -0
  186. package/dist/tools/web-search/router.d.ts +36 -0
  187. package/dist/tools/web-search/router.js +280 -0
  188. package/dist/tools/web-search/router.js.map +1 -0
  189. package/dist/tools/web-search/types.d.ts +45 -0
  190. package/dist/tools/web-search/types.js +6 -0
  191. package/dist/tools/web-search/types.js.map +1 -0
  192. package/dist/tools/web-search/web-search-tool.d.ts +51 -0
  193. package/dist/tools/web-search/web-search-tool.js +256 -0
  194. package/dist/tools/web-search/web-search-tool.js.map +1 -0
  195. package/dist/types/analysis.d.ts +177 -0
  196. package/dist/types/analysis.js +8 -0
  197. package/dist/types/analysis.js.map +1 -0
  198. package/dist/ui/components/api-key-input.js +2 -2
  199. package/dist/ui/components/api-key-input.js.map +1 -1
  200. package/dist/ui/components/chat-history.js +14 -7
  201. package/dist/ui/components/chat-history.js.map +1 -1
  202. package/dist/ui/components/chat-input.js +12 -7
  203. package/dist/ui/components/chat-input.js.map +1 -1
  204. package/dist/ui/components/chat-interface.js +75 -54
  205. package/dist/ui/components/chat-interface.js.map +1 -1
  206. package/dist/ui/components/keyboard-hints.js +5 -4
  207. package/dist/ui/components/keyboard-hints.js.map +1 -1
  208. package/dist/ui/components/quick-actions.js +1 -0
  209. package/dist/ui/components/quick-actions.js.map +1 -1
  210. package/dist/ui/components/reasoning-display.js +14 -4
  211. package/dist/ui/components/reasoning-display.js.map +1 -1
  212. package/dist/ui/components/status-bar.d.ts +1 -0
  213. package/dist/ui/components/status-bar.js +37 -39
  214. package/dist/ui/components/status-bar.js.map +1 -1
  215. package/dist/ui/components/toast-notification.d.ts +29 -0
  216. package/dist/ui/components/toast-notification.js +17 -3
  217. package/dist/ui/components/toast-notification.js.map +1 -1
  218. package/dist/ui/components/welcome-panel.d.ts +1 -0
  219. package/dist/ui/components/welcome-panel.js +106 -4
  220. package/dist/ui/components/welcome-panel.js.map +1 -1
  221. package/dist/utils/analysis-logger.d.ts +47 -0
  222. package/dist/utils/analysis-logger.js +70 -0
  223. package/dist/utils/analysis-logger.js.map +1 -0
  224. package/dist/utils/automatosx-detector.d.ts +19 -0
  225. package/dist/utils/automatosx-detector.js +52 -0
  226. package/dist/utils/automatosx-detector.js.map +1 -0
  227. package/dist/utils/config-loader.d.ts +4 -0
  228. package/dist/utils/config-loader.js.map +1 -1
  229. package/dist/utils/confirmation-service.js +1 -1
  230. package/dist/utils/confirmation-service.js.map +1 -1
  231. package/dist/utils/init-previewer.js +26 -4
  232. package/dist/utils/init-previewer.js.map +1 -1
  233. package/dist/utils/setup-validator.js +1 -0
  234. package/dist/utils/setup-validator.js.map +1 -1
  235. package/dist/utils/text-utils.d.ts +1 -0
  236. package/dist/utils/text-utils.js +12 -0
  237. package/dist/utils/text-utils.js.map +1 -1
  238. package/package.json +19 -4
  239. package/vitest.config.ts +1 -0
@@ -0,0 +1,267 @@
1
+ /**
2
+ * MCP Server Health Monitoring
3
+ *
4
+ * Provides health checking, status monitoring, and automatic reconnection
5
+ * for MCP servers.
6
+ */
7
+ import { EventEmitter } from 'events';
8
+ import { ReconnectionManager } from './reconnection.js';
9
+ /**
10
+ * MCP Health Monitor
11
+ *
12
+ * Monitors the health of MCP servers and provides automatic reconnection
13
+ */
14
+ export class MCPHealthMonitor extends EventEmitter {
15
+ mcpManager;
16
+ healthCheckInterval = null;
17
+ reconnectionManager;
18
+ serverStats = new Map();
19
+ constructor(mcpManager, reconnectionStrategy) {
20
+ super();
21
+ this.mcpManager = mcpManager;
22
+ this.reconnectionManager = new ReconnectionManager(reconnectionStrategy);
23
+ // Forward reconnection events
24
+ this.reconnectionManager.on('reconnection-scheduled', (data) => this.emit('reconnection-scheduled', data));
25
+ this.reconnectionManager.on('reconnection-attempt', (data) => this.emit('reconnection-attempt', data));
26
+ this.reconnectionManager.on('reconnection-success', (data) => this.emit('reconnection-success', data));
27
+ this.reconnectionManager.on('reconnection-failed', (data) => this.emit('reconnection-failed', data));
28
+ this.reconnectionManager.on('max-retries-reached', (data) => this.emit('max-retries-reached', data));
29
+ }
30
+ /**
31
+ * Start health monitoring with specified interval
32
+ */
33
+ start(intervalMs = 60000) {
34
+ if (this.healthCheckInterval) {
35
+ throw new Error('Health monitoring already started');
36
+ }
37
+ // Initialize stats for existing servers
38
+ const servers = this.mcpManager.getServers();
39
+ for (const serverName of servers) {
40
+ if (!this.serverStats.has(serverName)) {
41
+ this.serverStats.set(serverName, {
42
+ connectedAt: Date.now(),
43
+ successCount: 0,
44
+ failureCount: 0,
45
+ latencies: [],
46
+ });
47
+ }
48
+ }
49
+ this.healthCheckInterval = setInterval(async () => {
50
+ await this.performHealthChecks();
51
+ }, intervalMs);
52
+ }
53
+ /**
54
+ * Stop health monitoring
55
+ */
56
+ stop() {
57
+ if (this.healthCheckInterval) {
58
+ clearInterval(this.healthCheckInterval);
59
+ this.healthCheckInterval = null;
60
+ }
61
+ }
62
+ /**
63
+ * Perform health checks on all servers
64
+ */
65
+ async performHealthChecks() {
66
+ const servers = this.mcpManager.getServers();
67
+ for (const serverName of servers) {
68
+ try {
69
+ const health = await this.checkServerHealth(serverName);
70
+ this.emit('health-check', health);
71
+ // Check if server is unhealthy
72
+ if (!health.connected && health.successRate < 50) {
73
+ this.emit('server-disconnected', serverName);
74
+ // Note: Automatic reconnection disabled - config not available in health monitor
75
+ // Reconnection should be handled externally via the reconnection manager
76
+ }
77
+ }
78
+ catch (error) {
79
+ this.emit('health-check-error', { serverName, error: error });
80
+ }
81
+ }
82
+ }
83
+ /**
84
+ * Check health of a specific server
85
+ */
86
+ async checkServerHealth(serverName) {
87
+ const tools = this.mcpManager.getTools().filter((t) => t.serverName === serverName);
88
+ // Initialize stats if not present
89
+ if (!this.serverStats.has(serverName)) {
90
+ this.serverStats.set(serverName, {
91
+ connectedAt: Date.now(),
92
+ successCount: 0,
93
+ failureCount: 0,
94
+ latencies: [],
95
+ });
96
+ }
97
+ const stats = this.serverStats.get(serverName);
98
+ // Calculate success rate
99
+ const total = stats.successCount + stats.failureCount;
100
+ const successRate = total > 0 ? (stats.successCount / total) * 100 : 100;
101
+ // Calculate latencies
102
+ const avgLatency = stats.latencies.length > 0
103
+ ? stats.latencies.reduce((a, b) => a + b, 0) / stats.latencies.length
104
+ : undefined;
105
+ const p95Latency = stats.latencies.length > 0
106
+ ? this.calculatePercentile(stats.latencies, 0.95)
107
+ : undefined;
108
+ // Calculate uptime
109
+ const uptime = Date.now() - stats.connectedAt;
110
+ return {
111
+ serverName,
112
+ connected: tools.length > 0,
113
+ toolCount: tools.length,
114
+ uptime,
115
+ connectedAt: stats.connectedAt,
116
+ lastSuccess: stats.lastSuccess,
117
+ lastError: stats.lastError,
118
+ lastErrorAt: stats.lastErrorAt,
119
+ successCount: stats.successCount,
120
+ failureCount: stats.failureCount,
121
+ avgLatency,
122
+ p95Latency,
123
+ successRate,
124
+ };
125
+ }
126
+ /**
127
+ * Record a successful tool call
128
+ */
129
+ recordSuccess(serverName, latencyMs) {
130
+ // Initialize stats if not present
131
+ if (!this.serverStats.has(serverName)) {
132
+ this.serverStats.set(serverName, {
133
+ connectedAt: Date.now(),
134
+ successCount: 0,
135
+ failureCount: 0,
136
+ latencies: [],
137
+ });
138
+ }
139
+ const stats = this.serverStats.get(serverName);
140
+ stats.successCount++;
141
+ stats.lastSuccess = Date.now();
142
+ stats.latencies.push(latencyMs);
143
+ // Keep only last 100 latencies
144
+ if (stats.latencies.length > 100) {
145
+ stats.latencies.shift();
146
+ }
147
+ }
148
+ /**
149
+ * Record a failed tool call
150
+ */
151
+ recordFailure(serverName, error) {
152
+ // Initialize stats if not present
153
+ if (!this.serverStats.has(serverName)) {
154
+ this.serverStats.set(serverName, {
155
+ connectedAt: Date.now(),
156
+ successCount: 0,
157
+ failureCount: 0,
158
+ latencies: [],
159
+ });
160
+ }
161
+ const stats = this.serverStats.get(serverName);
162
+ stats.failureCount++;
163
+ stats.lastError = error;
164
+ stats.lastErrorAt = Date.now();
165
+ }
166
+ /**
167
+ * Attempt to reconnect to a disconnected server
168
+ *
169
+ * NOTE: This method is currently not used because the health monitor
170
+ * doesn't have access to server configs. Reconnection should be handled
171
+ * externally by listening to 'server-disconnected' events.
172
+ */
173
+ /* private async attemptReconnection(serverName: string, config: any): Promise<void> {
174
+ // Only schedule if not already reconnecting
175
+ if (this.reconnectionManager.isReconnecting(serverName)) {
176
+ return;
177
+ }
178
+
179
+ await this.reconnectionManager.scheduleReconnection(
180
+ serverName,
181
+ config,
182
+ async (cfg) => {
183
+ await this.mcpManager.addServer(cfg);
184
+ }
185
+ );
186
+ } */
187
+ /**
188
+ * Get reconnection manager
189
+ */
190
+ getReconnectionManager() {
191
+ return this.reconnectionManager;
192
+ }
193
+ /**
194
+ * Calculate percentile from array of values
195
+ */
196
+ calculatePercentile(values, percentile) {
197
+ const sorted = [...values].sort((a, b) => a - b);
198
+ const index = Math.ceil(sorted.length * percentile) - 1;
199
+ return sorted[index] || 0;
200
+ }
201
+ /**
202
+ * Get health report for all servers
203
+ */
204
+ async getHealthReport() {
205
+ const servers = this.mcpManager.getServers();
206
+ const report = [];
207
+ for (const serverName of servers) {
208
+ const health = await this.checkServerHealth(serverName);
209
+ report.push(health);
210
+ }
211
+ return report;
212
+ }
213
+ /**
214
+ * Get health status for a specific server
215
+ */
216
+ async getServerStatus(serverName) {
217
+ const servers = this.mcpManager.getServers();
218
+ if (!servers.includes(serverName)) {
219
+ return null;
220
+ }
221
+ return await this.checkServerHealth(serverName);
222
+ }
223
+ /**
224
+ * Reset stats for a server
225
+ */
226
+ resetStats(serverName) {
227
+ this.serverStats.set(serverName, {
228
+ connectedAt: Date.now(),
229
+ successCount: 0,
230
+ failureCount: 0,
231
+ latencies: [],
232
+ });
233
+ }
234
+ /**
235
+ * Get formatted uptime string
236
+ */
237
+ static formatUptime(uptimeMs) {
238
+ const seconds = Math.floor(uptimeMs / 1000);
239
+ const minutes = Math.floor(seconds / 60);
240
+ const hours = Math.floor(minutes / 60);
241
+ const days = Math.floor(hours / 24);
242
+ if (days > 0) {
243
+ return `${days}d ${hours % 24}h`;
244
+ }
245
+ else if (hours > 0) {
246
+ return `${hours}h ${minutes % 60}m`;
247
+ }
248
+ else if (minutes > 0) {
249
+ return `${minutes}m ${seconds % 60}s`;
250
+ }
251
+ else {
252
+ return `${seconds}s`;
253
+ }
254
+ }
255
+ /**
256
+ * Get formatted latency string
257
+ */
258
+ static formatLatency(latencyMs) {
259
+ if (latencyMs < 1000) {
260
+ return `${Math.round(latencyMs)}ms`;
261
+ }
262
+ else {
263
+ return `${(latencyMs / 1000).toFixed(2)}s`;
264
+ }
265
+ }
266
+ }
267
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/mcp/health.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * MCP Server Automatic Reconnection (Phase 5)
3
+ *
4
+ * Provides intelligent retry logic with exponential backoff for failed MCP connections
5
+ * Ensures production reliability without overwhelming servers
6
+ */
7
+ import { EventEmitter } from 'events';
8
+ import type { MCPServerConfig } from '../schemas/settings-schemas.js';
9
+ export interface ReconnectionStrategy {
10
+ /** Maximum number of retry attempts */
11
+ maxRetries: number;
12
+ /** Initial delay in milliseconds */
13
+ baseDelayMs: number;
14
+ /** Maximum delay in milliseconds */
15
+ maxDelayMs: number;
16
+ /** Backoff multiplier (2 = double each time) */
17
+ backoffMultiplier: number;
18
+ /** Add random jitter to prevent thundering herd */
19
+ jitter: boolean;
20
+ }
21
+ export declare const DEFAULT_STRATEGY: ReconnectionStrategy;
22
+ export interface ReconnectionState {
23
+ serverName: string;
24
+ attempts: number;
25
+ lastAttempt: number;
26
+ nextAttempt: number | null;
27
+ status: 'idle' | 'scheduled' | 'connecting' | 'failed' | 'connected';
28
+ lastError?: string;
29
+ }
30
+ /**
31
+ * Reconnection Manager
32
+ *
33
+ * Manages automatic reconnection attempts with exponential backoff
34
+ */
35
+ export declare class ReconnectionManager extends EventEmitter {
36
+ private retryAttempts;
37
+ private reconnectTimers;
38
+ private reconnectionState;
39
+ private strategy;
40
+ constructor(strategy?: ReconnectionStrategy);
41
+ /**
42
+ * Schedule reconnection for a server
43
+ */
44
+ scheduleReconnection(serverName: string, config: MCPServerConfig, reconnectFn: (config: MCPServerConfig) => Promise<void>): Promise<void>;
45
+ /**
46
+ * Calculate delay for next attempt with exponential backoff
47
+ */
48
+ private calculateDelay;
49
+ /**
50
+ * Cancel reconnection attempts for a server
51
+ */
52
+ cancelReconnection(serverName: string): void;
53
+ /**
54
+ * Cancel all reconnection attempts
55
+ */
56
+ cancelAll(): void;
57
+ /**
58
+ * Reset retry counter for a server
59
+ */
60
+ resetRetries(serverName: string): void;
61
+ /**
62
+ * Get reconnection state for a server
63
+ */
64
+ getState(serverName: string): ReconnectionState | null;
65
+ /**
66
+ * Get all reconnection states
67
+ */
68
+ getAllStates(): ReconnectionState[];
69
+ /**
70
+ * Update reconnection state
71
+ */
72
+ private updateState;
73
+ /**
74
+ * Get number of active reconnection attempts
75
+ */
76
+ getActiveReconnections(): number;
77
+ /**
78
+ * Check if server is currently attempting to reconnect
79
+ */
80
+ isReconnecting(serverName: string): boolean;
81
+ /**
82
+ * Format time until next reconnection attempt
83
+ */
84
+ static formatNextAttempt(nextAttemptMs: number): string;
85
+ /**
86
+ * Get strategy configuration
87
+ */
88
+ getStrategy(): ReconnectionStrategy;
89
+ /**
90
+ * Update strategy configuration
91
+ */
92
+ setStrategy(strategy: Partial<ReconnectionStrategy>): void;
93
+ }
@@ -0,0 +1,216 @@
1
+ /**
2
+ * MCP Server Automatic Reconnection (Phase 5)
3
+ *
4
+ * Provides intelligent retry logic with exponential backoff for failed MCP connections
5
+ * Ensures production reliability without overwhelming servers
6
+ */
7
+ import { EventEmitter } from 'events';
8
+ export const DEFAULT_STRATEGY = {
9
+ maxRetries: 5,
10
+ baseDelayMs: 1000, // Start at 1 second
11
+ maxDelayMs: 30000, // Cap at 30 seconds
12
+ backoffMultiplier: 2, // Double each time: 1s, 2s, 4s, 8s, 16s, 30s
13
+ jitter: true // Add randomness
14
+ };
15
+ /**
16
+ * Reconnection Manager
17
+ *
18
+ * Manages automatic reconnection attempts with exponential backoff
19
+ */
20
+ export class ReconnectionManager extends EventEmitter {
21
+ retryAttempts = new Map();
22
+ reconnectTimers = new Map();
23
+ reconnectionState = new Map();
24
+ strategy;
25
+ constructor(strategy = DEFAULT_STRATEGY) {
26
+ super();
27
+ this.strategy = strategy;
28
+ }
29
+ /**
30
+ * Schedule reconnection for a server
31
+ */
32
+ async scheduleReconnection(serverName, config, reconnectFn) {
33
+ const attempts = this.retryAttempts.get(serverName) || 0;
34
+ if (attempts >= this.strategy.maxRetries) {
35
+ this.updateState(serverName, {
36
+ serverName,
37
+ attempts,
38
+ lastAttempt: Date.now(),
39
+ nextAttempt: null,
40
+ status: 'failed',
41
+ lastError: 'Max reconnection attempts reached'
42
+ });
43
+ this.emit('max-retries-reached', {
44
+ serverName,
45
+ attempts,
46
+ config
47
+ });
48
+ return;
49
+ }
50
+ const delay = this.calculateDelay(attempts);
51
+ this.updateState(serverName, {
52
+ serverName,
53
+ attempts,
54
+ lastAttempt: Date.now(),
55
+ nextAttempt: Date.now() + delay,
56
+ status: 'scheduled'
57
+ });
58
+ this.emit('reconnection-scheduled', {
59
+ serverName,
60
+ attempt: attempts + 1,
61
+ maxAttempts: this.strategy.maxRetries,
62
+ delayMs: delay
63
+ });
64
+ const timer = setTimeout(async () => {
65
+ this.updateState(serverName, {
66
+ serverName,
67
+ attempts: attempts + 1,
68
+ lastAttempt: Date.now(),
69
+ nextAttempt: null,
70
+ status: 'connecting'
71
+ });
72
+ this.emit('reconnection-attempt', {
73
+ serverName,
74
+ attempt: attempts + 1,
75
+ maxAttempts: this.strategy.maxRetries
76
+ });
77
+ try {
78
+ await reconnectFn(config);
79
+ // Success - reset attempts
80
+ this.retryAttempts.set(serverName, 0);
81
+ this.updateState(serverName, {
82
+ serverName,
83
+ attempts: 0,
84
+ lastAttempt: Date.now(),
85
+ nextAttempt: null,
86
+ status: 'connected'
87
+ });
88
+ this.emit('reconnection-success', {
89
+ serverName,
90
+ totalAttempts: attempts + 1
91
+ });
92
+ }
93
+ catch (error) {
94
+ // Failure - schedule next attempt
95
+ this.retryAttempts.set(serverName, attempts + 1);
96
+ const errorMessage = error instanceof Error ? error.message : String(error);
97
+ this.updateState(serverName, {
98
+ serverName,
99
+ attempts: attempts + 1,
100
+ lastAttempt: Date.now(),
101
+ nextAttempt: null,
102
+ status: 'idle',
103
+ lastError: errorMessage
104
+ });
105
+ this.emit('reconnection-failed', {
106
+ serverName,
107
+ attempt: attempts + 1,
108
+ maxAttempts: this.strategy.maxRetries,
109
+ error: errorMessage
110
+ });
111
+ // Schedule next attempt
112
+ await this.scheduleReconnection(serverName, config, reconnectFn);
113
+ }
114
+ }, delay);
115
+ this.reconnectTimers.set(serverName, timer);
116
+ }
117
+ /**
118
+ * Calculate delay for next attempt with exponential backoff
119
+ */
120
+ calculateDelay(attempts) {
121
+ let delay = this.strategy.baseDelayMs * Math.pow(this.strategy.backoffMultiplier, attempts);
122
+ // Cap at max delay
123
+ delay = Math.min(delay, this.strategy.maxDelayMs);
124
+ // Add jitter if enabled (±25% randomness)
125
+ if (this.strategy.jitter) {
126
+ const jitterRange = delay * 0.25;
127
+ const jitter = (Math.random() * 2 - 1) * jitterRange;
128
+ delay += jitter;
129
+ }
130
+ return Math.max(delay, 0);
131
+ }
132
+ /**
133
+ * Cancel reconnection attempts for a server
134
+ */
135
+ cancelReconnection(serverName) {
136
+ const timer = this.reconnectTimers.get(serverName);
137
+ if (timer) {
138
+ clearTimeout(timer);
139
+ this.reconnectTimers.delete(serverName);
140
+ }
141
+ this.retryAttempts.delete(serverName);
142
+ this.reconnectionState.delete(serverName);
143
+ this.emit('reconnection-cancelled', { serverName });
144
+ }
145
+ /**
146
+ * Cancel all reconnection attempts
147
+ */
148
+ cancelAll() {
149
+ for (const serverName of this.reconnectTimers.keys()) {
150
+ this.cancelReconnection(serverName);
151
+ }
152
+ }
153
+ /**
154
+ * Reset retry counter for a server
155
+ */
156
+ resetRetries(serverName) {
157
+ this.retryAttempts.set(serverName, 0);
158
+ }
159
+ /**
160
+ * Get reconnection state for a server
161
+ */
162
+ getState(serverName) {
163
+ return this.reconnectionState.get(serverName) || null;
164
+ }
165
+ /**
166
+ * Get all reconnection states
167
+ */
168
+ getAllStates() {
169
+ return Array.from(this.reconnectionState.values());
170
+ }
171
+ /**
172
+ * Update reconnection state
173
+ */
174
+ updateState(serverName, state) {
175
+ this.reconnectionState.set(serverName, state);
176
+ }
177
+ /**
178
+ * Get number of active reconnection attempts
179
+ */
180
+ getActiveReconnections() {
181
+ return this.reconnectTimers.size;
182
+ }
183
+ /**
184
+ * Check if server is currently attempting to reconnect
185
+ */
186
+ isReconnecting(serverName) {
187
+ const state = this.getState(serverName);
188
+ return state?.status === 'scheduled' || state?.status === 'connecting';
189
+ }
190
+ /**
191
+ * Format time until next reconnection attempt
192
+ */
193
+ static formatNextAttempt(nextAttemptMs) {
194
+ const diff = nextAttemptMs - Date.now();
195
+ if (diff <= 0)
196
+ return 'now';
197
+ const seconds = Math.floor(diff / 1000);
198
+ if (seconds < 60)
199
+ return `${seconds}s`;
200
+ const minutes = Math.floor(seconds / 60);
201
+ return `${minutes}m ${seconds % 60}s`;
202
+ }
203
+ /**
204
+ * Get strategy configuration
205
+ */
206
+ getStrategy() {
207
+ return { ...this.strategy };
208
+ }
209
+ /**
210
+ * Update strategy configuration
211
+ */
212
+ setStrategy(strategy) {
213
+ this.strategy = { ...this.strategy, ...strategy };
214
+ }
215
+ }
216
+ //# sourceMappingURL=reconnection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconnection.js","sourceRoot":"","sources":["../../src/mcp/reconnection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * MCP Server Registry Integration (Phase 5)
3
+ *
4
+ * Enables discovery and installation of MCP servers from the GitHub MCP Registry
5
+ * Provides one-command install and browsing capabilities
6
+ */
7
+ import type { MCPServerConfig } from '../schemas/settings-schemas.js';
8
+ export interface RegistryServer {
9
+ /** Server name/identifier */
10
+ name: string;
11
+ /** Human-readable display name */
12
+ displayName: string;
13
+ /** Server description */
14
+ description: string;
15
+ /** GitHub repository URL */
16
+ repository: string;
17
+ /** GitHub stars count */
18
+ stars: number;
19
+ /** Server category (design, deployment, database, etc.) */
20
+ category: string;
21
+ /** Transport type */
22
+ transport: 'stdio' | 'http' | 'sse';
23
+ /** NPM package name (for stdio servers) */
24
+ packageName?: string;
25
+ /** Install command */
26
+ installCommand: string;
27
+ /** Whether this is an official/verified server */
28
+ verified: boolean;
29
+ /** Author/organization */
30
+ author: string;
31
+ /** Latest version */
32
+ version?: string;
33
+ /** Homepage URL */
34
+ homepage?: string;
35
+ }
36
+ export interface RegistrySearchOptions {
37
+ /** Search query */
38
+ query?: string;
39
+ /** Filter by category */
40
+ category?: string;
41
+ /** Filter by transport type */
42
+ transport?: 'stdio' | 'http' | 'sse';
43
+ /** Sort by (stars, name, updated) */
44
+ sortBy?: 'stars' | 'name' | 'updated';
45
+ /** Max results to return */
46
+ limit?: number;
47
+ }
48
+ /**
49
+ * Search the MCP server registry
50
+ */
51
+ export declare function searchRegistry(options?: RegistrySearchOptions): Promise<RegistryServer[]>;
52
+ /**
53
+ * Get details for a specific server from the registry
54
+ */
55
+ export declare function getRegistryServer(nameOrPackage: string): Promise<RegistryServer | null>;
56
+ /**
57
+ * Get popular/featured MCP servers
58
+ */
59
+ export declare function getPopularServers(): Promise<RegistryServer[]>;
60
+ /**
61
+ * Get servers by category
62
+ */
63
+ export declare function getServersByCategory(category: string): Promise<RegistryServer[]>;
64
+ /**
65
+ * Generate MCP server configuration from registry entry
66
+ */
67
+ export declare function generateConfigFromRegistry(server: RegistryServer): MCPServerConfig;
68
+ /**
69
+ * Format registry server for display
70
+ */
71
+ export declare function formatRegistryServer(server: RegistryServer, compact?: boolean): string;