🆔 用它自己的身分,再註明它代表你。Claude Code 在你電腦上跑
gh用的是你登入的 token,GitHub 上看起來就是你本人,分不出是它做的,也沒辦法只停掉它。自己做的 Agent 要代使用者動 GitHub、Google,就讓使用者用 OAuth 授權給你的 App,token 存在 Harness、模型拿不到,也能單獨撤銷;服務沒標出 App 的,像 Google 行事曆,由 Harness 記下哪一輪、代表誰。
昨天在 Day 21|開了 Sandbox,就安全了嗎?,我們實測了 Claude Code 的 sandbox:它管的是 Bash 在本機讀寫哪些檔案、連哪些網址;Agent 拿著憑證呼叫 GitHub 之後,GitHub 怎麼處理這個請求,sandbox 管不到。昨天最後問那把憑證能開的門會不會太多,在談門開多大之前,要先看這把憑證是誰的。
快速回顧一下:Day 20 的 gemini-cli 事件裡,模型那一步拿著一把能改 Issue 的 token,Issue 裡夾帶的指示叫它把 token 寫進公開的內文;Day 21 實測過,Claude Code 的 Bash 指令繼承你的環境變數,用你的使用者權限跑。
你在自己的電腦上請 Claude Code 修一個 bug,修完 commit,再用 gh 開 PR。一個月後同事問:這個 repo 裡哪些 commit 是 Claude 寫的?或是更糟,Claude 讀到一段夾帶指示的內容,用 gh 做了你沒要求的事,你想只停掉 Claude,不停掉自己。
這兩件事做不做得到,要看 GitHub 收到請求時認不認得出 Claude。我請 Claude Code 在丟棄用的 repo 裡印出它用的 GitHub 帳號和 git 作者,再照它平常的做法 commit 一次。
gh 登入的是我的帳號 davidleitw,token 的權限包括我所有的 repo 和管理 SSH 金鑰;commit 的作者是我在 git 裡設定的名字。Claude 留下的痕跡只有 commit 尾巴一行 Co-Authored-By: Claude Opus 5.5,這行字由設定決定,設定清空時,commit 上完全看不出跟 Claude 有關。

