Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
56daaff
Use official Playwright MCP server in .vscode/mcp.json
nnoce14 Apr 8, 2026
63d2e2d
chore: upgrade vite to fix audit vulnerability
nnoce14 Apr 8, 2026
7386b64
Configure Playwright MCP (stdio) and remove http variant
nnoce14 Apr 9, 2026
e581424
Add repo-level Copilot MCP config and install script
nnoce14 Apr 9, 2026
6d89558
docs(mcp): add .github/mcp README and verification script; prefer ins…
nnoce14 Apr 9, 2026
31b802c
chore: commit pnpm-lock.yaml
nnoce14 Apr 9, 2026
a09f4c1
ci(mcp): start Playwright MCP and install repo mcp-config in copilot …
nnoce14 Apr 9, 2026
65d803e
chore(mcp): add safe installer for mcp-config and use it in CI\n\nCre…
nnoce14 Apr 9, 2026
a7b234e
ci(mcp): align pnpm action version with package.json (10.30.1)\n\nEns…
nnoce14 Apr 9, 2026
60a0c31
Merge origin/main into issue/203-playwright-mcp: resolve merge confli…
nnoce14 Apr 9, 2026
cc43df0
chore: resolve audit vulnerability for axios
nnoce14 Apr 9, 2026
e353dc4
chore: fix sonar scan memory issue on CI pipeline
nnoce14 Apr 9, 2026
82dbff5
chore(ci): pin @playwright/mcp version to 1.59.0 in workflow\n\nCo-au…
nnoce14 Apr 9, 2026
4ccf9c1
chore(mcp): pin @playwright/mcp to 0.0.70 across workflow and configs…
nnoce14 Apr 9, 2026
af5901a
chore(mcp): centralize MCP start script; ignore unknown flags in inst…
nnoce14 Apr 9, 2026
3c49ffb
chore(mcp): remove unused .github/mcp/run_login.mjs to satisfy knip
nnoce14 Apr 9, 2026
d3208f1
Merge branch 'main' into issue/203-playwright-mcp
nnoce14 Apr 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .copilot/mcp-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"mcpServers": {
"playwright": {
"type": "stdio",
"command": "npx",
"args": ["@playwright/mcp@0.0.70"],
"tools": ["*"]
}
}
}
36 changes: 36 additions & 0 deletions .github/mcp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Playwright MCP — Agent & Developer Guidance

This folder documents how to use the Playwright MCP server for Copilot/agents and local development.

Key points:
- The verification script used during testing was temporary. It's not required every time.
- The canonical MCP config for this repo is `.copilot/mcp-config.json` (committed). Copilot CLI reads `~/.copilot/mcp-config.json`.

Recommended developer steps (manual):
1. Install the repo MCP config into your home directory (non-destructive):

pnpm run mcp:install-config

This copies `./.copilot/mcp-config.json` to `~/.copilot/mcp-config.json` if you don't already have one.

2. Start the Playwright MCP server (HTTP, programmatic):

pnpm run mcp:playwright:start

(For editor/stdio usage, use `pnpm run mcp:playwright:stdio`.)

3. Start the dev stack (portless mapping):

pnpm run dev

4. Optional manual verification (headless):

node .github/mcp/run_login.mjs

This script is a convenience for maintainers to verify a headless login flow. It is not required for agents to function.

Guidance for automation/CI:
- Prefer using the HTTP MCP server (`--port 8931`) for CI and programmatic checks.
- Avoid automatically overwriting users' `~/.copilot/mcp-config.json` in postinstall hooks. Prefer documented, explicit steps (as above).

If you want a packaged automation for agents, prefer creating a small GitHub Actions workflow that starts the MCP on a runner and uses it for tests, rather than forcing local machine changes.
80 changes: 80 additions & 0 deletions .github/mcp/install-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/env node
import fs from 'fs/promises';
import path from 'path';
import os from 'os';

const argv = process.argv.slice(2).filter(a => a !== '--');

function printUsage() {
console.log(`Usage: node install-config.js [--force] [--source <path>]\n\nOptions:\n --force, -f Overwrite existing config without creating a backup\n --source, -s Path to source mcp-config.json (defaults to ./.copilot/mcp-config.json in the repo)\n --help, -h Show this help message\n\nNote: Unknown extra arguments are ignored to allow wrapper passthrough.`);
}

let force = false;
let source = null;

for (let i = 0; i < argv.length; i++) {
const a = argv[i];
if (a === '--force' || a === '-f') {
force = true;
} else if (a === '--source' || a === '-s') {
const val = argv[i + 1];
if (!val || val.startsWith('-')) {
console.error('Error: --source requires a path argument');
printUsage();
process.exit(1);
}
source = val;
i++;
} else if (a === '--help' || a === '-h') {
printUsage();
process.exit(0);
} else {
console.warn('Warning: Ignoring unknown argument:', a);
// Allow passthrough of extra args from wrappers; ignore unknown flags
continue;
}
}

