Skip to content

MCP 接入指南

本指南面向希望透過 MCP(Model Context Protocol) 將電商或業務平台接入 Webnav.ai 的開發者。MCP 是基於 JSON-RPC 2.0 over HTTP 的開放標準工具協議。

MCP 模式為 Enterprise 功能。


為什麼選擇 MCP?

MCP 是 AI Actions 的接入方式:你執行一個 MCP 工具伺服器,Webnav.ai 透過 tools/list 自動發現你的工具,依其 annotations(destructiveHintreadOnlyHint 等)驅動確認邏輯,並以開放標準呼叫它們。所有工具皆套用相同的確認流程SKU 校驗呼叫日誌SSRF 防護


架構

訪客 → Widget → Webnav.ai ──JSON-RPC 2.0──► 你的 MCP 伺服器
                            ◄──────────────── (工具結果)
  1. 域名初次載入時,Webnav.ai 對你的 MCP 端點發送 initialize
  2. 呼叫 tools/list 發現可用工具(含 annotations)。
  3. 訪客觸發動作時,Webnav.ai 呼叫 tools/call 並傳入工具名與參數。
  4. 寫工具(create_ordercreate_refund)會先彈出確認卡片——訪客必須點確認才會執行。

Canonical 工具(5 個標準工具)

以下五個工具是 Webnav.ai 原生識別的工具,建議全部實作以獲得完整電商支援;也可只實作其中一部分。

工具總覽

工具類型需確認用途
list_products回傳商品目錄,用於 SKU 校驗
query_order查詢訂單狀態/詳情
query_logistics查物流軌跡
create_order下新訂單(items 陣列,一次呼叫)
create_refund發起退款申請

list_products 由 Webnav.ai 在內部使用,用於在顯示確認卡片前校驗 SKU。若訪客要求的 SKU 不在 list_products 結果中,助手會提示其從真實商品中選擇——無效 SKU 不會彈出確認卡片。


工具規格

list_products

json
{
  "name": "list_products",
  "description": "回傳可購買的商品目錄。",
  "inputSchema": { "type": "object", "properties": {} },
  "annotations": { "readOnlyHint": true }
}

回應 data.products

json
[
  { "sku": "PB-10000", "name": "行動電源 10000 mAh", "price": "19.99" },
  { "sku": "CB-USBC",  "name": "USB-C 充電線 2m",     "price": "7.99"  }
]

query_order

json
{
  "name": "query_order",
  "description": "依訂單 ID 查詢訂單狀態與詳情。",
  "inputSchema": {
    "type": "object",
    "properties": { "order_id": { "type": "string", "description": "訂單識別碼" } },
    "required": ["order_id"]
  },
  "annotations": { "readOnlyHint": true }
}

回應 data

json
{
  "order_id": "SO20260613",
  "status": "paid",
  "amount": "199.00",
  "currency": "USD",
  "items": [{ "sku": "PB-10000", "name": "行動電源", "qty": 2 }]
}

query_logistics

json
{
  "name": "query_logistics",
  "description": "查詢訂單的物流狀態。",
  "inputSchema": {
    "type": "object",
    "properties": { "order_id": { "type": "string" } },
    "required": ["order_id"]
  },
  "annotations": { "readOnlyHint": true }
}

回應 data

json
{
  "order_id": "SO20260613",
  "carrier": "順豐",
  "tracking_no": "SF123456789",
  "status": "in_transit",
  "tracks": [
    { "time": "2026-06-12 14:30", "desc": "到達深圳轉運中心" },
    { "time": "2026-06-13 09:10", "desc": "派送中" }
  ]
}

create_order

json
{
  "name": "create_order",
  "description": "下新訂單,每件商品必須是 list_products 中的真實商品。",
  "inputSchema": {
    "type": "object",
    "properties": {
      "items": {
        "type": "array",
        "description": "要訂購的商品清單",
        "items": {
          "type": "object",
          "properties": {
            "sku":      { "type": "string", "description": "商品 SKU" },
            "quantity": { "type": "integer", "minimum": 1 },
            "name":     { "type": "string", "description": "商品名稱(可選)" }
          },
          "required": ["sku", "quantity"]
        }
      },
      "address": { "type": "string", "description": "配送地址(可選)" }
    },
    "required": ["items"]
  },
  "annotations": { "destructiveHint": true, "idempotentHint": false, "title": "下單" }
}

