~/docs/mcp/overview/

MCP 接入(Model Context Protocol)

MCP(Model Context Protocol)是让 AI 客户端直接调用外部工具的标准协议。蜀农 API 提供 MCP 端点,把天气搜索、知识库检索、生长周期识别、当前时间四类农业能力以标准工具的形式暴露给支持 MCP 的客户端——客户端无需编写适配代码,配置一次即可让模型自主调用这些能力。

如果你的应用已经在用 OpenAI SDK,也可以继续走 REST 接口(/api/v1/chat/completions)。两者能力一致、密钥通用,区别只在调用方式:MCP 由客户端负责工具编排,REST 由你的代码负责。

端点信息

项目 值
端点地址 https://ai.agriwis.com/mcp
传输方式 Streamable HTTP(仅支持 POST)
鉴权方式 Authorization: Bearer <API Key>
协议版本 2025-06-18,兼容 2024-11-05
会话 有状态,服务端在初始化时下发 mcp-session-id
提供能力 仅 tools(prompts、resources 当前为空)

端点只接受 POST 请求。不带密钥直接 GET 该地址会先因鉴权失败返回 401;带上 Authorization 再用 GET 才会返回 400 Bad Request。两者都不是故障,而是 Streamable HTTP 传输的预期行为。

鉴权

每个请求都必须携带 API Key,放在 Authorization 请求头中,格式为 Bearer 加空格加密钥。

Authorization: Bearer sk_xxxxxxxxxxxxxxxx
Content-Type: application/json

密钥的获取与管理方式参见 获取 API Key。缺失密钥时返回 401:

{"error":"missing api key, header: Authorization: Bearer<api key>"}

密钥无效或已撤销时同样返回 401:

{"error":"invalid api key"}

API Key 具备账户额度权限,只应配置在可信环境(本机客户端、服务端代理)中。不要把密钥提交到代码仓库、前端页面或公开的客户端配置文件里。

连接流程

标准 MCP 客户端按四步走:

  1. initialize:协商协议版本,服务端在响应头返回 mcp-session-id。
  2. notifications/initialized:通知服务端握手完成,返回 202,无响应体。
  3. tools/list:拉取工具清单与参数结构。
  4. tools/call:调用具体工具。

第 1 步是硬性要求,没有 mcp-session-id 的后续请求会被拒绝。第 2 步是协议规范中的通知,标准客户端都会发送;服务端不强制校验,但缺少它不算完整握手,自建客户端建议照发。

1. initialize

curl -s -D headers.txt -X POST https://ai.agriwis.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Authorization: Bearer $SHUNONG_API_KEY" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2025-06-18",
      "capabilities": {},
      "clientInfo": {"name": "my-client", "version": "1.0.0"}
    }
  }'

响应头中包含会话标识,后续请求必须原样带回:

mcp-session-id: 2f7c1e8a-9b3d-4c5e-8a1f-0d6b2c4e9a71

响应体:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2025-06-18",
    "capabilities": {
      "completions": {},
      "logging": {},
      "prompts": {"listChanged": true},
      "resources": {"subscribe": false, "listChanged": true},
      "tools": {"listChanged": true}
    },
    "serverInfo": {"name": "agriwis-mcp", "version": "1.0.0"}
  }
}

2. notifications/initialized

curl -s -X POST https://ai.agriwis.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Authorization: Bearer $SHUNONG_API_KEY" \
  -H "mcp-session-id: $SID" \
  -d '{"jsonrpc":"2.0","method":"notifications/initialized"}'

该请求返回 202 Accepted,无响应体。它是通知而非调用,不要期待 result 字段。

3. tools/list

curl -s -X POST https://ai.agriwis.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Authorization: Bearer $SHUNONG_API_KEY" \
  -H "mcp-session-id: $SID" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'

返回 4 个工具的定义与 JSON Schema,字段说明见 MCP 工具参考。

4. tools/call

curl -s -X POST https://ai.agriwis.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Authorization: Bearer $SHUNONG_API_KEY" \
  -H "mcp-session-id: $SID" \
  -d '{
    "jsonrpc": "2.0",
    "id": 3,
    "method": "tools/call",
    "params": {
      "name": "weather_search",
      "arguments": {"location": "成都", "date": "now"}
    }
  }'

响应格式

服务端按 Accept 协商结果返回两种形态,客户端需要两种都能处理:

  • application/json:直接返回 JSON-RPC 报文(initialize 通常是这种)。
  • text/event-stream:SSE 流,报文在 data: 行内(tools/list、tools/call 通常是这种)。

