brave-real-browser-mcp-server 2.8.4 → 2.8.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.
@@ -120,11 +120,13 @@ export async function handleContentClassification(args) {
120
120
  return { category: cat.name, score };
121
121
  });
122
122
  scores.sort((a, b) => b.score - a.score);
123
+ const confidence = scores[0].score / (scores.reduce((sum, s) => sum + s.score, 0) || 1);
124
+ const resultText = `✅ Content Classification\n\nPrimary Category: ${scores[0].category} (Score: ${scores[0].score})\nConfidence: ${(confidence * 100).toFixed(2)}%\n\nAll Categories:\n${JSON.stringify(scores.slice(0, 5), null, 2)}`;
123
125
  return {
124
- success: true,
125
- primaryCategory: scores[0],
126
- allScores: scores,
127
- confidence: scores[0].score / (scores.reduce((sum, s) => sum + s.score, 0) || 1)
126
+ content: [{
127
+ type: 'text',
128
+ text: resultText
129
+ }]
128
130
  };
129
131
  }
130
132
  catch (error) {
@@ -173,23 +175,18 @@ export async function handleSentimentAnalysis(args) {
173
175
  sentiment: s.score > 0 ? 'positive' : s.score < 0 ? 'negative' : 'neutral'
174
176
  };
175
177
  });
178
+ const stats = {
179
+ totalSentences: sentences.length,
180
+ positiveSentences: sentenceSentiments.filter(s => s.sentiment === 'positive').length,
181
+ negativeSentences: sentenceSentiments.filter(s => s.sentiment === 'negative').length,
182
+ neutralSentences: sentenceSentiments.filter(s => s.sentiment === 'neutral').length
183
+ };
184
+ const resultText = `✅ Sentiment Analysis\n\nOverall Sentiment: ${result.score > 0 ? 'Positive' : result.score < 0 ? 'Negative' : 'Neutral'}\nScore: ${result.score}\nComparative: ${result.comparative.toFixed(4)}\n\nStatistics:\n- Total Sentences: ${stats.totalSentences}\n- Positive: ${stats.positiveSentences}\n- Negative: ${stats.negativeSentences}\n- Neutral: ${stats.neutralSentences}\n\nPositive Words: ${result.positive.join(', ')}\nNegative Words: ${result.negative.join(', ')}`;
176
185
  return {
177
- success: true,
178
- overall: {
179
- score: result.score,
180
- comparative: result.comparative,
181
- sentiment: result.score > 0 ? 'positive' : result.score < 0 ? 'negative' : 'neutral',
182
- tokens: result.tokens.length,
183
- positive: result.positive,
184
- negative: result.negative
185
- },
186
- sentences: sentenceSentiments,
187
- statistics: {
188
- totalSentences: sentences.length,
189
- positiveSentences: sentenceSentiments.filter(s => s.sentiment === 'positive').length,
190
- negativeSentences: sentenceSentiments.filter(s => s.sentiment === 'negative').length,
191
- neutralSentences: sentenceSentiments.filter(s => s.sentiment === 'neutral').length
192
- }
186
+ content: [{
187
+ type: 'text',
188
+ text: resultText
189
+ }]
193
190
  };
194
191
  }
