# Architecture ``` MCP client (AI agent / VS Code Copilot) │ HTTP /mcp (Streamable MCP) ▼ ┌──────────────────────────────────────┐ │ NestJS app (src/) │ │ │ │ McpService ← all MCP tools │ │ │ │ AuthService login + sessions │ │ SessionService session CRUD │ │ EnvironmentService environment CRUD │ │ BrowserService ad-hoc browsing │ │ CodeExecutorService sandboxed JS │ │ │ │ ScenarioService scenario CRUD │ │ ScenarioSchedulerService │ │ └─ @Interval(1 s) tick loop │ └──────────────────┬───────────────────┘ │ better-sqlite3 (TypeORM) ▼ data/sessions.db ``` - **McpService** — registers every MCP tool and delegates to domain services. - **AuthService** — drives a Playwright browser to log in via a key descriptor; saves cookies + localStorage as a `Session`. - **SessionService** — stores and retrieves saved browser sessions. - **EnvironmentService** — stores named environments (URL maps) used by auth and scenarios. - **BrowserService** — ad-hoc, stateless `open_url` / `exec_code` operations outside the scenario scheduler. - **CodeExecutorService** — compiles and runs user-supplied Playwright JS inside a sandboxed `async` function with `page`, `context`, and `helpers` in scope. - **ScenarioService** — CRUD for scenarios, steps, runs, and run logs; import/export. - **ScenarioSchedulerService** — polls for pending step runs every second and executes them. All steps in the same run share **one browser instance** (see [scenario.md](scenario.md)).