Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .github/workflows/claude.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Claude Code

on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]

jobs:
claude:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
actions: read # Required for Claude to read CI results on PRs
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 1

- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}

# Optional: Customize the trigger phrase (default: @claude)
# trigger_phrase: "/claude"

# Optional: Trigger when specific user is assigned to an issue
# assignee_trigger: "claude-bot"

# Optional: Configure Claude's behavior with CLI arguments
# claude_args: |
# --model claude-opus-4-1-20250805
# --max-turns 10
# --allowedTools "Bash(npm install),Bash(npm run build),Bash(npm run test:*),Bash(npm run lint:*)"
# --system-prompt "Follow our coding standards. Ensure all new code has tests. Use TypeScript for new files."

# Optional: Advanced settings configuration
# settings: |
# {
# "env": {
# "NODE_ENV": "test"
# }
# }
25 changes: 25 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,31 @@

`gws` is a Rust CLI tool for interacting with Google Workspace APIs. It dynamically generates its command surface at runtime by parsing Google Discovery Service JSON documents.

> [!NOTE]
> This is a fork of [googleworkspace/cli](https://github.com/googleworkspace/cli) maintained by **HODL1** (kushim-team).
> This is **not** an officially supported Google product.

### Fork Branch Strategy

This repository is a fork of [googleworkspace/cli](https://github.com/googleworkspace/cli) with the following branch strategy:

| Branch | Purpose |
|--------|---------|
| `main` | Kept in sync with upstream `googleworkspace/cli` main. No custom changes. |
| `custom` | All HODL1-specific changes are developed here. |

#### Syncing with upstream

```bash
git fetch upstream
git checkout main
git merge upstream/main
git checkout custom
git merge main
```

Upstream updates are merged (not rebased) into `custom` to preserve a clean, shared-friendly history.
Comment on lines +7 to +30
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

フォークのブランチ戦略とアップストリームとの同期に関するこの情報は、README.mdにも存在します。情報の重複を避け、メンテナンスを容易にするために、この情報を一箇所(例えば開発者向けガイドであるこのAGENTS.md)に集約し、もう一方のファイルからはリンクするようにしてはいかがでしょうか。


> [!IMPORTANT]
> **Dynamic Discovery**: This project does NOT use generated Rust crates (e.g., `google-drive3`) for API interaction. Instead, it fetches the Discovery JSON at runtime and builds `clap` commands dynamically. When adding a new service, you only need to register it in `src/services.rs` and verify the Discovery URL pattern in `src/discovery.rs`. Do NOT add new crates to `Cargo.toml` for standard Google APIs.

Expand Down
1 change: 1 addition & 0 deletions CLAUDE.md
46 changes: 45 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,33 @@
<h1 align="center">gws</h1>
<h1 align="center">gws (HODL1 Fork)</h1>

**One CLI for all of Google Workspace — built for humans and AI agents.**<br>
Drive, Gmail, Calendar, and every Workspace API. Zero boilerplate. Structured JSON output. 40+ agent skills included.

> [!NOTE]
> This is a fork of [googleworkspace/cli](https://github.com/googleworkspace/cli) maintained by **HODL1** (kushim-team).
> This is **not** an officially supported Google product.

## Fork Branch Strategy

This repository is a fork of [googleworkspace/cli](https://github.com/googleworkspace/cli) with the following branch strategy:

| Branch | Purpose |
|--------|---------|
| `main` | Kept in sync with upstream `googleworkspace/cli` main. No custom changes. |
| `custom` | All HODL1-specific changes are developed here. |

### Syncing with upstream

```bash
git fetch upstream
git checkout main
git merge upstream/main
git checkout custom
git merge main
```

Upstream updates are merged (not rebased) into `custom` to preserve a clean, shared-friendly history.

<p>
<a href="https://www.npmjs.com/package/@googleworkspace/cli"><img src="https://img.shields.io/npm/v/@googleworkspace/cli" alt="npm version"></a>
<a href="https://github.com/googleworkspace/cli/blob/main/LICENSE"><img src="https://img.shields.io/github/license/googleworkspace/cli" alt="license"></a>
Expand Down Expand Up @@ -363,6 +385,28 @@ cargo test # unit tests
./scripts/coverage.sh # HTML coverage report → target/llvm-cov/html/
```

### AI-DLC 開発サイクル

本プロジェクト (HODL1 fork) では [AI-DLC (AI-Driven Development Life Cycle)](https://aws.amazon.com/jp/blogs/devops/ai-driven-development-life-cycle/) に基づく開発サイクルを採用しています。

各フィーチャーの中間成果物は `specs/<feature-name>/` に配置します。

```
specs/
remote-mcp-gateway/
requirements.md # Inception: 要件定義
design.md # Inception → Construction: 設計・決定事項
tasks.md # Construction: 実装タスクのブレイクダウン
```

**開発の流れ:**

1. **Inception** — 要件を `requirements.md` に整理し、設計判断を `design.md` にまとめる
2. **Construction** — `tasks.md` のタスクリストに従い実装する。AI エージェントは specs を読んでコンテキストを得る
3. **Operations** — デプロイ・運用に関する知見を specs にフィードバックする

新しいフィーチャーを始めるときは `specs/<feature-name>/` ディレクトリを作成し、同じ 3 ファイル構成で進めてください。

## License

Apache-2.0
Expand Down
155 changes: 155 additions & 0 deletions specs/remote-mcp-gateway/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# Remote MCP Gateway - Design

## アーキテクチャ概要

```
┌─────────────────────────┐
│ Claude Desktop / │
│ Claude Code │
│ (各メンバーの端末) │
└───────────┬─────────────┘
│ MCP (Streamable HTTP)
│ + セッショントークン
┌───────────────────────────────────┐
│ MCP Gateway (Cloud Run) │
│ │
│ ┌─────────┐ ┌───────────────┐ │
│ │ 認証層 │ │ 権限制御層 │ │
│ │ OAuth2 │ │ メソッドID │ │
│ │ Google │ │ ホワイトリスト │ │
│ └────┬────┘ └───────┬───────┘ │
│ │ │ │
│ ┌────▼───────────────▼───────┐ │
│ │ 実行層 │ │
│ │ gws コア (Discovery JSON │ │
│ │ → API 呼び出し) │ │
│ └────────────┬───────────────┘ │
│ │ │
│ ┌────────────▼───────────────┐ │
│ │ ログ層 │ │
│ │ Cloud Logging │ │
│ └────────────────────────────┘ │
└───────────────────────────────────┘
Google Workspace API
```

## 決定事項

| 項目 | 決定 | 理由 |
|------|------|------|
| MCP トランスポート | Streamable HTTP | 組織コネクタに必要 |
| 認証方式 | MCP OAuth フロー + Google OAuth 兼用 | 1回のログインで MCP 認証と Google API 認可を両立 |
| 権限粒度 | Discovery JSON メソッド ID 単位 | Google 公式の命名体系をそのまま利用でき、自前定義不要 |
| 権限デフォルト | 未登録ユーザーは何もできない | セキュリティ優先 |
| tools/list | ユーザー権限でフィルタ | エージェントの不要な試行を防止 |
| OAuth トークン保管 | サーバー側保持 | 組織コネクタの仕組み上クライアント送信は不可 |
| 権限設定 | Git リポジトリ内 YAML | PR レビューで変更管理、DB 不要 |
| 管理方法 | YAML 編集 → PR → マージ → 再デプロイ | エンジニア向け、変更履歴が残る |
| デプロイ先 | Cloud Run (GCP) | コンテナ化、スケーリング、IAM 連携 |
| 利用統計 | Cloud Logging | 20名規模なら十分 |
| OAuth スコープ | 全サービス一括要求 | 権限制御は自前レイヤーで絞る |

## 認証フロー

```
1. ユーザーが Claude 上でコネクタを初回利用
2. Claude が MCP Gateway の認可エンドポイントにリダイレクト
3. MCP Gateway が Google OAuth 同意画面を表示
4. ユーザーが自分の Google アカウントで同意
5. MCP Gateway が Google OAuth トークンをサーバー側に保存
6. MCP Gateway がセッショントークンを発行し Claude に返す
7. 以降、Claude はセッショントークンを MCP リクエストに付与
8. MCP Gateway はセッショントークンからユーザーを特定し、
保存済みの Google OAuth トークンで API を呼び出す
```

## 権限制御

### メソッド ID

Discovery JSON で Google が公式に定義する一意識別子。

| メソッド ID | 操作内容 |
|-------------|----------|
| `gmail.users.messages.list` | メール一覧取得 |
| `gmail.users.messages.get` | メール取得 |
| `gmail.users.messages.send` | メール送信 |
| `drive.files.list` | ファイル一覧取得 |
| `drive.files.get` | ファイル取得 |
| `drive.files.create` | ファイル作成 |

### ワイルドカード

- `*` — 全メソッド許可
- `gmail.*` — Gmail の全メソッド許可
- `gmail.users.messages.*` — Gmail メッセージ関連の全メソッド許可

### 権限設定ファイル

```yaml
# config/permissions.yaml

roles:
admin:
allow:
- "*"

workspace-reader:
allow:
- "gmail.users.messages.list"
- "gmail.users.messages.get"
- "gmail.users.labels.list"
- "drive.files.list"
- "drive.files.get"
- "calendar.events.list"
- "calendar.events.get"

gmail-full:
allow:
- "gmail.*"

users:
admin@company.com:
role: admin

tanaka@company.com:
role: workspace-reader

suzuki@company.com:
role: gmail-full
```

### リクエスト処理フロー

```
1. Claude から MCP リクエスト受信
2. セッショントークンからユーザーを特定
3. リクエストされたメソッド ID を権限設定と照合
4. 許可されていれば実行、拒否ならエラーを返す
```

## データストア

| データ | 保存先 | 備考 |
|--------|--------|------|
| 権限設定 (YAML) | Git リポジトリ → コンテナイメージに同梱 | PR レビューで変更管理 |
| OAuth トークン | Secret Manager または暗号化ストレージ | 機密情報 |
| 利用ログ | Cloud Logging | 構造化ログ |

## 利用統計

### 記録項目

| 項目 | 例 |
|------|-----|
| ユーザー email | tanaka@company.com |
| タイムスタンプ | 2026-03-05T10:30:00Z |
| メソッド ID | gmail.users.messages.list |
| 成功/失敗 | success |

### 基盤

Cloud Logging に構造化ログとして出力。必要に応じて BigQuery にエクスポートし可視化。
41 changes: 41 additions & 0 deletions specs/remote-mcp-gateway/requirements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Remote MCP Gateway - Requirements

## 背景

会社で契約している Claude Desktop / Claude Code から Google Workspace API を安全に利用したい。
gws を Claude for Business/Enterprise の組織コネクタ(Integrations)として全社配布する。

## ユーザー

- 社員約20名
- 管理者ユーザー: 権限設定を管理する
- 通常ユーザー: 許可された操作のみ実行する

## 要件

### R1: 組織コネクタとしての配布

- Claude 管理コンソールから組織コネクタとして登録し、全メンバーに自動配布する
- メンバーは Claude Desktop / Claude.ai 上でコネクタを利用開始できる

### R2: Google アカウントによる認証

- 各メンバーが自分の Google アカウントで OAuth し、MCP 経由で Google Workspace を操作する
- MCP Gateway への認証と Google API への認可を 1 回の Google OAuth ログインで兼用する

### R3: ホワイトリスト方式の権限制御

- 管理者が通常ユーザーに対して、実行可能な操作をホワイトリスト方式で設定する
- 権限の粒度は Google Discovery JSON のメソッド ID 単位(例: `gmail.users.messages.send`)
- 未登録ユーザーは何もできない
- MCP の `tools/list` はユーザーに許可されたメソッドのみ返す(エージェントが不許可操作を試みること自体を防ぐ)

### R4: 利用統計

- 各ユーザーの利用状況(誰が・いつ・どの操作を・何回呼んだか)を記録する
- 目的は活用度の把握

## 非機能要件

- GCP 上でホストする
- 20名規模に対応できればよい(大規模スケーリングは不要)
Loading