项目文件夹

文件
2026-07-13 13:31:35 +08:00

26 KiB

Streaming HTTPS com Model Context Protocol (MCP)

Este capítulo fornece um guia abrangente para implementar streaming seguro, escalável e em tempo real com o Model Context Protocol (MCP) usando HTTPS. Ele cobre a motivação para streaming, os mecanismos de transporte disponíveis, como implementar HTTP transmissível no MCP, melhores práticas de segurança, migração de SSE e orientações práticas para construir suas próprias aplicações de streaming MCP.

Mecanismos de Transporte e Streaming no MCP

Esta seção explora os diferentes mecanismos de transporte disponíveis no MCP e seu papel em possibilitar capacidades de streaming para comunicação em tempo real entre clientes e servidores.

O que é um Mecanismo de Transporte?

Um mecanismo de transporte define como os dados são trocados entre o cliente e o servidor. O MCP suporta múltiplos tipos de transporte para atender diferentes ambientes e requisitos:

  • stdio: Entrada/saída padrão, adequado para ferramentas locais e baseadas em CLI. Simples, mas não adequado para web ou nuvem.
  • SSE (Server-Sent Events): Permite que servidores enviem atualizações em tempo real para clientes via HTTP. Bom para interfaces web, mas limitado em escalabilidade e flexibilidade. A partir da Especificação MCP 2025-06-18, o transporte SSE autônomo (Server-Sent Events) foi descontinuado e substituído pelo transporte "Streamable HTTP".
  • Streamable HTTP: Transporte de streaming moderno baseado em HTTP, suportando notificações e melhor escalabilidade. Recomendado para a maioria dos cenários em produção e na nuvem.

Tabela de Comparação

Confira a tabela de comparação abaixo para entender as diferenças entre esses mecanismos de transporte:

Transporte Atualizações em Tempo Real Streaming Escalabilidade Caso de Uso
stdio Não Não Baixa Ferramentas CLI locais
SSE Sim Sim Média Web, atualizações em tempo real
Streamable HTTP Sim Sim Alta Nuvem, múltiplos clientes

Dica: Escolher o transporte correto impacta performance, escalabilidade e experiência do usuário. Streamable HTTP é recomendado para aplicações modernas, escaláveis e preparadas para nuvem.

Observe os transportes stdio e SSE que foram apresentados nos capítulos anteriores e como o streamable HTTP é o transporte abordado neste capítulo.

Streaming: Conceitos e Motivação

Entender os conceitos fundamentais e a motivação por trás do streaming é essencial para implementar sistemas de comunicação em tempo real eficazes.

Streaming é uma técnica em programação de rede que permite que dados sejam enviados e recebidos em pequenos pedaços gerenciáveis ou como uma sequência de eventos, ao invés de esperar que toda uma resposta esteja pronta. Isso é especialmente útil para:

  • Arquivos ou conjuntos de dados grandes.
  • Atualizações em tempo real (ex: chat, barras de progresso).
  • Computações de longa duração onde você quer manter o usuário informado.

Aqui está o que você precisa saber sobre streaming em alto nível:

  • Os dados são entregues progressivamente, não de uma só vez.
  • O cliente pode processar os dados conforme eles chegam.
  • Reduz a latência percebida e melhora a experiência do usuário.

Por que usar streaming?

As razões para usar streaming são as seguintes:

  • Os usuários recebem feedback imediatamente, não só ao final.
  • Habilita aplicações em tempo real e interfaces responsivas.
  • Uso mais eficiente dos recursos de rede e computação.

Exemplo Simples: Servidor & Cliente de Streaming HTTP

Aqui está um exemplo simples de como o streaming pode ser implementado:

Python

