跳至主要內容

指南

MCP 伺服器

讓 Agent 調用你系統裡的工具。

MCP(Model Context Protocol)是 Agent 調用外部工具的開放協議。把你的系統(例如訂單查詢、工單系統、內部 API)封裝成一個遠端 MCP 伺服器,註冊到項目後,在建立會話時用 mcp_servers 指定,這個會話的每一輪開始時平台都會連接它,連上後 Agent 就能調用它的工具。

與技能的區別:技能是說明和腳本,在平台的沙箱裡執行;MCP 伺服器由你託管,Agent 遠端調用,適合需要訪問你內網數據、帶權限控制、或邏輯經常變化的場景。兩者可以同時使用,例如技能裡寫「查訂單用 shop 的 lookup_order 工具」。

你的伺服器需要滿足

  • 傳輸:MCP 的 Streamable HTTP 傳輸(2025-03-26 及之後的規範),一個 https 端點,通常以 /mcp 結尾。舊的 HTTP + SSE 傳輸(/sse 端點)不支援。證書必須是有效的公網證書,自簽名證書無法通過。
  • 可達性:平台從自己的伺服器連接你的端點,所以地址必須是公網地址,不能解析到內網、本機或鏈路本地地址(例如 10.x、192.168.x、127.0.0.1、169.254.x)。平台不跟隨 HTTP 跳轉,請直接填最終地址。
  • 鑑權:三種方式之一——不鑑權、Authorization: Bearer <token>、或自訂請求頭(例如 X-Api-Key)。憑證是靜態的;不支援需要瀏覽器授權的 OAuth 流程。
  • 工具:透過 tools/list 列出。註冊時最多保留 256 個工具,名字 ≤ 128 字元,描述取前 500 字元存檔(Agent 調用時看到的是完整描述)。每個工具請寫清楚用途、參數含義和返回內容——Agent 只能根據名字和描述決定何時調用、怎麼填參數。
  • 副作用:工具會被 Agent 自動調用,平台不會在調用前徵求人工確認。對有副作用的操作(下單、退款、刪除),請在伺服器端做好權限驗證和冪等處理,或者不要暴露給 Agent。

一個最小的 Python 伺服器(mcp SDK 2.x + uvicorn),帶 Bearer 鑑權:

import os
import uvicorn
from mcp.server.mcpserver import MCPServer
from mcp.server.transport_security import TransportSecuritySettings

TOKEN = os.environ["MCP_TOKEN"]
server = MCPServer(name="shop-mcp", version="0.1")


@server.tool(description="按訂單號查詢訂單狀態。")
def lookup_order(order_number: str) -> str:
    return f"訂單 {order_number}:已發貨"


# 在反向代理(nginx 等)後面時,SDK 預設會拒絕它不認識的 Host;關掉這項檢查,
# 或改為 TransportSecuritySettings(allowed_hosts=["mcp.example.com"])。
mcp_app = server.streamable_http_app(
    stateless_http=True,
    transport_security=TransportSecuritySettings(enable_dns_rebinding_protection=False),
)


async def app(scope, receive, send):
    """Bearer 驗證,其餘交給 MCP SDK。"""
    if scope["type"] == "http":
        headers = dict(scope["headers"])
        if headers.get(b"authorization") != f"Bearer {TOKEN}".encode():
            await send({"type": "http.response.start", "status": 401, "headers": []})
            await send({"type": "http.response.body", "body": b"unauthorized"})
            return
    await mcp_app(scope, receive, send)


if __name__ == "__main__":
    uvicorn.run(app, host="127.0.0.1", port=8017)

用 nginx 等反向代理加上 https,端點就是 https://your-domain/mcp。

註冊

註冊時平台會先探測一次:用你給的憑證完成 MCP 握手,列出工具(最長等 60 秒)。通過才保存,地址或憑證寫錯會在這一步報錯。

curl -s "$AXON_API/mcp-servers" \
  -H "Authorization: Bearer $AXON_KEY" -H "Content-Type: application/json" \
  -d '{
        "name": "shop",
        "url": "https://mcp.example.com/mcp",
        "auth": {"type": "BEARER", "token": "your-mcp-token"},
        "allowed_tools": ["lookup_order", "create_ticket"]
      }'
  • name:工具的命名空間,項目內唯一。改名會改變工具名。
  • url:建立後不能改;要換地址,刪掉重新註冊。同一個地址在項目內只能註冊一次。
  • auth:{"type": "NONE"}、{"type": "BEARER", "token": "…"} 或 {"type": "HEADER", "name": "X-Api-Key", "value": "…"}。憑證加密保存,任何接口都不會返回它;回應裡的 auth 只有類型(和請求頭的名字)。
  • allowed_tools:只讓 Agent 使用這些工具,名字必須在探測到的 tools 裡,否則返回 422 unknown_mcp_tool。不填或 null 表示全部。注意區別:null 時你的伺服器之後新增的工具,下一輪會自動可用;設了白名單時,新工具要先用 PATCH 加進白名單。
  • 回應裡的 tools 是探測到的工具快照,server_name 是伺服器自報的名字。

探測失敗返回 422 mcp_probe_failed,message 說明原因:

