Claude Media
Managed AgentsのvaultでOAuthリフレッシュ失敗の診断手順

Managed AgentsのvaultでOAuthリフレッシュ失敗の診断手順

Managed Agentsのvaultでmcp_oauth認証情報のリフレッシュが失敗したとき、webhookとmcp_oauth_validateでどこまで原因を切り分けられるかを、statusの3値ごとの対応とあわせて示します。

Managed Agentsのvaultに登録したmcp_oauthクレデンシャルは、アクセストークンが期限切れになると自動で再取得されます。このリフレッシュが失敗するとvault_credential.refresh_failedイベントが飛ぶだけで、原因までは教えてくれません。原因の切り分けにはmcp_oauth_validateエンドポイントを呼び、返ってくるstatusの3値(valid / invalid / unknown)で対応を分けます。

OAuthリフレッシュの失敗はどのイベントで検知できるか

vaultに登録したクレデンシャルは、セッション実行中もvaultのライフサイクル全体でも定期的に再解決されます。この仕組みのおかげで、クレデンシャルのローテーション・アーカイブ・削除がセッションを再起動せずに反映されます。mcp_oauthクレデンシャルの場合、再解決のタイミングでアクセストークンの有効期限も同時にチェックされ、切れていれば自動でリフレッシュが試みられます。

このリフレッシュが失敗するとvault_credential.refresh_failedイベントが発行されます。検知するにはvaultとcredentialのwebhookを購読しておく必要があり、購読していなければ失敗は静かに積み重なるだけです。ほかにもvault.archived / vault.deleted / vault_credential.archived / vault_credential.deletedといったライフサイクルイベントがあり、refresh_failedはこの一覧の一部という位置づけです。

ここで注意したいのは、webhookが教えてくれるのは「失敗した」という事実だけだという点です。リフレッシュトークン自体が無効になったのか、OAuthサーバー側が一時的に落ちているだけなのかは、イベント本文からは判断できません。次のステップで診断エンドポイントを呼ぶ必要があります。

mcp_oauth_validateで失敗原因を切り分ける

POST /v1/vaults/{vault_id}/credentials/{credential_id}/mcp_oauth_validateを呼ぶと、そのクレデンシャルが実際に使えるかどうかをAnthropic側が検証してくれます。SDKではclient.beta.vaults.credentials.mcp_oauth_validate(...)に対応します。

curl --fail-with-body -sS -X POST \
  "https://api.anthropic.com/v1/vaults/$vault_id/credentials/$credential_id/mcp_oauth_validate?beta=true" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "anthropic-beta: managed-agents-2026-04-01"

レスポンスはvault_credential_validation型のオブジェクトです。mcp_probeには実際にMCPサーバーへハンドシェイクを試みた結果、refreshにはリフレッシュを試みた結果がそれぞれ入ります。

{
  "type": "vault_credential_validation",
  "credential_id": "vcrd_01ABC...",
  "vault_id": "vlt_01XYZ...",
  "validated_at": "2026-04-29T17:12:00Z",
  "has_refresh_token": false,
  "status": "invalid",
  "mcp_probe": {
    "method": "initialize",
    "http_response": {
      "status_code": 401,
      "content_type": "application/json",
      "body": "{\"error\":\"invalid_token\"}",
      "body_truncated": false
    }
  },
  "refresh": {
    "status": "no_refresh_token",
    "http_response": null
  }
}

この例ではhas_refresh_tokenfalseになっており、そもそもリフレッシュトークンを登録していないクレデンシャルだったことがrefresh.statusno_refresh_tokenから分かります。MCPサーバーへのinitialize呼び出し自体も401で弾かれているため、アクセストークンもリフレッシュトークンも両方無効という状態です。

statusの3値ごとに取るべき対応

トップレベルのstatusが、次に何をすべきかをそのまま示します。

status意味取るべき対応
valid意味トークンは正常に動いている取るべき対応何もしなくてよい
invalid意味認可自体が失効、またはOAuthサーバーが4xxでリフレッシュを拒否取るべき対応エンドユーザーに再認可を促す
unknown意味5xx・429・ネットワーク障害などの一時的エラー取るべき対応少し待ってから再試行する

