Metadata-Version: 2.4
Name: penink-pilot
Version: 1.0.0
Summary: 讓任何 AI agent 像 Codex 一樣操控真實 Chrome 瀏覽器的瀏覽器駕駛員（MCP Server）
Author: penink
License: MIT
Keywords: mcp,agent,browser,chrome,cdp,ai,penink
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Framework :: AsyncIO
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: mcp<2.0.0,>=1.5.0
Requires-Dist: websockets>=12.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.24; extra == "dev"
Dynamic: license-file

# penink-pilot

讓**任何 AI agent 或桌面 agent** 像 OpenAI Codex 一樣「駕駛」真實 Chrome
瀏覽器的 MCP Server（Python）。裝上去之後，你的 AI 就能：

- 開啟真實 Chrome（可見視窗，可先登入網站）
- 前往任何網站、翻頁、回上頁、重新整理
- 讀取整頁結構化快照（標題、網址、可互動元素編號、內文）
- 點擊、輸入、按 Enter／方向鍵、捲動、下拉選單
- 執行任意 JavaScript、截圖確認畫面
- 開多個分頁並切換

> 不用提供 API key、不用付費。只要本機有 Chrome，就能用。

---

## 快速開始

需要 Python 3.10+ 與本機 Chrome（macOS／Windows／Linux 皆可）。

### 1. 安裝

```bash
pip install penink-pilot        # 或： uv pip install penink-pilot
# 開發模式（從本資料夾）： pip install -e .
```

### 2. 找到你的 Chrome（通常不需要）

工具會自動找 Chrome／Chromium。找不到時：

```bash
export CHROME_PATH="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
```

### 3. 先自己測試（不掛 agent）

不想馬上接 agent，想先看它會不會動？

```bash
penink-pilot-demo --url https://example.com
# 或： python -m penink_pilot --demo --url https://example.com
```

它會自己開 Chrome 視窗、導覽、列出頁面元素、截圖存到
`~/penink-pilot-screenshots/`。看到這就是成功了。

### 4. 掛到你的 agent

MCP 是標準協定，任何支援 MCP 的 agent／桌面 agent（Claude Desktop、
opencode、Cursor、Windsurf、Cline…）都能接。以下是幾個範例：

**Claude Desktop**（`claude_desktop_config.json`）：

```json
{
  "mcpServers": {
    "penink-pilot": {
      "command": "penink-pilot",
      "args": []
    }
  }
}
```

**opencode**（`opencode.json`）：

```json
{
  "mcp": {
    "penink-pilot": {
      "type": "local",
      "command": ["penink-pilot"],
      "enabled": true
    }
  }
}
```

也可以直接用 `uvx` 執行，省去手動安裝：

```json
{
  "mcpServers": {
    "penink-pilot": {
      "command": "uvx",
      "args": ["--from", "penink-pilot", "penink-pilot"]
    }
  }
}
```

更多範例看 `examples/`。

### 測試

```bash
pip install -e ".[dev]"
pytest tests/        # 會真的開 headless Chrome 驗證整條鏈路
penink-pilot-demo    # 直接開 Chrome 示範導覽＋快照＋截圖
```

---

## 工具清單（共 23 支，全部 `pilot_` 前綴）

| 工具 | 說明 |
| --- | --- |
| `pilot_start` | 啟動瀏覽器（首次使用自動呼叫） |
| `pilot_stop` | 關閉瀏覽器（保留登入狀態） |
| `pilot_status` | 瀏覽器狀態、分頁清單 |
| `pilot_navigate(url)` | 前往網址 |
| `pilot_back` / `pilot_forward` / `pilot_reload` | 上／下頁、整理 |
| `pilot_snapshot` | **頁面快照**：標題、可互動元素編號、內文 |
| `pilot_title_url` | 只看標題與網址 |
| `pilot_click(ref)` | 點擊快照中編號 ref 的元素 |
| `pilot_dblclick(ref)` | 連點兩下 |
| `pilot_hover(ref)` | 滑鼠移到元素上 |
| `pilot_type(ref, text, enter)` | 輸入文字，可順便按 Enter |
| `pilot_press(key)` | 特殊按鍵（Enter、Tab、Escape、方向鍵…） |
| `pilot_scroll(direction, amount)` | 捲動頁面 |
| `pilot_select(ref, value)` | 下拉選單選值 |
| `pilot_evaluate(js)` | 執行任意 JS，回傳 JSON |
| `pilot_new_tab` / `pilot_switch_tab` / `pilot_close_tab` / `pilot_list_tabs` | 分頁管理 |
| `pilot_screenshot(path?)` | 截圖存 PNG，回傳檔案路徑 |
| `pilot_help` | 使用說明 |

### 基本流程

```
1  pilot_navigate("https://example.com")
2  pilot_snapshot()        ← 拿到所有可互動元素的編號 ref
3  pilot_click(5)          ← 點擊編號 5
4  pilot_type(3, "好內容", enter=True)
5  pilot_screenshot()      ← 確認結果
```

> 注意：`ref` 編號是「當次快照」的，頁面一變動就要重新 `pilot_snapshot`。

---

## 分頁與登入狀態

- 每個 Chrome 有專屬的 profile（`--user-data-dir`），登入／Cookie 在
  `pilot_stop` 後仍保留，下次開啟可直接續用。
- 開多個分頁：`pilot_new_tab("https://...")` → `pilot_switch_tab(0)`。
- 預設開「可見視窗」；想在伺服器上無頭運行可設 `PILOT_HEADLESS=1`。

---

## 開發

```bash
pip install -e ".[dev]"
pytest tests/               # 包含真實開 Chrome 的 e2e 測試
```

程式結構：

```
penink_pilot/
  cdp.py      極簡 CDP WebSocket 客戶端
  chrome.py   Chrome 啟動／尋找／關閉
  pilot.py    把瀏覽器動作翻譯成 CDP 指令（高階邏輯都在這）
  js.py       注入網頁的 JS 片段（掃描／定位／聚焦）
  server.py   MCP Server，23 支 pilot_* 工具
```

## 授權

MIT License，見 [LICENSE](LICENSE)。可自由使用、修改、散佈、商用。

---

### 它是怎麼做到「像 Codex」的

1. 透過 `Chrome DevTools Protocol` 直接跟真實 Chrome 對話（不是模擬器）。
2. `pilot_snapshot` 在網頁裡注入一小段 JS，把「看得見、可互動」的元素
   標上編號，產出人類可讀的結構化文字——AI 不用看圖也能掌握整頁。
3. 點擊是**真實滑鼠事件**（mousePressed／Released at 元素中心座標），
   不是 JS `.click()`，所以 React 等 SPA 與需要 hover 的按鈕都能吃。
4. 輸入走 CDP `Input.insertText`，Unicode／中文沒問題。
