brave-real-browser-mcp-server 2.14.4 → 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/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, handleApiFinder, handleRegexPatternFinder, handleIframeExtractor, handleEmbedPageExtractor, handleImageExtractorAdvanced, handleVideoSourceExtractor, handleVideoPlayerExtractor, handleVideoPlayerHosterFinder, handleOriginalVideoHosterFinder, handleUrlRedirectTracer, handleUserAgentExtractor, } from "./handlers/smart-data-extractors.js";
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;
@@ -498,29 +473,19 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
498
473
  return await executeToolByName(name, args);
499
474
  });
500
475
  // Main function - now using multi-protocol launcher
501
- import { main as launcherMain } from "./launcher.js";
476
+ // Main function
502
477
  async function main() {
503
- // Check if user wants multi-protocol mode
504
- const hasProtocolArg = process.argv.some((arg) => arg === "--mode" || arg === "-m" || arg === "--http" || arg === "--lsp");
505
- if (hasProtocolArg) {
506
- // Use multi-protocol launcher
507
- await launcherMain();
508
- }
509
- else {
510
- // Default: MCP mode (backward compatibility)
511
- console.error("🔍 [DEBUG] Starting in MCP mode (default)...");
512
- console.error("💡 Tip: Use --mode http or --mode lsp for other protocols");
513
- setupProcessCleanup(async () => {
514
- await closeBrowser();
515
- await forceKillAllBraveProcesses();
516
- });
517
- const transport = new StdioServerTransport();
518
- await withErrorHandling(async () => {
519
- await server.connect(transport);
520
- console.error("🚀 Brave Real Browser MCP Server started successfully");
521
- console.error("📋 Available tools:", TOOLS.map((t) => t.name).join(", "));
522
- }, "Failed to start MCP server");
523
- }
478
+ console.error("🔍 [DEBUG] Starting in STDIO mode...");
479
+ setupProcessCleanup(async () => {
480
+ await closeBrowser();
481
+ await forceKillAllBraveProcesses();
482
+ });
483
+ const transport = new StdioServerTransport();
484
+ await withErrorHandling(async () => {
485
+ await server.connect(transport);
486
+ console.error("🚀 Brave Real Browser MCP Server started successfully");
487
+ console.error("📋 Available tools:", TOOLS.map((t) => t.name).join(", "));
488
+ }, "Failed to start MCP server");
524
489
  }
525
490
  // Enhanced error handling with debug info
526
491
  console.error("🔍 [DEBUG] Setting up error handlers...");
@@ -551,32 +516,9 @@ process.on("SIGINT", () => {
551
516
  });
552
517
  console.error("🔍 [DEBUG] All error handlers registered");
553
518
  // Start the server
554
- console.error("🔍 [DEBUG] Checking if module is main...");
555
- console.error(`🔍 [DEBUG] import.meta.url: ${import.meta.url}`);
556
- console.error(`🔍 [DEBUG] process.argv[1]: ${process.argv[1]}`);
557
- console.error(`🔍 [DEBUG] process.argv[0]: ${process.argv[0]}`);
558
- // Enhanced main module detection for npx compatibility
559
- const isMain = import.meta.url === `file://${process.argv[1]}` ||
560
- process.argv[1].includes("brave-real-browser-mcp-server") ||
561
- process.argv[1].endsWith(".bin/brave-real-browser-mcp-server") ||
562
- process.argv.some((arg) => arg.includes("brave-real-browser-mcp-server"));
563
- console.error(`🔍 [DEBUG] Enhanced main detection result: ${isMain}`);
564
- if (isMain) {
565
- console.error("🔍 [DEBUG] Module is main - starting server...");
566
- main().catch((error) => {
567
- console.error(`🔍 [DEBUG] Main function failed at ${new Date().toISOString()}`);
568
- console.error("❌ Failed to start server:", error);
569
- console.error(`🔍 [DEBUG] Error stack:`, error.stack);
570
- process.exit(1);
571
- });
572
- }
573
- else {
574
- console.error("🔍 [DEBUG] Module is not main - not starting server");
575
- console.error("🔍 [DEBUG] FORCE STARTING - This is likely an npx execution");
576
- main().catch((error) => {
577
- console.error(`🔍 [DEBUG] Forced main function failed at ${new Date().toISOString()}`);
578
- console.error("❌ Failed to start server:", error);
579
- console.error(`🔍 [DEBUG] Error stack:`, error.stack);
580
- process.exit(1);
581
- });
582
- }
519
+ main().catch((error) => {
520
+ console.error(`🔍 [DEBUG] Main function failed at ${new Date().toISOString()}`);
521
+ console.error("❌ Failed to start server:", error);
522
+ console.error(`🔍 [DEBUG] Error stack:`, error.stack);
523
+ process.exit(1);
524
+ });
@@ -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.4",
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",
@@ -19,12 +19,7 @@
19
19
  "build": "tsc",
20
20
  "rebuild": "npm run clean && npm run build",
21
21
  "start": "node dist/index.js",
22
- "start:http": "node dist/index.js --mode http",
23
- "start:lsp": "node dist/index.js --mode lsp",
24
- "start:all": "node dist/index.js --mode all",
25
22
  "dev": "tsx src/index.ts",
26
- "dev:http": "tsx src/index.ts --mode http",
27
- "dev:lsp": "tsx src/index.ts --mode lsp",
28
23
  "test": "vitest",
29
24
  "test:watch": "vitest --watch",
30
25
  "test:ui": "vitest --ui",
@@ -44,13 +39,12 @@
44
39
  "ajv": "^8.12.0",
45
40
  "axios": "^1.6.5",
46
41
  "brave-real-browser": "^1.5.105",
47
- "brave-real-launcher": "^1.2.19",
48
- "brave-real-puppeteer-core": "^24.26.1",
42
+ "brave-real-launcher": "^1.2.28",
43
+ "brave-real-puppeteer-core": "^24.33.0-patch.1",
49
44
  "cheerio": "^1.0.0-rc.12",
50
45
  "chrono-node": "^2.7.0",
51
46
  "compromise": "^14.13.0",
52
47
  "dotenv": "^17.2.3",
53
- "express": "^4.21.2",
54
48
  "franc": "^6.2.0",
55
49
  "libphonenumber-js": "^1.10.51",
56
50
  "natural": "^6.12.0",
@@ -60,20 +54,15 @@
60
54
  "sentiment": "^5.0.2",
61
55
  "tesseract.js": "^5.0.5",
62
56
  "turndown": "^7.2.2",
63
- "vscode-languageserver": "^9.0.1",
64
- "vscode-languageserver-textdocument": "^1.0.12",
65
- "ws": "^8.18.3",
66
57
  "xml2js": "^0.6.2"
67
58
  },
68
59
  "devDependencies": {
69
60
  "@types/cheerio": "^0.22.35",
70
- "@types/express": "^4.17.23",
71
61
  "@types/node": "latest",
72
- "@types/ws": "^8.18.1",
73
62
  "@types/xml2js": "^0.4.14",
74
63
  "@vitest/coverage-v8": "^3.2.4",
75
64
  "@vitest/ui": "^3.2.4",
76
- "rimraf": "^6.0.1",
65
+ "rimraf": "^6.1.2",
77
66
  "tsx": "latest",
78
67
  "typescript": "^5.5.3",
79
68
  "vitest": "^3.2.4"
@@ -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
- }