找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4684

积分

0

好友

633

主题
发表于 10 小时前 | 查看: 2| 回复: 0

通过抓包分析,我们清晰地了解了 MCP 通信的全过程:从建立 SSE 连接、三步初始化、工具调用操作到最终的连接终止。可以看出,MCP 基于简单的 SSE 协议搭建了一个功能强大的工具调用框架,使 AI 代理能够便捷地调用外部工具完成复杂任务。

相比传统的接口调用方式,MCP 更加灵活,能够自动适应不同的工具集,让 AI 代理“即插即用”地使用各种服务能力,这也是其设计的精妙之处。

当然,MCP 也并不是完美的,作为一个新兴的协议,它仍然在不断发展中。未来可能会有更多的功能和特性被添加进来,以满足更复杂的需求。

背景

MCP 支持两种标准的传输实现:标准输入/输出(stdio)和 Server-Sent Event[1](下称 SSE)。stdio 基于命令行工具,多用于本地集成,通过进程通信来实现;SSE 基于客户端和服务器的网络通信,用于跨设备网络的通信场景。

既然是用抓包来分析,我们就要选择使用 SSE 传输的 MCP server,然后通过工具进行网络抓包分析。在抓包分析之前,我们有必要对 SSE 协议进行简单的了解。

SSE 协议

SSE 协议是一种服务器推送技术,使客户端能够通过 HTTP 连接从服务器自动接收更新,通常用于服务器向客户端发送消息更新或者连续的数据流(流信息 streaming)。

本质上,HTTP 协议是无法实现主动推送消息的,除非服务端“通知”客户端接下来发送的是流信息。因此客户端便不会断开该连接,并持续从该连接上接收数据流。

看到这里你是否想到了 WebSocket 协议?二者看起来都是客户端与服务端建立连接,然后服务端向客户端推送数据。看似相同,实际差别还挺大:

  • SSE 是基于 HTTP 的轻量级协议;WebSocket 是独立的协议。
  • SSE 是基于 HTTP 请求 Accept: text/event-stream;WebSocket 借助 HTTP 升级协议 Upgrade: websocket,之后使用独立协议。
  • SSE 是伪双工,只支持服务端到客户端的单向通信,客户端到服务端的通信还需要另外发送 HTTP 请求进行;WebSocket 是全双工的双向通信。
  • SSE 简单、轻量,适合单向低频推送;WebSocket 复杂度高、实时性强,适合双向高频交互。

从上面的对比不难看出 MCP 选择 SSE 作为网络传输协议的原因了。

了解了 SSE 协议之后,我们就可以开始了。

环境

  • 抓包工具:Proxyman ,并安装 CA 证书,方便处理 HTTPS 的请求。
  • AI 应用:VSCode Insiders,安装 GitHub Copilot 插件并开启 Agent 模式。
  • MCP Server:使用上一篇文章[2]中的示例。

MCP通信架构图

配置 MCP Server

settings.json 中添加 MCP Server 配置。为了能够使用 Proxyman 的 HTTP 代理,在 /etc/hosts 中添加 127.0.0.1 nio.local

{
  “mcp”: {
    “servers”: {
      “spring-ai-mcp-sample”: {
        “type”: “sse”,
        “url”: “http://nio.local:8080/sse”
      }
    }
  }
}

添加好之后就可以启动 MCP Client 连接 Server 了。

VSCode中MCP Server配置运行状态

MCP 通信

下面我们将通过抓包分析,详细了解 MCP 通信的完整生命周期,包括建立连接、初始化、操作和终止四个阶段。

当 VSCode 成功连接到 MCP Server 后,从 Proxyman 已经可以看到多条通信记录了。

Proxyman抓包界面展示MCP连接请求

建立连接

由于不确定 Server 支持哪种方法,MCP Client 会同时发送 GETPOST 请求到我们配置的 Server 地址,尝试建立连接。请求中的 Accept 头是 text/event-stream,说明是与 Server 尝试进行 SSE 通信。

这里配置的 Server 仅支持通过 GET 方式建立 SSE 通信,POST 请求收到了 404 响应。而 GET 请求的响应中,Server 端回传了如下信息:

  • 会话 id:3e19fbcd-51f4-4784-9f63-538c9a203859
  • 事件 eventendpoint 表示数据的内容,也就是后续客户端 Client 与 Server 单向通信的端点。
  • 数据 data/mcp/messages?sessionId=3e19fbcd-51f4-4784-9f63-538c9a203859,其中 /mcp/messages 是由服务侧配置的 spring.ai.mcp.server.sse-message-endpoint: /mcp/messages