Servidor (Python, usando FastAPI e 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")

Cliente (Python, usando 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())

Este exemplo demonstra um servidor enviando uma série de mensagens ao cliente conforme elas ficam disponíveis, ao invés de esperar que todas as mensagens estejam prontas.

Como funciona:

  • O servidor produz cada mensagem assim que ela está pronta.
  • O cliente recebe e imprime cada pedaço conforme chega.

Requisitos:

  • O servidor deve usar uma resposta de streaming (ex: StreamingResponse no FastAPI).
  • O cliente deve processar a resposta como um stream (stream=True no requests).
  • O Content-Type é geralmente text/event-stream ou application/octet-stream.

Java

Servidor (Java, usando Spring Boot e 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));
    }
}

Cliente (Java, usando 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();
    }
}

Notas de Implementação Java:

  • Usa a stack reativa do Spring Boot com Flux para streaming.
  • ServerSentEvent fornece streaming de eventos estruturados com tipos de evento.
  • WebClient com bodyToFlux() permite consumo reativo do streaming.
  • delayElements() simula tempo de processamento entre eventos.
  • Eventos podem ter tipos (info, result) para melhor tratamento no cliente.

Comparação: Streaming Clássico vs Streaming MCP

As diferenças entre como o streaming funciona de maneira "clássica" versus como funciona no MCP podem ser ilustradas assim:

Característica Streaming HTTP Clássico Streaming MCP (Notificações)
Resposta principal Em pedaços (chunked) Única, ao final
Atualizações de progresso Enviadas como pedaços de dados Enviadas como notificações
Requisitos do cliente Deve processar o stream Deve implementar um handler de mensagens
Caso de uso Arquivos grandes, streams de tokens AI Progresso, logs, feedback em tempo real

Diferenças Chave Observadas

Além disso, aqui estão algumas diferenças chaves:

  • Padrão de Comunicação:

    • Streaming HTTP clássico: usa codificação de transferência chunked simples para enviar dados em pedaços.
    • Streaming MCP: usa um sistema estruturado de notificações com protocolo JSON-RPC.
  • Formato da Mensagem:

    • HTTP clássico: pedaços de texto simples com quebras de linha.
    • MCP: objetos estruturados LoggingMessageNotification com metadados.
  • Implementação do Cliente:

    • HTTP clássico: cliente simples que processa respostas de streaming.
    • MCP: cliente mais sofisticado com handler de mensagens para processar diferentes tipos.
  • Atualizações de Progresso:

    • HTTP clássico: o progresso é parte do fluxo principal de resposta.
    • MCP: progresso é enviado via mensagens de notificação separadas enquanto a resposta principal vem ao final.

Recomendações

Algumas recomendações quanto à escolha entre implementar streaming clássico (como o endpoint que mostramos acima usando /stream) versus escolher streaming via MCP:

  • Para necessidades simples de streaming: Streaming HTTP clássico é mais simples de implementar e suficiente para necessidades básicas.

  • Para aplicações complexas e interativas: Streaming MCP oferece uma abordagem mais estruturada com metadados mais ricos e separação entre notificações e resultados finais.

  • Para aplicações AI: O sistema de notificações do MCP é particularmente útil para tarefas AI de longa duração onde você quer manter usuários informados sobre o progresso.

Streaming no MCP

Ok, você já viu algumas recomendações e comparações até aqui sobre a diferença entre streaming clássico e streaming no MCP. Vamos agora detalhar exatamente como você pode aproveitar o streaming no MCP.

Entender como o streaming funciona dentro do framework MCP é essencial para construir aplicações responsivas que forneçam feedback em tempo real para os usuários durante operações longas.

No MCP, streaming não é sobre enviar a resposta principal em pedaços, mas enviar notificações para o cliente enquanto uma ferramenta processa uma requisição. Essas notificações podem incluir atualizações de progresso, logs ou outros eventos.

Como funciona

O resultado principal ainda é enviado como uma única resposta. Entretanto, notificações podem ser enviadas como mensagens separadas durante o processamento e assim atualizar o cliente em tempo real. O cliente deve ser capaz de manipular e exibir essas notificações.

