Skip to content

Latest commit

 

History

History
524 lines (368 loc) · 33.1 KB

File metadata and controls

524 lines (368 loc) · 33.1 KB

HTTPS стриминг са Model Context Protocol (MCP)

Ово поглавље пружа свеобухватан водич за имплементацију безбедног, скалабилног и реално-временског стриминга уз коришћење Model Context Protocol (MCP) преко HTTPS-а. Обухвата мотивацију за стриминг, доступне транспортне механизме, како имплементирати стриминг HTTP у MCP-у, најбоље безбедносне праксе, миграцију са SSE-а и практичне смернице за изградњу сопствених стриминг MCP апликација.

Транспортни механизми и стриминг у 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 транспорт који се обрађује у овом поглављу.

Стриминг: Концепти и мотивација

Разумевање основних концепата и мотивације иза стриминга је кључно за имплементацију ефикасних система за реално-временску комуникацију.

Стриминг је техника у мрежном програмирању која омогућава слање и пријем података у малим, управљивим деловима или као низ догађаја, уместо да се чека да цео одговор буде спреман. Ово је посебно корисно за:

  • Велике фајлове или скупове података.
  • Реално-временска ажурирања (нпр. чет, траке напретка).
  • Дуго трајајуће прорачуне где желите да корисник буде информисан.

Ево шта треба да знате о стримингу на високом нивоу:

  • Подаци се испоручују постепено, не одједном.
  • Клијент може обрађивати податке како стижу.
  • Смањује перципирану латенцију и побољшава корисничко искуство.

Зашто користити стриминг?

Разлози за коришћење стриминга су следећи:

  • Корисници добијају повратну информацију одмах, а не само на крају
  • Омогућава реално-временске апликације и одзивне интерфејсе
  • Ефикаснија употреба мрежних и рачунарских ресурса

Једноставан пример: HTTP стриминг сервер и клијент

Ево једноставног примера како се стриминг може имплементирати:

Python

Сервер (Python, користећи FastAPI и StreamingResponse):

Python

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):

Python

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

Сервер (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) за бољу обраду на клијенту

Поређење: Класични стриминг vs MCP стриминг

Разлике између класичног начина стриминга и начина на који 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-у, стриминг није слање главног одговора у деловима, већ слање нотификација клијенту док алат обрађује захтев. Ове нотификације могу укључивати ажурирања напретка, логове или друге догађаје.

Како функционише

Главни резултат се и даље шаље као један одговор. Међутим, нотификације се могу слати као посебне поруке током обраде и на тај начин ажурирати клијента у реалном времену. Клијент мора бити у стању да обрађује и приказује ове нотификације.

Шта је нотификација?

Рекли смо "нотификација", шта то значи у контексту 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-у, потребно је да подесите и серверску и клијентску страну да обрађују реално-временска ажурирања. Ово омогућава вашој апликацији да пружи тренутне повратне информације корисницима током дуготрајних операција.

Серверска страна: Слање нотификација

Почнимо са серверском страном. У MCP-у дефинишете алате који могу слати нотификације током обраде захтева. Сервер користи контекст објекат (обично ctx) за слање порука клијенту.

Python

@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")

.NET

[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();

Клијентска страна: Примање нотификација

Клијент мора имплементирати обраду порука која ће примати и приказивати нотификације како стижу.

Python

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 за обраду долазних нотификација.

.NET

// 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 сервер и клијента где сервер обрађује листу ставки (нпр. фајлове или документе) и шаље обавештење за сваку обрађену ставку. Клијент треба да приказује сваки долазни сигнал у реалном времену.

Кораци:

  1. Имплементирајте серверски алат који обрађује листу и шаље обавештења за сваку ставку.
  2. Имплементирајте клијента са обрадом порука који приказује обавештења у реалном времену.
  3. Тестирајте имплементацију покретањем и сервера и клијента и пратите обавештења.

Solution

Додатно читање и шта даље?

Да бисте наставили своје путовање са MCP стримингом и проширили знање, овај одељак пружа додатне ресурсе и предлоге за следеће кораке у изградњи напреднијих апликација.

Додатно читање

Шта даље?

  • Покушајте да направите напредније MCP алате који користе стриминг за реално-временску аналитику, чет или колаборативно уређивање.
  • Истражите интеграцију MCP стриминга са фронтенд фрејмворцима (React, Vue и сл.) за ажурирање корисничког интерфејса уживо.
  • Следеће: Коришћење AI Toolkit-а за VSCode

Одрицање од одговорности:
Овај документ је преведен коришћењем AI услуге за превођење Co-op Translator. Иако се трудимо да превод буде тачан, молимо вас да имате у виду да аутоматски преводи могу садржати грешке или нетачности. Оригинални документ на његовом изворном језику треба сматрати ауторитетним извором. За критичне информације препоручује се професионални људски превод. Нисмо одговорни за било каква неспоразума или погрешна тумачења која произилазе из коришћења овог превода.