Learning objectives
By the end of this lesson you will be able to:- Explain the difference between classic HTTP streaming and MCP streaming notifications
- Implement a server that sends progress notifications using Streamable HTTP
- Write a client that handles incoming notifications in real time
- Understand the security considerations for HTTP-based MCP servers
Transport comparison
| Transport | Real-time updates | Streaming | Scalability | Recommended for |
|---|---|---|---|---|
| stdio | No | No | Low | Local CLI tools |
| SSE (deprecated) | Yes | Yes | Medium | — |
| Streamable HTTP | Yes | Yes | High | Cloud, multi-client |
Classic streaming vs. MCP streaming
MCP streaming is not about chunked HTTP responses. Instead it uses a structured notification system:| Feature | Classic HTTP streaming | MCP streaming (notifications) |
|---|---|---|
| Main response | Chunked | Single, at end |
| Progress updates | Sent as data chunks | Sent as separate notifications |
| Client requirements | Process stream | Implement message handler |
| Message format | Plain text chunks | Structured JSON-RPC objects |
What is an MCP notification?
A notification is a JSON-RPC message the server sends to the client to report progress during a long-running operation:Notification levels
| Level | Description | Example use case |
|---|---|---|
debug | Detailed debugging info | Function entry/exit |
info | General progress | Operation progress updates |
notice | Normal but significant events | Configuration changes |
warning | Warning conditions | Deprecated feature usage |
error | Error conditions | Operation failures |
critical | Critical conditions | System component failures |
Implementing notifications
Server side: sending notifications
- Python
- .NET
Client side: receiving notifications
- Python
- .NET
A simple HTTP streaming example
To understand the mechanics before using MCP’s notification layer, here is a plain HTTP streaming server and client:Security considerations
When you expose an MCP server over HTTP, you must address the following:Origin header validation
Origin header validation
Always validate the
Origin header to prevent DNS rebinding attacks. Reject requests from unexpected origins.Localhost binding for development
Localhost binding for development
During local development, bind servers to
localhost (127.0.0.1) only. Never expose a development server on 0.0.0.0.Authentication for production
Authentication for production
Implement authentication for any publicly accessible server — API keys, OAuth 2.0, or JWT tokens. Never deploy an unauthenticated HTTP MCP server to the public internet.
CORS configuration
CORS configuration
Configure Cross-Origin Resource Sharing (CORS) policies to restrict which origins can connect to your server.
HTTPS in production
HTTPS in production
Use HTTPS to encrypt traffic. Consider a reverse proxy (nginx, Caddy) to handle TLS termination.
Migrating from SSE to Streamable HTTP
If you have an existing SSE-based server:- Update server code to use
transport="streamable-http"inmcp.run(). - Update client code to use
streamablehttp_clientinstead of the SSE client. - Implement a
message_handlerin the client to process notifications. - Test with existing tools and workflows.
- Optionally run both SSE and Streamable HTTP in parallel on different endpoints during the transition.
Assignment
Build an MCP server and client where the server processes a list of items (e.g., files or documents) and sends a progress notification for each item. The client should display each notification as it arrives. Steps:- Implement a server tool that processes a list and calls
ctx.info()for each item. - Run the server with
transport="streamable-http". - Write a client with a
message_handlerthat prints notifications. - Observe the real-time output.
Key takeaways
- Streamable HTTP is the recommended transport for remote MCP servers (MCP spec 2025-11-25).
- MCP streaming uses a notification system — the final result is still a single response, but progress is sent as separate messages.
- Always validate the
Originheader and use HTTPS in production deployments. - Migrating from the deprecated SSE transport to Streamable HTTP requires only minor changes to both server and client.