圖:左邊是 Claude Code 在我電腦上拿到的身分:gh 帳號、token 權限和 git 作者都是我的 → 中間是 commit 長什麼樣:作者欄是我,尾巴那行署名照設定加上、改掉或清空 → 右邊是 GitHub 上看得到的:作者是我,哪些是 Claude 做的只能看那行字,token 能動我所有的 repo,也沒辦法只停掉 Claude。這是示意,實作要照自己的工具和環境調整。
在 GitHub 眼裡,Claude 跟我是同一個人。這種做法叫 impersonation,Agent 直接頂著你的身分;另一種做法叫 delegation,Agent 有自己的身分,紀錄上註明它代表誰。下面先講兩種做法差在哪、現在的 coding agent 多半是哪一種、delegation 在底下怎麼做到,再看自己做的 Agent 怎麼用 OAuth 串服務、最少要記什麼。
外部服務認的是你交出去的 token,它不知道這把 token 現在是人在用,還是 Agent 在用。OAuth(第三方登入和授權用的那套協定)的 token exchange 標準 RFC 8693 把「A 替 B 做事」分成兩種:
同樣是修 bug、開 PR,兩種做法下 GitHub 收到的東西並排:
impersonation:Agent 頂著你的身分
誰在做 → 你
代表誰 → (沒有這一欄)
能動什麼 → 那把 token 能動的;跟你共用登入的 token,就是你的全部
只停掉 Agent → 跟你共用同一把 token 時做不到,要停就是連你一起停
delegation:Agent 用自己的身分,註明代表你
誰在做 → Agent 自己的帳號
代表誰 → 你
能動什麼 → 授權時交給它的那部分
只停掉 Agent → 撤銷 Agent 那一份,你不受影響
OpenID Foundation 2025 年 10 月的白皮書談 Agent 的身分時寫,現在的 Agent 常常跟使用者分不出來,出事時說不清是誰做的。本機的 Claude Code 就是這樣。
我在 macOS、Claude Code 2.1.285(模型是 Claude Opus 5.5)開一個新的空資料夾,用 claude -p 請它依序執行下面四個指令,再照它平常的做法 commit 一次,結果是(email 我遮掉了,token 是 gh 自己遮的):
gh api user --jq .login → davidleitw
gh auth status → Logged in to github.com account davidleitw
Token: gho_***
Token scopes: 'admin:public_key', 'gist', 'read:org', 'repo'
git config user.name → davidlei
git config user.email → (我的 email)
gh 讀的是我用 gh auth login 登入時存下的 token(gho_ 開頭代表它是 OAuth 登入拿到的),我自己在 terminal 打 gh 也用這把;git 讀的是我的 git 設定;Bash 指令又是用我的使用者權限跑的。GitHub 收到的請求裡,沒有任何一欄寫著 Claude,這就是 impersonation。其他在你 terminal 裡跑 gh、git 的 Agent,只要沒另外給它憑證,用的也是這些工具替你存好的那份。
commit 尾巴倒是有一行 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>。Claude Code 的設定文件寫,這行由 attribution.commit 決定:沒設就加,設成空字串就不加,也可以換成任何文字;工具呼叫的紀錄也看得出,是模型自己把它寫進 git commit -m 的訊息裡。作者欄一樣是文字,來自 git 設定,誰都能把 user.name 設成別人的名字。GitHub 認人看的是推 commit、開 PR 時交出去的那把 token,而那把是我的。
頂著我的身分,平常很方便:Claude 開的 PR 在我的帳號底下,權限跟我一樣,什麼都不用設。問題出在要把我們分開的時候:
分不出是誰做的。 哪些是 Claude 做的,只能看尾巴那行字,而那行字能改、能清空,任何人也都能手打上去。
能動的是我的全部。 這次只需要動一個 repo,token 卻帶著 repo 權限,GitHub 的說明是能完整讀寫公開和私有的 repo,我所有的 repo 都在範圍內;admin:public_key 還能管理我帳號上的 SSH 金鑰。
沒辦法只停掉 Agent。 想讓 Claude 手上的 GitHub 權限馬上失效,只能撤銷我自己的登入,我也跟著不能用。
做法有三種,差在「Agent 自己的身分」和「代表誰」各記在哪裡。
一份 token 裡寫兩個身分。 RFC 8693 定義了一個 act 欄位:token 的 sub 放授權的使用者,act 放實際做事的一方。OpenID 白皮書推的也是這個形狀,token 裡同時有兩個身分,從第一步就留下查得到的關聯。下游服務收到請求,看 token 就知道是哪個 Agent 代表誰,可以兩邊各檢查一次。這是標準裡的欄位,發 token 和收 token 的服務都要支援才用得上,各家還沒有共同的實作。
GitHub App 代表使用者。 GitHub App 可以拿 user access token 代表某位使用者呼叫 API。GitHub 的文件寫,例如 App 代表你開了一個 Issue,畫面上的作者是你的頭像,旁邊加上 App 的小圖示;App 只能動你有權限、它自己也有權限、而且它有安裝的地方。App 有開啟 token 到期設定的話,這把 token 八小時後過期。
Agent 用自己的 bot 帳號,另外記下是誰叫的。 Claude Code 也能在 GitHub Actions 裡跑:在 Issue 或 PR 留言 @claude,workflow 就啟動 Claude,讓它回覆、改 code、推 commit。預設設定下,它用的是 Claude 的 GitHub App 自己的身分:
claude[bot]。Co-authored-by: <留言 @claude 的人>。跟本機剛好反過來,作者是 bot,叫它做事的人掛在尾巴。GitHub 自家的 Copilot cloud agent 被指派 Issue、或被要求改 PR 時也是這樣。GitHub 的文件寫:commit 的作者是 Copilot,指派工作的開發者列為 co-author;只有對 repo 有寫入權限的人能叫它做事;它只能推一個分支;叫它開 PR 的人不能自己核准那個 PR。
這種做法的兩個身分記在不同地方:token 只代表 App,叫它做事的人留在 GitHub 的留言、指派和 workflow 紀錄上。跟第一種把兩個身分寫進同一份 token 比,有兩點要知道。第一,它能做的事由 App 被授予的權限決定,不會跟著叫它的人縮小;預設只讓有寫入權限的人叫得動它,是為了不讓沒權限的人借它做事。第二,commit 尾巴的 co-author 只是 commit 訊息裡的一行字,claude-code-action 那行還是模型照 prompt 寫的。
雲端平台也往這個方向走。Google Cloud 的 Agent Identity 給每個 Agent 一個自己的身分,預設不跟其他程式共用;Agent 可以用自己的身分呼叫服務,也可以經使用者登入同意後代表使用者。
本機和 GitHub Actions 並排:
本機的 Claude Code(我這次實測):impersonation
GitHub 上是誰 → davidleitw,我本人的帳號
commit 作者 → davidlei,我的 git 設定
commit 尾巴 → Co-Authored-By: Claude,照設定可改可清空
代表誰 → 沒有紀錄,看起來都是我
token 能動什麼 → 我所有的 repo,還能管理 SSH 金鑰
只停掉 Claude → 做不到,只能連我一起停
GitHub Actions 裡的 claude-code-action(預設設定,照文件和原始碼):delegation
GitHub 上是誰 → Claude 的 GitHub App
commit 作者 → claude[bot]
commit 尾巴 → Co-authored-by: 留言 @claude 的人
代表誰 → 留言 @claude 的人,workflow 執行紀錄上也有
token 能動什麼 → 只有這個 repo,權限照 workflow 設定
只停掉 Claude → 把 App 從 repo 移除或關掉 workflow,我的帳號不受影響
下半邊我沒有實測,是照 claude-code-action 的文件、原始碼和 GitHub 的文件寫的。
前面看的都是現成產品。自己做 Agent 時更常碰到的是:使用者登入你的服務,把自己的 GitHub 帳號連給 Agent,請它代自己開 PR;換成 Google 帳號,就是代自己在行事曆加一筆行程。這條路走的是 OAuth:Agent 這個 App 把使用者送到 GitHub 的同意頁,使用者按同意,GitHub 先給一個只能用一次的授權碼,App 拿它換到 token。這就是上一節的第二種做法,GitHub 知道這把 token 屬於哪個 App、代表哪位使用者,GitHub 的文件也寫,它只能動使用者和 App 都動得到的東西。
Google 的 Agent 開發框架 ADK,驗證文件把自己寫 Agent loop 時要接的步驟寫得很完整。照它的順序,換成代使用者開 PR:
模型提出工具呼叫:開 PR
→ Harness 查這位使用者連過 GitHub 沒有
├─ 連過 → 取出他的 token 執行工具,模型只拿到 PR 網址
└─ 沒連過 → 這一輪停在工具執行前,給使用者一個 GitHub 授權連結
→ 使用者在 GitHub 按同意
→ GitHub 帶著授權碼,回到 App 事先登記的網址
→ Harness 確認回來的是同一個人,換成 token,存在他名下
→ 繼續這一輪,執行剛才那個工具
停在工具執行前。 ADK 的工具發現沒有憑證,會發出一個叫 adk_request_credential 的事件,這一輪先停下來,由你的前端把使用者帶去同意頁。這跟 Day 4 送出退款前等主管核准是同一種停法:模型已經提出工具呼叫,還沒執行,等一個人回來。使用者按了拒絕或一直沒回來,Harness 要替這個工具呼叫回一個「使用者沒有授權」的結果,模型才接得下去。LangChain 的 Agent Auth(beta)也一樣,缺授權就中斷這一輪,把 OAuth 網址交給使用者。
回來的人要對得上。 使用者按完同意,GitHub 會把瀏覽器導回 App 事先登記的網址,附上授權碼。Harness 收下之前要確認兩件事。第一,這是不是自己發出去的那一次:發連結時附一個 state 參數,放一串隨機字串,記下它屬於哪位使用者、哪一輪,回來時字串要對得上,GitHub 的文件說這是用來防偽造的請求。第二,按同意的是不是發起的那個人:看這個瀏覽器現在登入你服務的是誰。MCP 規格舉過只做第一件的漏洞:A 把自己那條授權連結騙 B 點開,B 按了同意,字串對得上,B 的 token 卻記到 A 名下,之後 A 叫 Agent 做的事,用的都是 B 的帳號。
token 存在 Harness,模型拿不到。 換到的 token 照使用者分開存,執行工具的那一刻才取出來,工具參數裡沒有它;Day 20 說過,token 不能留在模型那一步。ADK 換到的 token 預設放在這段對話的狀態裡,文件自己也提醒,這些狀態存在哪裡、誰讀得到,決定了 token 安不安全,能拿來換新 token 的 refresh token 更要小心。OpenAI Agents API 的 vault(beta)把使用者的 OAuth 授權存在 Agent 的指示和設定之外,查詢時也不回傳 token 本身;Google 的 OAuth 建議是存放時要保護好、傳送時不能是明文,用不到就撤銷、刪掉。
GitHub 這種 token 開了到期設定時八小時過期,另外附一把六個月內有效的 refresh token,Harness 拿它換新的,使用者不用每天再按一次同意。
工具放在 MCP server 後面時,登入分兩段。 Day 14 提過,MCP 規格到 2025-03-26 版才加上以 OAuth 2.1 為基礎的授權;照現行的 2026-07-28 版規格,Agent 要先拿到 MCP server 認可的 token,才能呼叫它的工具。第一段是 Agent 登入 MCP server,Claude Code 已經內建:用 /mcp 或 claude mcp login 開瀏覽器登入,文件寫 token 會安全存放、自動更新,每個 server 網址各登入一次,在 /mcp 選單點「Clear authentication」就撤銷那一個。
第二段是 MCP server 要替使用者動 GitHub、Google 時,自己當 OAuth 的 App,請使用者再按一次同意,token 存在 server 這邊。規格寫明,第三方的 token 不能經過 Agent 那一端,server 也不能把 Agent 交給它的 token 轉給第三方。Cloudflare 的 remote MCP 文章就是這樣做:GitHub、Google 發的 token 加密存在 server,server 另外發一把自己的 token 給 Agent;Agent 這把被偷了,也只能做 server 開放的那幾件事。
負責發 token 的,也不一定要是 MCP server 自己。OAuth 2.1 規格的作者之一 Aaron Parecki 在〈Let's fix OAuth in MCP〉主張,MCP server 只要檢查別人發的 token,登入和發 token 交給公司原本就有的登入系統,不用每個 MCP server 各做一套;現行規格也允許這樣分開。
串好之後,服務那邊記下了什麼,各家不一樣。同樣是用使用者授權的 OAuth token 做事:
GitHub(GitHub App 代使用者開 PR)
畫面上是誰 → 使用者的頭像,旁邊加上 App 的小圖示
只停掉這個 Agent → 使用者在 GitHub 設定的 Authorized GitHub Apps 按 Revoke
哪裡看得到 App → 畫面上就有
Google 行事曆(App 代使用者新增行程)
行程上是誰 → 建立者只有使用者;API 文件列的欄位裡,沒有哪個 App 建的
只停掉這個 Agent → 使用者在 Google 帳號的第三方連結頁移除這個 App
哪裡看得到 App → Workspace 管理員的 OAuth 紀錄,有 App 的 client ID 和呼叫的 API 方法;只有 Enterprise 等較高階方案才有
出處分別是 GitHub 的撤銷授權說明、Google 行事曆的 Events 欄位文件、Google 帳號說明和 Workspace 的 OAuth 紀錄說明。兩邊都能只停掉 Agent,使用者自己的登入不受影響,這是 OAuth 比共用你的 gh token 好的地方。可是在行事曆上,Agent 加的行程跟使用者自己加的看起來一樣,要查只能靠管理員的紀錄,一般個人帳號沒有這個後台。
行事曆這種服務不會記下是哪個 App 做的,所以 Harness 要自己記。Microsoft 的 Agent 最小權限指引列的稽核欄位也是這幾樣:Agent 身分、代表哪位使用者、動了什麼資源、什麼時間、關聯 ID。
| 欄位 | 這個情境的值或用途 | 誰讀寫 |
|---|---|---|
| run_id | 這次工作的編號,例如開這個 PR 的這一輪 | Harness 建立,寫進紀錄 |
| actor | 誰在做:你的 Agent 這個 App,例如 GitHub 發給它的編號 client ID | Harness 從 App 設定帶入 |
| on_behalf_of | 代表誰:登入你的服務、按了同意的那位使用者 | Harness 從登入狀態帶入,不讓模型填 |
| scopes | 使用者同意給的範圍,例如能動哪些 repo、行事曆能不能寫 | 服務在授權時決定,Harness 記下 |
| action | 這次做了什麼,例如在哪個 repo 開 PR | Harness 執行工具時寫入 |
少了 actor 和 on_behalf_of,行事曆上那筆行程就分不出是使用者自己加的,還是 Agent 替他加的;少了 run_id,分得出來也對不回是哪一次工作。
def run_tool(run_id, user_id, tool, args, vault, audit):
grant = vault.get(user_id, tool.service) # 這位使用者連過才有;模型讀不到
if grant is None:
state = vault.begin_consent(user_id, run_id) # 隨機字串,記下是誰、哪一輪
return pause(run_id, consent_url=tool.service.authorize_url(state))
if grant.expired():
grant = vault.refresh(grant) # 用 refresh token 換新的,使用者不用再按一次
audit.write(run_id=run_id, actor=APP_CLIENT_ID, on_behalf_of=user_id,
scopes=grant.scopes, action=(tool.name, args))
return tool.call(args, token=grant.access_token) # token 只在這裡交給工具
| 誰呼叫 | 什麼時候 | 結果 |
|---|---|---|
| Harness | 模型提出開 PR,這位使用者還沒連過 GitHub | 這一輪暫停,使用者看到 GitHub 的授權連結;開 PR 的工具呼叫還沒有結果 |
| GitHub 把使用者帶回來 | 使用者按了同意 | Harness 比對 state,也確認瀏覽器登入的是同一位使用者,才換 token 存在他名下,接著執行開 PR |
| Harness | 使用者按了拒絕,或超過時間沒回來 | 替開 PR 的工具呼叫回「使用者沒有授權」,模型照這個回覆使用者 |
| Harness | 使用者連過,token 還有效或換得到新的 | 先寫進紀錄再執行,模型拿到 PR 網址 |
| 使用者,或 App 的擁有者 | 想停掉這個 Agent | 使用者在 GitHub 設定撤銷這個 App;App 的擁有者可以呼叫 GitHub 的撤銷授權 API,這位使用者在這個 App 底下的 token 會一起刪掉。他自己的登入不受影響 |
不需要使用者連帳號的工作,例如 Issue 留言觸發、排程掃 repo,可以照 claude-code-action 的做法,每輪換一把 App 自己的 installation token。GitHub 的文件寫,它一小時後過期,發的時候可以只給特定 repo 和權限;這一輪被取消,就拿那把 token 呼叫撤銷 API。這時 actor 是 App 的 bot,on_behalf_of 從觸發事件帶入,例如留言 @claude 的人;前面說過,它能做的事由 App 的權限決定,不會跟著叫它的人縮小。
Agent 要呼叫的是自家 API 的話,actor 和 on_behalf_of 可以直接寫進 token:照 RFC 8693,on_behalf_of 放 sub,actor 放 act,下游服務就不用另外查紀錄。
代使用者動外部服務,最好交給 Harness 自己寫的工具,像開 PR、加行程,模型只給參數。讓模型在 sandbox 裡自己跑 gh 的話,token 得放進指令的環境變數,Day 21 實測過讀得到;OpenAI 的 vault 遇到這種情況,給 sandbox 的環境變數只是一個佔位值,真的 token 留在 sandbox 外面。

