claude-flow-novice 1.5.12 → 1.5.13

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 (40) hide show
  1. package/.claude-flow-novice/dist/mcp/auth.js +347 -0
  2. package/.claude-flow-novice/dist/mcp/claude-code-wrapper.js +717 -0
  3. package/.claude-flow-novice/dist/mcp/claude-flow-tools.js +1365 -0
  4. package/.claude-flow-novice/dist/mcp/client.js +201 -0
  5. package/.claude-flow-novice/dist/mcp/index.js +192 -0
  6. package/.claude-flow-novice/dist/mcp/integrate-wrapper.js +85 -0
  7. package/.claude-flow-novice/dist/mcp/lifecycle-manager.js +348 -0
  8. package/.claude-flow-novice/dist/mcp/load-balancer.js +386 -0
  9. package/.claude-flow-novice/dist/mcp/mcp-config-manager.js +1362 -0
  10. package/.claude-flow-novice/dist/mcp/mcp-server-novice-simplified.js +583 -0
  11. package/.claude-flow-novice/dist/mcp/mcp-server-novice.js +723 -0
  12. package/.claude-flow-novice/dist/mcp/mcp-server-sdk.js +649 -0
  13. package/.claude-flow-novice/dist/mcp/mcp-server.js +2256 -0
  14. package/.claude-flow-novice/dist/mcp/orchestration-integration.js +800 -0
  15. package/.claude-flow-novice/dist/mcp/performance-monitor.js +489 -0
  16. package/.claude-flow-novice/dist/mcp/protocol-manager.js +376 -0
  17. package/.claude-flow-novice/dist/mcp/router.js +220 -0
  18. package/.claude-flow-novice/dist/mcp/ruv-swarm-tools.js +671 -0
  19. package/.claude-flow-novice/dist/mcp/ruv-swarm-wrapper.js +254 -0
  20. package/.claude-flow-novice/dist/mcp/server-with-wrapper.js +32 -0
  21. package/.claude-flow-novice/dist/mcp/server-wrapper-mode.js +26 -0
  22. package/.claude-flow-novice/dist/mcp/server.js +539 -0
  23. package/.claude-flow-novice/dist/mcp/session-manager.js +338 -0
  24. package/.claude-flow-novice/dist/mcp/sparc-modes.js +455 -0
  25. package/.claude-flow-novice/dist/mcp/swarm-tools.js +903 -0
  26. package/.claude-flow-novice/dist/mcp/tools.js +426 -0
  27. package/.claude-flow-novice/dist/src/cli/commands/swarm.js +23 -1
  28. package/.claude-flow-novice/dist/src/cli/commands/swarm.js.map +1 -1
  29. package/.claude-flow-novice/dist/src/cli/simple-commands/init/templates/CLAUDE.md +40 -101
  30. package/.claude-flow-novice/dist/src/coordination/swarm-coordinator-factory.js +36 -0
  31. package/.claude-flow-novice/dist/src/coordination/swarm-coordinator-factory.js.map +1 -0
  32. package/.claude-flow-novice/dist/src/validators/index.js +12 -0
  33. package/.claude-flow-novice/dist/src/validators/index.js.map +1 -0
  34. package/.claude-flow-novice/dist/src/validators/swarm-init-validator.js +261 -0
  35. package/.claude-flow-novice/dist/src/validators/swarm-init-validator.js.map +1 -0
  36. package/.claude-flow-novice/dist/src/validators/todowrite-batching-validator.js +204 -0
  37. package/.claude-flow-novice/dist/src/validators/todowrite-batching-validator.js.map +1 -0
  38. package/.claude-flow-novice/dist/src/validators/todowrite-integration.js +189 -0
  39. package/.claude-flow-novice/dist/src/validators/todowrite-integration.js.map +1 -0
  40. package/package.json +2 -2
