@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,371 @@
1
+ import { createHash, randomUUID } from 'crypto';
2
+ import { gzip, gunzip } from 'zlib';
3
+ import { promisify } from 'util';
4
+ import { logger } from '../logger.js';
5
+ const gzipAsync = promisify(gzip);
6
+ const gunzipAsync = promisify(gunzip);
7
+ /**
8
+ * LRU Response Cache with TTL and memory management
9
+ */
10
+ export class ResponseCache {
11
+ entries = new Map();
12
+ analysisIdMap = new Map(); // NEW: ID to cache mapping
13
+ accessOrder = [];
14
+ stats = {
15
+ entries: 0,
16
+ totalSize: 0,
17
+ hits: 0,
18
+ misses: 0,
19
+ evictions: 0
20
+ };
21
+ // Configuration
22
+ maxEntries;
23
+ ttlMs;
24
+ maxTotalSizeMB;
25
+ maxEntrySizeMB;
26
+ compressionThresholdMB;
27
+ cleanupTimer;
28
+ constructor(options = {}) {
29
+ this.maxEntries = options.maxEntries || 50;
30
+ this.ttlMs = (options.ttlHours || 2) * 60 * 60 * 1000; // Convert hours to ms
31
+ this.maxTotalSizeMB = options.maxTotalSizeMB || 500;
32
+ this.maxEntrySizeMB = options.maxEntrySizeMB || 10;
33
+ this.compressionThresholdMB = options.compressionThresholdMB || 1;
34
+ // Log configuration
35
+ logger.info(`📦 ResponseCache initialized:`, {
36
+ maxEntries: this.maxEntries,
37
+ ttlHours: this.ttlMs / (1000 * 60 * 60),
38
+ maxTotalSizeMB: this.maxTotalSizeMB,
39
+ maxEntrySizeMB: this.maxEntrySizeMB,
40
+ compressionThresholdMB: this.compressionThresholdMB
41
+ });
42
+ // Periodic cleanup
43
+ this.cleanupTimer = setInterval(() => this.cleanupExpired(), 5 * 60 * 1000); // Every 5 minutes
44
+ // Allow Node to exit even if timer is active
45
+ this.cleanupTimer.unref();
46
+ }
47
+ /**
48
+ * Generate cache key from request parameters
49
+ */
50
+ generateCacheKey(params) {
51
+ // Create deterministic string from params
52
+ const sortedParams = Object.keys(params)
53
+ .sort()
54
+ .reduce((acc, key) => {
55
+ if (params[key] !== undefined && key !== 'analysis_id' && key !== 'offset' && key !== 'limit' && key !== 'cursor' && key !== 'force_refresh') {
56
+ acc[key] = params[key];
57
+ }
58
+ return acc;
59
+ }, {});
60
+ const paramString = JSON.stringify(sortedParams);
61
+ const hash = createHash('sha256').update(paramString).digest('hex');
62
+ return hash;
63
+ }
64
+ /**
65
+ * Generate secure analysis ID (UUID instead of 8-char hash)
66
+ */
67
+ generateAnalysisId(cacheKey) {
68
+ return randomUUID(); // Full UUID for security
69
+ }
70
+ /**
71
+ * Store response with session binding
72
+ */
73
+ async set(data, content, cacheKey, sessionId, requestId) {
74
+ const finalCacheKey = cacheKey || this.generateCacheKey(data);
75
+ const analysisId = this.generateAnalysisId(finalCacheKey);
76
+ // Check size limits before compression
77
+ const sizeInMB = Buffer.byteLength(content, 'utf8') / (1024 * 1024);
78
+ if (sizeInMB > this.maxEntrySizeMB) {
79
+ throw new Error(`Response too large: ${sizeInMB.toFixed(2)}MB > ${this.maxEntrySizeMB}MB limit`);
80
+ }
81
+ // Compress if needed
82
+ let finalContent = content;
83
+ let compressed = false;
84
+ if (sizeInMB > this.compressionThresholdMB) {
85
+ try {
86
+ const compressedBuffer = await gzipAsync(Buffer.from(content, 'utf8'));
87
+ finalContent = compressedBuffer.toString('base64');
88
+ compressed = true;
89
+ logger.debug(`📦 Compressed cache entry: ${sizeInMB.toFixed(2)}MB -> ${(compressedBuffer.length / (1024 * 1024)).toFixed(2)}MB`);
90
+ }
91
+ catch (error) {
92
+ logger.warn("Failed to compress cache entry, storing uncompressed", error);
93
+ }
94
+ }
95
+ // Create cache entry with session binding
96
+ const entry = {
97
+ content: finalContent,
98
+ metadata: {
99
+ ...data,
100
+ sessionId,
101
+ requestId,
102
+ originalSize: sizeInMB
103
+ },
104
+ timestamp: Date.now(),
105
+ accessCount: 1,
106
+ size: Buffer.byteLength(finalContent, 'utf8'),
107
+ compressed,
108
+ sessionId,
109
+ requestId
110
+ };
111
+ // Store in cache
112
+ this.entries.set(finalCacheKey, entry);
113
+ // Map analysis ID to cache key with session binding
114
+ this.analysisIdMap.set(analysisId, {
115
+ cacheKey: finalCacheKey,
116
+ sessionId: sessionId || 'anonymous',
117
+ created: Date.now()
118
+ });
119
+ // Update access order for LRU
120
+ this.updateAccessOrder(finalCacheKey);
121
+ // Update stats
122
+ this.stats.entries = this.entries.size;
123
+ this.stats.totalSize = Array.from(this.entries.values()).reduce((sum, e) => sum + e.size, 0);
124
+ // Ensure capacity limits
125
+ await this.ensureCapacity();
126
+ logger.debug(`✅ Cached response with analysis_id: ${analysisId} for session: ${sessionId?.substring(0, 8)}...`);
127
+ return { analysisId, cacheKey: finalCacheKey };
128
+ }
129
+ /**
130
+ * Retrieve response with session validation
131
+ */
132
+ async get(analysisIdOrCacheKey, sessionId) {
133
+ let cacheKey;
134
+ let requiredSessionId;
135
+ // Check if it's an analysis ID first
136
+ const mapping = this.analysisIdMap.get(analysisIdOrCacheKey);
137
+ if (mapping) {
138
+ cacheKey = mapping.cacheKey;
139
+ requiredSessionId = mapping.sessionId;
140
+ // Validate session access
141
+ if (requiredSessionId !== 'anonymous') {
142
+ if (!sessionId || sessionId !== requiredSessionId) {
143
+ logger.warn(`🚫 Session mismatch for analysis ${analysisIdOrCacheKey}: ${sessionId?.substring(0, 8) || 'none'} != ${requiredSessionId?.substring(0, 8)}`);
144
+ this.stats.misses++;
145
+ return null; // Block cross-session access
146
+ }
147
+ }
148
+ }
149
+ else {
150
+ // Direct cache key access (legacy support)
151
+ cacheKey = analysisIdOrCacheKey;
152
+ }
153
+ const entry = this.entries.get(cacheKey);
154
+ if (!entry) {
155
+ this.stats.misses++;
156
+ return null;
157
+ }
158
+ // Check TTL
159
+ if (Date.now() - entry.timestamp > this.ttlMs) {
160
+ logger.debug(`⏰ Cache entry expired: ${cacheKey.substring(0, 8)}...`);
161
+ this.entries.delete(cacheKey);
162
+ // Also clean up analysis ID mapping
163
+ if (mapping) {
164
+ this.analysisIdMap.delete(analysisIdOrCacheKey);
165
+ }
166
+ this.stats.misses++;
167
+ this.stats.evictions++;
168
+ return null;
169
+ }
170
+ // Additional session validation on the entry itself
171
+ if (sessionId && entry.sessionId && entry.sessionId !== sessionId && entry.sessionId !== 'anonymous') {
172
+ logger.warn(`🚫 Entry session mismatch for ${cacheKey.substring(0, 8)}: ${sessionId?.substring(0, 8)} != ${entry.sessionId?.substring(0, 8)}`);
173
+ this.stats.misses++;
174
+ return null;
175
+ }
176
+ // Update access tracking
177
+ entry.accessCount++;
178
+ this.updateAccessOrder(cacheKey);
179
+ this.stats.hits++;
180
+ // Decompress if needed
181
+ let content = entry.content;
182
+ if (entry.compressed) {
183
+ try {
184
+ const compressedBuffer = Buffer.from(content, 'base64');
185
+ const decompressedBuffer = await gunzipAsync(compressedBuffer);
186
+ content = decompressedBuffer.toString('utf8');
187
+ }
188
+ catch (error) {
189
+ logger.error("Failed to decompress cache entry", error);
190
+ return null;
191
+ }
192
+ }
193
+ logger.debug(`🎯 Cache hit for session ${sessionId?.substring(0, 8)}...: ${cacheKey.substring(0, 8)}...`);
194
+ return content;
195
+ }
196
+ /**
197
+ * Check if key exists in cache
198
+ */
199
+ has(keyOrId) {
200
+ // Check analysis ID mapping first
201
+ const mapping = this.analysisIdMap.get(keyOrId);
202
+ const cacheKey = mapping ? mapping.cacheKey : keyOrId;
203
+ const entry = this.entries.get(cacheKey);
204
+ if (!entry)
205
+ return false;
206
+ // Check if expired
207
+ const age = Date.now() - entry.timestamp;
208
+ if (age > this.ttlMs) {
209
+ this.delete(keyOrId);
210
+ return false;
211
+ }
212
+ return true;
213
+ }
214
+ /**
215
+ * Delete entry from cache
216
+ */
217
+ delete(keyOrId) {
218
+ // Check analysis ID mapping first
219
+ const mapping = this.analysisIdMap.get(keyOrId);
220
+ const cacheKey = mapping ? mapping.cacheKey : keyOrId;
221
+ const entry = this.entries.get(cacheKey);
222
+ if (entry) {
223
+ this.stats.totalSize -= entry.size;
224
+ // Delete from entries
225
+ this.entries.delete(cacheKey);
226
+ // Remove from analysis ID mapping if it exists
227
+ if (mapping) {
228
+ this.analysisIdMap.delete(keyOrId);
229
+ }
230
+ // Remove cache key from access order
231
+ this.accessOrder = this.accessOrder.filter(k => k !== cacheKey);
232
+ this.stats.entries = this.entries.size;
233
+ }
234
+ }
235
+ /**
236
+ * Update LRU access order
237
+ */
238
+ updateAccessOrder(key) {
239
+ this.accessOrder = this.accessOrder.filter(k => k !== key);
240
+ this.accessOrder.push(key);
241
+ }
242
+ /**
243
+ * Ensure cache has capacity for new entry
244
+ */
245
+ async ensureCapacity() {
246
+ const maxTotalSize = this.maxTotalSizeMB * 1024 * 1024;
247
+ // Check total size limit
248
+ while (this.stats.totalSize > maxTotalSize && this.accessOrder.length > 0) {
249
+ const oldestKey = this.accessOrder[0];
250
+ logger.info(`🗑️ Evicting for size limit: ${oldestKey}`);
251
+ this.delete(oldestKey);
252
+ this.stats.evictions++;
253
+ }
254
+ // Check entry count limit
255
+ while (this.entries.size >= this.maxEntries && this.accessOrder.length > 0) {
256
+ const oldestKey = this.accessOrder[0];
257
+ logger.info(`🗑️ Evicting for entry limit: ${oldestKey}`);
258
+ this.delete(oldestKey);
259
+ this.stats.evictions++;
260
+ }
261
+ }
262
+ /**
263
+ * Clean up expired entries
264
+ */
265
+ cleanupExpired() {
266
+ const now = Date.now();
267
+ let cleaned = 0;
268
+ for (const [key, entry] of this.entries.entries()) {
269
+ if (now - entry.timestamp > this.ttlMs) {
270
+ this.delete(key);
271
+ cleaned++;
272
+ }
273
+ }
274
+ if (cleaned > 0) {
275
+ logger.info(`🧹 Cleaned ${cleaned} expired cache entries`);
276
+ }
277
+ }
278
+ /**
279
+ * Get cache statistics
280
+ */
281
+ getStats() {
282
+ return { ...this.stats };
283
+ }
284
+ /**
285
+ * Retrieve response by analysis ID, returning full cached response object
286
+ */
287
+ async getByAnalysisId(analysisId, sessionId) {
288
+ const mapping = this.analysisIdMap.get(analysisId);
289
+ if (!mapping) {
290
+ this.stats.misses++;
291
+ logger.debug(`❌ Cache miss by analysis ID: ${analysisId}`);
292
+ return null;
293
+ }
294
+ // Validate session access
295
+ if (sessionId && mapping.sessionId !== sessionId && mapping.sessionId !== 'anonymous') {
296
+ logger.warn(`🚫 Session mismatch for analysis ${analysisId}: ${sessionId?.substring(0, 8)} != ${mapping.sessionId?.substring(0, 8)}`);
297
+ this.stats.misses++;
298
+ return null;
299
+ }
300
+ const entry = this.entries.get(mapping.cacheKey);
301
+ if (!entry) {
302
+ this.stats.misses++;
303
+ return null;
304
+ }
305
+ // Check TTL
306
+ const age = Date.now() - entry.timestamp;
307
+ if (age > this.ttlMs) {
308
+ logger.info(`⏰ Cache expired: ${analysisId} (age: ${(age / 1000 / 60).toFixed(0)} minutes)`);
309
+ this.delete(analysisId);
310
+ this.stats.misses++;
311
+ return null;
312
+ }
313
+ // Update access order
314
+ this.updateAccessOrder(mapping.cacheKey);
315
+ this.stats.hits++;
316
+ logger.info(`✅ Cache hit by analysis ID: ${analysisId} (age: ${(age / 1000 / 60).toFixed(0)} minutes)`);
317
+ // Decompress if needed
318
+ let content = entry.content;
319
+ if (entry.compressed) {
320
+ try {
321
+ const buffer = Buffer.from(entry.content, 'base64');
322
+ const decompressed = await gunzipAsync(buffer);
323
+ content = decompressed.toString('utf-8');
324
+ }
325
+ catch (error) {
326
+ logger.error('Decompression failed:', error);
327
+ this.delete(analysisId);
328
+ return null;
329
+ }
330
+ }
331
+ return {
332
+ content,
333
+ timestamp: entry.timestamp,
334
+ analysisId,
335
+ cacheKey: mapping.cacheKey,
336
+ requestParams: entry.metadata,
337
+ compressed: entry.compressed || false,
338
+ size: entry.size,
339
+ sessionId: entry.sessionId,
340
+ requestId: entry.requestId
341
+ };
342
+ }
343
+ /**
344
+ * Clear entire cache
345
+ */
346
+ clear() {
347
+ this.entries.clear();
348
+ this.analysisIdMap.clear();
349
+ this.accessOrder = [];
350
+ this.stats = {
351
+ entries: 0,
352
+ totalSize: 0,
353
+ hits: this.stats.hits,
354
+ misses: this.stats.misses,
355
+ evictions: this.stats.evictions
356
+ };
357
+ logger.info('🗑️ Cache cleared');
358
+ }
359
+ /**
360
+ * Destroy cache and cleanup resources
361
+ */
362
+ destroy() {
363
+ if (this.cleanupTimer) {
364
+ clearInterval(this.cleanupTimer);
365
+ this.cleanupTimer = undefined;
366
+ }
367
+ this.clear();
368
+ logger.info('💀 Cache destroyed');
369
+ }
370
+ }
371
+ //# sourceMappingURL=response-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response-cache.js","sourceRoot":"","sources":["../../src/utils/response-cache.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,OAAe,GACzB,MAAM,CAeR"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,OAAe,GACzB,MAAM,CAsCR"}
package/dist/utils.js CHANGED
@@ -10,14 +10,33 @@ import { realpathSync, existsSync } from 'fs';
10
10
  * @throws Error if the path is outside the project root or does not exist (if mustExist is true).
