brave-real-browser-mcp-server 2.9.21 ā 2.10.0
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/dist/handlers/advanced-extraction-handlers.js +483 -0
- package/dist/handlers/advanced-video-media-handlers.js +100 -41
- package/dist/handlers/api-integration-handlers.js +2 -1
- package/dist/handlers/captcha-handlers.js +2 -1
- package/dist/handlers/dynamic-session-handlers.js +41 -9
- package/dist/handlers/pagination-handlers.js +5 -5
- package/dist/handlers/smart-data-extractors.js +4 -4
- package/dist/handlers/visual-tools-handlers.js +2 -1
- package/dist/index.js +231 -106
- package/dist/mcp-response-validator.js +145 -0
- package/dist/tool-definitions.js +50 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12,6 +12,7 @@ console.error('š [DEBUG] Loading tool definitions...');
|
|
|
12
12
|
import { TOOLS, SERVER_INFO, CAPABILITIES, TOOL_NAMES } from './tool-definitions.js';
|
|
13
13
|
console.error('š [DEBUG] Loading system utils...');
|
|
14
14
|
import { withErrorHandling } from './system-utils.js';
|
|
15
|
+
import { validateMCPResponse } from './mcp-response-validator.js';
|
|
15
16
|
console.error('š [DEBUG] Loading browser manager...');
|
|
16
17
|
import { closeBrowser, forceKillAllBraveProcesses } from './browser-manager.js';
|
|
17
18
|
console.error('š [DEBUG] Loading core infrastructure...');
|
|
@@ -51,6 +52,8 @@ import { handleShadowDOMExtractor, handleCookieManager, handleSessionPersistence
|
|
|
51
52
|
import { handleProgressTracker, handleErrorLogger, handleSuccessRateReporter, handleDataQualityMetrics, handlePerformanceMonitor, handleGetMonitoringSummary } from './handlers/monitoring-reporting-handlers.js';
|
|
52
53
|
// Import advanced video & media handlers
|
|
53
54
|
import { handleVideoLinkFinder, handleVideoDownloadPage, handleVideoDownloadButton, handleVideoPlayPushSource, handleVideoPlayButtonClick, handleUrlRedirectTraceEndpoints, handleNetworkRecordingFinder, handleNetworkRecordingExtractors, handleVideoLinksFinders, handleVideosSelectors, handleLinkProcessExtracts, handleVideoLinkFindersExtracts, handleVideoDownloadButtonFinders } from './handlers/advanced-video-media-handlers.js';
|
|
55
|
+
// Import advanced extraction handlers (Ad-bypass & Obfuscation)
|
|
56
|
+
import { handleAdvancedVideoExtraction, handleDeobfuscateJS, handleMultiLayerRedirectTrace, handleAdProtectionDetector } from './handlers/advanced-extraction-handlers.js';
|
|
54
57
|
console.error('š [DEBUG] All modules loaded successfully');
|
|
55
58
|
console.error(`š [DEBUG] Server info: ${JSON.stringify(SERVER_INFO)}`);
|
|
56
59
|
console.error(`š [DEBUG] Available tools: ${TOOLS.length} tools loaded`);
|
|
@@ -104,238 +107,360 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
104
107
|
const { name, arguments: args } = request.params;
|
|
105
108
|
console.error(`š [DEBUG] Tool call received: ${name} with args: ${JSON.stringify(args)}`);
|
|
106
109
|
try {
|
|
110
|
+
let result;
|
|
107
111
|
switch (name) {
|
|
108
112
|
case TOOL_NAMES.BROWSER_INIT:
|
|
109
|
-
|
|
113
|
+
result = await handleBrowserInit(args || {});
|
|
114
|
+
break;
|
|
110
115
|
case TOOL_NAMES.NAVIGATE:
|
|
111
|
-
|
|
116
|
+
result = await handleNavigate(args);
|
|
117
|
+
break;
|
|
112
118
|
case TOOL_NAMES.GET_CONTENT:
|
|
113
|
-
|
|
119
|
+
result = await handleGetContent(args || {});
|
|
120
|
+
break;
|
|
114
121
|
case TOOL_NAMES.CLICK:
|
|
115
|
-
|
|
122
|
+
result = await handleClick(args);
|
|
123
|
+
break;
|
|
116
124
|
case TOOL_NAMES.TYPE:
|
|
117
|
-
|
|
125
|
+
result = await handleType(args);
|
|
126
|
+
break;
|
|
118
127
|
case TOOL_NAMES.WAIT:
|
|
119
|
-
|
|
128
|
+
result = await handleWait(args);
|
|
129
|
+
break;
|
|
120
130
|
case TOOL_NAMES.BROWSER_CLOSE:
|
|
121
|
-
|
|
131
|
+
result = await handleBrowserClose();
|
|
132
|
+
break;
|
|
122
133
|
case TOOL_NAMES.SOLVE_CAPTCHA:
|
|
123
|
-
|
|
134
|
+
result = await handleSolveCaptcha(args);
|
|
135
|
+
break;
|
|
124
136
|
case TOOL_NAMES.RANDOM_SCROLL:
|
|
125
|
-
|
|
137
|
+
result = await handleRandomScroll();
|
|
138
|
+
break;
|
|
126
139
|
case TOOL_NAMES.FIND_SELECTOR:
|
|
127
|
-
|
|
140
|
+
result = await handleFindSelector(args);
|
|
141
|
+
break;
|
|
128
142
|
case TOOL_NAMES.SAVE_CONTENT_AS_MARKDOWN:
|
|
129
|
-
|
|
143
|
+
result = await handleSaveContentAsMarkdown(args);
|
|
144
|
+
break;
|
|
130
145
|
// Smart Data Extractors
|
|
131
146
|
case TOOL_NAMES.SCRAPE_TABLE:
|
|
132
|
-
|
|
147
|
+
result = await handleScrapeTable(args || {});
|
|
148
|
+
break;
|
|
133
149
|
case TOOL_NAMES.EXTRACT_LIST:
|
|
134
|
-
|
|
150
|
+
result = await handleExtractList(args || {});
|
|
151
|
+
break;
|
|
135
152
|
case TOOL_NAMES.EXTRACT_JSON:
|
|
136
|
-
|
|
153
|
+
result = await handleExtractJSON(args || {});
|
|
154
|
+
break;
|
|
137
155
|
case TOOL_NAMES.SCRAPE_META_TAGS:
|
|
138
|
-
|
|
156
|
+
result = await handleScrapeMetaTags(args || {});
|
|
157
|
+
break;
|
|
139
158
|
case TOOL_NAMES.EXTRACT_SCHEMA:
|
|
140
|
-
|
|
159
|
+
result = await handleExtractSchema(args || {});
|
|
160
|
+
break;
|
|
141
161
|
// Multi-Element Extractors
|
|
142
162
|
case TOOL_NAMES.BATCH_ELEMENT_SCRAPER:
|
|
143
|
-
|
|
163
|
+
result = await handleBatchElementScraper(args);
|
|
164
|
+
break;
|
|
144
165
|
case TOOL_NAMES.NESTED_DATA_EXTRACTION:
|
|
145
|
-
|
|
166
|
+
result = await handleNestedDataExtraction(args);
|
|
167
|
+
break;
|
|
146
168
|
case TOOL_NAMES.ATTRIBUTE_HARVESTER:
|
|
147
|
-
|
|
169
|
+
result = await handleAttributeHarvester(args);
|
|
170
|
+
break;
|
|
148
171
|
// Content Type Specific
|
|
149
172
|
case TOOL_NAMES.IMAGE_SCRAPER:
|
|
150
|
-
|
|
173
|
+
result = await handleImageScraper(args || {});
|
|
174
|
+
break;
|
|
151
175
|
case TOOL_NAMES.LINK_HARVESTER:
|
|
152
|
-
|
|
176
|
+
result = await handleLinkHarvester(args || {});
|
|
177
|
+
break;
|
|
153
178
|
case TOOL_NAMES.MEDIA_EXTRACTOR:
|
|
154
|
-
|
|
179
|
+
result = await handleMediaExtractor(args || {});
|
|
180
|
+
break;
|
|
155
181
|
case TOOL_NAMES.PDF_LINK_FINDER:
|
|
156
|
-
|
|
182
|
+
result = await handlePDFLinkFinder(args || {});
|
|
183
|
+
break;
|
|
157
184
|
// Pagination Tools
|
|
158
185
|
case TOOL_NAMES.AUTO_PAGINATION:
|
|
159
|
-
|
|
186
|
+
result = await handleAutoPagination(args || {});
|
|
187
|
+
break;
|
|
160
188
|
case TOOL_NAMES.INFINITE_SCROLL:
|
|
161
|
-
|
|
189
|
+
result = await handleInfiniteScroll(args || {});
|
|
190
|
+
break;
|
|
162
191
|
case TOOL_NAMES.MULTI_PAGE_SCRAPER:
|
|
163
|
-
|
|
192
|
+
result = await handleMultiPageScraper(args);
|
|
193
|
+
break;
|
|
164
194
|
case TOOL_NAMES.SITEMAP_PARSER:
|
|
165
|
-
|
|
195
|
+
result = await handleSitemapParser(args || {});
|
|
196
|
+
break;
|
|
166
197
|
case TOOL_NAMES.BREADCRUMB_NAVIGATOR:
|
|
167
|
-
|
|
198
|
+
result = await handleBreadcrumbNavigator(args || {});
|
|
199
|
+
break;
|
|
168
200
|
// Data Processing Tools
|
|
169
201
|
case TOOL_NAMES.SMART_TEXT_CLEANER:
|
|
170
|
-
|
|
202
|
+
result = await handleSmartTextCleaner(args);
|
|
203
|
+
break;
|
|
171
204
|
case TOOL_NAMES.HTML_TO_TEXT:
|
|
172
|
-
|
|
205
|
+
result = await handleHTMLToText(args);
|
|
206
|
+
break;
|
|
173
207
|
case TOOL_NAMES.PRICE_PARSER:
|
|
174
|
-
|
|
208
|
+
result = await handlePriceParser(args);
|
|
209
|
+
break;
|
|
175
210
|
case TOOL_NAMES.DATE_NORMALIZER:
|
|
176
|
-
|
|
211
|
+
result = await handleDateNormalizer(args);
|
|
212
|
+
break;
|
|
177
213
|
case TOOL_NAMES.CONTACT_EXTRACTOR:
|
|
178
|
-
|
|
214
|
+
result = await handleContactExtractor(args);
|
|
215
|
+
break;
|
|
179
216
|
// Data Validation Tools
|
|
180
217
|
case TOOL_NAMES.SCHEMA_VALIDATOR:
|
|
181
|
-
|
|
218
|
+
result = await handleSchemaValidator(args);
|
|
219
|
+
break;
|
|
182
220
|
case TOOL_NAMES.REQUIRED_FIELDS_CHECKER:
|
|
183
|
-
|
|
221
|
+
result = await handleRequiredFieldsChecker(args);
|
|
222
|
+
break;
|
|
184
223
|
case TOOL_NAMES.DUPLICATE_REMOVER:
|
|
185
|
-
|
|
224
|
+
result = await handleDuplicateRemover(args);
|
|
225
|
+
break;
|
|
186
226
|
// AI-Powered Features
|
|
187
227
|
case TOOL_NAMES.SMART_SELECTOR_GENERATOR:
|
|
188
|
-
|
|
228
|
+
result = await handleSmartSelectorGenerator(args);
|
|
229
|
+
break;
|
|
189
230
|
case TOOL_NAMES.CONTENT_CLASSIFICATION:
|
|
190
|
-
|
|
231
|
+
result = await handleContentClassification(args);
|
|
232
|
+
break;
|
|
191
233
|
case TOOL_NAMES.SENTIMENT_ANALYSIS:
|
|
192
|
-
|
|
234
|
+
result = await handleSentimentAnalysis(args);
|
|
235
|
+
break;
|
|
193
236
|
case TOOL_NAMES.SUMMARY_GENERATOR:
|
|
194
|
-
|
|
237
|
+
result = await handleSummaryGenerator(args);
|
|
238
|
+
break;
|
|
195
239
|
case TOOL_NAMES.TRANSLATION_SUPPORT:
|
|
196
|
-
|
|
240
|
+
result = await handleTranslationSupport(args);
|
|
241
|
+
break;
|
|
197
242
|
// Search & Filter Tools
|
|
198
243
|
case TOOL_NAMES.KEYWORD_SEARCH:
|
|
199
|
-
|
|
244
|
+
result = await handleKeywordSearch(args);
|
|
245
|
+
break;
|
|
200
246
|
case TOOL_NAMES.REGEX_PATTERN_MATCHER:
|
|
201
|
-
|
|
247
|
+
result = await handleRegexPatternMatcher(args);
|
|
248
|
+
break;
|
|
202
249
|
case TOOL_NAMES.XPATH_SUPPORT:
|
|
203
|
-
|
|
250
|
+
result = await handleXPathSupport(args);
|
|
251
|
+
break;
|
|
204
252
|
case TOOL_NAMES.ADVANCED_CSS_SELECTORS:
|
|
205
|
-
|
|
253
|
+
result = await handleAdvancedCSSSelectors(args);
|
|
254
|
+
break;
|
|
206
255
|
case TOOL_NAMES.VISUAL_ELEMENT_FINDER:
|
|
207
|
-
|
|
256
|
+
result = await handleVisualElementFinder(args);
|
|
257
|
+
break;
|
|
208
258
|
// Data Quality & Validation
|
|
209
259
|
case TOOL_NAMES.DATA_DEDUPLICATION:
|
|
210
|
-
|
|
260
|
+
result = await handleDataDeduplication(args);
|
|
261
|
+
break;
|
|
211
262
|
case TOOL_NAMES.MISSING_DATA_HANDLER:
|
|
212
|
-
|
|
263
|
+
result = await handleMissingDataHandler(args);
|
|
264
|
+
break;
|
|
213
265
|
case TOOL_NAMES.DATA_TYPE_VALIDATOR:
|
|
214
|
-
|
|
266
|
+
result = await handleDataTypeValidator(args);
|
|
267
|
+
break;
|
|
215
268
|
case TOOL_NAMES.OUTLIER_DETECTION:
|
|
216
|
-
|
|
269
|
+
result = await handleOutlierDetection(args);
|
|
270
|
+
break;
|
|
217
271
|
case TOOL_NAMES.CONSISTENCY_CHECKER:
|
|
218
|
-
|
|
272
|
+
result = await handleConsistencyChecker(args);
|
|
273
|
+
break;
|
|
219
274
|
// Advanced Captcha Handling
|
|
220
275
|
case TOOL_NAMES.OCR_ENGINE:
|
|
221
|
-
|
|
276
|
+
result = await handleOCREngine(args);
|
|
277
|
+
break;
|
|
222
278
|
case TOOL_NAMES.AUDIO_CAPTCHA_SOLVER:
|
|
223
|
-
|
|
279
|
+
result = await handleAudioCaptchaSolver(args);
|
|
280
|
+
break;
|
|
224
281
|
case TOOL_NAMES.PUZZLE_CAPTCHA_HANDLER:
|
|
225
|
-
|
|
282
|
+
result = await handlePuzzleCaptchaHandler(args);
|
|
283
|
+
break;
|
|
226
284
|
// Screenshot & Visual Tools
|
|
227
285
|
case TOOL_NAMES.FULL_PAGE_SCREENSHOT:
|
|
228
|
-
|
|
286
|
+
result = await handleFullPageScreenshot(args);
|
|
287
|
+
break;
|
|
229
288
|
case TOOL_NAMES.ELEMENT_SCREENSHOT:
|
|
230
|
-
|
|
289
|
+
result = await handleElementScreenshot(args);
|
|
290
|
+
break;
|
|
231
291
|
case TOOL_NAMES.PDF_GENERATION:
|
|
232
|
-
|
|
292
|
+
result = await handlePDFGeneration(args);
|
|
293
|
+
break;
|
|
233
294
|
case TOOL_NAMES.VIDEO_RECORDING:
|
|
234
|
-
|
|
295
|
+
result = await handleVideoRecording(args);
|
|
296
|
+
break;
|
|
235
297
|
case TOOL_NAMES.VISUAL_COMPARISON:
|
|
236
|
-
|
|
298
|
+
result = await handleVisualComparison(args);
|
|
299
|
+
break;
|
|
237
300
|
// Website API Integration
|
|
238
301
|
case TOOL_NAMES.REST_API_ENDPOINT_FINDER:
|
|
239
|
-
|
|
302
|
+
result = await handleRESTAPIEndpointFinder(args);
|
|
303
|
+
break;
|
|
240
304
|
case TOOL_NAMES.WEBHOOK_SUPPORT:
|
|
241
|
-
|
|
305
|
+
result = await handleWebhookSupport(args);
|
|
306
|
+
break;
|
|
242
307
|
case TOOL_NAMES.ALL_WEBSITE_API_FINDER:
|
|
243
|
-
|
|
308
|
+
result = await handleAllWebsiteAPIFinder(args);
|
|
309
|
+
break;
|
|
244
310
|
// Smart Data Extractors (Advanced)
|
|
245
311
|
case 'html_elements_extractor':
|
|
246
|
-
|
|
312
|
+
result = await handleHtmlElementsExtractor(args || {});
|
|
313
|
+
break;
|
|
247
314
|
case 'tags_finder':
|
|
248
|
-
|
|
315
|
+
result = await handleTagsFinder(args || {});
|
|
316
|
+
break;
|
|
249
317
|
case 'links_finder':
|
|
250
|
-
|
|
318
|
+
result = await handleLinksFinder(args || {});
|
|
319
|
+
break;
|
|
251
320
|
case 'xpath_links':
|
|
252
|
-
|
|
321
|
+
result = await handleXpathLinks(args || {});
|
|
322
|
+
break;
|
|
253
323
|
case 'ajax_extractor':
|
|
254
|
-
|
|
324
|
+
result = await handleAjaxExtractor(args || {});
|
|
325
|
+
break;
|
|
255
326
|
case 'fetch_xhr':
|
|
256
|
-
|
|
327
|
+
result = await handleFetchXHR(args || {});
|
|
328
|
+
break;
|
|
257
329
|
case 'network_recorder':
|
|
258
|
-
|
|
330
|
+
result = await handleNetworkRecorder(args || {});
|
|
331
|
+
break;
|
|
259
332
|
case 'api_finder':
|
|
260
|
-
|
|
333
|
+
result = await handleApiFinder(args || {});
|
|
334
|
+
break;
|
|
261
335
|
case 'regex_pattern_finder':
|
|
262
|
-
|
|
336
|
+
result = await handleRegexPatternFinder(args);
|
|
337
|
+
break;
|
|
263
338
|
case 'iframe_extractor':
|
|
264
|
-
|
|
339
|
+
result = await handleIframeExtractor(args || {});
|
|
340
|
+
break;
|
|
265
341
|
case 'embed_page_extractor':
|
|
266
|
-
|
|
342
|
+
result = await handleEmbedPageExtractor(args || {});
|
|
343
|
+
break;
|
|
267
344
|
case 'image_extractor_advanced':
|
|
268
|
-
|
|
345
|
+
result = await handleImageExtractorAdvanced(args || {});
|
|
346
|
+
break;
|
|
269
347
|
case 'video_source_extractor':
|
|
270
|
-
|
|
348
|
+
result = await handleVideoSourceExtractor(args || {});
|
|
349
|
+
break;
|
|
271
350
|
case 'video_player_extractor':
|
|
272
|
-
|
|
351
|
+
result = await handleVideoPlayerExtractor(args || {});
|
|
352
|
+
break;
|
|
273
353
|
case 'video_player_hoster_finder':
|
|
274
|
-
|
|
354
|
+
result = await handleVideoPlayerHosterFinder(args || {});
|
|
355
|
+
break;
|
|
275
356
|
case 'original_video_hoster_finder':
|
|
276
|
-
|
|
357
|
+
result = await handleOriginalVideoHosterFinder(args || {});
|
|
358
|
+
break;
|
|
277
359
|
case 'url_redirect_tracer':
|
|
278
|
-
|
|
360
|
+
result = await handleUrlRedirectTracer(args);
|
|
361
|
+
break;
|
|
279
362
|
case 'user_agent_extractor':
|
|
280
|
-
|
|
363
|
+
result = await handleUserAgentExtractor(args || {});
|
|
364
|
+
break;
|
|
281
365
|
// Dynamic Content & Session Handling
|
|
282
366
|
case 'shadow_dom_extractor':
|
|
283
|
-
|
|
367
|
+
result = await handleShadowDOMExtractor(args || {});
|
|
368
|
+
break;
|
|
284
369
|
case 'cookie_manager':
|
|
285
|
-
|
|
370
|
+
result = await handleCookieManager(args);
|
|
371
|
+
break;
|
|
286
372
|
case 'session_persistence':
|
|
287
|
-
|
|
373
|
+
result = await handleSessionPersistence(args);
|
|
374
|
+
break;
|
|
288
375
|
case 'form_auto_fill':
|
|
289
|
-
|
|
376
|
+
result = await handleFormAutoFill(args);
|
|
377
|
+
break;
|
|
290
378
|
case 'ajax_content_waiter':
|
|
291
|
-
|
|
379
|
+
result = await handleAjaxContentWaiter(args);
|
|
380
|
+
break;
|
|
292
381
|
case 'modal_popup_handler':
|
|
293
|
-
|
|
382
|
+
result = await handleModalPopupHandler(args);
|
|
383
|
+
break;
|
|
294
384
|
case 'login_session_manager':
|
|
295
|
-
|
|
385
|
+
result = await handleLoginSessionManager(args);
|
|
386
|
+
break;
|
|
296
387
|
// Monitoring & Reporting
|
|
297
388
|
case 'progress_tracker':
|
|
298
|
-
|
|
389
|
+
result = await handleProgressTracker(args || {});
|
|
390
|
+
break;
|
|
299
391
|
case 'error_logger':
|
|
300
|
-
|
|
392
|
+
result = await handleErrorLogger(args || {});
|
|
393
|
+
break;
|
|
301
394
|
case 'success_rate_reporter':
|
|
302
|
-
|
|
395
|
+
result = await handleSuccessRateReporter(args || {});
|
|
396
|
+
break;
|
|
303
397
|
case 'data_quality_metrics':
|
|
304
|
-
|
|
398
|
+
result = await handleDataQualityMetrics(args || {});
|
|
399
|
+
break;
|
|
305
400
|
case 'performance_monitor':
|
|
306
|
-
|
|
401
|
+
result = await handlePerformanceMonitor(args || {});
|
|
402
|
+
break;
|
|
307
403
|
case 'monitoring_summary':
|
|
308
|
-
|
|
404
|
+
result = await handleGetMonitoringSummary(args || {});
|
|
405
|
+
break;
|
|
309
406
|
// Advanced Video & Media Download Tools
|
|
310
407
|
case 'video_link_finder':
|
|
311
|
-
|
|
408
|
+
result = await handleVideoLinkFinder(args || {});
|
|
409
|
+
break;
|
|
312
410
|
case 'video_download_page':
|
|
313
|
-
|
|
411
|
+
result = await handleVideoDownloadPage(args || {});
|
|
412
|
+
break;
|
|
314
413
|
case 'video_download_button':
|
|
315
|
-
|
|
414
|
+
result = await handleVideoDownloadButton(args);
|
|
415
|
+
break;
|
|
316
416
|
case 'video_play_push_source':
|
|
317
|
-
|
|
417
|
+
result = await handleVideoPlayPushSource(args || {});
|
|
418
|
+
break;
|
|
318
419
|
case 'video_play_button_click':
|
|
319
|
-
|
|
420
|
+
result = await handleVideoPlayButtonClick(args || {});
|
|
421
|
+
break;
|
|
320
422
|
case 'url_redirect_trace_endpoints':
|
|
321
|
-
|
|
423
|
+
result = await handleUrlRedirectTraceEndpoints(args);
|
|
424
|
+
break;
|
|
322
425
|
case 'network_recording_finder':
|
|
323
|
-
|
|
426
|
+
result = await handleNetworkRecordingFinder(args || {});
|
|
427
|
+
break;
|
|
324
428
|
case 'network_recording_extractors':
|
|
325
|
-
|
|
429
|
+
result = await handleNetworkRecordingExtractors(args || {});
|
|
430
|
+
break;
|
|
326
431
|
case 'video_links_finders':
|
|
327
|
-
|
|
432
|
+
result = await handleVideoLinksFinders(args || {});
|
|
433
|
+
break;
|
|
328
434
|
case 'videos_selectors':
|
|
329
|
-
|
|
435
|
+
result = await handleVideosSelectors(args || {});
|
|
436
|
+
break;
|
|
330
437
|
case 'link_process_extracts':
|
|
331
|
-
|
|
438
|
+
result = await handleLinkProcessExtracts(args || {});
|
|
439
|
+
break;
|
|
332
440
|
case 'video_link_finders_extracts':
|
|
333
|
-
|
|
441
|
+
result = await handleVideoLinkFindersExtracts(args || {});
|
|
442
|
+
break;
|
|
334
443
|
case 'video_download_button_finders':
|
|
335
|
-
|
|
444
|
+
result = await handleVideoDownloadButtonFinders(args || {});
|
|
445
|
+
break;
|
|
446
|
+
// Advanced Extraction Tools (Ad-Bypass & Obfuscation)
|
|
447
|
+
case 'advanced_video_extraction':
|
|
448
|
+
result = await handleAdvancedVideoExtraction(args || {});
|
|
449
|
+
break;
|
|
450
|
+
case 'deobfuscate_js':
|
|
451
|
+
result = await handleDeobfuscateJS(args || {});
|
|
452
|
+
break;
|
|
453
|
+
case 'multi_layer_redirect_trace':
|
|
454
|
+
result = await handleMultiLayerRedirectTrace(args);
|
|
455
|
+
break;
|
|
456
|
+
case 'ad_protection_detector':
|
|
457
|
+
result = await handleAdProtectionDetector(args || {});
|
|
458
|
+
break;
|
|
336
459
|
default:
|
|
337
460
|
throw new Error(`Unknown tool: ${name}`);
|
|
338
461
|
}
|
|
462
|
+
// Validate MCP response format universally
|
|
463
|
+
return validateMCPResponse(result, name);
|
|
339
464
|
}
|
|
340
465
|
catch (error) {
|
|
341
466
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Response Validator
|
|
3
|
+
* Ensures all tool responses conform to MCP SDK standards
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Validates and ensures response is in proper MCP format
|
|
7
|
+
*/
|
|
8
|
+
export function validateMCPResponse(response, toolName) {
|
|
9
|
+
// If response is null or undefined
|
|
10
|
+
if (!response) {
|
|
11
|
+
console.error(`ā ļø Tool ${toolName} returned null/undefined`);
|
|
12
|
+
return {
|
|
13
|
+
content: [{
|
|
14
|
+
type: 'text',
|
|
15
|
+
text: `ā ļø Tool ${toolName} returned no data. This might indicate:
|
|
16
|
+
⢠The tool completed but found no results
|
|
17
|
+
⢠An internal error occurred
|
|
18
|
+
⢠The page state doesn't support this operation
|
|
19
|
+
|
|
20
|
+
š” Try: Refresh the page or navigate to the target URL first.`
|
|
21
|
+
}]
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
// If response is empty object
|
|
25
|
+
if (typeof response === 'object' && Object.keys(response).length === 0) {
|
|
26
|
+
console.error(`ā ļø Tool ${toolName} returned empty object {}`);
|
|
27
|
+
return {
|
|
28
|
+
content: [{
|
|
29
|
+
type: 'text',
|
|
30
|
+
text: `ā ļø Tool ${toolName} returned empty result. This typically means:
|
|
31
|
+
⢠No data was found matching the criteria
|
|
32
|
+
⢠The page needs to be freshly loaded for monitoring tools
|
|
33
|
+
⢠Network events have already completed
|
|
34
|
+
|
|
35
|
+
š” Suggestion: For network monitoring tools, start monitoring before navigating to the page.`
|
|
36
|
+
}]
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
// If response has content array, validate it
|
|
40
|
+
if (response.content && Array.isArray(response.content)) {
|
|
41
|
+
// Check if content array is empty
|
|
42
|
+
if (response.content.length === 0) {
|
|
43
|
+
console.warn(`ā ļø Tool ${toolName} has empty content array`);
|
|
44
|
+
return {
|
|
45
|
+
content: [{
|
|
46
|
+
type: 'text',
|
|
47
|
+
text: `ā¹ļø Tool ${toolName} executed successfully but returned no content.`
|
|
48
|
+
}],
|
|
49
|
+
isError: response.isError
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
// Validate each content item
|
|
53
|
+
const validContent = response.content.filter((item) => {
|
|
54
|
+
return item && typeof item === 'object' && item.type && (item.text || item.data);
|
|
55
|
+
});
|
|
56
|
+
if (validContent.length === 0) {
|
|
57
|
+
console.error(`ā Tool ${toolName} has invalid content items`);
|
|
58
|
+
return {
|
|
59
|
+
content: [{
|
|
60
|
+
type: 'text',
|
|
61
|
+
text: `ā Tool ${toolName} returned malformed content. Please report this issue.`
|
|
62
|
+
}],
|
|
63
|
+
isError: true
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
content: validContent,
|
|
68
|
+
isError: response.isError
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
// If response is a string, wrap it
|
|
72
|
+
if (typeof response === 'string') {
|
|
73
|
+
return {
|
|
74
|
+
content: [{
|
|
75
|
+
type: 'text',
|
|
76
|
+
text: response
|
|
77
|
+
}]
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
// If response is in unexpected format
|
|
81
|
+
console.error(`ā Tool ${toolName} returned unexpected format:`, typeof response);
|
|
82
|
+
return {
|
|
83
|
+
content: [{
|
|
84
|
+
type: 'text',
|
|
85
|
+
text: `ā Tool ${toolName} returned unexpected format: ${typeof response}
|
|
86
|
+
|
|
87
|
+
Result: ${JSON.stringify(response, null, 2).substring(0, 500)}`
|
|
88
|
+
}],
|
|
89
|
+
isError: true
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Wraps tool execution with response validation
|
|
94
|
+
*/
|
|
95
|
+
export async function executeWithValidation(toolName, handler) {
|
|
96
|
+
try {
|
|
97
|
+
const result = await handler();
|
|
98
|
+
return validateMCPResponse(result, toolName);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
console.error(`ā Tool ${toolName} threw error:`, error);
|
|
102
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
103
|
+
return {
|
|
104
|
+
content: [{
|
|
105
|
+
type: 'text',
|
|
106
|
+
text: `ā Tool execution failed: ${toolName}
|
|
107
|
+
|
|
108
|
+
Error: ${errorMessage}
|
|
109
|
+
|
|
110
|
+
${error instanceof Error && error.stack ? `Stack:\n${error.stack.substring(0, 500)}` : ''}`
|
|
111
|
+
}],
|
|
112
|
+
isError: true
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Creates a "no data" response with helpful message
|
|
118
|
+
*/
|
|
119
|
+
export function createNoDataResponse(toolName, dataType, suggestions = []) {
|
|
120
|
+
let message = `ā¹ļø ${toolName}: No ${dataType} found.`;
|
|
121
|
+
if (suggestions.length > 0) {
|
|
122
|
+
message += `\n\nš” Suggestions:\n${suggestions.map(s => ` ⢠${s}`).join('\n')}`;
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
content: [{
|
|
126
|
+
type: 'text',
|
|
127
|
+
text: message
|
|
128
|
+
}]
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Creates a success response with data
|
|
133
|
+
*/
|
|
134
|
+
export function createSuccessResponse(toolName, message, data) {
|
|
135
|
+
let text = `ā
${message}`;
|
|
136
|
+
if (data) {
|
|
137
|
+
text += `\n\n${typeof data === 'string' ? data : JSON.stringify(data, null, 2)}`;
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
content: [{
|
|
141
|
+
type: 'text',
|
|
142
|
+
text
|
|
143
|
+
}]
|
|
144
|
+
};
|
|
145
|
+
}
|