Skip to content

Modularize MCP server into routing and execution layers #39

Description

@smartlabsAT

TL;DR: Replace the monolithic 2223-LOC MCP server with a layered architecture: a routing layer for tool dispatch and an execution layer for browser automation, plus deletion of ~933 LOC of obsoleted protocol modules.

Context

Part of Epic #35 (v0.2.0 architecture cleanup). src/mcp/server.ts currently mixes 7 concerns in a single file: type definitions, mutable state management, session handling, event listeners, browser lifecycle, 26 tool registrations with inline logic, and signal handlers. Splitting these into a routing layer and execution layer enables Epic 2–3 improvements (caching, test scenarios) to be added as interceptors without coupling to specific tools.

This sub-issue also deletes 3 protocol-validation modules (~933 LOC) that become redundant when SDK-level protocol handling takes over.

Acceptance Criteria

  • New src/proxy/ module structure in place (proxy-server.ts, upstream-client.ts)
  • All currently-working tools continue to function end-to-end
  • Server starts and accepts client connections within 3 seconds (measured; PoC baseline: 1.56s)
  • No regression in npm test
  • Existing .mcp.json configurations from prior versions work without modification
  • Protocol modules deleted: protocol-validator.ts, protocol-validation-layer.ts, protocol-error-recovery.ts
  • tsup.config.ts updated with new entry point and externals

Scope

In Scope:

  • Create src/proxy/proxy-server.ts (~280 LOC) — MCP Server, tool list merge, call routing, cleanup handlers
  • Create src/proxy/upstream-client.ts (~250 LOC) — subprocess lifecycle, auto-restart with rate-limit guard
  • Replace src/mcp/server.ts content with 3-line backward-compat shim
  • Add @playwright/mcp@0.0.75 to dependencies (exact pin)
  • Update tsup.config.ts: new proxy entry + @playwright/mcp external
  • Delete src/core/protocol-validator.ts (276 LOC)
  • Delete src/core/protocol-validation-layer.ts (320 LOC)
  • Delete src/core/protocol-error-recovery.ts (337 LOC)
  • Remove protocol exports from src/index.ts: DefaultMCPProtocolValidator, ProtocolError, ProtocolValidationLayer, ProtocolErrorRecovery
  • Delete protocol test files: tests/protocol-basic.test.js, tests/protocol-validation.test.js, tests/protocol-validation-simple.test.js

Out of Scope:

  • Interception logic for click/type (deferred to Epic 2)
  • Local tools (browser_save_test, browser_session_*) — empty local-tool registry in Epic 1, populated in Epic 3
  • --caps flag forwarding (deferred)
  • BASE_URL env var URL rewriting (acknowledged alpha.1 regression; restored in Epic 2)

Technical Implementation

  • New files:

    File LOC est. Purpose
    src/proxy/proxy-server.ts ~280 MCP Server (low-level), setRequestHandler for ListToolsRequestSchema + CallToolRequestSchema, inline local-tool registry, signal cleanup
    src/proxy/upstream-client.ts ~250 Spawn @playwright/mcp subprocess, Client + StdioClientTransport, auto-restart on transport.onclose with rate-limit (max 5/min), restartWith() for Epic 3 session/profile changes
  • Backward-compat shim (src/mcp/server.ts):

    import '../proxy/proxy-server.js';

    This keeps dist/mcp/server.cjs as a valid entry point for existing .mcp.json configs.

  • tsup.config.ts changes:

    • Add entry for src/proxy/proxy-server.tsdist/proxy/
    • Add '@playwright/mcp' to externals in MCP server entry
    • Both dist/mcp/server.cjs (shim) and dist/proxy/proxy-server.cjs get built
  • package.json changes:

    • Add "@playwright/mcp": "0.0.75" to dependencies
    • Verify engines.node is >=18.0.0
  • Auto-restart design: transport.onclose triggers restart with rate-limit guard. Max 5 restarts per 60s window; beyond that, exit with error. intentionalShutdown flag prevents restart on clean stop().

  • Subprocess resolution: require.resolve('@playwright/mcp/cli.js') — uses Node module resolution, no network per start. Fallback: document env var PLAYWRIGHT_MCP_CLI_PATH for unusual setups.

Architecture Reference

From Epic #35 Architecture Decisions:

  • MCP SDK Server class (low-level), not McpServer
  • @playwright/mcp@0.0.75 pinned
  • Backward-compat shim at src/mcp/server.ts
  • Protocol modules deleted
  • browser_* prefix for all tools
  • tsup.config.ts updated

Dependencies

Metadata

Metadata

Assignees

No one assigned

    Labels

    architectureArchitecture changesrefactorCode refactoringv0.2.0v0.2.0 milestone work

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions