@mcpjam/inspector 0.3.8 → 0.8.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 (193) hide show
  1. package/.next/BUILD_ID +1 -0
  2. package/.next/app-build-manifest.json +89 -0
  3. package/.next/app-path-routes-manifest.json +13 -0
  4. package/.next/build-manifest.json +33 -0
  5. package/.next/cache/.previewinfo +1 -0
  6. package/.next/cache/.rscinfo +1 -0
  7. package/.next/cache/.tsbuildinfo +1 -0
  8. package/.next/cache/eslint/.cache_11b5ofe +1 -0
  9. package/.next/cache/webpack/client-production/0.pack +0 -0
  10. package/.next/cache/webpack/client-production/index.pack +0 -0
  11. package/.next/cache/webpack/edge-server-production/0.pack +0 -0
  12. package/.next/cache/webpack/edge-server-production/index.pack +0 -0
  13. package/.next/cache/webpack/server-production/0.pack +0 -0
  14. package/.next/cache/webpack/server-production/index.pack +0 -0
  15. package/.next/diagnostics/build-diagnostics.json +6 -0
  16. package/.next/diagnostics/framework.json +1 -0
  17. package/.next/export-marker.json +6 -0
  18. package/.next/images-manifest.json +57 -0
  19. package/.next/next-minimal-server.js.nft.json +1 -0
  20. package/.next/next-server.js.nft.json +1 -0
  21. package/.next/package.json +1 -0
  22. package/.next/prerender-manifest.json +41 -0
  23. package/.next/react-loadable-manifest.json +1 -0
  24. package/.next/required-server-files.json +318 -0
  25. package/.next/routes-manifest.json +65 -0
  26. package/.next/server/app/_not-found/page.js +2 -0
  27. package/.next/server/app/_not-found/page.js.nft.json +1 -0
  28. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
  29. package/.next/server/app/api/mcp/chat/route.js +45 -0
  30. package/.next/server/app/api/mcp/chat/route.js.nft.json +1 -0
  31. package/.next/server/app/api/mcp/chat/route_client-reference-manifest.js +1 -0
  32. package/.next/server/app/api/mcp/connect/route.js +1 -0
  33. package/.next/server/app/api/mcp/connect/route.js.nft.json +1 -0
  34. package/.next/server/app/api/mcp/connect/route_client-reference-manifest.js +1 -0
  35. package/.next/server/app/api/mcp/prompts/get/route.js +1 -0
  36. package/.next/server/app/api/mcp/prompts/get/route.js.nft.json +1 -0
  37. package/.next/server/app/api/mcp/prompts/get/route_client-reference-manifest.js +1 -0
  38. package/.next/server/app/api/mcp/prompts/list/route.js +1 -0
  39. package/.next/server/app/api/mcp/prompts/list/route.js.nft.json +1 -0
  40. package/.next/server/app/api/mcp/prompts/list/route_client-reference-manifest.js +1 -0
  41. package/.next/server/app/api/mcp/resources/list/route.js +1 -0
  42. package/.next/server/app/api/mcp/resources/list/route.js.nft.json +1 -0
  43. package/.next/server/app/api/mcp/resources/list/route_client-reference-manifest.js +1 -0
  44. package/.next/server/app/api/mcp/resources/read/route.js +1 -0
  45. package/.next/server/app/api/mcp/resources/read/route.js.nft.json +1 -0
  46. package/.next/server/app/api/mcp/resources/read/route_client-reference-manifest.js +1 -0
  47. package/.next/server/app/api/mcp/tools/route.js +21 -0
  48. package/.next/server/app/api/mcp/tools/route.js.nft.json +1 -0
  49. package/.next/server/app/api/mcp/tools/route_client-reference-manifest.js +1 -0
  50. package/.next/server/app/favicon.ico/route.js +1 -0
  51. package/.next/server/app/favicon.ico/route.js.nft.json +1 -0
  52. package/.next/server/app/favicon.ico.body +0 -0
  53. package/.next/server/app/favicon.ico.meta +1 -0
  54. package/.next/server/app/oauth/callback/page.js +2 -0
  55. package/.next/server/app/oauth/callback/page.js.nft.json +1 -0
  56. package/.next/server/app/oauth/callback/page_client-reference-manifest.js +1 -0
  57. package/.next/server/app/page.js +16 -0
  58. package/.next/server/app/page.js.nft.json +1 -0
  59. package/.next/server/app/page_client-reference-manifest.js +1 -0
  60. package/.next/server/app-paths-manifest.json +13 -0
  61. package/.next/server/chunks/175.js +8 -0
  62. package/.next/server/chunks/260.js +82 -0
  63. package/.next/server/chunks/546.js +1 -0
  64. package/.next/server/chunks/548.js +6 -0
  65. package/.next/server/chunks/55.js +1 -0
  66. package/.next/server/chunks/985.js +22 -0
  67. package/.next/server/functions-config-manifest.json +4 -0
  68. package/.next/server/interception-route-rewrite-manifest.js +1 -0
  69. package/.next/server/middleware-build-manifest.js +1 -0
  70. package/.next/server/middleware-manifest.json +6 -0
  71. package/.next/server/middleware-react-loadable-manifest.js +1 -0
  72. package/.next/server/next-font-manifest.js +1 -0
  73. package/.next/server/next-font-manifest.json +1 -0
  74. package/.next/server/pages/500.html +1 -0
  75. package/.next/server/pages/_app.js +1 -0
  76. package/.next/server/pages/_app.js.nft.json +1 -0
  77. package/.next/server/pages/_document.js +1 -0
  78. package/.next/server/pages/_document.js.nft.json +1 -0
  79. package/.next/server/pages/_error.js +19 -0
  80. package/.next/server/pages/_error.js.nft.json +1 -0
  81. package/.next/server/pages-manifest.json +5 -0
  82. package/.next/server/server-reference-manifest.js +1 -0
  83. package/.next/server/server-reference-manifest.json +1 -0
  84. package/.next/server/webpack-runtime.js +1 -0
  85. package/.next/static/chunks/14-ae3a01e72ea53777.js +1 -0
  86. package/.next/static/chunks/214-cc4c35d88f2695ed.js +1 -0
  87. package/.next/static/chunks/4bd1b696-cf72ae8a39fa05aa.js +1 -0
  88. package/.next/static/chunks/866-04c19dda4c52f2bf.js +1 -0
  89. package/.next/static/chunks/964-eda38e26c0391a47.js +1 -0
  90. package/.next/static/chunks/app/_not-found/page-d7e832b54474da82.js +1 -0
  91. package/.next/static/chunks/app/api/mcp/chat/route-0341498a8bf5f2da.js +1 -0
  92. package/.next/static/chunks/app/api/mcp/connect/route-0341498a8bf5f2da.js +1 -0
  93. package/.next/static/chunks/app/api/mcp/prompts/get/route-0341498a8bf5f2da.js +1 -0
  94. package/.next/static/chunks/app/api/mcp/prompts/list/route-0341498a8bf5f2da.js +1 -0
  95. package/.next/static/chunks/app/api/mcp/resources/list/route-0341498a8bf5f2da.js +1 -0
  96. package/.next/static/chunks/app/api/mcp/resources/read/route-0341498a8bf5f2da.js +1 -0
  97. package/.next/static/chunks/app/api/mcp/tools/route-0341498a8bf5f2da.js +1 -0
  98. package/.next/static/chunks/app/layout-fb6e1ad5933381f3.js +1 -0
  99. package/.next/static/chunks/app/oauth/callback/page-d8b3908ea67ba3e3.js +1 -0
  100. package/.next/static/chunks/app/page-81e35b2a61edb363.js +1 -0
  101. package/.next/static/chunks/framework-7c95b8e5103c9e90.js +1 -0
  102. package/.next/static/chunks/main-app-7d61da15faa6c1af.js +1 -0
  103. package/.next/static/chunks/main-bbdafee21a7bd1d6.js +1 -0
  104. package/.next/static/chunks/pages/_app-0a0020ddd67f79cf.js +1 -0
  105. package/.next/static/chunks/pages/_error-03529f2c21436739.js +1 -0
  106. package/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  107. package/.next/static/chunks/webpack-cdfccaf38062dd25.js +1 -0
  108. package/.next/static/css/1e852d83e9c1d0c6.css +1 -0
  109. package/.next/static/css/f30152c0704fba31.css +1 -0
  110. package/.next/static/css/fe751fdbe975e9ca.css +1 -0
  111. package/.next/static/media/569ce4b8f30dc480-s.p.woff2 +0 -0
  112. package/.next/static/media/747892c23ea88013-s.woff2 +0 -0
  113. package/.next/static/media/8d697b304b401681-s.woff2 +0 -0
  114. package/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
  115. package/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
  116. package/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
  117. package/.next/static/media/ollama_dark.9af45ac0.png +0 -0
  118. package/.next/static/media/ollama_logo.9f08a95b.svg +7 -0
  119. package/.next/static/media/openai_logo.3f83154a.png +0 -0
  120. package/.next/static/wgHmsxKAquUu9gOMW6Qd5/_buildManifest.js +1 -0
  121. package/.next/static/wgHmsxKAquUu9gOMW6Qd5/_ssgManifest.js +1 -0
  122. package/.next/trace +35 -0
  123. package/.next/types/app/api/mcp/chat/route.ts +347 -0
  124. package/.next/types/app/api/mcp/connect/route.ts +347 -0
  125. package/.next/types/app/api/mcp/prompts/get/route.ts +347 -0
  126. package/.next/types/app/api/mcp/prompts/list/route.ts +347 -0
  127. package/.next/types/app/api/mcp/resources/list/route.ts +347 -0
  128. package/.next/types/app/api/mcp/resources/read/route.ts +347 -0
  129. package/.next/types/app/api/mcp/tools/route.ts +347 -0
  130. package/.next/types/app/layout.ts +84 -0
  131. package/.next/types/app/oauth/callback/page.ts +84 -0
  132. package/.next/types/app/page.ts +84 -0
  133. package/.next/types/cache-life.d.ts +141 -0
  134. package/.next/types/package.json +1 -0
  135. package/README.md +76 -161
  136. package/bin/start.js +504 -0
  137. package/next.config.ts +7 -0
  138. package/package.json +71 -54
  139. package/public/claude_logo.png +0 -0
  140. package/public/demo_1.png +0 -0
  141. package/public/demo_2.png +0 -0
  142. package/public/demo_3.png +0 -0
  143. package/public/file.svg +1 -0
  144. package/public/globe.svg +1 -0
  145. package/public/mcp.svg +1 -0
  146. package/public/next.svg +1 -0
  147. package/public/ollama_dark.png +0 -0
  148. package/public/ollama_logo.svg +7 -0
  149. package/public/openai_logo.png +0 -0
  150. package/public/vercel.svg +1 -0
  151. package/public/window.svg +1 -0
  152. package/LICENSE +0 -200
  153. package/cli/build/cli.js +0 -251
  154. package/cli/build/client/connection.js +0 -33
  155. package/cli/build/client/index.js +0 -6
  156. package/cli/build/client/prompts.js +0 -23
  157. package/cli/build/client/resources.js +0 -30
  158. package/cli/build/client/tools.js +0 -64
  159. package/cli/build/client/types.js +0 -1
  160. package/cli/build/error-handler.js +0 -18
  161. package/cli/build/index.js +0 -166
  162. package/cli/build/transport.js +0 -47
  163. package/client/bin/client.js +0 -71
  164. package/client/bin/start.js +0 -143
  165. package/client/dist/assets/OAuthCallback-Dovy-wwC.js +0 -56
  166. package/client/dist/assets/OAuthDebugCallback-CP9EZ76u.js +0 -44
  167. package/client/dist/assets/index-CWDemo1t.css +0 -4168
  168. package/client/dist/assets/index-DTD8_Uq7.js +0 -63318
  169. package/client/dist/index.html +0 -14
  170. package/client/dist/ollama_logo.png +0 -0
  171. package/client/dist/openai_logo.png +0 -0
  172. package/server/build/database/DatabaseManager.js +0 -108
  173. package/server/build/database/index.js +0 -8
  174. package/server/build/database/routes.js +0 -86
  175. package/server/build/database/types.js +0 -27
  176. package/server/build/database/utils.js +0 -86
  177. package/server/build/index.js +0 -331
  178. package/server/build/mcpProxy.js +0 -54
  179. package/server/build/shared/MCPProxyService.js +0 -221
  180. package/server/build/shared/TransportFactory.js +0 -130
  181. package/server/build/shared/index.js +0 -4
  182. package/server/build/shared/types.js +0 -1
  183. package/server/build/shared/utils.js +0 -27
  184. package/server/build/test-server.js +0 -145
  185. package/server/build/testing/HealthCheck.js +0 -42
  186. package/server/build/testing/TestExecutor.js +0 -240
  187. package/server/build/testing/TestRunner.js +0 -198
  188. package/server/build/testing/TestServer.js +0 -440
  189. package/server/build/testing/types.js +0 -1
  190. /package/{client/dist/claude_logo.png → .next/static/media/claude_logo.d33b25b0.png} +0 -0
  191. /package/{client/dist → public}/mcp_jam.svg +0 -0
  192. /package/{client/dist → public}/mcp_jam_dark.png +0 -0
  193. /package/{client/dist → public}/mcp_jam_light.png +0 -0