195
192
  catch (error) {
@@ -254,20 +251,13 @@ export async function handleSummaryGenerator(args) {
254
251
  // Sort by original order
255
252
  topSentences.sort((a, b) => a.index - b.index);
256
253
  const summary = topSentences.map(s => s.sentence).join(' ');
254
+ const compressionRatio = (summary.length / content.length * 100).toFixed(2);
255
+ const resultText = `✅ Summary Generated\n\nSummary:\n${summary}\n\nStatistics:\n- Original Length: ${content.length} characters\n- Summary Length: ${summary.length} characters\n- Compression Ratio: ${compressionRatio}%\n- Original Sentences: ${sentences.length}\n- Summary Sentences: ${topSentences.length}`;
257
256
  return {
258
- success: true,
259
- summary,
260
- originalLength: content.length,
261
- summaryLength: summary.length,
262
- compressionRatio: (summary.length / content.length * 100).toFixed(2) + '%',
263
- sentenceCount: {
264
- original: sentences.length,
265
- summary: topSentences.length
266
- },
267
- topScoredSentences: topSentences.map(s => ({
268
- sentence: s.sentence,
269
- score: s.score.toFixed(2)
270
- }))
257
+ content: [{
258
+ type: 'text',
259
+ text: resultText
260
+ }]
271
261
  };
272
262
  }
273
263
  catch (error) {
@@ -328,18 +318,13 @@ export async function handleTranslationSupport(args) {
328
318
  const keyPhrases = tfidf.listTerms(0)
329
319
  .slice(0, 10)
330
320
  .map(term => term.term);
321
+ const needsTranslation = detectedLang !== targetLanguage && detectedLang !== 'und';
322
+ const resultText = `✅ Translation Support\n\nDetected Language: ${languageName} (${detectedLang})\nTarget Language: ${targetLanguage}\nNeeds Translation: ${needsTranslation ? 'Yes' : 'No'}\n\nContent Length: ${contentToTranslate.length} characters\nContent Preview: ${contentToTranslate.substring(0, 200)}...\n\nKey Phrases: ${keyPhrases.join(', ')}\n\nNote: Use external translation API (Google Translate, DeepL) for actual translation`;
331
323
  return {
332
- success: true,
333
- detectedLanguage: {
334
- code: detectedLang,
335
- name: languageName
336
- },
337
- targetLanguage,
338
- needsTranslation: detectedLang !== targetLanguage && detectedLang !== 'und',
339
- contentPreview: contentToTranslate.substring(0, 200),
340
- contentLength: contentToTranslate.length,
341
- keyPhrases,
342
- translationNote: 'Use external translation API (Google Translate, DeepL) for actual translation'
324
+ content: [{
325
+ type: 'text',
326
+ text: resultText
327
+ }]
343
328
  };
344
329
  }
345
330
  catch (error) {
@@ -47,18 +47,23 @@ export async function handleOCREngine(args) {
47
47
  bbox: word.bbox
48
48
  }));
49
49
  return {
50
- success: true,
51
- text,
52
- confidence,
53
- words,
54
- lines: result.data.lines.length,
55
- language
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
- success: false,
61
- error: error.message
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
- success: true,
110
- audioUrl: audioSource,
111
- downloaded,
112
- downloadPath: downloaded ? downloadPath : null,
113
- note: 'Audio captcha solving requires external speech-to-text API (Google Speech, AWS Transcribe, etc.)'
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
- success: false,
119
- error: error.message
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
- success: true,
213
- ...result,
214
- note: 'Advanced puzzle solving requires computer vision libraries (OpenCV, TensorFlow)'
237
+ content: [
238
+ {
239
+ type: "text",
240
+ text: summary
241
+ }
242
+ ]
215
243
  };
216
244
  }
217
245
  catch (error) {
218
246
  return {
219
- success: false,
220
- error: error.message
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
- success: true,
244
- duration,
245
- fps,
246
- frameCount: frames.length,
247
- frames: frames.slice(0, 5), // Show first 5 frames
248
- outputPath,
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
- success: false,
255
- error: error.message
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
- success: false,
277
- error: 'Image dimensions do not match',
278
- image1: { width: img1.width, height: img1.height },
279
- image2: { width: img2.width, height: img2.height }
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
- success: true,
296
- identical: numDiffPixels === 0,
297
- differences: {
298
- pixels: numDiffPixels,
299
- percentage: diffPercentage.toFixed(2) + '%',
300
- totalPixels
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
- success: false,
314
- error: error.message
313
+ content: [
314
+ {
315
+ type: "text",
316
+ text: `Visual Comparison Error: ${error.message}`
317
+ }
318
+ ],
319
+ isError: true
315
320
  };
316
321
  }
317
322
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brave-real-browser-mcp-server",
3
- "version": "2.8.4",
3
+ "version": "2.8.6",
4
4
  "description": "MCP server for brave-real-browser",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",