Build: DDEV Add-on for Local MCP Server Testing with Playwright
· 2 min read
I built a DDEV add-on that runs Playwright checks against local MCP endpoints using internal DDEV DNS names like web. This solves flaky localhost-based testing and gives one command for repeatable MCP smoke tests.
The Problem
Teams testing MCP servers locally usually mix host networking, ad-hoc scripts, and one-off commands. That breaks quickly when ports change or when tests run from a different container context.
| Pain point | Typical failure |
|---|---|
Host-only URLs (localhost) | Fails inside containers where service DNS is required |
| Manual Playwright setup per project | Inconsistent versions and missing browser deps |
| No MCP-specific smoke command | Health-check regressions are discovered too late |
Related context: Build: MCP Web Setup, Build: Drupal MCP Toolkit, Drupal Context MCP Integration.
The Solution
The add-on installs:
- A dedicated
mcp-playwrightservice via Docker Compose. - DDEV commands:
ddev mcp-pw-smokeandddev mcp-pw-test. - A Playwright smoke test for
GET /healthwith configurableMCP_BASE_URL.
Code from the project:
# docker-compose.mcp-playwright.yaml
services:
mcp-playwright:
image: mcr.microsoft.com/playwright:v1.56.1-noble
working_dir: /var/www/html/.ddev/mcp-playwright
# commands/host/mcp-pw-smoke
ddev exec -s mcp-playwright "cd /var/www/html/.ddev/mcp-playwright && npm ci --silent && MCP_BASE_URL=\${MCP_BASE_URL:-http://web:3100} npx playwright test tests/mcp-health.spec.js --reporter=line"
// mcp-playwright/tests/mcp-health.spec.js
const response = await request.get(`${baseUrl}/health`);
expect(response.ok()).toBeTruthy();
What I Learned
webDNS names inside DDEV are safer thanlocalhostfor cross-container test reliability.- A tiny helper (
resolveMcpBaseUrl) plus tests prevents subtle URL-format bugs. - Dedicated smoke commands are worth adding early when MCP endpoints are a release gate.