id:3e19fbcd-51f4-4784-9f63-538c9a203859
event:endpoint
data:/mcp/messages?sessionId=3e19fbcd-51f4-4784-9f63-538c9a203859

这个 HTTP 连接将作为后续 Server 向 Client 推送流信息的通道,所以在截图中我们看到了其他的流信息。此时 MCP Client 与 Server 连接的生命周期就开始了:

  • 初始化
  • 操作
  • 终止

MCP通信序列图:初始化、操作、关闭三个阶段

初始化

初始化阶段必须是客户端与服务器之间的首次交互,这个过程有点类似 TCP 的三次握手

Client 发起初始化请求

从 Server 接收到后续的通信端点后,Client 会发送 initialize 请求进行初始化,上报信息和功能协商。

  • protocolVersion 协议的版本
  • capabilities 功能支持:listChanged 表示支持列表变更通知
  • clientInfo 客户端信息
{
  “jsonrpc”: “2.0”,
  “id”: 1,
  “method”: “initialize”,
  “params”: {
    “protocolVersion”: “2025-03-26”,
    “capabilities”: {
      “roots”: {
        “listChanged”: true
      }
    },
    “clientInfo”: {
      “name”: “Visual Studio Code - Insiders”,
      “version”: “1.100.0-insider”
    }
  }
}

Server 响应初始化请求

同样 Server 也回传了流信息:

  • 相同的会话 id
  • 事件类型 message
  • 事件数据
id:3e19fbcd-51f4-4784-9f63-538c9a203859
event:message
data:{“jsonrpc”:”2.0”,”id”:1,”result”:{“protocolVersion”:”2024-11-05”,”capabilities”:{“logging”:{},”tools”:{“listChanged”:true}},”serverInfo”:{“name”:”webmvc-mcp-server”,”version”:”1.0.0”}}}

在事件的数据部分,Server 也提供了与请求类似的内容(在下文中将直接展示流信息中的数据部分):

{
  “jsonrpc”: “2.0”,
  “id”: 1,
  “result”: {
    “protocolVersion”: “2024-11-05”,
    “capabilities”: {
      “logging”: {},
      “tools”: {
        “listChanged”: true
      }
    },
    “serverInfo”: {
      “name”: “webmvc-mcp-server”,
      “version”: “1.0.0”
    }
  }
}

初始化完成

在完成与 Server 端的信息交换,并协商(如版本兼容、功能支持)成功后,Client 发送请求完成初始化。

{
  “method”: “notifications/initialized”,
  “jsonrpc”: “2.0”
}

这一次 Server 并不会有任何响应,就像是 TCP 握手时客户端发送了 ACK 后,服务端不会进行任何处理一样。

操作

获取 tool 列表

完成初始化后,Client 发送请求获取 Server 支持的 tool 列表。

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

服务端通过 SSE 连接回传 tool 列表,我们使用的示例 Server 中包含了 4 个 tool。在响应内容包含了如 tool 名字、输入 schema 参数说明等信息。客户端收到这个响应后,会在本地缓存 tool 列表避免频繁的请求。只有当 Server 端更新了列表并通知 Client 后才会更新缓存内容。

篇幅原因,没有全部展示列表内容。

{
  “jsonrpc”: “2.0”,
  “id”: 2,
  “result”: {
    “tools”: [
      {
        “name”: “addUser”,
        “description”: “Add a new user”,
        “inputSchema”: {
          “type”: “object”,
          “properties”: {
            “arg0”: {
              “type”: “object”,
              “properties”: {
                “email”: {
                  “type”: “string”
                },
                “name”: {
                  “type”: “string”
                }
              },
              “required”: [
                “email”,
                “name”
              ],
              “description”: “user to add”
            }
          },
          “required”: [
            “arg0”
          ],
          “additionalProperties”: false
        }
      },
     //...
    ]
  }
}

有了 tool 列表之后,我们便可以尝试让 Copilot 为我们执行任务了。在 Copilot Agent 模式下输入和上次一样的任务:

First, help me check the user list to see if there is a user named Carson. If not, add a new user: Carson carson@gmail.com[3]; then check the list again to see if the new user was added successfully. Finally, say hello to Carson.

