关于MCP SSE 服务器的工作原理

模型上下文协议(Model Context Protocol,简称MCP) 是一种全新的开放协议,专门用于标准化地为大语言模型(LLMs)提供应用场景和数据背景。 你可以把MCP想象成AI领域的“USB-C接口”,它能让不同的AI模型与外部工具和数据源轻松连接

近来学习了一下,先是使用stdio的方式叫cursor做了一个,完全没有问题。但是sse的方式叫cursor 干始终不成功, 找了一轮,发现youtube的教程视频里主持,也没有搞定sse的服务器,balahblah说了一堆,就要move on ....于是研究了一下。

1. 首先MCP SSE是基于http协议的一个应用,服务器和客户端主要通过json rc的方式进行沟通。

2. MCP SSE Client会发起多个连接,但是第一个连接是http://yourhost:port/sse,  这个连接是沟通的第一步,它会使用chunked的回传数据,意思是不告诉client这个数据有多少,这样就它就可以一直连着了。 所以这个链接就是一个用来通知的链接。你现在就明白了为什么 ,就叫SSE(Server-Sent Events )。 它首先按以下格式信息给client, 然后就是定时的ping包了, 每次都只是一个chunk,估计后期server会有推送也会使用这个链接通知client.

event: 事件的名字
data:  事件的数据

      2.1 第一个event是,这个直接返回,就是给client分配一个session_id, 方便后面多个连接过来服务器可以分清谁和谁。


51
event: endpoint
data: /messages/?session_id=07aa8f90d79a49eaad802693cdd05b5b

      client收到这个,就会以http://yourhost:port/messages/?session_id=07aa8f90d79a49eaad802693cdd05b5b , 新发起一个连接去请求mcp sse server

     2.2 第二个event是event: message, 这个data 是一个json来的,就是告诉client,当前mcp server的能力,还有服务器的基本信息。

124
event: message
data: {
  "jsonrpc": "2.0",
  "id": 0,
  "result": {
    "protocolVersion": "2024-11-05",
    "capabilities": {
      "experimental": {},
      "prompts": {
        "listChanged": false
      },
      "resources": {
        "subscribe": false,
        "listChanged": false
      },
      "tools": {
        "listChanged": false
      }
    },
    "serverInfo": {
      "name": "mem0-mcp",
      "version": "1.3.0"
    }
  }
}

     2.3 第三个event也是一个message , 用来告诉client 服务器提供的tools有哪些。

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "add_coding_preference",
        "description": "Add a new coding preference to mem0. This tool stores code snippets, implementation details,\n    and coding patterns for future reference. Store every code snippet. When storing code, you should include:\n    - Complete code with all necessary imports and dependencies\n    - Language/framework version information (e.g., \"Python 3.9\", \"React 18\")\n    - Full implementation context and any required setup/configuration\n    - Detailed comments explaining the logic, especially for complex sections\n    - Example usage or test cases demonstrating the code\n    - Any known limitations, edge cases, or performance considerations\n    - Related patterns or alternative approaches\n    - Links to relevant documentation or resources\n    - Environment setup requirements (if applicable)\n    - Error handling and debugging tips\n    The preference will be indexed for semantic search and can be retrieved later using natural language queries.",
        "inputSchema": {
          "properties": {
            "text": {
              "title": "Text",
              "type": "string"
            }
          },
          "required": [
            "text"
          ],
          "title": "add_coding_preferenceArguments",
          "type": "object"
        }
      },
      {
        "name": "get_all_coding_preferences",
        "description": "Retrieve all stored coding preferences for the default user. Call this tool when you need \n    complete context of all previously stored preferences. This is useful when:\n    - You need to analyze all available code patterns\n    - You want to check all stored implementation examples\n    - You need to review the full history of stored solutions\n    - You want to ensure no relevant information is missed\n    Returns a comprehensive list of:\n    - Code snippets and implementation patterns\n    - Programming knowledge and best practices\n    - Technical documentation and examples\n    - Setup and configuration guides\n    Results are returned in JSON format with metadata.",
        "inputSchema": {
          "properties": {},
          "title": "get_all_coding_preferencesArguments",
          "type": "object"
        }
      },
      {
        "name": "search_coding_preferences",
        "description": "Search through stored coding preferences using semantic search. This tool should be called \n    for EVERY user query to find relevant code and implementation details. It helps find:\n    - Specific code implementations or patterns\n    - Solutions to programming problems\n    - Best practices and coding standards\n    - Setup and configuration guides\n    - Technical documentation and examples\n    The search uses natural language understanding to find relevant matches, so you can\n    describe what you're looking for in plain English. Always search the preferences before \n    providing answers to ensure you leverage existing knowledge.",
        "inputSchema": {
          "properties": {
            "query": {
              "title": "Query",
              "type": "string"
            }
          },
          "required": [
            "query"
          ],
          "title": "search_coding_preferencesArguments",
          "type": "object"
        }
      }
    ]
  }
}

跟着就是ping包的返回,防止client死了。


2d
: ping - 2025-03-12 08:16:23.071429+00:00

3. endpoint请求

   拿到endpont后,client 使用post的请求endpoint,  这个只处理请求,目前看 返回则在第一个http连接里。

第二个链接 请求如下:, 这个调用initialize,对应上面的第一个message的event.

第二个链接, 这个只回复202 Accepted