回應 data

json
{ "order_id": "SO20260614", "pay_url": "https://pay.example.com/SO20260614", "amount": "39.98" }

items 為陣列——訪客在一次對話中可新增多件商品,Webnav.ai 會一次性呼叫 create_order 並帶入所有商品,只彈一張確認卡片。


create_refund

json
{
  "name": "create_refund",
  "description": "為一筆訂單發起退款申請。",
  "inputSchema": {
    "type": "object",
    "properties": {
      "order_id": { "type": "string" },
      "reason":   { "type": "string", "description": "退款原因(可選)" }
    },
    "required": ["order_id"]
  },
  "annotations": { "destructiveHint": true, "title": "申請退款" }
}

回應 data

json
{ "refund_id": "RF20260613", "status": "pending", "amount": "199.00" }

工具 Annotations

Annotations 是 tools/list 中的工具元資料,告知 Webnav.ai 如何處理每個工具:

Annotation類型作用
destructiveHintbooltrue → Webnav.ai 呼叫前一定顯示確認卡片
readOnlyHintbooltrue → 無需確認,直接呼叫
idempotentHintboolfalse → 額外謹慎,可能強制更嚴格的單次使用待確認
openWorldHintbooltrue → 工具可能有不可預期的副作用
titlestring確認卡片上顯示的可讀標籤

信任模型: destructiveHint 為你的伺服器自行申報。Webnav.ai 不完全信任 annotations——它還會套用基於名稱的規則(create_*refund_*cancel_*pay_* → 一律確認)以及你在後台配置的 mcpConfirmTools 清單。三層 OR 疊加,寫工具永遠不會因漏標 destructiveHint 而被跳過確認。


通訊格式

握手(initialize

域名首次連接時,Webnav.ai 發送:

json
{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "clientInfo": { "name": "webnav-ai", "version": "1.0" },
    "capabilities": {}
  }
}

你的伺服器回應:

json
{
  "jsonrpc": "2.0",
  "id": "1",
  "result": {
    "protocolVersion": "2024-11-05",
    "serverInfo": { "name": "my-shop-mcp", "version": "0.1.0" },
    "capabilities": {}
  }
}

若協議版本不符,Webnav.ai 記錄 versionMismatch 警告(在 Dashboard → AI Actions → 測試連接中可見),但仍繼續運作。


