返回市场
麦普服务器事件引擎

麦普服务器事件引擎

作者:KelvinQiu80225 星标更新:2025-04-15

项目介绍

技术文档摘要

SSE MCP

HTTP+SSE 将逐步被替换为 Streamable HTTP

用新的“Streamable HTTP”传输替换 HTTP+SSE

当前情况

  • 通过STDio本地运行MCP是不安全的
    • 恶意MCP可以伪装成正常工具并被LLM调用
    • 敏感数据泄露
    • 安装不便(npx/uvx/docker)
  • MCP服务器托管变得流行
    • 需要筛选
    • 身份验证
    • 阿里云白名单/腾讯云/Zapier
    • HTTP+SSE / Streamable HTTP

目标

  • 什么是SSE及其原理(服务器发送事件)
  • 使用SSE的ChatGPT示例
  • 使用原生JS实现SSE服务器和客户端
  • MCP的SSE实现
  • 实现一个用于SSE传输的MCP服务器
  • CherryStudio调用
  • MCP Inspector + Wireshark 抓包

服务器发送事件

ChatGPT/KIMI/DeepSeek 的SSE

// ChatGPT SSE
event: delta
data: {"p": "/message/content/parts/0", "o": "append", "v": "\u597d\uff0c\u54b1\u63a5\u7740\u8bf4\uff0c\u8bf4\u5b8c"} 

event: delta
data: {"v": "\u4e86\u5ba2\u6237\u7aef\u8fd9\u8fb9\uff0c\u63a5\u4e0b\u6765\u770b\u770b"}       

event: delta
data: {"v": "\u3002\n\n"}  

event: delta
data: {"v": "---\n\n### \ud83d\udd27 \u670d\u52a1\u7aef\u793a\u4f8b"} 

event: delta
data: {"v": "\uff08\u4ee5 Node.js \u4e3a\u4f8b\uff09\n\n```"} 

event: delta
data: {"v": "js\nconst http = require(\"http"}
// KIMI SSE
data: {"event":"cmpl","idx_s":0,"idx_z":0,"text":"好","view":"cmpl"}

data: {"event":"cmpl","idx_s":0,"idx_z":0,"text":"的","view":"cmpl"}

data: {"event":"cmpl","idx_s":0,"idx_z":0,"text":",","view":"cmpl"}

data: {"event":"cmpl","idx_s":0,"idx_z":0,"text":"除","view":"cmpl"}

data: {"event":"cmpl","idx_s":0,"idx_z":0,"text":"了","view":"cmpl"}

data: {"event":"cmpl","idx_s":0,"idx_z":0,"text":"前","view":"cmpl"}

data: {"event":"cmpl","idx_s":0,"idx_z":0,"text":"面","view":"cmpl"}
// DeepSeek SSE
data: {"v": " **"}

data: {"v": "1"}

data: {"v": "."}

data: {"v": " "}

data: {"v": "高级"}

data: {"v": "用法"}

data: {"v": "与"}

data: {"v": "功能"}
  • ChatGPT:使用事件声明自定义事件
  • KIMI:全部使用默认消息事件,在JSON的事件字段中声明自定义事件
  • 没有定义ID
    • 不需要短期重连
    • 数据有序发送,一次性消费

原生JS SSE实现

代码仓库

MCP SSE

Wireshark抓包

连接

// 初次连接,SSE传输POST接口,用于后续请求
GET /sse HTTP/1.1
X-Powered-By: Express
Content-Type: text/event-stream
Cache-Control: no-cache, no-transform
Connection: keep-alive
Date: Tue, 15 Apr 2025 12:19:00 GMT
Transfer-Encoding: chunked

event: endpoint
data: /messages?sessionId=8838e9b4-d065-4b8e-9fa9-b96f31ef835c

---

// 客户端发送PSOT请求,初始化连接参数
POST /messages?sessionId=8838e9b4-d065-4b8e-9fa9-b96f31ef835c HTTP/1.1
host: localhost:3000
connection: keep-alive
Accept: text/event-stream
content-type: application/json
accept-language: *
sec-fetch-mode: cors
user-agent: node
accept-encoding: gzip, deflate
content-length: 204

{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{"sampling":{},"roots":{"listChanged":true}},"clientInfo":{"name":"mcp-inspector","version":"0.9.0"}}}

---

// SSE返回数据
event: message
data: {"result":{"protocolVersion":"2024-11-05","capabilities":{"tools":{}},"serverInfo":{"name":"hackernews-server","version":"1.0.0"}},"jsonrpc":"2.0","id":0}

