05|把後端接成 MCP 工具
你要完成什麼
Section titled “你要完成什麼”Agent 透過 MCP 探索業務資料與呼叫查詢。MCP 是協定介面;真正的 middleware 是後面的身分驗證、輸入限制、SQL 建構與憑證管理程式。
1. 看懂三個工具
Section titled “1. 看懂三個工具”| 工具 | 輸入 | 輸出 |
|---|---|---|
whoami |
無 | 驗證後的使用者、角色與資料範圍 |
describe_business_data |
無 | 業務定義、欄位、輸入 Schema 與限制 |
query_orders |
query 物件 |
訂單、實際 SQL、參數、分頁、request ID、撤銷結果 |
官方 Python MCP SDK 2.3.0 與 FastAPI 共用同一服務;sso/mcp_api.py 負責協定與 OAuth,sso/orders.py 負責參數及 SQL,sso/bao.py 共用短效憑證流程。
2. 配置專屬 OAuth client
Section titled “2. 配置專屬 OAuth client”完成前章後,在自己的主機執行:
python3 scripts/configure_mcp.pydocker compose up -d --build --no-deps ssodocker compose exec -T gateway nginx -s reload建立 textile-codex public client,使用 PKCE S256、scope orders:read,audience 綁定完整 MCP URL。沒有 client secret、password grant 或 wildcard callback。既有 Web 與 Grafana clients 保持獨立。
Nginx 已包含 MCP 與 protected-resource metadata 路徑。Tailscale 還要轉送 discovery:
tailscale serve --bg --https=28100 --set-path=/.well-known/oauth-protected-resource/textile/mcp http://127.0.0.1:28400/.well-known/oauth-protected-resource/textile/mcp3. 檢查輸入契約
Section titled “3. 檢查輸入契約”{ "query": { "as_of": "2026-10-20", "overdue_only": true, "remaining_only": true, "sort_by": "oldest_due", "limit": 10, "offset": 0 }}可另加 customer_id、status、order_date_from、order_date_to。排序僅允許 oldest_due、largest_remaining、newest_order。每頁 1–50 筆、offset 0–5000;日期 2020–2100,不接受反向日期範圍。
不能傳 sql、user、租戶 ID 或資料庫密碼。參數必須是預定型別;多餘欄位拒絕。每頁上限不等於累積匯出額度,這仍是後續要補的控制。
4. 試一次負面案例
Section titled “4. 試一次負面案例”把 limit 改成 500,或加入 sql: "SELECT * FROM hr.payroll"。預期工具拒絕輸入,而不是讓模型自行決定要不要遵守。
後端仍會驗證 JWT 的簽章、issuer、MCP URL audience、期限、subject、Bearer 類型及 client,然後驗證 scope 與業務角色。Portal 的 Token 不能拿來當 MCP Token。
5. 執行契約與資料存取測試
Section titled “5. 執行契約與資料存取測試”docker compose exec -T sso python - < scripts/verify_mcp.py預期 32 項通過,包括錯誤簽章/audience/scope、HR 拒絕、輸入注入、排序、分頁、範圍外客戶為空及撤銷。驗證使用測試簽章鍵,但 OpenBao 和 PostgreSQL 是真實服務;下一章再用真實 OAuth Agent 驗證。
若要支援「按客戶彙總」,先寫清楚單位、取消單處理、範圍與結果上限,再新增輸入 Schema 與參數化查詢。不要把受控工具直接改成 execute(sql: str) 就視為完成安全的動態 SQL。