@ai-jshook/mcp 0.1.1 → 0.1.3

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.
@@ -1,6 +1,6 @@
1
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
2
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
- import * as z from 'zod';
3
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
4
4
  import { logger } from '../utils/logger.js';
5
5
  import { CacheManager } from '../utils/cache.js';
6
6
  import { CodeCollector } from '../modules/collector/CodeCollector.js';
@@ -14,6 +14,11 @@ import { BrowserToolHandlers } from './BrowserToolHandlers.js';
14
14
  import { DebuggerToolHandlers } from './DebuggerToolHandlers.js';
15
15
  import { AdvancedToolHandlers } from './AdvancedToolHandlers.js';
16
16
  import { AIHookToolHandlers } from './AIHookToolHandlers.js';
17
+ import { browserTools } from './BrowserToolDefinitions.js';
18
+ import { debuggerTools } from './DebuggerToolDefinitions.js';
19
+ import { advancedTools } from './AdvancedToolDefinitions.js';
20
+ import { aiHookTools } from './AIHookToolDefinitions.js';
21
+ import { tokenBudgetTools } from './TokenBudgetToolDefinitions.js';
17
22
  import { Deobfuscator } from '../modules/deobfuscator/Deobfuscator.js';
18
23
  import { AdvancedDeobfuscator } from '../modules/deobfuscator/AdvancedDeobfuscator.js';
19
24
  import { ASTOptimizer } from '../modules/deobfuscator/ASTOptimizer.js';
@@ -24,6 +29,7 @@ import { CryptoDetector } from '../modules/crypto/CryptoDetector.js';
24
29
  import { HookManager } from '../modules/hook/HookManager.js';
25
30
  import { TokenBudgetManager } from '../utils/TokenBudgetManager.js';
26
31
  import { UnifiedCacheManager } from '../utils/UnifiedCacheManager.js';
