コンテンツにスキップ

3. Gmailと連携するエージェント

ボールトに追加する認証情報には、1. コンソールでエージェントを作成で使った「Bearerトークン」のほかに、「MCP OAuth」というタイプがあります。OAuth認証を使うMCPサーバー向けのタイプで、コンソールにはGmailhttps://gmailmcp.googleapis.com/mcp/v1)などのプリセットが用意されています。

このページでは、Gmailの下書きを作ってくれるエージェントを作成します。あわせて、ツールの実行前にユーザーの承認を求める 権限ポリシー(always_ask も体験します。

1. コンソールでGmailを「接続」する

Section titled “1. コンソールでGmailを「接続」する”

Bearerトークンと違い、MCP OAuthのプリセットでは、OAuthの認可フローをコンソールが代行してくれます。

  1. 「認証情報ボールト」でボールトを開き、「クレデンシャルを追加」をクリックします。

  2. タイプに「MCP OAuth」を選択し、MCPサーバーのプリセットから「Gmail」を選択します。

  3. 注意事項に同意して「接続」をクリックすると、Googleの認可画面が開きます。アカウントを選んで許可します。

  4. トークンがボールトに保管されます。有効期限が切れたときの更新もAnthropicが自動で行います。

プロジェクトを作成し、そのフォルダーに移動して、Claude SDKをインストールします。

Terminal window
uv init gmail-agent
cd gmail-agent
uv add anthropic
  1. プロジェクトのフォルダーにsetup_gmail.pyを作成し、以下の内容を保存します。

    setup_gmail.py
    import json
    from anthropic import Anthropic
    client = Anthropic()
    ###############################
    # 1. Gmailの認証情報が入ったボールトを探す
    ###############################
    gmail_vault_id = None
    for vault in client.beta.vaults.list():
    for cred in client.beta.vaults.credentials.list(vault_id=vault.id):
    url = getattr(cred.auth, "mcp_server_url", "") or ""
    if "gmailmcp.googleapis.com" in url:
    gmail_vault_id = vault.id
    print(f"Gmail認証情報を発見: vault={vault.id} ({vault.display_name}) / credential={cred.id}")
    break
    if gmail_vault_id:
    break
    if not gmail_vault_id:
    raise SystemExit("Gmailの認証情報が見つかりません。コンソールのボールトで「接続」してください。")
    ###############################
    # 2. 環境を作成(MCPサーバーへのネットワークアクセスを許可)
    ###############################
    environment = client.beta.environments.create(
    name="Gmail-environment",
    config={
    "type": "cloud",
    "networking": {"type": "limited", "allow_mcp_servers": True},
    },
    )
    print(f"environment: {environment.id}")
    ###############################
    # 3. エージェントを作成(権限ポリシーは always_ask = 実行前に承認を求める)
    ###############################
    agent = client.beta.agents.create(
    name="Gmail Agent",
    model={"id": "claude-haiku-4-5", "speed": "standard"},
    description="Gmailの検索・要約・下書き作成を行うエージェント。",
    system="あなたはGmailを扱うアシスタントです。メールの内容を要約するときは、送信者・件名・要点を簡潔にまとめてください。日本語で応答してください。",
    mcp_servers=[{"name": "gmail", "type": "url", "url": "https://gmailmcp.googleapis.com/mcp/v1"}],
    tools=[
    {
    "type": "mcp_toolset",
    "mcp_server_name": "gmail",
    "default_config": {
    "enabled": True,
    "permission_policy": {"type": "always_ask"},
    },
    }
    ],
    )
    print(f"agent: {agent.id}")
    with open("ids_gmail.json", "w") as f:
    json.dump(
    {
    "vault_id": gmail_vault_id,
    "environment_id": environment.id,
    "agent_id": agent.id,
    },
    f,
    indent=2,
    )
    print("IDをids_gmail.jsonに保存しました")

    ポイントは2つです。

    • ボールトの自動検出 ・・・ ボールトと認証情報を一覧し、GmailのMCPサーバーURLを持つクレデンシャルが入ったボールトを探しています。手順1でコンソールから作った認証情報も、コードからは他の認証情報と同じように参照できることが分かります
    • permission_policy: always_ask ・・・ これまでのalways_allowと違い、エージェントがツールを実行する前に承認を求めて一時停止する設定です。メールという実データを扱うので、安全側に倒しています
  2. スクリプトを実行します。

    Terminal window
    uv run setup_gmail.py
    Gmail認証情報を発見: vault=vlt_011Cch75YvJtEDJBgShwtgfb (Vault) / credential=vcrd_01Cwkza...
    environment: env_01RcwVQvCdgfidJqSN32Ypua
    agent: agent_01Rs4ReLgJkee8xkX18Mdxpp
    IDをids_gmail.jsonに保存しました
  1. プロジェクトのフォルダーにrun_gmail.pyを作成し、以下の内容を保存します。

    run_gmail.py
    import json
    from anthropic import Anthropic
    client = Anthropic()
    with open("ids_gmail.json") as f:
    ids = json.load(f)
    ###############################
    # 1. セッションを作成(エージェント・環境・Gmailのボールトを組み合わせる)
    ###############################
    session = client.beta.sessions.create(
    agent=ids["agent_id"],
    environment_id=ids["environment_id"],
    vault_ids=[ids["vault_id"]],
    )
    print(f"session: {session.id}")
    print("エージェントと対話します。exit と入力すると終了します。\n")
    ###############################
    # 2. 1ターン分の送信と受信(承認待ちになったらy/Nで確認)
    ###############################
    def run_turn(text: str) -> None:
    pending_tools = {} # event_id -> (ツール名, 引数)
    # ストリームを開いてからメッセージを送信
    stream = client.beta.sessions.events.stream(session_id=session.id)
    client.beta.sessions.events.send(
    session.id,
    events=[{"type": "user.message", "content": [{"type": "text", "text": text}]}],
    )
    for event in stream:
    if event.type == "agent.mcp_tool_use":
    if getattr(event, "evaluated_permission", None) == "ask":
    # 承認が必要なツール呼び出し。IDを控えておく
    pending_tools[event.id] = (event.name, event.input)
    else:
    print(f"[ツール: {event.name}]")
    elif event.type == "agent.message":
    for block in event.content:
    if block.type == "text":
    print(block.text)
    elif event.type == "session.status_idle":
    if event.stop_reason.type == "requires_action":
    # 承認待ち。ツールの内容を表示してユーザーに確認する
    for event_id in event.stop_reason.event_ids:
    name, tool_input = pending_tools.get(event_id, ("(不明)", {}))
    print("\n----- 承認リクエスト -----")
    print(f"ツール: {name}")
    print(f"引数: {json.dumps(tool_input, ensure_ascii=False, indent=2)}")
    answer = input("実行を許可しますか? [y/N] ").strip().lower()
    confirmation = {
    "type": "user.tool_confirmation",
    "tool_use_id": event_id,
    "result": "allow" if answer == "y" else "deny",
    }
    if answer != "y":
    confirmation["deny_message"] = "ユーザーが実行を拒否しました。"
    client.beta.sessions.events.send(session.id, events=[confirmation])
    print("回答を送信しました。続行します...\n")
    else:
    break
    elif event.type == "session.status_terminated":
    print("セッションが終了しました。")
    raise SystemExit(1)
    stream.close()
    ###############################
    # 3. 最初のタスクを送信し、そのあとは対話を続ける
    ###############################
    run_turn(
    "自分宛てに「明日の予定の確認」というメールの下書きを作成してください。"
    "本文は簡潔にお任せします。送信はしないでください。"
    "宛先のメールアドレスなど、分からないことがあれば私に質問してください。"
    )
    while True:
    user_input = input("\nあなた> ").strip()
    if user_input == "exit":
    break
    if not user_input:
    continue
    run_turn(user_input)
    print("\n完了しました")
  2. スクリプトを実行します。エージェントに質問されたらあなた>に回答し、承認リクエストが出たら引数の中身を確認してからyで許可します。

    Terminal window
    uv run run_gmail.py
    session: sesn_01WCk8w6uAJPuoP7QG32G4tr
    エージェントと対話します。exit と入力すると終了します。
    下書きを作成させていただきたいのですが、確認させていただきたいことが1つあります:
    **ご自身のメールアドレスを教えていただけますか?**
    あなた> あなたのメールアドレス
    ----- 承認リクエスト -----
    ツール: create_draft
    引数: {
    "body": "お疲れ様です。\n\n明日の予定について確認したいことがあります。...",
    "subject": "明日の予定の確認",
    "to": [
    "あなたのメールアドレス"
    ]
    }
    実行を許可しますか? [y/N] y
    回答を送信しました。続行します...
    完了しました!「明日の予定の確認」というメールの下書きを作成いたしました。
    あなた> exit
  3. Gmailの「下書き」フォルダーを開くと、エージェントが作成した下書きが保存されています。承認リクエストで表示されたものと同じ件名・本文であることが確認できます。

  • ボールトの「MCP OAuth」タイプにはGmailなどのプリセットがあり、コンソールの「接続」ボタンがOAuthの認可とトークンの保管・更新を代行してくれます。
  • コンソールで作った認証情報も、コードからは他の認証情報と同じように参照できます(OAuth系はコンソールで「接続」して作り、コードからはボールトIDで参照する、という分担)。
  • always_askにすると、ツール実行前にagent.mcp_tool_use(承認待ち)→user.tool_confirmation(allow/deny)という往復が発生します。実データを扱う操作を、実行前に中身を見てから許可できます。
  • Gmailのような個人アカウントの認証情報を扱うときは、ワークスペース共有の性質に注意してください。

おつかれさまでした!ここまでの感想を、ぜひXにポストしてください。

感想をXにポストする