@@ -1,240 +0,0 @@
1
- // server/src/testing/TestExecutor.ts
2
- import { randomUUID } from "node:crypto";
3
- export class TestExecutor {
4
- mcpProxyService;
5
- logger;
6
- constructor(mcpProxyService, logger) {
7
- this.mcpProxyService = mcpProxyService;
8
- this.logger = logger;
9
- }
10
- async executeTest(testCase) {
11
- const startTime = Date.now();
12
- const resultId = randomUUID();
13
- this.logger.info(`🧪 Starting test execution: ${testCase.name} (${testCase.id})`);
14
- try {
15
- // Validate test case
16
- this.validateTestCase(testCase);
17
- // Initialize connections to MCP servers
18
- const connections = await this.initializeConnections(testCase);
19
- // Execute the test
20
- const toolCalls = await this.executeTestLogic(testCase, connections);
21
- // Clean up connections
22
- await this.cleanupConnections(connections);
23
- const duration = Date.now() - startTime;
24
- const result = {
25
- id: resultId,
26
- testCase: testCase,
27
- toolCalls: toolCalls,
28
- duration: duration,
29
- success: true,
30
- timestamp: new Date(),
31
- metadata: {
32
- executorVersion: "1.0.0",
33
- executionMode: "single",
34
- },
35
- };
36
- this.logger.info(`✅ Test execution completed: ${testCase.name} (${duration}ms)`);
37
- return result;
38
- }
39
- catch (error) {
40
- const duration = Date.now() - startTime;
41
- const errorMessage = error instanceof Error ? error.message : String(error);
42
- this.logger.error(`❌ Test execution failed: ${testCase.name} - ${errorMessage}`);
43
- const result = {
44
- id: resultId,
45
- testCase: testCase,
46
- toolCalls: [],
47
- duration: duration,
48
- success: false,
49
- error: errorMessage,
50
- timestamp: new Date(),
51
- metadata: {
52
- executorVersion: "1.0.0",
53
- executionMode: "single",
54
- },
55
- };
56
- return result;
57
- }
58
- }
59
- validateTestCase(testCase) {
60
- if (!testCase.id) {
61
- throw new Error("Test case must have an ID");
62
- }
63
- if (!testCase.name) {
64
- throw new Error("Test case must have a name");
65
- }
66
- if (!testCase.prompt) {
67
- throw new Error("Test case must have a prompt");
68
- }
69
- if (!testCase.serverConfigs || testCase.serverConfigs.length === 0) {
70
- throw new Error("Test case must have at least one server configuration");
71
- }
72
- // Validate timeout
73
- if (testCase.timeout && testCase.timeout < 1000) {
74
- throw new Error("Test case timeout must be at least 1000ms");
75
- }
76
- }
77
- async initializeConnections(testCase) {
78
- const connections = new Map();
79
- for (const serverConfig of testCase.serverConfigs) {
80
- try {
81
- this.logger.info(`🔗 Initializing connection to server: ${serverConfig.name}`);
82
- // Use MCPProxyService to create connection
83
- let sessionId;
84
- if (serverConfig.type === "stdio") {
85
- // For STDIO, we need to create a mock response object for SSE
86
- const mockResponse = {
87
- writeHead: () => { },
88
- write: () => { },
89
- end: () => { },
90
- on: () => { },
91
- setHeader: () => { },
92
- };
93
- const connection = await this.mcpProxyService.createSSEConnection(serverConfig, mockResponse, {});
94
- sessionId = connection.sessionId;
95
- }
96
- else if (serverConfig.type === "streamable-http") {
97
- const connection = await this.mcpProxyService.createStreamableHTTPConnection(serverConfig, {});
98
- sessionId = connection.sessionId;
99
- }
100
- else {
101
- throw new Error(`Unsupported server type: ${serverConfig.type}`);
102
- }
103
- connections.set(serverConfig.id, sessionId);
104
- this.logger.info(`✅ Connected to server: ${serverConfig.name} (${sessionId})`);
105
- }
106
- catch (error) {
107
- this.logger.error(`❌ Failed to connect to server: ${serverConfig.name} - ${error}`);
108
- throw new Error(`Failed to connect to server: ${serverConfig.name}`);
109
- }
110
- }
111
- return connections;
112
- }
113
- async executeTestLogic(testCase, connections) {
114
- const toolCalls = [];
115
- // Set timeout for the entire test execution
116
- const timeout = testCase.timeout || 30000;
117
- const timeoutPromise = new Promise((_, reject) => {
118
- setTimeout(() => reject(new Error(`Test execution timed out after ${timeout}ms`)), timeout);
119
- });
120
- try {
121
- // Execute the test logic with timeout
122
- const result = await Promise.race([
123
- this.runTestWithConnections(testCase, connections),
124
- timeoutPromise,
125
- ]);
126
- return result;
127
- }
128
- catch (error) {
129
- if (error instanceof Error && error.message.includes("timed out")) {
130
- this.logger.error(`⏱️ Test execution timed out: ${testCase.name}`);
131
- }
132
- throw error;
133
- }
134
- }
135
- async runTestWithConnections(testCase, connections) {
136
- const toolCalls = [];
137
- // For now, implement a simple test execution that simulates tool calls
138
- // In a real implementation, this would involve:
139
- // 1. Sending the prompt to an LLM
140
- // 2. Processing tool calls returned by the LLM
141
- // 3. Executing those tool calls against the connected MCP servers
142
- // 4. Recording the results
143
- this.logger.info(`🤖 Processing prompt: ${testCase.prompt.substring(0, 100)}...`);
144
- // Simulate tool calls based on expected tools
145
- if (testCase.expectedTools && testCase.expectedTools.length > 0) {
146
- for (const expectedTool of testCase.expectedTools) {
147
- for (const [serverId, _sessionId] of connections.entries()) {
148
- const serverConfig = testCase.serverConfigs.find((s) => s.id === serverId);
149
- if (!serverConfig)
150
- continue;
151
- const toolCallStartTime = Date.now();
152
- try {
153
- // Simulate tool call execution
154
- await new Promise((resolve) => setTimeout(resolve, 100 + Math.random() * 400));
155
- const toolCall = {
156
- toolName: expectedTool,
157
- serverId: serverId,
158
- serverName: serverConfig.name,
159
- parameters: {
160
- prompt: testCase.prompt,
161
- timestamp: new Date().toISOString(),
162
- },
163
- response: {
164
- success: true,
165
- data: `Mock response for ${expectedTool}`,
166
- timestamp: new Date().toISOString(),
167
- },
168
- executionTimeMs: Date.now() - toolCallStartTime,
169
- success: true,
170
- timestamp: new Date(),
171
- };
172
- toolCalls.push(toolCall);
173
- this.logger.info(`🔧 Tool call executed: ${expectedTool} on ${serverConfig.name}`);
174
- }
175
- catch (error) {
176
- const errorMessage = error instanceof Error ? error.message : String(error);
177
- const toolCall = {
178
- toolName: expectedTool,
179
- serverId: serverId,
180
- serverName: serverConfig.name,
181
- parameters: {
182
- prompt: testCase.prompt,
183
- timestamp: new Date().toISOString(),
184
- },
185
- response: null,
186
- executionTimeMs: Date.now() - toolCallStartTime,
187
- success: false,
188
- error: errorMessage,
189
- timestamp: new Date(),
190
- };
191
- toolCalls.push(toolCall);
192
- this.logger.error(`❌ Tool call failed: ${expectedTool} on ${serverConfig.name} - ${errorMessage}`);
193
- }
194
- }
195
- }
196
- }
197
- else {
198
- // If no expected tools, simulate a basic interaction
199
- const serverId = connections.keys().next().value;
200
- if (serverId) {
201
- const _sessionId = connections.get(serverId);
202
- const serverConfig = testCase.serverConfigs.find((s) => s.id === serverId);
203
- if (serverConfig) {
204
- const toolCallStartTime = Date.now();
205
- const toolCall = {
206
- toolName: "default_interaction",
207
- serverId: serverId,
208
- serverName: serverConfig.name,
209
- parameters: {
210
- prompt: testCase.prompt,
211
- timestamp: new Date().toISOString(),
212
- },
213
- response: {
214
- success: true,
215
- data: "Mock response for default interaction",
216
- timestamp: new Date().toISOString(),
217
- },
218
- executionTimeMs: Date.now() - toolCallStartTime,
219
- success: true,
220
- timestamp: new Date(),
221
- };
222
- toolCalls.push(toolCall);
223
- }
224
- }
225
- }
226
- return toolCalls;
227
- }
228
- async cleanupConnections(connections) {
229
- for (const [serverId, sessionId] of connections.entries()) {
230
- try {
231
- // Note: MCPProxyService doesn't have a direct cleanup method for individual sessions
232
- // In a real implementation, you might want to add this functionality
233
- this.logger.info(`🧹 Cleaning up connection: ${serverId} (${sessionId})`);
234
- }
235
- catch (error) {
236
- this.logger.error(`❌ Failed to cleanup connection: ${serverId} - ${error}`);
237
- }
238
- }
239
- }
240
- }
@@ -1,198 +0,0 @@
1
- // server/src/testing/TestRunner.ts
2
- import { EventEmitter } from "events";
3
- import { randomUUID } from "node:crypto";
4
- export class TestRunner extends EventEmitter {
5
- mcpProxyService;
6
- _database;
7
- logger;
8
- activeTests = new Map();
9
- constructor(mcpProxyService, _database, logger) {
10
- super();
11
- this.mcpProxyService = mcpProxyService;
12
- this._database = _database;
13
- this.logger = logger;
14
- }
15
- async runTest(testCase) {
16
- const testId = randomUUID();
17
- const startTime = Date.now();
18
- this.logger.info(`Starting test: ${testCase.name} (${testId})`);
19
- try {
20
- // Create test execution context
21
- const execution = new TestExecution(testId, testCase, this.logger);
22
- this.activeTests.set(testId, execution);
23
- // Create MCP connections
24
- const connections = await this.createConnections(testCase.serverConfigs);
25
- execution.setConnections(connections);
26
- // Execute test
27
- const toolCalls = await this.executeTest(testCase, connections);
28
- // Create result
29
- const result = {
30
- id: testId,
31
- testCase,
32
- toolCalls,
33
- duration: Date.now() - startTime,
34
- success: true,
35
- timestamp: new Date(),
36
- };
37
- this.logger.info(`Test completed: ${testCase.name} (${testId})`);
38
- this.emit("testComplete", result);
39
- return result;
40
- }
41
- catch (error) {
42
- this.logger.error(`Test failed: ${testCase.name} (${testId}):`, error);
43
- const result = {
44
- id: testId,
45
- testCase,
46
- toolCalls: [],
47
- duration: Date.now() - startTime,
48
- success: false,
49
- error: error instanceof Error ? error.message : String(error),
50
- timestamp: new Date(),
51
- };
52
- this.emit("testError", result, error);
53
- return result;
54
- }
55
- finally {
56
- this.activeTests.delete(testId);
57
- }
58
- }
59
- async runBatch(testCases) {
60
- this.logger.info(`Starting batch test: ${testCases.length} tests`);
61
- // Run tests in parallel with controlled concurrency
62
- const maxConcurrency = 5;
63
- const results = [];
64
- for (let i = 0; i < testCases.length; i += maxConcurrency) {
65
- const batch = testCases.slice(i, i + maxConcurrency);
66
- const batchResults = await Promise.all(batch.map((testCase) => this.runTest(testCase)));
67
- results.push(...batchResults);
68
- }
69
- this.logger.info(`Batch test completed: ${results.length} results`);
70
- return results;
71
- }
72
- async getResults(_query) {
73
- // Mock implementation - in real version would query database
74
- return [];
75
- }
76
- async getResult(_id) {
77
- // Mock implementation - in real version would query database
78
- return null;
79
- }
80
- getActiveConnections() {
81
- return this.mcpProxyService.getActiveConnections();
82
- }
83
- async closeConnection(id) {
84
- // Note: MCPProxyService doesn't have closeConnection method
85
- // Would need to be implemented
86
- this.logger.info(`Closing connection: ${id}`);
87
- }
88
- async close() {
89
- // Close all active tests
90
- for (const [_testId, execution] of this.activeTests) {
91
- await execution.cancel();
92
- }
93
- this.activeTests.clear();
94
- // Close MCP connections
95
- await this.mcpProxyService.closeAllConnections();
96
- this.logger.info("Test runner closed");
97
- }
98
- async createConnections(serverConfigs) {
99
- const connections = [];
100
- for (const config of serverConfigs) {
101
- try {
102
- let sessionId;
103
- if (config.type === "stdio") {
104
- // For STDIO, create a mock response for SSE
105
- const mockResponse = {
106
- writeHead: () => { },
107
- write: () => { },
108
- end: () => { },
109
- on: () => { },
110
- setHeader: () => { },
111
- };
112
- const connection = await this.mcpProxyService.createSSEConnection(config, mockResponse, {});
113
- sessionId = connection.sessionId;
114
- }
115
- else if (config.type === "streamable-http") {
116
- const connection = await this.mcpProxyService.createStreamableHTTPConnection(config, {});
117
- sessionId = connection.sessionId;
118
- }
119
- else {
120
- throw new Error(`Unsupported server type: ${config.type}`);
121
- }
122
- connections.push(sessionId);
123
- this.logger.info(`Created connection: ${config.name} (${sessionId})`);
124
- }
125
- catch (error) {
126
- this.logger.error(`Failed to create connection for ${config.name}:`, error);
127
- throw error;
128
- }
129
- }
130
- return connections;
131
- }
132
- async executeTest(testCase, connections) {
133
- const toolCalls = [];
134
- const _timeout = testCase.timeout || 30000;
135
- // Simple mock execution for now
136
- // In real implementation, would use LLM to process prompt and make tool calls
137
- if (testCase.expectedTools && testCase.expectedTools.length > 0) {
138
- for (const expectedTool of testCase.expectedTools) {
139
- const toolCallStartTime = Date.now();
140
- try {
141
- // Mock tool call execution
142
- await new Promise((resolve) => setTimeout(resolve, 100));
143
- const toolCall = {
144
- toolName: expectedTool,
145
- serverId: connections[0] || "unknown",
146
- serverName: "Mock Server",
147
- parameters: { test: true },
148
- response: {
149
- success: true,
150
- data: `Mock response for ${expectedTool}`,
151
- },
152
- executionTimeMs: Date.now() - toolCallStartTime,
153
- success: true,
154
- timestamp: new Date(),
155
- };
156
- toolCalls.push(toolCall);
157
- }
158
- catch (error) {
159
- const toolCall = {
160
- toolName: expectedTool,
161
- serverId: connections[0] || "unknown",
162
- serverName: "Mock Server",
163
- parameters: { test: true },
164
- response: null,
165
- executionTimeMs: Date.now() - toolCallStartTime,
166
- success: false,
167
- error: error instanceof Error ? error.message : String(error),
168
- timestamp: new Date(),
169
- };
170
- toolCalls.push(toolCall);
171
- }
172
- }
173
- }
174
- return toolCalls;
175
- }
176
- }
177
- class TestExecution {
178
- id;
179
- testCase;
180
- logger;
181
- _connections = [];
182
- cancelled = false;
183
- constructor(id, testCase, logger) {
184
- this.id = id;
185
- this.testCase = testCase;
186
- this.logger = logger;
187
- }
188
- setConnections(connections) {
189
- this._connections = connections;
190
- }
191
- async cancel() {
192
- this.cancelled = true;
193
- this.logger.info(`Test execution cancelled: ${this.id}`);
194
- }
195
- isCancelled() {
196
- return this.cancelled;
197
- }
198
- }