32
+ import { cacheTools } from './CacheToolDefinitions.js';
27
33
  export class MCPServer {
28
34
  server;
29
35
  cache;
@@ -73,11 +79,15 @@ export class MCPServer {
73
79
  logger.info('TokenBudgetManager initialized');
74
80
  this.unifiedCache = UnifiedCacheManager.getInstance();
75
81
  logger.info('UnifiedCacheManager initialized');
76
- this.server = new McpServer({
82
+ this.server = new Server({
77
83
  name: config.mcp.name,
78
84
  version: config.mcp.version,
85
+ }, {
86
+ capabilities: {
87
+ tools: {},
88
+ },
79
89
  });
80
- this.registerTools();
90
+ this.setupHandlers();
81
91
  logger.info('MCP Server initialized with tools');
82
92
  }
83
93
  async registerCaches() {
@@ -107,711 +117,728 @@ export class MCPServer {
107
117
  logger.warn('Continuing without cache registration');
108
118
  }
109
119
  }
110
- registerTools() {
111
- this.registerCoreTools();
112
- this.registerBrowserTools();
113
- this.registerDebuggerTools();
114
- this.registerAdvancedTools();
115
- this.registerAIHookTools();
116
- this.registerTokenBudgetTools();
117
- this.registerCacheTools();
118
- logger.info('All MCP tools registered');
119
- }
120
- registerCoreTools() {
121
- const server = this.server;
122
- server.registerTool('collect_code', {
123
- title: 'Collect Code',
124
- description: 'Collect JavaScript code from a target website',
125
- inputSchema: {
126
- url: z.string().describe('Target website URL'),
127
- includeInline: z.boolean().optional().default(true),
128
- includeExternal: z.boolean().optional().default(true),
129
- includeDynamic: z.boolean().optional().default(false),
130
- smartMode: z.enum(['summary', 'priority', 'incremental', 'full']).optional().default('full'),
131
- compress: z.boolean().optional().default(false),
132
- maxTotalSize: z.number().optional().default(2097152),
133
- maxFileSize: z.number().optional().default(500),
134
- priorities: z.array(z.string()).optional(),
135
- },
136
- outputSchema: {
137
- files: z.array(z.object({
138
- url: z.string(),
139
- type: z.string(),
140
- size: z.number(),
141
- content: z.string(),
142
- })),
143
- totalSize: z.number(),
144
- collectTime: z.number(),
145
- },
146
- }, async (args) => {
147
- const result = await this.collector.collect({
148
- url: args.url,
149
- includeInline: args.includeInline,
150
- includeExternal: args.includeExternal,
151
- includeDynamic: args.includeDynamic,
152
- smartMode: args.smartMode,
153
- compress: args.compress,
154
- maxTotalSize: args.maxTotalSize,
155
- maxFileSize: args.maxFileSize ? args.maxFileSize * 1024 : undefined,
156
- priorities: args.priorities,
157
- });
158
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
159
- });
160
- server.registerTool('search_in_scripts', {
161
- title: 'Search in Scripts',
162
- description: 'Search for keywords in collected scripts',
163
- inputSchema: {
164
- keyword: z.string().describe('Keyword to search for'),
165
- isRegex: z.boolean().optional().default(false),
166
- caseSensitive: z.boolean().optional().default(false),
167
- contextLines: z.number().optional().default(3),
168
- maxMatches: z.number().optional().default(100),
169
- returnSummary: z.boolean().optional().default(false),
170
- maxContextSize: z.number().optional().default(50000),
171
- },
172
- }, async (args) => {
173
- const result = await this.handleSearchInScripts(args);
174
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
175
- });
176
- server.registerTool('extract_function_tree', {
177
- title: 'Extract Function Tree',
178
- description: 'Extract a function and its dependencies',
179
- inputSchema: {
180
- scriptId: z.string().describe('Script ID'),
181
- functionName: z.string().describe('Name of the function to extract'),
182
- maxDepth: z.number().optional().default(3),
183
- maxSize: z.number().optional().default(500),
184
- includeComments: z.boolean().optional().default(true),
185
- },
186
- }, async (args) => {
187
- const result = await this.handleExtractFunctionTree(args);
188
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
189
- });
190
- server.registerTool('deobfuscate', {
191
- title: 'Deobfuscate',
192
- description: 'Deobfuscate JavaScript code',
193
- inputSchema: {
194
- code: z.string().describe('Obfuscated code to deobfuscate'),
195
- aggressive: z.boolean().optional().default(false),
196
- },
197
- }, async (args) => {
198
- const result = await this.handleDeobfuscate(args);
199
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
200
- });
201
- server.registerTool('understand_code', {
202
- title: 'Understand Code',
203
- description: 'Analyze and understand code structure',
204
- inputSchema: {
205
- code: z.string().describe('Code to analyze'),
206
- context: z.record(z.string(), z.unknown()).optional(),
207
- focus: z.enum(['structure', 'business', 'security', 'all']).optional().default('all'),
208
- },
209
- }, async (args) => {
210
- const result = await this.handleUnderstandCode(args);
211
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
212
- });
213
- server.registerTool('detect_crypto', {
214
- title: 'Detect Crypto',
215
- description: 'Detect encryption algorithms in code',
216
- inputSchema: {
217
- code: z.string().describe('Code to analyze'),
218
- },
219
- }, async (args) => {
220
- const result = await this.handleDetectCrypto(args);
221
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
222
- });
223
- server.registerTool('manage_hooks', {
224
- title: 'Manage Hooks',
225
- description: 'Manage JavaScript hooks',
226
- inputSchema: {
227
- action: z.enum(['create', 'list', 'records', 'clear']).describe('Action'),
228
- target: z.string().optional(),
229
- type: z.enum(['function', 'xhr', 'fetch', 'websocket', 'localstorage', 'cookie']).optional(),
230
- hookAction: z.enum(['log', 'block', 'modify']).optional().default('log'),
231
- customCode: z.string().optional(),
232
- hookId: z.string().optional(),
233
- },
234
- }, async (args) => {
235
- const result = await this.handleManageHooks(args);
236
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
237
- });
238
- server.registerTool('detect_obfuscation', {
239
- title: 'Detect Obfuscation',
240
- description: 'Detect obfuscation types in code',
241
- inputSchema: {
242
- code: z.string().describe('Code to analyze'),
243
- generateReport: z.boolean().optional().default(true),
244
- },
245
- }, async (args) => {
246
- const result = await this.handleDetectObfuscation(args);
247
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
248
- });
249
- server.registerTool('advanced_deobfuscate', {
250
- title: 'Advanced Deobfuscate',
251
- description: 'Advanced deobfuscation with VM support',
252
- inputSchema: {
253
- code: z.string().describe('Code to deobfuscate'),
254
- detectOnly: z.boolean().optional().default(false),
255
- aggressiveVM: z.boolean().optional().default(false),
256
- useASTOptimization: z.boolean().optional().default(true),
257
- timeout: z.number().optional().default(60000),
258
- },
259
- }, async (args) => {
260
- const result = await this.handleAdvancedDeobfuscate(args);
261
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
262
- });
263
- server.registerTool('clear_collected_data', {
264
- title: 'Clear Collected Data',
265
- description: 'Clear all collected data',
266
- inputSchema: {},
267
- }, async () => {
268
- const result = await this.handleClearCollectedData({});
269
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
120
+ setupHandlers() {
121
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => {
122
+ const tools = this.getTools();
123
+ logger.info(`Returning ${tools.length} tools`);
124
+ return {
125
+ tools,
126
+ };
270
127
  });
271
- server.registerTool('get_collection_stats', {
272
- title: 'Get Collection Stats',
273
- description: 'Get statistics about collected data',
274
- inputSchema: {},
275
- }, async () => {
276
- const result = await this.handleGetCollectionStats({});
277
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
128
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
129
+ const { name, arguments: args } = request.params;
130
+ logger.info(`Tool called: ${name}`);
131
+ try {
132
+ const toolArgs = args || {};
133
+ const response = await this.executeToolWithTracking(name, toolArgs);
134
+ return response;
135
+ }
136
+ catch (error) {
137
+ logger.error(`Tool execution failed: ${name}`, error);
138
+ return {
139
+ content: [
140
+ {
141
+ type: 'text',
142
+ text: `Error: ${error.message}`,
143
+ },
144
+ ],
145
+ isError: true,
146
+ };
147
+ }
278
148
  });
279
149
  }
280
- registerBrowserTools() {
281
- const server = this.server;
282
- server.registerTool('browser_launch', {
283
- title: 'Browser Launch',
284
- description: 'Launch a browser instance',
285
- inputSchema: {
286
- headless: z.boolean().optional().default(true),
287
- stealth: z.boolean().optional().default(true),
288
- userDataDir: z.string().optional(),
289
- },
290
- }, async (args) => {
291
- const result = await this.browserHandlers.handleBrowserLaunch(args);
292
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
293
- });
294
- server.registerTool('browser_close', {
295
- title: 'Browser Close',
296
- description: 'Close the browser',
297
- inputSchema: {},
298
- }, async () => {
299
- const result = await this.browserHandlers.handleBrowserClose({});
300
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
301
- });
302
- server.registerTool('browser_status', {
303
- title: 'Browser Status',
304
- description: 'Get browser status',
305
- inputSchema: {},
306
- }, async () => {
307
- const result = await this.browserHandlers.handleBrowserStatus({});
308
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
309
- });
310
- server.registerTool('page_navigate', {
311
- title: 'Page Navigate',
312
- description: 'Navigate to a URL',
313
- inputSchema: {
314
- url: z.string().describe('URL to navigate to'),
315
- waitUntil: z.enum(['load', 'domcontentloaded', 'networkidle', 'commit']).optional().default('networkidle'),
316
- },
317
- }, async (args) => {
318
- const result = await this.browserHandlers.handlePageNavigate(args);
319
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
320
- });
321
- server.registerTool('page_reload', {
322
- title: 'Page Reload',
323
- description: 'Reload current page',
324
- inputSchema: {},
325
- }, async () => {
326
- const result = await this.browserHandlers.handlePageReload({});
327
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
328
- });
329
- server.registerTool('page_screenshot', {
330
- title: 'Page Screenshot',
331
- description: 'Take a screenshot of the page',
332
- inputSchema: {
333
- fullPage: z.boolean().optional().default(false),
334
- path: z.string().optional(),
335
- },
336
- }, async (args) => {
337
- const result = await this.browserHandlers.handlePageScreenshot(args);
338
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
339
- });
340
- server.registerTool('dom_query_selector', {
341
- title: 'DOM Query Selector',
342
- description: 'Query a single element',
343
- inputSchema: {
344
- selector: z.string().describe('CSS selector'),
345
- },
346
- }, async (args) => {
347
- const result = await this.browserHandlers.handleDOMQuerySelector(args);
348
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
349
- });
350
- server.registerTool('dom_query_all', {
351
- title: 'DOM Query All',
352
- description: 'Query multiple elements',
353
- inputSchema: {
354
- selector: z.string().describe('CSS selector'),
355
- },
356
- }, async (args) => {
357
- const result = await this.browserHandlers.handleDOMQueryAll(args);
358
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
359
- });
360
- server.registerTool('page_evaluate', {
361
- title: 'Page Evaluate',
362
- description: 'Execute JavaScript in page context',
363
- inputSchema: {
364
- script: z.string().describe('JavaScript code to execute'),
365
- },
366
- }, async (args) => {
367
- const result = await this.browserHandlers.handlePageEvaluate(args);
368
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
369
- });
370
- server.registerTool('page_click', {
371
- title: 'Page Click',
372
- description: 'Click on an element',
373
- inputSchema: {
374
- selector: z.string().describe('CSS selector'),
375
- delay: z.number().optional(),
376
- },
377
- }, async (args) => {
378
- const result = await this.browserHandlers.handlePageClick(args);
379
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
380
- });
381
- server.registerTool('page_type', {
382
- title: 'Page Type',
383
- description: 'Type text into an input',
384
- inputSchema: {
385
- selector: z.string().describe('CSS selector'),
386
- text: z.string().describe('Text to type'),
387
- delay: z.number().optional(),
388
- },
389
- }, async (args) => {
390
- const result = await this.browserHandlers.handlePageType(args);
391
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
392
- });
393
- server.registerTool('captcha_detect', {
394
- title: 'CAPTCHA Detect',
395
- description: 'Detect if page has CAPTCHA',
396
- inputSchema: {},
397
- }, async () => {
398
- const result = await this.browserHandlers.handleCaptchaDetect({});
399
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
400
- });
401
- server.registerTool('captcha_wait', {
402
- title: 'CAPTCHA Wait',
403
- description: 'Wait for CAPTCHA to be solved',
404
- inputSchema: {
405
- timeout: z.number().optional().default(300000),
406
- },
407
- }, async (args) => {
408
- const result = await this.browserHandlers.handleCaptchaWait(args);
409
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
410
- });
411
- server.registerTool('stealth_inject', {
412
- title: 'Stealth Inject',
413
- description: 'Inject anti-detection scripts',
414
- inputSchema: {},
415
- }, async () => {
416
- const result = await this.browserHandlers.handleStealthInject({});
417
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
418
- });
419
- server.registerTool('console_enable', {
420
- title: 'Console Enable',
421
- description: 'Enable console monitoring',
422
- inputSchema: {},
423
- }, async () => {
424
- const result = await this.browserHandlers.handleConsoleEnable({});
425
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
426
- });
427
- server.registerTool('console_get_logs', {
428
- title: 'Console Get Logs',
429
- description: 'Get captured console logs',
430
- inputSchema: {},
431
- }, async () => {
432
- const result = await this.browserHandlers.handleConsoleGetLogs({});
433
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
434
- });
435
- server.registerTool('get_all_scripts', {
436
- title: 'Get All Scripts',
437
- description: 'Get all collected scripts',
438
- inputSchema: {},
439
- }, async () => {
440
- const result = await this.browserHandlers.handleGetAllScripts({});
441
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
442
- });
443
- server.registerTool('get_script_source', {
444
- title: 'Get Script Source',
445
- description: 'Get source code of a script',
446
- inputSchema: {
447
- scriptId: z.string().describe('Script ID'),
448
- },
449
- }, async (args) => {
450
- const result = await this.browserHandlers.handleGetScriptSource(args);
451
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
452
- });
453
- server.registerTool('network_enable', {
454
- title: 'Network Enable',
455
- description: 'Enable network monitoring',
456
- inputSchema: {},
457
- }, async () => {
458
- const result = await this.advancedHandlers.handleNetworkEnable({});
459
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
460
- });
461
- server.registerTool('network_get_requests', {
462
- title: 'Network Get Requests',
463
- description: 'Get captured network requests',
464
- inputSchema: {},
465
- }, async () => {
466
- const result = await this.advancedHandlers.handleNetworkGetRequests({});
467
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
468
- });
150
+ async executeToolWithTracking(name, args) {
151
+ try {
152
+ const response = await this.executeToolInternal(name, args);
153
+ this.tokenBudget.recordToolCall(name, args, response);
154
+ return response;
155
+ }
156
+ catch (error) {
157
+ const errorResponse = {
158
+ content: [{ type: 'text', text: `Error: ${error.message}` }],
159
+ isError: true,
160
+ };
161
+ this.tokenBudget.recordToolCall(name, args, errorResponse);
162
+ throw error;
163
+ }
469
164
  }
470
- registerDebuggerTools() {
471
- const server = this.server;
472
- const handlers = this.debuggerHandlers;
473
- server.registerTool('debugger_enable', {
474
- title: 'Debugger Enable',
475
- description: 'Enable the debugger',
476
- inputSchema: {},
477
- }, async () => {
478
- const result = await handlers.handleDebuggerEnable({});
479
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
480
- });
481
- server.registerTool('debugger_disable', {
482
- title: 'Debugger Disable',
483
- description: 'Disable the debugger',
484
- inputSchema: {},
485
- }, async () => {
486
- const result = await handlers.handleDebuggerDisable({});
487
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
488
- });
489
- server.registerTool('debugger_pause', {
490
- title: 'Debugger Pause',
491
- description: 'Pause script execution',
492
- inputSchema: {},
493
- }, async () => {
494
- const result = await handlers.handleDebuggerPause({});
495
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
496
- });
497
- server.registerTool('debugger_resume', {
498
- title: 'Debugger Resume',
499
- description: 'Resume script execution',
500
- inputSchema: {},
501
- }, async () => {
502
- const result = await handlers.handleDebuggerResume({});
503
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
504
- });
505
- server.registerTool('debugger_step_into', {
506
- title: 'Debugger Step Into',
507
- description: 'Step into next function call',
508
- inputSchema: {},
509
- }, async () => {
510
- const result = await handlers.handleDebuggerStepInto({});
511
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
512
- });
513
- server.registerTool('debugger_step_over', {
514
- title: 'Debugger Step Over',
515
- description: 'Step over next function call',
516
- inputSchema: {},
517
- }, async () => {
518
- const result = await handlers.handleDebuggerStepOver({});
519
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
520
- });
521
- server.registerTool('debugger_step_out', {
522
- title: 'Debugger Step Out',
523
- description: 'Step out of current function',
524
- inputSchema: {},
525
- }, async () => {
526
- const result = await handlers.handleDebuggerStepOut({});
527
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
528
- });
529
- server.registerTool('breakpoint_set', {
530
- title: 'Breakpoint Set',
531
- description: 'Set a breakpoint',
532
- inputSchema: {
533
- url: z.string().optional(),
534
- scriptId: z.string().optional(),
535
- lineNumber: z.number().describe('Line number'),
536
- columnNumber: z.number().optional(),
537
- condition: z.string().optional(),
538
- },
539
- }, async (args) => {
540
- const result = await handlers.handleBreakpointSet(args);
541
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
542
- });
543
- server.registerTool('breakpoint_remove', {
544
- title: 'Breakpoint Remove',
545
- description: 'Remove a breakpoint',
546
- inputSchema: {
547
- breakpointId: z.string().describe('Breakpoint ID'),
165
+ async executeToolInternal(name, toolArgs) {
166
+ switch (name) {
167
+ case 'get_token_budget_stats':
168
+ return await this.handleGetTokenBudgetStats(toolArgs);
169
+ case 'manual_token_cleanup':
170
+ return await this.handleManualTokenCleanup(toolArgs);
171
+ case 'reset_token_budget':
172
+ return await this.handleResetTokenBudget(toolArgs);
173
+ case 'get_cache_stats':
174
+ return await this.handleGetCacheStats(toolArgs);
175
+ case 'smart_cache_cleanup':
176
+ return await this.handleSmartCacheCleanup(toolArgs);
177
+ case 'clear_all_caches':
178
+ return await this.handleClearAllCaches(toolArgs);
179
+ case 'collect_code':
180
+ return await this.handleCollectCode(toolArgs);
181
+ case 'search_in_scripts':
182
+ return await this.handleSearchInScripts(toolArgs);
183
+ case 'extract_function_tree':
184
+ return await this.handleExtractFunctionTree(toolArgs);
185
+ case 'deobfuscate':
186
+ return await this.handleDeobfuscate(toolArgs);
187
+ case 'understand_code':
188
+ return await this.handleUnderstandCode(toolArgs);
189
+ case 'detect_crypto':
190
+ return await this.handleDetectCrypto(toolArgs);
191
+ case 'manage_hooks':
192
+ return await this.handleManageHooks(toolArgs);
193
+ case 'detect_obfuscation':
194
+ return await this.handleDetectObfuscation(toolArgs);
195
+ case 'advanced_deobfuscate':
196
+ return await this.handleAdvancedDeobfuscate(toolArgs);
197
+ case 'clear_collected_data':
198
+ return await this.handleClearCollectedData(toolArgs);
199
+ case 'get_collection_stats':
200
+ return await this.handleGetCollectionStats(toolArgs);
201
+ case 'get_detailed_data':
202
+ return await this.browserHandlers.handleGetDetailedData(toolArgs);
203
+ case 'browser_launch':
204
+ return await this.browserHandlers.handleBrowserLaunch(toolArgs);
205
+ case 'browser_close':
206
+ return await this.browserHandlers.handleBrowserClose(toolArgs);
207
+ case 'browser_status':
208
+ return await this.browserHandlers.handleBrowserStatus(toolArgs);
209
+ case 'page_navigate':
210
+ return await this.browserHandlers.handlePageNavigate(toolArgs);
211
+ case 'page_reload':
212
+ return await this.browserHandlers.handlePageReload(toolArgs);
213
+ case 'page_back':
214
+ return await this.browserHandlers.handlePageBack(toolArgs);
215
+ case 'page_forward':
216
+ return await this.browserHandlers.handlePageForward(toolArgs);
217
+ case 'dom_query_selector':
218
+ return await this.browserHandlers.handleDOMQuerySelector(toolArgs);
219
+ case 'dom_query_all':
220
+ return await this.browserHandlers.handleDOMQueryAll(toolArgs);
221
+ case 'dom_get_structure':
222
+ return await this.browserHandlers.handleDOMGetStructure(toolArgs);
223
+ case 'dom_find_clickable':
224
+ return await this.browserHandlers.handleDOMFindClickable(toolArgs);
225
+ case 'page_click':
226
+ return await this.browserHandlers.handlePageClick(toolArgs);
227
+ case 'page_type':
228
+ return await this.browserHandlers.handlePageType(toolArgs);
229
+ case 'page_select':
230
+ return await this.browserHandlers.handlePageSelect(toolArgs);
231
+ case 'page_hover':
232
+ return await this.browserHandlers.handlePageHover(toolArgs);
233
+ case 'page_scroll':
234
+ return await this.browserHandlers.handlePageScroll(toolArgs);
235
+ case 'page_wait_for_selector':
236
+ return await this.browserHandlers.handlePageWaitForSelector(toolArgs);
237
+ case 'page_evaluate':
238
+ return await this.browserHandlers.handlePageEvaluate(toolArgs);
239
+ case 'page_screenshot':
240
+ return await this.browserHandlers.handlePageScreenshot(toolArgs);
241
+ case 'get_all_scripts':
242
+ return await this.browserHandlers.handleGetAllScripts(toolArgs);
243
+ case 'get_script_source':
244
+ return await this.browserHandlers.handleGetScriptSource(toolArgs);
245
+ case 'console_enable':
246
+ return await this.browserHandlers.handleConsoleEnable(toolArgs);
247
+ case 'console_get_logs':
248
+ return await this.browserHandlers.handleConsoleGetLogs(toolArgs);
249
+ case 'console_execute':
250
+ return await this.browserHandlers.handleConsoleExecute(toolArgs);
251
+ case 'dom_get_computed_style':
252
+ return await this.browserHandlers.handleDOMGetComputedStyle(toolArgs);
253
+ case 'dom_find_by_text':
254
+ return await this.browserHandlers.handleDOMFindByText(toolArgs);
255
+ case 'dom_get_xpath':
256
+ return await this.browserHandlers.handleDOMGetXPath(toolArgs);
257
+ case 'dom_is_in_viewport':
258
+ return await this.browserHandlers.handleDOMIsInViewport(toolArgs);
259
+ case 'page_get_performance':
260
+ return await this.browserHandlers.handlePageGetPerformance(toolArgs);
261
+ case 'page_inject_script':
262
+ return await this.browserHandlers.handlePageInjectScript(toolArgs);
263
+ case 'page_set_cookies':
264
+ return await this.browserHandlers.handlePageSetCookies(toolArgs);
265
+ case 'page_get_cookies':
266
+ return await this.browserHandlers.handlePageGetCookies(toolArgs);
267
+ case 'page_clear_cookies':
268
+ return await this.browserHandlers.handlePageClearCookies(toolArgs);
269
+ case 'page_set_viewport':
270
+ return await this.browserHandlers.handlePageSetViewport(toolArgs);
271
+ case 'page_emulate_device':
272
+ return await this.browserHandlers.handlePageEmulateDevice(toolArgs);
273
+ case 'page_get_local_storage':
274
+ return await this.browserHandlers.handlePageGetLocalStorage(toolArgs);
275
+ case 'page_set_local_storage':
276
+ return await this.browserHandlers.handlePageSetLocalStorage(toolArgs);
277
+ case 'page_press_key':
278
+ return await this.browserHandlers.handlePagePressKey(toolArgs);
279
+ case 'page_get_all_links':
280
+ return await this.browserHandlers.handlePageGetAllLinks(toolArgs);
281
+ case 'captcha_detect':
282
+ return await this.browserHandlers.handleCaptchaDetect(toolArgs);
283
+ case 'captcha_wait':
284
+ return await this.browserHandlers.handleCaptchaWait(toolArgs);
285
+ case 'captcha_config':
286
+ return await this.browserHandlers.handleCaptchaConfig(toolArgs);
287
+ case 'stealth_inject':
288
+ return await this.browserHandlers.handleStealthInject(toolArgs);
289
+ case 'stealth_set_user_agent':
290
+ return await this.browserHandlers.handleStealthSetUserAgent(toolArgs);
291
+ case 'ai_hook_generate':
292
+ return await this.aiHookHandlers.handleAIHookGenerate(toolArgs);
293
+ case 'ai_hook_inject':
294
+ return await this.aiHookHandlers.handleAIHookInject(toolArgs);
295
+ case 'ai_hook_get_data':
296
+ return await this.aiHookHandlers.handleAIHookGetData(toolArgs);
297
+ case 'ai_hook_list':
298
+ return await this.aiHookHandlers.handleAIHookList(toolArgs);
299
+ case 'ai_hook_clear':
300
+ return await this.aiHookHandlers.handleAIHookClear(toolArgs);
301
+ case 'ai_hook_toggle':
302
+ return await this.aiHookHandlers.handleAIHookToggle(toolArgs);
303
+ case 'ai_hook_export':
304
+ return await this.aiHookHandlers.handleAIHookExport(toolArgs);
305
+ case 'debugger_enable':
306
+ return await this.debuggerHandlers.handleDebuggerEnable(toolArgs);
307
+ case 'debugger_disable':
308
+ return await this.debuggerHandlers.handleDebuggerDisable(toolArgs);
309
+ case 'debugger_pause':
310
+ return await this.debuggerHandlers.handleDebuggerPause(toolArgs);
311
+ case 'debugger_resume':
312
+ return await this.debuggerHandlers.handleDebuggerResume(toolArgs);
313
+ case 'debugger_step_into':
314
+ return await this.debuggerHandlers.handleDebuggerStepInto(toolArgs);
315
+ case 'debugger_step_over':
316
+ return await this.debuggerHandlers.handleDebuggerStepOver(toolArgs);
317
+ case 'debugger_step_out':
318
+ return await this.debuggerHandlers.handleDebuggerStepOut(toolArgs);
319
+ case 'breakpoint_set':
320
+ return await this.debuggerHandlers.handleBreakpointSet(toolArgs);
321
+ case 'breakpoint_remove':
322
+ return await this.debuggerHandlers.handleBreakpointRemove(toolArgs);
323
+ case 'breakpoint_list':
324
+ return await this.debuggerHandlers.handleBreakpointList(toolArgs);
325
+ case 'get_call_stack':
326
+ return await this.debuggerHandlers.handleGetCallStack(toolArgs);
327
+ case 'debugger_evaluate':
328
+ return await this.debuggerHandlers.handleDebuggerEvaluate(toolArgs);
329
+ case 'debugger_evaluate_global':
330
+ return await this.debuggerHandlers.handleDebuggerEvaluateGlobal(toolArgs);
331
+ case 'debugger_wait_for_paused':
332
+ return await this.debuggerHandlers.handleDebuggerWaitForPaused(toolArgs);
333
+ case 'debugger_get_paused_state':
334
+ return await this.debuggerHandlers.handleDebuggerGetPausedState(toolArgs);
335
+ case 'breakpoint_set_on_exception':
336
+ return await this.debuggerHandlers.handleBreakpointSetOnException(toolArgs);
337
+ case 'get_object_properties':
338
+ return await this.debuggerHandlers.handleGetObjectProperties(toolArgs);
339
+ case 'get_scope_variables_enhanced':
340
+ return await this.debuggerHandlers.handleGetScopeVariablesEnhanced(toolArgs);
341
+ case 'debugger_save_session':
342
+ return await this.debuggerHandlers.handleSaveSession(toolArgs);
343
+ case 'debugger_load_session':
344
+ return await this.debuggerHandlers.handleLoadSession(toolArgs);
345
+ case 'debugger_export_session':
346
+ return await this.debuggerHandlers.handleExportSession(toolArgs);
347
+ case 'debugger_list_sessions':
348
+ return await this.debuggerHandlers.handleListSessions(toolArgs);
349
+ case 'watch_add':
350
+ return await this.debuggerHandlers.handleWatchAdd(toolArgs);
351
+ case 'watch_remove':
352
+ return await this.debuggerHandlers.handleWatchRemove(toolArgs);
353
+ case 'watch_list':
354
+ return await this.debuggerHandlers.handleWatchList(toolArgs);
355
+ case 'watch_evaluate_all':
356
+ return await this.debuggerHandlers.handleWatchEvaluateAll(toolArgs);
357
+ case 'watch_clear_all':
358
+ return await this.debuggerHandlers.handleWatchClearAll(toolArgs);
359
+ case 'xhr_breakpoint_set':
360
+ return await this.debuggerHandlers.handleXHRBreakpointSet(toolArgs);
361
+ case 'xhr_breakpoint_remove':
362
+ return await this.debuggerHandlers.handleXHRBreakpointRemove(toolArgs);
363
+ case 'xhr_breakpoint_list':
364
+ return await this.debuggerHandlers.handleXHRBreakpointList(toolArgs);
365
+ case 'event_breakpoint_set':
366
+ return await this.debuggerHandlers.handleEventBreakpointSet(toolArgs);
367
+ case 'event_breakpoint_set_category':
368
+ return await this.debuggerHandlers.handleEventBreakpointSetCategory(toolArgs);
369
+ case 'event_breakpoint_remove':
370
+ return await this.debuggerHandlers.handleEventBreakpointRemove(toolArgs);
371
+ case 'event_breakpoint_list':
372
+ return await this.debuggerHandlers.handleEventBreakpointList(toolArgs);
373
+ case 'blackbox_add':
374
+ return await this.debuggerHandlers.handleBlackboxAdd(toolArgs);
375
+ case 'blackbox_add_common':
376
+ return await this.debuggerHandlers.handleBlackboxAddCommon(toolArgs);
377
+ case 'blackbox_list':
378
+ return await this.debuggerHandlers.handleBlackboxList(toolArgs);
379
+ case 'network_enable':
380
+ return await this.advancedHandlers.handleNetworkEnable(toolArgs);
381
+ case 'network_disable':
382
+ return await this.advancedHandlers.handleNetworkDisable(toolArgs);
383
+ case 'network_get_status':
384
+ return await this.advancedHandlers.handleNetworkGetStatus(toolArgs);
385
+ case 'network_get_requests':
386
+ return await this.advancedHandlers.handleNetworkGetRequests(toolArgs);
387
+ case 'network_get_response_body':
388
+ return await this.advancedHandlers.handleNetworkGetResponseBody(toolArgs);
389
+ case 'network_get_stats':
390
+ return await this.advancedHandlers.handleNetworkGetStats(toolArgs);
391
+ case 'performance_get_metrics':
392
+ return await this.advancedHandlers.handlePerformanceGetMetrics(toolArgs);
393
+ case 'performance_start_coverage':
394
+ return await this.advancedHandlers.handlePerformanceStartCoverage(toolArgs);
395
+ case 'performance_stop_coverage':
396
+ return await this.advancedHandlers.handlePerformanceStopCoverage(toolArgs);
397
+ case 'performance_take_heap_snapshot':
398
+ return await this.advancedHandlers.handlePerformanceTakeHeapSnapshot(toolArgs);
399
+ case 'console_get_exceptions':
400
+ return await this.advancedHandlers.handleConsoleGetExceptions(toolArgs);
401
+ case 'console_inject_script_monitor':
402
+ return await this.advancedHandlers.handleConsoleInjectScriptMonitor(toolArgs);
403
+ case 'console_inject_xhr_interceptor':
404
+ return await this.advancedHandlers.handleConsoleInjectXhrInterceptor(toolArgs);
405
+ case 'console_inject_fetch_interceptor':
406
+ return await this.advancedHandlers.handleConsoleInjectFetchInterceptor(toolArgs);
407
+ case 'console_inject_function_tracer':
408
+ return await this.advancedHandlers.handleConsoleInjectFunctionTracer(toolArgs);
409
+ default:
410
+ throw new Error(`Unknown tool: ${name}`);
411
+ }
412
+ }
413
+ getTools() {
414
+ return [
415
+ {
416
+ name: 'collect_code',
417
+ description: 'Collect JavaScript code from a target website. 🆕 Supports smart collection modes: summary (fast analysis), priority (key code first), full (complete). Use summary mode for large websites to avoid token overflow.',
418
+ inputSchema: {
419
+ type: 'object',
420
+ properties: {
421
+ url: {
422
+ type: 'string',
423
+ description: 'Target website URL',
424
+ },
425
+ includeInline: {
426
+ type: 'boolean',
427
+ description: 'Include inline scripts',
428
+ default: true,
429
+ },
430
+ includeExternal: {
431
+ type: 'boolean',
432
+ description: 'Include external scripts',
433
+ default: true,
434
+ },
435
+ includeDynamic: {
436
+ type: 'boolean',
437
+ description: 'Include dynamically loaded scripts',
438
+ default: false,
439
+ },
440
+ smartMode: {
441
+ type: 'string',
442
+ description: '🆕 Smart collection mode: "summary" (only metadata, fastest), "priority" (key code first), "incremental" (on-demand), "full" (all code, default)',
443
+ enum: ['summary', 'priority', 'incremental', 'full'],
444
+ default: 'full',
445
+ },
446
+ compress: {
447
+ type: 'boolean',
448
+ description: '🆕 Enable gzip compression (70-90% size reduction). Compression info saved in metadata.',
449
+ default: false,
450
+ },
451
+ maxTotalSize: {
452
+ type: 'number',
453
+ description: '🆕 Maximum total size in bytes (default: 2MB). Used with priority/incremental modes.',
454
+ default: 2097152,
455
+ },
456
+ maxFileSize: {
457
+ type: 'number',
458
+ description: 'Maximum single file size in KB (default: 500KB). Files larger than this will be truncated.',
459
+ default: 500,
460
+ },
461
+ priorities: {
462
+ type: 'array',
463
+ description: '🆕 Priority URL patterns for priority mode (e.g., ["encrypt", "crypto", "sign"]). Files matching these patterns are collected first.',
464
+ items: { type: 'string' },
465
+ },
466
+ returnSummaryOnly: {
467
+ type: 'boolean',
468
+ description: '⚠️ DEPRECATED: Use smartMode="summary" instead.',
469
+ default: false,
470
+ },
471
+ },
472
+ required: ['url'],
473
+ },
548
474
  },
549
- }, async (args) => {
550
- const result = await handlers.handleBreakpointRemove(args);
551
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
552
- });
553
- server.registerTool('breakpoint_list', {
554
- title: 'Breakpoint List',
555
- description: 'List all breakpoints',
556
- inputSchema: {},
557
- }, async () => {
558
- const result = await handlers.handleBreakpointList({});
559
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
560
- });
561
- server.registerTool('get_call_stack', {
562
- title: 'Get Call Stack',
563
- description: 'Get current call stack',
564
- inputSchema: {},
565
- }, async () => {
566
- const result = await handlers.handleGetCallStack({});
567
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
568
- });
569
- server.registerTool('debugger_evaluate', {
570
- title: 'Debugger Evaluate',
571
- description: 'Evaluate expression in paused context',
572
- inputSchema: {
573
- expression: z.string().describe('Expression to evaluate'),
475
+ {
476
+ name: 'search_in_scripts',
477
+ description: `🆕 Search for keywords in collected scripts. Auto-truncates large results to avoid context overflow.
478
+
479
+ Use this tool when:
480
+ - You need to find where a specific function/variable is defined
481
+ - Looking for API endpoints or encryption algorithms
482
+ - Searching for specific patterns in large codebases
483
+
484
+ ⚠️ IMPORTANT: Large results (>50KB) automatically return summary only. Use specific keywords to reduce matches.
485
+
486
+ Example:
487
+ search_in_scripts(keyword="a_bogus", contextLines=5, maxMatches=50)
488
+ Returns all occurrences with surrounding code`,
489
+ inputSchema: {
490
+ type: 'object',
491
+ properties: {
492
+ keyword: {
493
+ type: 'string',
494
+ description: 'Keyword to search for (supports regex if isRegex=true)',
495
+ },
496
+ isRegex: {
497
+ type: 'boolean',
498
+ description: 'Whether the keyword is a regular expression',
499
+ default: false,
500
+ },
501
+ caseSensitive: {
502
+ type: 'boolean',
503
+ description: 'Whether the search is case-sensitive',
504
+ default: false,
505
+ },
506
+ contextLines: {
507
+ type: 'number',
508
+ description: 'Number of context lines to include before and after matches',
509
+ default: 3,
510
+ },
511
+ maxMatches: {
512
+ type: 'number',
513
+ description: 'Maximum number of matches to return (default: 100). Reduce this if getting summary-only results.',
514
+ default: 100,
515
+ },
516
+ returnSummary: {
517
+ type: 'boolean',
518
+ description: '🆕 Return summary only (match count, preview) instead of full results. Useful for large result sets.',
519
+ default: false,
520
+ },
521
+ maxContextSize: {
522
+ type: 'number',
523
+ description: '🆕 Maximum result size in bytes (default: 50KB). Results larger than this return summary only.',
524
+ default: 50000,
525
+ },
526
+ },
527
+ required: ['keyword'],
528
+ },
574
529
  },
575
- }, async (args) => {
576
- const result = await handlers.handleDebuggerEvaluate(args);
577
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
578
- });
579
- server.registerTool('watch_add', {
580
- title: 'Watch Add',
581
- description: 'Add a watch expression',
582
- inputSchema: {
583
- expression: z.string().describe('Expression to watch'),
530
+ {
531
+ name: 'extract_function_tree',
532
+ description: `Extract a function and all its dependencies from collected scripts.
533
+
534
+ This tool solves the context overflow problem by extracting only relevant code instead of analyzing entire files.
535
+
536
+ Use this tool when:
537
+ - You want to analyze a specific function (e.g., "sign", "encrypt")
538
+ - Need to understand function dependencies
539
+ - Want to avoid context overflow with large files
540
+
541
+ Example workflow:
542
+ 1. search_in_scripts(keyword="a_bogus") → Find which file contains it
543
+ 2. extract_function_tree(functionName="sign", maxDepth=3) → Extract sign() and its dependencies
544
+ 3. analyze_code_chunk(code=extractedCode) → Analyze the small extracted code
545
+
546
+ Returns:
547
+ - Complete code of the function and its dependencies
548
+ - Call graph showing relationships
549
+ - Total size (much smaller than original file)`,
550
+ inputSchema: {
551
+ type: 'object',
552
+ properties: {
553
+ scriptId: {
554
+ type: 'string',
555
+ description: 'Script ID from collect_code or search_in_scripts',
556
+ },
557
+ functionName: {
558
+ type: 'string',
559
+ description: 'Name of the function to extract',
560
+ },
561
+ maxDepth: {
562
+ type: 'number',
563
+ description: 'Maximum dependency depth to extract',
564
+ default: 3,
565
+ },
566
+ maxSize: {
567
+ type: 'number',
568
+ description: 'Maximum total size in KB',
569
+ default: 500,
570
+ },
571
+ includeComments: {
572
+ type: 'boolean',
573
+ description: 'Whether to include comments in extracted code',
574
+ default: true,
575
+ },
576
+ },
577
+ required: ['scriptId', 'functionName'],
578
+ },
584
579
  },
585
- }, async (args) => {
586
- const result = await handlers.handleWatchAdd(args);
587
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
588
- });
589
- server.registerTool('watch_list', {
590
- title: 'Watch List',
591
- description: 'List all watch expressions',
592
- inputSchema: {},
593
- }, async () => {
594
- const result = await handlers.handleWatchList({});
595
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
596
- });
597
- server.registerTool('xhr_breakpoint_set', {
598
- title: 'XHR Breakpoint Set',
599
- description: 'Set XHR breakpoint',
600
- inputSchema: {
601
- urlPattern: z.string().optional(),
602
- methods: z.array(z.string()).optional(),
580
+ {
581
+ name: 'deobfuscate',
582
+ description: 'AI-driven code deobfuscation',
583
+ inputSchema: {
584
+ type: 'object',
585
+ properties: {
586
+ code: {
587
+ type: 'string',
588
+ description: 'Obfuscated code to deobfuscate',
589
+ },
590
+ llm: {
591
+ type: 'string',
592
+ enum: ['gpt-4', 'claude'],
593
+ description: 'LLM to use for deobfuscation',
594
+ default: 'gpt-4',
595
+ },
596
+ aggressive: {
597
+ type: 'boolean',
598
+ description: 'Use aggressive deobfuscation',
599
+ default: false,
600
+ },
601
+ },
602
+ required: ['code'],
603
+ },
603
604
  },
604
- }, async (args) => {
605
- const result = await handlers.handleXHRBreakpointSet(args);
606
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
607
- });
608
- server.registerTool('event_breakpoint_set', {
609
- title: 'Event Breakpoint Set',
610
- description: 'Set event breakpoint',
611
- inputSchema: {
612
- eventName: z.string().describe('Event name'),
605
+ {
606
+ name: 'understand_code',
607
+ description: 'AI-assisted code semantic understanding',
608
+ inputSchema: {
609
+ type: 'object',
610
+ properties: {
611
+ code: {
612
+ type: 'string',
613
+ description: 'Code to analyze',
614
+ },
615
+ context: {
616
+ type: 'object',
617
+ description: 'Additional context for analysis',
618
+ },
619
+ focus: {
620
+ type: 'string',
621
+ enum: ['structure', 'business', 'security', 'all'],
622
+ description: 'Analysis focus',
623
+ default: 'all',
624
+ },
625
+ },
626
+ required: ['code'],
627
+ },
613
628
  },
614
- }, async (args) => {
615
- const result = await handlers.handleEventBreakpointSet(args);
616
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
617
- });
618
- server.registerTool('blackbox_add', {
619
- title: 'Blackbox Add',
620
- description: 'Add script to blackbox',
621
- inputSchema: {
622
- pattern: z.string().describe('URL pattern'),
629
+ {
630
+ name: 'detect_crypto',
631
+ description: 'Detect and analyze encryption algorithms',
632
+ inputSchema: {
633
+ type: 'object',
634
+ properties: {
635
+ code: {
636
+ type: 'string',
637
+ description: 'Code to analyze for crypto algorithms',
638
+ },
639
+ },
640
+ required: ['code'],
641
+ },
623
642
  },
624
- }, async (args) => {
625
- const result = await handlers.handleBlackboxAdd(args);
626
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
627
- });
628
- }
629
- registerAdvancedTools() {
630
- const server = this.server;
631
- const handlers = this.advancedHandlers;
632
- server.registerTool('performance_get_metrics', {
633
- title: 'Performance Get Metrics',
634
- description: 'Get performance metrics',
635
- inputSchema: {},
636
- }, async () => {
637
- const result = await handlers.handlePerformanceGetMetrics({});
638
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
639
- });
640
- server.registerTool('performance_start_coverage', {
641
- title: 'Performance Start Coverage',
642
- description: 'Start code coverage recording',
643
- inputSchema: {},
644
- }, async () => {
645
- const result = await handlers.handlePerformanceStartCoverage({});
646
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
647
- });
648
- server.registerTool('performance_stop_coverage', {
649
- title: 'Performance Stop Coverage',
650
- description: 'Stop code coverage recording',
651
- inputSchema: {},
652
- }, async () => {
653
- const result = await handlers.handlePerformanceStopCoverage({});
654
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
655
- });
656
- server.registerTool('console_get_exceptions', {
657
- title: 'Console Get Exceptions',
658
- description: 'Get caught exceptions',
659
- inputSchema: {},
660
- }, async () => {
661
- const result = await handlers.handleConsoleGetExceptions({});
662
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
663
- });
664
- server.registerTool('console_inject_xhr_interceptor', {
665
- title: 'Console Inject XHR Interceptor',
666
- description: 'Inject XHR interceptor',
667
- inputSchema: {},
668
- }, async () => {
669
- const result = await handlers.handleConsoleInjectXhrInterceptor({});
670
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
671
- });
672
- server.registerTool('console_inject_fetch_interceptor', {
673
- title: 'Console Inject Fetch Interceptor',
674
- description: 'Inject fetch interceptor',
675
- inputSchema: {},
676
- }, async () => {
677
- const result = await handlers.handleConsoleInjectFetchInterceptor({});
678
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
679
- });
680
- server.registerTool('network_get_stats', {
681
- title: 'Network Get Stats',
682
- description: 'Get network statistics',
683
- inputSchema: {},
684
- }, async () => {
685
- const result = await handlers.handleNetworkGetStats({});
686
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
687
- });
688
- }
689
- registerAIHookTools() {
690
- const server = this.server;
691
- const handlers = this.aiHookHandlers;
692
- server.registerTool('ai_hook_generate', {
693
- title: 'AI Hook Generate',
694
- description: 'Generate hook code for a request pattern',
695
- inputSchema: {
696
- pattern: z.string().describe('Request pattern to hook'),
643
+ {
644
+ name: 'manage_hooks',
645
+ description: 'Manage JavaScript hooks for runtime interception',
646
+ inputSchema: {
647
+ type: 'object',
648
+ properties: {
649
+ action: {
650
+ type: 'string',
651
+ enum: ['create', 'list', 'records', 'clear'],
652
+ description: 'Hook management action',
653
+ },
654
+ target: {
655
+ type: 'string',
656
+ description: 'Hook target (function name, API, etc.)',
657
+ },
658
+ type: {
659
+ type: 'string',
660
+ enum: ['function', 'xhr', 'fetch', 'websocket', 'localstorage', 'cookie'],
661
+ description: 'Type of hook to create',
662
+ },
663
+ hookAction: {
664
+ type: 'string',
665
+ enum: ['log', 'block', 'modify'],
666
+ description: 'What to do when hook is triggered',
667
+ default: 'log',
668
+ },
669
+ customCode: {
670
+ type: 'string',
671
+ description: 'Custom JavaScript code to execute in hook',
672
+ },
673
+ hookId: {
674
+ type: 'string',
675
+ description: 'Hook ID for records/clear actions',
676
+ },
677
+ },
678
+ required: ['action'],
679
+ },
697
680
  },
698
- }, async (args) => {
699
- const result = await handlers.handleAIHookGenerate(args);
700
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
701
- });
702
- server.registerTool('ai_hook_inject', {
703
- title: 'AI Hook Inject',
704
- description: 'Inject generated hook into page',
705
- inputSchema: {
706
- hookId: z.string().describe('Hook ID'),
681
+ {
682
+ name: 'detect_obfuscation',
683
+ description: 'Detect obfuscation types in JavaScript code (supports 2024-2025 latest techniques)',
684
+ inputSchema: {
685
+ type: 'object',
686
+ properties: {
687
+ code: {
688
+ type: 'string',
689
+ description: 'Code to analyze for obfuscation',
690
+ },
691
+ generateReport: {
692
+ type: 'boolean',
693
+ description: 'Generate detailed report',
694
+ default: true,
695
+ },
696
+ },
697
+ required: ['code'],
698
+ },
707
699
  },
708
- }, async (args) => {
709
- const result = await handlers.handleAIHookInject(args);
710
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
711
- });
712
- server.registerTool('ai_hook_list', {
713
- title: 'AI Hook List',
714
- description: 'List all active hooks',
715
- inputSchema: {},
716
- }, async () => {
717
- const result = await handlers.handleAIHookList({});
718
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
719
- });
720
- server.registerTool('ai_hook_get_data', {
721
- title: 'AI Hook Get Data',
722
- description: 'Get captured hook data',
723
- inputSchema: {
724
- hookId: z.string().describe('Hook ID'),
700
+ {
701
+ name: 'advanced_deobfuscate',
702
+ description: 'Advanced deobfuscation supporting VM protection, invisible unicode, control flow flattening, etc.',
703
+ inputSchema: {
704
+ type: 'object',
705
+ properties: {
706
+ code: {
707
+ type: 'string',
708
+ description: 'Obfuscated code to deobfuscate',
709
+ },
710
+ detectOnly: {
711
+ type: 'boolean',
712
+ description: 'Only detect obfuscation types without deobfuscating',
713
+ default: false,
714
+ },
715
+ aggressiveVM: {
716
+ type: 'boolean',
717
+ description: 'Use aggressive VM deobfuscation (experimental)',
718
+ default: false,
719
+ },
720
+ useASTOptimization: {
721
+ type: 'boolean',
722
+ description: 'Apply AST-based optimizations',
723
+ default: true,
724
+ },
725
+ timeout: {
726
+ type: 'number',
727
+ description: 'Timeout in milliseconds',
728
+ default: 60000,
729
+ },
730
+ },
731
+ required: ['code'],
732
+ },
725
733
  },
726
- }, async (args) => {
727
- const result = await handlers.handleAIHookGetData(args);
728
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
729
- });
730
- server.registerTool('ai_hook_clear', {
731
- title: 'AI Hook Clear',
732
- description: 'Clear all hooks',
733
- inputSchema: {},
734
- }, async () => {
735
- const result = await handlers.handleAIHookClear({});
736
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
737
- });
738
- server.registerTool('ai_hook_toggle', {
739
- title: 'AI Hook Toggle',
740
- description: 'Toggle hook on/off',
741
- inputSchema: {
742
- hookId: z.string().describe('Hook ID'),
743
- enabled: z.boolean().describe('Enable or disable'),
734
+ {
735
+ name: 'clear_collected_data',
736
+ description: '🧹 Clear all collected data (file cache, compression cache, collected URLs). Use this when switching to a new website to avoid data interference.',
737
+ inputSchema: {
738
+ type: 'object',
739
+ properties: {},
740
+ },
744
741
  },
745
- }, async (args) => {
746
- const result = await handlers.handleAIHookToggle(args);
747
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
748
- });
749
- server.registerTool('ai_hook_export', {
750
- title: 'AI Hook Export',
751
- description: 'Export hook data',
752
- inputSchema: {
753
- format: z.enum(['json', 'har']).optional().default('json'),
742
+ {
743
+ name: 'get_collection_stats',
744
+ description: '📊 Get statistics about collected data (cache stats, compression stats, collected URLs count).',
745
+ inputSchema: {
746
+ type: 'object',
747
+ properties: {},
748
+ },
754
749
  },
755
- }, async (args) => {
756
- const result = await handlers.handleAIHookExport(args);
757
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
758
- });
750
+ ...browserTools,
751
+ ...debuggerTools,
752
+ ...advancedTools,
753
+ ...aiHookTools,
754
+ ...tokenBudgetTools,
755
+ ...cacheTools,
756
+ ];
759
757
  }
760
- registerTokenBudgetTools() {
761
- const server = this.server;
762
- server.registerTool('get_token_budget_stats', {
763
- title: 'Get Token Budget Stats',
764
- description: 'Get token budget statistics',
765
- inputSchema: {},
766
- }, async () => {
767
- const result = await this.handleGetTokenBudgetStats({});
768
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
769
- });
770
- server.registerTool('manual_token_cleanup', {
771
- title: 'Manual Token Cleanup',
772
- description: 'Manually clean up token usage',
773
- inputSchema: {},
774
- }, async () => {
775
- const result = await this.handleManualTokenCleanup({});
776
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
777
- });
778
- server.registerTool('reset_token_budget', {
779
- title: 'Reset Token Budget',
780
- description: 'Reset token budget',
781
- inputSchema: {},
782
- }, async () => {
783
- const result = await this.handleResetTokenBudget({});
784
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
785
- });
786
- }
787
- registerCacheTools() {
788
- const server = this.server;
789
- server.registerTool('get_cache_stats', {
790
- title: 'Get Cache Stats',
791
- description: 'Get cache statistics',
792
- inputSchema: {},
793
- }, async () => {
794
- const result = await this.handleGetCacheStats({});
795
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
796
- });
797
- server.registerTool('smart_cache_cleanup', {
798
- title: 'Smart Cache Cleanup',
799
- description: 'Smart cleanup of cache',
800
- inputSchema: {
801
- targetSize: z.number().optional(),
802
- },
803
- }, async (args) => {
804
- const result = await this.handleSmartCacheCleanup(args);
805
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
806
- });
807
- server.registerTool('clear_all_caches', {
808
- title: 'Clear All Caches',
809
- description: 'Clear all caches',
810
- inputSchema: {},
811
- }, async () => {
812
- const result = await this.handleClearAllCaches({});
813
- return { content: [{ type: 'text', text: JSON.stringify(result) }] };
814
- });
758
+ async handleCollectCode(args) {
759
+ const returnSummaryOnly = args.returnSummaryOnly ?? false;
760
+ let smartMode = args.smartMode;
761
+ if (returnSummaryOnly && !smartMode) {
762
+ smartMode = 'summary';
763
+ }
764
+ const result = await this.collector.collect({
765
+ url: args.url,
766
+ includeInline: args.includeInline,
767
+ includeExternal: args.includeExternal,
768
+ includeDynamic: args.includeDynamic,
769
+ smartMode: smartMode,
770
+ compress: args.compress,
771
+ maxTotalSize: args.maxTotalSize,
772
+ maxFileSize: args.maxFileSize ? args.maxFileSize * 1024 : undefined,
773
+ priorities: args.priorities,
774
+ });
775
+ if (returnSummaryOnly) {
776
+ logger.info('📋 Returning summary only (user requested)');
777
+ return {
778
+ content: [
779
+ {
780
+ type: 'text',
781
+ text: JSON.stringify({
782
+ mode: 'summary',
783
+ totalSize: result.totalSize,
784
+ totalSizeKB: (result.totalSize / 1024).toFixed(2),
785
+ filesCount: result.files.length,
786
+ collectTime: result.collectTime,
787
+ summary: result.files.map(f => ({
788
+ url: f.url,
789
+ type: f.type,
790
+ size: f.size,
791
+ sizeKB: (f.size / 1024).toFixed(2),
792
+ truncated: f.metadata?.truncated || false,
793
+ preview: f.content.substring(0, 200) + '...',
794
+ })),
795
+ hint: 'Use get_script_source tool to fetch specific files',
796
+ }, null, 2),
797
+ },
798
+ ],
799
+ };
800
+ }
801
+ const totalSize = result.totalSize;
802
+ const MAX_SAFE_SIZE = 1 * 1024 * 1024;
803
+ if (totalSize > MAX_SAFE_SIZE) {
804
+ logger.warn(`⚠️ Total code size (${(totalSize / 1024).toFixed(2)} KB) exceeds safe limit (${MAX_SAFE_SIZE / 1024} KB), auto-switching to summary mode`);
805
+ return {
806
+ content: [
807
+ {
808
+ type: 'text',
809
+ text: JSON.stringify({
810
+ warning: '⚠️ Code size too large for full response - auto-switched to summary mode',
811
+ totalSize,
812
+ totalSizeKB: (totalSize / 1024).toFixed(2),
813
+ filesCount: result.files.length,
814
+ collectTime: result.collectTime,
815
+ summary: result.files.map(f => ({
816
+ url: f.url,
817
+ type: f.type,
818
+ size: f.size,
819
+ sizeKB: (f.size / 1024).toFixed(2),
820
+ truncated: f.metadata?.truncated || false,
821
+ preview: f.content.substring(0, 200) + '...',
822
+ })),
823
+ recommendations: [
824
+ '1. Use get_script_source to fetch specific files',
825
+ '2. Filter files by URL pattern (e.g., files containing "encrypt" or "api")',
826
+ '3. Use returnSummaryOnly=true parameter to explicitly request summary mode',
827
+ '4. Enable caching to speed up repeated requests',
828
+ ],
829
+ }, null, 2),
830
+ },
831
+ ],
832
+ };
833
+ }
834
+ return {
835
+ content: [
836
+ {
837
+ type: 'text',
838
+ text: JSON.stringify(result, null, 2),
839
+ },
840
+ ],
841
+ };
815
842
  }
816
843
  async handleSearchInScripts(args) {
817
844
  const { ScriptManager } = await import('../modules/debugger/ScriptManager.js');