O que é uma Notificação?

Dissemos "Notificação", o que isso significa no contexto do MCP?

Uma notificação é uma mensagem enviada do servidor para o cliente para informar sobre progresso, status ou outros eventos durante uma operação longa. Notificações melhoram transparência e experiência do usuário.

Por exemplo, espera-se que o cliente envie uma notificação assim que o handshake inicial com o servidor for concluído.

Uma notificação tem a seguinte aparência em JSON:

{
  jsonrpc: "2.0";
  method: string;
  params?: {
    [key: string]: unknown;
  };
}

Notificações pertencem a um tópico no MCP referido como "Logging".

Para que o logging funcione, o servidor precisa habilitá-lo como uma funcionalidade/capacidade assim:

{
  "capabilities": {
    "logging": {}
  }
}

Note

Dependendo do SDK usado, o logging pode estar habilitado por padrão, ou você pode precisar ativá-lo explicitamente na configuração do seu servidor.

Existem diferentes tipos de notificações:

Nível Descrição Exemplo de Caso de Uso
debug Informações detalhadas de depuração Pontos de entrada/saída de funções
info Mensagens informativas gerais Atualizações de progresso de operação
notice Eventos normais mas significativos Mudanças de configuração
warning Condições de aviso Uso de funcionalidade obsoleta
error Condições de erro Falhas em operações
critical Condições críticas Falhas de componentes do sistema
alert Ação deve ser tomada imediatamente Detecção de corrupção de dados
emergency Sistema está inutilizável Falha completa do sistema

Implementando Notificações no MCP

Para implementar notificações no MCP, você precisa configurar tanto o lado do servidor quanto o do cliente para manipular atualizações em tempo real. Isso permite que sua aplicação forneça feedback imediato aos usuários durante operações longas.

Lado Servidor: Enviando Notificações

Vamos começar com o lado servidor. No MCP, você define ferramentas que podem enviar notificações enquanto processam requisições. O servidor usa o objeto de contexto (geralmente ctx) para enviar mensagens para o cliente.

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

No exemplo acima, a ferramenta process_files envia três notificações para o cliente conforme processa cada arquivo. O método ctx.info() é usado para enviar mensagens informativas.

Além disso, para habilitar notificações, certifique-se que seu servidor está usando um transporte de streaming (como streamable-http) e que seu cliente implementa um handler de mensagens para processar notificações. Veja como configurar o servidor para usar o transporte 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}"
    };
}

Neste exemplo .NET, a ferramenta ProcessFiles está decorada com o atributo Tool e envia três notificações para o cliente enquanto processa cada arquivo. O método ctx.Info() é usado para enviar mensagens informativas.

Para habilitar notificações no seu servidor MCP .NET, assegure-se de usar um transporte de streaming:

var builder = McpBuilder.Create();
await builder
    .UseStreamableHttp() // Enable streamable HTTP transport
    .Build()
    .RunAsync();

Lado Cliente: Recebendo Notificações

O cliente deve implementar um handler de mensagens para processar e exibir notificações à medida que chegam.

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:

No código acima, a função message_handler verifica se a mensagem entrante é uma notificação. Se for, ela imprime a notificação; caso contrário, processa como uma mensagem regular do servidor. Note também como o ClientSession é inicializado com o message_handler para lidar com notificações recebidas.

.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

Neste exemplo .NET, a função MessageHandler verifica se a mensagem entrante é uma notificação. Se for, ela imprime a notificação; caso contrário, processa como mensagem regular do servidor. O ClientSession é inicializado com o handler de mensagens via ClientSessionOptions.

Para habilitar notificações, assegure que seu servidor usa um transporte de streaming (como streamable-http) e seu cliente implementa um handler de mensagens para processar notificações.

Notificações de Progresso & Cenários

Esta seção explica o conceito de notificações de progresso no MCP, por que são importantes e como implementá-las usando Streamable HTTP. Você também encontrará um exercício prático para reforçar seu entendimento.

