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 客户端按四步走:
initialize:协商协议版本,服务端在响应头返回mcp-session-id。notifications/initialized:通知服务端握手完成,返回202,无响应体。tools/list:拉取工具清单与参数结构。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 等客户端中的配置方法。