MCP + SSE:?jiǎn)蜗蛲ㄐ湃绾瓮娉鲭p向操作?
“ 你是否覺(jué)得 SSE 只能單向通信?MCP 用一招教你實(shí)現(xiàn)雙向通信!”
SSE 本身確實(shí)只能從服務(wù)器到客戶(hù)端單向通信,但 MCP(Model Context Protocol)通過(guò)一個(gè)巧妙的組合拳,把 SSE 和 HTTP POST 請(qǐng)求搭配在一起,成功實(shí)現(xiàn)了完整的雙向通信。
聽(tīng)起來(lái)是不是很酷?其實(shí)原理很簡(jiǎn)單——一個(gè)負(fù)責(zé)“說(shuō)”,一個(gè)負(fù)責(zé)“聽(tīng)”,組合起來(lái)就是“對(duì)話(huà)”了。
雙向通信的秘密
想象一下,客戶(hù)端和服務(wù)器在聊天,它們的對(duì)話(huà)是這樣開(kāi)始的:
- 客戶(hù)端先打招呼:通過(guò) GET 請(qǐng)求建立 SSE 連接,就像撥通了一個(gè)電話(huà)。
- 服務(wù)器回應(yīng):發(fā)送一個(gè)“endpoint”事件,告訴客戶(hù)端“我在這里等你發(fā)消息”。
- 客戶(hù)端開(kāi)始說(shuō)話(huà):通過(guò) HTTP POST 請(qǐng)求,把消息發(fā)到服務(wù)器提供的端點(diǎn)。
- 服務(wù)器回應(yīng):通過(guò) SSE 連接,把回復(fù)送回客戶(hù)端。
- 服務(wù)器主動(dòng)通知:隨時(shí)可以通過(guò) SSE 推送消息,就像發(fā)短信一樣。
- 客戶(hù)端再次發(fā)言:繼續(xù)用 HTTP POST 發(fā)送新消息。
為了更直觀地理解這個(gè)過(guò)程,我們可以通過(guò)以下流程圖來(lái)展示雙向通信的每一步:
整個(gè)過(guò)程就像兩個(gè)人打電話(huà),雖然用的是兩種不同的通信方式,但邏輯上完全實(shí)現(xiàn)了雙向?qū)υ?huà)。
客戶(hù)端的雙重身份
客戶(hù)端的工作分為兩部分:一是訂閱 SSE 事件流,二是通過(guò) HTTP POST 發(fā)送消息。
// 連接建立過(guò)程
@Override
publicMono<Void>connect(Function<Mono<JSONRPCMessage>, Mono<JSONRPCMessage>> handler){
// 1. 訂閱 SSE 事件流,就像打開(kāi)收音機(jī)
sseClient.subscribe(this.baseUri +this.sseEndpoint,newFlowSseClient.SseEventHandler(){
@Override
publicvoidonEvent(SseEvent event){
// 2. 處理 endpoint 事件,獲取消息發(fā)送端點(diǎn)
if(ENDPOINT_EVENT_TYPE.equals(event.type())){
String endpoint = event.data();
messageEndpoint.set(endpoint);
// 連接建立完成
}
// 3. 處理服務(wù)器發(fā)來(lái)的消息
elseif(MESSAGE_EVENT_TYPE.equals(event.type())){
JSONRPCMessage message =McpSchema.deserializeJsonRpcMessage(objectMapper, event.data());
handler.apply(Mono.just(message)).subscribe();
}
}
});
returnMono.fromFuture(future);
}
// 客戶(hù)端發(fā)送消息
@Override
publicMono<Void>sendMessage(JSONRPCMessage message){
// 使用 HTTP POST 發(fā)送消息到服務(wù)器提供的端點(diǎn)
// ...
}
簡(jiǎn)單來(lái)說(shuō),客戶(hù)端就像一個(gè)既能聽(tīng)又能說(shuō)的人:一邊通過(guò) SSE“聽(tīng)”服務(wù)器的消息,一邊通過(guò) HTTP POST“說(shuō)”自己的話(huà)。
服務(wù)器的中轉(zhuǎn)站
服務(wù)器的工作更像一個(gè)中轉(zhuǎn)站,既要處理客戶(hù)端的請(qǐng)求,又要通過(guò) SSE 推送消息。
// 處理 SSE 連接請(qǐng)求
privateServerResponsehandleSseConnection(ServerRequest request){
// 創(chuàng)建會(huì)話(huà),就像給每個(gè)客戶(hù)端分配一個(gè)專(zhuān)屬頻道
String sessionId =UUID.randomUUID().toString();
// 發(fā)送初始 endpoint 事件,告訴客戶(hù)端“我在哪”
sseBuilder.id(sessionId)
.event(ENDPOINT_EVENT_TYPE)
.data(this.baseUrl +this.messageEndpoint +"?sessinotallow="+ sessionId);
// 創(chuàng)建會(huì)話(huà)傳輸層
WebMvcMcpSessionTransport sessionTransport =newWebMvcMcpSessionTransport(sessionId, sseBuilder);
McpServerSession session = sessionFactory.create(sessionTransport);
this.sessions.put(sessionId, session);
}
// 處理客戶(hù)端發(fā)來(lái)的消息
privateServerResponsehandleMessage(ServerRequest request){
// 從請(qǐng)求中獲取會(huì)話(huà) ID,就像找到對(duì)應(yīng)的聊天窗口
String sessionId = request.param("sessionId").orElse(null);
// 處理客戶(hù)端發(fā)來(lái)的消息
// ...
// 通過(guò) SSE 連接發(fā)送響應(yīng)
// ...
}
// 服務(wù)器向客戶(hù)端發(fā)送消息
@Override
publicMono<Void>sendMessage(McpSchema.JSONRPCMessage message){
returnMono.fromRunnable(()->{
try{
String jsonText = objectMapper.writeValueAsString(message);
sseBuilder.id(sessionId).event(MESSAGE_EVENT_TYPE).data(jsonText);
}
catch(Exception e){
// 錯(cuò)誤處理
}
});
}
服務(wù)器的核心任務(wù)是管理會(huì)話(huà),確保每個(gè)客戶(hù)端的消息都能準(zhǔn)確無(wú)誤地傳遞。
雙向通信的四大支柱
- 初始連接:客戶(hù)端通過(guò) GET 請(qǐng)求建立 SSE 連接,就像撥通了一個(gè)電話(huà)。
- 端點(diǎn)發(fā)現(xiàn):服務(wù)器通過(guò) SSE 發(fā)送“endpoint”事件,告訴客戶(hù)端“我在這里等你”。
- 雙向通信:
a.客戶(hù)端通過(guò) HTTP POST 發(fā)送消息
b.服務(wù)器通過(guò) SSE 推送消息到客戶(hù)端
- 會(huì)話(huà)管理:服務(wù)器為每個(gè)客戶(hù)端分配唯一的會(huì)話(huà) ID,確保消息不會(huì)“串門(mén)”。
這種設(shè)計(jì)的厲害之處在于,它沒(méi)有試圖“改造”SSE,而是聰明地利用了它的實(shí)時(shí)推送優(yōu)勢(shì),同時(shí)用 HTTP POST 解決了反向通信的問(wèn)題。
就像給一輛單缸摩托車(chē)裝上了副駕駛座,瞬間變成了能對(duì)話(huà)的“雙人通信車(chē)”。
更妙的是,這種組合拳式的實(shí)現(xiàn)方式,不僅保持了 SSE 的輕量化特性,還避免了 WebSocket 那種復(fù)雜的雙向協(xié)議開(kāi)銷(xiāo)。
對(duì)于那些需要實(shí)時(shí)推送但又不想引入復(fù)雜技術(shù)棧的項(xiàng)目來(lái)說(shuō),MCP 的這套方案簡(jiǎn)直是“降維打擊”。
雙向通信的更多可能
MCP 的這套組合拳,不僅解決了 SSE 的單向通信問(wèn)題,還保留了實(shí)時(shí)推送的優(yōu)勢(shì)。
未來(lái),這種設(shè)計(jì)思路可以應(yīng)用到更多場(chǎng)景中,比如物聯(lián)網(wǎng)設(shè)備通信、微服務(wù)之間的輕量級(jí)消息傳遞,甚至是 Web 應(yīng)用中的實(shí)時(shí)協(xié)作功能。
想象一下,當(dāng)你的前端應(yīng)用需要和后端服務(wù)實(shí)時(shí)互動(dòng)時(shí),用 MCP 的這套方案,既簡(jiǎn)單又高效,還能避免引入額外的技術(shù)復(fù)雜性。是不是很期待?趕緊試試吧!