---
name: Asana MCP Integration
overview: Asana公式MCP V2 + ローカルMCPガードサーバーのハイブリッド構成で、Cursor Agent から自然言語でAsanaのポートフォリオ/プロジェクト/タスク管理を安全に実行する基盤を構築する。
todos:
- id: step1-nodejs
content: Node.js LTS 通常版インストール (winget install OpenJS.NodeJS.LTS / 管理者権限あり)
status: pending
- id: step2-pat
content: Asana PAT 発行 + keyring 保管 + users/me API で認証確認
status: pending
- id: step3-venv
content: Python venv 作成 + MCP SDK/httpx/keyring 等の依存インストール
status: pending
- id: step4-oauth
content: Asana Developer Console で MCP App (OAuth) 作成 + Client ID/Secret 保管
status: pending
- id: step5-mcp-config
content: .cursor/mcp.json 作成 + 公式 MCP V2 接続確認
status: pending
- id: step6-local-server
content: ローカル MCP サーバー MVP 実装 (delete guard + 監査ログ)
status: pending
- id: step7-cursor-rules
content: .cursor/rules/asana-operations.mdc 作成 (Agent 行動規範)
status: pending
- id: step8-e2e
content: E2E 動作確認 (タスク作成→削除の一連フロー)
status: pending
isProject: false
---
# Asana MCP ハイブリッド実行基盤 構築計画
---
## 環境調査結果 (確定事項)
| 項目 | 状態 |
| ---------------- | --------------------------------------------------------- |
| OS | Windows 10 (10.0.26100) |
| Python | 3.12.9 (pip 25.2) |
| Node.js / npm | **未インストール** → LTS 通常版をインストール予定 (管理者権限あり) |
| 管理者権限 | **あり** |
| プロキシ | `http://c000a10-vip.cosmo-oil.co.jp:12080` (HTTP/HTTPS共通) |
| keyring | インストール済 (Windows Credential Manager 利用可) |
| httpx / requests | インストール済 |
| cryptography | 46.0.4 インストール済 |
| 既存MCP設定 | なし |
---
## 1) 全体アーキテクチャ設計
```mermaid
flowchart TB
subgraph CursorIDE [Cursor IDE]
Agent[Agent Mode]
MCPConfig[".cursor/mcp.json"]
end
subgraph OfficialMCP [公式MCP V2 - 日常操作]
MCPRemote["mcp-remote (npx)"]
AsanaMCPV2["Asana MCP V2\nhttps://mcp.asana.com/v2/mcp"]
end
subgraph LocalMCP [ローカルMCP - ガード付き操作]
LocalServer["asana-guard-server\n(Python / stdio)"]
DryRun[dry-run]
TwoStep[二段階確認]
AuditLog[監査ログ]
NamingPolicy[命名規則]
end
subgraph AsanaCloud [Asana Cloud]
AsanaAPI["REST API\napp.asana.com/api/1.0"]
AsanaData["Portfolios / Projects / Tasks"]
end
subgraph Security [セキュリティ層]
WinCredMgr["Windows Credential Manager\n(keyring)"]
Proxy["Corporate Proxy\n:12080"]
end
Agent --> MCPConfig
MCPConfig -->|stdio| MCPRemote
MCPConfig -->|stdio| LocalServer
MCPRemote -->|OAuth| AsanaMCPV2
AsanaMCPV2 --> AsanaData
LocalServer -->|PAT / OAuth| AsanaAPI
AsanaAPI --> AsanaData
MCPRemote --> Proxy
LocalServer --> Proxy
LocalServer --> WinCredMgr
LocalServer --> DryRun
LocalServer --> TwoStep
LocalServer --> AuditLog
LocalServer --> NamingPolicy
```
### 公式MCP V2 (日常操作)
- **接続方式**: stdio経由で `npx mcp-remote https://mcp.asana.com/v2/mcp` を起動
- **認証方式**: OAuth 2.0 (Asana Developer Console で MCP App を作成)
- **責務**: 閲覧、タスク作成・更新、プロジェクト作成・更新、検索
- **ツール一覧確認**: 接続後に Cursor の Settings > Tools & MCP で確認、または Agent に `tools/list` を要求
- **制約**: Node.js が必要 (管理者権限ありのため LTS 通常版をインストール)
### ローカルMCP (ガード付き操作)
- **ホスティング**: ローカルPC (stdio接続)、将来はコンテナ/社内サーバへ移行可能
- **言語**: **Python 3.12** (理由: 環境に既存、keyring/httpx等の依存済み、MCP Python SDK対応)
- **責務**: 削除操作、一括更新、命名規則強制、監査ログ、dry-run
- **APIツール一覧** (後述の Section 3 で詳細):
- `asana_delete_task` / `asana_delete_project` (二段階確認付き)
- `asana_bulk_update` (dry-run + 確認)
- `asana_validate_naming` (命名規則チェック)
- `asana_audit_search` (監査ログ検索)
- `asana_preview_changes` (dry-run プレビュー)
### Cursor側 MCP設定
設定ファイル: `[.cursor/mcp.json](.cursor/mcp.json)` (プロジェクトレベル)
```json
{
"mcpServers": {
"asana-official": {
"command": "npx",
"args": [
"-y", "mcp-remote",
"https://mcp.asana.com/v2/mcp"
],
"env": {
"HTTPS_PROXY": "http://c000a10-vip.cosmo-oil.co.jp:12080"
}
},
"asana-guard": {
"command": "python",
"args": ["${workspaceFolder}/mcp-local-server/src/server.py"],
"env": {
"ASANA_WORKSPACE": "${env:ASANA_WORKSPACE}",
"HTTPS_PROXY": "http://c000a10-vip.cosmo-oil.co.jp:12080",
"LOG_DIR": "${workspaceFolder}/logs"
}
}
}
}
```
**注意**: シークレット (PAT, client_secret) は `mcp.json` に直接書かず、`keyring` 経由で取得。
---
## 2) Asana認証 (OAuth / PAT) 手順
### 2-A. PAT (Personal Access Token) -- MVP用 (即座に利用可能)
ローカルMCPの REST API 呼び出しに使用。最も手軽だが、ユーザー個人の全権限が付与される。
**手順**:
1. ブラウザで [https://app.asana.com/0/my-apps](https://app.asana.com/0/my-apps) を開く
2. 「Create token」をクリック
3. トークン名: `cursor-local-mcp-guard` と入力
4. 生成されたトークンをコピー (この画面を閉じると二度と表示されない)
5. PowerShell でWindows Credential Manager に保存:
```powershell
python -c "import keyring; keyring.set_password('asana-mcp', 'pat', input('PAT: '))"
```
1. 動作確認:
```powershell
python -c "
import keyring, httpx
pat = keyring.get_password('asana-mcp', 'pat')
r = httpx.get('https://app.asana.com/api/1.0/users/me',
headers={'Authorization': f'Bearer {pat}'},
proxy='http://c000a10-vip.cosmo-oil.co.jp:12080')
print(r.json()['data']['name'])
"
```
### 2-B. OAuth App (公式MCP V2用)
**Asana Developer Console での作成手順**:
1. [https://app.asana.com/0/my-apps](https://app.asana.com/0/my-apps) にアクセス
2. 「Create new app」> アプリタイプ「**MCP app**」を選択
3. 入力項目:
- App name: `Cursor MCP Integration`
- Redirect URL: `http://localhost:3334/callback` (mcp-remote のデフォルト)
- Workspace distribution: 利用するWorkspaceを選択
4. 作成後に取得:
- **Client ID**: メモ (公開値)
- **Client Secret**: Windows Credential Manager に保存:
```powershell
python -c "import keyring; keyring.set_password('asana-mcp', 'client_secret', input('Secret: '))"
```
1. スコープ設計 (最小権限):
- `default` (MCP Appの場合、ユーザーのAsana権限に準拠)
**動作確認**: Cursor を再起動し、Agent に「Asanaのワークスペース一覧を教えて」と指示。OAuth認証ブラウザフローが起動すれば成功。
### 2-C. トークン保管方針
| レイヤ | 保管先 | 方式 |
| -------- | ------------------------------------- | ----------------- |
| MVP (暫定) | Windows Credential Manager | `keyring` ライブラリ経由 |
| 将来 | Azure Key Vault / HashiCorp Vault | SDK経由で取得 |
| 禁止 | `.env` ファイル平文、コード内ハードコード、`mcp.json` 内 | - |
**暫定措置としてローカル保管する場合**: `keyring` (Windows Credential Manager) を使う。DPAPI で暗号化され、ログインユーザーのみ復号可能。`.env` は `.env.example` (値なし) のみリポジトリに含める。
---
## 3) ローカルMCP (ガード付き) 実装計画
### 言語選定: Python 3.12
| 候補 | 利点 | 欠点 | 結論 |
| ---------- | ------------------------------------------- | ----------------------- | ------------------------------ |
| **Python** | 環境に既存、keyring/httpx/cryptography済、MCP SDK対応 | 型安全性がGoより弱い | **採用** |
| Node.js | MCP SDK が最も成熟、LTSインストール予定 | 依存が二重管理になる (公式MCPのみで使用) | ローカルMCPには不採用 (公式MCP接続用として別途利用) |
| Go | 型安全、バイナリ配布容易 | MCP SDK未成熟、環境構築が必要 | 不採用 |
### 機能要件 (ツール一覧)
**削除系 (二段階確認必須)**:
- `guard_delete_task(task_gid)` -> プレビュー返却 + 確認トークン発行
- `guard_confirm_delete_task(task_gid, confirm_token)` -> 実削除
- `guard_delete_project(project_gid)` -> 同上
- `guard_confirm_delete_project(project_gid, confirm_token)` -> 同上
**一括操作 (dry-run 必須)**:
- `guard_bulk_update(targets, changes, dry_run=true)` -> 差分プレビュー
- `guard_bulk_move_tasks(task_gids, dest_project, dry_run=true)` -> 移動プレビュー
**命名規則**:
- `guard_validate_name(entity_type, name)` -> ポリシー適合チェック
- `guard_create_project_safe(name, ...)` -> 命名規則チェック後に作成
**監査**:
- `guard_audit_log(filter)` -> 監査ログ検索
- 全操作が自動で JSONL ファイルに記録される
**二段階確認フロー (実装パターン)**:
```mermaid
sequenceDiagram
participant Agent
participant GuardMCP as Guard MCP Server
participant Asana as Asana REST API
Agent->>GuardMCP: guard_delete_task(task_gid)
GuardMCP->>Asana: GET /tasks/{gid} (詳細取得)
Asana-->>GuardMCP: タスク詳細
GuardMCP-->>Agent: プレビュー + confirm_token (TTL 60s)
Note over Agent: ユーザーに確認を求める
Agent->>GuardMCP: guard_confirm_delete(task_gid, confirm_token)
GuardMCP->>GuardMCP: トークン検証 + 監査ログ記録
GuardMCP->>Asana: DELETE /tasks/{gid}
Asana-->>GuardMCP: 204 No Content
GuardMCP-->>Agent: 削除完了 + ロールバック情報
```
### 非機能要件
**プロキシ対応**:
- `httpx` の `proxy` パラメータに `HTTPS_PROXY` 環境変数を利用
- カスタムCA証明書: `httpx.Client(verify="/path/to/ca-bundle.crt")` で対応
- タイムアウト: 接続 10s / 読取 30s
**レート制限/リトライ**:
- Asana API: 有料 1,500 req/min、無料 150 req/min
- 429応答時: `Retry-After` ヘッダに従い exponential backoff (最大3回)
- 冪等性: 操作前に GET で現在状態を確認し、既に完了していればスキップ
**ログ出力**:
- 形式: JSONL (`logs/audit_YYYYMMDD.jsonl`)
- 各エントリ: `{timestamp, user, tool, params, asana_gid, result, error, duration_ms}`
- シークレットマスキング: トークン値をログに出力しない
- 将来: SIEM連携 (Splunk/Sentinel) は JSONL をそのまま取り込み可能
---
## 4) "メリット両取り" 運用設計
### 操作の振り分けルール
| 操作 | 担当MCP | 理由 |
| ------------------- | ---------------------- | ------------ |
| タスク/プロジェクトの閲覧・検索 | 公式 V2 | 標準操作、ガード不要 |
| タスク作成・単体更新 | 公式 V2 | 標準操作 |
| プロジェクト作成 | ローカル (命名規則チェック) | ポリシー強制 |
| **削除** (タスク/プロジェクト) | **ローカル (必須)** | 二段階確認 |
| **一括更新/移動** | **ローカル (必須)** | dry-run + 確認 |
| ポートフォリオ操作 | 公式 V2 (閲覧) / ローカル (変更) | 影響範囲大の変更はガード |
### Agent 行動規範
Cursor Rules (`[.cursor/rules/asana-operations.mdc](.cursor/rules/asana-operations.mdc)`) に以下を定義:
```
- 「削除」「remove」「一括」「bulk」「全件」「all」を含む指示 → asana-guard MCP を使用
- プロジェクト新規作成 → asana-guard の guard_create_project_safe を使用
- 上記以外 → asana-official MCP を使用
- 削除操作は必ず: プレビュー表示 → ユーザー承認 → 実行 の3ステップ
```
### 承認フロー
1. ユーザーが自然言語で指示 (例: 「タスクXを削除して」)
2. Agent が `guard_delete_task` を呼び出し → プレビュー取得
3. Agent がプレビューをユーザーに表示し承認を求める
4. ユーザーが承認 → Agent が `guard_confirm_delete_task` を呼び出し
5. 監査ログに記録
### 監査・レビュー
- `logs/` ディレクトリの JSONL を定期確認 (週次)
- 月次: PAT/OAuthスコープの棚卸し
- 四半期: 命名規則ポリシーの見直し
---
## 5) テスト計画
### 機能テスト
- ポートフォリオ: 一覧取得、項目追加/削除
- プロジェクト: 作成 (命名規則OK/NG)、更新、削除 (二段階確認)
- タスク: CRUD、サブタスク、プロジェクト間移動
- 曖昧性: 同名プロジェクト存在時の候補提示
- 権限不足: 403応答時のエラーメッセージ
- リトライ: 429応答時の backoff 動作
### セキュリティテスト
- `keyring` からのトークン取得/保管が正常動作
- 監査ログにトークン値が出力されないこと
- `.env` ファイルにシークレットが含まれないこと
- PAT の最小権限確認 (不要な操作が拒否されること)
### 運用テスト
- プロキシ環境下での全操作の疎通確認
- ネットワーク断: タイムアウト + リトライ動作
- Asana側障害 (5xx): エラーメッセージとリトライ
- レート制限: 大量リクエスト時の 429 ハンドリング
---
## 6) 構築手順チェックリスト
### Step 1: Node.js LTS 通常版インストール (公式MCP V2 用)
- **作業**: Node.js LTS 通常版のインストール (管理者権限あり)
- **コマンド**:
```powershell
winget install OpenJS.NodeJS.LTS
```
- **代替**: winget が使えない場合 → [https://nodejs.org](https://nodejs.org) から `.msi` インストーラーをダウンロードして管理者権限で実行
- **完了条件**: 新しいターミナルで以下が全て成功すること
```powershell
node --version # v22.x.x 以上
npm --version # 10.x.x 以上
npx --version # 10.x.x 以上
```
- **トラブル**: インストール後に `node` が認識されない → ターミナルを再起動 (PATH反映のため)。それでも不可の場合は `$env:PATH` に `C:\Program Files\nodejs\` を手動追加
### Step 2: Asana PAT 取得とローカル保管
- **作業**: Asana Developer Console で PAT 発行 → keyring 保管
- **コマンド**: 上記 Section 2-A の手順
- **完了条件**: `users/me` API が自分の名前を返す
- **トラブル**: プロキシでブロックされる場合 → ブラウザでは Asana にアクセスできることを確認、`httpx` に `proxy` を明示的に指定
### Step 3: Python 仮想環境 + 依存インストール
- **作業**: venv 作成、MCP SDK とAsanaクライアント依存をインストール
- **コマンド**:
```powershell
cd c:\Users\11250150\REFACT\Asana_MCP_RestAPI
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install mcp httpx keyring pydantic pyyaml
pip freeze > requirements.txt
```
- **完了条件**: `python -c "import mcp; print(mcp.__version__)"` が成功
- **トラブル**: プロキシ → `pip install --proxy http://c000a10-vip.cosmo-oil.co.jp:12080 ...`
### Step 4: ローカルMCPサーバー実装 (MVP)
- **作業**: `mcp-local-server/src/server.py` に最小構成 (delete guard のみ) を実装
- **完了条件**: `python server.py` で stdio MCP サーバーが起動し、Cursor から tools が見える
### Step 5: Cursor MCP 設定
- **作業**: `.cursor/mcp.json` を作成
- **完了条件**: Cursor 再起動後、Settings > Tools & MCP に `asana-official` と `asana-guard` が表示
### Step 6: Asana OAuth App 作成 (公式MCP V2 用)
- **作業**: 上記 Section 2-B の手順
- **完了条件**: Cursor Agent 経由で Asana ワークスペース情報を取得できる
### Step 7: 動作確認 (E2E)
- **作業**: 「テストタスクを作成して」→「削除して」の一連操作
- **完了条件**: 作成は公式MCP、削除はローカルMCP経由で二段階確認付きで完了
---
## 7) 成果物一覧 (ファイル構成)
```
Asana_MCP_RestAPI/
+-- .cursor/
| +-- mcp.json # MCP サーバー設定
| +-- rules/
| +-- asana-operations.mdc # Agent 行動規範
+-- mcp-local-server/
| +-- src/
| | +-- server.py # MCP サーバー本体
| | +-- tools/
| | | +-- delete_guard.py # 削除ガード (二段階確認)
| | | +-- bulk_operations.py # 一括操作 + dry-run
| | | +-- naming_policy.py # 命名規則チェック
| | +-- asana_client.py # Asana REST API ラッパー
| | +-- auth.py # keyring 連携トークン管理
| | +-- config.py # 設定ローダー
| | +-- audit_logger.py # 監査ログ出力
| | +-- rate_limiter.py # レート制限/リトライ
| +-- tests/
| | +-- test_delete_guard.py
| | +-- test_naming_policy.py
| +-- pyproject.toml
+-- configs/
| +-- .env.example # テンプレート (値なし)
| +-- naming_rules.yaml # 命名規則定義
| +-- policies.yaml # 操作ポリシー
+-- scripts/
| +-- setup_auth.py # PAT/OAuth セットアップヘルパー
| +-- verify_connection.py # 接続確認スクリプト
+-- logs/ # 監査ログ (.gitignore対象)
+-- docs/
| +-- RUNBOOK.md # 障害時対応手順
| +-- SECURITY.md # セキュリティポリシー
+-- .gitignore
+-- requirements.txt
+-- README.md
```
---
## 8) ロードマップ: MVP → Perfect
### MVP (1-2週間)
- Node.js LTS 通常版インストール (管理者権限で実行)
- Asana PAT 取得 + keyring 保管
- 公式 MCP V2 接続 (mcp-remote)
- ローカル MCP: **削除ガードのみ** (`guard_delete_task`, `guard_confirm_delete_task`)
- 監査ログ (JSONL) の最小実装
- `.cursor/mcp.json` + `.cursor/rules/asana-operations.mdc`
- E2E 動作確認
### Perfect (1-3ヶ月)
- 一括更新 + dry-run 機能
- 命名規則の強制 (YAML ポリシーファイル)
- OAuth App による認証 (PAT から移行)
- Azure Key Vault / HashiCorp Vault 連携
- 完全な監査ログ (SIEM連携対応)
- 承認フロー (Slack/Teams 通知連携)
- CI (pytest + linter + セキュリティスキャン)
- テスト自動化 (モック Asana API)
- コンテナ化 (Docker) + 社内サーバーデプロイ
- RUNBOOK / SECURITY.md 完備
---
## リスクと対策
| リスク | 影響 | 対策 |
| --------------------------------------- | ---------- | ----------------------------------------------------------- |
| Node.js インストール後の PATH 不整合 | npx が起動しない | ターミナル再起動、PATH 手動追加、Cursor 完全再起動 |
| プロキシによるSSL検証エラー | API接続失敗 | 社内CA証明書を `httpx` の `verify` に指定 / `REQUESTS_CA_BUNDLE` 環境変数 |
| Asana API レート制限 | 一括操作失敗 | exponential backoff + チャンク分割 (50件ずつ) |
| PAT 漏洩 | 全権限でのアクセス | keyring (DPAPI暗号化)、`.gitignore` 徹底、監査ログで異常検知 |
| 誤削除 | データ消失 | 二段階確認必須、プレビューにタスク名/プロジェクト名を表示 |
| mcp-remote と Asana MCP V2 の OAuth フロー失敗 | 公式MCP使用不可 | PAT を使う REST API 直接呼び出しにフォールバック |
---
## 次に実施すべき最初の5アクション
1. **Node.js LTS 通常版をインストール** → `winget install OpenJS.NodeJS.LTS` を管理者権限で実行 → `node --version` / `npm --version` / `npx --version` で確認
2. **Asana Developer Console で PAT を発行** → PowerShell で `keyring` に保管し、`users/me` API で認証確認
3. **Python 仮想環境を作成** → `python -m venv .venv` で依存を分離し、`pip install mcp httpx keyring pydantic pyyaml` を実行
4. **Asana Developer Console で MCP App (OAuth) を作成** → Client ID / Secret を取得し keyring に保管
5. `**.cursor/mcp.json` を作成して Cursor を再起動** → 公式MCP V2 の接続を確認