用 Apps SDK 打造 ChatGPT App:MCP·OAuth 實作與審核回顧
大家好,我是 yeonghyeon,負責 3Min API 的開發。
過去幾週,我一直在處理 3Min API 的 ChatGPT Apps 註冊。中間被退件過一次,修正後才獲得通過,期間我們用同一份程式碼也提交到了 Claude Connectors。這篇文章是寫給走在同一條路上的開發者的整理:需要實作什麼、哪些地方容易被退件、審核環節實際在做什麼,我都放在了一起。
跟具體雲端服務或部署堆疊有關的部分,我刻意沒寫。不管底下用的是什麼,ChatGPT Apps 註冊的流程都是一樣的。
概述 — ChatGPT Apps 與作為基礎的 MCP
ChatGPT Apps 是 OpenAI 推出的擴充模型,讓你可以從 ChatGPT 內部呼叫外部服務。使用者在 ChatGPT 裡新增你的 app,在對話流程中可以直接呼叫你後端公開的工具。
它的基礎是 Model Context Protocol(MCP)。MCP 是連接 LLM 與外部工具的開放規範,定義了如何列出工具、如何安全地呼叫它們。ChatGPT Apps 是跑在 MCP 之上的客戶端之一,Anthropic 的 Claude Connectors 也建立在同一個規範上。也就是說,把 MCP 伺服器一次實作好,兩個生態都能涵蓋。我們也是用同一份程式碼同時提交到兩邊,工具定義和認證流程是直接共用的。
為什麼我們選擇成為工具,而不是做自己的 AI 聊天機器人
一開始我們也考慮過做自家的聊天機器人。但退一步看,使用者其實已經把自己的業務脈絡完整地告訴了 ChatGPT 或 Claude。如果我們再做一個聊天機器人,同一個人就要從頭再說一遍同樣的故事。
所以我們轉了方向。把 3Min API 當作工具,接進你已經在用的 AI 裡面。 平常你向 ChatGPT 抒發業務煩惱的那個對話框,現在可以直接說「那我來用 3Min API 幫你設定好」,並且真的把事情做完。我們仍然在評估自家的聊天機器人,但優先順序在工具化這邊。
實作
SDK 選擇 — 只用標準 MCP SDK
OpenAI 確實有提供一個 ChatGPT Apps 專用的 SDK,但我們沒走那條路。我們的伺服器只依賴一個東西:標準 MCP SDK(@modelcontextprotocol/sdk)。原因很單純:同一台伺服器要同時被 ChatGPT Apps 和 Claude Connectors 認得。只用標準 SDK 來寫,就不會因為某邊生態更新而讓程式碼分岔,我們也能把同一份建置產物原樣提交到兩個目錄。
OpenAI 這邊的規範整理在 Build your MCP server 與 Connect from ChatGPT。兩份文件都是從用戶端視角描述 ChatGPT 用戶端如何辨識和呼叫你的伺服器——只要把標準 MCP 伺服器確實實作好,OpenAI 那邊的要求自然會被滿足。
認證 — OAuth 2.1 為基本,API Key 在同一台伺服器上作為輔助
對 ChatGPT Apps 來說,實際上能選的認證就是 OAuth 2.1 一種。OpenAI 的 官方指南 上講得很明白:「ChatGPT does not support … custom API keys or customer-provided mTLS certificates」。也就是說,要提交到 ChatGPT Apps 目錄的 app,把 OAuth 2.1 實作好就足夠了(對於不會接觸使用者資料的工具,允許使用 noauth 匿名模式;但像我們這種會操作使用者帳號下的端點和記錄檔的工具,OAuth 是必要的)。
但是,如果你想讓同一台 MCP 伺服器也能在 Cursor、Claude Code、Gemini CLI 這類本機客戶端裡直接使用,情況就不一樣了。本機環境是使用者自己可以保管金鑰的地方,OAuth 流程在那裡反而顯得太重。所以我們選擇了 把 OAuth 2.1 當作 ChatGPT Apps·Claude Connectors 的基本認證,再在同一台伺服器上疊一條 API Key 路徑。同一份工具定義,在兩種認證下都能直接運作。
OAuth 2.1 — ChatGPT Apps 與 Claude Connectors 的基本認證
跑在託管環境裡的客戶端沒辦法讓使用者自己管金鑰,OpenAI 的政策上也沒有其他選項。要讓客戶端正確辨識我們的伺服器,以下標準必須到位。
- RFC 7591 — OAuth Dynamic Client Registration。客戶端自己完成註冊流程。
- RFC 8414 — Authorization Server Metadata。在
/.well-known/oauth-authorization-server公開認證端點。 - RFC 9728 — Protected Resource Metadata。公開 MCP 資源本身的中繼資料。
- RFC 7636 PKCE — 防止 authorization code 被中途攔截的 S256 challenge。
流程本身就是標準那一套。客戶端動態註冊 → 使用者登入後核發 authorization code(一次性,10 分鐘失效)→ 帶 PKCE 驗證做 token 交換 → access token(1 小時)+ refresh token(30 天,輪替)。access token 過期時用 refresh token 續發,每次續發連 refresh token 自身也輪替,以降低被竊用的風險。
實作裡最費心的一處是 確保 code 在原子層面只被消費一次。authorization code 是被中途攔截價值很大的資源,所以我們在 token 交換那一步,用單一 update 陳述把 code 一次 claim 起來,避免出現 race condition。
API Key — 讓同一份程式碼也能在 CLI/IDE 裡使用的輔助路徑
ChatGPT Apps 走 OAuth 進來,但我們希望同一份工具定義在 Cursor、Claude Code、Gemini CLI、Smithery 這類本機 MCP 客戶端裡也能直接使用,所以又疊上一條 API Key 路徑。這邊使用者自己可以保管金鑰,用 x-api-key 標頭帶核發過的 key 就最乾淨。我們核發帶 tm_mcp_ 前綴、按使用者區分的 key,並按 key 追蹤啟用/停用狀態與最後使用時間。
對外公開的 8 個工具,以及它們的權限標註
3Min API 對 ChatGPT/Claude 公開 8 個工具。每個工具都需要明確聲明 MCP 標準的三個 annotation。先看含義:
| annotation | 含義 | true 範例 |
|---|---|---|
readOnlyHint | 是否唯讀(不變更資料) | 查詢記錄檔/統計 |
destructiveHint | 是否會造成不可逆的變更 | 修改/刪除端點 |
openWorldHint | 是否會與外部世界通訊或產生副作用 | 送出外部 webhook |
把這三個值套到我們的 8 個工具,結果如下:
| 工具 | 說明 | readOnly | destructive | openWorld |
|---|---|---|---|---|
help | 查詢服務指南 | true | false | false |
endpoints | 端點 CRUD/部署 | false | true | false |
api_call | 呼叫端點 | false | true | true |
logs | 查詢呼叫記錄檔 | true | false | false |
stats | 用量統計 | true | false | false |
collaborators | 協作金鑰/邀請 | false | true | true |
subscription | 訂閱資訊 | true | false | false |
archives | 封存下載 | true | false | true |
刻意沒有公開的領域
帳號本身的刪除、付款方式變更、MCP 認證金鑰的核發與撤銷 這類一旦同意有偏差就無法回頭、或是直接牽動認證體系本身的動作,我們沒有暴露成工具。把這些交給 LLM 判斷,一次錯誤呼叫就能直接演變成資安事故,而且這也跟 ChatGPT Apps 審核指南推薦的方向不符。
測試 — 兩條認證路徑都跑一次比較穩
正式提交前,我們把兩條路徑都跑了一遍。
- OAuth 路徑 — 在 ChatGPT 網頁版的 Settings → Apps & Connectors → Advanced settings 開啟 Developer Mode,然後用 'Create app' 註冊我們的 MCP 伺服器 URL。ChatGPT 會自動去讀我們伺服器的
/.well-known/...來辨識 OAuth 中繼資料,所以可以親自走完同意畫面、直到實際呼叫工具。 - API Key 路徑 — 在 Claude Code、Cursor、Gemini CLI 加上 MCP 伺服器,驗證工具呼叫。同時也註冊到 Smithery,確認在目錄上能正常出現。
兩條路徑的程式碼本身是一樣的,但 OAuth 那邊還要再過 well-known 中繼資料、同意畫面、token 續發這幾關,所以多了一道難度。提交之前,建議你至少把 真正的 ChatGPT 連到你的伺服器、把工具清單拉下來 這一步親自跑一次。
提交審核 — 被退件一次之後才理解的事
提交本身,跟著 OpenAI 官方指南(app-submission-guidelines)邊看邊問 ChatGPT 也能順利完成。但在表單填寫階段,ChatGPT 會實際連進你的伺服器去拉工具清單,所以 提交當下你的正式環境必須已經上線。還要一併提供測試帳號資訊(電子郵件/密碼,或另開一個審核專用帳號),不然 OpenAI 的審核人員沒辦法直接呼叫工具。
注意事項 1 — 工具權限標註要保守
這是最常見的退件原因。我們第一次提交時,把三個會跟外部通訊的工具(api_call、collaborators、archives)的 openWorldHint 設成 false,結果就被退件。修正後才通過。
這三個裡面,archives 會核發外部下載 URL,openWorldHint=true 是顯而易見的。api_call(透過使用者定義的 webhook 觸發外部通訊)和 collaborators(向協作者發出邀請信)就比較間接,會讓人猶豫一下。事後看來,把這兩個也保守地標成 true 才是對的。
判斷標準其實很單純:一旦被退件,下一次審核又得再等大約兩週。 工具只要有任何往外通訊的流程,別猶豫,直接 true。從時間成本看這是最划算的做法。把每個工具產生的副作用一行一行寫下來,確認其中有沒有任何一條會傳到系統外,標註自然就會就位。
注意事項 2 — 截圖不是「螢幕擷圖」,而是「模板作業」
提交表單裡有一項要展示你的 app 在 ChatGPT 裡看起來是什麼樣的截圖。自己截圖直接上傳一定會被退件。 這一步 OpenAI 給了明確的指南,提交頁面裡也直接給了指南連結。流程是這樣:
- 提交表單到截圖這一步時,指南連結會把你導到 OpenAI 官方的 Figma 檔。
- 把那份 Figma 檔裡的 截圖模板複製到你自己的 Figma 工作區。
- 把你的 app 在 ChatGPT 裡實際運作的畫面 貼到模板裡指定的位置。比例、留白、構圖在模板裡都已經訂好,你只要把內容填進去就好。
- 把完成的畫板 匯出成圖片,在提交表單上傳。
也就是說,提交的成果不是單純的螢幕擷圖,而是 把你的 app 畫面放進 OpenAI 訂好的畫框裡得到的成品。提交前再過一次指南,照做就行。如果跳過這一步、自己擷圖丟上去,提交會直接被退件。
審核回顧 — 通過之後還有一步
從提交到出結果,大約要等兩週以上。被退件再修正後重投,通常還要再花差不多的時間。可以從 OpenAI 開發者控制台查看狀態,被退件或通過時都會收到電子郵件。
收到通過信並不代表已經上架。還要在控制台按一次 Publish 按鈕,一般使用者那邊才會看到。
上架之後還有一件事要留意。即使使用者已經把你的 app 加進去了,ChatGPT 也不會在每段對話裡都自動去用你的工具。就算話題相關,經常也會回出沒有工具呼叫的回覆。這種時候要 提醒使用者用 @ 提及來直接喚出你的 app。把這一點告訴使用者,工具使用率會明顯上升。
Claude Connectors 目前進度
Claude Connectors 跑在同一套 MCP 上。程式碼層面幾乎沒有額外要補的東西。但審核流程不像 OpenAI 那邊那麼整齊:沒有可以查詢提交狀態的控制台,我們提交快滿一個月了,還沒收到通過或退件的回覆。兩邊同時投是值得推薦的,但時程建議以 OpenAI 那邊為基準。
親自試一試
如果你想在 ChatGPT 裡試試 3Min API 的 MCP 工具,或者想看看我們具體公開了什麼,只要 在 ChatGPT Apps 新增畫面搜尋「3Min API」 就能安裝。完成一次認證之後,平常對話裡用 @3Min API 提及就能呼叫工具。
如果想從本機 MCP 客戶端(Claude Code、Cursor 等)試,登入後到 設定 → AI 整合 頁面核發 API Key,就能馬上用。每個工具的細節和呼叫範例,都整理在 AI 整合指南 裡。
願這篇文章能成為走在同一條路上的開發者的一條小捷徑。
Related Posts
現在,在 ChatGPT 裡就能打造 API —— 3Min API 已加入 ChatGPT Apps
3Min API 加入 ChatGPT Apps 了。不用寫程式碼、不用租伺服器,你就可以在 ChatGPT 的對話流程裡直接打造 API、做測試、把合作夥伴邀請進來。我們用一個剛起步的葡萄酒生意情境,帶你看看這件事到底代表什麼。
用 AI 管理你的 API:MCP 支援正式上線
3Min API 現已支援 MCP——連接你的 AI 助手,透過自然對話管理端點、查看日誌等。
什麼是 JSON?寫給非開發者店主的入門指南
一份為葡萄酒店店主故事收尾的 JSON 入門指南。從一張 Excel 表出發,沿著鍵、值、物件、陣列的遞迴結構走一遍,最後還帶一個「今天就能動手」的練習:把自己生意裡的一樁事寫成 JSON。無需任何前置知識。