Appearance
Remote MCP 連接(Claude 與 ChatGPT)
本手冊說明如何讓本專案的 /mcp 以 OAuth-compatible remote MCP 方式接到 Claude remote connector 與 ChatGPT 自定義應用程式 / connector,並保留 legacy Bearer token + Desktop bridge 作為 migration / internal tooling 路徑。
結論先講
- 正式主路線已改為:既有本地帳號 + known connector allowlist + OAuth-compatible remote MCP
- 正式 consumer 已涵蓋:
- Claude remote connector:可走 known connector allowlist
- ChatGPT 自定義應用程式 / connector:可走 ChatGPT Dynamic Client Registration(DCR)
Authorization: Bearer <legacy token>仍可用,但定位只限 migration、Inspector、內部驗證與非使用者型 automation- 若要給一般使用者直接授權使用,不要再引導他們手貼 legacy token
架構摘要
text
Claude remote connector
-> GET /api/auth/mcp/authorize
-> 使用者以既有 better-auth 帳號登入
-> consent UI 確認 granted scopes
-> POST /api/auth/mcp/authorize
-> POST /api/auth/mcp/token
-> Bearer <oauth access token> 呼叫 /mcp
-> middleware 解析 principal.userId
-> role / guest policy / restricted replay 沿用既有治理同一個 /mcp endpoint 仍同時接受:
- OAuth access token:正式 remote connector 路線
- legacy MCP token:migration-only 路線
ChatGPT 自定義應用程式會多走一次 dynamic registration:
text
ChatGPT Create connector
-> GET /.well-known/oauth-protected-resource
-> GET /.well-known/oauth-authorization-server
-> POST /api/auth/mcp/register
-> 回傳 client_id metadata document URL
-> ChatGPT OAuth 授權流程接回 /auth/mcp/authorize
-> POST /api/auth/mcp/token
-> Bearer <oauth access token> 呼叫 /mcp必備設定
1. Runtime config
以下變數會影響 remote connector rollout:
| 變數 | 用途 | 建議值 |
|---|---|---|
NUXT_KNOWLEDGE_MCP_CONNECTOR_CLIENTS_JSON | known client allowlist | Claude 至少包含 claude-remote;ChatGPT DCR 不必預先配置 |
NUXT_KNOWLEDGE_MCP_ACCESS_TOKEN_TTL_SECONDS | access token TTL | 600 |
NUXT_KNOWLEDGE_MCP_AUTHORIZATION_CODE_TTL_SECONDS | authorization code TTL | 120 |
NUXT_KNOWLEDGE_MCP_CONNECTOR_CLIENTS_JSON 範例:
json
[
{
"clientId": "claude-remote",
"enabled": true,
"allowedScopes": [
"knowledge.ask",
"knowledge.search",
"knowledge.category.list",
"knowledge.citation.read"
],
"environments": ["production"],
"name": "Claude Remote",
"redirectUris": ["https://claude.ai/api/mcp/auth_callback"]
}
]注意事項:
- 這是 allowlist config,不是 secret;可用
wrangler secret put或vars管理,但 production 仍建議走受控流程更新 - 若值缺失、JSON 格式錯誤、或不是陣列,Nuxt 啟動會直接失敗,避免 silent misconfig
- 若 registry 為空,remote connector 授權流程會在
/api/auth/mcp/authorize直接拒絕 unknown client - Anthropic 官方目前的 Claude OAuth callback URL 是
https://claude.ai/api/mcp/auth_callback;若之後官方變更,redirectUris也必須跟著更新 - ChatGPT DCR 會由
/api/auth/mcp/register產生client_idmetadata document URL;目前只接受https://chatgpt.com/connector/oauth/<callback_id>與 legacyhttps://chatgpt.com/connector_platform_oauth_redirect
2. 本地帳號前提
使用者必須先有本系統既有帳號。授權流程 不會 自動建帳。
允許的登入來源:
- Google OAuth
- Passkey(若 feature flag 開啟)
若 session 沒有對應本地 user.id,授權頁會顯示「無法辨識本地帳號」並拒絕繼續。
Claude remote connector 上線流程
Operator 準備
- 設好
NUXT_KNOWLEDGE_MCP_CONNECTOR_CLIENTS_JSON - 確認 client 的
redirectUris、allowedScopes、environments正確 - 確認部署環境可從外網存取
/api/auth/mcp/authorize、/api/auth/mcp/token、/mcp - 確認測試帳號已可登入本系統,且角色 / guest policy 符合預期
使用者授權流程
- Claude 送使用者到
/auth/mcp/authorize?... - 未登入者先看到本地帳號登入卡片
- 已登入者看到 consent 卡片,列出:
- 目前授權帳號
- connector 名稱
- requested / granted scopes
- 使用者按「允許並繼續」後,系統發 authorization code 回 connector
- connector 用 code 打
/api/auth/mcp/token - 之後以
Bearer <oauth access token>呼叫/mcp
Claude Desktop 實際操作步驟
以下步驟是站在「你已經把本站部署到公開網址,且 runtime config 已設好」的前提。
- 打開 Claude Desktop。
- 進入
Settings > Connectors。 - 點
Add connector或Add custom connector。 Connector name輸入任意名稱,例如Yuntech RAG。Connector URL輸入你的遠端 MCP endpoint,例如https://agentic.yudefine.com.tw/mcp。- 若 UI 有
Advanced settings:OAuth Client ID填claude-remoteOAuth Client Secret留空
- 按
Add。 - 在 connector 列表找到剛新增的項目,按
Connect。 - Claude 會開啟本專案的
/auth/mcp/authorize授權頁。 - 用本系統既有帳號登入。
- 在 consent 頁確認 scope 與帳號資訊後,按「允許並繼續」。
- 回到 Claude Desktop,開新對話。
- 在對話左下
+的Connectors裡把這個 connector 打開。 - 先測一個 browse-safe 問題,例如「列出知識庫分類」或「搜尋某個主題」。
ChatGPT 自定義應用程式 MCP 上線流程
2026-04-24 依 OpenAI Apps SDK / Developer mode 文件確認:ChatGPT Create connector 需要公開 HTTPS
/mcpendpoint;OAuth connector 支援 static credentials 或 Dynamic Client Registration。OpenAI 文件同時建議用 developer mode、API Playground、MCP Inspector 與 golden prompts 做驗證。
Server 端準備
- 確認部署網域是公開 HTTPS。
- 確認以下路徑未被 WAF / auth middleware 擋住:
/.well-known/oauth-protected-resource/.well-known/oauth-protected-resource/mcp/.well-known/oauth-authorization-server/api/auth/mcp/register/api/auth/mcp/chatgpt-client-metadata/auth/mcp/authorize/api/auth/mcp/token/mcp
- 確認 OAuth metadata 會公告:
authorization_endpointtoken_endpointregistration_endpointcode_challenge_methods_supported: ["S256"]token_endpoint_auth_methods_supported: ["none"]
- 確認測試帳號已可用 Google OAuth 或 Passkey 登入本系統。
ChatGPT DCR 不需要在 NUXT_KNOWLEDGE_MCP_CONNECTOR_CLIENTS_JSON 預先放 client;ChatGPT 會呼叫 /api/auth/mcp/register,server 會回傳一個 metadata document URL 形式的 client_id。後續 /auth/mcp/authorize 會讀取該 metadata document,檢查 redirect URI 是否為 ChatGPT callback,再進入既有 consent 流程。
ChatGPT 實際操作步驟
- 打開 ChatGPT web。
- 進入
Settings > Apps & Connectors > Advanced settings,開啟Developer mode。 - 回到
Settings > Connectors,點Create。 - 填入:
Connector name:例如Yuntech RAGDescription:說明何時使用本知識庫,例如「Use this when the user asks questions about the Yuntech project report, source documents, SOPs, or governed knowledge base.」Connector URL:公開 MCP endpoint,例如https://agentic.yudefine.com.tw/mcp
- 點
Create。成功後應看到 server advertised tools。 - 開新對話,從 composer 附近的
+/More選取剛建立的 connector。 - 先測 browse-safe prompt:
- 「使用 Yuntech RAG connector 列出知識庫分類。」
- 「只使用 Yuntech RAG connector 搜尋專題報告的 MCP 相關內容。」
- 檢查 ChatGPT 顯示的 tool payload,確認輸入、輸出與權限提示符合預期。
ChatGPT static credentials fallback
若 ChatGPT UI 或企業管理流程要求手動填 static OAuth client,而不是 DCR,可以改用 known connector allowlist:
json
[
{
"clientId": "chatgpt-custom-app",
"enabled": true,
"allowedScopes": [
"knowledge.ask",
"knowledge.search",
"knowledge.category.list",
"knowledge.citation.read"
],
"environments": ["production"],
"name": "ChatGPT Custom App",
"redirectUris": [
"https://chatgpt.com/connector/oauth/<callback_id>",
"https://chatgpt.com/connector_platform_oauth_redirect"
]
}
]<callback_id> 以 ChatGPT app management 頁面顯示的 production redirect URI 為準。設定後重新部署,並在 ChatGPT static client 設定中填 chatgpt-custom-app;client secret 留空,因為本專案的 token endpoint 使用 public client + PKCE。
ChatGPT 驗證清單
GET /.well-known/oauth-protected-resource回傳resource: https://<domain>/mcpGET /.well-known/oauth-authorization-server包含registration_endpoint- ChatGPT 建立 connector 時可成功列出 tools
- 未登入授權頁會要求本地帳號登入
- 已登入授權頁會顯示 consent 與 granted scopes
- 同意後 ChatGPT 能以 OAuth access token 呼叫
/mcp listCategories/searchKnowledge成功askKnowledge依角色與 guest policy 成功或被正確阻擋- restricted citation replay 仍需
knowledge.restricted.read
Metadata 與安全注意事項
- Connector description 會影響 ChatGPT 何時選用本 connector;描述要明確寫「Use this when...」,也要寫不該使用的情境。
- Tools 若只是讀取或查詢,metadata 應盡量標示 read-only hint;寫入或破壞性 tool 必須保留人工確認與 server-side validation。
- Tool result 的 structured content 只放當次回答需要的資料,不要把 token、secret、完整 PII 或過量原文塞進回傳。
- 所有 tool call 都必須在 server 端重新驗證 scope、角色、guest policy 與 restricted access;不要信任模型傳入的參數。
- 用 golden prompts 做回歸:direct、indirect、negative 三類都要測,避免 ChatGPT 在不該使用 connector 時誤觸。
Operator 最短清單
如果你是要幫使用者先把 server 端準備好,最少要完成這四件事:
- 在部署環境設定:
bash
NUXT_KNOWLEDGE_MCP_ACCESS_TOKEN_TTL_SECONDS=600
NUXT_KNOWLEDGE_MCP_AUTHORIZATION_CODE_TTL_SECONDS=120
NUXT_KNOWLEDGE_MCP_CONNECTOR_CLIENTS_JSON='[
{
"clientId": "claude-remote",
"enabled": true,
"allowedScopes": [
"knowledge.ask",
"knowledge.search",
"knowledge.category.list",
"knowledge.citation.read"
],
"environments": ["production"],
"name": "Claude Remote",
"redirectUris": ["https://claude.ai/api/mcp/auth_callback"]
}
]'- 重新部署。
- 確認外網可連到
/mcp、/api/auth/mcp/authorize、/api/auth/mcp/token。 - 先手動打開以下 URL,確認授權頁能正常顯示:
text
https://<your-domain>/auth/mcp/authorize?client_id=claude-remote&redirect_uri=https://claude.ai/api/mcp/auth_callback&scope=knowledge.ask%20knowledge.search%20knowledge.category.listChatGPT DCR 路線可另外用以下 smoke request 確認 registration endpoint:
bash
curl -s -X POST "https://<your-domain>/api/auth/mcp/register" \
-H "Content-Type: application/json" \
-d '{
"client_name": "Yuntech RAG",
"redirect_uris": ["https://chatgpt.com/connector/oauth/callback_123"]
}' | jq .回應中的 client_id 應是 https://<your-domain>/api/auth/mcp/chatgpt-client-metadata?...,且 redirect_uris 保留 ChatGPT callback。
Smoke checklist
- 未登入打授權頁,看到登入卡片而不是 500
- 已登入 member 打授權頁,看到 consent 與正確 scope
- 拒絕授權時,redirect URI 收到
error=access_denied - 同意授權後,token exchange 拿到
access_token、token_type=Bearer - 用 access token 打
/mcp:listCategories/searchKnowledge成功askKnowledge成功或依 guest policy 被正確阻擋- restricted replay 仍需
knowledge.restricted.read
Guest policy 與權限語意
OAuth principal 與 Web 使用相同的本地使用者真相:
admin/member:正常依 scope 存取guest+same_as_member:照 member 規則guest+browse_only:可用searchKnowledge/listCategories/getDocumentChunk,askKnowledge會被拒絕guest+no_access:所有 MCP tools 都會回ACCOUNT_PENDING
這些規則對 OAuth access token 與 legacy token 共用同一套 knowledge.* scope vocabulary。
Legacy Bearer token 路徑
legacy MCP token 仍存在,但用途改為:
- migration 期間的相容驗證
- MCP Inspector / curl / integration smoke
- 本機 Claude Desktop stdio bridge
- 明確受控的 non-user automation
不建議用途:
- 一般使用者 remote connector
- 文件把它寫成與 OAuth 並列的正式接入方式
Claude Desktop bridge
若現在就要在本機接 Claude Desktop,可繼續用:
scripts/claude-desktop-mcp-bridge.mjs
bridge 仍會:
- 接收本機 stdio JSON-RPC
- 轉送到遠端
/mcp - 自動附上
Authorization: Bearer <legacy token>
這條路徑是 workaround,不是正式 remote connector onboarding。
失敗處置與 rollback
立即停用 remote connector
若 rollout 出現 blocking issue,可先:
- 將
NUXT_KNOWLEDGE_MCP_CONNECTOR_CLIENTS_JSON中對應 client 的enabled改為false - 重新部署
- 保留 legacy token / bridge 路徑做暫時回退
常見失敗點
| 症狀 | 可能原因 | 處置 |
|---|---|---|
/api/auth/mcp/authorize 回 Unknown MCP connector client | allowlist 未配置或 clientId 不符 | 檢查 NUXT_KNOWLEDGE_MCP_CONNECTOR_CLIENTS_JSON |
/api/auth/mcp/authorize 回 Redirect URI is not allowed | redirect URI 未在 allowlist | 補上正確 redirect URI 後重新部署 |
| 授權頁顯示「無法辨識本地帳號」 | session 沒有本地 user.id | 先完成一般登入 / account linking |
/api/auth/mcp/token 回 Authorization code is invalid or expired | code 過期或重複使用 | 重新走一次授權流程 |
OAuth token 打 /mcp 仍被 403 | guest policy / scope / restricted rule 命中 | 檢查使用者角色、scope 與 policy |
驗證對應
- integration:
test/integration/mcp-connector-authorize-route.test.tstest/integration/mcp-connector-authorize-post-route.test.tstest/integration/mcp-connector-token-route.test.tstest/integration/mcp-oauth-metadata-routes.test.tstest/integration/mcp-oauth-tool-access.test.ts
- unit:
test/unit/mcp-connector-clients.test.tstest/unit/mcp-connector-client-registry.test.tstest/unit/mcp-middleware.test.tstest/unit/mcp-role-gate.test.ts
- e2e:
e2e/mcp-connector-authorize.spec.ts
- legacy bridge:
test/integration/claude-desktop-mcp-bridge.test.ts