brave-real-browser-mcp-server 2.27.0 → 2.27.1

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.
@@ -7,9 +7,103 @@ export const SERVER_INFO = {
7
7
  // MCP capabilities with LSP-compatible streaming support
8
8
  export const CAPABILITIES = {
9
9
  tools: {},
10
- resources: {},
11
- prompts: {},
10
+ resources: { subscribe: true, listChanged: true },
11
+ prompts: { listChanged: true },
12
12
  };
13
+ // MCP Resources - Dynamic browser state resources
14
+ export const RESOURCES = [
15
+ {
16
+ uri: 'browser://state',
17
+ name: 'Browser State',
18
+ description: 'Current browser instance state including page URL, title, and session info',
19
+ mimeType: 'application/json',
20
+ },
21
+ {
22
+ uri: 'browser://page/content',
23
+ name: 'Page Content',
24
+ description: 'Current page HTML content',
25
+ mimeType: 'text/html',
26
+ },
27
+ {
28
+ uri: 'browser://page/text',
29
+ name: 'Page Text',
30
+ description: 'Current page text content (no HTML)',
31
+ mimeType: 'text/plain',
32
+ },
33
+ {
34
+ uri: 'browser://cookies',
35
+ name: 'Browser Cookies',
36
+ description: 'All cookies in current browser session',
37
+ mimeType: 'application/json',
38
+ },
39
+ {
40
+ uri: 'browser://network/requests',
41
+ name: 'Network Requests',
42
+ description: 'Recent network requests captured during browsing',
43
+ mimeType: 'application/json',
44
+ },
45
+ {
46
+ uri: 'browser://console/logs',
47
+ name: 'Console Logs',
48
+ description: 'Browser console log messages',
49
+ mimeType: 'application/json',
50
+ },
51
+ ];
52
+ // MCP Prompts - Reusable automation workflows
53
+ export const PROMPTS = [
54
+ {
55
+ name: 'scrape_website',
56
+ description: 'Scrape content from a website with automatic navigation and extraction',
57
+ arguments: [
58
+ { name: 'url', description: 'URL to scrape', required: true },
59
+ { name: 'selector', description: 'CSS selector for target content', required: false },
60
+ { name: 'outputFormat', description: 'Output format (json, markdown, text)', required: false },
61
+ ],
62
+ },
63
+ {
64
+ name: 'extract_download_links',
65
+ description: 'Extract all download links from a page with quality and size info',
66
+ arguments: [
67
+ { name: 'url', description: 'Page URL to extract from', required: true },
68
+ { name: 'fileTypes', description: 'File types to extract (mp4, mkv, pdf, etc.)', required: false },
69
+ ],
70
+ },
71
+ {
72
+ name: 'monitor_page_changes',
73
+ description: 'Monitor a page for changes and notify when content updates',
74
+ arguments: [
75
+ { name: 'url', description: 'URL to monitor', required: true },
76
+ { name: 'selector', description: 'Element to watch for changes', required: true },
77
+ { name: 'interval', description: 'Check interval in seconds', required: false },
78
+ ],
79
+ },
80
+ {
81
+ name: 'automate_login',
82
+ description: 'Automate login to a website with credentials',
83
+ arguments: [
84
+ { name: 'url', description: 'Login page URL', required: true },
85
+ { name: 'usernameSelector', description: 'Username field selector', required: true },
86
+ { name: 'passwordSelector', description: 'Password field selector', required: true },
87
+ { name: 'submitSelector', description: 'Submit button selector', required: true },
88
+ ],
89
+ },
90
+ {
91
+ name: 'batch_screenshot',
92
+ description: 'Take screenshots of multiple URLs',
93
+ arguments: [
94
+ { name: 'urls', description: 'Comma-separated list of URLs', required: true },
95
+ { name: 'outputDir', description: 'Directory to save screenshots', required: true },
96
+ ],
97
+ },
98
+ {
99
+ name: 'extract_video_stream',
100
+ description: 'Extract video streaming URL from a page (m3u8, mp4)',
101
+ arguments: [
102
+ { name: 'url', description: 'Video page URL', required: true },
103
+ { name: 'quality', description: 'Preferred quality (highest, 1080p, 720p)', required: false },
104
+ ],
105
+ },
106
+ ];
13
107
  // Extended capabilities for streaming and auto-sync (for documentation/client info)
14
108
  export const EXTENDED_CAPABILITIES = {
15
109
  streaming: true,
@@ -17,10 +17,10 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
17
17
  import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
18
18
  import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
19
19
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
20
- import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ListPromptsRequestSchema, InitializeRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
20
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, InitializeRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
21
21
  import { randomUUID } from 'crypto';
22
22
  // Import core modules
23
- import { TOOLS, SERVER_INFO, CAPABILITIES, TOOL_NAMES } from './tool-definitions.js';
23
+ import { TOOLS, SERVER_INFO, CAPABILITIES, TOOL_NAMES, RESOURCES, PROMPTS } from './tool-definitions.js';
24
24
  import { getSharedEventBus } from './shared/event-bus.js';
25
25
  import { getProgressNotifier } from './transport/progress-notifier.js';
26
26
  import { getSessionManager } from './transport/session-manager.js';
@@ -69,8 +69,109 @@ mcpServer.setRequestHandler(InitializeRequestSchema, async (request) => {
69
69
  };
70
70
  });
71
71
  mcpServer.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
72
- mcpServer.setRequestHandler(ListResourcesRequestSchema, async () => ({ resources: [] }));
73
- mcpServer.setRequestHandler(ListPromptsRequestSchema, async () => ({ prompts: [] }));
72
+ mcpServer.setRequestHandler(ListResourcesRequestSchema, async () => ({ resources: RESOURCES }));
73
+ mcpServer.setRequestHandler(ListPromptsRequestSchema, async () => ({ prompts: PROMPTS }));
74
+ // Read Resource Handler
75
+ mcpServer.setRequestHandler(ReadResourceRequestSchema, async (request) => {
76
+ const { uri } = request.params;
77
+ const page = getPageInstance();
78
+ debug(`ReadResource: ${uri}`);
79
+ try {
80
+ switch (uri) {
81
+ case 'browser://state': {
82
+ const state = page ? {
83
+ url: page.url(),
84
+ title: await page.title(),
85
+ isConnected: page.browser()?.connected ?? false,
86
+ viewport: page.viewport(),
87
+ } : { status: 'Browser not initialized' };
88
+ return { contents: [{ uri, mimeType: 'application/json', text: JSON.stringify(state, null, 2) }] };
89
+ }
90
+ case 'browser://page/content': {
91
+ if (!page)
92
+ throw new Error('Browser not initialized');
93
+ const html = await page.content();
94
+ return { contents: [{ uri, mimeType: 'text/html', text: html }] };
95
+ }
96
+ case 'browser://page/text': {
97
+ if (!page)
98
+ throw new Error('Browser not initialized');
99
+ const text = await page.evaluate(() => document.body.innerText);
100
+ return { contents: [{ uri, mimeType: 'text/plain', text }] };
101
+ }
102
+ case 'browser://cookies': {
103
+ if (!page)
104
+ throw new Error('Browser not initialized');
105
+ const cookies = await page.cookies();
106
+ return { contents: [{ uri, mimeType: 'application/json', text: JSON.stringify(cookies, null, 2) }] };
107
+ }
108
+ case 'browser://network/requests': {
109
+ // Return cached network requests from event bus
110
+ const history = eventBus.getHistory().filter(e => e.type.includes('network'));
111
+ return { contents: [{ uri, mimeType: 'application/json', text: JSON.stringify(history.slice(-50), null, 2) }] };
112
+ }
113
+ case 'browser://console/logs': {
114
+ const logs = eventBus.getHistory().filter(e => e.type.includes('console'));
115
+ return { contents: [{ uri, mimeType: 'application/json', text: JSON.stringify(logs.slice(-100), null, 2) }] };
116
+ }
117
+ default:
118
+ throw new Error(`Unknown resource: ${uri}`);
119
+ }
120
+ }
121
+ catch (error) {
122
+ const errorMessage = error instanceof Error ? error.message : String(error);
123
+ return { contents: [{ uri, mimeType: 'text/plain', text: `Error: ${errorMessage}` }] };
124
+ }
125
+ });
126
+ // Get Prompt Handler
127
+ mcpServer.setRequestHandler(GetPromptRequestSchema, async (request) => {
128
+ const { name, arguments: args } = request.params;
129
+ debug(`GetPrompt: ${name}`);
130
+ const prompt = PROMPTS.find(p => p.name === name);
131
+ if (!prompt) {
132
+ throw new Error(`Unknown prompt: ${name}`);
133
+ }
134
+ // Generate prompt messages based on template
135
+ let messages = [];
136
+ switch (name) {
137
+ case 'scrape_website':
138
+ messages = [
139
+ { role: 'user', content: { type: 'text', text: `Scrape the website at ${args?.url || '[URL]'}. ${args?.selector ? `Focus on elements matching: ${args.selector}` : 'Extract main content.'}` } },
140
+ ];
141
+ break;
142
+ case 'extract_download_links':
143
+ messages = [
144
+ { role: 'user', content: { type: 'text', text: `Extract all download links from ${args?.url || '[URL]'}. ${args?.fileTypes ? `Filter for: ${args.fileTypes}` : 'Include all file types.'}` } },
145
+ ];
146
+ break;
147
+ case 'monitor_page_changes':
148
+ messages = [
149
+ { role: 'user', content: { type: 'text', text: `Monitor ${args?.url || '[URL]'} for changes in element: ${args?.selector || '[SELECTOR]'}. Check every ${args?.interval || 60} seconds.` } },
150
+ ];
151
+ break;
152
+ case 'automate_login':
153
+ messages = [
154
+ { role: 'user', content: { type: 'text', text: `Automate login to ${args?.url || '[URL]'}. Use ${args?.usernameSelector || '#username'} for username, ${args?.passwordSelector || '#password'} for password, and ${args?.submitSelector || 'button[type=submit]'} to submit.` } },
155
+ ];
156
+ break;
157
+ case 'batch_screenshot':
158
+ messages = [
159
+ { role: 'user', content: { type: 'text', text: `Take screenshots of: ${args?.urls || '[URLs]'}. Save to: ${args?.outputDir || './screenshots'}` } },
160
+ ];
161
+ break;
162
+ case 'extract_video_stream':
163
+ messages = [
164
+ { role: 'user', content: { type: 'text', text: `Extract video streaming URL from ${args?.url || '[URL]'}. Prefer quality: ${args?.quality || 'highest'}` } },
165
+ ];
166
+ break;
167
+ default:
168
+ messages = [{ role: 'user', content: { type: 'text', text: `Execute prompt: ${name}` } }];
169
+ }
170
+ return {
171
+ description: prompt.description,
172
+ messages,
173
+ };
174
+ });
74
175
  mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => {
75
176
  const { name, arguments: args } = request.params;
76
177
  debug(`Tool call: ${name}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brave-real-browser-mcp-server",
3
- "version": "2.27.0",
3
+ "version": "2.27.1",
4
4
  "description": "🦁 MCP server for Brave Real Browser - NPM Workspaces Monorepo with anti-detection features, SSE streaming, and LSP compatibility",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -50,7 +50,7 @@
50
50
  "dependencies": {
51
51
  "@modelcontextprotocol/sdk": "latest",
52
52
  "@types/turndown": "latest",
53
- "brave-real-browser": "^2.8.0",
53
+ "brave-real-browser": "^2.8.1",
54
54
  "puppeteer-core": "^24.35.0",
55
55
  "turndown": "latest",
56
56
  "vscode-languageserver": "^9.0.1",