Notificações de progresso são mensagens em tempo real enviadas do servidor para o cliente durante operações longas. Ao invés de esperar o processo completo terminar, o servidor mantém o cliente atualizado sobre o status atual. Isso melhora transparência, experiência do usuário e facilita a depuração.

Exemplo:


"Processing document 1/10"
"Processing document 2/10"
...
"Processing complete!"

Por que usar notificações de progresso?

Notificações de progresso são essenciais por vários motivos:

  • Melhor experiência do usuário: Usuários veem atualizações conforme o trabalho progride, e não somente ao final.
  • Feedback em tempo real: Clientes podem mostrar barras de progresso ou logs, deixando o app mais responsivo.
  • Depuração e monitoramento mais fáceis: Desenvolvedores e usuários podem ver onde um processo está lento ou travado.

Como implementar notificações de progresso

Veja como implementar notificações de progresso no MCP:

  • No servidor: Use ctx.info() ou ctx.log() para enviar notificações à medida que cada item é processado. Isso envia uma mensagem ao cliente antes do resultado principal estar pronto.
  • No cliente: Implemente um handler de mensagens que escute e exiba notificações conforme elas chegam. Esse handler distingue entre notificações e resultado final.

Exemplo Servidor:

Python

@mcp.tool(description="A tool that sends progress notifications")
async def process_files(message: str, ctx: Context) -> TextContent:
    for i in range(1, 11):
        await ctx.info(f"Processing document {i}/10")
    await ctx.info("Processing complete!")
    return TextContent(type="text", text=f"Done: {message}")

Exemplo Cliente:

Python

async def message_handler(message):
    if isinstance(message, types.ServerNotification):
        print("NOTIFICATION:", message)
    else:
        print("SERVER MESSAGE:", message)

Considerações de Segurança

Ao implementar servidores MCP com transportes baseados em HTTP, a segurança torna-se uma preocupação primordial que requer atenção cuidadosa a múltiplos vetores de ataque e mecanismos de proteção.

Visão Geral

A segurança é crítica ao expor servidores MCP via HTTP. Streamable HTTP introduz novas superfícies de ataque e requer configuração cuidadosa.

Pontos-Chave

  • Validação do Cabeçalho Origin: Sempre valide o cabeçalho Origin para prevenir ataques de DNS rebinding.
  • Vinculação a Localhost: Para desenvolvimento local, vincule servidores a localhost para evitar exposição à internet pública.
  • Autenticação: Implemente autenticação (ex: chaves API, OAuth) para ambientes de produção.
  • CORS: Configure políticas de Cross-Origin Resource Sharing para restringir acesso.
  • HTTPS: Utilize HTTPS em produção para criptografar o tráfego.

Melhores Práticas

  • Nunca confie em requisições recebidas sem validação.
  • Registre e monitore todos acessos e erros.
  • Atualize dependências regularmente para corrigir vulnerabilidades de segurança.

Desafios

  • Equilibrando segurança com facilidade de desenvolvimento
  • Garantindo compatibilidade com vários ambientes de cliente

Atualizando de SSE para Streamable HTTP

Para aplicações que atualmente usam Server-Sent Events (SSE), migrar para Streamable HTTP oferece capacidades aprimoradas e melhor sustentabilidade a longo prazo para suas implementações MCP.

Por que atualizar?

Há duas razões convincentes para atualizar de SSE para Streamable HTTP:

  • Streamable HTTP oferece melhor escalabilidade, compatibilidade e suporte a notificações mais ricos do que SSE.
  • É o transporte recomendado para novas aplicações MCP.

Passos para migração

Aqui está como você pode migrar de SSE para Streamable HTTP em suas aplicações MCP:

  • Atualize o código do servidor para usar transport="streamable-http" em mcp.run().
  • Atualize o código do cliente para usar streamablehttp_client em vez do cliente SSE.
  • Implemente um handler de mensagens no cliente para processar notificações.
  • Teste a compatibilidade com ferramentas e fluxos de trabalho existentes.

