@ricardodeazambuja/browser-mcp-server 1.0.3

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/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@ricardodeazambuja/browser-mcp-server",
3
+ "version": "1.0.3",
4
+ "description": "Universal browser automation MCP server using Playwright. Works with Antigravity, Claude Desktop, and any MCP client.",
5
+ "main": "browser-mcp-server-playwright.js",
6
+ "bin": {
7
+ "browser-mcp-server": "./browser-mcp-server-playwright.js"
8
+ },
9
+ "scripts": {
10
+ "start": "node browser-mcp-server-playwright.js",
11
+ "install-browsers": "npx playwright install chromium",
12
+ "test": "echo 'Testing MCP server...' && echo '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"test\",\"version\":\"1.0.0\"}}}' | node browser-mcp-server-playwright.js"
13
+ },
14
+ "keywords": [
15
+ "mcp",
16
+ "mcp-server",
17
+ "model-context-protocol",
18
+ "browser-automation",
19
+ "playwright",
20
+ "claude",
21
+ "antigravity",
22
+ "web-automation",
23
+ "testing",
24
+ "scraping"
25
+ ],
26
+ "author": "Ricardo de Azambuja (https://ricardodeazambuja.com)",
27
+ "license": "MIT",
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "git+https://github.com/ricardodeazambuja/browser-mcp-server.git"
31
+ },
32
+ "bugs": {
33
+ "url": "https://github.com/ricardodeazambuja/browser-mcp-server/issues"
34
+ },
35
+ "homepage": "https://github.com/ricardodeazambuja/browser-mcp-server#readme",
36
+ "engines": {
37
+ "node": ">=16.0.0"
38
+ },
39
+ "dependencies": {
40
+ "playwright": "^1.57.0"
41
+ },
42
+ "files": [
43
+ "browser-mcp-server-playwright.js",
44
+ "README.md",
45
+ "LICENSE",
46
+ "CHANGELOG-v1.0.2.md",
47
+ "test-mcp.js",
48
+ "test-browser-automation.js"
49
+ ]
50
+ }
@@ -0,0 +1,189 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Comprehensive browser automation test
5
+ * Tests actual browser operations: navigate, evaluate JS, screenshot
6
+ */
7
+
8
+ const { spawn } = require('child_process');
9
+ const readline = require('readline');
10
+ const fs = require('fs');
11
+
12
+ let requestId = 0;
13
+ let proc;
14
+
15
+ function sendRequest(method, params = {}) {
16
+ const id = ++requestId;
17
+ const request = {
18
+ jsonrpc: '2.0',
19
+ id,
20
+ method,
21
+ params
22
+ };
23
+
24
+ console.log(`\nโžก๏ธ ${method}${params.name ? ` (${params.name})` : ''}`);
25
+ proc.stdin.write(JSON.stringify(request) + '\n');
26
+ return id;
27
+ }
28
+
29
+ async function runTests() {
30
+ console.log('๐ŸŒ Browser Automation Test Suite\n');
31
+ console.log('=' .repeat(60));
32
+
33
+ proc = spawn('node', ['browser-mcp-server-playwright.js'], {
34
+ stdio: ['pipe', 'pipe', 'pipe']
35
+ });
36
+
37
+ const rl = readline.createInterface({
38
+ input: proc.stdout,
39
+ crlfDelay: Infinity
40
+ });
41
+
42
+ let testStep = 0;
43
+ const tests = [
44
+ 'Initialize',
45
+ 'List Tools',
46
+ 'Health Check',
47
+ 'Navigate to Example.com',
48
+ 'Evaluate JavaScript',
49
+ 'Take Screenshot',
50
+ 'Cleanup'
51
+ ];
52
+
53
+ rl.on('line', async (line) => {
54
+ try {
55
+ const response = JSON.parse(line);
56
+
57
+ if (response.id === undefined) return; // Skip notifications
58
+
59
+ const currentTest = tests[testStep];
60
+
61
+ if (response.error) {
62
+ console.log(` โŒ ${currentTest} failed: ${response.error.message}`);
63
+ proc.kill();
64
+ process.exit(1);
65
+ return;
66
+ }
67
+
68
+ switch (response.id) {
69
+ case 1: // Initialize
70
+ console.log(` โœ… ${currentTest}`);
71
+ testStep++;
72
+ setTimeout(() => sendRequest('tools/list'), 100);
73
+ break;
74
+
75
+ case 2: // Tools list
76
+ console.log(` โœ… ${currentTest} (${response.result.tools.length} tools)`);
77
+ testStep++;
78
+ setTimeout(() => sendRequest('tools/call', {
79
+ name: 'browser_health_check',
80
+ arguments: {}
81
+ }), 100);
82
+ break;
83
+
84
+ case 3: // Health check
85
+ const healthText = response.result.content[0].text;
86
+ const mode = healthText.includes('Launched standalone')
87
+ ? 'Standalone Mode'
88
+ : 'Antigravity Mode';
89
+ console.log(` โœ… ${currentTest} (${mode})`);
90
+ testStep++;
91
+
92
+ // Navigate to a real page
93
+ setTimeout(() => sendRequest('tools/call', {
94
+ name: 'browser_navigate',
95
+ arguments: { url: 'https://example.com' }
96
+ }), 100);
97
+ break;
98
+
99
+ case 4: // Navigate
100
+ console.log(` โœ… ${currentTest}`);
101
+ testStep++;
102
+
103
+ // Evaluate some JavaScript
104
+ setTimeout(() => sendRequest('tools/call', {
105
+ name: 'browser_evaluate',
106
+ arguments: {
107
+ code: 'document.title + " - " + window.location.href'
108
+ }
109
+ }), 500);
110
+ break;
111
+
112
+ case 5: // Evaluate JS
113
+ const evalResult = JSON.parse(response.result.content[0].text);
114
+ console.log(` โœ… ${currentTest}`);
115
+ console.log(` Result: ${evalResult}`);
116
+ testStep++;
117
+
118
+ // Take a screenshot
119
+ setTimeout(() => sendRequest('tools/call', {
120
+ name: 'browser_screenshot',
121
+ arguments: { fullPage: false }
122
+ }), 500);
123
+ break;
124
+
125
+ case 6: // Screenshot
126
+ const imgData = response.result.content[0].data;
127
+ const imgSize = Buffer.from(imgData, 'base64').length;
128
+ console.log(` โœ… ${currentTest} (${(imgSize / 1024).toFixed(1)} KB)`);
129
+ testStep++;
130
+
131
+ // All tests complete
132
+ setTimeout(() => {
133
+ console.log('\n' + '='.repeat(60));
134
+ console.log('\n๐ŸŽ‰ All browser automation tests passed!\n');
135
+ console.log('โœ… Test Results:');
136
+ console.log(' โ€ข MCP protocol communication');
137
+ console.log(' โ€ข Browser launch (standalone mode)');
138
+ console.log(' โ€ข Page navigation (example.com)');
139
+ console.log(' โ€ข JavaScript evaluation');
140
+ console.log(' โ€ข Screenshot capture');
141
+ console.log('\nโœจ The MCP server is fully functional!\n');
142
+
143
+ proc.kill();
144
+ process.exit(0);
145
+ }, 500);
146
+ break;
147
+ }
148
+ } catch (error) {
149
+ console.error(`\nโŒ Error: ${error.message}`);
150
+ proc.kill();
151
+ process.exit(1);
152
+ }
153
+ });
154
+
155
+ proc.stderr.on('data', (data) => {
156
+ const msg = data.toString();
157
+ if (msg.toLowerCase().includes('error')) {
158
+ console.error(`โš ๏ธ ${msg}`);
159
+ }
160
+ });
161
+
162
+ proc.on('close', (code) => {
163
+ if (code !== 0 && testStep < tests.length) {
164
+ console.error(`\nโŒ Process exited unexpectedly (code ${code})`);
165
+ process.exit(code);
166
+ }
167
+ });
168
+
169
+ // Start test sequence
170
+ setTimeout(() => {
171
+ sendRequest('initialize', {
172
+ protocolVersion: '2024-11-05',
173
+ capabilities: {},
174
+ clientInfo: { name: 'automation-test', version: '1.0.0' }
175
+ });
176
+ }, 100);
177
+
178
+ // Timeout after 60 seconds
179
+ setTimeout(() => {
180
+ console.error('\nโŒ Test timeout');
181
+ proc.kill();
182
+ process.exit(1);
183
+ }, 60000);
184
+ }
185
+
186
+ runTests().catch(error => {
187
+ console.error('โŒ Fatal error:', error);
188
+ process.exit(1);
189
+ });
package/test-mcp.js ADDED
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Comprehensive test script for the browser MCP server
5
+ */
6
+
7
+ const { spawn } = require('child_process');
8
+ const readline = require('readline');
9
+
10
+ let requestId = 0;
11
+
12
+ function sendRequest(proc, method, params = {}) {
13
+ const id = ++requestId;
14
+ const request = {
15
+ jsonrpc: '2.0',
16
+ id,
17
+ method,
18
+ params
19
+ };
20
+
21
+ console.log(`\nโžก๏ธ Sending: ${method}`);
22
+ proc.stdin.write(JSON.stringify(request) + '\n');
23
+ return id;
24
+ }
25
+
26
+ function sendNotification(proc, method, params = {}) {
27
+ const notification = {
28
+ jsonrpc: '2.0',
29
+ method,
30
+ params
31
+ };
32
+
33
+ console.log(`\nโžก๏ธ Sending notification: ${method}`);
34
+ proc.stdin.write(JSON.stringify(notification) + '\n');
35
+ }
36
+
37
+ async function runTests() {
38
+ console.log('๐Ÿงช Starting MCP Server Tests\n');
39
+ console.log('=' .repeat(50));
40
+
41
+ const proc = spawn('node', ['browser-mcp-server-playwright.js'], {
42
+ stdio: ['pipe', 'pipe', 'pipe']
43
+ });
44
+
45
+ const rl = readline.createInterface({
46
+ input: proc.stdout,
47
+ crlfDelay: Infinity
48
+ });
49
+
50
+ const responses = new Map();
51
+ let testsCompleted = 0;
52
+ const totalTests = 3;
53
+
54
+ rl.on('line', (line) => {
55
+ try {
56
+ const response = JSON.parse(line);
57
+ console.log(`\nโฌ…๏ธ Response (id=${response.id}):`);
58
+
59
+ if (response.error) {
60
+ console.log(` โŒ Error: ${response.error.message}`);
61
+ } else if (response.result) {
62
+ if (response.id === 1) {
63
+ // Initialize response
64
+ console.log(` โœ… Protocol: ${response.result.protocolVersion}`);
65
+ console.log(` โœ… Server: ${response.result.serverInfo.name} v${response.result.serverInfo.version}`);
66
+ testsCompleted++;
67
+
68
+ // Send initialized notification
69
+ sendNotification(proc, 'notifications/initialized');
70
+
71
+ // Request tools list
72
+ setTimeout(() => sendRequest(proc, 'tools/list'), 100);
73
+
74
+ } else if (response.id === 2) {
75
+ // Tools list response
76
+ const toolCount = response.result.tools.length;
77
+ console.log(` โœ… Received ${toolCount} tools:`);
78
+ response.result.tools.forEach(tool => {
79
+ console.log(` - ${tool.name}`);
80
+ });
81
+ testsCompleted++;
82
+
83
+ // Test health check (actual browser operation)
84
+ setTimeout(() => sendRequest(proc, 'tools/call', {
85
+ name: 'browser_health_check',
86
+ arguments: {}
87
+ }), 100);
88
+
89
+ } else if (response.id === 3) {
90
+ // Health check response
91
+ if (response.result.content && response.result.content[0]) {
92
+ console.log(` โœ… Health Check Result:`);
93
+ console.log(response.result.content[0].text.split('\n').map(l => ` ${l}`).join('\n'));
94
+ }
95
+ testsCompleted++;
96
+
97
+ // All tests done
98
+ setTimeout(() => {
99
+ console.log('\n' + '='.repeat(50));
100
+ console.log(`\nโœ… All tests passed! (${testsCompleted}/${totalTests})`);
101
+ console.log('\n๐Ÿ“Š Test Summary:');
102
+ console.log(' โœ… MCP Protocol initialization');
103
+ console.log(' โœ… Tools listing (16 tools)');
104
+ console.log(' โœ… Browser automation (health check)');
105
+ console.log('\n๐ŸŽ‰ MCP Server is fully functional!\n');
106
+ proc.kill();
107
+ process.exit(0);
108
+ }, 500);
109
+ }
110
+ }
111
+ } catch (error) {
112
+ console.error('โŒ Error parsing response:', error.message);
113
+ }
114
+ });
115
+
116
+ proc.stderr.on('data', (data) => {
117
+ const msg = data.toString();
118
+ if (msg.includes('Error') || msg.includes('error')) {
119
+ console.error(`\nโš ๏ธ stderr: ${msg}`);
120
+ }
121
+ });
122
+
123
+ proc.on('close', (code) => {
124
+ if (code !== 0 && testsCompleted < totalTests) {
125
+ console.error(`\nโŒ Process exited with code ${code}`);
126
+ process.exit(code);
127
+ }
128
+ });
129
+
130
+ // Start the test sequence
131
+ setTimeout(() => {
132
+ sendRequest(proc, 'initialize', {
133
+ protocolVersion: '2024-11-05',
134
+ capabilities: {},
135
+ clientInfo: { name: 'test-client', version: '1.0.0' }
136
+ });
137
+ }, 100);
138
+
139
+ // Safety timeout
140
+ setTimeout(() => {
141
+ console.error('\nโŒ Test timeout - tests did not complete in time');
142
+ proc.kill();
143
+ process.exit(1);
144
+ }, 30000); // 30 second timeout
145
+ }
146
+
147
+ runTests().catch(error => {
148
+ console.error('โŒ Test failed:', error);
149
+ process.exit(1);
150
+ });