@brutalist/mcp 0.5.1 → 0.6.1

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 (75) hide show
  1. package/README.md +65 -63
  2. package/dist/brutalist-server.d.ts +15 -0
  3. package/dist/brutalist-server.d.ts.map +1 -1
  4. package/dist/brutalist-server.js +405 -357
  5. package/dist/brutalist-server.js.map +1 -1
  6. package/dist/cli-agents.d.ts +8 -3
  7. package/dist/cli-agents.d.ts.map +1 -1
  8. package/dist/cli-agents.js +352 -50
  9. package/dist/cli-agents.js.map +1 -1
  10. package/dist/streaming/circuit-breaker.d.ts +186 -0
  11. package/dist/streaming/circuit-breaker.d.ts.map +1 -0
  12. package/dist/streaming/circuit-breaker.js +463 -0
  13. package/dist/streaming/circuit-breaker.js.map +1 -0
  14. package/dist/streaming/intelligent-buffer.d.ts +141 -0
  15. package/dist/streaming/intelligent-buffer.d.ts.map +1 -0
  16. package/dist/streaming/intelligent-buffer.js +555 -0
  17. package/dist/streaming/intelligent-buffer.js.map +1 -0
  18. package/dist/streaming/output-parser.d.ts +89 -0
  19. package/dist/streaming/output-parser.d.ts.map +1 -0
  20. package/dist/streaming/output-parser.js +349 -0
  21. package/dist/streaming/output-parser.js.map +1 -0
  22. package/dist/streaming/progress-tracker.d.ts +149 -0
  23. package/dist/streaming/progress-tracker.d.ts.map +1 -0
  24. package/dist/streaming/progress-tracker.js +519 -0
  25. package/dist/streaming/progress-tracker.js.map +1 -0
  26. package/dist/streaming/session-manager.d.ts +238 -0
  27. package/dist/streaming/session-manager.d.ts.map +1 -0
  28. package/dist/streaming/session-manager.js +546 -0
  29. package/dist/streaming/session-manager.js.map +1 -0
  30. package/dist/streaming/sse-transport.d.ts +95 -0
  31. package/dist/streaming/sse-transport.d.ts.map +1 -0
  32. package/dist/streaming/sse-transport.js +319 -0
  33. package/dist/streaming/sse-transport.js.map +1 -0
  34. package/dist/streaming/streaming-orchestrator.d.ts +153 -0
  35. package/dist/streaming/streaming-orchestrator.d.ts.map +1 -0
  36. package/dist/streaming/streaming-orchestrator.js +436 -0
  37. package/dist/streaming/streaming-orchestrator.js.map +1 -0
  38. package/dist/test-utils/process-manager.d.ts +61 -0
  39. package/dist/test-utils/process-manager.d.ts.map +1 -0
  40. package/dist/test-utils/process-manager.js +262 -0
  41. package/dist/test-utils/process-manager.js.map +1 -0
  42. package/dist/test-utils/server-harness.d.ts +73 -0
  43. package/dist/test-utils/server-harness.d.ts.map +1 -0
  44. package/dist/test-utils/server-harness.js +296 -0
  45. package/dist/test-utils/server-harness.js.map +1 -0
  46. package/dist/test-utils/streaming-fuzz.d.ts +57 -0
  47. package/dist/test-utils/streaming-fuzz.d.ts.map +1 -0
  48. package/dist/test-utils/streaming-fuzz.js +287 -0
  49. package/dist/test-utils/streaming-fuzz.js.map +1 -0
  50. package/dist/test-utils/test-isolation.d.ts +70 -0
  51. package/dist/test-utils/test-isolation.d.ts.map +1 -0
  52. package/dist/test-utils/test-isolation.js +193 -0
  53. package/dist/test-utils/test-isolation.js.map +1 -0
  54. package/dist/tool-definitions.d.ts +6 -0
  55. package/dist/tool-definitions.d.ts.map +1 -0
  56. package/dist/tool-definitions.js +217 -0
  57. package/dist/tool-definitions.js.map +1 -0
  58. package/dist/types/brutalist.d.ts +3 -19
  59. package/dist/types/brutalist.d.ts.map +1 -1
  60. package/dist/types/tool-config.d.ts +51 -0
  61. package/dist/types/tool-config.d.ts.map +1 -0
  62. package/dist/types/tool-config.js +24 -0
  63. package/dist/types/tool-config.js.map +1 -0
  64. package/dist/utils/pagination.d.ts +2 -2
  65. package/dist/utils/pagination.d.ts.map +1 -1
  66. package/dist/utils/pagination.js +1 -1
  67. package/dist/utils/pagination.js.map +1 -1
  68. package/dist/utils/response-cache.d.ts +96 -0
  69. package/dist/utils/response-cache.d.ts.map +1 -0
  70. package/dist/utils/response-cache.js +371 -0
  71. package/dist/utils/response-cache.js.map +1 -0
  72. package/dist/utils.d.ts.map +1 -1
  73. package/dist/utils.js +22 -3
  74. package/dist/utils.js.map +1 -1
  75. package/package.json +14 -4
