feat(server): add host option to SSE server configuration (#261)

This commit is contained in:
Zheng Xi Zhou 2025-04-24 14:04:00 +08:00 committed by GitHub
parent 4d95761f66
commit 0ed0bcd914
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 25 additions and 6 deletions

View File

@ -74,6 +74,7 @@ The Playwright MCP server supports the following command-line options:
- `--executable-path <path>`: Path to the browser executable
- `--headless`: Run browser in headless mode (headed by default)
- `--port <port>`: Port to listen on for SSE transport
- `--host <host>`: Host to bind server to. Default is localhost. Use 0.0.0.0 to bind to all interfaces.
- `--user-data-dir <path>`: Path to the user data directory
- `--vision`: Run server that uses screenshots (Aria snapshots are used by default)
@ -89,8 +90,7 @@ Playwright MCP will launch the browser with the new profile, located at
All the logged in information will be stored in that profile, you can delete it between sessions if you'd like to clear the offline state.
### Running headless browser (Browser without GUI).
### Running headless browser (Browser without GUI)
This mode is useful for background or batch operations.
@ -129,6 +129,24 @@ And then in MCP client config, set the `url` to the SSE endpoint:
}
```
When running in a remote server, you can use the `--host` flag to bind the server to `0.0.0.0` to make it accessible from outside.
```bash
npx @playwright/mcp@latest --port 8931 --host 0.0.0.0`
```
In MCP client config, `$server-ip` is the IP address of the server:
```js
{
"mcpServers": {
"playwright": {
"url": "http://{$server-ip}:8931/sse"
}
}
}
```
### Docker
**NOTE:** The Docker implementation only supports headless chromium at the moment.

View File

@ -38,6 +38,7 @@ program
.option('--executable-path <path>', 'Path to the browser executable.')
.option('--headless', 'Run browser in headless mode, headed by default')
.option('--port <port>', 'Port to listen on for SSE transport.')
.option('--host <host>', 'Host to bind server to. Default is localhost. Use 0.0.0.0 to bind to all interfaces.')
.option('--user-data-dir <path>', 'Path to the user data directory')
.option('--vision', 'Run server that uses screenshots (Aria snapshots are used by default)')
.action(async options => {
@ -53,7 +54,7 @@ program
setupExitWatchdog(serverList);
if (options.port) {
startSSEServer(+options.port, serverList);
startSSEServer(+options.port, options.host || 'localhost', serverList);
} else {
const server = await serverList.create();
await server.connect(new StdioServerTransport());
@ -74,7 +75,7 @@ function setupExitWatchdog(serverList: ServerList) {
program.parse(process.argv);
function startSSEServer(port: number, serverList: ServerList) {
function startSSEServer(port: number, host: string, serverList: ServerList) {
const sessions = new Map<string, SSEServerTransport>();
const httpServer = http.createServer(async (req, res) => {
if (req.method === 'POST') {
@ -110,7 +111,7 @@ function startSSEServer(port: number, serverList: ServerList) {
}
});
httpServer.listen(port, () => {
httpServer.listen(port, host, () => {
const address = httpServer.address();
assert(address, 'Could not bind server socket');
let url: string;
@ -120,7 +121,7 @@ function startSSEServer(port: number, serverList: ServerList) {
const resolvedPort = address.port;
let resolvedHost = address.family === 'IPv4' ? address.address : `[${address.address}]`;
if (resolvedHost === '0.0.0.0' || resolvedHost === '[::]')
resolvedHost = 'localhost';
resolvedHost = host === 'localhost' ? 'localhost' : resolvedHost;
url = `http://${resolvedHost}:${resolvedPort}`;
}
console.log(`Listening on ${url}`);