---

// 初始化完成通知
POST /messages?sessionId=8838e9b4-d065-4b8e-9fa9-b96f31ef835c HTTP/1.1
host: localhost:3000
connection: keep-alive
Accept: text/event-stream
content-type: application/json
accept-language: *
sec-fetch-mode: cors
user-agent: node
accept-encoding: gzip, deflate
content-length: 54

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

---

Accepted

---

列出工具

POST /messages?sessionId=32468b11-6f98-454d-b176-ffcf985602d6 HTTP/1.1
host: localhost:3000
connection: keep-alive
Accept: text/event-stream
content-type: application/json
accept-language: *
sec-fetch-mode: cors
user-agent: node
accept-encoding: gzip, deflate
content-length: 85

{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{"_meta":{"progressToken":1}}}

---

event: message
data: {"result":{"tools":[{"name":"get-hackernews-top-stories","description":"获取Hacker News上的故事","inputSchema":{"type":"object","properties":{"type":{"type":"string","enum":["topstories","newstories","beststories"]},"amount":{"type":"number","minimum":1,"maximum":500,"default":10}},"required":["type"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}]},"jsonrpc":"2.0","id":1}

调用工具

POST /messages?sessionId=a03d6f2f-483a-4432-a685-f900aae6a15c HTTP/1.1
host: localhost:3000
connection: keep-alive
Accept: text/event-stream
content-type: application/json
accept-language: *
sec-fetch-mode: cors
user-agent: node
accept-encoding: gzip, deflate
content-length: 166

{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"_meta":{"progressToken":2},"name":"get-hackernews-top-stories","arguments":{"type":"topstories","amount":5}}}

---

event: message
data: {"result":{"content":[{"type":"text","text":"{\"by\":\"doener\",\"descendants\":26,\"id\":43690955,\"kids\":[43691597,43691629,43691555,43691554,43691616,43691669,43691546,43691621],\"score\":58,\"time\":1744712237,\"title\":\"Teuken-7B-Base and Teuken-7B-Instruct: Towards European LLMs\",\"type\":\"story\",\"url\":\"https://arxiv.org/abs/2410.03730\"}"},{"type":"text","text":"{\"by\":\"rbanffy\",\"descendants\":75,\"id\":43661954,\"kids\":[43690672,43691740,43690999,43690833,43691234,43690870,43691618,43691314,43690559,43691552,43662023,43690935,43690670,43690778,43691387,43690568],\"score\":154,\"time\":1744440499,\"title\":\"Wait. HOW MANY supernova explode every year?\",\"type\":\"story\",\"url\":\"https://badastronomy.beehiiv.com/p/ban-447-wait-how-many-supernova-explode\"}"},{"type":"text","text":"{\"by\":\"LookAtThatBacon\",\"descendants\":92,\"id\":43691334,\"kids\":[43691534,43691870,43691925,43691637,43691663,43691580,43691851,43691654,43691801,43691922,43691927,43691673,43691694,43691744,43691635,43691652,43691763,43691733,43691557],\"score\":135,\"time\":1744716656,\"title\":\"4chan hacked. Hacker reopens /QA/ and leaks all admins emails\",\"type\":\"story\",\"url\":\"https://old.reddit.com/r/4chan/comments/1jzkjlg/4chan_hacked_hacker_reopens_qa_and_leaks_all/\"}"},{"type":"text","text":"{\"by\":\"walterbell\",\"descendants\":46,\"id\":43688658,\"kids\":[43691249,43689886,43689209,43691657,43690253,43689327,43691628,43691289,43690261,43689700,43689175,43689172,43689747,43690464,43689992,43690388,43689144,43689473,43689002],\"score\":236,\"time\":1744686775,\"title\":\"Hacking a Smart Home Device (2024)\",\"type\":\"story\",\"url\":\"https://jmswrnr.com/blog/hacking-a-smart-home-device\"}"},{"type":"text","text":"{\"by\":\"TechTechTech\",\"descendants\":75,\"id\":43678590,\"kids\":[43689599,43689147,43691529,43690367,43689187,43690040,43689517,43690321,43689995,43680524,43689481,43690012,43691232,43689773,43690682,43691317,43684752,43689254,43689452,43689731],\"score\":229,\"time\":1744612068,\"title\":\"JSLinux\",\"type\":\"story\",\"url\":\"https://www.bellard.org/jslinux/\"}"}]},"jsonrpc":"2.0","id":2}