@@ -0,0 +1,262 @@
1
+ import { spawn, execSync } from 'child_process';
2
+ import { logger } from '../logger.js';
3
+ import * as os from 'os';
4
+ /**
5
+ * Cross-platform process manager that tracks all spawned processes
6
+ * and ensures proper cleanup, preventing orphaned processes in tests
7
+ */
8
+ export class ProcessManager {
9
+ static instance;
10
+ processes = new Map();
11
+ isWindows = os.platform() === 'win32';
12
+ cleanupRegistered = false;
13
+ constructor() {
14
+ // Register global cleanup handlers
15
+ this.registerCleanupHandlers();
16
+ }
17
+ static getInstance() {
18
+ if (!ProcessManager.instance) {
19
+ ProcessManager.instance = new ProcessManager();
20
+ }
21
+ return ProcessManager.instance;
22
+ }
23
+ registerCleanupHandlers() {
24
+ if (this.cleanupRegistered)
25
+ return;
26
+ const cleanup = async () => {
27
+ await this.cleanup();
28
+ };
29
+ process.on('exit', cleanup);
30
+ process.on('SIGINT', cleanup);
31
+ process.on('SIGTERM', cleanup);
32
+ process.on('uncaughtException', async (err) => {
33
+ logger.error('Uncaught exception, cleaning up processes:', err);
34
+ await cleanup();
35
+ });
36
+ this.cleanupRegistered = true;
37
+ }
38
+ /**
39
+ * Spawn a managed process with automatic tracking and cleanup
40
+ */
41
+ async spawn(command, args, options = {}) {
42
+ return new Promise((resolve, reject) => {
43
+ const startTime = Date.now();
44
+ const cwd = options.cwd || process.cwd();
45
+ // Handle shell builtins that don't exist as standalone executables
46
+ const shellBuiltins = ['echo', 'cd', 'pwd', 'test', 'true', 'false'];
47
+ const needsShell = shellBuiltins.includes(command);
48
+ // Create new process group on POSIX for proper tree killing
49
+ const spawnOptions = {
50
+ cwd,
51
+ stdio: ['pipe', 'pipe', 'pipe'],
52
+ shell: needsShell, // Enable shell for builtins
53
+ env: options.env || process.env
54
+ };
55
+ // On POSIX, create new process group for tree killing
56
+ if (!this.isWindows) {
57
+ spawnOptions.detached = true;
58
+ }
59
+ const child = spawn(command, args, spawnOptions);
60
+ if (!child.pid) {
61
+ reject(new Error(`Failed to spawn process: ${command}`));
62
+ return;
63
+ }
64
+ const managed = {
65
+ pid: child.pid,
66
+ command,
67
+ args,
68
+ process: child,
69
+ stdout: '',
70
+ stderr: '',
71
+ killed: false,
72
+ startTime
73
+ };
74
+ this.processes.set(child.pid, managed);
75
+ logger.debug(`ProcessManager: Spawned ${command} with PID ${child.pid}`);
76
+ let timedOut = false;
77
+ let timer;
78
+ let killTimer;
79
+ // Set up timeout with escalation
80
+ if (options.timeout) {
81
+ timer = setTimeout(() => {
82
+ timedOut = true;
83
+ logger.warn(`Process ${child.pid} timed out after ${options.timeout}ms`);
84
+ this.killProcessTree(child.pid).catch(err => {
85
+ logger.error(`Failed to kill timed out process ${child.pid}:`, err);
86
+ });
87
+ }, options.timeout);
88
+ }
89
+ // Handle stdout with buffer limit
90
+ child.stdout?.on('data', (data) => {
91
+ const chunk = data.toString();
92
+ if (options.maxBuffer && managed.stdout.length + chunk.length > options.maxBuffer) {
93
+ logger.warn(`Process ${child.pid} exceeded stdout buffer limit`);
94
+ this.killProcessTree(child.pid);
95
+ return;
96
+ }
97
+ managed.stdout += chunk;
98
+ options.onProgress?.(chunk, 'stdout');
99
+ });
100
+ // Handle stderr with buffer limit
101
+ child.stderr?.on('data', (data) => {
102
+ const chunk = data.toString();
103
+ if (options.maxBuffer && managed.stderr.length + chunk.length > options.maxBuffer) {
104
+ logger.warn(`Process ${child.pid} exceeded stderr buffer limit`);
105
+ this.killProcessTree(child.pid);
106
+ return;
107
+ }
108
+ managed.stderr += chunk;
109
+ options.onProgress?.(chunk, 'stderr');
110
+ });
111
+ // Handle process exit
112
+ child.on('exit', (code, signal) => {
113
+ managed.killed = true;
114
+ if (timer)
115
+ clearTimeout(timer);
116
+ if (killTimer)
117
+ clearTimeout(killTimer);
118
+ this.processes.delete(child.pid);
119
+ logger.debug(`Process ${child.pid} exited with code ${code}, signal ${signal}`);
120
+ if (timedOut) {
121
+ reject(new Error(`Process timed out after ${options.timeout}ms`));
122
+ }
123
+ else if (signal) {
124
+ reject(new Error(`Process killed with signal ${signal}`));
125
+ }
126
+ else {
127
+ resolve({
128
+ stdout: managed.stdout,
129
+ stderr: managed.stderr,
130
+ exitCode: code
131
+ });
132
+ }
133
+ });
134
+ child.on('error', (error) => {
135
+ managed.killed = true;
136
+ if (timer)
137
+ clearTimeout(timer);
138
+ if (killTimer)
139
+ clearTimeout(killTimer);
140
+ this.processes.delete(child.pid);
141
+ logger.error(`Process ${child.pid} error:`, error);
142
+ reject(error);
143
+ });
144
+ // Write stdin if provided
145
+ if (options.input) {
146
+ child.stdin?.write(options.input);
147
+ child.stdin?.end();
148
+ }
149
+ });
150
+ }
151
+ /**
152
+ * Kill a process and all its children (cross-platform)
153
+ */
154
+ async killProcessTree(pid, signal = 'SIGTERM') {
155
+ const managed = this.processes.get(pid);
156
+ if (!managed || managed.killed) {
157
+ return;
158
+ }
159
+ logger.info(`Killing process tree for PID ${pid}`);
160
+ managed.killed = true;
161
+ try {
162
+ if (this.isWindows) {
163
+ // Windows: Use taskkill to kill process tree
164
+ try {
165
+ execSync(`taskkill /pid ${pid} /T /F`, { stdio: 'ignore' });
166
+ }
167
+ catch (err) {
168
+ logger.warn(`Windows taskkill failed for ${pid}, trying direct kill`);
169
+ managed.process.kill('SIGKILL');
170
+ }
171
+ }
172
+ else {
173
+ // POSIX: Kill process group
174
+ try {
175
+ // First try SIGTERM to the process group
176
+ process.kill(-pid, signal);
177
+ // Give processes 5 seconds to exit gracefully
178
+ await new Promise(resolve => setTimeout(resolve, 5000));
179
+ // Check if still running and escalate to SIGKILL
180
+ try {
181
+ process.kill(-pid, 0); // Check if process group still exists
182
+ logger.warn(`Process group ${pid} still alive after SIGTERM, using SIGKILL`);
183
+ process.kill(-pid, 'SIGKILL');
184
+ }
185
+ catch {
186
+ // Process group is gone, good
187
+ }
188
+ }
189
+ catch (err) {
190
+ // Fallback to direct process kill if group kill fails
191
+ logger.warn(`Failed to kill process group -${pid}, trying direct kill`);
192
+ managed.process.kill('SIGKILL');
193
+ }
194
+ }
195
+ }
196
+ catch (error) {
197
+ logger.error(`Failed to kill process tree ${pid}:`, error);
198
+ throw error;
199
+ }
200
+ finally {
201
+ this.processes.delete(pid);
202
+ }
203
+ }
204
+ /**
205
+ * Get all currently running managed processes
206
+ */
207
+ getRunningProcesses() {
208
+ return Array.from(this.processes.values()).filter(p => !p.killed);
209
+ }
210
+ /**
211
+ * Clean up all tracked processes
212
+ */
213
+ async cleanup() {
214
+ const running = this.getRunningProcesses();
215
+ if (running.length === 0) {
216
+ return;
217
+ }
218
+ logger.info(`ProcessManager: Cleaning up ${running.length} processes`);
219
+ const killPromises = running.map(async (managed) => {
220
+ try {
221
+ await this.killProcessTree(managed.pid);
222
+ }
223
+ catch (err) {
224
+ logger.error(`Failed to clean up process ${managed.pid}:`, err);
225
+ }
226
+ });
227
+ await Promise.all(killPromises);
228
+ this.processes.clear();
229
+ }
230
+ /**
231
+ * Get diagnostic information about running processes
232
+ */
233
+ getDiagnostics() {
234
+ const running = this.getRunningProcesses();
235
+ if (running.length === 0) {
236
+ return 'No running processes';
237
+ }
238
+ const lines = ['Running processes:'];
239
+ for (const proc of running) {
240
+ const runtime = Date.now() - proc.startTime;
241
+ lines.push(` PID ${proc.pid}: ${proc.command} ${proc.args.join(' ')} (running ${runtime}ms)`);
242
+ if (proc.stdout) {
243
+ lines.push(` Last stdout: ${proc.stdout.slice(-100)}`);
244
+ }
245
+ if (proc.stderr) {
246
+ lines.push(` Last stderr: ${proc.stderr.slice(-100)}`);
247
+ }
248
+ }
249
+ return lines.join('\n');
250
+ }
251
+ /**
252
+ * Assert no processes are leaked (for test cleanup validation)
253
+ */
254
+ assertNoLeakedProcesses() {
255
+ const running = this.getRunningProcesses();
256
+ if (running.length > 0) {
257
+ const diagnostics = this.getDiagnostics();
258
+ throw new Error(`Test leaked ${running.length} processes:\n${diagnostics}`);
259
+ }
260
+ }
261
+ }
262
+ //# sourceMappingURL=process-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-manager.js","sourceRoot":"","sources":["../../src/test-utils/process-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import { BrutalistServer } from '../brutalist-server.js';
2
+ export interface ServerHarnessOptions {
3
+ maxStartupTime?: number;
4
+ healthCheckInterval?: number;
5
+ shutdownTimeout?: number;
6
+ }
7
+ /**
8
+ * Harness for deterministic server lifecycle management in tests.
9
+ * Provides event-based readiness detection and proper cleanup.
10
+ */
11
+ export declare class ServerHarness {
12
+ private options;
13
+ private server;
14
+ private actualPort;
15
+ private baseUrl;
16
+ private startTime;
17
+ private httpServer;
18
+ private sessionId;
19
+ constructor(options?: ServerHarnessOptions);
20
+ /**
21
+ * Start server and wait for it to be ready (not just started)
22
+ */
23
+ start(config?: any): Promise<void>;
24
+ /**
25
+ * Wait for HTTP server to respond to health checks
26
+ */
27
+ private waitForHttpReady;
28
+ /**
29
+ * Parse SSE response format to extract JSON data
30
+ */
31
+ private parseSSEResponse;
32
+ /**
33
+ * Initialize MCP connection with handshake
34
+ */
35
+ private initializeMCP;
36
+ /**
37
+ * Stop server with graceful shutdown and forced kill if needed
38
+ */
39
+ stop(): Promise<void>;
40
+ /**
41
+ * Reset server state (for cleanup after failed startup)
42
+ */
43
+ private cleanup;
44
+ /**
45
+ * Get the actual port the server is listening on
46
+ */
47
+ getPort(): number;
48
+ /**
49
+ * Get the base URL for HTTP requests
50
+ */
51
+ getBaseUrl(): string;
52
+ /**
53
+ * Get the server instance for direct access if needed
54
+ */
55
+ getServer(): BrutalistServer;
56
+ /**
57
+ * Check if server is currently running
58
+ */
59
+ isRunning(): boolean;
60
+ /**
61
+ * Make a test request to the server
62
+ */
63
+ testRequest(path: string, options?: any): Promise<any>;
64
+ /**
65
+ * Execute an MCP tool via HTTP
66
+ */
67
+ executeTool(toolName: string, args: any, progressToken?: string): Promise<any>;
68
+ /**
69
+ * Get diagnostic information about the server
70
+ */
71
+ getDiagnostics(): string;
72
+ }
73
+ //# sourceMappingURL=server-harness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-harness.d.ts","sourceRoot":"","sources":["../../src/test-utils/server-harness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,MAAM,WAAW,oBAAoB;IACnC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,qBAAa,aAAa;IAQZ,OAAO,CAAC,OAAO;IAP3B,OAAO,CAAC,MAAM,CAAgC;IAC9C,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,SAAS,CAAqB;gBAElB,OAAO,GAAE,oBAAyB;IAStD;;OAEG;IACG,KAAK,CAAC,MAAM,GAAE,GAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IA2C5C;;OAEG;YACW,gBAAgB;IA0B9B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAgBxB;;OAEG;YACW,aAAa;IAwC3B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA0C3B;;OAEG;IACH,OAAO,CAAC,OAAO;IASf;;OAEG;IACH,OAAO,IAAI,MAAM;IAOjB;;OAEG;IACH,UAAU,IAAI,MAAM;IAOpB;;OAEG;IACH,SAAS,IAAI,eAAe;IAO5B;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,GAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;IA8BhE;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IA4BpF;;OAEG;IACH,cAAc,IAAI,MAAM;CAUzB"}
@@ -0,0 +1,296 @@
1
+ import { BrutalistServer } from '../brutalist-server.js';
2
+ import { logger } from '../logger.js';
3
+ /**
4
+ * Harness for deterministic server lifecycle management in tests.
5
+ * Provides event-based readiness detection and proper cleanup.
6
+ */
7
+ export class ServerHarness {
8
+ options;
9
+ server = null;
10
+ actualPort;
11
+ baseUrl;
12
+ startTime;
13
+ httpServer;
14
+ sessionId;
15
+ constructor(options = {}) {
16
+ this.options = options;
17
+ this.options = {
18
+ maxStartupTime: 30000,
19
+ healthCheckInterval: 100,
20
+ shutdownTimeout: 5000,
21
+ ...options
22
+ };
23
+ }
24
+ /**
25
+ * Start server and wait for it to be ready (not just started)
26
+ */
27
+ async start(config = {}) {
28
+ if (this.server) {
29
+ throw new Error('Server already started');
30
+ }
31
+ this.startTime = Date.now();
32
+ logger.info('ServerHarness: Starting server...');
33
+ try {
34
+ // Create server instance
35
+ this.server = new BrutalistServer({
36
+ ...config,
37
+ httpPort: config.httpPort ?? 0 // Use 0 for random port if not specified
38
+ });
39
+ // Start the server
40
+ await this.server.start();
41
+ // Get actual port for HTTP transport
42
+ if (config.transport === 'http' || !config.transport) {
43
+ this.actualPort = this.server.getActualPort();
44
+ if (!this.actualPort) {
45
+ throw new Error('Failed to get actual server port');
46
+ }
47
+ this.baseUrl = `http://localhost:${this.actualPort}`;
48
+ // Wait for HTTP server to be ready
49
+ await this.waitForHttpReady();
50
+ // Initialize MCP connection
51
+ await this.initializeMCP();
52
+ }
53
+ const startupTime = Date.now() - this.startTime;
54
+ logger.info(`ServerHarness: Server ready in ${startupTime}ms on port ${this.actualPort}`);
55
+ }
56
+ catch (error) {
57
+ // Cleanup on startup failure
58
+ logger.error('ServerHarness: Startup failed:', error);
59
+ this.cleanup();
60
+ throw error;
61
+ }
62
+ }
63
+ /**
64
+ * Wait for HTTP server to respond to health checks
65
+ */
66
+ async waitForHttpReady() {
67
+ const deadline = Date.now() + this.options.maxStartupTime;
68
+ let lastError;
69
+ while (Date.now() < deadline) {
70
+ try {
71
+ const response = await fetch(`${this.baseUrl}/health`);
72
+ if (response.ok) {
73
+ const data = await response.json();
74
+ if (data.status === 'ok') {
75
+ logger.debug('ServerHarness: Health check passed');
76
+ return;
77
+ }
78
+ }
79
+ }
80
+ catch (error) {
81
+ lastError = error;
82
+ // Server not ready yet, keep trying
83
+ }
84
+ await new Promise(resolve => setTimeout(resolve, this.options.healthCheckInterval));
85
+ }
86
+ throw new Error(`Server failed to become ready within ${this.options.maxStartupTime}ms: ${lastError?.message}`);
87
+ }
88
+ /**
89
+ * Parse SSE response format to extract JSON data
90
+ */
91
+ parseSSEResponse(responseText) {
92
+ const lines = responseText.split('\n');
93
+ for (const line of lines) {
94
+ if (line.startsWith('data: ')) {
95
+ try {
96
+ return JSON.parse(line.substring(6)); // Remove "data: " prefix
97
+ }
98
+ catch (e) {
99
+ // Continue looking for valid JSON
100
+ }
101
+ }
102
+ }
103
+ throw new Error(`Failed to parse SSE response: ${responseText}`);
104
+ }
105
+ /**
106
+ * Initialize MCP connection with handshake
107
+ */
108
+ async initializeMCP() {
109
+ const initRequest = {
110
+ jsonrpc: '2.0',
111
+ id: 1,
112
+ method: 'initialize',
113
+ params: {
114
+ protocolVersion: '2024-11-05',
115
+ capabilities: {
116
+ tools: {}
117
+ },
118
+ clientInfo: {
119
+ name: 'test-client',
120
+ version: '1.0.0'
121
+ }
122
+ }
123
+ };
124
+ const response = await this.testRequest('/mcp', {
125
+ method: 'POST',
126
+ body: JSON.stringify(initRequest)
127
+ });
128
+ // Handle SSE response format
129
+ const responseText = await response.text();
130
+ const jsonData = this.parseSSEResponse(responseText);
131
+ if (jsonData.error) {
132
+ throw new Error(`MCP initialization failed: ${JSON.stringify(jsonData.error)}`);
133
+ }
134
+ // Extract session ID from response headers
135
+ const sessionIdHeader = response.headers.get('mcp-session-id');
136
+ if (sessionIdHeader) {
137
+ this.sessionId = sessionIdHeader;
138
+ logger.debug(`MCP session ID: ${this.sessionId}`);
139
+ }
140
+ logger.debug('MCP server initialized successfully');
141
+ }
142
+ /**
143
+ * Stop server with graceful shutdown and forced kill if needed
144
+ */
145
+ async stop() {
146
+ if (!this.server) {
147
+ return;
148
+ }
149
+ logger.info('ServerHarness: Stopping server...');
150
+ const stopStart = Date.now();
151
+ try {
152
+ // Try graceful shutdown first
153
+ if (this.httpServer) {
154
+ await new Promise((resolve, reject) => {
155
+ const timeout = setTimeout(() => {
156
+ reject(new Error('Server shutdown timed out'));
157
+ }, this.options.shutdownTimeout);
158
+ this.httpServer.close((err) => {
159
+ clearTimeout(timeout);
160
+ if (err)
161
+ reject(err);
162
+ else
163
+ resolve();
164
+ });
165
+ });
166
+ }
167
+ // Additional server cleanup if needed
168
+ if (this.server) {
169
+ this.server.cleanup();
170
+ }
171
+ const stopTime = Date.now() - stopStart;
172
+ logger.info(`ServerHarness: Server stopped in ${stopTime}ms`);
173
+ }
174
+ catch (error) {
175
+ logger.error('ServerHarness: Graceful shutdown failed, forcing stop:', error);
176
+ // Force cleanup
177
+ this.httpServer = undefined;
178
+ }
179
+ finally {
180
+ this.server = null;
181
+ this.actualPort = undefined;
182
+ this.baseUrl = undefined;
183
+ }
184
+ }
185
+ /**
186
+ * Reset server state (for cleanup after failed startup)
187
+ */
188
+ cleanup() {
189
+ this.server = null;
190
+ this.actualPort = undefined;
191
+ this.baseUrl = undefined;
192
+ this.httpServer = undefined;
193
+ this.sessionId = undefined;
194
+ this.startTime = undefined;
195
+ }
196
+ /**
197
+ * Get the actual port the server is listening on
198
+ */
199
+ getPort() {
200
+ if (!this.actualPort) {
201
+ throw new Error('Server not started or port not available');
202
+ }
203
+ return this.actualPort;
204
+ }
205
+ /**
206
+ * Get the base URL for HTTP requests
207
+ */
208
+ getBaseUrl() {
209
+ if (!this.baseUrl) {
210
+ throw new Error('Server not started or not using HTTP transport');
211
+ }
212
+ return this.baseUrl;
213
+ }
214
+ /**
215
+ * Get the server instance for direct access if needed
216
+ */
217
+ getServer() {
218
+ if (!this.server) {
219
+ throw new Error('Server not started');
220
+ }
221
+ return this.server;
222
+ }
223
+ /**
224
+ * Check if server is currently running
225
+ */
226
+ isRunning() {
227
+ return this.server !== null;
228
+ }
229
+ /**
230
+ * Make a test request to the server
231
+ */
232
+ async testRequest(path, options = {}) {
233
+ if (!this.baseUrl) {
234
+ throw new Error('Server not started or not using HTTP transport');
235
+ }
236
+ const url = `${this.baseUrl}${path}`;
237
+ const headers = {
238
+ 'Content-Type': 'application/json',
239
+ 'Accept': 'application/json, text/event-stream',
240
+ ...options.headers
241
+ };
242
+ // Add session ID if available and this is an MCP request
243
+ if (this.sessionId && path === '/mcp') {
244
+ headers['Mcp-Session-Id'] = this.sessionId;
245
+ }
246
+ const response = await fetch(url, {
247
+ ...options,
248
+ headers
249
+ });
250
+ if (!response.ok && !options.allowFailure) {
251
+ const text = await response.text();
252
+ throw new Error(`Request failed: ${response.status} ${response.statusText}\n${text}`);
253
+ }
254
+ return response;
255
+ }
256
+ /**
257
+ * Execute an MCP tool via HTTP
258
+ */
259
+ async executeTool(toolName, args, progressToken) {
260
+ const request = {
261
+ jsonrpc: '2.0',
262
+ id: Date.now(),
263
+ method: 'tools/call',
264
+ params: {
265
+ name: toolName,
266
+ arguments: args,
267
+ _meta: progressToken ? { progressToken } : undefined
268
+ }
269
+ };
270
+ const response = await this.testRequest('/mcp', {
271
+ method: 'POST',
272
+ body: JSON.stringify(request)
273
+ });
274
+ // Handle SSE response format
275
+ const responseText = await response.text();
276
+ const jsonData = this.parseSSEResponse(responseText);
277
+ if (jsonData.error) {
278
+ throw new Error(`Tool execution failed: ${JSON.stringify(jsonData.error)}`);
279
+ }
280
+ return jsonData.result;
281
+ }
282
+ /**
283
+ * Get diagnostic information about the server
284
+ */
285
+ getDiagnostics() {
286
+ const lines = ['ServerHarness diagnostics:'];
287
+ lines.push(` Running: ${this.isRunning()}`);
288
+ if (this.server) {
289
+ lines.push(` Port: ${this.actualPort}`);
290
+ lines.push(` Base URL: ${this.baseUrl}`);
291
+ lines.push(` Uptime: ${Date.now() - this.startTime}ms`);
292
+ }
293
+ return lines.join('\n');
294
+ }
295
+ }
296
+ //# sourceMappingURL=server-harness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-harness.js","sourceRoot":"","sources":["../../src/test-utils/server-harness.ts"],"names":[],"mappings":"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"}