跳到內容

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 清單。

  • 路徑:/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 都要明確列出)
Terminal window
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 的參數被序列化成 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 次),所以過大的值是放大攻擊向量而不是憑證。

同一份 gortexa.ai.v1 annotations 可以離線輸出成 provider-ready 格式:

Terminal window
gortexa export --format=mcp
gortexa export --format=openai # OpenAI strict function calling
gortexa 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。

不需要。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 都要明確列出。