invalidunknownを混同すると対応を誤ります。invalidはOAuth連携そのものが切れているサインなので、再試行しても直りません。ユーザーに再度認可フローを踏んでもらい、新しいアクセストークンとリフレッシュトークンでクレデンシャルを更新する必要があります。一方は相手のOAuthサーバー側の一時的な不調が疑われる状態で、バックオフを挟んだ再試行が有効です。

再認可でクレデンシャルを更新するときは、access_token / expires_at / refresh.refresh_tokenを新しい値に差し替えます。稼働中のセッションがあっても再起動は不要で、次の再解決タイミングで新しいトークンに切り替わります。

クレデンシャルの再解決の仕組みとリフレッシュの関係

mcp_oauth_validateが便利なのは、リフレッシュの成否だけでなくMCPサーバーへの実際の接続確認(mcp_probe)まで一度に返す点です。裏を返すと、この2つは別々の失敗要因になり得ます。リフレッシュ自体は成功していても、MCPサーバー側のスコープ変更やエンドポイント移行でmcp_probeが失敗するケースもあり、その場合はrefresh.statusが正常でもstatus全体はinvalid側に倒れます。

もう一つ見落としやすいのが、mcp_server_url / token_endpoint / client_idといった構造的なフィールドは作成後にロックされる点です。これらを変更したい場合、既存クレデンシャルの更新では対応できず、アーカイブしてから新規に作り直す必要があります。OAuthプロバイダー側でトークンエンドポイントのURLが変わった、あるいはクライアントIDをローテーションした、といった構成変更が起きたときにリフレッシュが失敗し続けるなら、まずこの構造的フィールドが古いままになっていないかを先に確認します。値の差し替えではなく、クレデンシャルの作り直しが必要な典型パターンです。

診断の流れをまとめると、webhookで失敗を検知し、mcp_oauth_validatestatusを確認し、invalidなら再認可または作り直し、unknownなら再試行、という3段階になります。この順番を踏まずに再試行だけを繰り返すと、実際には再認可が必要なケースを見逃したまま失敗が積み重なります。

refreshブロックの設定ミスを疑う

クレデンシャル作成時に渡すrefreshブロックには、token_endpoint / client_id / scope / refresh_tokenに加えて、リフレッシュ呼び出し自体をどう認証するかを決めるtoken_endpoint_auth.typeがあります。ここの設定がOAuthサーバー側の要求と食い違っていると、リフレッシュコール自体が401や400で拒否され続けます。

token_endpoint_auth.type意味
none意味パブリッククライアント。クライアントシークレットを送らない
client_secret_basic意味クライアントシークレットをHTTP Basic認証で送る
client_secret_post意味クライアントシークレットをPOSTボディに含めて送る

OAuthプロバイダーのドキュメントで指定されている認証方式と、クレデンシャル作成時に登録したtoken_endpoint_auth.typeが一致しているかは、mcp_oauth_validateを1回呼んだだけのレスポンスだけでは判断がつきません。refresh.http_responseにOAuthサーバーからの生のエラーボディが返るので、invalid_clientのようなエラーコードが含まれていないかをまず確認します。このコードが返っている場合、リフレッシュトークン自体はまだ有効でも、認証方式の指定ミスによってリフレッシュコールそのものが手前で弾かれている可能性が高くなります。この場合はinvalidステータスから連想しがちな「再認可」ではなく、token_endpoint_authの設定を修正してクレデンシャルを作り直す対処になります。

修正後は、access_token / expires_at / refreshをまとめて更新します。

curl --fail-with-body -sS \
  "https://api.anthropic.com/v1/vaults/$vault_id/credentials/$credential_id" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "anthropic-beta: managed-agents-2026-04-01" \
  -H "content-type: application/json" \
  -d '{
    "auth": {
      "type": "mcp_oauth",
      "access_token": "xoxp-new-...",
      "expires_at": "2099-12-31T23:59:59Z",
      "refresh": {"refresh_token": "xoxe-1-new-..."}
    }
  }'

