@sparkleideas/shared 3.0.0-alpha.7
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.
- package/README.md +323 -0
- package/__tests__/hooks/bash-safety.test.ts +289 -0
- package/__tests__/hooks/file-organization.test.ts +335 -0
- package/__tests__/hooks/git-commit.test.ts +336 -0
- package/__tests__/hooks/index.ts +23 -0
- package/__tests__/hooks/session-hooks.test.ts +357 -0
- package/__tests__/hooks/task-hooks.test.ts +193 -0
- package/docs/EVENTS_IMPLEMENTATION_SUMMARY.md +388 -0
- package/docs/EVENTS_QUICK_REFERENCE.md +470 -0
- package/docs/EVENTS_README.md +352 -0
- package/package.json +39 -0
- package/src/core/config/defaults.ts +207 -0
- package/src/core/config/index.ts +15 -0
- package/src/core/config/loader.ts +271 -0
- package/src/core/config/schema.ts +188 -0
- package/src/core/config/validator.ts +209 -0
- package/src/core/event-bus.ts +236 -0
- package/src/core/index.ts +22 -0
- package/src/core/interfaces/agent.interface.ts +251 -0
- package/src/core/interfaces/coordinator.interface.ts +363 -0
- package/src/core/interfaces/event.interface.ts +267 -0
- package/src/core/interfaces/index.ts +19 -0
- package/src/core/interfaces/memory.interface.ts +332 -0
- package/src/core/interfaces/task.interface.ts +223 -0
- package/src/core/orchestrator/event-coordinator.ts +122 -0
- package/src/core/orchestrator/health-monitor.ts +214 -0
- package/src/core/orchestrator/index.ts +89 -0
- package/src/core/orchestrator/lifecycle-manager.ts +263 -0
- package/src/core/orchestrator/session-manager.ts +279 -0
- package/src/core/orchestrator/task-manager.ts +317 -0
- package/src/events/domain-events.ts +584 -0
- package/src/events/event-store.test.ts +387 -0
- package/src/events/event-store.ts +588 -0
- package/src/events/example-usage.ts +293 -0
- package/src/events/index.ts +90 -0
- package/src/events/projections.ts +561 -0
- package/src/events/state-reconstructor.ts +349 -0
- package/src/events.ts +367 -0
- package/src/hooks/INTEGRATION.md +658 -0
- package/src/hooks/README.md +532 -0
- package/src/hooks/example-usage.ts +499 -0
- package/src/hooks/executor.ts +379 -0
- package/src/hooks/hooks.test.ts +421 -0
- package/src/hooks/index.ts +131 -0
- package/src/hooks/registry.ts +333 -0
- package/src/hooks/safety/bash-safety.ts +604 -0
- package/src/hooks/safety/file-organization.ts +473 -0
- package/src/hooks/safety/git-commit.ts +623 -0
- package/src/hooks/safety/index.ts +46 -0
- package/src/hooks/session-hooks.ts +559 -0
- package/src/hooks/task-hooks.ts +513 -0
- package/src/hooks/types.ts +357 -0
- package/src/hooks/verify-exports.test.ts +125 -0
- package/src/index.ts +195 -0
- package/src/mcp/connection-pool.ts +438 -0
- package/src/mcp/index.ts +183 -0
- package/src/mcp/server.ts +774 -0
- package/src/mcp/session-manager.ts +428 -0
- package/src/mcp/tool-registry.ts +566 -0
- package/src/mcp/transport/http.ts +557 -0
- package/src/mcp/transport/index.ts +294 -0
- package/src/mcp/transport/stdio.ts +324 -0
- package/src/mcp/transport/websocket.ts +484 -0
- package/src/mcp/types.ts +565 -0
- package/src/plugin-interface.ts +663 -0
- package/src/plugin-loader.ts +638 -0
- package/src/plugin-registry.ts +604 -0
- package/src/plugins/index.ts +34 -0
- package/src/plugins/official/hive-mind-plugin.ts +330 -0
- package/src/plugins/official/index.ts +24 -0
- package/src/plugins/official/maestro-plugin.ts +508 -0
- package/src/plugins/types.ts +108 -0
- package/src/resilience/bulkhead.ts +277 -0
- package/src/resilience/circuit-breaker.ts +326 -0
- package/src/resilience/index.ts +26 -0
- package/src/resilience/rate-limiter.ts +420 -0
- package/src/resilience/retry.ts +224 -0
- package/src/security/index.ts +39 -0
- package/src/security/input-validation.ts +265 -0
- package/src/security/secure-random.ts +159 -0
- package/src/services/index.ts +16 -0
- package/src/services/v3-progress.service.ts +505 -0
- package/src/types/agent.types.ts +144 -0
- package/src/types/index.ts +22 -0
- package/src/types/mcp.types.ts +300 -0
- package/src/types/memory.types.ts +263 -0
- package/src/types/swarm.types.ts +255 -0
- package/src/types/task.types.ts +205 -0
- package/src/types.ts +367 -0
- package/src/utils/secure-logger.d.ts +69 -0
- package/src/utils/secure-logger.d.ts.map +1 -0
- package/src/utils/secure-logger.js +208 -0
- package/src/utils/secure-logger.js.map +1 -0
- package/src/utils/secure-logger.ts +257 -0
- package/tmp.json +0 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V3 MCP Connection Pool Manager
|
|
3
|
+
*
|
|
4
|
+
* High-performance connection pooling for MCP server:
|
|
5
|
+
* - Reusable connections to reduce overhead
|
|
6
|
+
* - Max connections: 10 (configurable)
|
|
7
|
+
* - Idle timeout handling with automatic eviction
|
|
8
|
+
* - Connection health monitoring
|
|
9
|
+
* - Graceful shutdown support
|
|
10
|
+
*
|
|
11
|
+
* Performance Targets:
|
|
12
|
+
* - Connection acquire: <5ms
|
|
13
|
+
* - Connection release: <1ms
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { EventEmitter } from 'events';
|
|
17
|
+
import {
|
|
18
|
+
PooledConnection,
|
|
19
|
+
ConnectionPoolStats,
|
|
20
|
+
ConnectionPoolConfig,
|
|
21
|
+
ConnectionState,
|
|
22
|
+
IConnectionPool,
|
|
23
|
+
ILogger,
|
|
24
|
+
TransportType,
|
|
25
|
+
} from './types.js';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Default connection pool configuration
|
|
29
|
+
*/
|
|
30
|
+
const DEFAULT_POOL_CONFIG: ConnectionPoolConfig = {
|
|
31
|
+
maxConnections: 10,
|
|
32
|
+
minConnections: 2,
|
|
33
|
+
idleTimeout: 30000, // 30 seconds
|
|
34
|
+
acquireTimeout: 5000, // 5 seconds
|
|
35
|
+
maxWaitingClients: 50,
|
|
36
|
+
evictionRunInterval: 10000, // 10 seconds
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Connection wrapper with lifecycle management
|
|
41
|
+
*/
|
|
42
|
+
class ManagedConnection implements PooledConnection {
|
|
43
|
+
public state: ConnectionState = 'idle';
|
|
44
|
+
public lastUsedAt: Date;
|
|
45
|
+
public useCount: number = 0;
|
|
46
|
+
|
|
47
|
+
constructor(
|
|
48
|
+
public readonly id: string,
|
|
49
|
+
public readonly transport: TransportType,
|
|
50
|
+
public readonly createdAt: Date = new Date(),
|
|
51
|
+
public metadata?: Record<string, unknown>
|
|
52
|
+
) {
|
|
53
|
+
this.lastUsedAt = this.createdAt;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Mark connection as busy
|
|
58
|
+
*/
|
|
59
|
+
acquire(): void {
|
|
60
|
+
this.state = 'busy';
|
|
61
|
+
this.lastUsedAt = new Date();
|
|
62
|
+
this.useCount++;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Mark connection as idle
|
|
67
|
+
*/
|
|
68
|
+
release(): void {
|
|
69
|
+
this.state = 'idle';
|
|
70
|
+
this.lastUsedAt = new Date();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Check if connection is expired
|
|
75
|
+
*/
|
|
76
|
+
isExpired(idleTimeout: number): boolean {
|
|
77
|
+
if (this.state !== 'idle') return false;
|
|
78
|
+
return Date.now() - this.lastUsedAt.getTime() > idleTimeout;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Check if connection is healthy
|
|
83
|
+
*/
|
|
84
|
+
isHealthy(): boolean {
|
|
85
|
+
return this.state !== 'error' && this.state !== 'closed';
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Waiting client for connection
|
|
91
|
+
*/
|
|
92
|
+
interface WaitingClient {
|
|
93
|
+
resolve: (connection: PooledConnection) => void;
|
|
94
|
+
reject: (error: Error) => void;
|
|
95
|
+
timestamp: number;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Connection Pool Manager
|
|
100
|
+
*
|
|
101
|
+
* Manages a pool of reusable connections for optimal performance
|
|
102
|
+
*/
|
|
103
|
+
export class ConnectionPool extends EventEmitter implements IConnectionPool {
|
|
104
|
+
private readonly config: ConnectionPoolConfig;
|
|
105
|
+
private readonly connections: Map<string, ManagedConnection> = new Map();
|
|
106
|
+
private readonly waitingClients: WaitingClient[] = [];
|
|
107
|
+
private evictionTimer?: NodeJS.Timeout;
|
|
108
|
+
private connectionCounter: number = 0;
|
|
109
|
+
private isShuttingDown: boolean = false;
|
|
110
|
+
|
|
111
|
+
// Statistics
|
|
112
|
+
private stats = {
|
|
113
|
+
totalAcquired: 0,
|
|
114
|
+
totalReleased: 0,
|
|
115
|
+
totalCreated: 0,
|
|
116
|
+
totalDestroyed: 0,
|
|
117
|
+
acquireTimeTotal: 0,
|
|
118
|
+
acquireCount: 0,
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
constructor(
|
|
122
|
+
config: Partial<ConnectionPoolConfig> = {},
|
|
123
|
+
private readonly logger: ILogger,
|
|
124
|
+
private readonly transportType: TransportType = 'in-process'
|
|
125
|
+
) {
|
|
126
|
+
super();
|
|
127
|
+
this.config = { ...DEFAULT_POOL_CONFIG, ...config };
|
|
128
|
+
this.startEvictionTimer();
|
|
129
|
+
this.initializeMinConnections();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Initialize minimum number of connections
|
|
134
|
+
*/
|
|
135
|
+
private async initializeMinConnections(): Promise<void> {
|
|
136
|
+
const promises: Promise<ManagedConnection>[] = [];
|
|
137
|
+
for (let i = 0; i < this.config.minConnections; i++) {
|
|
138
|
+
promises.push(this.createConnection());
|
|
139
|
+
}
|
|
140
|
+
await Promise.all(promises);
|
|
141
|
+
this.logger.debug('Connection pool initialized', {
|
|
142
|
+
minConnections: this.config.minConnections,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Create a new connection
|
|
148
|
+
*/
|
|
149
|
+
private async createConnection(): Promise<ManagedConnection> {
|
|
150
|
+
const id = `conn-${++this.connectionCounter}-${Date.now()}`;
|
|
151
|
+
const connection = new ManagedConnection(id, this.transportType);
|
|
152
|
+
|
|
153
|
+
this.connections.set(id, connection);
|
|
154
|
+
this.stats.totalCreated++;
|
|
155
|
+
|
|
156
|
+
this.emit('pool:connection:created', { connectionId: id });
|
|
157
|
+
this.logger.debug('Connection created', { id, total: this.connections.size });
|
|
158
|
+
|
|
159
|
+
return connection;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Acquire a connection from the pool
|
|
164
|
+
*/
|
|
165
|
+
async acquire(): Promise<PooledConnection> {
|
|
166
|
+
const startTime = performance.now();
|
|
167
|
+
|
|
168
|
+
if (this.isShuttingDown) {
|
|
169
|
+
throw new Error('Connection pool is shutting down');
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Try to find an idle connection
|
|
173
|
+
for (const connection of this.connections.values()) {
|
|
174
|
+
if (connection.state === 'idle' && connection.isHealthy()) {
|
|
175
|
+
connection.acquire();
|
|
176
|
+
this.stats.totalAcquired++;
|
|
177
|
+
this.recordAcquireTime(startTime);
|
|
178
|
+
|
|
179
|
+
this.emit('pool:connection:acquired', { connectionId: connection.id });
|
|
180
|
+
this.logger.debug('Connection acquired from pool', { id: connection.id });
|
|
181
|
+
|
|
182
|
+
return connection;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Create new connection if under limit
|
|
187
|
+
if (this.connections.size < this.config.maxConnections) {
|
|
188
|
+
const connection = await this.createConnection();
|
|
189
|
+
connection.acquire();
|
|
190
|
+
this.stats.totalAcquired++;
|
|
191
|
+
this.recordAcquireTime(startTime);
|
|
192
|
+
|
|
193
|
+
this.emit('pool:connection:acquired', { connectionId: connection.id });
|
|
194
|
+
return connection;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Wait for a connection to become available
|
|
198
|
+
return this.waitForConnection(startTime);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Wait for a connection to become available
|
|
203
|
+
*/
|
|
204
|
+
private waitForConnection(startTime: number): Promise<PooledConnection> {
|
|
205
|
+
return new Promise((resolve, reject) => {
|
|
206
|
+
if (this.waitingClients.length >= this.config.maxWaitingClients) {
|
|
207
|
+
reject(new Error('Connection pool exhausted - max waiting clients reached'));
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const client: WaitingClient = {
|
|
212
|
+
resolve: (connection) => {
|
|
213
|
+
this.recordAcquireTime(startTime);
|
|
214
|
+
resolve(connection);
|
|
215
|
+
},
|
|
216
|
+
reject,
|
|
217
|
+
timestamp: Date.now(),
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
this.waitingClients.push(client);
|
|
221
|
+
|
|
222
|
+
// Set timeout
|
|
223
|
+
setTimeout(() => {
|
|
224
|
+
const index = this.waitingClients.indexOf(client);
|
|
225
|
+
if (index !== -1) {
|
|
226
|
+
this.waitingClients.splice(index, 1);
|
|
227
|
+
reject(new Error(`Connection acquire timeout after ${this.config.acquireTimeout}ms`));
|
|
228
|
+
}
|
|
229
|
+
}, this.config.acquireTimeout);
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Release a connection back to the pool
|
|
235
|
+
*/
|
|
236
|
+
release(connection: PooledConnection): void {
|
|
237
|
+
const managed = this.connections.get(connection.id);
|
|
238
|
+
if (!managed) {
|
|
239
|
+
this.logger.warn('Attempted to release unknown connection', { id: connection.id });
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Check for waiting clients first
|
|
244
|
+
const waitingClient = this.waitingClients.shift();
|
|
245
|
+
if (waitingClient) {
|
|
246
|
+
managed.acquire();
|
|
247
|
+
this.stats.totalAcquired++;
|
|
248
|
+
this.emit('pool:connection:acquired', { connectionId: connection.id });
|
|
249
|
+
waitingClient.resolve(managed);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Return to pool
|
|
254
|
+
managed.release();
|
|
255
|
+
this.stats.totalReleased++;
|
|
256
|
+
|
|
257
|
+
this.emit('pool:connection:released', { connectionId: connection.id });
|
|
258
|
+
this.logger.debug('Connection released to pool', { id: connection.id });
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Destroy a connection (remove from pool)
|
|
263
|
+
*/
|
|
264
|
+
destroy(connection: PooledConnection): void {
|
|
265
|
+
const managed = this.connections.get(connection.id);
|
|
266
|
+
if (!managed) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
managed.state = 'closed';
|
|
271
|
+
this.connections.delete(connection.id);
|
|
272
|
+
this.stats.totalDestroyed++;
|
|
273
|
+
|
|
274
|
+
this.emit('pool:connection:destroyed', { connectionId: connection.id });
|
|
275
|
+
this.logger.debug('Connection destroyed', { id: connection.id });
|
|
276
|
+
|
|
277
|
+
// Create new connection to maintain minimum if needed
|
|
278
|
+
if (this.connections.size < this.config.minConnections && !this.isShuttingDown) {
|
|
279
|
+
this.createConnection().catch((err) => {
|
|
280
|
+
this.logger.error('Failed to create replacement connection', err);
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Get pool statistics
|
|
287
|
+
*/
|
|
288
|
+
getStats(): ConnectionPoolStats {
|
|
289
|
+
let idleCount = 0;
|
|
290
|
+
let busyCount = 0;
|
|
291
|
+
|
|
292
|
+
for (const connection of this.connections.values()) {
|
|
293
|
+
if (connection.state === 'idle') idleCount++;
|
|
294
|
+
else if (connection.state === 'busy') busyCount++;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return {
|
|
298
|
+
totalConnections: this.connections.size,
|
|
299
|
+
idleConnections: idleCount,
|
|
300
|
+
busyConnections: busyCount,
|
|
301
|
+
pendingRequests: this.waitingClients.length,
|
|
302
|
+
totalAcquired: this.stats.totalAcquired,
|
|
303
|
+
totalReleased: this.stats.totalReleased,
|
|
304
|
+
totalCreated: this.stats.totalCreated,
|
|
305
|
+
totalDestroyed: this.stats.totalDestroyed,
|
|
306
|
+
avgAcquireTime: this.stats.acquireCount > 0
|
|
307
|
+
? this.stats.acquireTimeTotal / this.stats.acquireCount
|
|
308
|
+
: 0,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Drain the pool (wait for all connections to be released)
|
|
314
|
+
*/
|
|
315
|
+
async drain(): Promise<void> {
|
|
316
|
+
this.isShuttingDown = true;
|
|
317
|
+
this.logger.info('Draining connection pool');
|
|
318
|
+
|
|
319
|
+
// Reject all waiting clients
|
|
320
|
+
while (this.waitingClients.length > 0) {
|
|
321
|
+
const client = this.waitingClients.shift();
|
|
322
|
+
client?.reject(new Error('Connection pool is draining'));
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Wait for busy connections to be released
|
|
326
|
+
const maxWait = 10000; // 10 seconds
|
|
327
|
+
const startTime = Date.now();
|
|
328
|
+
|
|
329
|
+
while (Date.now() - startTime < maxWait) {
|
|
330
|
+
let busyCount = 0;
|
|
331
|
+
for (const connection of this.connections.values()) {
|
|
332
|
+
if (connection.state === 'busy') busyCount++;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (busyCount === 0) break;
|
|
336
|
+
|
|
337
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
this.logger.info('Connection pool drained');
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Clear all connections from the pool
|
|
345
|
+
*/
|
|
346
|
+
async clear(): Promise<void> {
|
|
347
|
+
this.stopEvictionTimer();
|
|
348
|
+
await this.drain();
|
|
349
|
+
|
|
350
|
+
// Destroy all remaining connections
|
|
351
|
+
for (const connection of this.connections.values()) {
|
|
352
|
+
connection.state = 'closed';
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
this.connections.clear();
|
|
356
|
+
this.logger.info('Connection pool cleared');
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Start the eviction timer
|
|
361
|
+
*/
|
|
362
|
+
private startEvictionTimer(): void {
|
|
363
|
+
this.evictionTimer = setInterval(() => {
|
|
364
|
+
this.evictIdleConnections();
|
|
365
|
+
}, this.config.evictionRunInterval);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Stop the eviction timer
|
|
370
|
+
*/
|
|
371
|
+
private stopEvictionTimer(): void {
|
|
372
|
+
if (this.evictionTimer) {
|
|
373
|
+
clearInterval(this.evictionTimer);
|
|
374
|
+
this.evictionTimer = undefined;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Evict idle connections that have exceeded the timeout
|
|
380
|
+
*/
|
|
381
|
+
private evictIdleConnections(): void {
|
|
382
|
+
if (this.isShuttingDown) return;
|
|
383
|
+
|
|
384
|
+
const toEvict: ManagedConnection[] = [];
|
|
385
|
+
|
|
386
|
+
for (const connection of this.connections.values()) {
|
|
387
|
+
if (
|
|
388
|
+
connection.isExpired(this.config.idleTimeout) &&
|
|
389
|
+
this.connections.size > this.config.minConnections
|
|
390
|
+
) {
|
|
391
|
+
toEvict.push(connection);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
for (const connection of toEvict) {
|
|
396
|
+
this.destroy(connection);
|
|
397
|
+
this.logger.debug('Evicted idle connection', { id: connection.id });
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (toEvict.length > 0) {
|
|
401
|
+
this.logger.info('Evicted idle connections', { count: toEvict.length });
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Record acquire time for statistics
|
|
407
|
+
*/
|
|
408
|
+
private recordAcquireTime(startTime: number): void {
|
|
409
|
+
const duration = performance.now() - startTime;
|
|
410
|
+
this.stats.acquireTimeTotal += duration;
|
|
411
|
+
this.stats.acquireCount++;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Get all connections (for debugging/monitoring)
|
|
416
|
+
*/
|
|
417
|
+
getConnections(): PooledConnection[] {
|
|
418
|
+
return Array.from(this.connections.values());
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Check if pool is healthy
|
|
423
|
+
*/
|
|
424
|
+
isHealthy(): boolean {
|
|
425
|
+
return !this.isShuttingDown && this.connections.size >= this.config.minConnections;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Create a connection pool with default settings
|
|
431
|
+
*/
|
|
432
|
+
export function createConnectionPool(
|
|
433
|
+
config: Partial<ConnectionPoolConfig> = {},
|
|
434
|
+
logger: ILogger,
|
|
435
|
+
transportType: TransportType = 'in-process'
|
|
436
|
+
): ConnectionPool {
|
|
437
|
+
return new ConnectionPool(config, logger, transportType);
|
|
438
|
+
}
|
package/src/mcp/index.ts
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V3 MCP Module
|
|
3
|
+
*
|
|
4
|
+
* Optimized MCP (Model Context Protocol) implementation for Claude-Flow V3
|
|
5
|
+
*
|
|
6
|
+
* Features:
|
|
7
|
+
* - High-performance server with <400ms startup
|
|
8
|
+
* - Connection pooling with max 10 connections
|
|
9
|
+
* - Multiple transport support (stdio, http, websocket, in-process)
|
|
10
|
+
* - Fast tool registry with <10ms registration
|
|
11
|
+
* - Session management with timeout handling
|
|
12
|
+
* - Comprehensive metrics and monitoring
|
|
13
|
+
*
|
|
14
|
+
* Performance Targets:
|
|
15
|
+
* - Server startup: <400ms
|
|
16
|
+
* - Tool registration: <10ms
|
|
17
|
+
* - Tool execution: <50ms overhead
|
|
18
|
+
* - Connection acquire: <5ms
|
|
19
|
+
*
|
|
20
|
+
* @module @sparkleideas/mcp
|
|
21
|
+
* @version 3.0.0
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
// Core types - using 'export type' for TypeScript isolatedModules compatibility
|
|
25
|
+
export type {
|
|
26
|
+
// Protocol types
|
|
27
|
+
JsonRpcVersion,
|
|
28
|
+
RequestId,
|
|
29
|
+
MCPMessage,
|
|
30
|
+
MCPRequest,
|
|
31
|
+
MCPResponse,
|
|
32
|
+
MCPNotification,
|
|
33
|
+
MCPError,
|
|
34
|
+
|
|
35
|
+
// Server configuration
|
|
36
|
+
TransportType,
|
|
37
|
+
AuthMethod,
|
|
38
|
+
AuthConfig,
|
|
39
|
+
LoadBalancerConfig,
|
|
40
|
+
ConnectionPoolConfig,
|
|
41
|
+
MCPServerConfig,
|
|
42
|
+
|
|
43
|
+
// Session types
|
|
44
|
+
SessionState,
|
|
45
|
+
MCPSession,
|
|
46
|
+
MCPClientInfo,
|
|
47
|
+
|
|
48
|
+
// Capability types
|
|
49
|
+
MCPCapabilities,
|
|
50
|
+
MCPProtocolVersion,
|
|
51
|
+
MCPInitializeParams,
|
|
52
|
+
MCPInitializeResult,
|
|
53
|
+
|
|
54
|
+
// Tool types
|
|
55
|
+
JSONSchema,
|
|
56
|
+
ToolContext,
|
|
57
|
+
ToolHandler,
|
|
58
|
+
MCPTool,
|
|
59
|
+
ToolCallResult,
|
|
60
|
+
ToolRegistrationOptions,
|
|
61
|
+
|
|
62
|
+
// Transport types
|
|
63
|
+
RequestHandler,
|
|
64
|
+
NotificationHandler,
|
|
65
|
+
TransportHealthStatus,
|
|
66
|
+
ITransport,
|
|
67
|
+
|
|
68
|
+
// Connection pool types
|
|
69
|
+
ConnectionState,
|
|
70
|
+
PooledConnection,
|
|
71
|
+
ConnectionPoolStats,
|
|
72
|
+
IConnectionPool,
|
|
73
|
+
|
|
74
|
+
// Metrics types
|
|
75
|
+
ToolCallMetrics,
|
|
76
|
+
MCPServerMetrics,
|
|
77
|
+
SessionMetrics,
|
|
78
|
+
|
|
79
|
+
// Event types
|
|
80
|
+
MCPEventType,
|
|
81
|
+
MCPEvent,
|
|
82
|
+
EventHandler,
|
|
83
|
+
|
|
84
|
+
// Logger
|
|
85
|
+
LogLevel,
|
|
86
|
+
ILogger,
|
|
87
|
+
} from './types.js';
|
|
88
|
+
|
|
89
|
+
// Import types for local use in quickStart function
|
|
90
|
+
import type { MCPServerConfig, ILogger } from './types.js';
|
|
91
|
+
|
|
92
|
+
// Error handling - values (not types)
|
|
93
|
+
export { ErrorCodes, MCPServerError } from './types.js';
|
|
94
|
+
|
|
95
|
+
// Server - class and interface exports
|
|
96
|
+
import { MCPServer, createMCPServer } from './server.js';
|
|
97
|
+
export { MCPServer, createMCPServer };
|
|
98
|
+
export type { IMCPServer } from './server.js';
|
|
99
|
+
|
|
100
|
+
// Tool Registry
|
|
101
|
+
export { ToolRegistry, createToolRegistry, defineTool } from './tool-registry.js';
|
|
102
|
+
|
|
103
|
+
// Session Manager - class and factory exports
|
|
104
|
+
import { SessionManager, createSessionManager } from './session-manager.js';
|
|
105
|
+
export { SessionManager, createSessionManager };
|
|
106
|
+
export type { SessionConfig } from './session-manager.js';
|
|
107
|
+
|
|
108
|
+
// Connection Pool
|
|
109
|
+
export { ConnectionPool, createConnectionPool } from './connection-pool.js';
|
|
110
|
+
|
|
111
|
+
// Transport layer - values
|
|
112
|
+
export {
|
|
113
|
+
// Factory
|
|
114
|
+
createTransport,
|
|
115
|
+
createInProcessTransport,
|
|
116
|
+
TransportManager,
|
|
117
|
+
createTransportManager,
|
|
118
|
+
DEFAULT_TRANSPORT_CONFIGS,
|
|
119
|
+
|
|
120
|
+
// Specific transports
|
|
121
|
+
StdioTransport,
|
|
122
|
+
HttpTransport,
|
|
123
|
+
WebSocketTransport,
|
|
124
|
+
} from './transport/index.js';
|
|
125
|
+
|
|
126
|
+
// Transport layer - types
|
|
127
|
+
export type {
|
|
128
|
+
TransportConfig,
|
|
129
|
+
StdioTransportConfig,
|
|
130
|
+
HttpTransportConfig,
|
|
131
|
+
WebSocketTransportConfig,
|
|
132
|
+
} from './transport/index.js';
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Quick start function to create and configure an MCP server
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* import { quickStart } from '@sparkleideas/mcp';
|
|
140
|
+
*
|
|
141
|
+
* const server = await quickStart({
|
|
142
|
+
* transport: 'stdio',
|
|
143
|
+
* name: 'My MCP Server',
|
|
144
|
+
* });
|
|
145
|
+
*
|
|
146
|
+
* // Register custom tools
|
|
147
|
+
* server.registerTool({
|
|
148
|
+
* name: 'my-tool',
|
|
149
|
+
* description: 'My custom tool',
|
|
150
|
+
* inputSchema: { type: 'object', properties: {} },
|
|
151
|
+
* handler: async () => ({ result: 'success' }),
|
|
152
|
+
* });
|
|
153
|
+
*
|
|
154
|
+
* // Start server
|
|
155
|
+
* await server.start();
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
export async function quickStart(
|
|
159
|
+
config: Partial<MCPServerConfig>,
|
|
160
|
+
logger?: ILogger
|
|
161
|
+
): Promise<MCPServer> {
|
|
162
|
+
// Create default logger if not provided
|
|
163
|
+
const defaultLogger: ILogger = logger || {
|
|
164
|
+
debug: (msg, data) => console.debug(`[DEBUG] ${msg}`, data || ''),
|
|
165
|
+
info: (msg, data) => console.info(`[INFO] ${msg}`, data || ''),
|
|
166
|
+
warn: (msg, data) => console.warn(`[WARN] ${msg}`, data || ''),
|
|
167
|
+
error: (msg, data) => console.error(`[ERROR] ${msg}`, data || ''),
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const server = createMCPServer(config, defaultLogger);
|
|
171
|
+
|
|
172
|
+
return server;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Module version
|
|
177
|
+
*/
|
|
178
|
+
export const VERSION = '3.0.0';
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Module name
|
|
182
|
+
*/
|
|
183
|
+
export const MODULE_NAME = '@sparkleideas/mcp';
|