工具發現(tools/list

json
// 請求
{ "jsonrpc": "2.0", "id": "2", "method": "tools/list" }

// 回應
{
  "jsonrpc": "2.0",
  "id": "2",
  "result": {
    "tools": [
      {
        "name": "list_products",
        "description": "回傳商品目錄。",
        "inputSchema": { "type": "object", "properties": {} },
        "annotations": { "readOnlyHint": true }
      },
      {
        "name": "create_order",
        "description": "下新訂單。",
        "inputSchema": { "type": "object", "properties": { "items": { "type": "array" } } },
        "annotations": { "destructiveHint": true, "title": "下單" }
      }
    ]
  }
}

工具呼叫(tools/call

json
// 請求
{
  "jsonrpc": "2.0",
  "id": "3",
  "method": "tools/call",
  "params": {
    "name": "query_order",
    "arguments": { "order_id": "SO20260613" }
  }
}

// 回應 —— canonical 格式(推薦)
{
  "jsonrpc": "2.0",
  "id": "3",
  "result": {
    "ok": true,
    "data": { "order_id": "SO20260613", "status": "paid", "amount": "199.00" },
    "display": {
      "title": "訂單 SO20260613",
      "fields": [{ "label": "狀態", "value": "已付款" }]
    }
  }
}

// 回應 —— MCP content-block 格式(也接受)
{
  "jsonrpc": "2.0",
  "id": "3",
  "result": {
    "content": [{ "type": "text", "text": "{\"order_id\":\"SO20260613\",\"status\":\"paid\"}" }],
    "isError": false
  }
}

兩種格式均支援。Canonical {ok, data, display} 格式可獲得更豐富的 widget 卡片渲染效果。


Display 卡片渲染能力

工具結果上的可選 display 物件決定 widget 如何渲染結構化卡片。所有欄位皆為可選,可自由組合。

json
"display": {
  "title": "訂單 SO20260613",
  "subtitle": "標題下方的輔助說明。",
  "fields":  [{ "label": "狀態", "value": "已付款" }],
  "items":   [{ "title": "到達轉運中心", "time": "2026-06-12 14:30" }],
  "buttons": [{ "label": "查看訂單", "url": "/orders/SO20260613", "style": "primary" }],
  "options": [{ "label": "AlipayPlus", "value": "alipay", "hint": "本地電子錢包" }],
  "submit":  { "label": "生成訂單", "url": "/checkout?method={value}", "target": "_self" }
}
欄位類型渲染為
titlestring卡片標題
subtitlestring標題下方的淺色說明
fields[{label, value}]鍵值行
items[{title|desc, time?}]時間軸列表(如物流軌跡)
products[…]橫向滾動商品卡
buttons[{label, url, style?}]操作按鈕。url 於新分頁開啟;根相對 /path 會以你的 data-base-url 為前綴。styleprimary(預設)/ secondary
options + submit見下單選卡(radio 列表 + 一個提交按鈕)

單選卡(options + submit

用於讓訪客不打字、選一項即可操作。widget 把 options 渲染為 radio 列;提交按鈕在選中前保持禁用

  • options[{ label, value, hint? }]
  • submit:點擊後的行為(url 優先於 prompt):
    • submit.url——導航宿主視窗至該 URL。{value} / {label} 以所選項替換。根相對 /path嵌入頁面的 origin 解析(而非 data-base-url)。submit.target_self(預設)或 _blank
    • submit.prompt——把該文字作為訪客的下一條對話訊息發送(交回助手處理;同樣替換 {value} / {label})。當下一步需要再經由助手時使用。
    • submit.label——按鈕文字;省略時 widget 顯示本地化預設值。

範例:充值工具把啟用的支付方式作為 options 回傳,並給一個 submit.url"/wallet?amount=5&method={value}&autopay=1"。訪客選方式、點按鈕,宿主頁面即下單並開啟結帳——無需額外對話輪次或確認。

授權卡(AUTH_REQUIRED

當用戶相關工具沒有有效的 user token 時,回傳一個display 的業務錯誤,而非靜默失敗:

json
{ "ok": false, "error_code": "AUTH_REQUIRED", "message": "請先登入。",
  "display": { "title": "連接你的帳號",
               "subtitle": "登入後繼續。",
               "buttons": [{ "label": "登入", "url": "/login", "style": "primary" }] } }

widget 會把它渲染成授權卡——讀工具、以及寫工具確認失敗時皆適用——讓訪客看到登入按鈕而非一行錯誤。


訪客身份轉發(user token)

對於用戶相關的工具(某帳號的訂單、餘額、API Key、用量…),你的站點為已登入訪客簽發短時 user token 並交給 widget:

js
window.WebnavWidget.setUserToken('YOUR_SIGNED_USER_TOKEN')

Webnav.ai 不解析也不儲存此令牌。每次 tools/call 時,它會把令牌不透明地作為 HTTP 標頭轉發給你的 MCP 端點——預設為:

X-Webnav-User-Token: <你的 user token>

你可在 後台 → AI Actions 改用其它標頭名(如 Authorization)。由的 MCP 伺服器自行驗證該令牌(如校驗 JWT 簽名)並還原真實用戶。

寫工具/確認: 令牌在確認呼叫時會再次重發,並以雜湊與待確認動作綁定——確保已確認的 create_* 以發起時的同一身份執行。確認時令牌缺失/被竄改會被拒絕(TOKEN_MISMATCH)且不執行。

需要用戶身份但未收到有效令牌的讀工具,應回傳業務錯誤(如 {ok:false, error_code:"AUTH_REQUIRED"})——widget 會渲染授權卡片提示訪客登入,而非靜默失敗。


錯誤歸一化

Webnav.ai 將所有 MCP 傳輸和協議錯誤統一映射為 error_code

情境error_code
HTTP 狀態非 2xxMCP_HTTP_<status>(如 MCP_HTTP_503
JSON-RPC error 欄位MCP_RPC_ERROR
結果中 isError: trueMCP_TOOL_ERROR
連接逾時MCP_TIMEOUT
Host 無法連接/拒絕連接MCP_UNREACHABLE

這些錯誤碼會出現在 Dashboard → AI Actions → 呼叫日誌,以及助手轉述給訪客的錯誤訊息中。

你自己的業務錯誤應在 data.error_code 欄位使用描述性錯誤碼(如 ORDER_NOT_FOUNDOUT_OF_STOCK)。


後台配置

  1. 進入 Dashboard → AI Actions
  2. 模式 切換為 MCP
  3. 輸入你的 MCP 端點(如 https://mcp.yourshop.com/mcp)。
  4. 視需要新增鑑權標頭(鍵值對——值加密儲存,不以明文回傳)。
  5. 測試連接——Webnav.ai 透過 initialize + tools/list 探測你的端點,並顯示發現的工具清單與 annotations。
  6. 需確認工具面板中,確認預選的寫工具是否正確,並補充任何其他需要確認卡片的工具名稱。
  7. 儲存

關於測試連接的說明: 探測請求會透過 Webnav.ai 後端代理發出——你的 MCP 端點不會被瀏覽器直接訪問,同樣受 SSRF 防護(本地環境開啟 ACTIONS_ALLOW_INSECURE 時除外)。


安全

要求原因
使用 HTTPS 服務Webnav.ai 綁定解析 IP 並驗證憑證。
使用公網 hostWebnav.ai 拒絕私網/環回/元數據位址(SSRF 防護)。
驗證鑑權標頭mcp_headers 中設定 bearer token 或 API key,並在每次請求時於你的伺服器端驗證。
寫工具冪等設計Webnav.ai 只發一次確認呼叫,但網路重試可能發生——設計 create_order/create_refund 使其安全地可重複接收。
不依賴 destructiveHint 作為唯一安全機制Webnav.ai 還會套用名稱規則與 mcpConfirmTools 作為額外安全層。

Demo MCP 伺服器

倉庫提供兩個演示用 MCP 伺服器,皆實作全部五個 canonical 工具並帶有正確的 annotations。

方案 A — 模擬商城整合端點(推薦)

演示商城(examples/shop/shop_server.py,連接埠 4000)暴露 /mcp 端點,與店面共用同一份訂單資料。AI 透過 MCP 下的單會即時出現在店面「我的訂單」面板中——這是端到端體驗「訪客 → widget → MCP → 訂單」完整鏈路的最佳方式。

bash
# 同時啟動店面 + /mcp,位於 http://localhost:4000
WEBNAV_SECRET=webnav-mock-secret-001 ./.venv/bin/python examples/shop/shop_server.py

可選 Bearer 鑑權:啟動時設定 MCP_AUTH_TOKEN=<token>,再於後台 Auth Headers 加入 Authorization: Bearer <token>。不設定 = 不鑑權(演示預設)。

然後在 Dashboard → AI Actions 中設定模式 = MCP、端點 = http://localhost:4000/mcp,點測試連接即可。

方案 B — 獨立參考伺服器

examples/mcp_server.py(連接埠 4100)是最精簡的獨立參考實作,使用自己的記憶體訂單儲存(不與店面面板連動),適合純協議測試。

警告: 兩者皆為參考/演示實作。獨立伺服器沒有鑑權或冪等保護。請勿直接部署到生產環境。

bash
./.venv/bin/python examples/mcp_server.py   # 啟動在 http://localhost:4100/mcp

直接測試通訊格式

bash
# 握手(獨立伺服器請把 4000 換成 4100)
curl -s -X POST http://localhost:4000/mcp \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":"1","method":"initialize","params":{"protocolVersion":"2024-11-05","clientInfo":{"name":"test","version":"1"}}}'

# 發現工具
curl -s -X POST http://localhost:4000/mcp \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":"2","method":"tools/list"}'

# 呼叫工具
curl -s -X POST http://localhost:4000/mcp \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":"3","method":"tools/call","params":{"name":"list_products","arguments":{}}}'

Webnav.ai — AI 智能客服