brave-real-browser-mcp-server 2.8.5 → 2.8.7
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.
|
@@ -88,27 +88,31 @@ export async function handleRESTAPIEndpointFinder(args) {
|
|
|
88
88
|
});
|
|
89
89
|
return apis;
|
|
90
90
|
});
|
|
91
|
+
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}`;
|
|
92
|
+
if (apiEndpoints.length > 0) {
|
|
93
|
+
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')}`;
|
|
94
|
+
}
|
|
95
|
+
if (discoveredAPIs.length > 0) {
|
|
96
|
+
summary += `\n\nDiscovered APIs (Top 10):\n${discoveredAPIs.slice(0, 10).map((api, i) => `${i + 1}. ${api.url}\n Source: ${api.source}`).join('\n')}`;
|
|
97
|
+
}
|
|
91
98
|
return {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
count: discoveredAPIs.length,
|
|
99
|
-
endpoints: discoveredAPIs.slice(0, 20) // Limit to 20
|
|
100
|
-
},
|
|
101
|
-
summary: {
|
|
102
|
-
totalFound: apiEndpoints.length + discoveredAPIs.length,
|
|
103
|
-
uniqueNetworkAPIs: apiEndpoints.length,
|
|
104
|
-
discoveredAPIs: discoveredAPIs.length
|
|
105
|
-
}
|
|
99
|
+
content: [
|
|
100
|
+
{
|
|
101
|
+
type: "text",
|
|
102
|
+
text: summary
|
|
103
|
+
}
|
|
104
|
+
]
|
|
106
105
|
};
|
|
107
106
|
}
|
|
108
107
|
catch (error) {
|
|
109
108
|
return {
|
|
110
|
-
|
|
111
|
-
|
|
109
|
+
content: [
|
|
110
|
+
{
|
|
111
|
+
type: "text",
|
|
112
|
+
text: `REST API Endpoint Finder Error: ${error.message}`
|
|
113
|
+
}
|
|
114
|
+
],
|
|
115
|
+
isError: true
|
|
112
116
|
};
|
|
113
117
|
}
|
|
114
118
|
}
|
|
@@ -138,48 +142,47 @@ export async function handleWebhookSupport(args) {
|
|
|
138
142
|
timeout: 10000
|
|
139
143
|
});
|
|
140
144
|
return {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
statusText: response.statusText,
|
|
148
|
-
headers: response.headers,
|
|
149
|
-
data: response.data
|
|
150
|
-
}
|
|
145
|
+
content: [
|
|
146
|
+
{
|
|
147
|
+
type: "text",
|
|
148
|
+
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)}`
|
|
149
|
+
}
|
|
150
|
+
]
|
|
151
151
|
};
|
|
152
152
|
}
|
|
153
153
|
catch (webhookError) {
|
|
154
154
|
return {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
data: webhookError.response?.data
|
|
163
|
-
}
|
|
155
|
+
content: [
|
|
156
|
+
{
|
|
157
|
+
type: "text",
|
|
158
|
+
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)}` : ''}`
|
|
159
|
+
}
|
|
160
|
+
],
|
|
161
|
+
isError: true
|
|
164
162
|
};
|
|
165
163
|
}
|
|
166
164
|
}
|
|
167
165
|
else {
|
|
168
166
|
// Production mode - set up webhook listener
|
|
169
167
|
return {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
168
|
+
content: [
|
|
169
|
+
{
|
|
170
|
+
type: "text",
|
|
171
|
+
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`
|
|
172
|
+
}
|
|
173
|
+
]
|
|
176
174
|
};
|
|
177
175
|
}
|
|
178
176
|
}
|
|
179
177
|
catch (error) {
|
|
180
178
|
return {
|
|
181
|
-
|
|
182
|
-
|
|
179
|
+
content: [
|
|
180
|
+
{
|
|
181
|
+
type: "text",
|
|
182
|
+
text: `Webhook Support Error: ${error.message}`
|
|
183
|
+
}
|
|
184
|
+
],
|
|
185
|
+
isError: true
|
|
183
186
|
};
|
|
184
187
|
}
|
|
185
188
|
}
|
|
@@ -291,24 +294,41 @@ export async function handleAllWebsiteAPIFinder(args) {
|
|
|
291
294
|
}, deepScan, includeExternal);
|
|
292
295
|
// Deduplicate APIs
|
|
293
296
|
const uniqueAPIs = [...new Set(apiDiscovery.apis.map((api) => api.url))];
|
|
297
|
+
const restFound = apiDiscovery.rest.filter((r) => r.found).length;
|
|
298
|
+
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}`;
|
|
299
|
+
if (apiDiscovery.graphql.length > 0) {
|
|
300
|
+
summary += `\n\nGraphQL:\n- Indicators Found: ${apiDiscovery.graphql[0].indicators}\n- Possible Endpoints: ${apiDiscovery.graphql[0].possibleEndpoints.join(', ')}`;
|
|
301
|
+
}
|
|
302
|
+
if (uniqueAPIs.length > 0) {
|
|
303
|
+
summary += `\n\nUnique APIs (Top 10):\n${uniqueAPIs.slice(0, 10).map((api, i) => `${i + 1}. ${api}`).join('\n')}`;
|
|
304
|
+
}
|
|
305
|
+
if (apiDiscovery.websockets.length > 0) {
|
|
306
|
+
summary += `\n\nWebSockets:\n${apiDiscovery.websockets.map((ws, i) => `${i + 1}. ${ws.url} (${ws.protocol})`).join('\n')}`;
|
|
307
|
+
}
|
|
308
|
+
if (apiDiscovery.documentationLinks?.length > 0) {
|
|
309
|
+
summary += `\n\nDocumentation Links:\n${apiDiscovery.documentationLinks.slice(0, 5).map((link, i) => `${i + 1}. ${link.text}: ${link.href}`).join('\n')}`;
|
|
310
|
+
}
|
|
311
|
+
if (apiDiscovery.swagger?.length > 0) {
|
|
312
|
+
summary += `\n\nSwagger/OpenAPI:\n${apiDiscovery.swagger.map((s, i) => `${i + 1}. ${s.href}`).join('\n')}`;
|
|
313
|
+
}
|
|
294
314
|
return {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
documentationLinks: apiDiscovery.documentationLinks?.length || 0
|
|
302
|
-
},
|
|
303
|
-
details: apiDiscovery,
|
|
304
|
-
uniqueAPIs: uniqueAPIs.slice(0, 20),
|
|
305
|
-
recommendations: []
|
|
315
|
+
content: [
|
|
316
|
+
{
|
|
317
|
+
type: "text",
|
|
318
|
+
text: summary
|
|
319
|
+
}
|
|
320
|
+
]
|
|
306
321
|
};
|
|
307
322
|
}
|
|
308
323
|
catch (error) {
|
|
309
324
|
return {
|
|
310
|
-
|
|
311
|
-
|
|
325
|
+
content: [
|
|
326
|
+
{
|
|
327
|
+
type: "text",
|
|
328
|
+
text: `All Website API Finder Error: ${error.message}`
|
|
329
|
+
}
|
|
330
|
+
],
|
|
331
|
+
isError: true
|
|
312
332
|
};
|
|
313
333
|
}
|
|
314
334
|
}
|
|
@@ -47,18 +47,23 @@ export async function handleOCREngine(args) {
|
|
|
47
47
|
bbox: word.bbox
|
|
48
48
|
}));
|
|
49
49
|
return {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
50
|
+
content: [
|
|
51
|
+
{
|
|
52
|
+
type: "text",
|
|
53
|
+
text: `OCR Results:\n- Extracted Text: ${text}\n- Confidence: ${confidence.toFixed(2)}%\n- Words Found: ${words.length}\n- Lines: ${result.data.lines.length}\n- Language: ${language}\n\nWords Detail:\n${words.map((w) => ` "${w.text}" (confidence: ${w.confidence.toFixed(2)}%)`).join('\n')}`
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
58
|
catch (error) {
|
|
59
59
|
return {
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
content: [
|
|
61
|
+
{
|
|
62
|
+
type: "text",
|
|
63
|
+
text: `OCR Engine Error: ${error.message}`
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
isError: true
|
|
62
67
|
};
|
|
63
68
|
}
|
|
64
69
|
}
|
|
@@ -106,17 +111,23 @@ export async function handleAudioCaptchaSolver(args) {
|
|
|
106
111
|
}
|
|
107
112
|
}
|
|
108
113
|
return {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
+
content: [
|
|
115
|
+
{
|
|
116
|
+
type: "text",
|
|
117
|
+
text: `Audio Captcha Analysis:\n- Audio URL: ${audioSource}\n- Downloaded: ${downloaded ? 'Yes' : 'No'}${downloaded ? `\n- Download Path: ${downloadPath}` : ''}\n\nNote: Audio captcha solving requires external speech-to-text API (Google Speech, AWS Transcribe, etc.)`
|
|
118
|
+
}
|
|
119
|
+
]
|
|
114
120
|
};
|
|
115
121
|
}
|
|
116
122
|
catch (error) {
|
|
117
123
|
return {
|
|
118
|
-
|
|
119
|
-
|
|
124
|
+
content: [
|
|
125
|
+
{
|
|
126
|
+
type: "text",
|
|
127
|
+
text: `Audio Captcha Solver Error: ${error.message}`
|
|
128
|
+
}
|
|
129
|
+
],
|
|
130
|
+
isError: true
|
|
120
131
|
};
|
|
121
132
|
}
|
|
122
133
|
}
|
|
@@ -208,16 +219,38 @@ export async function handlePuzzleCaptchaHandler(args) {
|
|
|
208
219
|
result.solveError = solveError.message;
|
|
209
220
|
}
|
|
210
221
|
}
|
|
222
|
+
let summary = `Puzzle Captcha Analysis:\n- Puzzle Found: ${result.puzzleFound ? 'Yes' : 'No'}\n- Slider Found: ${result.sliderFound ? 'Yes' : 'No'}`;
|
|
223
|
+
if (result.puzzle) {
|
|
224
|
+
summary += `\n\nPuzzle Details:\n- Dimensions: ${result.puzzle.width}x${result.puzzle.height}\n- Position: (${result.puzzle.left}, ${result.puzzle.top})\n- Visible: ${result.puzzle.visible ? 'Yes' : 'No'}`;
|
|
225
|
+
}
|
|
226
|
+
if (result.puzzlePiece) {
|
|
227
|
+
summary += `\n\nPuzzle Piece:\n- Dimensions: ${result.puzzlePiece.width}x${result.puzzlePiece.height}\n- Position: (${result.puzzlePiece.left}, ${result.puzzlePiece.top})`;
|
|
228
|
+
}
|
|
229
|
+
if (result.slider) {
|
|
230
|
+
summary += `\n\nSlider Details:\n- Dimensions: ${result.slider.width}x${result.slider.height}\n- Position: (${result.slider.left}, ${result.slider.top})\n- Visible: ${result.slider.visible ? 'Yes' : 'No'}\n- Tag: ${result.slider.tagName}`;
|
|
231
|
+
}
|
|
232
|
+
if (result.attemptedSolve) {
|
|
233
|
+
summary += `\n\nSolve Attempt:\n- Method: ${result.method}\n- Status: ${result.solveError ? 'Failed' : 'Completed'}${result.solveError ? `\n- Error: ${result.solveError}` : ''}`;
|
|
234
|
+
}
|
|
235
|
+
summary += `\n\nNote: Advanced puzzle solving requires computer vision libraries (OpenCV, TensorFlow)`;
|
|
211
236
|
return {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
237
|
+
content: [
|
|
238
|
+
{
|
|
239
|
+
type: "text",
|
|
240
|
+
text: summary
|
|
241
|
+
}
|
|
242
|
+
]
|
|
215
243
|
};
|
|
216
244
|
}
|
|
217
245
|
catch (error) {
|
|
218
246
|
return {
|
|
219
|
-
|
|
220
|
-
|
|
247
|
+
content: [
|
|
248
|
+
{
|
|
249
|
+
type: "text",
|
|
250
|
+
text: `Puzzle Captcha Handler Error: ${error.message}`
|
|
251
|
+
}
|
|
252
|
+
],
|
|
253
|
+
isError: true
|
|
221
254
|
};
|
|
222
255
|
}
|
|
223
256
|
}
|
|
@@ -240,19 +240,23 @@ export async function handleVideoRecording(args) {
|
|
|
240
240
|
}
|
|
241
241
|
}
|
|
242
242
|
return {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
note: 'For actual video file, use ffmpeg or puppeteer-screen-recorder library to combine frames'
|
|
243
|
+
content: [
|
|
244
|
+
{
|
|
245
|
+
type: "text",
|
|
246
|
+
text: `Video Recording Complete:\n- Duration: ${duration} seconds\n- FPS: ${fps}\n- Frames Captured: ${frames.length}\n- Output Path: ${outputPath}\n- Sample Frames:\n${frames.slice(0, 5).map((f, i) => ` ${i + 1}. ${f}`).join('\n')}\n\nNote: For actual video file, use ffmpeg or puppeteer-screen-recorder library to combine frames`
|
|
247
|
+
}
|
|
248
|
+
]
|
|
250
249
|
};
|
|
251
250
|
}
|
|
252
251
|
catch (error) {
|
|
253
252
|
return {
|
|
254
|
-
|
|
255
|
-
|
|
253
|
+
content: [
|
|
254
|
+
{
|
|
255
|
+
type: "text",
|
|
256
|
+
text: `Video Recording Error: ${error.message}`
|
|
257
|
+
}
|
|
258
|
+
],
|
|
259
|
+
isError: true
|
|
256
260
|
};
|
|
257
261
|
}
|
|
258
262
|
}
|
|
@@ -273,10 +277,13 @@ export async function handleVisualComparison(args) {
|
|
|
273
277
|
// Check if dimensions match
|
|
274
278
|
if (img1.width !== img2.width || img1.height !== img2.height) {
|
|
275
279
|
return {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
+
content: [
|
|
281
|
+
{
|
|
282
|
+
type: "text",
|
|
283
|
+
text: `Image dimensions do not match:\n- Image 1: ${img1.width}x${img1.height}\n- Image 2: ${img2.width}x${img2.height}`
|
|
284
|
+
}
|
|
285
|
+
],
|
|
286
|
+
isError: true
|
|
280
287
|
};
|
|
281
288
|
}
|
|
282
289
|
// Create diff image
|
|
@@ -291,27 +298,25 @@ export async function handleVisualComparison(args) {
|
|
|
291
298
|
}
|
|
292
299
|
const totalPixels = img1.width * img1.height;
|
|
293
300
|
const diffPercentage = (numDiffPixels / totalPixels) * 100;
|
|
301
|
+
const similarity = ((1 - (numDiffPixels / totalPixels)) * 100).toFixed(2);
|
|
294
302
|
return {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
},
|
|
302
|
-
dimensions: {
|
|
303
|
-
width: img1.width,
|
|
304
|
-
height: img1.height
|
|
305
|
-
},
|
|
306
|
-
threshold,
|
|
307
|
-
diffImagePath: diffOutputPath,
|
|
308
|
-
similarity: ((1 - (numDiffPixels / totalPixels)) * 100).toFixed(2) + '%'
|
|
303
|
+
content: [
|
|
304
|
+
{
|
|
305
|
+
type: "text",
|
|
306
|
+
text: `Visual Comparison Results:\n- Identical: ${numDiffPixels === 0 ? 'Yes' : 'No'}\n- Similarity: ${similarity}%\n- Different Pixels: ${numDiffPixels} (${diffPercentage.toFixed(2)}%)\n- Total Pixels: ${totalPixels}\n- Image Dimensions: ${img1.width}x${img1.height}\n- Threshold: ${threshold}${diffOutputPath ? `\n- Diff Image Saved: ${diffOutputPath}` : ''}`
|
|
307
|
+
}
|
|
308
|
+
]
|
|
309
309
|
};
|
|
310
310
|
}
|
|
311
311
|
catch (error) {
|
|
312
312
|
return {
|
|
313
|
-
|
|
314
|
-
|
|
313
|
+
content: [
|
|
314
|
+
{
|
|
315
|
+
type: "text",
|
|
316
|
+
text: `Visual Comparison Error: ${error.message}`
|
|
317
|
+
}
|
|
318
|
+
],
|
|
319
|
+
isError: true
|
|
315
320
|
};
|
|
316
321
|
}
|
|
317
322
|
}
|