MCP
MCP(Model Context Protocol)bridge 把 proto 裡標了 gortexa.ai.v1 annotations 的方法暴露成 tools。AI agent 對 /mcp 發 JSON-RPC,bridge 經 in-process gRPC loopback 呼叫原本的服務——AI 的呼叫跟一般請求過同一條攔截器鏈,auth 與 validation 一段不少。
在 rpc 上加 gortexa.ai.v1.ai_tool annotation:
rpc GetResource(GetResourceRequest) returns (Resource) { option (google.api.http) = {get: "/v1/resources/{id}"}; option (gortexa.ai.v1.ai_tool) = { expose: true name: "get_resource" description: "Fetch a single resource by id and return its current state." read_only: true };}read_only 與 destructive 會進入 tool schema 的行為提示。沒標 expose: true 的方法不會出現在 tools 清單。
Endpoint
Section titled “Endpoint”- 路徑:
/mcp(Streamable HTTP) - Protocol versions:
2025-03-26(預設)與2024-11-05 - Request body 上限 1 MiB、讀取逾時 30 秒
- JSON-RPC batch 最多 100 個 element;超過回 413 與 JSON-RPC error
-32000 "batch too large"(在進入攔截器鏈之前就擋下) - Bridge 是無狀態的:不發放也不讀取
Mcp-Session-Id,不保留任何 session 狀態,每個請求各自以自己的憑證授權 - 被拒的
Origin與超量的 batch 各自以 WARN 經slog.Default()記錄(附 origin/element 數與 client IP)——先前這兩者只回一個狀態碼、對維運沒有任何紀錄 - Browser-based client 需要 CORS 時開
server.enable_cors,並把允許的 origin 列進server.cors_origins——這個 allowlist 就是防 DNS rebinding 的機制,Origin沒列在上面的請求會收到403 forbidden origin,且"*"在這裡會被忽略(每個 browser origin 都要明確列出)
tools/list
Section titled “tools/list”curl -XPOST localhost:8080/mcp \ -H 'Content-Type: application/json' \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'回傳所有標注方法的 tool schema。清單是 memoized 的(約 142 ns 一次),不會每次呼叫重算。
tools/call
Section titled “tools/call”tools/call 的參數被序列化成 protobuf 訊息、經 loopback 打到原服務,結果再轉回 JSON-RPC。沒過 auth 就得到 unauthenticated 的 error envelope,跟 gRPC、HTTP 的行為一致。Authorization 與 X-Request-Id 只在位元組是合法 gRPC metadata(可列印 ASCII)時才轉送到 loopback;無效值直接丟棄而不傳播,呼叫端因此仍拿到鏈的真實答案(例如 unauthenticated)而非不透明的 internal,request id 則由下游重新鑄造。超過 8 KiB 的 Authorization 值同樣會被丟棄:真實憑證頂多幾 KB,而 bridge 會把這個標頭重新編碼到 batch 中每一個 element 的 loopback 呼叫上(最多 100 次),所以過大的值是放大攻擊向量而不是憑證。
Schema 匯出
Section titled “Schema 匯出”同一份 gortexa.ai.v1 annotations 可以離線輸出成 provider-ready 格式:
gortexa export --format=mcpgortexa export --format=openai # OpenAI strict function callinggortexa export --format=gemini三種輸出都有 golden test 鎖定:proto 改了,schema 跟著變,測試會抓到意外的漂移。
怎麼把 gRPC service 開成給 LLM 用的 MCP tools?
Section titled “怎麼把 gRPC service 開成給 LLM 用的 MCP tools?”在 proto 的 method 上標 gortexa.ai.v1 annotations,然後把該 service 加進 mcp.ServiceDescriptors(...) 並用 mcp.NewBridge 掛到 /mcp。schema 由 proto 產生,不必另外手寫工具定義。
MCP 的 tool call 會經過我的 auth interceptor 嗎?
Section titled “MCP 的 tool call 會經過我的 auth interceptor 嗎?”會。tools/call 透過 in-process loopback 派送回同一個 gRPC server,所以它和任何一般請求一樣,要走完 recover、request-id、logging、load shedding、rate limiting、斷路器、auth 與 validation。
MCP endpoint 需要 session 嗎?
Section titled “MCP endpoint 需要 session 嗎?”不需要。Bridge 是無狀態的:不發放也不讀取 Mcp-Session-Id,每個請求各自以自己的憑證授權。
瀏覽器裡的 MCP client 要怎麼設定?
Section titled “瀏覽器裡的 MCP client 要怎麼設定?”開 server.enable_cors 並把允許的 origin 列進 server.cors_origins。那份 allowlist 同時是 DNS rebinding 的防線——沒列進去的 origin 發出的請求會被以 403 forbidden origin 拒絕,並記一行 WARN。CORS 視為全部允許的 "*",這道防線刻意忽略,所以每個 browser origin 都要明確列出。