1. はじめに
OCI Database Tools MCP Server を Claude Desktop / Claude Code に接続して使っていたところ、「さっきまで動いていたのに、急に切れて再接続できなくなる」 事象に遭遇しました。
クライアント側のログを見ると、こんなエラーが出ています。
Connection error: Error: Incompatible auth server:
does not support dynamic client registration
原因を確認したところ、Bearer Token として渡している Personal Access Token (PAT) が失効していた ことでした。
ここで気になったのが、OCI コンソールの PAT 生成画面で 「失効までの分数 = 180」 と指定していたのに、ものの 1 時間で切れていることです。
画面上の入力欄には「1 から 527040 までの値にする必要があります」と注釈もあり、180 分どころか 年単位(527040 分 ≒ 1 年)まで指定できる はずなのに。
本記事では、
- PAT の実体(JWT)をデコードして本当の有効期限を確認し、
- UI 指定値と実発行値の関係を 10 分指定 / 180 分指定 の 2 通りで実測し、
- Identity Domain (IDCS) の UI / API を一通り探して 延長設定の有無 を確定させる
ことを通じて、「OCI PAT の有効期限は最大 60 分にサイレントでキャップされる」 という挙動の原因を整理します。
今回の検証ゴール
| # | 検証項目 |
|---|---|
| 1 | PAT の実体(JWT)の exp - iat が、UI 指定値どおりかをデコードして確認する |
| 2 | UI 値より小さい指定(10 分)と大きい指定(180 分)で発行された PAT を比較し、キャップが上方向だけに効くのか、それとも UI 値が常に無視されるのかを判定する |
| 3 | Identity Domain UI / API を辿って、ユーザー側で有効期限を延長できる設定箇所があるかを実証する |
検証環境
| 項目 | 内容 |
|---|---|
| OCI リージョン | ap-tokyo-1 |
| Identity Domain | Default(IDCS 形式) |
| 対象 MCP サーバ | OCI Database Tools MCP Server(マネージド) |
2. JWT をデコードして確認
2.1. PAT の実体は JWT
OCI コンソールでダウンロードした PAT ファイルを開くと、1 行の長大な文字列が入っています。これは xxxxx.yyyyy.zzzzz という 3 つの Base64URL 文字列をピリオドで結合した JWT (JSON Web Token) です。
# decode_jwt.ps1 (src/ に同梱)
param([Parameter(Mandatory=$true)][string]$Path)
$token = (Get-Content $Path -Raw).Trim()
$payload = $token.Split('.')[1]
while ($payload.Length % 4) { $payload += '=' }
$bytes = [Convert]::FromBase64String($payload.Replace('-','+').Replace('_','/'))
$obj = [Text.Encoding]::UTF8.GetString($bytes) | ConvertFrom-Json
$iat = (Get-Date '1970-01-01').AddSeconds($obj.iat).ToLocalTime()
$exp = (Get-Date '1970-01-01').AddSeconds($obj.exp).ToLocalTime()
$diff = $obj.exp - $obj.iat
"iat: $iat"
"exp: $exp"
"exp - iat: $diff 秒 (= $($diff/60) 分)"
"aud: $($obj.aud)"
"client_id: $($obj.client_id)"
"tok_type: $($obj.tok_type)"
180 分指定で発行した PAT をデコードした結果:
iat: 2026-05-23 19:54:54
exp: 2026-05-23 20:54:54
exp - iat: 3600 秒 (= 60 分)
aud: urn:opc:dbtools:mcpserver:ocid1.databasetoolsmcpserver.oc1.ap-tokyo-1.amaaaaaa...
client_id: te
tok_type: AT
UI で 180 分を指定したのに、exp - iat は きっかり 3600 秒(= 60 分)。
60 分を境にスパッと切られているのが分かります。
2.2. 主要 claim の読み解き
| claim | 値の例 | 意味 |
|---|---|---|
iat |
2026-05-23 19:54:54 |
Issued At(発行時刻、Unix 秒) |
exp |
2026-05-23 20:54:54 |
Expiration(有効期限、Unix 秒) |
aud |
urn:opc:dbtools:mcpserver:ocid1... |
Audience(このトークンが向けて発行された対象リソース) |
tok_type |
AT |
Access Token(refresh token ではない) |
client_id |
te |
発行元クライアント。te は Token Exchange(OCI 内部の組み込みクライアント) |
sidle |
480 |
Session Idle Timeout(IDCS UI セッションのアイドル分数。トークン寿命とは別) |
特に重要なのが aud。この MCP サーバの OCID にロックされている ため、万が一漏洩しても他のリソースには使えませんが、逆に サーバを作り直すと再発行が必要 という制約もあります。
2.3. GitHub PAT との違い
「PAT」というと GitHub の ghp_xxxxxxxxxx... のような不透明な長命トークンを思い浮かべますが、OCI の PAT は仕組みがかなり異なります。
| GitHub PAT | OCI PAT | |
|---|---|---|
| 形式 | 不透明文字列 | JWT(RS256 署名付き) |
| 検証方式 | サーバ側 DB 照合 | 署名検証だけで完結(ステートレス) |
| 寿命 | ユーザー指定(無期限可) | IDCS ポリシー支配(典型 60 分) |
| 失効 | 手動で revoke |
exp で自動失効 |
GitHub のイメージで「PAT は長く使えるもの」と思い込んでいると、OCI で 短命の JWT で切り分けに時間がかかった・・というお話です。
3. UI 値と実発行値を実測
UI 入力欄が 1〜527,040 分を受け付けるのに、実発行が 60 分で頭打ちになるなら、「下方向(短い指定)」も同じく無視されるのか? が次の疑問です。
| 仮説 | 内容 | 10 分指定の予測 |
|---|---|---|
| (a) 上限キャップ説 | UI 値は要求値、IDCS 側の最大値(3600 秒)で頭打ち | 600 秒(指定通り) |
| (b) 完全無視説 | UI 値は完全に無視、常に 3600 秒で発行 | 3600 秒(指定無視) |
判定するため、もう一度 PAT を 「失効までの分数 = 10」 で発行し直してデコードします。
iat: 2026-05-23 20:36:31
exp: 2026-05-23 20:46:31
exp - iat: 600 秒 (= 10 分)
10 分指定はそのまま 10 分で発行され、180 分指定だけが 60 分に切り詰められています。つまり、 60分でキャップされるような動きであることがわかります。
OCI PAT の有効期限は、UI 入力値に対して以下の 非対称な挙動 をします。
| UI 指定値 | 実発行 exp - iat
|
挙動 |
|---|---|---|
| 10 分 | 600 秒(= 10 分) ✅ | 指定どおり |
| 180 分 | 3600 秒(= 60 分) ⚠️ | 60 分にキャップ |
| 527040 分(=最大) | 3600 秒(= 60 分) ⚠️ | 60 分にキャップ |
UI 入力欄の注釈「1 から 527,040 までの値にする必要があります」は 嘘ではないものの、
60 分を超える値を入れても 警告もエラーも一切出さずに 60 分にされる ため、
画面だけ見て運用設計するとハマります。
3.1. なぜ 60 分なのか — 公式 Docs の根拠
これは IDCS の標準仕様で、根拠は公式 Docs の 「トークン有効期限表」 にあります。
「OAuthアクセス・トークンの有効期間」のセクションに、既定値 3600 秒 と、ATの有効期限が OAuthConfig / リソース・アプリケーション / カスタム の組み合わせで決まる旨が明記されています。
「リソース・アプリケーションの有効期限時間もユーザー・セッションの有効期限時間も構成されておらず、カスタム有効期限時間も指定されていない場合、ATの有効期限はデフォルトの OAuthアクセス・トークンの有効期間である 3600 秒 になります。」
— トークン有効期限表 - OCI Documentation
同 Docs によれば、Access Token の最終有効期限は次の 3 階層の最小値 で決まります。
| # | 階層 | 設定場所 |
|---|---|---|
| ① | OAuthConfig Access Token Expiry(グローバル既定) | テナント単位 / 既定 3600 秒 |
| ② | Resource App Expiry(リソース個別) | Identity Domain の Resource Server 型アプリ |
| ③ | Custom Expiry(リクエスト時) | OAuth scope に urn:opc:resource:expiry=<seconds> を付与 |
最終 exp - iat = min( ① OAuthConfig, ② Resource App, ③ Custom Expiry )
これに今回の実測を当てはめると、
| UI 指定 | ③ Custom Expiry | ① OAuthConfig | 最小値 | 実発行 | 一致 |
|---|---|---|---|---|---|
| 180 分 = 10800 秒 | 10800 | 3600 | 3600 | 3600 ✅ | ✅ |
| 10 分 = 600 秒 | 600 | 3600 | 600 | 600 ✅ | ✅ |
実測と公式の説明が完全に整合します。
OCI Database Tools MCP の PAT 生成画面の値は ③ の Custom Expiry として渡され、① の既定値 3600 秒で頭打ちされていた、というのが正体です。
3.2. 延長する設定箇所はあるのか
3 階層の最小値で決まるなら、① OAuthConfig か ② Resource App を伸ばせば 180 分も通る はず ― ということで、Identity Domain の中を一通り探しました。
| # | 探索 | 結果 |
|---|---|---|
| 1 | コンソール → ドメイン → Default → 設定(セッション設定) |
セッション期間 = 480 分 のみ。Access Token Expiry の項目は存在しない
|
| 2 | 同 → 統合アプリケーション(GUI) | 自分が登録した claude-desktop-client(Confidential Client)のみ |
| 3 | OCI CLI apps list --filter 'name co "dbtools" or "DatabaseTool" or "MCP"'
|
[] |
| 4 | OCI CLI apps list --filter 'name eq "<resource_app_id>"'
|
[] |
ドメイン設定の「セッション設定」には セッション期間 と アイドル・タイムアウト の2 つしかなく、Access Token Expiry の欄は見当たりません。
これらの 480 分はあくまで コンソール UI セッションの寿命(JWT の sidle: 480 claim に対応)であって、発行された Access Token の寿命とは別物です。
統合アプリケーション一覧にも、自分で OAuth 用に登録した claude-desktop-client 1 件だけが見えます。
ちなみに claude-desktop-client を開くと 「トークン発行ポリシー」 という、いかにも寿命をいじれそうなセクションがありますが、中身は 「認可されたリソース: 明示的」というアクセス可否のホワイトリスト設定で、TTL の項目ではありません。
そもそも、このアプリは今回の PAT 発行経路上にいません。JWT の client_id は te
(Token Exchange = OCI 内部の組み込みクライアント)であって claude-desktop-client の Client ID 8894d... ではないため、ここを編集しても今回の PAT 発行フローには構造的に作用しない という関係のようです。
トークン有効期限表 によれば本来 Access Token Expiry は アプリ単位(= Resource Server 型アプリの設定)で変更できるようなのですが、OCI Database Tools MCP の Resource App はテナント内のどこからも見えない(GUI 非表示・API でも 0 件)ため、ユーザー側からは編集できない ことが確定しました。
OCI Database Tools MCP Server 自体のドキュメントにも、サラッとですが 1 時間で切れる旨が明記されています。
「Bearerトークンは約1時間有効です。」
— MCPサーバーのトラブルシューティング - Autonomous Database(「ストリーム可能な HTTP エラー – 401」セクション)
4. まとめ
| # | 検証項目 | 結論 |
|---|---|---|
| 1 | PAT の exp - iat が UI 指定値どおりか |
60 分以下なら指定どおり、60 分超は 60 分にキャップ(仮説 a 確定) |
| 2 | 「上方向だけキャップ」か「常に無視」か | 上方向だけサイレントキャップ。下方向(短く指定)は素通し |
| 3 | ユーザー側で延長できる設定箇所はあるか | 存在しない。Resource App が OCI マネージド側に隠蔽されているため GUI/API どちらからも見えない |
公式 Docs の 「3 階層の最小値ルール」 に当てはめると、OCI Database Tools MCP の PAT は 常に IDCS のグローバル既定 3600 秒 で頭打ちされ、これを伸ばす設定面がユーザー側に露出していない、というのが本記事の発見でした。
実運用上は 60 分前提でフローを組む しかありません。
具体的には次のような選択肢が候補になります(後ろ 2 つは未検証の提案ベース)。
-
手動再発行(実証済み): 1 時間ごとに OCI コンソールから取り直して MCP 設定ファイルの
Authorization: Bearer ...を更新する最小コストの運用。検証や試用フェーズではこれで十分 -
自動再発行ラッパーが候補(未検証): OAuth
client_credentialsgrant で PAT 相当のトークンを再取得するスクリプトをmcp-remote起動前に噛ませて、毎回置換する構成 -
urn:opc:resource:expiryの scope 指定も候補(未検証): トークン有効期限表 には明示要求の手段として記載があるが、UI 経由の PAT 発行フローからは指定できないので、自動化スクリプト側で OAuth 直接呼び出しに切り替えた場合の候補
本記事の範囲では、「PAT は最大 60 分」を前提として運用設計に組み込んでおくと、失効でハマる時間を減らせます ―― ここまでが今回の結論です。