@@ -0,0 +1,347 @@
1
+ /**
2
+ * Authentication and authorization for MCP
3
+ */ import { createHash, timingSafeEqual } from 'node:crypto';
4
+ /**
5
+ * Authentication manager implementation
6
+ */ export class AuthManager {
7
+ config;
8
+ logger;
9
+ revokedTokens = new Set();
10
+ tokenStore = new Map();
11
+ constructor(config, logger){
12
+ this.config = config;
13
+ this.logger = logger;
14
+ // Start token cleanup timer
15
+ if (config.enabled) {
16
+ setInterval(()=>{
17
+ this.cleanupExpiredTokens();
18
+ }, 300000); // Clean up every 5 minutes
19
+ }
20
+ }
21
+ async authenticate(credentials) {
22
+ if (!this.config.enabled) {
23
+ return {
24
+ success: true,
25
+ user: 'anonymous',
26
+ permissions: [
27
+ '*'
28
+ ]
29
+ };
30
+ }
31
+ this.logger.debug('Authenticating credentials', {
32
+ method: this.config.method,
33
+ hasCredentials: !!credentials
34
+ });
35
+ try {
36
+ switch(this.config.method){
37
+ case 'token':
38
+ return await this.authenticateToken(credentials);
39
+ case 'basic':
40
+ return await this.authenticateBasic(credentials);
41
+ case 'oauth':
42
+ return await this.authenticateOAuth(credentials);
43
+ default:
44
+ return {
45
+ success: false,
46
+ error: `Unsupported authentication method: ${this.config.method}`
47
+ };
48
+ }
49
+ } catch (error) {
50
+ this.logger.error('Authentication error', error);
51
+ return {
52
+ success: false,
53
+ error: error instanceof Error ? error instanceof Error ? error.message : String(error) : 'Authentication failed'
54
+ };
55
+ }
56
+ }
57
+ authorize(session, permission) {
58
+ if (!this.config.enabled || !session.authenticated) {
59
+ return !this.config.enabled; // If auth disabled, allow all
60
+ }
61
+ const permissions = session.authData?.permissions || [];
62
+ // Check for wildcard permission
63
+ if (permissions.includes('*')) {
64
+ return true;
65
+ }
66
+ // Check for exact permission match
67
+ if (permissions.includes(permission)) {
68
+ return true;
69
+ }
70
+ // Check for prefix-based permissions (e.g., "tools.*" matches "tools.list")
71
+ for (const perm of permissions){
72
+ if (perm.endsWith('*') && permission.startsWith(perm.slice(0, -1))) {
73
+ return true;
74
+ }
75
+ }
76
+ this.logger.warn('Authorization denied', {
77
+ sessionId: session.id,
78
+ user: session.authData?.user,
79
+ permission,
80
+ userPermissions: permissions
81
+ });
82
+ return false;
83
+ }
84
+ async validateToken(token) {
85
+ if (this.revokedTokens.has(token)) {
86
+ return {
87
+ valid: false,
88
+ error: 'Token has been revoked'
89
+ };
90
+ }
91
+ const tokenData = this.tokenStore.get(token);
92
+ if (!tokenData) {
93
+ return {
94
+ valid: false,
95
+ error: 'Invalid token'
96
+ };
97
+ }
98
+ if (tokenData.expiresAt < new Date()) {
99
+ this.tokenStore.delete(token);
100
+ return {
101
+ valid: false,
102
+ error: 'Token has expired'
103
+ };
104
+ }
105
+ return {
106
+ valid: true,
107
+ user: tokenData.user,
108
+ permissions: tokenData.permissions,
109
+ expiresAt: tokenData.expiresAt
110
+ };
111
+ }
112
+ async generateToken(userId, permissions) {
113
+ const token = this.createSecureToken();
114
+ const now = new Date();
115
+ const expiresAt = new Date(now.getTime() + (this.config.sessionTimeout || 3600000));
116
+ this.tokenStore.set(token, {
117
+ user: userId,
118
+ permissions,
119
+ createdAt: now,
120
+ expiresAt
121
+ });
122
+ this.logger.info('Token generated', {
123
+ userId,
124
+ permissions,
125
+ expiresAt
126
+ });
127
+ return token;
128
+ }
129
+ async revokeToken(token) {
130
+ this.revokedTokens.add(token);
131
+ this.tokenStore.delete(token);
132
+ this.logger.info('Token revoked', {
133
+ token: token.substring(0, 8) + '...'
134
+ });
135
+ }
136
+ async authenticateToken(credentials) {
137
+ const token = this.extractToken(credentials);
138
+ if (!token) {
139
+ return {
140
+ success: false,
141
+ error: 'Token not provided'
142
+ };
143
+ }
144
+ // Check if it's a stored token (generated by us)
145
+ const validation = await this.validateToken(token);
146
+ if (validation.valid) {
147
+ return {
148
+ success: true,
149
+ user: validation.user,
150
+ permissions: validation.permissions,
151
+ token
152
+ };
153
+ }
154
+ // Check against configured static tokens
155
+ if (this.config.tokens && this.config.tokens.length > 0) {
156
+ const isValid = this.config.tokens.some((validToken)=>{
157
+ return this.timingSafeEqual(token, validToken);
158
+ });
159
+ if (isValid) {
160
+ return {
161
+ success: true,
162
+ user: 'token-user',
163
+ permissions: [
164
+ '*'
165
+ ],
166
+ token
167
+ };
168
+ }
169
+ }
170
+ return {
171
+ success: false,
172
+ error: 'Invalid token'
173
+ };
174
+ }
175
+ async authenticateBasic(credentials) {
176
+ const { username, password } = this.extractBasicAuth(credentials);
177
+ if (!username || !password) {
178
+ return {
179
+ success: false,
180
+ error: 'Username and password required'
181
+ };
182
+ }
183
+ if (!this.config.users || this.config.users.length === 0) {
184
+ return {
185
+ success: false,
186
+ error: 'No users configured'
187
+ };
188
+ }
189
+ const user = this.config.users.find((u)=>u.username === username);
190
+ if (!user) {
191
+ return {
192
+ success: false,
193
+ error: 'Invalid username or password'
194
+ };
195
+ }
196
+ // Verify password
197
+ const isValidPassword = this.verifyPassword(password, user.password);
198
+ if (!isValidPassword) {
199
+ return {
200
+ success: false,
201
+ error: 'Invalid username or password'
202
+ };
203
+ }
204
+ // Generate a session token
205
+ const token = await this.generateToken(username, user.permissions);
206
+ return {
207
+ success: true,
208
+ user: username,
209
+ permissions: user.permissions,
210
+ token
211
+ };
212
+ }
213
+ async authenticateOAuth(credentials) {
214
+ // TODO: Implement OAuth authentication
215
+ // This would typically involve:
216
+ // 1. Validating JWT tokens
217
+ // 2. Checking token expiration
218
+ // 3. Extracting user info and permissions from token claims
219
+ this.logger.warn('OAuth authentication not yet implemented');
220
+ return {
221
+ success: false,
222
+ error: 'OAuth authentication not implemented'
223
+ };
224
+ }
225
+ extractToken(credentials) {
226
+ if (typeof credentials === 'string') {
227
+ return credentials;
228
+ }
229
+ if (typeof credentials === 'object' && credentials !== null) {
230
+ const creds = credentials;
231
+ if (typeof creds.token === 'string') {
232
+ return creds.token;
233
+ }
234
+ if (typeof creds.authorization === 'string') {
235
+ const match = creds.authorization.match(/^Bearer\s+(.+)$/i);
236
+ return match ? match[1] : null;
237
+ }
238
+ }
239
+ return null;
240
+ }
241
+ extractBasicAuth(credentials) {
242
+ if (typeof credentials === 'object' && credentials !== null) {
243
+ const creds = credentials;
244
+ if (typeof creds.username === 'string' && typeof creds.password === 'string') {
245
+ return {
246
+ username: creds.username,
247
+ password: creds.password
248
+ };
249
+ }
250
+ if (typeof creds.authorization === 'string') {
251
+ const match = creds.authorization.match(/^Basic\s+(.+)$/i);
252
+ if (match) {
253
+ try {
254
+ const decoded = atob(match[1]);
255
+ const colonIndex = decoded.indexOf(':');
256
+ if (colonIndex >= 0) {
257
+ return {
258
+ username: decoded.substring(0, colonIndex),
259
+ password: decoded.substring(colonIndex + 1)
260
+ };
261
+ }
262
+ } catch {
263
+ // Invalid base64
264
+ }
265
+ }
266
+ }
267
+ }
268
+ return {};
269
+ }
270
+ verifyPassword(providedPassword, storedPassword) {
271
+ // For now, using simple hash comparison
272
+ // In production, use proper password hashing like bcrypt
273
+ const hashedProvided = this.hashPassword(providedPassword);
274
+ const hashedStored = this.hashPassword(storedPassword);
275
+ return this.timingSafeEqual(hashedProvided, hashedStored);
276
+ }
277
+ hashPassword(password) {
278
+ return createHash('sha256').update(password).digest('hex');
279
+ }
280
+ timingSafeEqual(a, b) {
281
+ const encoder = new TextEncoder();
282
+ const bufferA = encoder.encode(a);
283
+ const bufferB = encoder.encode(b);
284
+ if (bufferA.length !== bufferB.length) {
285
+ return false;
286
+ }
287
+ return timingSafeEqual(bufferA, bufferB);
288
+ }
289
+ createSecureToken() {
290
+ // Generate a secure random token
291
+ const timestamp = Date.now().toString(36);
292
+ const random1 = Math.random().toString(36).substring(2, 15);
293
+ const random2 = Math.random().toString(36).substring(2, 15);
294
+ const hash = createHash('sha256').update(`${timestamp}${random1}${random2}`).digest('hex').substring(0, 32);
295
+ return `mcp_${timestamp}_${hash}`;
296
+ }
297
+ cleanupExpiredTokens() {
298
+ const now = new Date();
299
+ let cleaned = 0;
300
+ for (const [token, data] of this.tokenStore.entries()){
301
+ if (data.expiresAt < now) {
302
+ this.tokenStore.delete(token);
303
+ cleaned++;
304
+ }
305
+ }
306
+ if (cleaned > 0) {
307
+ this.logger.debug('Cleaned up expired tokens', {
308
+ count: cleaned
309
+ });
310
+ }
311
+ }
312
+ }
313
+ /**
314
+ * Permission constants for common operations
315
+ */ export const Permissions = {
316
+ // System operations
317
+ SYSTEM_INFO: 'system.info',
318
+ SYSTEM_HEALTH: 'system.health',
319
+ SYSTEM_METRICS: 'system.metrics',
320
+ // Tool operations
321
+ TOOLS_LIST: 'tools.list',
322
+ TOOLS_INVOKE: 'tools.invoke',
323
+ TOOLS_DESCRIBE: 'tools.describe',
324
+ // Agent operations
325
+ AGENTS_LIST: 'agents.list',
326
+ AGENTS_SPAWN: 'agents.spawn',
327
+ AGENTS_TERMINATE: 'agents.terminate',
328
+ AGENTS_INFO: 'agents.info',
329
+ // Task operations
330
+ TASKS_LIST: 'tasks.list',
331
+ TASKS_CREATE: 'tasks.create',
332
+ TASKS_CANCEL: 'tasks.cancel',
333
+ TASKS_STATUS: 'tasks.status',
334
+ // Memory operations
335
+ MEMORY_READ: 'memory.read',
336
+ MEMORY_WRITE: 'memory.write',
337
+ MEMORY_QUERY: 'memory.query',
338
+ MEMORY_DELETE: 'memory.delete',
339
+ // Administrative operations
340
+ ADMIN_CONFIG: 'admin.config',
341
+ ADMIN_LOGS: 'admin.logs',
342
+ ADMIN_SESSIONS: 'admin.sessions',
343
+ // Wildcard permission
344
+ ALL: '*'
345
+ };
346
+
347
+ //# sourceMappingURL=auth.js.map