POST /messages/?session_id=9aa12073a4494d5580a5c30ed54c4bfd HTTP/1.1
host: 10.0.105.64:8080
connection: keep-alive
content-type: application/json
accept: */*
accept-language: *
sec-fetch-mode: cors
user-agent: node
accept-encoding: gzip, deflate
content-length: 253

{"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{"tools":true,"prompts":false,"resources":true,"logging":false,"roots":{"listChanged":false}},"clientInfo":{"name":"cursor-vscode","version":"1.0.0"}},"jsonrpc":"2.0","id":0}
HTTP/1.1 202 Accepted

date: Wed, 12 Mar 2025 08:08:32 GMT
server: uvicorn
content-length: 8

Accepted

第三个链接,请求如下:


第三个链接,仅回复 202 Accepted

POST /messages/?session_id=9aa12073a4494d5580a5c30ed54c4bfd HTTP/1.1
host: 10.0.105.64:8080
connection: keep-alive
content-type: application/json
accept: */*
accept-language: *
sec-fetch-mode: cors
user-agent: node
accept-encoding: gzip, deflate
content-length: 54

{"method":"notifications/initialized","jsonrpc":"2.0"}
HTTP/1.1 202 Accepted
date: Wed, 12 Mar 2025 08:08:32 GMT
server: uvicorn
content-length: 8

Accepted

第四个链接,请求如下,请求tools/list, 服务器在第一个get的链接,通过event的方式返回了这个列表给mcp sse client


第四个链接,仅加复 202 Accepted


POST /messages/?session_id=9aa12073a4494d5580a5c30ed54c4bfd HTTP/1.1
host: 10.0.105.64:8080
connection: keep-alive
content-type: application/json
accept: */*
accept-language: *
sec-fetch-mode: cors
user-agent: node
accept-encoding: gzip, deflate
content-length: 46

{"method":"tools/list","jsonrpc":"2.0","id":1}
HTTP/1.1 202 Accepted
date: Wed, 12 Mar 2025 08:08:32 GMT
server: uvicorn
content-length: 8

Accepted

1-3完成就是属于初始化完成,mcp sse的client和server 连接起来了。

然后后面使用mcp call 调用的,在cursor chat里输入

call mcp tool search_coding_preferences about StdioServerTransport

就是新起一个http短链接,post到endpoint,如下

POST /messages/?session_id=97a44bcff590415e99cf803350ffd542 HTTP/1.1
host: 10.0.105.64:8080
connection: keep-alive
content-type: application/json
accept: */*
accept-language: *
sec-fetch-mode: cors
user-agent: node
accept-encoding: gzip, deflate
content-length: 143

{"method":"tools/call","params":{"name":"search_coding_preferences","arguments":{"query":"about StdioServerTransport"}},"jsonrpc":"2.0","id":3}HTTP/1.1 202 Accepted
date: Wed, 12 Mar 2025 09:10:43 GMT
server: uvicorn
content-length: 8

HTTP/1.1 202 Accepted
date: Wed, 12 Mar 2025 09:10:43 GMT
server: uvicorn
content-length: 8

Accepted

第一个链接就是会有一个通知返回如下:

event: message
data: {"jsonrpc":"2.0","id":3,"result":{"content":[{"type":"text","text":"[]"}],"isError":false}}

### ### MCPSSE工作原理MCP(Model Control Plane)框架中,SSE(Server-Sent Events)模式与传统的 stdio 模式在通信方式和服务器位置上有显著差异。SSE 模式基于 HTTP 协议,允许服务器向客户端单向推送事件流,适用于需要实时更新的场景[^1]。 SSE 的工作机制基于 HTTP 长连接。客户端通过标准的 HTTP GET 请求向服务器订阅事件流,服务器保持连接打开,并在有新事件时持续发送数据,直到连接关闭或服务器终止流。与 stdio 模式不同,SSE 模式不需要直接的进程间通信(IPC),而是通过网络进行通信,使得客户端可以在远程访问服务器。 在 MCP 框架中,SSE 模式通常用于实现服务器向客户端的实时数据推送。客户端通过 `EventSource` API 订阅服务器端的事件流,服务器端则需要支持保持连接开放,并以 `text/event-stream` 的 MIME 类型响应客户端请求。每当有新事件发生时,服务器将事件数据写入响应流中,客户端则通过事件监听器接收数据[^2]。 ### ### MCPSSE 的使用方法 在 MCP 框架中,客户端通过 `EventSource` API 订阅服务器端的事件流。以下是一个示例代码: ```javascript const eventSource = new EventSource('https://mcp.amap.com/sse?key=YOUR_KEY'); eventSource.onopen = (event) => { console.log('SSE连接已建立'); }; eventSource.addEventListener('message', (event) => { const data = JSON.parse(event.data); console.log('收到服务器数据:', data); }); eventSource.onerror = (event) => { console.error('SSE连接错误'); eventSource.close(); }; ``` 服务器端需要支持保持连接开放,并以 `text/event-stream` 的 MIME 类型响应客户端请求。每当有新事件发生时,服务器将事件数据写入响应流中,客户端则通过事件监听器接收数据。服务器在发送数据时遵循特定的格式规范,确保客户端能够正确解析事件流[^3]。 ### ### MCPSSE 的优势 SSEMCP 框架中的优势在于其基于 HTTP,无需额外的协议协商,实现成本较低,适用于服务器向客户端的单向数据推送。SSE 提供了自动重连机制,客户端会自动尝试重新连接以维持事件流的持续性,除非服务器明确关闭连接。此外,SSE 使用纯文本格式进行数据传输,支持 `data`、`event`、`id` 和 `retry` 等字段,使得数据传输更加灵活。 ### ### 适用场景 SSEMCP 框架中特别适合需要服务器向客户端单向推送数据的应用,例如实时通知系统、数据流更新(如股票价格、天气变化)、日志信息推送、进度更新(如文件上传状态)等场景。这些应用场景通常需要服务器能够实时地将更新推送给客户端,而客户端不需要频繁地向服务器发送请求。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值