message 開頭含義
TLS verification failed證書無效、過期或域名不匹配
The MCP server rejected the credential (401) / (403)憑證錯誤,或鑑權方式填錯(例如該用 HEADER 卻填了 BEARER)
The server answered, but not with MCP地址指向了網頁或其他接口,不是 Streamable HTTP 端點;舊的 /sse 端點也會這樣
The MCP server answered HTTP 5xx/4xx伺服器報錯,看你那邊的日誌
The MCP server did not finish … in time60 秒內沒完成握手和列出工具
The MCP server could not be reached連不上:端口未開放、防火牆、DNS 等,後面附具體錯誤

地址本身不合規(不是 https、解析到內網等)返回 422 invalid_mcp_server_url。

在會話中使用

建立會話時用 mcp_servers 指定伺服器 ID(最多 10 個,需要 mcp_servers:read 權限)。和模型、指令一樣,會話的 MCP 伺服器建立後不能改;要換,就新建會話。

curl -s "$AXON_API/sessions" \
  -H "Authorization: Bearer $AXON_KEY" -H "Content-Type: application/json" \
  -d "{\"model_id\": \"deepseek-v4-flash\", \"mcp_servers\": [\"$MCP\"]}"

每一輪裡發生的事:

  1. 輪次開始時,平台用註冊時的憑證連接會話指定的所有伺服器(並行,每個最多等 20 秒),列出工具,交給 Agent。連接每輪新建、本輪結束斷開,你的伺服器不需要維持長連接。
  2. 這些工具與內置工具的調用方式相同:agent.tool_use 的 name 為 mcp__<name>__<工具名>,input 是工具參數;你的伺服器返回的結果出現在 agent.tool_result 的 content 裡(文字;過長會截斷)。伺服器返回的錯誤會以 is_error: true 交給 Agent,由 Agent 決定是否調整參數重試。
  3. 每次連接的結果記錄在伺服器上:成功寫 last_connected_at 並清空 last_connect_error,失敗寫 last_connect_error。排查「Agent 沒有調用我的工具」時先看這兩項。
{"type": "agent.tool_use", "name": "mcp__shop__lookup_order", "input": {"order_number": "A1001"}, …}
{"type": "agent.tool_result", "content": "訂單 A1001:已發貨", "is_error": false, …}

工具名的規則:mcp__<name>__<工具名>。伺服器名稱裡的連字元變成底線,例如 my-shop 的工具叫 mcp__my_shop__lookup_order;工具名裡字母、數字、底線以外的字元也替換成底線;整體超過 64 字元時截斷並附一段短哈希。

連接失敗時(伺服器掛了、憑證失效、超過 20 秒):這一輪 Agent 沒有該伺服器的工具,並被明確告知「這些工具本輪不可用,不要調用」,輪次照常進行,其他伺服器不受影響;下一輪會重新連接。失敗原因寫在 last_connect_error 裡,查詢 MCP 伺服器可以看到。

修改與維護

要做什麼怎麼做影響
換憑證(輪換 token)PATCH 傳新的 auth用新憑證重新探測,通過才保存;已有會話下一輪起用新憑證
改名PATCH 傳 name工具名隨之改變,已有會話下一輪起看到新名字
調整白名單PATCH 傳 allowed_tools,null 取消限制名字必須在當前 tools 裡;下一輪生效
伺服器新增或刪除了工具POST …/probe 重新探測刷新 tools 快照(白名單為 null 時,Agent 每輪連接時拿到的已是最新工具,探測只更新接口裡看到的快照)
換地址刪除後重新註冊新的 ID;引用舊 ID 的會話從下一輪起沒有它的工具
刪除DELETE已指定它的會話不受影響,但從下一輪起不再連接,Agent 不再有它的工具(不會收到提醒);已發出的事件不變;名字和地址可以給新伺服器使用

接口細節見修改 MCP 伺服器、重新探測、刪除 MCP 伺服器。

安全

  • 只接受 https 和公網地址;連接時再次驗證,並且連接固定到驗證過的 IP、不跟隨跳轉,防止透過 DNS 把平台引向內網。
  • 憑證加密保存,只在連接你的伺服器時解密使用;接口不返回,日誌裡也不記錄。
  • 平台從自己的伺服器發起連接。如果你的伺服器按來源 IP 限制訪問,請聯絡我們取得出口地址。
  • 工具調用是 Agent 自主發起的。請把 MCP 伺服器當成一個帶權限的 API 來設計:只暴露必要的工具,按憑證區分權限,關鍵操作在伺服器端驗證。

排查 MCP 問題

現象看什麼
註冊返回 422 mcp_probe_failed按上面的 message 對照表處理;先用 curl 從公網訪問一次你的端點
註冊返回 422 invalid_mcp_server_url地址不是 https,或域名解析到了內網/本機
Agent 沒有調用工具先看伺服器的 last_connect_error;為空再檢查 allowed_tools 是否把工具排除了,以及工具描述是否足夠清楚;建立會話時是否真的傳了 mcp_servers
工具調用返回錯誤agent.tool_result 的 content 是你的伺服器返回的錯誤文字,到伺服器日誌裡對照
改了伺服器但 Agent 還在用舊工具已有會話下一輪才會重新連接;白名單模式下新工具要先加進 allowed_tools