Skip to main content
Glama
README.md
# Konnect

A local browser-automation bridge that lets AI agents drive your **real** browser
— your actual login sessions, cookies, and tabs — instead of a cloud sandbox or
headless instance. Konnect connects MCP-compatible coding agents (and a token-cheap
CLI) to [Comet Browser](https://www.comet.com/) via a long-lived daemon and a
Chrome MV3 extension.

**Status:** production. Runs on macOS via `launchd` (port 9223).

## Architecture

A persistent aiohttp daemon (`daemon/`, listens on `:9223`) owns the WebSocket to
a Chrome MV3 extension (`extension/`) that performs the actual page interaction;
the WS survives MV3 service-worker eviction via an offscreen document. Two thin
clients front the daemon's HTTP API: an MCP stdio shim (`mcp/`) for AI agents and
a CLI (`cli/`) for low-token coding. The daemon is the single source of truth —
MCP is *one* client, not the only interface.

See [`ARCHITECTURE.md`](./ARCHITECTURE.md) for full design rationale and the
decision tree (why daemon-over-MCP, why snapshot-first, why CLI+SKILL alongside MCP).

## Components

```
konnect/
├── daemon/      # aiohttp daemon: /command /ws /health (the persistent core)
├── extension/   # Chrome MV3 extension (service worker + content script + offscreen WS)
├── mcp/         # MCP stdio server — thin shim → daemon HTTP
├── cli/         # argparse CLI → daemon HTTP (token-cheap)
├── skill/       # SKILL.md — agent operating instructions
├── tests/       # isolated test harness (disposable Chromium + CDP)
├── deploy/      # launchd plist template + install.sh
└── docs/        # operations notes
```

## Install

```bash
# 1. Python deps (aiohttp for the daemon)
pip install -e .

# 2. Install + start the daemon under launchd
deploy/install.sh

# 3. Load the extension (one-time, manual)
#    chrome://extensions (or comet://extensions) → Developer mode → Load unpacked
#    → choose this repo's extension/ directory
```

`deploy/install.sh` auto-detects a Python with `aiohttp` (or takes an explicit
path: `deploy/install.sh /path/to/python`). It renders `local.konnect.daemon.plist`
with your `$HOME` and repo path — no hardcoded user paths.

Verify the daemon sees the extension:

```bash
curl http://127.0.0.1:9223/health   # → {"extension_connected": true}
```

Logs: `/tmp/konnect-daemon.log`. Stop: `launchctl unload ~/Library/LaunchAgents/local.konnect.daemon.plist`.

## Usage — MCP tools

Wire `mcp/konnect_mcp.py` as an MCP server in your agent (Claude, Cursor, opencode).
Exposed tools (all proxy to the daemon over HTTP):

| Tool | Purpose |
|------|---------|
| `konnect_health` | Check daemon + extension connection |
| `konnect_list_tabs` | List open browser tabs (group + blocked state) |
| `konnect_find_tab` | Select an already-open tab by URL prefix |
| `konnect_navigate` | Open a URL (new background tab by default) |
| `konnect_snapshot` | AX-style accessibility tree with `ref=N` targeting |
| `konnect_click` | Click an element by ref |
| `konnect_fill` | Fill an input/textarea/select/contenteditable by ref |
| `konnect_screenshot` | Capture tab/element to a PNG file (read via `Read`) |
| `konnect_get_text` | Visible text of the current tab |
| `konnect_evaluate` | Run JS in the page main world (fallback for ref limits) |

Targeting is snapshot-first: call `konnect_snapshot`, read the `ref=N` tags, then
`konnect_click`/`konnect_fill` by ref. Screenshots write to disk and are read with
`Read` — never base64 into context.

## Security

- Bearer-token auth (`extension/token.json`), generated by the daemon; tokens are
  git-ignored and never committed.
- `evaluate` runs in the MAIN world for trusted local use only. Sites that check
  `event.isTrusted` may reject synthetic events — a product boundary, not a bug.

## License

[MIT](./LICENSE). Clean-room implementation; see `ARCHITECTURE.md`.