if (!source) {
source = path.resolve(process.cwd(), '.copilot', 'mcp-config.json');
} else {
source = path.resolve(process.cwd(), source);
}

async function exists(p) {
try { await fs.access(p); return true } catch { return false }
}

async function main(){
try {
if (!await exists(source)){
console.error(`Source config not found at ${source}`);
process.exit(2);
}

const destDir = path.join(os.homedir(), '.copilot');
const destFile = path.join(destDir, 'mcp-config.json');

await fs.mkdir(destDir, { recursive: true });

if (await exists(destFile)){
if (force){
console.log('Overwriting existing config due to --force');
} else {
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const backupPath = `${destFile}.${timestamp}.bak`;
await fs.copyFile(destFile, backupPath);
console.log(`Existing config backed up to ${backupPath}`);
}
}

await fs.copyFile(source, destFile);
console.log(`Installed MCP config from ${source} to ${destFile}`);
process.exit(0);
} catch (err){
console.error('Failed to install MCP config:', err);
process.exit(1);
}
}

main();
38 changes: 36 additions & 2 deletions .github/workflows/copilot-setup-steps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
- name: Set up pnpm
uses: pnpm/action-setup@v4
with:
version: 10.18.2
version: 10.30.1

- name: Cache pnpm store
uses: actions/cache@v4
Expand Down Expand Up @@ -65,7 +65,7 @@ jobs:
uses: actions/cache@v4
with:
path: /home/runner/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ hashFiles('**/package-lock.json') }}
key: ${{ runner.os }}-playwright-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-playwright-

Expand All @@ -77,6 +77,40 @@ jobs:
PLAYWRIGHT_BROWSERS_PATH: /home/runner/.cache/ms-playwright
if: steps.playwright-cache.outputs.cache-hit != 'true'

- name: Install repo MCP config
run: pnpm run mcp:install-config -- --force

- name: Start Playwright MCP (HTTP, background)
run: |
echo "Starting Playwright MCP on port 8931 (pnpm dlx)..."
nohup pnpm run mcp:start > mcp.log 2>&1 &
# Wait briefly for MCP to open the port
for i in $(seq 1 30); do
ss -ltn | grep -q ':8931' && break || sleep 1
done
echo "MCP log (last 200 lines):"
tail -n 200 mcp.log || true
env:
PLAYWRIGHT_BROWSERS_PATH: /home/runner/.cache/ms-playwright

- name: Wait for MCP readiness
run: |
ready=0
for i in $(seq 1 30); do
if curl -fsS http://localhost:8931/ >/dev/null 2>&1 || ss -ltn | grep -q ':8931'; then
echo "Playwright MCP seems ready"
ready=1
break
fi
sleep 1
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
done
if [ "$ready" -ne 1 ]; then
echo "Playwright MCP did not become ready after 30s"
echo "MCP log (last 200 lines):"
tail -n 200 mcp.log || true
exit 1
fi

- name: Install Java SDK (Required for SonarCloud)
uses: actions/setup-java@v4
with:
Expand Down
5 changes: 5 additions & 0 deletions .vscode/mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
"MDB_MCP_CONNECTION_STRING": "mongodb://localhost:50000"
}
},
"playwright": {
"command": "npx",
"args": ["@playwright/mcp@0.0.70"],
"type": "stdio"
},
"chrome-devtools": {
"name": "chrome-devtools",
"command": "bash",
Expand Down
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@
"snyk:iac:report": "snyk iac test iac/build/**/*.json --org=cellixjs --remote-repo-url=https://github.com/CellixJs/cellixjs --target-reference=main --target-name=cellixjs-iac --report",
"analyze": "pnpm dlx @e18e/cli analyze",
"prepare": "husky",
"edgescan:run": "docker run --tty --rm edgescan/cicd-integration:latest --api-token $ES_API_TOKEN --asset-id $ES_ASSET_ID --start-scan --max-risk-threshold 3 --wait --color"
"edgescan:run": "docker run --tty --rm edgescan/cicd-integration:latest --api-token $ES_API_TOKEN --asset-id $ES_ASSET_ID --start-scan --max-risk-threshold 3 --wait --color",
"mcp:start": "pnpm dlx @playwright/mcp@0.0.70 --port 8931 --headless --ignore-https-errors --allowed-hosts='localhost' --allowed-origins='http://localhost,https://localhost'",
"mcp:playwright:start": "pnpm run mcp:start",
"mcp:playwright:stdio": "pnpm dlx @playwright/mcp@0.0.70",
"mcp:install-config": "node .github/mcp/install-config.js"
},
"devDependencies": {
"@amiceli/vitest-cucumber": "^6.3.0",
Expand All @@ -74,6 +78,7 @@
"concurrently": "^9.1.2",
"husky": "^9.1.7",
"knip": "^5.64.2",
"playwright": "1.59.0",
"portless": "0.9.1",
"rimraf": "^6.0.1",
"snyk": "^1.1300.2",
Expand Down
Loading
Loading