Skip to main content
Glama
README.md
# Fovea Web

Cross-browser **MCP server + Manifest V3 extension** for **mobile-first layout auditing** and browser automation. The only MCP that thinks like a responsive QA, not just a click-bot.

## Architecture

```
AI Harness <--(Stdio/MCP)--> MCP Server <--(WebSocket :8080)--> Extension Background Worker <--(CDP/DOM)--> Web Page
                              keeps login (extension) vs disposable profile (Playwright)
```

## Why Fovea Web vs Playwright / chrome-devtools-mcp / BrowserTools

| Feature | Fovea Web | Playwright MCP (52 tools) | chrome-devtools-mcp (57) | BrowserTools (16) |
|---|---|---|---|---|
| **Mobile audit** (overflow, viewport, tap targets) | ✅ `audit_responsive` + `screenshot_matrix` | ❌ only `resize` | ❌ only `emulate` | ❌ |
| Touch `swipe` | ✅ `swipe` | ❌ mouse only | ❌ | ❌ |
| VisualViewport + safe-area | ✅ `get_viewport_metrics` | ❌ | ❌ | ❌ |
| Media query introspection | ✅ `get_media_queries` | ❌ | ❌ | ❌ |
| Keeps logged-in session | ✅ extension | ❌ isolated profile | ❌ | ✅ read-only |

## 🚀 Quick Start

### 1. Build
```bash
npm install
npm run build
```

### 2. Load Extension
* **Chrome / Brave / Edge:** `chrome://extensions` → Developer Mode → **Load unpacked** → `dist/extension`
* **Firefox:** `about:debugging#/runtime/this-firefox` → Load Temporary Add-on → `dist/extension/manifest.firefox.json`

Popup shows **● Connected** / **○ Disconnected**, active tabs, and a one-click **Audit This Page** checker.

### 3. Connect to AI Harness
Add to `mcp.json`:
```json
{
  "mcpServers": {
    "fovea-web": {
      "command": "node",
      "args": ["/path/to/fovea-web/dist/server/index.js"],
      "env": { "WS_PORT": "8080" }
    }
  }
}
```
Or use the included `.mcp.json`.

## Tools (16)

| Tool | Description |
|------|-------------|
| `capture_mobile_layout` | Emulate 8 presets (SE/14/Pro Max/Pixel/iPad/Desktop/HD/Custom) + DPR/touch/UA, full-page screenshot or `convertToText` |
| `get_accessibility_tree` | Chrome a11y tree via CDP |
| `click_element` | CSS/XPath click |
| `scroll_page` | up/down/top/bottom |
| **`navigate`** | Navigate active tab, wait for load |
| **`type_text`** | Real keystrokes into inputs (clear/submit/delay) |
| **`press_key`** | `Enter`/`Escape`/`Arrow*` + modifiers |
| **`hover_element`** | Hover to open menus |
| **`evaluate_js`** | Run JS in page, return JSON |
| **`get_console_logs`** | Buffered console (log/warn/error) |
| **`get_viewport_metrics`** | inner/outer/visualViewport/DPR/scrollWidth/safeArea/meta viewport |
| **`get_media_queries`** | List media queries + `matches` |
| **`audit_responsive`** | ⭐ Cycle 5 viewports, detect `HORIZONTAL_OVERFLOW`/`MISSING_VIEWPORT`/`FIXED_WIDTH_OVERFLOW`/`SMALL_TAP_TARGET`, markdown + JSON |
| **`screenshot_matrix`** | ⭐ One-call screenshots across `N` devices |
| `swipe` | Touch swipe (up/down/left/right) |
| `tabs` | list/create/close tabs |

### Example — responsive audit

Ask your LLM: *"audit responsive layout for this page, include screenshots"* → calls `audit_responsive{devices:[iPhone_SE, Pixel_7, Desktop], includeScreenshots:true}` → returns:

```markdown
# Responsive Audit — https://example.com
_2025-08-20_ — ❌ FAIL — 2 errors, 1 warnings
| Viewport | Overflow | Issues |
| iPhone_SE (375px) | ⚠️ YES | 2 |
## iPhone_SE — 2 issue(s)
- 🔴 HORIZONTAL_OVERFLOW document — scrollWidth 412px > viewport 375px
- 🔴 FIXED_WIDTH_OVERFLOW div.hero — width 400px > viewport 375px
```

## Project Structure
```
fovea-web/
├── src/
│   ├── protocol.ts          # WS wire + 8 device presets + ViewportMetrics/AuditResult
│   ├── tools.ts             # Zod schemas for 16 tools
│   ├── ws-bridge.ts         # WS server :8080 with req_id timeout map
│   ├── layout-analyzer.ts   # analyzeLayout + auditBreakpoint + formatAuditAsMarkdown
│   └── mcp-server.ts        # 16 MCP tools via stdio
├── extension/
│   ├── manifest.json        # MV3 + alarms keep-alive (Fovea Web)
│   ├── background.ts        # CDP + scripting + audit orchestration + badge
│   ├── content.ts           # console hook + viewport/media/audit snapshot
│   ├── popup.html/ts        # status + tabs + quick audit
│   └── manifest.firefox.json
└── tests/
    ├── mcp-server.test.ts
    └── layout-analyzer.test.ts
```

## Testing
```bash
npm test          # vitest
npm run lint      # tsc --noEmit
npm run build     # esbuild -> dist/
```

## Env
See `.env.example`. `WS_PORT` defaults to `8080`. Extension uses `chrome.alarms` keep-alive to survive MV3 idle.

## Roadmap
- [x] Device matrix + touch + viewport + media introspection
- [x] Audit + matrix (differentiators)
- [ ] Network throttling (`slow4g`/`cpu4x`), Lighthouse-mobile
- [ ] Visual regression store + diff threshold