Ово поглавље пружа свеобухватан водич за имплементацију безбедног, скалабилног и реално-временског стриминга уз коришћење Model Context Protocol (MCP) преко HTTPS-а. Обухвата мотивацију за стриминг, доступне транспортне механизме, како имплементирати стриминг HTTP у MCP-у, најбоље безбедносне праксе, миграцију са SSE-а и практичне смернице за изградњу сопствених стриминг MCP апликација.
Овај одељак истражује различите транспортне механизме доступне у MCP-у и њихову улогу у омогућавању стриминг могућности за реално-временску комуникацију између клијената и сервера.
Транспортни механизам дефинише како се подаци размењују између клијента и сервера. MCP подржава више типова транспорта како би одговарао различитим окружењима и захтевима:
- stdio: Стандардни улаз/излаз, погодан за локалне и CLI алате. Једноставан, али није погодан за веб или облак.
- SSE (Server-Sent Events): Омогућава серверима да шаљу реално-временске ажурирања клијентима преко HTTP-а. Добро за веб интерфејсе, али ограничено у скалабилности и флексибилности.
- Streamable HTTP: Модеран HTTP базиран стриминг транспорт, који подржава нотификације и бољу скалабилност. Препоручује се за већину продукционих и облачних сценарија.
Погледајте табелу поређења испод да бисте разумели разлике између ових транспортних механизама:
| Транспорт | Реално-временска ажурирања | Стриминг | Скалабилност | Примена |
|---|---|---|---|---|
| stdio | Не | Не | Ниска | Локални CLI алати |
| SSE | Да | Да | Средња | Веб, реално-временска ажурирања |
| Streamable HTTP | Да | Да | Висока | Облак, више клијената |
Tip: Избор правог транспорта утиче на перформансе, скалабилност и корисничко искуство. Streamable HTTP се препоручује за модерне, скалабилне и облачно спремне апликације.
Обратите пажњу на транспортне механизме stdio и SSE који су вам приказани у претходним поглављима и како је streamable HTTP транспорт који се обрађује у овом поглављу.
Разумевање основних концепата и мотивације иза стриминга је кључно за имплементацију ефикасних система за реално-временску комуникацију.
Стриминг је техника у мрежном програмирању која омогућава слање и пријем података у малим, управљивим деловима или као низ догађаја, уместо да се чека да цео одговор буде спреман. Ово је посебно корисно за:
- Велике фајлове или скупове података.
- Реално-временска ажурирања (нпр. чет, траке напретка).
- Дуго трајајуће прорачуне где желите да корисник буде информисан.
Ево шта треба да знате о стримингу на високом нивоу:
- Подаци се испоручују постепено, не одједном.
- Клијент може обрађивати податке како стижу.
- Смањује перципирану латенцију и побољшава корисничко искуство.
Разлози за коришћење стриминга су следећи:
- Корисници добијају повратну информацију одмах, а не само на крају
- Омогућава реално-временске апликације и одзивне интерфејсе
- Ефикаснија употреба мрежних и рачунарских ресурса
Ево једноставног примера како се стриминг може имплементирати:
Сервер (Python, користећи FastAPI и StreamingResponse):
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import time
app = FastAPI()
async def event_stream():
for i in range(1, 6):
yield f"data: Message {i}\n\n"
time.sleep(1)
@app.get("/stream")
def stream():
return StreamingResponse(event_stream(), media_type="text/event-stream")Клијент (Python, користећи requests):
import requests
with requests.get("http://localhost:8000/stream", stream=True) as r:
for line in r.iter_lines():
if line:
print(line.decode())Овај пример показује сервер који шаље низ порука клијенту како постају доступне, уместо да чека да све поруке буду спремне.
Како функционише:
- Сервер шаље сваку поруку чим је спремна.
- Клијент прима и исписује сваки део како стиже.
Захтеви:
- Сервер мора користити стриминг одговор (нпр.
StreamingResponseу FastAPI-ју). - Клијент мора обрађивати одговор као стрим (
stream=Trueу requests). - Content-Type је обично
text/event-streamилиapplication/octet-stream.
Сервер (Java, користећи Spring Boot и Server-Sent Events):
@RestController
public class CalculatorController {
@GetMapping(value = "/calculate", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<String>> calculate(@RequestParam double a,
@RequestParam double b,
@RequestParam String op) {
double result;
switch (op) {
case "add": result = a + b; break;
case "sub": result = a - b; break;
case "mul": result = a * b; break;
case "div": result = b != 0 ? a / b : Double.NaN; break;
default: result = Double.NaN;
}
return Flux.<ServerSentEvent<String>>just(
ServerSentEvent.<String>builder()
.event("info")
.data("Calculating: " + a + " " + op + " " + b)
.build(),
ServerSentEvent.<String>builder()
.event("result")
.data(String.valueOf(result))
.build()
)
.delayElements(Duration.ofSeconds(1));
}
}Клијент (Java, користећи Spring WebFlux WebClient):
@SpringBootApplication
public class CalculatorClientApplication implements CommandLineRunner {
private final WebClient client = WebClient.builder()
.baseUrl("http://localhost:8080")
.build();
@Override
public void run(String... args) {
client.get()
.uri(uriBuilder -> uriBuilder
.path("/calculate")
.queryParam("a", 7)
.queryParam("b", 5)
.queryParam("op", "mul")
.build())
.accept(MediaType.TEXT_EVENT_STREAM)
.retrieve()
.bodyToFlux(String.class)
.doOnNext(System.out::println)
.blockLast();
}
}Напомене о Java имплементацији:
- Користи реактивни стек Spring Boot-а са
Fluxза стриминг ServerSentEventпружа структуирано стримовање догађаја са типовима догађајаWebClientсаbodyToFlux()омогућава реактивну конзумацију стримаdelayElements()симулира време обраде између догађаја- Догађаји могу имати типове (
info,result) за бољу обраду на клијенту
Разлике између класичног начина стриминга и начина на који MCP ради стриминг могу се приказати овако:
| Карактеристика | Класични HTTP стриминг | MCP стриминг (нотификације) |
|---|---|---|
| Главни одговор | Подељен на делове (chunked) | Један, на крају |
| Ажурирања напретка | Слање као делови података | Слање као нотификације |
| Захтеви клијента | Мора да обрађује стрим | Мора да имплементира обраду порука |
| Примена | Велики фајлови, AI токени | Напредак, логови, реално-временска повратна информација |
Поред тога, ево неких кључних разлика:
-
Образац комуникације:
- Класични HTTP стриминг: Користи једноставно chunked пренос података
- MCP стриминг: Користи структуирани систем нотификација са JSON-RPC протоколом
-
Формат поруке:
- Класични HTTP: Обичан текст са новим редовима
- MCP: Структуирани LoggingMessageNotification објекти са метаподацима
-
Имплементација клијента:
- Класични HTTP: Једноставан клијент који обрађује стриминг одговоре
- MCP: Сложенији клијент са обрадом порука за различите типове порука
-
Ажурирања напретка:
- Класични HTTP: Напредак је део главног стрима одговора
- MCP: Напредак се шаље као посебне нотификације, док главни одговор стиже на крају
Постоје неке препоруке када је реч о избору између класичног стриминга (као што смо показали горе користећи /stream ендпоинт) и стриминга преко MCP-а.
-
За једноставне потребе стриминга: Класични HTTP стриминг је једноставнији за имплементацију и довољан за основне потребе.
-
За сложене, интерактивне апликације: MCP стриминг пружа структуиранији приступ са богатијим метаподацима и раздвајањем нотификација и коначних резултата.
-
За AI апликације: MCP систем нотификација је посебно користан за дуготрајне AI задатке где желите да корисници буду информисани о напретку.
Добро, видели сте неке препоруке и поређења до сада о разликама између класичног стриминга и стриминга у MCP-у. Хајде да детаљније погледамо како можете искористити стриминг у MCP-у.
Разумевање како стриминг функционише у оквиру MCP-а је кључно за изградњу одзивних апликација које пружају реално-временске повратне информације корисницима током дуготрајних операција.
У MCP-у, стриминг није слање главног одговора у деловима, већ слање нотификација клијенту док алат обрађује захтев. Ове нотификације могу укључивати ажурирања напретка, логове или друге догађаје.
Главни резултат се и даље шаље као један одговор. Међутим, нотификације се могу слати као посебне поруке током обраде и на тај начин ажурирати клијента у реалном времену. Клијент мора бити у стању да обрађује и приказује ове нотификације.
Рекли смо "нотификација", шта то значи у контексту MCP-а?
Нотификација је порука послата са сервера ка клијенту која обавештава о напретку, статусу или другим догађајима током дуготрајне операције. Нотификације побољшавају транспарентност и корисничко искуство.
На пример, клијент треба да пошаље нотификацију када је успостављен почетни руковање (handshake) са сервером.
Нотификација изгледа овако као JSON порука:
{
jsonrpc: "2.0";
method: string;
params?: {
[key: string]: unknown;
};
}Нотификације припадају теми у MCP-у која се назива "Logging".
Да би логовање радило, сервер мора да га омогући као функцију/могућност овако:
{
"capabilities": {
"logging": {}
}
}Note
У зависности од коришћеног SDK-а, логовање може бити подразумевано омогућено или ћете морати експлицитно да га укључите у конфигурацији сервера.
Постоје различити типови нотификација:
| Ниво | Опис | Пример употребе |
|---|---|---|
| debug | Детаљне информације за дебаг | Улази/излази из функција |
| info | Опште информативне поруке | Ажурирања напретка операције |
| notice | Нормални али значајни догађаји | Промене конфигурације |
| warning | Упозорења | Коришћење застареле функције |
| error | Грешке | Неуспеси операција |
| critical | Критични услови | Кварови системских компоненти |
| alert | Одмах је потребна акција | Откривена корупција података |
| emergency | Систем је неисправан | Потпуни квар система |
Да бисте имплементирали нотификације у MCP-у, потребно је да подесите и серверску и клијентску страну да обрађују реално-временска ажурирања. Ово омогућава вашој апликацији да пружи тренутне повратне информације корисницима током дуготрајних операција.
Почнимо са серверском страном. У MCP-у дефинишете алате који могу слати нотификације током обраде захтева. Сервер користи контекст објекат (обично ctx) за слање порука клијенту.
@mcp.tool(description="A tool that sends progress notifications")
async def process_files(message: str, ctx: Context) -> TextContent:
await ctx.info("Processing file 1/3...")
await ctx.info("Processing file 2/3...")
await ctx.info("Processing file 3/3...")
return TextContent(type="text", text=f"Done: {message}")У претходном примеру, алат process_files шаље три нотификације клијенту док обрађује сваки фајл. Метод ctx.info() се користи за слање информативних порука.
Поред тога, да бисте омогућили нотификације, уверите се да ваш сервер користи стриминг транспорт (нпр. streamable-http) и да ваш клијент имплементира обраду порука за нотификације. Ево како да подесите сервер да користи streamable-http транспорт:
mcp.run(transport="streamable-http")[Tool("A tool that sends progress notifications")]
public async Task<TextContent> ProcessFiles(string message, ToolContext ctx)
{
await ctx.Info("Processing file 1/3...");
await ctx.Info("Processing file 2/3...");
await ctx.Info("Processing file 3/3...");
return new TextContent
{
Type = "text",
Text = $"Done: {message}"
};
}У овом .NET примеру, алат ProcessFiles је означен атрибутом Tool и шаље три нотификације клијенту док обрађује сваки фајл. Метод ctx.Info() се користи за слање информативних порука.
Да бисте омогућили нотификације у вашем .NET MCP серверу, уверите се да користите стриминг транспорт:
var builder = McpBuilder.Create();
await builder
.UseStreamableHttp() // Enable streamable HTTP transport
.Build()
.RunAsync();Клијент мора имплементирати обраду порука која ће примати и приказивати нотификације како стижу.
async def message_handler(message):
if isinstance(message, types.ServerNotification):
print("NOTIFICATION:", message)
else:
print("SERVER MESSAGE:", message)
async with ClientSession(
read_stream,
write_stream,
logging_callback=logging_collector,
message_handler=message_handler,
) as session:У претходном коду, функција message_handler проверава да ли је долазна порука нотификација. Ако јесте, исписује нотификацију; у супротном, обрађује је као редовну серверску поруку. Такође, обратите пажњу како је ClientSession иницијализован са message_handler за обраду долазних нотификација.
// Define a message handler
void MessageHandler(IJsonRpcMessage message)
{
if (message is ServerNotification notification)
{
Console.WriteLine($"NOTIFICATION: {notification}");
}
else
{
Console.WriteLine($"SERVER MESSAGE: {message}");
}
}
// Create and use a client session with the message handler
var clientOptions = new ClientSessionOptions
{
MessageHandler = MessageHandler,
LoggingCallback = (level, message) => Console.WriteLine($"[{level}] {message}")
};
using var client = new ClientSession(readStream, writeStream, clientOptions);
await client.InitializeAsync();
// Now the client will process notifications through the MessageHandlerУ овом .NET примеру, функција MessageHandler проверава да ли је долазна порука нотификација. Ако јесте, исписује нотификацију; у супротном, обрађује је као редовну серверску поруку. ClientSession је иницијализован са обрадом порука преко ClientSessionOptions.
Да бисте омогућили нотификације, уверите се да ваш сервер користи стриминг транспорт (нпр. streamable-http) и да ваш клијент имплементира обраду порука за нотификације.
Овај одељак објашњава концепт нотификација напретка у MCP-у, зашто су важне и како их имплементирати користећи Streamable HTTP. Такође ћете пронаћи практичну вежбу за јачање разумевања.
Нотификације напретка су реално-временске поруке послате са сервера ка клијенту током дуготрајних операција. Уместо да се чека да цео процес заврши, сервер стално обавештава клијента о тренутном статусу. Ово побољшава транспарентност, корисничко искуство и олакшава отклањање грешака.
Пример:
"Processing document 1/10"
"Processing document 2/10"
...
"Processing complete!"
Нотификације напретка су важне из више разлога:
- Боље корисничко искуство: Корисници виде ажурирања како рад напредује, а не само на крају.
- Реално-временска повратна информација: Клијенти могу приказивати траке напретка или логове, што апликацији даје осећај одзивности.
- Лакше отклањање грешака и праћење: Програмери и корисници могу видети где процес може бити спор или заглављен.
Ево како можете имплем
Постоје два убедљива разлога за надоградњу са SSE на Streamable HTTP:
- Streamable HTTP нуди бољу скалабилност, компатибилност и богатију подршку за обавештења у односу на SSE.
- Препоручени је транспорт за нове MCP апликације.
Ево како можете мигрирати са SSE на Streamable HTTP у вашим MCP апликацијама:
- Ажурирајте серверски код да користи
transport="streamable-http"уmcp.run(). - Ажурирајте клијентски код да користи
streamablehttp_clientуместо SSE клијента. - Имплементирајте обраду порука у клијенту за обраду обавештења.
- Тестирајте компатибилност са постојећим алатима и радним токовима.
Препоручује се одржавање компатибилности са постојећим SSE клијентима током процеса миграције. Ево неких стратегија:
- Можете подржати и SSE и Streamable HTTP тако што ћете покретати оба транспорта на различитим крајњим тачкама.
- Постепено мигрирајте клијенте на нови транспорт.
Обавезно решите следеће изазове током миграције:
- Осигурати да су сви клијенти ажурирани
- Руковање разликама у испоруци обавештења
Безбедност треба да буде највиши приоритет при имплементацији било ког сервера, посебно када се користе HTTP базирани транспорти као што је Streamable HTTP у MCP-у.
При имплементацији MCP сервера са HTTP базираним транспортима, безбедност постаје кључна тема која захтева пажљиво разматрање више нападачких вектора и механизама заштите.
Безбедност је критична када се MCP сервери излажу преко HTTP-а. Streamable HTTP уводи нове површине за нападе и захтева пажљиву конфигурацију.
Ево неких кључних безбедносних напомена:
- Валидација Origin заглавља: Увек проверите
Originзаглавље како бисте спречили DNS rebinding нападе. - Локално повезивање: За локални развој, повежите сервере на
localhostда бисте избегли излагање јавном интернету. - Аутентификација: Имплементирајте аутентификацију (нпр. API кључеве, OAuth) за продукцијске инсталације.
- CORS: Конфигуришите политике Cross-Origin Resource Sharing (CORS) да ограничите приступ.
- HTTPS: Користите HTTPS у продукцији за шифровање саобраћаја.
Поред тога, ево неких најбољих пракси које треба пратити при имплементацији безбедности у вашем MCP стриминг серверу:
- Никада не верујте долазним захтевима без валидације.
- Логовање и праћење свих приступа и грешака.
- Редовно ажурирајте зависности како бисте закрпили безбедносне рањивости.
Суочићете се са неким изазовима при имплементацији безбедности у MCP стриминг серверима:
- Балансирање безбедности и лакоће развоја
- Осигурање компатибилности са различитим клијентским окружењима
Сценарио: Направите MCP сервер и клијента где сервер обрађује листу ставки (нпр. фајлове или документе) и шаље обавештење за сваку обрађену ставку. Клијент треба да приказује сваки долазни сигнал у реалном времену.
Кораци:
- Имплементирајте серверски алат који обрађује листу и шаље обавештења за сваку ставку.
- Имплементирајте клијента са обрадом порука који приказује обавештења у реалном времену.
- Тестирајте имплементацију покретањем и сервера и клијента и пратите обавештења.
Да бисте наставили своје путовање са MCP стримингом и проширили знање, овај одељак пружа додатне ресурсе и предлоге за следеће кораке у изградњи напреднијих апликација.
- Microsoft: Увод у HTTP стриминг
- Microsoft: Server-Sent Events (SSE)
- Microsoft: CORS у ASP.NET Core
- Python requests: Streaming Requests
- Покушајте да направите напредније MCP алате који користе стриминг за реално-временску аналитику, чет или колаборативно уређивање.
- Истражите интеграцију MCP стриминга са фронтенд фрејмворцима (React, Vue и сл.) за ажурирање корисничког интерфејса уживо.
- Следеће: Коришћење AI Toolkit-а за VSCode
Одрицање од одговорности:
Овај документ је преведен коришћењем AI услуге за превођење Co-op Translator. Иако се трудимо да превод буде тачан, молимо вас да имате у виду да аутоматски преводи могу садржати грешке или нетачности. Оригинални документ на његовом изворном језику треба сматрати ауторитетним извором. За критичне информације препоручује се професионални људски превод. Нисмо одговорни за било каква неспоразума или погрешна тумачења која произилазе из коришћења овог превода.