11
11
  */
12
12
  export function resolveAndValidatePath(projectRoot, userPath, mustExist = false) {
13
+ // Check for null byte injection before any path operations
14
+ if (userPath.includes('\0')) {
15
+ throw new Error(`Path traversal detected`);
16
+ }
13
17
  const absoluteProjectRoot = realpathSync(projectRoot);
18
+ // For absolute paths, check if they start outside project root immediately
19
+ if (resolve(userPath) === userPath) { // userPath is absolute
20
+ if (!userPath.startsWith(absoluteProjectRoot + sep) && userPath !== absoluteProjectRoot) {
21
+ throw new Error(`Path traversal detected`);
22
+ }
23
+ }
14
24
  const resolvedPath = resolve(absoluteProjectRoot, userPath);
15
- const absoluteResolvedPath = realpathSync(resolvedPath);
25
+ let absoluteResolvedPath;
26
+ const pathExists = existsSync(resolvedPath);
27
+ if (pathExists) {
28
+ // Use realpathSync to resolve symlinks and detect traversal for existing paths
29
+ absoluteResolvedPath = realpathSync(resolvedPath);
30
+ }
31
+ else {
32
+ // For non-existent paths, use logical resolution for traversal detection
33
+ absoluteResolvedPath = resolvedPath;
34
+ }
16
35
  // Ensure the resolved path is a sub-path of the project root
17
36
  if (!absoluteResolvedPath.startsWith(absoluteProjectRoot + sep) && absoluteResolvedPath !== absoluteProjectRoot) {
18
- throw new Error(`Path traversal detected: ${userPath} resolves outside project root.`);
37
+ throw new Error(`Path traversal detected`);
19
38
  }
20
- if (mustExist && !existsSync(absoluteResolvedPath)) {
39
+ if (mustExist && !pathExists) {
21
40
  throw new Error(`Path does not exist: ${userPath}`);
22
41
  }
23
42
  return absoluteResolvedPath;
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,GAAG,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAE9C;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CACpC,WAAmB,EACnB,QAAgB,EAChB,YAAqB,KAAK;IAE1B,MAAM,mBAAmB,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;IACtD,MAAM,YAAY,GAAG,OAAO,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC;IAC5D,MAAM,oBAAoB,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IAExD,6DAA6D;IAC7D,IAAI,CAAC,oBAAoB,CAAC,UAAU,CAAC,mBAAmB,GAAG,GAAG,CAAC,IAAI,oBAAoB,KAAK,mBAAmB,EAAE,CAAC;QAChH,MAAM,IAAI,KAAK,CAAC,4BAA4B,QAAQ,iCAAiC,CAAC,CAAC;IACzF,CAAC;IAED,IAAI,SAAS,IAAI,CAAC,UAAU,CAAC,oBAAoB,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,oBAAoB,CAAC;AAC9B,CAAC"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,GAAG,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAE9C;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CACpC,WAAmB,EACnB,QAAgB,EAChB,YAAqB,KAAK;IAE1B,2DAA2D;IAC3D,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,mBAAmB,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;IAEtD,2EAA2E;IAC3E,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,QAAQ,EAAE,CAAC,CAAC,uBAAuB;QAC3D,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,mBAAmB,GAAG,GAAG,CAAC,IAAI,QAAQ,KAAK,mBAAmB,EAAE,CAAC;YACxF,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,MAAM,YAAY,GAAG,OAAO,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC;IAE5D,IAAI,oBAA4B,CAAC;IACjC,MAAM,UAAU,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IAE5C,IAAI,UAAU,EAAE,CAAC;QACf,+EAA+E;QAC/E,oBAAoB,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;IACpD,CAAC;SAAM,CAAC;QACN,yEAAyE;QACzE,oBAAoB,GAAG,YAAY,CAAC;IACtC,CAAC;IAED,6DAA6D;IAC7D,IAAI,CAAC,oBAAoB,CAAC,UAAU,CAAC,mBAAmB,GAAG,GAAG,CAAC,IAAI,oBAAoB,KAAK,mBAAmB,EAAE,CAAC;QAChH,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IAED,IAAI,SAAS,IAAI,CAAC,UAAU,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,oBAAoB,CAAC;AAC9B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brutalist/mcp",
3
- "version": "0.5.1",
3
+ "version": "0.6.1",
4
4
  "description": "Deploy Claude, Codex & Gemini CLI agents to demolish your work before users do. Real file analysis. Brutal honesty. Now with intelligent pagination.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -21,15 +21,20 @@
21
21
  "prebuild": "npm run clean",
22
22
  "build": "tsc && chmod +x dist/index.js",
23
23
  "prepare": "npm run build",
24
- "prepublishOnly": "npm run test && npm audit --production && npm run build",
24
+ "prepublishOnly": "npm run test:unit && npm audit --production && npm run build",
25
25
  "watch": "tsc --watch",
26
26
  "start": "node dist/index.js",
27
27
  "dev": "npm run build && npm start",
28
28
  "debug": "DEBUG=true node --trace-warnings dist/index.js",
29
29
  "inspector": "npx @modelcontextprotocol/inspector dist/index.js",
30
30
  "test": "jest",
31
+ "test:unit": "jest --config jest.config.js",
31
32
  "test:watch": "jest --watch",
32
- "test:coverage": "jest --coverage"
33
+ "test:coverage": "jest --coverage",
34
+ "test:integration": "jest --config jest.integration.config.js --detectOpenHandles",
35
+ "test:integration:watch": "jest --config jest.integration.config.js --watch",
36
+ "test:all": "npm run test:unit && npm run test:integration",
37
+ "test:fast": "npm run test:unit"
33
38
  },
34
39
  "keywords": [
35
40
  "brutalist",
@@ -75,17 +80,22 @@
75
80
  },
76
81
  "dependencies": {
77
82
  "@modelcontextprotocol/sdk": "^1.18.1",
83
+ "express": "^4.18.2",
78
84
  "zod": "^3.24.2"
79
85
  },
80
86
  "devDependencies": {
81
- "@types/express": "^5.0.3",
87
+ "@types/eventsource": "^1.1.15",
88
+ "@types/express": "^4.17.21",
82
89
  "@types/jest": "^30.0.0",
83
90
  "@types/node": "^20.17.28",
84
91
  "@types/node-fetch": "^2.6.13",
92
+ "@types/supertest": "^6.0.3",
85
93
  "@types/ws": "^8.18.1",
86
94
  "dotenv": "^17.2.2",
95
+ "eventsource": "^4.0.0",
87
96
  "jest": "^30.1.3",
88
97
  "node-fetch": "^3.3.2",
98
+ "supertest": "^7.1.4",
89
99
  "ts-jest": "^29.4.2",
90
100
  "typescript": "^5.8.2",
91
101
  "ws": "^8.18.3"