Mantendo compatibilidade

É recomendado manter compatibilidade com clientes SSE existentes durante o processo de migração. Aqui estão algumas estratégias:

  • Você pode suportar ambos SSE e Streamable HTTP executando ambos os transportes em endpoints diferentes.
  • Migre os clientes gradualmente para o novo transporte.

Desafios

Certifique-se de tratar os seguintes desafios durante a migração:

  • Garantir que todos os clientes sejam atualizados
  • Lidar com diferenças na entrega das notificações

Considerações de segurança

A segurança deve ser prioridade máxima ao implementar qualquer servidor, especialmente ao usar transportes baseados em HTTP como Streamable HTTP no MCP.

Ao implementar servidores MCP com transportes baseados em HTTP, a segurança torna-se uma preocupação primordial que exige atenção cuidadosa a múltiplos vetores de ataque e mecanismos de proteção.

Visão geral

A segurança é crítica quando expõe servidores MCP via HTTP. Streamable HTTP introduz novas superfícies de ataque e requer configuração cuidadosa.

Aqui estão algumas considerações-chave de segurança:

  • Validação do cabeçalho Origin: Sempre valide o cabeçalho Origin para evitar ataques de DNS rebinding.
  • Binding localhost: Para desenvolvimento local, faça o binding dos servidores ao localhost para evitar exposição à internet pública.
  • Autenticação: Implemente autenticação (ex.: chaves API, OAuth) para implantações em produção.
  • CORS: Configure políticas de Cross-Origin Resource Sharing (CORS) para restringir acesso.
  • HTTPS: Use HTTPS em produção para criptografar o tráfego.

Melhores práticas

Além disso, aqui estão algumas melhores práticas para seguir ao implementar segurança no seu servidor de streaming MCP:

  • Nunca confie em requisições recebidas sem validação.
  • Registre e monitore todos os acessos e erros.
  • Atualize as dependências regularmente para corrigir vulnerabilidades de segurança.

Desafios

Você enfrentará alguns desafios ao implementar segurança em servidores de streaming MCP:

  • Equilibrar segurança com facilidade de desenvolvimento
  • Garantir compatibilidade com vários ambientes de cliente

Exercício: Crie sua própria aplicação MCP de streaming

Cenário: Construa um servidor e cliente MCP onde o servidor processa uma lista de itens (ex.: arquivos ou documentos) e envia uma notificação para cada item processado. O cliente deve exibir cada notificação assim que ela chegar.

Passos:

  1. Implemente uma ferramenta de servidor que processe uma lista e envie notificações para cada item.
  2. Implemente um cliente com um handler de mensagens para exibir notificações em tempo real.
  3. Teste sua implementação executando ambos servidor e cliente, e observe as notificações.

Solução

Leitura adicional e próximos passos

Para continuar sua jornada com streaming MCP e expandir seu conhecimento, esta seção fornece recursos adicionais e passos sugeridos para construir aplicações mais avançadas.

Leitura adicional

Próximos passos

  • Experimente construir ferramentas MCP mais avançadas que usem streaming para análises em tempo real, chat ou edição colaborativa.
  • Explore integrar streaming MCP com frameworks frontend (React, Vue, etc.) para atualizações ao vivo da UI.
  • Próximo: Utilising AI Toolkit for VSCode

Aviso Legal: Este documento foi traduzido usando o serviço de tradução por IA Co-op Translator. Embora nos esforcemos pela precisão, por favor, esteja ciente de que traduções automatizadas podem conter erros ou imprecisões. O documento original em seu idioma nativo deve ser considerado a fonte autorizada. Para informações críticas, recomenda-se tradução profissional humana. Não nos responsabilizamos por quaisquer mal-entendidos ou interpretações incorretas decorrentes do uso desta tradução.