先来看执行结果。

在我发出任务请求后,VSCode 经过一通分析决定一次执行几个 tool 来完成任务。这里我使用的是 GPT-4o 的模型,没有任何推理过程的展示。如果不是展开了工具的执行结果,最终能看到的只有最后的一句话。

GitHub Copilot Agent使用GPT-4o模型执行MCP工具

如果切换到 Claude 3.7 Sonnet 模型,执行时会加入推理,整个流程会清晰很多。

GitHub Copilot Agent使用Claude 3.7模型执行MCP工具

执行

回到 Proxyman 查看抓取的请求。

  1. VSCode 请求 Copilot Server:传输的请求内容比较长。以 GPT-4o 模型为例,请求大小为 49.7 KB,响应 1.34 KB
    请求中包含了:

    • 一段非常长的系统 Prompt,有兴趣的可以参考开发者整理的 GitHub Copilot Agent 官方 Prompt[4]
    • 可用的 tool 列表,包括 VSCode 官方提供的系统 tool 以及配置的 MCP Server 提供的 tool

    Proxyman抓取到Copilot API请求的详细内容

    在响应中包含了经过分析任务后决定要调用的 tool:

    {
      “choices”: [
        {
          “index”: 0,
          “delta”: {
            “content”: null,
            “role”: “assistant”,
            “tool_calls”: [
              {
                “function”: {
                  “arguments”: “”,
                  “name”: “bb7_getUsers”
                },
                “id”: “call_nL7ToTNvrfLwUPYoqtUH8Yx3”,
                “index”: 0,
                “type”: “function”
              }
            ]
          }
        }
      ],
      “created”: 1745649196,
      “id”: “chatcmpl-BQTO863fJsOBHD4tU1LN3AEk5Uuo2”,
      “model”: “gpt-4o-2024-11-20”,
      “system_fingerprint”: “fp_ee1d74bde0”
    }
  2. VSCode 调用 MCP Tool:根据响应内容,VSCode 向 MCP Server 发送请求。

    //http://nio.local:8080/mcp/messages?sessionId=3e19fbcd-51f4-4784-9f63-538c9a203859
    {
      “jsonrpc”: “2.0”,
      “id”: 3,
      “method”: “tools/call”,
      “params”: {
        “name”: “getUsers”,
        “arguments”: {}
      }
    }

    MCP Server 在 SSE 连接中回传 tool 的调用结果。

    {
      “jsonrpc”: “2.0”,
      “id”: 3,
      “result”: {
        “content”: [
          {
            “type”: “text”,
            “text”: “[{\"name\":\"John\",\"email\":\"john@example.com\"},{\"name\":\"Jane\",\"email\":\"jane@example.com\"}]”
          }
        ],
        “isError”: false
      }
    }

    紧接着 VSCode 将调用结果发送给 Copilot Server 进行处理,然后又得到一个要调用的 tool,以及需要提供的参数。

    Copilot API响应中包含下一个要调用的工具及参数

  3. 循环执行:如此往复,直到最终完成任务的执行。在最后一个发送给 Copilot Server 的请求中,可以看到这个任务执行过程中所有调用的 tool 请求和响应的列表。也就是说,每次调用模型时,都会带上此前调用的所有 tool 请求和响应,因此请求的 size 也是逐渐变大的。

    Copilot最终请求中包含了完整的工具调用历史记录

终止

终止操作就简单了,对于 SSE 传输类型的 MCP 交互来说,就是断开相关的 HTTP 连接。

参考资料

[1] Server-Sent Event: _https://en.wikipedia.org/wiki/Server-sent_events_

[2] 上一篇文章: _https://mp.weixin.qq.com/s/jhXpxkMSyts_O5OuDsE9XA_

[3] carson@gmail.com: vscode-file://vscode-app/Applications/Visual%20Studio%20Code%20-%20Insiders.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html

[4] GitHub Copilot Agent 官方 Prompt: _https://github.com/LouisShark/chatgpt_system_prompt/blob/main/prompts/official-product/github/github_copilot_agent.md_





上一篇:抖音美好体(DouyinSans)品牌定制字体设计解读与应用,现已开源免费商用
下一篇:MCP协议解析:它如何成为AI应用开发的智能服务编排器?
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-4-7 18:12 , Processed in 0.726175 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表