ただし、この更新で書き換えられるのはdisplay_name・秘密情報の値・(環境変数クレデンシャルなら)injection_locationだけです。mcp_server_url / token_endpoint / client_idのような構造フィールドを直したい場合、この更新リクエストは通らず、クレデンシャルをアーカイブしてから新規作成する必要があります。

アーカイブ済みのvault・credentialが原因になっていないか

リフレッシュ失敗の原因として見落としやすいのが、クレデンシャルやそれを含むvault自体がすでにアーカイブ済みというケースです。vaultをアーカイブすると、配下のすべてのクレデンシャルもカスケードでアーカイブされ、シークレットの実体は完全にパージされます。アーカイブ以降に作られる新規セッションはそのvaultを参照できずに失敗し、すでに動いているセッションだけがそのまま継続します。クレデンシャル単体をアーカイブした場合も同様にシークレットがパージされますが、mcp_server_urlsecret_nameといったキー自体は表示上残り、置き換え用の新しいクレデンシャルに再利用できる状態になります。

vault_credential.refresh_failedが繰り返し飛んでくるとき、まずクレデンシャルが意図せずアーカイブされていないかを確認する価値があります。アーカイブ済みのクレデンシャルはシークレットが存在しないため、mcp_oauth_validateを呼んでも当然リフレッシュは成功しません。これは「トークンが実際に失効した」場合とは根本的に別の原因であり、再認可を促しても解決しません。アーカイブ済みのクレデンシャルはシークレットがすでにパージされているため、新しいクレデンシャルを作り直して置き換える必要があります。削除(ハード削除)の場合はレコード自体が残らないため、監査目的で経緯を追いたいならアーカイブを、完全に痕跡を残したくないなら削除を選びます。

確認作業でつまずきやすいのが一覧APIの既定挙動です。vaultやクレデンシャルの一覧は新しい順のページネーションで返りますが、アーカイブ済みのレコードは既定では除外されます。原因調査のために一覧を見ても、まさに問題のクレデンシャルがアーカイブ済みで一覧に出てこず「そんなクレデンシャルは存在しない」と誤認してしまうことがあります。include_archived=trueを付けて再度一覧を取得すれば、アーカイブ済みのレコードも含めて確認できます。

よくある質問

static_bearerクレデンシャルでもこの診断は使えますか

いいえ。mcp_oauth_validatemcp_oauthクレデンシャルのリフレッシュ失敗を診断するためのエンドポイントです。static_bearerは固定のベアラートークンを使う方式で、そもそもリフレッシュという概念がありません。トークン自体が無効になった場合は、新しい値でクレデンシャルを更新するだけで直ります。

vaultをアーカイブすると配下のクレデンシャルにも個別のイベントが飛びますか

はい。vault.archivedイベントが発行されるのと同時に、そのvaultに紐づく各クレデンシャルについてもvault_credential.archivedイベントが個別に発行されます。webhookの受信ログで大量のvault_credential.archivedが一度に届いたときは、個々のクレデンシャルの問題ではなく、親のvaultがアーカイブされたことによるカスケードを疑うとよい手がかりになります。

まとめ

vaultのmcp_oauthクレデンシャルは期限切れ時に自動でリフレッシュされますが、失敗時にwebhookが教えてくれるのは「失敗した」という事実だけです。mcp_oauth_validateを呼んでstatusを確認し、validなら静観、invalidなら再認可かクレデンシャルの作り直し、unknownなら再試行、という3分岐で対応します。構造的フィールド(mcp_server_urltoken_endpointclient_id)は更新できずロックされている点も、繰り返し失敗するケースの見落としがちな原因です。認証情報の管理全体をどう設計するかはAgent SDKのManaged Agentsの設計思想、MCPサーバーごとの許可範囲の考え方はMCPセキュリティガイド、SDK側からMCP接続を組む手順はAgent SDK MCP接続ガイドで扱っています。

この記事を共有:XはてブLinkedIn