# MCP

URL: https://flow.lanstar.dev/docs/mcp

> 讓 AI agent（Claude Code 等 MCP client）控制 Flow：開檔、播放、seek、調整音量與速度、讀取播放狀態。

Flow 內建 MCP server，以 Streamable HTTP 提供於 `http://127.0.0.1:17996/mcp`。所有 tool 都經 Command／Property 操作播放器，與 UI 和快捷鍵走同一條路。

## 啟用

預設關閉。啟用後重新開啟 Flow：

```sh
defaults write dev.lanstar.flow MCPServerEnabled -bool YES
defaults write dev.lanstar.flow MCPServerPort -int 18000   # 選用，預設 17996
```

停用：`defaults delete dev.lanstar.flow MCPServerEnabled`。

- Flow 須保持開啟；server 在視窗就緒後才開始監聽。
- port 被佔用時不會啟動，錯誤寫入系統 log（見[疑難排解](#疑難排解)）。

## 連線

以下以 server 名稱 `flow` 為例；改過 `MCPServerPort` 時，URL 的 port 須一併修改。

### CLI

```sh
claude mcp add --transport http flow http://127.0.0.1:17996/mcp   # Claude Code
codex mcp add flow --url http://127.0.0.1:17996/mcp               # Codex CLI
gemini mcp add --transport http flow http://127.0.0.1:17996/mcp   # Gemini CLI
pi mcp add flow --url http://127.0.0.1:17996/mcp                  # Pi
```

### 設定檔

| Client | 設定檔 | 內容 |
|---|---|---|
| Cursor | `~/.cursor/mcp.json` | `{"mcpServers":{"flow":{"url":"http://127.0.0.1:17996/mcp"}}}` |
| VS Code（Copilot） | `.vscode/mcp.json` | `{"servers":{"flow":{"type":"http","url":"http://127.0.0.1:17996/mcp"}}}` |
| Windsurf | `~/.codeium/windsurf/mcp_config.json` | `{"mcpServers":{"flow":{"serverUrl":"http://127.0.0.1:17996/mcp"}}}` |
| opencode | `opencode.json` | `{"mcp":{"flow":{"type":"remote","url":"http://127.0.0.1:17996/mcp"}}}` |

設定檔已有其他 server 時，只合併 `flow` 這一項。

### 只支援 stdio 的 client

Claude Desktop 等只支援 stdio 的 client，經 [`mcp-remote`](https://www.npmjs.com/package/mcp-remote) 轉接（Claude Desktop 的設定檔為 `~/Library/Application Support/Claude/claude_desktop_config.json`）：

```json
{ "mcpServers": { "flow": { "command": "npx", "args": ["-y", "mcp-remote", "http://127.0.0.1:17996/mcp"] } } }
```

其他 client 依其文件填入上述 URL。

## Tools

每個 tool 執行後都回傳[播放狀態](#播放狀態)，讓 agent 直接看到結果。

| Tool | 參數 | 說明 |
|---|---|---|
| `load` | `url`：絕對路徑（可用 `~`）或 URL | 開啟並開始播放，取代目前的媒體 |
| `play` | — | 繼續播放；播完後從頭播放 |
| `pause` | — | 暫停 |
| `stop` | — | 卸載媒體 |
| `seek` | `seconds`：≥ 0；`mode`：`exact`（預設）或 `keyframe` | `exact` 顯示目標幀；`keyframe` 跳到之前的關鍵幀，較快 |
| `set` | `property`、`value`，見下表 | 設定屬性 |
| `status` | — | 讀取播放狀態 |

| `property` | `value` |
|---|---|
| `audio.volume` | 0–100（%），超出範圍時取最近的值 |
| `audio.mute` | `true`／`false` |
| `playback.rate` | 0.25–4，超出範圍時取最近的值；變速時音調不變 |
| `video.rotate` | 順時針角度，須為 90 的倍數 |

參數錯誤或指令失敗時，結果標為 `isError` 並附原因，agent 可修正後重試。

## 播放狀態

```json
{"audio.mute":false,"audio.volume":100,"playback.duration":90,"playback.paused":false,"playback.position":12.346,"playback.rate":1,"video.rotate":0}
```

| 欄位 | 說明 |
|---|---|
| `playback.position` | 目前位置（秒，精確到毫秒） |
| `playback.duration` | 長度（秒）；未開啟媒體或長度未知時為 `null` |
| `playback.paused` | 是否暫停 |
| `playback.rate`、`audio.volume`、`audio.mute`、`video.rotate` | 同 `set` |

## 用 curl 測試

```sh
curl -s http://127.0.0.1:17996/mcp -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"status"}}'
```

不需先送 `initialize`，也不需 session。

## 安全

- 只監聽 `127.0.0.1`，其他機器連不到。
- Host 與 Origin 都必須是 `127.0.0.1` 或 `localhost`，擋下瀏覽器網頁的 DNS rebinding。
- 沒有身分驗證：啟用後，本機任何程式都能控制 Flow，能做的事與使用者在 UI 上相同。不需要時請停用。

## 限制

- 不支援 resources、prompts 與通知；狀態變化須呼叫 `status` 查詢。
- 尚無解碼、丟幀等統計（VID-06）。
- 不提供截圖。

## 疑難排解

```sh
lsof -nP -iTCP:17996 -sTCP:LISTEN                                     # 是否在監聽
log stream --predicate 'subsystem == "Flow" AND category == "FlowMCP"' # 啟動與錯誤 log
```

- 沒有監聽：確認已啟用並重新開啟 Flow；port 被佔用時改用 `MCPServerPort`。
- 回應 403：請求的 Host 或 Origin 不是本機。
