當智能體調用 MCP 工具時,工具返回的未經處理資料可能包含敏感資訊,或需要格式化、審計標記等後處理。MCP Tool Hook 在 MCP 用戶端和服務端之間插入代理層,在工具調用前後執行自訂邏輯,無需修改原始 MCP 服務代碼。
工作原理
MCP Tool Hook 基於 AgentRun MCP 代理層運行。代理層位於 MCP 用戶端(智能體)和 MCP 服務端之間,作為透明中介層轉寄所有 MCP 協議請求。啟用代理後,工具調用請求不再直接到達 MCP 服務,而是經過代理層中轉。代理層在執行 tools/list 和 tools/call 操作的前後,觸發已配置的 Hook 事件,將請求或響應轉寄至外部 Hook 服務(HTTP Webhook)進行處理。
MCP 協議標準本身不定義 Hook 或中介軟體機制。MCP Tool Hook 是 AgentRun 在協議層之上的擴充能力,對 MCP 服務端完全透明。
以 POST_CALL_TOOL 事件為例,資料流轉過程如下:
智能體發起工具調用請求。
AgentRun MCP 代理層接收請求,調用 MCP 服務執行工具操作。
MCP 服務返回原始結果。
代理層根據 Hook 配置,將結果通過 HTTP POST 轉寄至 Hook 服務。
Hook 服務對結果進行處理(如脫敏、審計標記),返回修改後的結果。
代理層將最終結果返回給智能體。
其他事件的流轉方式類似:PRE_CALL_TOOL 在工具調用前觸發,可修改請求參數或攔截調用;PRE_LIST_TOOLS 和 POST_LIST_TOOLS 分別在擷取工具列表前後觸發,可對工具列表進行預先處理或過濾修改。
Hook 事件類型
支援以下 Hook 事件:
事件類型 | 觸發時機 | 說明 |
PRE_CALL_TOOL | 工具調用之前 | MCP 服務執行工具調用前觸發。Hook 服務接收請求參數,可修改參數或攔截調用。 |
POST_CALL_TOOL | 工具調用完成後 | MCP 服務返回工具調用結果後觸發。Hook 服務接收原始結果,可修改後返回。 |
PRE_LIST_TOOLS | 擷取工具列表之前 | MCP 服務執行 |
POST_LIST_TOOLS | 擷取工具列表之後 | MCP 服務返回工具列表後觸發。Hook 服務可對工具列表進行過濾或修改。 |
適用情境
資料脫敏:對工具返回結果中的手機號、郵箱、地址等敏感資訊進行掩碼處理。
審計標記:在工具調用結果中注入請求 ID、時間戳記等審計標識,便於追蹤和審計。
結果增強:對工具返回的未經處理資料進行格式化、補充或過濾。
存取控制:在工具調用前後添加許可權校正邏輯,限制特定工具的使用範圍。
部署模式
AgentRun 支援兩種 MCP Tool Hook 部署模式:
部署模式 | 架構 | 適用情境 |
mcp_remote | 遠程 MCP + 代理 + Hook。MCP 服務和 Hook 服務分別獨立部署為 HTTP 服務。 | MCP 服務已獨立部署。 |
mcp_code | 代碼打包 MCP + 代理 + Hook。MCP 服務代碼直接打包到 AgentRun 運行時。 | 希望簡化部署流程,將 MCP 服務代碼直接打包到運行時。 |
兩種模式使用相同的 Hook 配置方式,區別在於 MCP 服務的部署和引用方式。
準備工作
已開通 AgentRun 服務。可通過AgentRun 控制台確認。
已開通Function Compute(FC)服務,用於部署 MCP 服務和 Hook 服務。
已安裝 Golang 1.23 及以上開發環境。
已擷取阿里雲帳號的 UID、AccessKey ID 和 AccessKey Secret。擷取方式請參見擷取 AccessKey。
已準備 MCP 服務代碼和 Hook 服務代碼。完整樣本可從 start-agentrun 倉庫擷取:
git clone https://github.com/devsapp/start-agentrun.git cd start-agentrun專案中包含兩個樣本目錄:
mcp_remote(遠程 MCP 模式)和mcp_code(代碼打包模式),分別對應兩種部署模式的完整樣本。以下操作步驟中的相對路徑均基於專案根目錄start-agentrun/。
部署Function Compute服務時,預設使用國際站地區(如 ap-southeast-1)。請根據實際業務需求選擇合適的地區。
配置 MCP Tool Hook(mcp_remote 模式)
以下以訂單查詢服務(orderdesk)和資料脫敏 Hook 服務(userhook)為例,示範 mcp_remote 模式的完整配置流程。
步驟一:配置環境變數
進入 mcp_remote 樣本目錄,配置阿里雲憑證資訊。
進入樣本目錄:
cd mcp_remote複製環境變數模板並填寫憑證資訊:
cp .env.example .env編輯
.env檔案,填入您的阿里雲帳號資訊。其中AGENTRUN_DATA_ENDPOINT需將<ALIBABA_CLOUD_UID>替換為實際 UID:ALIBABA_CLOUD_UID=<您的阿里雲帳號 UID> ALIBABA_CLOUD_ACCESS_KEY_ID=<您的 AccessKey ID> ALIBABA_CLOUD_ACCESS_KEY_SECRET=<您的 AccessKey Secret>
步驟二:一鍵部署
運行樣本程式,自動完成 MCP 服務(orderdesk)和 Hook 服務(userhook)的部署,以及 AgentRun 上的工具建立、代理啟用和 Hook 配置。
go run .程式將自動執行以下操作:
將 MCP 服務和 Hook 服務部署到Function Compute。
在 AgentRun 中建立 MCP 工具,並啟用代理。
配置 Hook(
POST_CALL_TOOL事件),將 Hook 服務地址關聯到工具配置中。發起測試調用並輸出驗證結果。
樣本程式在驗證完成後不會自動清理所部署的資源。保留的Function Compute函數不產生額外費用。如需清理,請手動刪除Function Compute中對應的函數和 AgentRun 中對應的 MCP 工具。
步驟三:驗證結果
程式執行完成後,查看輸出的驗證結果,確認 Hook 已生效。
未啟用 Hook 時返回的原始訂單資料(以查詢 ORDER-1001 為例):
{
"order_id": "ORDER-1001",
"customer_name": "張三",
"phone": "138****5678",
"email": "zhangsan@example.com",
"shipping_address": "浙江省杭州市西湖區文三路 100 號",
"status": "PAID",
"amount": 259.8,
"items": [
{"sku": "SKU-AX100", "name": "人體工學滑鼠", "quantity": 1, "price": 129.9},
{"sku": "SKU-KB200", "name": "機械鍵盤鍵帽", "quantity": 1, "price": 129.9}
]
}啟用 Hook 後,返回的脫敏資料:
{
"order_id": "ORDER-1001",
"customer_name": "張*",
"phone": "138****5678",
"email": "zh***@example.com",
"shipping_address": "浙江省杭州市****",
"status": "PAID",
"amount": 259.8,
"items": [
{"sku": "SKU-AX100", "name": "人體工學滑鼠", "quantity": 1, "price": 129.9},
{"sku": "SKU-KB200", "name": "機械鍵盤鍵帽", "quantity": 1, "price": 129.9}
],
"audit_id": "audit_xxxxxxxxxxxxxxxx"
}配置參數參考
樣本程式自動產生的 mcpProxyConfiguration 配置如下:
{
"proxyEnabled": true,
"hooks": [
{
"event": "POST_CALL_TOOL",
"endpoint": "<Hook 服務的 Endpoint 地址>"
}
]
}配置參數說明:
參數 | 類型 | 必填 | 說明 |
proxyEnabled | Boolean | 是 | 是否啟用 MCP 代理。設定為 |
hooks | Array | 否 | Hook 配置列表。每個元素包含事件類型和 Hook 服務地址。 |
hooks[].event | String | 是 | Hook 事件類型。支援 |
hooks[].endpoint | String | 是 | Hook 服務的 HTTP 地址。代理層在事件觸發時,向該地址發送 HTTP POST 請求。 |
hooks[].enabled | Boolean | 否 | 是否啟用該 Hook,預設 |
hooks[].timeout | Integer | 否 | Hook 請求逾時時間(秒)。 |
hooks[].description | String | 否 | Hook 描述資訊。 |
hooks[].headers | Object | 否 | 自訂要求標頭,索引值對格式。 |
配置 MCP Tool Hook(mcp_code 模式)
mcp_code 模式將 MCP 服務代碼打包到 AgentRun 運行時中,無需單獨部署 MCP 服務,簡化部署流程。以下同樣以 orderdesk(MCP 服務)和 userhook(Hook 服務)為例。
步驟一:配置環境變數
進入 mcp_code 樣本目錄,配置阿里雲憑證資訊。
進入樣本目錄:
cd mcp_code複製環境變數模板並填寫憑證資訊:
cp .env.example .env編輯
.env檔案,填入您的阿里雲帳號資訊(格式與 mcp_remote 模式相同)。
步驟二:一鍵部署
運行樣本程式,自動完成 MCP 服務代碼打包、Hook 服務部署,以及 AgentRun 上的工具建立、代理啟用和 Hook 配置。
go run .與 mcp_remote 模式不同,mcp_code 模式下 MCP 服務代碼直接打包到 AgentRun 運行時,無需部署獨立的 MCP 服務。
步驟三:驗證結果
驗證方式與 mcp_remote 模式相同,參考步驟三:驗證結果。
樣本:訂單資料脫敏 Hook 服務
樣本程式中的 Hook 服務(userhook)使用 Go 實現,處理 POST_CALL_TOOL 事件。以下是核心脫敏函數,完整代碼參見 start-agentrun 倉庫。
// maskPhone 對手機號進行掩碼處理,保留前 3 位和後 4 位。
func maskPhone(phone string) string {
runes := []rune(strings.TrimSpace(phone))
if len(runes) <= 7 {
return "***"
}
return string(runes[:3]) + "****" + string(runes[len(runes)-4:])
}
// maskEmail 對郵箱進行掩碼處理,保留前 2 位使用者名稱。
func maskEmail(email string) string {
parts := strings.SplitN(email, "@", 2)
if len(parts) != 2 {
return "***"
}
name := []rune(parts[0])
keep := 1
if len(name) > 2 {
keep = 2
}
return string(name[:keep]) + "***@" + parts[1]
}
// maskAddress 對地址進行掩碼處理,保留前 6 個字元。
func maskAddress(address string) string {
runes := []rune(strings.TrimSpace(address))
if len(runes) <= 6 {
return "***"
}
return string(runes[:6]) + "****"
}
// maskName 對姓名進行掩碼處理,保留姓氏。
func maskName(name string) string {
runes := []rune(strings.TrimSpace(name))
if len(runes) == 0 {
return "***"
}
return string(runes[:1]) + "*"
}
// auditIDFromBytes 根據原始響應產生審計編號(SHA256 雜湊首碼)。
func auditIDFromBytes(body []byte) string {
sum := sha256.Sum256(body)
return "audit_" + hex.EncodeToString(sum[:])[:16]
}Hook 服務接收代理層通過 HTTP POST 轉寄的事件裝載,負載中的請求和響應 Body 採用 Base 64 編碼。Hook 服務解碼後對敏感欄位進行掩碼處理,注入審計標識,再將修改後的結果 Base 64 編碼返回。
錯誤處理
Hook 服務異常時,代理層將中斷本次 MCP 請求:
異常情境 | 代理層行為 |
Hook 服務逾時 | MCP 請求失敗,向調用方返回錯誤。 |
Hook 服務不可用(串連失敗) | MCP 請求失敗,向調用方返回錯誤。 |
Hook 服務返回非 200 狀態代碼 | MCP 請求失敗,向調用方返回錯誤。 |
Hook 服務異常(逾時、不可用或返回非 200 狀態代碼)時,代理層不會降級處理,而是直接將本次 MCP請求標記為失敗。PRE_CALL_TOOL 階段失敗時,工具不會被執行。POST_CALL_TOOL 階段失敗時,工具的原始結果不會返回給調用方。請確保 Hook 服務的高可用性。
常見問題
Hook 服務配置後不生效
按以下步驟排查:
確認
proxyEnabled已設定為true。確認
hooks[].endpoint地址正確且 Hook 服務正常運行。確認
hooks[].event值為支援的事件類型(PRE_CALL_TOOL、POST_CALL_TOOL、PRE_LIST_TOOLS或POST_LIST_TOOLS,注意大小寫)。檢查 Hook 服務日誌,確認是否收到代理層的 HTTP POST 請求。
如何選擇部署模式
條件 | 推薦模式 |
MCP 服務已獨立部署 | mcp_remote |
希望簡化部署,將 MCP 服務代碼打包到運行時 | mcp_code |