MCP网关前言
本文最后更新于9 天前,其中的信息可能已经过时,如有错误请发送邮件到2125094989@qq.com

本文聚焦 MCP Gateway 的上下游通信:客户端、网关、后端 MCP Server 如何交换消息,以及网关需要负责哪些治理

1. MCP 与网关的位置

MCP(Model Context Protocol)让 AI 客户端通过统一协议发现和使用外部能力:

  • Tools:可执行动作,如查询订单、创建工单、调用内部 API;
  • Resources:可读取上下文,如知识库、文件、配置;
  • Prompts:可复用提示词模板。

MCP 客户端与服务端以 UTF-8 编码的 JSON-RPC 2.0 通信。网关对上是稳定的 MCP Server,对下可以路由、聚合多个 MCP Server 或内部系统。

AI Client / IDE / Agent
        │ MCP / JSON-RPC
        ▼
    MCP Gateway
        │ 路由、认证、鉴权、审计、限流、协议适配
        ▼
多个 MCP Server / 内部 API / 数据库

2. JSON-RPC 的统一消息格式

请求 Request

请求必须带 id,用来关联响应。

{
  "jsonrpc": "2.0",
  "id": "req-001",
  "method": "tools/call",
  "params": {}
}

成功响应 Response

响应的 id 与请求一致,业务结果放进 result

{
  "jsonrpc": "2.0",
  "id": "req-001",
  "result": {}
}

通知 Notification

通知不带 id,接收方不返回响应;适合初始化完成、工具列表变化、进度更新等事件。

{
  "jsonrpc": "2.0",
  "method": "notifications/initialized"
}

协议错误 Error

请求格式、方法或参数不合法等协议层问题,用顶层 error 返回。

{
  "jsonrpc": "2.0",
  "id": "req-001",
  "error": {
    "code": -32602,
    "message": "Invalid params",
    "data": { "field": "orderId", "reason": "required" }
  }
}

3. 连接与初始化

调用顺序应为:initialize → 初始化响应 → notifications/initialized → 正常业务调用。初始化时协商版本和能力;之后只能使用双方已协商的能力。

客户端初始化

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-06-18",
    "capabilities": {},
    "clientInfo": {
      "name": "company-agent",
      "version": "1.0.0"
    }
  }
}

网关返回能力

网关只应声明真正支持且允许当前调用方使用的能力。

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2025-06-18",
    "capabilities": {
      "tools": { "listChanged": true },
      "resources": { "listChanged": true }
    },
    "serverInfo": {
      "name": "company-mcp-gateway",
      "version": "1.0.0"
    },
    "instructions": "敏感写操作需要用户确认。"
  }
}
{
  "jsonrpc": "2.0",
  "method": "notifications/initialized"
}

4. Tool 交流格式

工具发现:tools/list

客户端先获得工具清单。网关可在此执行多服务聚合、工具名规范化、租户和 RBAC 过滤。

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list",
  "params": {}
}

建议对外暴露带业务前缀的稳定工具名,避免下游服务重名:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "order.query_order",
        "title": "查询订单",
        "description": "根据订单号查询订单状态、金额和收货信息。仅允许读取当前租户订单。",
        "inputSchema": {
          "type": "object",
          "properties": {
            "orderId": {
              "type": "string",
              "description": "订单号,例如 ORD-20260726-001"
            }
          },
          "required": ["orderId"],
          "additionalProperties": false
        }
      }
    ]
  }
}

工具定义应至少说明:

字段约定
name稳定、唯一、机器使用的标识;不要随意改名。
title面向人的短名称。
description何时可调用、会做什么、权限与副作用;模型主要靠它选择工具。
inputSchemaJSON Schema,声明必填字段、类型、枚举和边界。
outputSchema可选但推荐,为稳定结果提供结构化约束。

工具调用:tools/call

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "order.query_order",
    "arguments": {
      "orderId": "ORD-20260726-001"
    }
  }
}

工具成功结果

content 供模型和用户阅读;structuredContent 供程序稳定解析。网关推荐同时返回两者。

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "订单 ORD-20260726-001 已支付,金额 ¥99.00。"
      }
    ],
    "structuredContent": {
      "orderId": "ORD-20260726-001",
      "status": "PAID",
      "amount": 99.0,
      "currency": "CNY"
    },
    "isError": false
  }
}

工具执行失败

当工具调用格式正确、但下游 API 或业务执行失败时,使用 result.isError: true,不要伪装成协议错误。

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "未找到订单 ORD-20260726-001。请确认订单号,或查询最近订单。"
      }
    ],
    "isError": true
  }
}

5. Resources 与 Prompts

Resource

Resource 是可读取、可引用的上下文,不是执行动作。URI 是稳定标识。

{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "resources/read",
  "params": {
    "uri": "company://knowledge/refund-policy"
  }
}
{
  "jsonrpc": "2.0",
  "id": 4,
  "result": {
    "contents": [
      {
        "uri": "company://knowledge/refund-policy",
        "mimeType": "text/markdown",
        "text": "# 退款政策\n..."
      }
    ]
  }
}

Prompt

Prompt 是参数化提示词模板,例如生成售后回复。它不应成为绕过用户确认来执行高风险操作的通道。

{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "prompts/get",
  "params": {
    "name": "reply_to_refund_request",
    "arguments": { "tone": "professional" }
  }
}

6. 网关约定

命名与路由

对外命名采用 <domain>.<action>

order.query_order
order.create_refund
crm.search_customer
knowledge.search

网关内部维护下游映射,不将服务地址、实现类和内部敏感参数暴露给客户端:

order.query_order → order-server / tools/call / query_order

网关内部上下文

这些字段不必全部成为 MCP 协议字段,但网关处理每个请求都应记录、校验并安全传递:

{
  "requestId": "gw-01J...",
  "traceId": "trace-...",
  "tenantId": "tenant-a",
  "principal": { "id": "user-123", "roles": ["support"] },
  "toolName": "order.query_order",
  "timeoutMs": 10000,
  "idempotencyKey": "仅写操作可选"
}

身份、租户和角色必须从认证上下文获得;**不能信任模型在 arguments 中自己填写的 userIdroletenantId**。

读写工具治理

级别示例建议策略
只读order.query_order权限校验、审计、限流。
低风险写ticket.create展示关键入参,按产品策略确认。
高风险写payment.refunduser.delete必须显式用户确认、幂等键、强审计;默认拒绝批量操作。

错误语义

场景返回形式
JSON-RPC 格式/参数错误顶层 error,如 -32602 Invalid params
工具不存在顶层 error
工具已被正确调用但业务失败result.isError: true
身份无权限统一拒绝,且不泄露资源是否存在。
下游超时result.isError: true,给出可重试提示,不暴露内部地址。

7. 传输方式

stdio

适合本地部署:客户端启动服务端子进程,通过 stdin / stdout 逐行传 JSON-RPC。stdout 只能输出合法 MCP 消息,日志写到 stderr

Streamable HTTP

适合远程网关:客户端使用 POST /mcp 提交一条 JSON-RPC 消息;服务端返回一个 JSON 或 SSE 流。后续请求要带协商后的 MCP-Protocol-Version;若服务端返回会话 ID,还需带 Mcp-Session-Id

POST /mcp HTTP/1.1
Accept: application/json, text/event-stream
Content-Type: application/json
MCP-Protocol-Version: 2025-06-18
Authorization: Bearer <token>

{ "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { ... } }

8.参考

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