brave-real-browser-mcp-server 2.17.10 → 2.17.12

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.
@@ -237,17 +237,33 @@ export const TOOLS = [
237
237
  },
238
238
  {
239
239
  name: 'solve_captcha',
240
- description: 'Attempt to solve CAPTCHAs (if supported)',
240
+ description: 'Solve various types of CAPTCHAs (Auto-detect, OCR, Audio, Puzzle). Routes to appropriate solver based on arguments.',
241
241
  inputSchema: {
242
242
  type: 'object',
243
243
  properties: {
244
- type: {
244
+ strategy: {
245
245
  type: 'string',
246
- enum: ['recaptcha', 'hCaptcha', 'turnstile'],
247
- description: 'Type of captcha to solve',
246
+ enum: ['auto', 'ocr', 'audio', 'puzzle', 'recaptcha', 'hCaptcha', 'turnstile'],
247
+ description: 'Strategy to use. "auto" attempts to infer based on provided arguments.',
248
+ default: 'auto'
248
249
  },
250
+ // Shared
251
+ url: { type: 'string' },
252
+ // OCR
253
+ selector: { type: 'string' },
254
+ imageUrl: { type: 'string' },
255
+ imageBuffer: { type: 'string' },
256
+ language: { type: 'string' },
257
+ // Audio
258
+ audioSelector: { type: 'string' },
259
+ audioUrl: { type: 'string' },
260
+ downloadPath: { type: 'string' },
261
+ // Puzzle
262
+ puzzleSelector: { type: 'string' },
263
+ sliderSelector: { type: 'string' },
264
+ method: { type: 'string' },
249
265
  },
250
- required: ['type'],
266
+ required: [],
251
267
  },
252
268
  },
253
269
  {
@@ -336,18 +352,6 @@ export const TOOLS = [
336
352
  },
337
353
  // Smart Data Extractors
338
354
  // DOM & HTML Extraction (Phase 1)
339
- {
340
- name: 'html_elements_extractor',
341
- description: 'Extract detailed information about HTML elements matching a selector',
342
- inputSchema: {
343
- type: 'object',
344
- properties: {
345
- selector: { type: 'string', default: '*' },
346
- maxElements: { type: 'number', default: 100 },
347
- includeStyles: { type: 'boolean', default: false },
348
- },
349
- },
350
- },
351
355
  {
352
356
  name: 'extract_json',
353
357
  description: 'Extract embedded JSON/API data from the page',
@@ -398,19 +402,6 @@ export const TOOLS = [
398
402
  required: ['selector'],
399
403
  },
400
404
  },
401
- {
402
- name: 'attribute_harvester',
403
- description: 'Collect attributes (href, src, data-*) from elements',
404
- inputSchema: {
405
- type: 'object',
406
- properties: {
407
- selector: { type: 'string' },
408
- attributes: { type: 'array', items: { type: 'string' } },
409
- maxElements: { type: 'number', default: 100 },
410
- },
411
- required: ['selector'],
412
- },
413
- },
414
405
  // Content Type Specific Extractors
415
406
  {
416
407
  name: 'link_harvester',
@@ -476,115 +467,60 @@ export const TOOLS = [
476
467
  },
477
468
  },
478
469
  // Search & Filter Tools (5 tools)
470
+ // Search & Filter Tools (Consolidated)
479
471
  {
480
- name: 'keyword_search',
481
- description: 'Advanced keyword search in page content',
472
+ name: 'search_content',
473
+ description: 'Search content using keywords or regex patterns.',
482
474
  inputSchema: {
483
475
  type: 'object',
484
476
  properties: {
477
+ query: { type: 'string', description: 'Keyword or Regex pattern' },
478
+ type: { type: 'string', enum: ['text', 'regex'], default: 'text' },
485
479
  url: { type: 'string' },
486
- keywords: { type: 'array', items: { type: 'string' } },
480
+ // Text options
487
481
  caseSensitive: { type: 'boolean', default: false },
488
482
  wholeWord: { type: 'boolean', default: false },
489
483
  context: { type: 'number', default: 50 },
490
- },
491
- required: ['keywords'],
492
- },
493
- },
494
- {
495
- name: 'regex_pattern_matcher',
496
- description: 'Search using regular expressions',
497
- inputSchema: {
498
- type: 'object',
499
- properties: {
500
- url: { type: 'string' },
501
- pattern: { type: 'string', description: 'Regular expression pattern' },
484
+ // Regex options
502
485
  flags: { type: 'string', default: 'g' },
503
- selector: { type: 'string' },
486
+ selector: { type: 'string', description: 'Limit search to specific element' },
504
487
  },
505
- required: ['pattern'],
488
+ required: ['query'],
506
489
  },
507
490
  },
508
491
  {
509
- name: 'xpath_support',
510
- description: 'Query elements using XPath',
492
+ name: 'find_element_advanced',
493
+ description: 'Find elements using XPath or Advanced CSS selectors.',
511
494
  inputSchema: {
512
495
  type: 'object',
513
496
  properties: {
497
+ query: { type: 'string', description: 'Selector or XPath expression' },
498
+ type: { type: 'string', enum: ['css', 'xpath'], default: 'css' },
514
499
  url: { type: 'string' },
515
- xpath: { type: 'string', description: 'XPath expression' },
516
- returnType: { type: 'string', default: 'elements' },
517
- },
518
- required: ['xpath'],
519
- },
520
- },
521
- {
522
- name: 'advanced_css_selectors',
523
- description: 'Support for complex CSS selectors',
524
- inputSchema: {
525
- type: 'object',
526
- properties: {
527
- url: { type: 'string' },
528
- selector: { type: 'string' },
500
+ // CSS options
529
501
  operation: { type: 'string', enum: ['query', 'closest', 'matches'], default: 'query' },
530
- returnType: { type: 'string', default: 'elements' },
502
+ // Shared
503
+ returnType: { type: 'string', enum: ['elements', 'styles', 'html'], default: 'elements' },
531
504
  },
532
- required: ['selector'],
505
+ required: ['query'],
533
506
  },
534
507
  },
535
508
  // Data Quality & Validation (5 tools)
509
+ // Deep Analysis Tool -- Trace Recording
536
510
  {
537
- name: 'data_type_validator',
538
- description: 'Validate data types against JSON schema',
539
- inputSchema: {
540
- type: 'object',
541
- properties: {
542
- data: { description: 'Data to validate' },
543
- schema: { type: 'object', description: 'JSON Schema' },
544
- },
545
- required: ['data', 'schema'],
546
- },
547
- },
548
- // Advanced Captcha Handling (3 tools)
549
- {
550
- name: 'ocr_engine',
551
- description: 'Extract text from captcha images using OCR',
511
+ name: 'deep_analysis',
512
+ description: 'Perform a deep analysis of the page including network traces, console logs, DOM snapshot, and screenshot. Equivalent to a trace recording.',
552
513
  inputSchema: {
553
514
  type: 'object',
554
515
  properties: {
555
516
  url: { type: 'string' },
556
- selector: { type: 'string' },
557
- imageUrl: { type: 'string' },
558
- imageBuffer: { type: 'string', description: 'Base64 encoded image' },
559
- language: { type: 'string', default: 'eng' },
560
- },
561
- },
562
- },
563
- {
564
- name: 'audio_captcha_solver',
565
- description: 'Handle audio captchas',
566
- inputSchema: {
567
- type: 'object',
568
- properties: {
569
- url: { type: 'string' },
570
- audioSelector: { type: 'string' },
571
- audioUrl: { type: 'string' },
572
- downloadPath: { type: 'string' },
573
- },
574
- },
575
- },
576
- {
577
- name: 'puzzle_captcha_handler',
578
- description: 'Handle slider and puzzle captchas',
579
- inputSchema: {
580
- type: 'object',
581
- properties: {
582
- url: { type: 'string' },
583
- puzzleSelector: { type: 'string' },
584
- sliderSelector: { type: 'string' },
585
- method: { type: 'string', enum: ['auto', 'manual'], default: 'auto' },
586
- },
587
- },
517
+ duration: { type: 'number', default: 5000, description: 'Duration to record (ms)' },
518
+ screenshots: { type: 'boolean', default: true },
519
+ network: { type: 'boolean', default: true },
520
+ logs: { type: 'boolean', default: true },
521
+ dom: { type: 'boolean', default: true }
522
+ }
523
+ }
588
524
  },
