colab-cli-mcp
by nmt3325
README.md
# colab-cli-mcp
Google 公式の [google-colab-cli](https://github.com/googlecolab/google-colab-cli) をラップした
**リモート MCP サーバー**です。ブラウザ・`ws://localhost`・SSH トンネルを一切使わずに、
Notion AI などの MCP クライアントから Colab の GPU/TPU ランタイムで Python を実行できます。
```
Notion AI ──HTTPS(OAuth)──▶ colab-cli-mcp ──subprocess──▶ colab CLI ──HTTPS──▶ Colab runtime
```
## MCP ツール
| ツール | 対応する CLI | 説明 |
| --- | --- | --- |
| `create_session(session, gpu, tpu)` | `colab new` | ランタイム作成(gpu: T4/L4/G4/H100/A100、tpu: v5e1/v6e1、無指定は CPU) |
| `list_sessions()` | `colab sessions` | セッション一覧(runtime token は返しません) |
| `session_status(session)` | `colab status` | 状態確認 |
| `stop_session(session)` | `colab stop` | ランタイム解放 |
| `restart_kernel(session)` | `colab restart-kernel` | カーネル再起動 |
| `run_code(code, session, timeout)` | `colab exec -f` | Python コード実行 |
| `install_packages(packages, session, timeout)` | `colab exec` | uv / pip でパッケージ導入 |
| `list_files(path, session)` | `colab ls` | VM 上のファイル一覧 |
| `read_remote_file(remote_path)` | `colab download` | VM 上のテキストを取得 |
| `write_remote_file(remote_path, content)` | `colab upload` | VM 上にテキストを書き込み |
| `download_to_workspace` / `upload_workspace_file` | `colab download` / `upload` | 大きい/バイナリファイル用 |
| `remove_remote_file(path, session)` | `colab rm` | ファイル削除 |
| `mount_drive(path, session, force_remount)` | `colab exec` | Google Drive マウント |
| `session_log(session, lines, event_type)` | `colab log` | 実行履歴 |
| `session_notebook_url(session)` | `colab url` | 同じ VM にブラウザから接続する URL |
| `cli_version()` | `colab version` | CLI バージョン |
> **実装メモ**: `install_packages` と `mount_drive` は `colab exec` 経路で実行しています。
> `colab install` / `colab drivemount` 自体は正常に動作しますが、colab-cli 0.6.0 の
> `run_automation()` には `colab exec` が持っているセッション存在チェック
> (`if not s`) がなく、セッションがローカル状態から消えていると
> `AttributeError: 'NoneType' object has no attribute 'url'` という生のトレースバックを返します。
> exec 経路にそろえることで、エラー処理を統一し、タイムアウト指定と
> 完了マーカーによる成否判定を可能にしています。
> **Google Drive のマウントについて**: Drive の認可が未取得の場合、
> どちらの方式でもヘッドレスでは完結しません。`colab drivemount` の認証フックは
> `open("/dev/tty")` での手動確認を要求するため、TTY のないコンテナでは
> 600 秒のタイムアウトまでハングします。exec 経路なら `timeout` 秒で
> 打ち切って原因を含むエラーを返します。初回は `session_notebook_url` の URL を
> ブラウザで開き、Drive アクセスを一度許可してください。
`repl` / `console` / `edit` / `ssh` / `pay` / `update` は対話専用なので意図的に除外しています。
## 2 層の認証
1. **MCP クライアント → 本サーバー**: `--auth token|none|google|github|oidc`
2. **本サーバー → Colab**: Colab CLI 自身の `--colab-auth oauth2|adc`
### 1. MCP 側(Notion AI から繋ぐ)
```bash
colab-cli-mcp \
--transport http --host 0.0.0.0 --port 8080 --path /mcp \
--auth google \
--base-url https://colab-mcp.example.com \
--oauth-client-id xxxxx.apps.googleusercontent.com \
--oauth-client-secret GOCSPX-xxxxx \
--allowed-identity you@example.com
```
Google Cloud Console のリダイレクト URI には `<base-url>/auth/callback` を登録します。
公開が必要なエンドポイント: `/mcp`, `/.well-known/oauth-authorization-server`,
`/.well-known/oauth-protected-resource/mcp`, `/authorize`, `/token`, `/register`,
`/consent`, `/auth/callback`。
> **警告**: `--allowed-identity` を省略すると、OAuth を通った *任意の* Google アカウントが
> あなたの Colab で任意コードを実行できます。必ず自分のアドレス(または `@domain`)を指定してください。
### 2. Colab CLI 側(ヘッドレスサーバーでの初回認証)
CLI はブラウザなしでも認証できます(`auth.py` の remote flow / `token_usage=remote`)。
サーバー上で 1 回だけ手で実行してトークンを作ります。
```bash
# コンテナ内で 1 回だけ
docker compose run --rm --entrypoint colab colab-cli-mcp sessions
# → 表示された URL を手元のブラウザで開き、
# 表示された認可コードを貼り付ける(~/.config/colab-cli/token.json に保存)
```
ADC を使う場合は `--colab-auth adc` にして、
```bash
gcloud auth application-default login \
--scopes=openid,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/colaboratory
```
`~/.config/colab-cli/` と workspace は **必ず volume で永続化**してください(compose 済み)。
## Docker
### GHCR の公式イメージを使う(ビルド不要)
`main` への push ごとに GitHub Actions が linux/amd64 + linux/arm64 の
マルチアーキイメージを自動で公開しています。
```bash
docker pull ghcr.io/animationsaver/colab-cli-mcp:latest
```
タグ: `latest` / `main` / `sha-<short>` / リリース時は `1.2.3`・`1.2`。
```bash
cp .env.example .env
# .env を編集(最低限 COLAB_CLI_MCP_AUTH_TOKEN を openssl rand -hex 24 で埋める)
docker compose -f docker-compose.ghcr.yml up -d
# 初回のみ: Colab CLI の認証(トークンは volume に残るので 1 回だけ)
docker compose -f docker-compose.ghcr.yml run --rm --entrypoint colab colab-cli-mcp sessions
```
動作確認:
```bash
curl -X POST http://127.0.0.1:8080/mcp \
-H "Authorization: Bearer $COLAB_CLI_MCP_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'
```
イメージを更新するときは `docker compose -f docker-compose.ghcr.yml pull && \
docker compose -f docker-compose.ghcr.yml up -d`。
### ソースからビルドする
```bash
export COLAB_CLI_MCP_BASE_URL=https://colab-mcp.example.com
export COLAB_CLI_MCP_OAUTH_CLIENT_ID=...
export COLAB_CLI_MCP_OAUTH_CLIENT_SECRET=...
export COLAB_CLI_MCP_ALLOWED_IDENTITY=you@example.com
docker compose up -d --build
```
TLS は Caddy / nginx / Cloudflare Tunnel などで前段終端してください。
## 環境変数
`COLAB_CLI_MCP_` + `TRANSPORT` / `HOST` / `PORT` / `PATH` / `AUTH` / `AUTH_TOKEN`(csv) /
`BASE_URL` / `OAUTH_CLIENT_ID` / `OAUTH_CLIENT_SECRET` / `OAUTH_SCOPE`(csv) /
`OAUTH_REDIRECT_PATH` / `OAUTH_NO_CONSENT` / `OIDC_CONFIG_URL` / `ALLOWED_IDENTITY`(csv) /
`EXECUTABLE` / `COLAB_AUTH` / `COLAB_OAUTH_CONFIG` / `COLAB_STATE` / `WORKSPACE`
## 設計上のポイント
- **ローカル FS のサンドボックス**: upload/download のローカル側は workspace 配下に限定(`..` は拒否)。
- **セッション単位のロック**: Colab カーネルは同時 1 リクエストなので `asyncio.Lock` で直列化。
- **秘密情報の非公開**: `sessions.json` の `token`(runtime proxy token)はツール出力から除去。
- **出力の正規化**: rich の枠線・ANSI・アップデートバナーを除去してから返す。
- **既知の上流バグ**: 長時間実行は [google-colab-cli#14](https://github.com/googlecolab/google-colab-cli/issues/14)
(80 秒で無応答)の影響を受ける可能性があります。`run_code` の `timeout` は余裕を持たせてください。
## 開発
```bash
uv sync
uv run ruff check . && uv run ruff format --check .
uv run pytest -q
```
## Multiple Google accounts
Every account gets its own HOME under `<workspace>/accounts/<name>/`, so its
`token.json`, `sessions.json`, `settings.json` and history stay separate. The
`default` account keeps the container HOME (`~/.config/colab-cli`), so an
already authenticated deployment keeps working with no migration.
| Tool | Purpose |
| --- | --- |
| `list_accounts` | Show configured accounts, which one is active, and their sessions |
| `switch_account` | Make an account active for every later call (creates it if new) |
| `authorize_account` | Sign an account in: first call returns the Google URL, second call takes the code |
| `forget_account` | Delete a named account credentials, sessions and history |
Sign in a second account without a terminal:
1. `switch_account { "account": "work" }`
2. `authorize_account {}` -> returns `authorization_url`
3. Open the URL, approve, copy the code Google shows
4. `authorize_account { "code": "4/0A..." }` -> `signed_in: true`
Google はコードを「その URL を発行したサインインフロー」に紐付けるため、URL を表示した CLI
プロセスはプロンプトで待機したまま保持され、2 回目の呼び出しが同じプロセスへコードを入力
します。待機は 15 分(`PENDING_PROMPT_TTL`)で失効するので、過ぎた場合は 2. からやり直して
ください。
Start the server on a given account with `--colab-account NAME` or
`COLAB_CLI_MCP_COLAB_ACCOUNT=NAME`.
Google allows one Colab runtime assignment per account, so separate accounts are
also the way to run more than one runtime at a time.
## Session lifetime and the keep-alive daemon
`colab new` starts a detached keep-alive process (`colab keep-alive`, recorded as
`keep_alive_pid`) that pings `/tun/m/<endpoint>/keep-alive/` every 60 seconds. It
is detached from any terminal, so closing the shell does not end the session -
but it lives inside this container, so `docker compose down`, a restart or an
image update kills it, and Colab then idles the runtime out.
The daemon also stops on its own after 24 hours (`time_limit_reached`), when the
local session record disappears (`session_not_found`), when the endpoint changes
(`endpoint_mismatch`), or after two consecutive 4xx replies
(`consecutive_4xx_errors`, usually a missing `colaboratory` OAuth scope). Check
`session_log` for the `keep_alive_stopped` event and its reason.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues