brave-real-browser-mcp-server 2.14.5 → 2.14.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -25
- package/dist/index.js +1 -26
- package/dist/tool-definitions.js +0 -45
- package/package.json +1 -1
- package/dist/handlers/api-integration-handlers.js +0 -335
- package/dist/universal-ide-adapter.js +0 -855
package/README.md
CHANGED
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
|
|
7
7
|

|
|
8
8
|

|
|
9
|
-

|
|
10
10
|

|
|
11
11
|

|
|
12
12
|
|
|
13
|
-
**सभी AI IDEs के लिए Universal MCP Server |
|
|
13
|
+
**सभी AI IDEs के लिए Universal MCP Server | 108+ Tools | Browser Automation | Web Scraping | CAPTCHA Solving**
|
|
14
14
|
|
|
15
|
-
[Installation](#-installation) | [Quick Start](#-quick-start) | [Qoder AI Setup](#-qoder-ai---complete-integration-guide) | [Tools](#-available-tools-
|
|
15
|
+
[Installation](#-installation) | [Quick Start](#-quick-start) | [Qoder AI Setup](#-qoder-ai---complete-integration-guide) | [Tools](#-available-tools-108) | [IDE Configurations](#-ide-configurations)
|
|
16
16
|
|
|
17
17
|
</div>
|
|
18
18
|
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
**Brave Real Browser MCP Server** एक powerful automation tool है जो:
|
|
24
24
|
|
|
25
25
|
- ✅ **15+ AI IDEs में काम करता है** (Claude, Cursor, Windsurf, Cline, Zed, VSCode, Qoder AI, etc.)
|
|
26
|
-
- ✅ **
|
|
26
|
+
- ✅ **108+ Automation Tools** - Browser control, scraping, CAPTCHA solving, video extraction
|
|
27
27
|
- ✅ **MCP Protocol (STDIO)** - Fast and secure local communication
|
|
28
28
|
- ✅ **Auto-Detection** - Automatically detects your IDE
|
|
29
29
|
- ✅ **Real Brave Browser** - Anti-detection features, bypass Cloudflare
|
|
@@ -81,19 +81,19 @@ npx brave-real-browser-mcp-server@latest
|
|
|
81
81
|
**Config file locations:**
|
|
82
82
|
|
|
83
83
|
- **Claude Desktop:** `%APPDATA%\Claude\claude_desktop_config.json` (Windows) or `~/Library/Application Support/Claude/claude_desktop_config.json` (Mac)
|
|
84
|
-
- **Cursor:** `%APPDATA%\Cursor\User\globalStorage\saoudrizwan.claude-dev\settings
|
|
84
|
+
- **Cursor:** `%APPDATA%\Cursor\User\globalStorage\saoudrizwan.claude-dev\settings<tool_call>_mcp_settings.json`
|
|
85
85
|
- **Windsurf:** `%APPDATA%\Windsurf\mcp.json`
|
|
86
86
|
|
|
87
87
|
### For Qoder AI
|
|
88
88
|
|
|
89
|
-
**Qoder AI supports MCP
|
|
89
|
+
**Qoder AI supports MCP servers through **STDIO** (Standard Input/Output).
|
|
90
90
|
|
|
91
91
|
**Complete step-by-step guide:** [See Qoder AI Integration Guide](#-qoder-ai---complete-integration-guide)
|
|
92
92
|
|
|
93
93
|
**Quick setup (STDIO):**
|
|
94
94
|
1. Add to config: `{"command": "npx", "args": ["-y", "brave-real-browser-mcp-server@latest"]}`
|
|
95
95
|
2. Restart Qoder AI
|
|
96
|
-
3. Use
|
|
96
|
+
3. Use 108 browser automation tools!
|
|
97
97
|
|
|
98
98
|
---
|
|
99
99
|
|
|
@@ -181,7 +181,7 @@ In Qoder AI, test:
|
|
|
181
181
|
|
|
182
182
|
```
|
|
183
183
|
"List all available MCP tools"
|
|
184
|
-
→ Expected:
|
|
184
|
+
→ Expected: 108 tools from Brave Real Browser
|
|
185
185
|
|
|
186
186
|
"Use browser_init to start the browser"
|
|
187
187
|
→ Expected: Browser opens
|
|
@@ -236,7 +236,7 @@ Then update config to:
|
|
|
236
236
|
|
|
237
237
|
### 📊 Available Tools in Qoder AI
|
|
238
238
|
|
|
239
|
-
All **
|
|
239
|
+
All **108 tools** are available:
|
|
240
240
|
|
|
241
241
|
✅ **Browser Management:** `browser_init`, `browser_close`
|
|
242
242
|
✅ **Navigation:** `navigate`, `wait`, `click`, `type`
|
|
@@ -245,7 +245,7 @@ All **111 tools** are available:
|
|
|
245
245
|
✅ **CAPTCHA Solving:** `solve_captcha`, `ocr_engine`
|
|
246
246
|
✅ **Data Processing:** `price_parser`, `date_normalizer`, `contact_extractor`
|
|
247
247
|
✅ **Visual Tools:** `full_page_screenshot`, `pdf_generation`
|
|
248
|
-
✅ **And
|
|
248
|
+
✅ **And 87+ more tools!**
|
|
249
249
|
|
|
250
250
|
---
|
|
251
251
|
|
|
@@ -363,7 +363,7 @@ Copy and paste this configuration:
|
|
|
363
363
|
|
|
364
364
|
**Location:**
|
|
365
365
|
|
|
366
|
-
- Windows: `%APPDATA%\Code\User\globalStorage\saoudrizwan.claude-dev\settings
|
|
366
|
+
- Windows: `%APPDATA%\Code\User\globalStorage\saoudrizwan.claude-dev\settings<tool_call>_mcp_settings.json`
|
|
367
367
|
- Mac: `~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`
|
|
368
368
|
|
|
369
369
|
```json
|
|
@@ -377,7 +377,7 @@ Copy and paste this configuration:
|
|
|
377
377
|
}
|
|
378
378
|
```
|
|
379
379
|
|
|
380
|
-
## 🛠️ Available Tools (
|
|
380
|
+
## 🛠️ Available Tools (108)
|
|
381
381
|
|
|
382
382
|
### 🌐 Browser Management (2 tools)
|
|
383
383
|
|
|
@@ -440,10 +440,10 @@ Copy and paste this configuration:
|
|
|
440
440
|
| `ajax_extractor` | Extract AJAX/dynamic content |
|
|
441
441
|
| `fetch_xhr` | Capture XHR/Fetch requests |
|
|
442
442
|
| `network_recorder` | Record all network traffic |
|
|
443
|
-
| `api_finder` | Discover API endpoints |
|
|
444
443
|
| `regex_pattern_finder` | Find patterns using regex |
|
|
445
444
|
| `iframe_extractor` | Extract iframe content |
|
|
446
445
|
| `embed_page_extractor` | Extract embedded pages |
|
|
446
|
+
| `user_agent_extractor` | Extract user agent info |
|
|
447
447
|
|
|
448
448
|
### 🎬 Video & Media Tools (19 tools)
|
|
449
449
|
|
|
@@ -563,15 +563,7 @@ Copy and paste this configuration:
|
|
|
563
563
|
| `performance_monitor` | Monitor performance |
|
|
564
564
|
| `monitoring_summary` | Get monitoring summary |
|
|
565
565
|
|
|
566
|
-
###
|
|
567
|
-
|
|
568
|
-
| Tool | Description |
|
|
569
|
-
| -------------------------- | ------------------------ |
|
|
570
|
-
| `rest_api_endpoint_finder` | Find REST API endpoints |
|
|
571
|
-
| `webhook_support` | Webhook integration |
|
|
572
|
-
| `all_website_api_finder` | Find all APIs on website |
|
|
573
|
-
|
|
574
|
-
### 🛡️ Advanced Extraction & Obfuscation (5 tools)
|
|
566
|
+
### 🛡️ Advanced Extraction & Obfuscation (4 tools)
|
|
575
567
|
|
|
576
568
|
| Tool | Description |
|
|
577
569
|
| ---------------------------- | --------------------------- |
|
|
@@ -579,7 +571,6 @@ Copy and paste this configuration:
|
|
|
579
571
|
| `multi_layer_redirect_trace` | Trace multi-layer redirects |
|
|
580
572
|
| `ad_protection_detector` | Detect ad protection |
|
|
581
573
|
| `url_redirect_tracer` | Trace URL redirects |
|
|
582
|
-
| `user_agent_extractor` | Extract user agent info |
|
|
583
574
|
|
|
584
575
|
|
|
585
576
|
## 🔧 Environment Variables
|
|
@@ -617,7 +608,6 @@ MIT License - See LICENSE file for details.
|
|
|
617
608
|
|
|
618
609
|
<div align="center">
|
|
619
610
|
|
|
620
|
-
**🌟
|
|
611
|
+
**🌟 108 Tools | 15+ AI IDEs | MCP Protocol | Universal Support 🌟**
|
|
621
612
|
|
|
622
613
|
**Made with ❤️ for the AI Development Community**
|
|
623
|
-
|
package/dist/index.js
CHANGED
|
@@ -3,9 +3,6 @@
|
|
|
3
3
|
console.error(`🔍 [DEBUG] Process starting - PID: ${process.pid}, Node: ${process.version}, Platform: ${process.platform}`);
|
|
4
4
|
console.error(`🔍 [DEBUG] Working directory: ${process.cwd()}`);
|
|
5
5
|
console.error(`🔍 [DEBUG] Command args: ${process.argv.join(" ")}`);
|
|
6
|
-
// Universal AI IDE Adapter - Auto-detect and support all AI IDEs
|
|
7
|
-
console.error("🔍 [DEBUG] Loading Universal IDE Adapter...");
|
|
8
|
-
import { UniversalIDEAdapter, } from "./universal-ide-adapter.js";
|
|
9
6
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
10
7
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
11
8
|
import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ListPromptsRequestSchema, InitializeRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
@@ -13,7 +10,6 @@ console.error("🔍 [DEBUG] MCP SDK imports completed successfully");
|
|
|
13
10
|
// Import extracted modules
|
|
14
11
|
console.error("🔍 [DEBUG] Loading tool definitions...");
|
|
15
12
|
import { TOOLS, SERVER_INFO, CAPABILITIES, TOOL_NAMES, } from "./tool-definitions.js";
|
|
16
|
-
console.error("🔍 [DEBUG] Universal IDE Adapter loaded successfully");
|
|
17
13
|
console.error("🔍 [DEBUG] Loading system utils...");
|
|
18
14
|
import { withErrorHandling } from "./system-utils.js";
|
|
19
15
|
import { validateMCPResponse } from "./mcp-response-validator.js";
|
|
@@ -21,12 +17,6 @@ console.error("🔍 [DEBUG] Loading browser manager...");
|
|
|
21
17
|
import { closeBrowser, forceKillAllBraveProcesses } from "./browser-manager.js";
|
|
22
18
|
console.error("🔍 [DEBUG] Loading core infrastructure...");
|
|
23
19
|
import { setupProcessCleanup, } from "./core-infrastructure.js";
|
|
24
|
-
// Initialize Universal IDE Adapter
|
|
25
|
-
const universalAdapter = new UniversalIDEAdapter({
|
|
26
|
-
enableAutoDetection: true,
|
|
27
|
-
fallbackToHttp: true,
|
|
28
|
-
logDetectionDetails: true,
|
|
29
|
-
});
|
|
30
20
|
// Import handlers
|
|
31
21
|
console.error("🔍 [DEBUG] Loading handlers...");
|
|
32
22
|
import { handleBrowserInit, handleBrowserClose, } from "./handlers/browser-handlers.js";
|
|
@@ -52,10 +42,8 @@ import { handleDataDeduplication, handleMissingDataHandler, handleDataTypeValida
|
|
|
52
42
|
import { handleOCREngine, handleAudioCaptchaSolver, handlePuzzleCaptchaHandler, } from "./handlers/captcha-handlers.js";
|
|
53
43
|
// Import visual tools handlers
|
|
54
44
|
import { handleFullPageScreenshot, handleElementScreenshot, handlePDFGeneration, handleVideoRecording, handleVisualComparison, } from "./handlers/visual-tools-handlers.js";
|
|
55
|
-
// Import API integration handlers
|
|
56
|
-
import { handleRESTAPIEndpointFinder, handleWebhookSupport, handleAllWebsiteAPIFinder, } from "./handlers/api-integration-handlers.js";
|
|
57
45
|
// Import smart data extractors
|
|
58
|
-
import { handleHtmlElementsExtractor, handleTagsFinder, handleLinksFinder, handleXpathLinks, handleAjaxExtractor, handleFetchXHR, handleNetworkRecorder,
|
|
46
|
+
import { handleHtmlElementsExtractor, handleTagsFinder, handleLinksFinder, handleXpathLinks, handleAjaxExtractor, handleFetchXHR, handleNetworkRecorder, handleRegexPatternFinder, handleIframeExtractor, handleEmbedPageExtractor, handleImageExtractorAdvanced, handleVideoSourceExtractor, handleVideoPlayerExtractor, handleVideoPlayerHosterFinder, handleOriginalVideoHosterFinder, handleUrlRedirectTracer, handleUserAgentExtractor, } from "./handlers/smart-data-extractors.js";
|
|
59
47
|
// Import dynamic session handlers
|
|
60
48
|
import { handleShadowDOMExtractor, handleCookieManager, handleSessionPersistence, handleFormAutoFill, handleAjaxContentWaiter, handleModalPopupHandler, handleLoginSessionManager, } from "./handlers/dynamic-session-handlers.js";
|
|
61
49
|
// Import monitoring & reporting handlers
|
|
@@ -304,16 +292,6 @@ export async function executeToolByName(name, args) {
|
|
|
304
292
|
case TOOL_NAMES.VISUAL_COMPARISON:
|
|
305
293
|
result = await handleVisualComparison(args);
|
|
306
294
|
break;
|
|
307
|
-
// Website API Integration
|
|
308
|
-
case TOOL_NAMES.REST_API_ENDPOINT_FINDER:
|
|
309
|
-
result = await handleRESTAPIEndpointFinder(args);
|
|
310
|
-
break;
|
|
311
|
-
case TOOL_NAMES.WEBHOOK_SUPPORT:
|
|
312
|
-
result = await handleWebhookSupport(args);
|
|
313
|
-
break;
|
|
314
|
-
case TOOL_NAMES.ALL_WEBSITE_API_FINDER:
|
|
315
|
-
result = await handleAllWebsiteAPIFinder(args);
|
|
316
|
-
break;
|
|
317
295
|
// Smart Data Extractors (Advanced)
|
|
318
296
|
case "html_elements_extractor":
|
|
319
297
|
result = await handleHtmlElementsExtractor(args || {});
|
|
@@ -336,9 +314,6 @@ export async function executeToolByName(name, args) {
|
|
|
336
314
|
case "network_recorder":
|
|
337
315
|
result = await handleNetworkRecorder(args || {});
|
|
338
316
|
break;
|
|
339
|
-
case "api_finder":
|
|
340
|
-
result = await handleApiFinder(args || {});
|
|
341
|
-
break;
|
|
342
317
|
case "regex_pattern_finder":
|
|
343
318
|
result = await handleRegexPatternFinder(args);
|
|
344
319
|
break;
|
package/dist/tool-definitions.js
CHANGED
|
@@ -960,47 +960,6 @@ export const TOOLS = [
|
|
|
960
960
|
required: ['image1Path', 'image2Path'],
|
|
961
961
|
},
|
|
962
962
|
},
|
|
963
|
-
// Website API Integration (3 tools)
|
|
964
|
-
{
|
|
965
|
-
name: 'rest_api_endpoint_finder',
|
|
966
|
-
description: 'Discover REST API endpoints',
|
|
967
|
-
inputSchema: {
|
|
968
|
-
type: 'object',
|
|
969
|
-
properties: {
|
|
970
|
-
url: { type: 'string' },
|
|
971
|
-
analyzeNetworkRequests: { type: 'boolean', default: true },
|
|
972
|
-
scanDuration: { type: 'number', default: 10000 },
|
|
973
|
-
},
|
|
974
|
-
},
|
|
975
|
-
},
|
|
976
|
-
{
|
|
977
|
-
name: 'webhook_support',
|
|
978
|
-
description: 'Set up and test webhooks',
|
|
979
|
-
inputSchema: {
|
|
980
|
-
type: 'object',
|
|
981
|
-
properties: {
|
|
982
|
-
webhookUrl: { type: 'string' },
|
|
983
|
-
method: { type: 'string', default: 'POST' },
|
|
984
|
-
payload: { type: 'object' },
|
|
985
|
-
headers: { type: 'object' },
|
|
986
|
-
testMode: { type: 'boolean', default: true },
|
|
987
|
-
},
|
|
988
|
-
required: ['webhookUrl'],
|
|
989
|
-
},
|
|
990
|
-
},
|
|
991
|
-
{
|
|
992
|
-
name: 'all_website_api_finder',
|
|
993
|
-
description: 'Comprehensive API discovery',
|
|
994
|
-
inputSchema: {
|
|
995
|
-
type: 'object',
|
|
996
|
-
properties: {
|
|
997
|
-
url: { type: 'string' },
|
|
998
|
-
deepScan: { type: 'boolean', default: true },
|
|
999
|
-
includeExternal: { type: 'boolean', default: false },
|
|
1000
|
-
},
|
|
1001
|
-
required: ['url'],
|
|
1002
|
-
},
|
|
1003
|
-
},
|
|
1004
963
|
// Smart Data Extractors (Advanced)
|
|
1005
964
|
{
|
|
1006
965
|
name: 'html_elements_extractor',
|
|
@@ -1573,10 +1532,6 @@ export const TOOL_NAMES = {
|
|
|
1573
1532
|
PDF_GENERATION: 'pdf_generation',
|
|
1574
1533
|
VIDEO_RECORDING: 'video_recording',
|
|
1575
1534
|
VISUAL_COMPARISON: 'visual_comparison',
|
|
1576
|
-
// Website API Integration
|
|
1577
|
-
REST_API_ENDPOINT_FINDER: 'rest_api_endpoint_finder',
|
|
1578
|
-
WEBHOOK_SUPPORT: 'webhook_support',
|
|
1579
|
-
ALL_WEBSITE_API_FINDER: 'all_website_api_finder',
|
|
1580
1535
|
};
|
|
1581
1536
|
// Tool categories for organization
|
|
1582
1537
|
export const TOOL_CATEGORIES = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brave-real-browser-mcp-server",
|
|
3
|
-
"version": "2.14.
|
|
3
|
+
"version": "2.14.6",
|
|
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,335 +0,0 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
import { getPageInstance } from '../browser-manager.js';
|
|
3
|
-
import axios from 'axios';
|
|
4
|
-
import { sleep } from '../system-utils.js';
|
|
5
|
-
/**
|
|
6
|
-
* REST API Endpoint Finder - Discover REST API endpoints
|
|
7
|
-
*/
|
|
8
|
-
export async function handleRESTAPIEndpointFinder(args) {
|
|
9
|
-
const { url, analyzeNetworkRequests = true, scanDuration = 10000 } = args;
|
|
10
|
-
try {
|
|
11
|
-
const page = getPageInstance();
|
|
12
|
-
if (!page) {
|
|
13
|
-
throw new Error('Browser not initialized. Call browser_init first.');
|
|
14
|
-
}
|
|
15
|
-
const apiEndpoints = [];
|
|
16
|
-
const seenUrls = new Set();
|
|
17
|
-
// Listen to network requests
|
|
18
|
-
if (analyzeNetworkRequests) {
|
|
19
|
-
const requestHandler = (request) => {
|
|
20
|
-
const requestUrl = request.url();
|
|
21
|
-
const method = request.method();
|
|
22
|
-
const resourceType = request.resourceType();
|
|
23
|
-
// Filter for API-like requests
|
|
24
|
-
if ((resourceType === 'xhr' || resourceType === 'fetch') &&
|
|
25
|
-
!seenUrls.has(requestUrl)) {
|
|
26
|
-
seenUrls.add(requestUrl);
|
|
27
|
-
const headers = request.headers();
|
|
28
|
-
const postData = request.postData();
|
|
29
|
-
apiEndpoints.push({
|
|
30
|
-
url: requestUrl,
|
|
31
|
-
method,
|
|
32
|
-
resourceType,
|
|
33
|
-
headers: Object.keys(headers).reduce((acc, key) => {
|
|
34
|
-
if (!key.toLowerCase().includes('cookie') && !key.toLowerCase().includes('authorization')) {
|
|
35
|
-
acc[key] = headers[key];
|
|
36
|
-
}
|
|
37
|
-
return acc;
|
|
38
|
-
}, {}),
|
|
39
|
-
hasBody: !!postData,
|
|
40
|
-
timestamp: new Date().toISOString()
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
page.on('request', requestHandler);
|
|
45
|
-
// Navigate and wait
|
|
46
|
-
if (url && page.url() !== url) {
|
|
47
|
-
await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 });
|
|
48
|
-
}
|
|
49
|
-
// Wait for additional requests
|
|
50
|
-
await sleep(scanDuration);
|
|
51
|
-
page.off('request', requestHandler);
|
|
52
|
-
}
|
|
53
|
-
// Also scan page content for API endpoints
|
|
54
|
-
const discoveredAPIs = await page.evaluate(() => {
|
|
55
|
-
const apis = [];
|
|
56
|
-
const scripts = Array.from(document.querySelectorAll('script'));
|
|
57
|
-
// Common API URL patterns
|
|
58
|
-
const apiPatterns = [
|
|
59
|
-
/https?:\/\/[^"'\s]+\/api\/[^"'\s]*/gi,
|
|
60
|
-
/https?:\/\/api\.[^"'\s]+/gi,
|
|
61
|
-
/\/api\/v?\d*\/[^"'\s]*/gi,
|
|
62
|
-
/graphql/gi,
|
|
63
|
-
/rest\/v?\d*/gi
|
|
64
|
-
];
|
|
65
|
-
scripts.forEach(script => {
|
|
66
|
-
const content = script.textContent || '';
|
|
67
|
-
apiPatterns.forEach(pattern => {
|
|
68
|
-
const matches = content.match(pattern);
|
|
69
|
-
if (matches) {
|
|
70
|
-
matches.forEach(match => apis.push({
|
|
71
|
-
url: match,
|
|
72
|
-
source: 'script_content',
|
|
73
|
-
type: 'discovered'
|
|
74
|
-
}));
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
// Check for data attributes
|
|
79
|
-
const elements = Array.from(document.querySelectorAll('[data-api], [data-endpoint], [data-url]'));
|
|
80
|
-
elements.forEach(el => {
|
|
81
|
-
const apiUrl = el.getAttribute('data-api') || el.getAttribute('data-endpoint') || el.getAttribute('data-url');
|
|
82
|
-
if (apiUrl) {
|
|
83
|
-
apis.push({
|
|
84
|
-
url: apiUrl,
|
|
85
|
-
source: 'data_attribute',
|
|
86
|
-
element: el.tagName.toLowerCase()
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
return apis;
|
|
91
|
-
});
|
|
92
|
-
let summary = `REST API Discovery Results:\n\nSummary:\n- Total APIs Found: ${apiEndpoints.length + discoveredAPIs.length}\n- Network APIs: ${apiEndpoints.length}\n- Discovered in Content: ${discoveredAPIs.length}`;
|
|
93
|
-
if (apiEndpoints.length > 0) {
|
|
94
|
-
summary += `\n\nNetwork API Endpoints (Top 10):\n${apiEndpoints.slice(0, 10).map((ep, i) => `${i + 1}. ${ep.method} ${ep.url}\n Type: ${ep.resourceType}${ep.hasBody ? ' (with body)' : ''}`).join('\n')}`;
|
|
95
|
-
}
|
|
96
|
-
if (discoveredAPIs.length > 0) {
|
|
97
|
-
summary += `\n\nDiscovered APIs (Top 10):\n${discoveredAPIs.slice(0, 10).map((api, i) => `${i + 1}. ${api.url}\n Source: ${api.source}`).join('\n')}`;
|
|
98
|
-
}
|
|
99
|
-
return {
|
|
100
|
-
content: [
|
|
101
|
-
{
|
|
102
|
-
type: "text",
|
|
103
|
-
text: summary
|
|
104
|
-
}
|
|
105
|
-
]
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
catch (error) {
|
|
109
|
-
return {
|
|
110
|
-
content: [
|
|
111
|
-
{
|
|
112
|
-
type: "text",
|
|
113
|
-
text: `REST API Endpoint Finder Error: ${error.message}`
|
|
114
|
-
}
|
|
115
|
-
],
|
|
116
|
-
isError: true
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Webhook Support - Set up and test webhooks
|
|
122
|
-
*/
|
|
123
|
-
export async function handleWebhookSupport(args) {
|
|
124
|
-
const { webhookUrl, method = 'POST', payload, headers, testMode = true } = args;
|
|
125
|
-
try {
|
|
126
|
-
if (!webhookUrl) {
|
|
127
|
-
throw new Error('Webhook URL is required');
|
|
128
|
-
}
|
|
129
|
-
const defaultHeaders = {
|
|
130
|
-
'Content-Type': 'application/json',
|
|
131
|
-
'User-Agent': 'Brave-MCP-Server/1.0',
|
|
132
|
-
...headers
|
|
133
|
-
};
|
|
134
|
-
let response;
|
|
135
|
-
if (testMode) {
|
|
136
|
-
// Test webhook with ping
|
|
137
|
-
try {
|
|
138
|
-
response = await axios({
|
|
139
|
-
method,
|
|
140
|
-
url: webhookUrl,
|
|
141
|
-
headers: defaultHeaders,
|
|
142
|
-
data: payload || { test: true, timestamp: new Date().toISOString() },
|
|
143
|
-
timeout: 10000
|
|
144
|
-
});
|
|
145
|
-
return {
|
|
146
|
-
content: [
|
|
147
|
-
{
|
|
148
|
-
type: "text",
|
|
149
|
-
text: `Webhook Test Successful:\n- URL: ${webhookUrl}\n- Method: ${method}\n- Status: ${response.status} ${response.statusText}\n- Response Headers: ${JSON.stringify(response.headers, null, 2)}\n- Response Data: ${JSON.stringify(response.data, null, 2)}`
|
|
150
|
-
}
|
|
151
|
-
]
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
catch (webhookError) {
|
|
155
|
-
return {
|
|
156
|
-
content: [
|
|
157
|
-
{
|
|
158
|
-
type: "text",
|
|
159
|
-
text: `Webhook Test Failed:\n- URL: ${webhookUrl}\n- Error: ${webhookError.message}${webhookError.response ? `\n- Status: ${webhookError.response.status} ${webhookError.response.statusText}\n- Response: ${JSON.stringify(webhookError.response.data, null, 2)}` : ''}`
|
|
160
|
-
}
|
|
161
|
-
],
|
|
162
|
-
isError: true
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
else {
|
|
167
|
-
// Production mode - set up webhook listener
|
|
168
|
-
return {
|
|
169
|
-
content: [
|
|
170
|
-
{
|
|
171
|
-
type: "text",
|
|
172
|
-
text: `Webhook Configured:\n- URL: ${webhookUrl}\n- Method: ${method}\n- Test Mode: No\n- Status: Configured\n\nNote: Webhook configured. Send data using separate call or integrate with scraping workflow`
|
|
173
|
-
}
|
|
174
|
-
]
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
catch (error) {
|
|
179
|
-
return {
|
|
180
|
-
content: [
|
|
181
|
-
{
|
|
182
|
-
type: "text",
|
|
183
|
-
text: `Webhook Support Error: ${error.message}`
|
|
184
|
-
}
|
|
185
|
-
],
|
|
186
|
-
isError: true
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
/**
|
|
191
|
-
* All Website API Finder - Comprehensive API discovery
|
|
192
|
-
*/
|
|
193
|
-
export async function handleAllWebsiteAPIFinder(args) {
|
|
194
|
-
const { url, deepScan = true, includeExternal = false } = args;
|
|
195
|
-
try {
|
|
196
|
-
const page = getPageInstance();
|
|
197
|
-
if (!page) {
|
|
198
|
-
throw new Error('Browser not initialized. Call browser_init first.');
|
|
199
|
-
}
|
|
200
|
-
if (url && page.url() !== url) {
|
|
201
|
-
await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 });
|
|
202
|
-
}
|
|
203
|
-
const apiDiscovery = await page.evaluate((deep, external) => {
|
|
204
|
-
const result = {
|
|
205
|
-
apis: [],
|
|
206
|
-
graphql: [],
|
|
207
|
-
rest: [],
|
|
208
|
-
websockets: [],
|
|
209
|
-
metadata: {}
|
|
210
|
-
};
|
|
211
|
-
// 1. Check for API documentation links
|
|
212
|
-
const apiLinks = Array.from(document.querySelectorAll('a[href*="api"], a[href*="docs"], a[href*="developer"]'));
|
|
213
|
-
result.documentationLinks = apiLinks.map(link => ({
|
|
214
|
-
text: link.textContent?.trim(),
|
|
215
|
-
href: link.href
|
|
216
|
-
})).slice(0, 10);
|
|
217
|
-
// 2. Scan for GraphQL
|
|
218
|
-
const graphqlIndicators = document.body.innerHTML.match(/graphql|__schema|query\s*{|mutation\s*{/gi);
|
|
219
|
-
if (graphqlIndicators) {
|
|
220
|
-
result.graphql.push({
|
|
221
|
-
found: true,
|
|
222
|
-
indicators: graphqlIndicators.length,
|
|
223
|
-
possibleEndpoints: [
|
|
224
|
-
'/graphql',
|
|
225
|
-
'/api/graphql',
|
|
226
|
-
'/v1/graphql'
|
|
227
|
-
]
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
// 3. Scan scripts for API configurations
|
|
231
|
-
const scripts = Array.from(document.querySelectorAll('script'));
|
|
232
|
-
scripts.forEach(script => {
|
|
233
|
-
const content = script.textContent || '';
|
|
234
|
-
// Look for API base URLs
|
|
235
|
-
const baseUrlPatterns = [
|
|
236
|
-
/apiUrl\s*[:=]\s*["']([^"']+)["']/gi,
|
|
237
|
-
/baseURL\s*[:=]\s*["']([^"']+)["']/gi,
|
|
238
|
-
/API_BASE\s*[:=]\s*["']([^"']+)["']/gi,
|
|
239
|
-
/endpoint\s*[:=]\s*["']([^"']+)["']/gi
|
|
240
|
-
];
|
|
241
|
-
baseUrlPatterns.forEach(pattern => {
|
|
242
|
-
const matches = Array.from(content.matchAll(pattern));
|
|
243
|
-
matches.forEach(match => {
|
|
244
|
-
if (match[1] && (external || match[1].startsWith('/'))) {
|
|
245
|
-
result.apis.push({
|
|
246
|
-
type: 'config',
|
|
247
|
-
url: match[1],
|
|
248
|
-
source: 'script'
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
});
|
|
252
|
-
});
|
|
253
|
-
// Look for WebSocket connections
|
|
254
|
-
if (content.includes('WebSocket') || content.includes('ws://') || content.includes('wss://')) {
|
|
255
|
-
const wsMatches = content.match(/wss?:\/\/[^"'\s]+/gi);
|
|
256
|
-
if (wsMatches) {
|
|
257
|
-
wsMatches.forEach(ws => {
|
|
258
|
-
result.websockets.push({
|
|
259
|
-
url: ws,
|
|
260
|
-
protocol: ws.startsWith('wss') ? 'secure' : 'unsecure'
|
|
261
|
-
});
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
});
|
|
266
|
-
// 4. Check meta tags for API info
|
|
267
|
-
const metaTags = Array.from(document.querySelectorAll('meta[name*="api"], meta[property*="api"]'));
|
|
268
|
-
result.metadata.apiMeta = metaTags.map(meta => ({
|
|
269
|
-
name: meta.getAttribute('name') || meta.getAttribute('property'),
|
|
270
|
-
content: meta.getAttribute('content')
|
|
271
|
-
}));
|
|
272
|
-
// 5. Look for REST patterns
|
|
273
|
-
const restPatterns = [
|
|
274
|
-
'/api/v1', '/api/v2', '/api/v3',
|
|
275
|
-
'/rest/v1', '/rest/v2',
|
|
276
|
-
'/api/users', '/api/products', '/api/data'
|
|
277
|
-
];
|
|
278
|
-
restPatterns.forEach(pattern => {
|
|
279
|
-
const found = document.body.innerHTML.includes(pattern);
|
|
280
|
-
if (found) {
|
|
281
|
-
result.rest.push({
|
|
282
|
-
pattern,
|
|
283
|
-
found: true
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
// 6. Check for Swagger/OpenAPI
|
|
288
|
-
const swaggerLinks = Array.from(document.querySelectorAll('a[href*="swagger"], a[href*="openapi"], link[href*="swagger"]'));
|
|
289
|
-
if (swaggerLinks.length > 0) {
|
|
290
|
-
result.swagger = swaggerLinks.map(link => ({
|
|
291
|
-
href: link.href || link.href
|
|
292
|
-
}));
|
|
293
|
-
}
|
|
294
|
-
return result;
|
|
295
|
-
}, deepScan, includeExternal);
|
|
296
|
-
// Deduplicate APIs
|
|
297
|
-
const uniqueAPIs = [...new Set(apiDiscovery.apis.map((api) => api.url))];
|
|
298
|
-
const restFound = apiDiscovery.rest.filter((r) => r.found).length;
|
|
299
|
-
let summary = `Comprehensive API Discovery:\n\nSummary:\n- Total Unique APIs: ${uniqueAPIs.length}\n- GraphQL Detected: ${apiDiscovery.graphql.length > 0 ? 'Yes' : 'No'}\n- REST Endpoints: ${restFound}\n- WebSockets: ${apiDiscovery.websockets.length}\n- Documentation Links: ${apiDiscovery.documentationLinks?.length || 0}`;
|
|
300
|
-
if (apiDiscovery.graphql.length > 0) {
|
|
301
|
-
summary += `\n\nGraphQL:\n- Indicators Found: ${apiDiscovery.graphql[0].indicators}\n- Possible Endpoints: ${apiDiscovery.graphql[0].possibleEndpoints.join(', ')}`;
|
|
302
|
-
}
|
|
303
|
-
if (uniqueAPIs.length > 0) {
|
|
304
|
-
summary += `\n\nUnique APIs (Top 10):\n${uniqueAPIs.slice(0, 10).map((api, i) => `${i + 1}. ${api}`).join('\n')}`;
|
|
305
|
-
}
|
|
306
|
-
if (apiDiscovery.websockets.length > 0) {
|
|
307
|
-
summary += `\n\nWebSockets:\n${apiDiscovery.websockets.map((ws, i) => `${i + 1}. ${ws.url} (${ws.protocol})`).join('\n')}`;
|
|
308
|
-
}
|
|
309
|
-
if (apiDiscovery.documentationLinks?.length > 0) {
|
|
310
|
-
summary += `\n\nDocumentation Links:\n${apiDiscovery.documentationLinks.slice(0, 5).map((link, i) => `${i + 1}. ${link.text}: ${link.href}`).join('\n')}`;
|
|
311
|
-
}
|
|
312
|
-
if (apiDiscovery.swagger?.length > 0) {
|
|
313
|
-
summary += `\n\nSwagger/OpenAPI:\n${apiDiscovery.swagger.map((s, i) => `${i + 1}. ${s.href}`).join('\n')}`;
|
|
314
|
-
}
|
|
315
|
-
return {
|
|
316
|
-
content: [
|
|
317
|
-
{
|
|
318
|
-
type: "text",
|
|
319
|
-
text: summary
|
|
320
|
-
}
|
|
321
|
-
]
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
catch (error) {
|
|
325
|
-
return {
|
|
326
|
-
content: [
|
|
327
|
-
{
|
|
328
|
-
type: "text",
|
|
329
|
-
text: `All Website API Finder Error: ${error.message}`
|
|
330
|
-
}
|
|
331
|
-
],
|
|
332
|
-
isError: true
|
|
333
|
-
};
|
|
334
|
-
}
|
|
335
|
-
}
|