589
525
  // Screenshot & Visual Tools (5 tools)
590
526
  {
@@ -616,16 +552,6 @@ export const TOOLS = [
616
552
  },
617
553
  },
618
554
  // Smart Data Extractors (Advanced)
619
- {
620
- name: 'fetch_xhr',
621
- description: 'Capture fetch and XHR requests with responses',
622
- inputSchema: {
623
- type: 'object',
624
- properties: {
625
- duration: { type: 'number', default: 15000 },
626
- },
627
- },
628
- },
629
555
  {
630
556
  name: 'network_recorder',
631
557
  description: 'Record all network activity',
@@ -713,14 +639,6 @@ export const TOOLS = [
713
639
  },
714
640
  },
715
641
  },
716
- {
717
- name: 'deobfuscate_js',
718
- description: 'Deobfuscate JavaScript code and extract hidden URLs, domains, and base64-encoded content. Detects eval, atob, hex encoding, and identifier obfuscation.',
719
- inputSchema: {
720
- type: 'object',
721
- properties: {},
722
- },
723
- },
724
642
  {
725
643
  name: 'multi_layer_redirect_trace',
726
644
  description: 'Follow multiple layers of redirects (URL redirects and iframe chains) to find final video source. Traces up to specified depth.',
@@ -754,46 +672,6 @@ export const TOOLS = [
754
672
  },
755
673
  },
756
674
  // Phase 3: Media & Video Tools
757
- {
758
- name: 'video_source_extractor',
759
- description: 'Extract raw video sources from video tags and sources',
760
- inputSchema: {
761
- type: 'object',
762
- properties: {
763
- url: { type: 'string' }
764
- }
765
- }
766
- },
767
- {
768
- name: 'video_player_finder',
769
- description: 'Identify video players (JWPlayer, VideoJS, etc) and extract config',
770
- inputSchema: {
771
- type: 'object',
772
- properties: {
773
- url: { type: 'string' }
774
- }
775
- }
776
- },
777
- {
778
- name: 'stream_detector',
779
- description: 'Detects HLS (m3u8) and DASH (mpd) streams from network traffic',
780
- inputSchema: {
781
- type: 'object',
782
- properties: {
783
- duration: { type: 'number', description: 'Monitoring duration in ms' }
784
- }
785
- }
786
- },
787
- {
788
- name: 'video_download_link_finder',
789
- description: 'Find direct download links for video files',
790
- inputSchema: {
791
- type: 'object',
792
- properties: {
793
- extensions: { type: 'array', items: { type: 'string' } }
794
- }
795
- }
796
- }
797
675
  ];
798
676
  // Tool name constants for type safety
799
677
  export const TOOL_NAMES = {
@@ -814,14 +692,11 @@ export const TOOL_NAMES = {
814
692
  EXTRACT_SCHEMA: 'extract_schema',
815
693
  // Multi-Element Extractors
816
694
  BATCH_ELEMENT_SCRAPER: 'batch_element_scraper',
817
- ATTRIBUTE_HARVESTER: 'attribute_harvester',
818
695
  // Content Type Specific
819
696
  LINK_HARVESTER: 'link_harvester',
820
697
  MEDIA_EXTRACTOR: 'media_extractor',
821
698
  // DOM & HTML Extraction (Phase 1)
822
- HTML_ELEMENTS_EXTRACTOR: 'html_elements_extractor',
823
699
  // Network Tools (Phase 1)
824
- FETCH_XHR: 'fetch_xhr',
825
700
  NETWORK_RECORDER: 'network_recorder',
826
701
  API_FINDER: 'api_finder',
827
702
  // Pagination Tools
@@ -831,20 +706,17 @@ export const TOOL_NAMES = {
831
706
  SMART_SELECTOR_GENERATOR: 'smart_selector_generator',
832
707
  CONTENT_CLASSIFICATION: 'content_classification',
833
708
  // Phase 3: Media & Video
834
- VIDEO_SOURCE_EXTRACTOR: 'video_source_extractor',
835
- VIDEO_PLAYER_FINDER: 'video_player_finder',
836
- STREAM_DETECTOR: 'stream_detector',
837
- // Search & Filter Tools
838
- KEYWORD_SEARCH: 'keyword_search',
839
- REGEX_PATTERN_MATCHER: 'regex_pattern_matcher',
840
- XPATH_SUPPORT: 'xpath_support',
841
- ADVANCED_CSS_SELECTORS: 'advanced_css_selectors',
709
+ // Search & Filter (Consolidated)
710
+ SEARCH_CONTENT: 'search_content',
711
+ FIND_ELEMENT_ADVANCED: 'find_element_advanced',
712
+ // Deep Analysis
713
+ DEEP_ANALYSIS: 'deep_analysis',
842
714
  // Data Quality & Validation
843
- DATA_TYPE_VALIDATOR: 'data_type_validator',
844
- // Advanced Captcha Handling
845
- OCR_ENGINE: 'ocr_engine',
846
- AUDIO_CAPTCHA_SOLVER: 'audio_captcha_solver',
847
- PUZZLE_CAPTCHA_HANDLER: 'puzzle_captcha_handler',
715
+ // (Removed DATA_TYPE_VALIDATOR)
716
+ // Advanced Captcha Handling (Consolidated)
717
+ // OCR_ENGINE: 'ocr_engine', // Merged into solve_captcha
718
+ // AUDIO_CAPTCHA_SOLVER: 'audio_captcha_solver', // Merged
719
+ // PUZZLE_CAPTCHA_HANDLER: 'puzzle_captcha_handler', // Merged
848
720
  // Screenshot & Visual Tools
849
721
  ELEMENT_SCREENSHOT: 'element_screenshot',
850
722
  VIDEO_RECORDING: 'video_recording',
@@ -1,10 +1,9 @@
1
1
  import { handleBrowserInit } from '../handlers/browser-handlers.js';
2
2
  import { handleNavigate } from '../handlers/navigation-handlers.js';
3
- import { handleAdProtectionDetector, handleAdvancedVideoExtraction, handleDeobfuscateJS } from '../handlers/advanced-extraction-handlers.js';
4
- import { handleVideoDownloadLinkFinder } from '../handlers/advanced-video-media-handlers.js';
3
+ import { handleAdProtectionDetector, handleAdvancedVideoExtraction } from '../handlers/advanced-extraction-handlers.js';
5
4
  import { handleSmartSelectorGenerator } from '../handlers/ai-powered-handlers.js';
6
5
  import { handleNetworkRecorder, handleApiFinder } from '../handlers/smart-data-extractors.js';
7
- import { handleRegexPatternMatcher } from '../handlers/search-filter-handlers.js';
6
+ import { handleSearchContent } from '../handlers/unified-search-handler.js';
8
7
  import { handleRandomScroll } from '../handlers/interaction-handlers.js';
9
8
  async function main() {
10
9
  const targetUrl = "https://multimovies.golf/movies/120-bahadur/";
@@ -48,15 +47,7 @@ async function main() {
48
47
  }
49
48
  // Logic Extraction (looking for player config)
50
49
  try {
51
- const deobfuscated = await handleDeobfuscateJS({});
52
- // Filter for relevant keys
53
- if (deobfuscated && deobfuscated.content) {
54
- const keyTerms = ['player', 'token', 'm3u8', 'mp4', 'config'];
55
- const relevantScripts = deobfuscated.content
56
- .filter((c) => c.text && keyTerms.some(term => c.text.includes(term)))
57
- .map((c) => c.text.substring(0, 200) + "...");
58
- report.infrastructure.event_handlers = relevantScripts;
59
- }
50
+ console.log("Deobfuscation is now handled by Advanced Video Extraction.");
60
51
  }
61
52
  catch (e) {
62
53
  console.log("Deobfuscation skipped");
@@ -79,7 +70,7 @@ async function main() {
79
70
  ];
80
71
  report.infrastructure.patterns = [];
81
72
  for (const check of regexChecks) {
82
- const match = await handleRegexPatternMatcher({ pattern: check.pattern });
73
+ const match = await handleSearchContent({ query: check.pattern, type: 'regex' });
83
74
  if (match && match.content) {
84
75
  report.infrastructure.patterns.push({ type: check.name, result: match.content });
85
76
  }
@@ -91,8 +82,7 @@ async function main() {
91
82
  // Assuming videoAssets structure, we'd loop and add to report.targets
92
83
  // For now, dump the raw result
93
84
  report.targets_raw = videoAssets;
94
- const downloadLinks = await handleVideoDownloadLinkFinder({});
95
- report.download_links = downloadLinks;
85
+ report.download_links = "Handled by Advanced Video Extraction";
96
86
  console.log("--- MASTER REPORT JSON ---");
97
87
  console.log(JSON.stringify(report, null, 2));
98
88
  console.log("--- END REPORT ---");
@@ -3,8 +3,7 @@ import { handleNavigate } from '../handlers/navigation-handlers.js';
3
3
  import { handleRandomScroll } from '../handlers/interaction-handlers.js';
4
4
  import { handleElementScreenshot } from '../handlers/visual-tools-handlers.js';
5
5
  import { handleNetworkRecorder } from '../handlers/smart-data-extractors.js';
6
- import { handleAdvancedVideoExtraction, handleDeobfuscateJS, handleAdProtectionDetector } from '../handlers/advanced-extraction-handlers.js';
7
- import { handleVideoDownloadLinkFinder } from '../handlers/advanced-video-media-handlers.js';
6
+ import { handleAdvancedVideoExtraction, handleAdProtectionDetector } from '../handlers/advanced-extraction-handlers.js';
8
7
  async function main() {
9
8
  const targetUrl = process.argv[2];
10
9
  if (!targetUrl) {
@@ -45,9 +44,7 @@ async function main() {
45
44
  }
46
45
  // 6. Obfuscation Bypass
47
46
  if (!foundMedia) {
48
- console.log("Deep Scan empty. Attempting Deobfuscation...");
49
- const deobfuscated = await handleDeobfuscateJS({});
50
- console.log("Deobfuscation Results:", deobfuscated);
47
+ console.log("Deep Scan empty. Deobfuscation is now handled by Advanced Video Extraction.");
51
48
  }
52
49
  // 7. Network Traffic
53
50
  if (!foundMedia) {
@@ -57,9 +54,7 @@ async function main() {
57
54
  }
58
55
  // Phase 3: Redirect & Link Validation
59
56
  console.log("\n--- Phase 3: Redirect & Link Validation ---");
60
- console.log("Dumping page download links...");
61
- const links = await handleVideoDownloadLinkFinder({});
62
- console.log("Page Video Links:", links);
57
+ console.log("Direct download link finding is now integrated into Advanced Video Extraction.");
63
58
  // Phase 4: Fallback
64
59
  console.log("\n--- Phase 4: Fallback / Manual Aid ---");
65
60
  if (!foundMedia) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brave-real-browser-mcp-server",
3
- "version": "2.17.10",
3
+ "version": "2.17.12",
4
4
  "description": "Universal AI IDE MCP Server - Auto-detects and supports all AI IDEs (Claude Desktop, Cursor, Windsurf, Cline, Zed, VSCode, Qoder AI, etc.) with Brave browser automation",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,139 +0,0 @@
1
- import { getPageInstance } from '../browser-manager.js';
2
- /**
3
- * Extract raw video sources from <video> tags and <source> elements
4
- */
5
- export async function handleVideoSourceExtractor(args) {
6
- const { url } = args;
7
- const page = getPageInstance();
8
- if (!page)
9
- throw new Error('Browser not initialized. Call browser_init first.');
10
- if (url && page.url() !== url)
11
- await page.goto(url, { waitUntil: 'domcontentloaded' });
12
- const sources = await page.evaluate(() => {
13
- return Array.from(document.querySelectorAll('video')).map((v, i) => ({
14
- index: i,
15
- src: v.src,
16
- currentSrc: v.currentSrc,
17
- sources: Array.from(v.querySelectorAll('source')).map(s => ({ src: s.src, type: s.type })),
18
- poster: v.poster
19
- }));
20
- });
21
- return { content: [{ type: 'text', text: JSON.stringify(sources, null, 2) }] };
22
- }
23
- /**
24
- * Identify common video players and configuration
25
- */
26
- export async function handleVideoPlayerFinder(args) {
27
- const { url } = args;
28
- const page = getPageInstance();
29
- if (!page)
30
- throw new Error('Browser not initialized. Call browser_init first.');
31
- if (url && page.url() !== url)
32
- await page.goto(url, { waitUntil: 'domcontentloaded' });
33
- const players = await page.evaluate(() => {
34
- const detected = [];
35
- // @ts-ignore
36
- if (window.jwplayer)
37
- detected.push('JWPlayer');
38
- // @ts-ignore
39
- if (window.videojs)
40
- detected.push('VideoJS');
41
- // Check for iframes
42
- document.querySelectorAll('iframe').forEach(f => {
43
- if (f.src.includes('youtube.com/embed'))
44
- detected.push('YouTube Embed');
45
- if (f.src.includes('vimeo.com'))
46
- detected.push('Vimeo Embed');
47
- });
48
- return [...new Set(detected)];
49
- });
50
- return { content: [{ type: 'text', text: `Detected Players: ${players.join(', ') || 'None found'}` }] };
51
- }
52
- /**
53
- * Detect HLS (m3u8) / DASH (mpd) streams in network traffic
54
- */
55
- export async function handleStreamDetector(args) {
56
- const page = getPageInstance();
57
- if (!page)
58
- throw new Error('Browser not initialized. Call browser_init first.');
59
- const duration = args.duration || 10000;
60
- const streams = [];
61
- const handler = (response) => {
62
- const url = response.url();
63
- if (url.includes('.m3u8') || url.includes('.mpd')) {
64
- streams.push({ url, type: url.includes('.m3u8') ? 'HLS' : 'DASH', status: response.status() });
65
- }
66
- };
67
- page.on('response', handler);
68
- await new Promise(resolve => setTimeout(resolve, duration));
69
- page.off('response', handler);
70
- return { content: [{ type: 'text', text: JSON.stringify(streams, null, 2) }] };
71
- }
72
- /**
73
- * Trace URL redirects
74
- */
75
- export async function handleRedirectTracer(args) {
76
- const page = getPageInstance();
77
- if (!page)
78
- throw new Error('Browser not initialized. Call browser_init first.');
79
- const chain = [];
80
- const handler = (response) => {
81
- if ([301, 302, 303, 307, 308].includes(response.status())) {
82
- chain.push(`${response.url()} -> ${response.headers()['location']}`);
83
- }
84
- };
85
- page.on('response', handler);
86
- await page.goto(args.url, { waitUntil: 'networkidle2' });
87
- page.off('response', handler);
88
- return { content: [{ type: 'text', text: JSON.stringify({ finalUrl: page.url(), redirectChain: chain }, null, 2) }] };
89
- }
90
- /**
91
- * Find direct video download links
92
- */
93
- export async function handleVideoDownloadLinkFinder(args) {
94
- const page = getPageInstance();
95
- if (!page)
96
- throw new Error('Browser not initialized. Call browser_init first.');
97
- const exts = args.extensions || ['.mp4', '.mkv', '.avi', '.mov', '.webm'];
98
- const links = await page.evaluate((extensions) => {
99
- return Array.from(document.querySelectorAll('a'))
100
- .filter(a => extensions.some(ext => a.href.toLowerCase().endsWith(ext)))
101
- .map(a => ({ text: a.textContent, href: a.href }));
102
- }, exts);
103
- return { content: [{ type: 'text', text: JSON.stringify(links, null, 2) }] };
104
- }
105
- // --- Implementation of missing "Ghost" handlers required by index.ts ---
106
- // Aliases or specific implementations
107
- export const handleVideoLinkFinder = handleVideoDownloadLinkFinder;
108
- export async function handleVideoDownloadButton(args) {
109
- // Basic implementation trying to find "Download" buttons contextually
110
- const page = getPageInstance();
111
- if (!page)
112
- throw new Error('Browser not initialized');
113
- const downloadProbability = await page.evaluate(() => {
114
- const buttons = Array.from(document.querySelectorAll('button, a'));
115
- return buttons.filter(b => b.textContent?.toLowerCase().includes('download')).map(b => ({
116
- text: b.textContent,
117
- outerHTML: b.outerHTML.substring(0, 100)
118
- }));
119
- });
120
- return { content: [{ type: 'text', text: JSON.stringify(downloadProbability, null, 2) }] };
121
- }
122
- export async function handleVideoPlayPushSource(args) {
123
- return { content: [{ type: 'text', text: "Video Play Push Source detected (Simulated)" }] };
124
- }
125
- export async function handleVideoPlayButtonClick(args) {
126
- const page = getPageInstance();
127
- if (!page)
128
- throw new Error('Browser not initialized');
129
- // Try to click the first play button found
130
- const clicked = await page.evaluate(() => {
131
- const playBtn = document.querySelector('button[aria-label="Play"], .vjs-big-play-button, .ytp-play-button');
132
- if (playBtn instanceof HTMLElement) {
133
- playBtn.click();
134
- return true;
135
- }
136
- return false;
137
- });
138
- return { content: [{ type: 'text', text: clicked ? "Clicked Play Button" : "No Play Button Found" }] };
139
- }