SSE 形态形如:

id:2f7c1e8a-9b3d-4c5e-8a1f-0d6b2c4e9a71
event:message
data:{"jsonrpc":"2.0","id":3,"result":{...}}

因此 Accept 请求头必须同时声明 application/json 和 text/event-stream,只写其中一个可能导致握手被拒。解析时先判断 Content-Type:SSE 需按行读取、取 data: 之后的内容再解析 JSON。

工具结果是二次序列化的字符串

tools/call 返回的 content[0].text 是字符串化的 JSON,不是对象。客户端需要再解析一次:

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"city\":\"101270101\",\"weather\":\"阴\",\"temperature\":\"19.8℃\"}"
      }
    ],
    "isError": false
  }
}
import json

payload = json.loads(response["result"]["content"][0]["text"])

错误处理

工具执行失败时,服务端把 isError 置为 true,失败原因放在 text 里。注意此时的 text 不是 JSON,而是 Error invoking method: <方法名> 开头的纯文本,第二行起才是中文原因:

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Error invoking method: cropGrowthRecognize\n图片下载失败: HTTP 404 https://example.com/a.jpg"
      }
    ],
    "isError": true
  }
}

因此解析逻辑要先判断形态,再做 JSON 解析:

text = response["result"]["content"][0]["text"]
if response["result"].get("isError"):
    reason = text.split("\n", 1)[-1]        # 去掉 "Error invoking method: xxx" 前缀
else:
    payload = json.loads(text)              # 成功时才是字符串化的 JSON

不要把失败文本丢给模型当作工具结果。先取 isError,为 true 时把 reason 原样反馈给用户或转成重试逻辑,否则模型会把失败信息当成正常数据继续推理,产出无依据的结论。

除工具内部错误外,协议层错误按 JSON-RPC 标准返回:

场景 HTTP / code 说明
工具名不存在 -32602 报文 message 为 Unknown tool: invalid_tool_name,data 中给出实际传入的名称,如 Tool not found: knowledge_search_v2
缺少必填参数 — 以 isError: true 返回,text 中给出校验失败详情,见下方示例
缺少会话标识 400 / -32600 message 为 缺少 Mcp-Session-Id 请求头: 请先调用 initialize 建立会话
会话不存在或已过期 404 / -32603 message 为 Session not found: <会话 ID>,需重新 initialize
Accept 头不合法 400 / -32601 message 为 Invalid Accept headers. Expected TEXT_EVENT_STREAM and APPLICATION_JSON

常见参数校验失败的返回(knowledge_search 未传必填的 query):

{
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Tool (knowledge_search) input validation failed: Validation failed: JSON schema validation errors: [: required property 'query' not found]"
      }
    ],
    "isError": true
  }
}

与 REST 接口的对照

维度 MCP 端点 REST 接口
地址 https://ai.agriwis.com/mcp https://ai.agriwis.com/api/v1/chat/completions
调用方职责 客户端负责工具编排与结果回传 你的代码负责声明工具、执行工具、回传结果
是否需要模型 不需要,只调用工具 需要,模型决定何时调用工具
返回内容 工具原始结果 模型整合后的自然语言回答
适用场景 已有 AI 客户端(Claude、Cursor 等)或自建 Agent 自有业务系统、后端代理、需要统一计费口径

两者使用同一套 API Key,额度与计费规则一致,参见 计费说明。

能力范围与限制

  • 当前只提供 tools。prompts/list 与 resources/list 返回空数组,客户端不必实现这两类交互。
  • 会话有状态,mcp-session-id 失效或被服务端回收后,需要重新执行 initialize。建议客户端在收到 400(缺少 Mcp-Session-Id 请求头)或 404(Session not found)时自动重建一次会话再重试,不要无限重试。
  • 图像识别工具的 imageUrl 必须是公网可直接访问的图片直链,服务端不跟随重定向,也不保证能访问境外站点。需要传本地图片时改用 base64 或 data URI,详见 MCP 工具参考。
  • 工具定义、参数或返回结构如有调整,服务端通过 tools/list 的 listChanged 能力提示,建议客户端缓存清单并支持刷新。

下一步

  • MCP 工具参考:四个工具的参数、返回值与调用示例。
  • 客户端接入:在 Claude Code、Claude Desktop、Cursor、Cline 等客户端中的配置方法。