@ricardodeazambuja/browser-mcp-server 1.0.3 → 1.4.0
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/CHANGELOG-v1.3.0.md +42 -0
- package/CHANGELOG-v1.4.0.md +8 -0
- package/README.md +271 -45
- package/package.json +11 -10
- package/plugins/.gitkeep +0 -0
- package/src/.gitkeep +0 -0
- package/src/browser.js +152 -0
- package/src/cdp.js +58 -0
- package/src/index.js +126 -0
- package/src/tools/.gitkeep +0 -0
- package/src/tools/console.js +139 -0
- package/src/tools/docs.js +1611 -0
- package/src/tools/index.js +60 -0
- package/src/tools/info.js +139 -0
- package/src/tools/interaction.js +126 -0
- package/src/tools/keyboard.js +27 -0
- package/src/tools/media.js +264 -0
- package/src/tools/mouse.js +104 -0
- package/src/tools/navigation.js +72 -0
- package/src/tools/network.js +552 -0
- package/src/tools/pages.js +149 -0
- package/src/tools/performance.js +517 -0
- package/src/tools/security.js +470 -0
- package/src/tools/storage.js +467 -0
- package/src/tools/system.js +196 -0
- package/src/utils.js +131 -0
- package/tests/.gitkeep +0 -0
- package/tests/fixtures/.gitkeep +0 -0
- package/tests/fixtures/test-media.html +35 -0
- package/tests/fixtures/test-network.html +48 -0
- package/tests/fixtures/test-performance.html +61 -0
- package/tests/fixtures/test-security.html +33 -0
- package/tests/fixtures/test-storage.html +76 -0
- package/tests/run-all.js +50 -0
- package/{test-browser-automation.js → tests/test-browser-automation.js} +44 -5
- package/{test-mcp.js → tests/test-mcp.js} +9 -4
- package/tests/test-media-tools.js +168 -0
- package/tests/test-network.js +212 -0
- package/tests/test-performance.js +254 -0
- package/tests/test-security.js +203 -0
- package/tests/test-storage.js +192 -0
- package/CHANGELOG-v1.0.2.md +0 -126
- package/browser-mcp-server-playwright.js +0 -792
package/src/utils.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for Browser MCP Server
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
// Get version from package.json
|
|
10
|
+
let version = 'unknown';
|
|
11
|
+
try {
|
|
12
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'));
|
|
13
|
+
version = pkg.version;
|
|
14
|
+
} catch (error) {
|
|
15
|
+
// Fallback if package.json cannot be read
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Log file location
|
|
19
|
+
const logFile = `${os.tmpdir()}/mcp-browser-server.log`;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Log debug messages to file
|
|
23
|
+
* @param {string} msg - Message to log
|
|
24
|
+
*/
|
|
25
|
+
function debugLog(msg) {
|
|
26
|
+
const timestamp = new Date().toISOString();
|
|
27
|
+
fs.appendFileSync(logFile, `${timestamp} - ${msg}\n`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Playwright loading state
|
|
31
|
+
let playwright = null;
|
|
32
|
+
let playwrightError = null;
|
|
33
|
+
let playwrightPath = null;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Load Playwright from multiple possible sources
|
|
37
|
+
* @returns {Object} Playwright module
|
|
38
|
+
* @throws {Error} If Playwright cannot be loaded
|
|
39
|
+
*/
|
|
40
|
+
function loadPlaywright() {
|
|
41
|
+
if (playwright) return playwright;
|
|
42
|
+
if (playwrightError) throw playwrightError;
|
|
43
|
+
|
|
44
|
+
const sources = [
|
|
45
|
+
{ path: 'playwright', name: 'npm Playwright (local)' },
|
|
46
|
+
{ path: `${process.env.HOME}/.cache/ms-playwright-go/1.50.1/package`, name: 'Antigravity Go Playwright' },
|
|
47
|
+
{ path: `${process.env.HOME}/.npm-global/lib/node_modules/playwright`, name: 'npm Playwright (global)' }
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
for (const source of sources) {
|
|
51
|
+
try {
|
|
52
|
+
debugLog(`Trying to load Playwright from: ${source.path}`);
|
|
53
|
+
playwright = require(source.path);
|
|
54
|
+
playwrightPath = source.path;
|
|
55
|
+
debugLog(`✅ Playwright loaded successfully: ${source.name}`);
|
|
56
|
+
return playwright;
|
|
57
|
+
} catch (error) {
|
|
58
|
+
debugLog(`❌ Could not load from ${source.path}: ${error.message}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
playwrightError = new Error(
|
|
63
|
+
'❌ Playwright is not installed.\n\n' +
|
|
64
|
+
'To install Playwright:\n' +
|
|
65
|
+
'1. In Antigravity: Click the Chrome logo (top right) to "Open Browser" - this installs Playwright automatically\n' +
|
|
66
|
+
'2. Standalone mode: Run:\n' +
|
|
67
|
+
' npm install playwright\n' +
|
|
68
|
+
' npx playwright install chromium\n\n' +
|
|
69
|
+
`Tried locations:\n${sources.map(s => ` - ${s.path}`).join('\n')}`
|
|
70
|
+
);
|
|
71
|
+
throw playwrightError;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Get the path where Playwright was loaded from
|
|
76
|
+
* @returns {string|null} Playwright path or null
|
|
77
|
+
*/
|
|
78
|
+
function getPlaywrightPath() {
|
|
79
|
+
return playwrightPath;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Find Chrome executable in common locations
|
|
84
|
+
* @returns {string|null} Path to Chrome executable or null
|
|
85
|
+
*/
|
|
86
|
+
function findChromeExecutable() {
|
|
87
|
+
const { execSync } = require('child_process');
|
|
88
|
+
|
|
89
|
+
const commonPaths = [
|
|
90
|
+
'/usr/bin/google-chrome',
|
|
91
|
+
'/usr/bin/google-chrome-stable',
|
|
92
|
+
'/usr/bin/chromium',
|
|
93
|
+
'/usr/bin/chromium-browser',
|
|
94
|
+
'/snap/bin/chromium',
|
|
95
|
+
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
|
96
|
+
'/Applications/Chromium.app/Contents/MacOS/Chromium',
|
|
97
|
+
'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
|
|
98
|
+
'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe'
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
for (const path of commonPaths) {
|
|
102
|
+
if (fs.existsSync(path)) {
|
|
103
|
+
debugLog(`Found Chrome at: ${path}`);
|
|
104
|
+
return path;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (process.platform !== 'win32') {
|
|
109
|
+
try {
|
|
110
|
+
const result = execSync('which google-chrome || which chromium || which chromium-browser', { encoding: 'utf8' }).trim();
|
|
111
|
+
if (result && fs.existsSync(result)) {
|
|
112
|
+
debugLog(`Found Chrome via 'which': ${result}`);
|
|
113
|
+
return result;
|
|
114
|
+
}
|
|
115
|
+
} catch (e) {
|
|
116
|
+
debugLog(`'which' command failed: ${e.message}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
debugLog('No system Chrome found');
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
module.exports = {
|
|
125
|
+
debugLog,
|
|
126
|
+
loadPlaywright,
|
|
127
|
+
getPlaywrightPath,
|
|
128
|
+
findChromeExecutable,
|
|
129
|
+
logFile,
|
|
130
|
+
version
|
|
131
|
+
};
|
package/tests/.gitkeep
ADDED
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8">
|
|
6
|
+
<title>MCP Media Test Page</title>
|
|
7
|
+
</head>
|
|
8
|
+
|
|
9
|
+
<body>
|
|
10
|
+
<h1>Media Test Page</h1>
|
|
11
|
+
<p>This page is used for testing browser media tools.</p>
|
|
12
|
+
|
|
13
|
+
<h2>Audio Element</h2>
|
|
14
|
+
<audio id="test-audio" controls loop>
|
|
15
|
+
<source src="https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3" type="audio/mp3">
|
|
16
|
+
Your browser does not support the audio element.
|
|
17
|
+
</audio>
|
|
18
|
+
|
|
19
|
+
<h2>Video Element</h2>
|
|
20
|
+
<video id="test-video" width="320" height="240" controls loop muted>
|
|
21
|
+
<source src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4"
|
|
22
|
+
type="video/mp4">
|
|
23
|
+
Your browser does not support the video element.
|
|
24
|
+
</video>
|
|
25
|
+
|
|
26
|
+
<script>
|
|
27
|
+
// Fallback: create Web Audio oscillator if audio tag fails to load data URI
|
|
28
|
+
const audio = document.getElementById('test-audio');
|
|
29
|
+
if (audio.error) {
|
|
30
|
+
console.error('Audio tag error:', audio.error);
|
|
31
|
+
}
|
|
32
|
+
</script>
|
|
33
|
+
</body>
|
|
34
|
+
|
|
35
|
+
</html>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Network Test Page</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<h1>Network Test Page</h1>
|
|
10
|
+
<p>This page makes multiple network requests for testing.</p>
|
|
11
|
+
<div id="status"></div>
|
|
12
|
+
|
|
13
|
+
<script>
|
|
14
|
+
async function makeNetworkRequests() {
|
|
15
|
+
const status = document.getElementById('status');
|
|
16
|
+
status.innerHTML = 'Making network requests...<br>';
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
// Make multiple fetch requests
|
|
20
|
+
const urls = [
|
|
21
|
+
'https://jsonplaceholder.typicode.com/posts/1',
|
|
22
|
+
'https://jsonplaceholder.typicode.com/posts/2',
|
|
23
|
+
'https://jsonplaceholder.typicode.com/users/1'
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
for (const url of urls) {
|
|
27
|
+
try {
|
|
28
|
+
const response = await fetch(url);
|
|
29
|
+
const data = await response.json();
|
|
30
|
+
status.innerHTML += `✓ Fetched: ${url}<br>`;
|
|
31
|
+
} catch (e) {
|
|
32
|
+
status.innerHTML += `✗ Failed: ${url} - ${e.message}<br>`;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
status.innerHTML += 'Network requests completed!';
|
|
37
|
+
} catch (error) {
|
|
38
|
+
status.innerHTML += `Error: ${error.message}`;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Auto-run after page load
|
|
43
|
+
window.addEventListener('load', () => {
|
|
44
|
+
setTimeout(makeNetworkRequests, 500);
|
|
45
|
+
});
|
|
46
|
+
</script>
|
|
47
|
+
</body>
|
|
48
|
+
</html>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Performance Test Page</title>
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
font-family: Arial, sans-serif;
|
|
10
|
+
padding: 20px;
|
|
11
|
+
}
|
|
12
|
+
.container {
|
|
13
|
+
max-width: 800px;
|
|
14
|
+
margin: 0 auto;
|
|
15
|
+
}
|
|
16
|
+
</style>
|
|
17
|
+
</head>
|
|
18
|
+
<body>
|
|
19
|
+
<div class="container">
|
|
20
|
+
<h1>Performance Test Page</h1>
|
|
21
|
+
<p>This page is used for testing CPU profiling and performance metrics.</p>
|
|
22
|
+
<button id="heavy-compute">Run Heavy Computation</button>
|
|
23
|
+
<div id="output"></div>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<script>
|
|
27
|
+
// Heavy computation for CPU profiling test
|
|
28
|
+
function fibonacci(n) {
|
|
29
|
+
if (n <= 1) return n;
|
|
30
|
+
return fibonacci(n - 1) + fibonacci(n - 2);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function performHeavyComputation() {
|
|
34
|
+
const start = Date.now();
|
|
35
|
+
const result = fibonacci(35);
|
|
36
|
+
const duration = Date.now() - start;
|
|
37
|
+
document.getElementById('output').innerHTML =
|
|
38
|
+
`Computed fibonacci(35) = ${result} in ${duration}ms`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Auto-run computation for testing
|
|
42
|
+
document.getElementById('heavy-compute').addEventListener('click', performHeavyComputation);
|
|
43
|
+
|
|
44
|
+
// Run automatically after a short delay
|
|
45
|
+
setTimeout(performHeavyComputation, 100);
|
|
46
|
+
|
|
47
|
+
// Create some DOM nodes for metrics testing
|
|
48
|
+
for (let i = 0; i < 100; i++) {
|
|
49
|
+
const div = document.createElement('div');
|
|
50
|
+
div.textContent = `Node ${i}`;
|
|
51
|
+
div.style.display = 'none';
|
|
52
|
+
document.body.appendChild(div);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Add event listeners for metrics testing
|
|
56
|
+
for (let i = 0; i < 50; i++) {
|
|
57
|
+
document.body.addEventListener('click', () => {});
|
|
58
|
+
}
|
|
59
|
+
</script>
|
|
60
|
+
</body>
|
|
61
|
+
</html>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-inline'">
|
|
7
|
+
<title>Security Test Page</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<h1>Security Test Page</h1>
|
|
11
|
+
<p>This page is used for testing security features.</p>
|
|
12
|
+
<div id="status"></div>
|
|
13
|
+
|
|
14
|
+
<script>
|
|
15
|
+
// This inline script is allowed by CSP
|
|
16
|
+
document.getElementById('status').innerHTML = 'Page loaded successfully';
|
|
17
|
+
|
|
18
|
+
// Attempt to trigger CSP violation by trying to load external script
|
|
19
|
+
// (This will be blocked and create a CSP violation)
|
|
20
|
+
try {
|
|
21
|
+
const script = document.createElement('script');
|
|
22
|
+
script.src = 'https://example.com/external.js';
|
|
23
|
+
document.head.appendChild(script);
|
|
24
|
+
} catch (e) {
|
|
25
|
+
console.log('CSP blocked external script');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Log security info
|
|
29
|
+
console.log('Page protocol:', window.location.protocol);
|
|
30
|
+
console.log('Page origin:', window.location.origin);
|
|
31
|
+
</script>
|
|
32
|
+
</body>
|
|
33
|
+
</html>
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Storage Test Page</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<h1>Storage Test Page</h1>
|
|
10
|
+
<p>This page creates IndexedDB and Cache Storage for testing.</p>
|
|
11
|
+
<div id="status"></div>
|
|
12
|
+
|
|
13
|
+
<script>
|
|
14
|
+
async function setupStorage() {
|
|
15
|
+
const status = document.getElementById('status');
|
|
16
|
+
status.innerHTML = 'Setting up storage...<br>';
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
// Create IndexedDB
|
|
20
|
+
const dbRequest = indexedDB.open('testDB', 1);
|
|
21
|
+
|
|
22
|
+
dbRequest.onupgradeneeded = (event) => {
|
|
23
|
+
const db = event.target.result;
|
|
24
|
+
if (!db.objectStoreNames.contains('users')) {
|
|
25
|
+
const objectStore = db.createObjectStore('users', { keyPath: 'id' });
|
|
26
|
+
objectStore.createIndex('name', 'name', { unique: false });
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
dbRequest.onsuccess = async (event) => {
|
|
31
|
+
const db = event.target.result;
|
|
32
|
+
const transaction = db.transaction(['users'], 'readwrite');
|
|
33
|
+
const objectStore = transaction.objectStore('users');
|
|
34
|
+
|
|
35
|
+
// Add some data
|
|
36
|
+
objectStore.add({ id: 1, name: 'Alice', email: 'alice@example.com' });
|
|
37
|
+
objectStore.add({ id: 2, name: 'Bob', email: 'bob@example.com' });
|
|
38
|
+
|
|
39
|
+
status.innerHTML += '✓ IndexedDB created and populated<br>';
|
|
40
|
+
|
|
41
|
+
// Create Cache Storage
|
|
42
|
+
if ('caches' in window) {
|
|
43
|
+
const cache = await caches.open('test-cache-v1');
|
|
44
|
+
await cache.put('/test', new Response('Test data'));
|
|
45
|
+
status.innerHTML += '✓ Cache Storage created<br>';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Register Service Worker (if supported)
|
|
49
|
+
if ('serviceWorker' in navigator) {
|
|
50
|
+
try {
|
|
51
|
+
// Note: Service worker registration requires HTTPS or localhost
|
|
52
|
+
status.innerHTML += 'Service Worker registration skipped (requires HTTPS)<br>';
|
|
53
|
+
} catch (e) {
|
|
54
|
+
status.innerHTML += `Service Worker: ${e.message}<br>`;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
status.innerHTML += 'Storage setup complete!';
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
dbRequest.onerror = (event) => {
|
|
62
|
+
status.innerHTML += `✗ IndexedDB error: ${event.target.error}<br>`;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
} catch (error) {
|
|
66
|
+
status.innerHTML += `Error: ${error.message}`;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Auto-run after page load
|
|
71
|
+
window.addEventListener('load', () => {
|
|
72
|
+
setTimeout(setupStorage, 500);
|
|
73
|
+
});
|
|
74
|
+
</script>
|
|
75
|
+
</body>
|
|
76
|
+
</html>
|
package/tests/run-all.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Main Test Runner
|
|
5
|
+
* Runs all test files in the tests directory
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { spawnSync } = require('child_process');
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
const testsDir = __dirname;
|
|
13
|
+
const testFiles = fs.readdirSync(testsDir)
|
|
14
|
+
.filter(f => f.startsWith('test-') && f.endsWith('.js'))
|
|
15
|
+
.sort();
|
|
16
|
+
|
|
17
|
+
console.log('🚀 Running all Browser MCP Server tests...\n');
|
|
18
|
+
|
|
19
|
+
let passed = 0;
|
|
20
|
+
let failed = 0;
|
|
21
|
+
|
|
22
|
+
testFiles.forEach(file => {
|
|
23
|
+
console.log(`\n------------------------------------------------------------`);
|
|
24
|
+
console.log(`📄 Testing: ${file}`);
|
|
25
|
+
console.log(`------------------------------------------------------------\n`);
|
|
26
|
+
|
|
27
|
+
const result = spawnSync('node', [path.join(testsDir, file)], {
|
|
28
|
+
stdio: 'inherit'
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (result.status === 0) {
|
|
32
|
+
passed++;
|
|
33
|
+
} else {
|
|
34
|
+
failed++;
|
|
35
|
+
console.error(`\n❌ ${file} failed with exit code ${result.status}`);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
console.log(`\n\n${'='.repeat(60)}`);
|
|
40
|
+
console.log(`📊 Final Test Summary:`);
|
|
41
|
+
console.log(` ✅ Passed: ${passed}`);
|
|
42
|
+
console.log(` ❌ Failed: ${failed}`);
|
|
43
|
+
console.log(`${'='.repeat(60)}\n`);
|
|
44
|
+
|
|
45
|
+
if (failed > 0) {
|
|
46
|
+
process.exit(1);
|
|
47
|
+
} else {
|
|
48
|
+
console.log('🎉 All test suites passed successfully!\n');
|
|
49
|
+
process.exit(0);
|
|
50
|
+
}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
const { spawn } = require('child_process');
|
|
9
9
|
const readline = require('readline');
|
|
10
10
|
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
11
12
|
|
|
12
13
|
let requestId = 0;
|
|
13
14
|
let proc;
|
|
@@ -28,9 +29,10 @@ function sendRequest(method, params = {}) {
|
|
|
28
29
|
|
|
29
30
|
async function runTests() {
|
|
30
31
|
console.log('🌐 Browser Automation Test Suite\n');
|
|
31
|
-
console.log('='
|
|
32
|
+
console.log('='.repeat(60));
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
const serverPath = path.join(__dirname, '..', 'src', 'index.js');
|
|
35
|
+
proc = spawn('node', [serverPath], {
|
|
34
36
|
stdio: ['pipe', 'pipe', 'pipe']
|
|
35
37
|
});
|
|
36
38
|
|
|
@@ -47,6 +49,9 @@ async function runTests() {
|
|
|
47
49
|
'Navigate to Example.com',
|
|
48
50
|
'Evaluate JavaScript',
|
|
49
51
|
'Take Screenshot',
|
|
52
|
+
'Open New Page',
|
|
53
|
+
'List Pages',
|
|
54
|
+
'Wait',
|
|
50
55
|
'Cleanup'
|
|
51
56
|
];
|
|
52
57
|
|
|
@@ -123,9 +128,41 @@ async function runTests() {
|
|
|
123
128
|
break;
|
|
124
129
|
|
|
125
130
|
case 6: // Screenshot
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
131
|
+
console.log(` ✅ ${currentTest}`);
|
|
132
|
+
testStep++;
|
|
133
|
+
|
|
134
|
+
// Open new page
|
|
135
|
+
setTimeout(() => sendRequest('tools/call', {
|
|
136
|
+
name: 'browser_new_page',
|
|
137
|
+
arguments: { url: 'https://google.com' }
|
|
138
|
+
}), 100);
|
|
139
|
+
break;
|
|
140
|
+
|
|
141
|
+
case 7: // New Page
|
|
142
|
+
console.log(` ✅ ${currentTest}`);
|
|
143
|
+
testStep++;
|
|
144
|
+
|
|
145
|
+
// List pages
|
|
146
|
+
setTimeout(() => sendRequest('tools/call', {
|
|
147
|
+
name: 'browser_list_pages',
|
|
148
|
+
arguments: {}
|
|
149
|
+
}), 100);
|
|
150
|
+
|
|
151
|
+
break;
|
|
152
|
+
|
|
153
|
+
case 8: // List Pages
|
|
154
|
+
console.log(` ✅ ${currentTest}`);
|
|
155
|
+
testStep++;
|
|
156
|
+
|
|
157
|
+
// Wait
|
|
158
|
+
setTimeout(() => sendRequest('tools/call', {
|
|
159
|
+
name: 'browser_wait',
|
|
160
|
+
arguments: { ms: 500 }
|
|
161
|
+
}), 100);
|
|
162
|
+
break;
|
|
163
|
+
|
|
164
|
+
case 9: // Wait
|
|
165
|
+
console.log(` ✅ ${currentTest}`);
|
|
129
166
|
testStep++;
|
|
130
167
|
|
|
131
168
|
// All tests complete
|
|
@@ -138,6 +175,8 @@ async function runTests() {
|
|
|
138
175
|
console.log(' • Page navigation (example.com)');
|
|
139
176
|
console.log(' • JavaScript evaluation');
|
|
140
177
|
console.log(' • Screenshot capture');
|
|
178
|
+
console.log(' • Multi-page management');
|
|
179
|
+
console.log(' • Wait utility');
|
|
141
180
|
console.log('\n✨ The MCP server is fully functional!\n');
|
|
142
181
|
|
|
143
182
|
proc.kill();
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
const { spawn } = require('child_process');
|
|
8
8
|
const readline = require('readline');
|
|
9
|
+
const path = require('path');
|
|
9
10
|
|
|
10
11
|
let requestId = 0;
|
|
11
12
|
|
|
@@ -36,9 +37,10 @@ function sendNotification(proc, method, params = {}) {
|
|
|
36
37
|
|
|
37
38
|
async function runTests() {
|
|
38
39
|
console.log('🧪 Starting MCP Server Tests\n');
|
|
39
|
-
console.log('='
|
|
40
|
+
console.log('='.repeat(50));
|
|
40
41
|
|
|
41
|
-
const
|
|
42
|
+
const serverPath = path.join(__dirname, '..', 'src', 'index.js');
|
|
43
|
+
const proc = spawn('node', [serverPath], {
|
|
42
44
|
stdio: ['pipe', 'pipe', 'pipe']
|
|
43
45
|
});
|
|
44
46
|
|
|
@@ -49,6 +51,7 @@ async function runTests() {
|
|
|
49
51
|
|
|
50
52
|
const responses = new Map();
|
|
51
53
|
let testsCompleted = 0;
|
|
54
|
+
let toolCount = 0;
|
|
52
55
|
const totalTests = 3;
|
|
53
56
|
|
|
54
57
|
rl.on('line', (line) => {
|
|
@@ -73,7 +76,7 @@ async function runTests() {
|
|
|
73
76
|
|
|
74
77
|
} else if (response.id === 2) {
|
|
75
78
|
// Tools list response
|
|
76
|
-
|
|
79
|
+
toolCount = response.result.tools.length;
|
|
77
80
|
console.log(` ✅ Received ${toolCount} tools:`);
|
|
78
81
|
response.result.tools.forEach(tool => {
|
|
79
82
|
console.log(` - ${tool.name}`);
|
|
@@ -100,7 +103,9 @@ async function runTests() {
|
|
|
100
103
|
console.log(`\n✅ All tests passed! (${testsCompleted}/${totalTests})`);
|
|
101
104
|
console.log('\n📊 Test Summary:');
|
|
102
105
|
console.log(' ✅ MCP Protocol initialization');
|
|
103
|
-
console.log(
|
|
106
|
+
console.log(` ✅ Tools listing (${toolCount} tools)`);
|
|
107
|
+
|
|
108
|
+
|
|
104
109
|
console.log(' ✅ Browser automation (health check)');
|
|
105
110
|
console.log('\n🎉 MCP Server is fully functional!\n');
|
|
106
111
|
proc.kill();
|