ts-mcp-durable-browser-automation
MCP server for robust browser automation of legacy web portals, featuring exactly-once execution via an SQLite-backed idempotency lock and resilient Playwright locators.
README
ts-mcp-durable-browser-automation
A production-grade Model Context Protocol (MCP) Server built in TypeScript that wraps a resilient Playwright browser engine with an SQLite-backed Exactly-Once (idempotency) lock, purpose-built to automate interactions with legacy AEC (Architecture, Engineering, Construction) portals that expose unpredictable, brittle APIs.
Architecture
Three discrete, independently testable layers:
LLM / MCP Client
│
▼
┌─────────────────────────────┐
│ Layer 1 · MCP Interface │ @modelcontextprotocol/sdk · Zod v4 input validation
└────────────┬────────────────┘
│
▼
┌─────────────────────────────┐
│ Layer 2 · Idempotency Lock │ SQLite state machine: PENDING → SUCCESS | FAILED
└────────────┬────────────────┘ Rejects concurrent duplicate requests
│
▼
┌─────────────────────────────┐
│ Layer 3 · Playwright Engine│ Resilient locators · auto-retry · screenshot capture
└─────────────────────────────┘ Guaranteed browser.close() via try/finally
Core Features
- Exactly-Once Execution — Every tool call requires an
idempotencyKey. The SQLite lock engine prevents duplicate executions and returns cached results on replay. - Race Condition Protection — Concurrent requests with the same key are rejected while a
PENDINGoperation is in flight. - Resilient Browser Automation — Playwright uses
getByRole/getByTextlocators instead of fragile CSS selectors, with explicit auto-waiting for unpredictable DOM mutations. - Zero Browser Leaks — All browser and context instances are destroyed in
try/finallyblocks, even on fatal crashes. - Strict Type Safety —
strict: trueTypeScript, Zod v4 runtime schema validation, noanytypes. - Physical Proof Generation — A CLI script runs a full end-to-end simulation and outputs a markdown artifact containing structured execution logs and Base64-encoded screenshots.
Project Structure
ts-mcp-durable-browser-automation/
├── src/
│ ├── index.ts # MCP Server entry point
│ ├── mcp/ # Zod schemas, tool handlers
│ ├── automation/ # Playwright lifecycle, submitPermit task
│ ├── core/ # SQLite idempotency lock, structured logger
│ └── types/ # Shared TypeScript interfaces
├── scripts/
│ └── generate_proof.ts # CLI — generates automation_proof.md
├── tests/
│ ├── idempotency.test.ts # Proves exactly-once lock behaviour
│ └── browser.test.ts # Proves browser lifecycle + form automation
├── docs/
│ └── mock_portal.html # Offline legacy AEC portal target
└── automation_proof.md # Generated artifact (Base64 screenshots + logs)
Prerequisites
- Node.js ≥ 20
- npm ≥ 10
Setup
git clone https://github.com/irgiaryanda/ts-mcp-durable-browser-automation.git
cd ts-mcp-durable-browser-automation
npm install
npx playwright install chromium
Commands
Run automated tests
Mathematically proves the idempotency lock (SUCCESS cache hit, PENDING race rejection, FAILED retry) and Playwright browser lifecycle:
npm test
Expected output:
Tests: 8 passed, 8 total
Generate physical proof artifact
Runs a full end-to-end simulation against the offline mock AEC portal and writes automation_proof.md with execution logs and a Base64 screenshot:
npm run prove
Output file: automation_proof.md
Type-check (zero errors)
npx tsc --noEmit
MCP Tool: submit_planning_permit
| Parameter | Type | Description |
|---|---|---|
idempotencyKey |
string |
Unique key guaranteeing exactly-once execution |
projectName |
string |
Name of the construction project |
permitType |
enum |
new_construction | renovation | demolition | change_of_use | heritage |
applicantId |
string |
Registered applicant identifier |
submitDate |
string |
Date in YYYY-MM-DD format |
The tool is safe to retry — replaying a call with an existing idempotencyKey that previously succeeded returns the cached result instantly without re-executing the browser automation.
Key Technical Decisions
| Decision | Rationale |
|---|---|
| SQLite for idempotency store | Zero-dependency, file-based, ACID-compliant. No external service required. |
| Zod v4 for runtime validation | Full compatibility with @modelcontextprotocol/sdk type system (ZodRawShapeCompat). |
getByRole / getByText locators |
Immune to CSS class changes in legacy portal markup. |
try/finally around all browser instances |
Guarantees browser.close() even on unhandled exceptions. |
Offline mock_portal.html as test target |
Eliminates network flakiness — deterministic, reproducible automation proof. |
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.