圖:上方是本機和 GitHub Actions 並排:本機 Claude Code 用我的帳號、token 能動我所有的 repo、只停掉 Claude 做不到;GitHub Actions 裡的 Claude 用 App 的身分、commit 作者是 claude[bot]、叫它做事的人掛在尾巴、token 只限這個 repo 且一小時過期 → 下方是自己的 Agent 用 OAuth 代使用者開 PR:還沒連過 GitHub 就暫停這一輪、給他授權連結 → 使用者按同意,比對 state,token 存在他名下 → 寫進紀錄:哪一輪、App、代表誰、範圍 → 執行時才取 token,模型只拿到 PR 網址。這是示意,實作要照自己的工具和環境調整。
act 疊起來記,但它也寫明,做授權判斷時只看最外層正在做事的那一個,前面幾層只當參考。OpenID 白皮書把這種一層層往下交、權限要跟著一層層縮小的情況,列為接下來要處理的題目。這兩題先留著。
假設你已經做到 Day 21:Agent 跑指令的環境讀不到家目錄的憑證和不需要的環境變數。接下來確認它到了外部服務,頂著的是誰的名字。
先看 Agent 是哪一種。 請 Claude 跑一次 gh auth status 和 git config user.name,帳號是你、紀錄上沒有 Agent 自己的名字,就是 impersonation。其他會呼叫外部服務的工具也一樣,看它讀的是哪一份憑證。
署名留著,但別當證據。 attribution 保持預設,Co-Authored-By 留著方便自己查;它和作者欄都是文字,能改、能清空,追責任時要看推上去用的是哪把 token。
要分得出是誰做的,換成 delegation。 會被別人觸發、沒人在旁邊看、事後要查的工作,放到 GitHub Actions 用 claude-code-action 或 Copilot cloud agent。自己做的 Agent 要代使用者動 GitHub、Google,照上兩節讓使用者用 OAuth 授權給你的 App,token 存在 Harness、模型拿不到,紀錄寫下 actor 和 on_behalf_of。
只在自己電腦上、自己盯著用,事後也不需要分出哪些是 Agent 做的,可以做到第二步就停;代價是 GitHub 分不出哪些是 Agent 做的,出事也只能連你一起停。使用者在 GitHub 按的同意,給的是這個 App 能動哪些東西,沒有說這一次要開哪個 PR;Day 23 看有權執行之後,做的是不是使用者同意的那件事,Day 24 看 token 能開的門要多大,Day 28 再把授權和執行紀錄串成查得動的軌跡。
可以試著問自己兩題,一題回到開頭修 bug 的例子,一題換成你自己做的 Agent。第一題:同一個 commit,本機的 Claude Code 推上去和 claude-code-action 推上去,GitHub 各記下了誰?第二題:使用者用 OAuth 授權你的 Agent 動他的 Google 行事曆,Agent 替他加了一筆行程;一個月後他問這筆是不是 Agent 加的,要去哪裡查?
第一題,本機推的只記下我的帳號,是 impersonation。commit 尾巴那行 Co-Authored-By: Claude Opus 5.5 是模型照設定寫的文字,能改、能清空,證明不了是 Claude 做的。claude-code-action 推的記下 Claude 的 App,叫它做事的人也留在 GitHub 的留言和執行紀錄上,是 delegation。
第二題,行事曆上查不到:那筆行程的建立者只寫使用者,跟他自己加的看起來一樣。要查的是 Harness 自己的紀錄,哪一輪、哪個 App、代表誰、做了什麼都在上面。公司用 Google Workspace 的話,管理員的 OAuth 紀錄也看得到是哪個 App 呼叫的,但只有較高階的方案才有。服務不一定替你記,這就是 Harness 要自己記的原因。
用它自己的身分,再註明它代表你。Claude Code 在你電腦上跑 gh 用的是你登入的 token,GitHub 上看起來就是你本人,分不出是它做的,也沒辦法只停掉它。自己做的 Agent 要代使用者動 GitHub、Google,就讓使用者用 OAuth 授權給你的 App,token 存在 Harness、模型拿不到,也能單獨撤銷;服務沒標出 App 的,像 Google 行事曆,由 Harness 記下哪一輪、代表誰。
Day 21 收起了 Agent 在本機讀得到的東西,今天看它到了外部服務頂著誰的名字。接下來還有另一個問題:就算 Agent 有權執行,它現在要做的,還是你剛才同意的那件事嗎?
act 欄位標出實際做事的一方,疊起來的多層 act 只有最外層用來做授權判斷。gho_ 開頭是 OAuth access token。前綴只看得出 token 的種類,看不出是哪個 App 發的。attribution.commit 沒設時加上 Co-Authored-By 尾巴、設成空字串就不加、可換成任何文字。實驗結果是我在 macOS、Claude Code 2.1.285 上跑的。repo 能完整讀寫公開和私有 repo,admin:public_key 能完整管理公鑰;scope 不會給出使用者本來沒有的權限。@claude 觸發 Claude Code 的 workflow。allowed_non_write_users 可以放寬;commit 預設不簽章,可以改用 GitHub API 建 commit 讓 GitHub 標成 App 驗證過。claude[bot]。Co-authored-by。這是寫給模型的指示,不是 GitHub 檢查過的身分。state 放隨機字串防偽造的請求;token 只能動使用者和 App 都動得到的東西,開了到期設定時八小時過期、refresh token 六個月。adk_request_credential 事件、使用者授權回來後換 token 並重試工具;也提醒 token 放在 session 狀態的風險。這是 Google 框架的做法,不是標準。/mcp 和 claude mcp login 登入遠端 MCP server,token 安全存放、自動更新、每個網址分開,/mcp 選單的 Clear authentication 撤銷。文件沒寫 token 存在哪個檔案。creator 只有建立者的名稱、email、Profile ID,欄位裡沒有記錄是哪個 App 建的。行事曆網頁畫面我沒有實際看過。DELETE /installation/token 用要撤銷的那把 token 本身呼叫,撤銷後就不能再用。