diff --git "a/2025/mcp-dev-summit-oct/presentation.html" "b/2025/mcp-dev-summit-oct/presentation.html" new file mode 100644--- /dev/null +++ "b/2025/mcp-dev-summit-oct/presentation.html" @@ -0,0 +1,574 @@ +Shaun Smith `@evalstate`
+
github.com/evalstate
+
Streams, Sessions, Stats: Transport and Client Behaviour
+
MCP Dev Summit, London
+
Shaun Smith
+
October 2025
+ + + + + + + + + + + + + + + + +
+
+
github.com/evalstate
+
+
+

Shaun Smith @evalstate

+
    +
  • +

    @ Hugging Face MCP

    +
  • +
  • +

    MCP Maintainer / Transports WG

    +
  • +
  • +

    Transports WG

    +
  • +
  • +

    Maintainer of fast-agent

    +
  • +
+
+
+


+

+
+
+
+
+
github.com/evalstate
+

Hugging Face MCP Server: Huge Traffic Drop!

+

+
+
+
github.com/evalstate
+

Request/Response Streamable HTTP MCP Server

+ +

+
+
+

If all you need are Tools, Prompts, Resources (and Completions) this is enough!

+

Client POST's its Request to the MCP Server - which returns a JSON-RPC response.

+

Normal HTTP!

+
+
+
+

+
+
new StreamableHTTPServerTransport(){
+    // Note: Not Default!
+    enableJSONResponse: true
+}
+
+
+
+
+
+
github.com/evalstate
+

Adding Tool Progress Notifications

+
+
+

Longer running Tools (like Image Generation) can send Progress Notifications.

+

MCP Server responds to the POST Request with an SSE Stream.

+

Server Streams notifications to Client, then the Response, and closes.

+
+

MCP Server developer should make sure Notifications are sent on the correct channel.

+
+
+
+
+

+
+
async (request, extra) => {
+  await server.notification({
+    method: "notifications/statusUpdate",
+    params: { /* your params */ }
+  }, { relatedRequestId: extra.requestId });
+};
+
+
+
await session.send_progress_notification(
+    progress_token="token-789",
+    progress=50,
+    related_request_id="tool-call-456"  
+)
+
+
+
+
+
+
github.com/evalstate
+

Server Elicitation Request related to Tool Call

+
+
+

MCP can be bi-directional: Servers can make Sampling and Elicitation requests to the Client.

+

Server sends its Elicitation Request via the Tool's Response SSE stream.

+

Elicitation Result is POSTed to the MCP Server with it's Request-ID for association - and returns a 202.

+

Server then returns the Tool Result via the original Post SSE stream.

+
+
+

+

Note that the Elicitation Request should complete before the SSE Connection times out!

+
+

This applies to any associated Request / Response method, but Tool and Elicitation chosen to keep example simple.

+
+
+
+
+
+
github.com/evalstate
+

Server Request to Client (Server Initiated)

+

Server Initiated communications happen over a GET SSE Stream. This includes Resource Subscriptions,List Change Notifications or Server-Initiated Sampling/Elicitation.

+
+
+

+
+
+
+
+
github.com/evalstate
+

Ping!

+
+
+

The Host can POST a Ping to the Server to tell it's alive.
+The Server can Ping the Host via the GET SSE Channel (if open).

+

+
+
+
+

+
+
+
+
+
+
github.com/evalstate
+ +

REFERENCE: Capabilities Matrix

+ + + + + + + + + + + + + + + + + + + + + + + + + +
POST/JSON
POST/SSE
POST/SSE
+Response
POST/SSE
GET/SSE
+Response
+
+
+
github.com/evalstate
+

Using Mcp-Session-Id

+
+ +
+

Sessions are controlled by the MCP Server, not the Host - and are embedded within the Streamable HTTP Transport.

+

Knowledge about the User is usually handled with OAuth Identity or API key (e.g. ZeroGPU Quota, Selected Spaces).

+
+
+
github.com/evalstate
+

Mcp-Session-Id for Conversational State?

+
+
+

The Mcp-Session-Id is NOT a Chat ID.

+
+

VSCode uses one Transport Session per Chat

+
+
+
+

Desirable or undesirable this behaviour should be intentional.

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Server StateChat 1: "Production Issue"Chat 2: "Testing Cleanup"
DB: staging"Show me the test data"
DB: staging"I need to check production"
DB: staging"Switch to production database"
DB: production"What are the recent orders?"
DB: production"Delete those old records"
DB: production💥 Deletes production data!
+
+
+
github.com/evalstate
+

Mcp-Session-Id for Routing

+
+
+

alt text

+
+
+

With Multiple MCP Server instances, Client to Server Responses needs to go the correct Server.

+

Mcp-Session-Id HTTP Header can be used for Routing to the correct Server (sticky sessions).

+

Sharing Mcp-Session-Id state amongst the cluster is not enough: Both Mcp-Session-Id and Elicitation RequestId are needed for correlation.

+
+
+
+
+
github.com/evalstate
+

Hugging Face MCP Server: Huge Traffic Drop!

+

+
+

+
+
+
+
github.com/evalstate
+

Tool Call : MCP Method Ratio (Hugging Face MCP Server)

+
+
+ + + + + + + + + + + + + + + +
MCP MethodAugSep
initialize1.0001.000
tools/list0.4001.175
notifications/initialized0.9950.982
prompts/list1.0810.685
resources/list1.0390.606
notifications/cancelled0.0630.150
Actual Tool/Prompt Calls0.0110.032
ping0.0010.027
resources/templates/list0.0000.022
+
+
+

Initialization sequence is usually at least 3 calls.

+

MCP has significant overhead. For September:

+
    +
  • We see ~3 Tool/Prompt Calls per 100 Initialize events.
  • +
  • and ~165 MCP Method Calls for every Tool/Prompt Call.
  • +
  • compared to 547 in August!
  • +
+

The resource methods aren't supported, yet clients still request them.

+

JSON-RPC content stops standard HTTP Cache mechanisms.

+
+
+
+
+
github.com/evalstate
+

Initialize != Usage

+
+
+

Interactive Hosts (IDE/UI)

+

Sessions may remain open for minutes/hours.

+

Tool/Prompt Usage is User driven so idle sessions are normal.

+

VSCode has a high "efficiency ratio"

+

Examples are claude-ai, windsurf-client and mcp-inspector.

+
+
+

Gateways / Embedded Hosts

+

MCP Server is used as part of an automation, from a "Remote" Host or a gateway.

+

Burst of activity to Initialize and Call Tool that typically lasts under 5 seconds.

+

Examples are openai-mcp, docker-mcp-gateway, and javelin-mcp-client.

+
+
+
+
+
github.com/evalstate
+

Client Top 20 (by Usage) with Capabilities / Approx ~1.5m Sessions Sep '25

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#ClientIcons#ClientIcons
1claude-ai
RSE
11docker-mcp-gateway
DeleteRSE
2lmstudio-mcp-bridge
RSE
12groq-mcp-client
RSE
3Visual Studio Code
RSE
13openai-mcp
DeleteRSE
4test-client
AlertRSE
14Cherry Studio
RSE
5cursor-vscode
AlertRSE
15fast-agent-mcp
DeleteRSE
6claude-code
RSE
16codex (via mcp-remote)
RSE
7mcp (via mcp-remote)
RSE
17claude-ai (via mcp-remote)
RSE
8Anthropic/ClaudeAI
RSE
18@n8n/langchain.mcpClientT
AlertRSE
9mcp
DeleteRSE
19lobehub-mcp-client
RSE
10Manus
DeleteRSE
20dev.warp.Warp-Stable
RSE
+
+
+ R + Roots +
+
+ S + Sampling +
+
+ E + Elicitation +
+
+ Delete + Session Deletion +
+
+ Alert + Invalid Capabilities +
+
+
+
+
github.com/evalstate
+ +

MCP Client Primitives

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IconFeatureUsage
RootsRoots7.1% of all sessions, 33.6% of sessions that use tools
Not currently useful for Remote Servers
SamplingSampling0.9% of all sessions, 22.2% of sessions that use tools
ElicitationsElicitations3.2% of all sessions, 21.6% of sessions that use tools
Session DeletionSession Deletion4 of the top 20 clients delete sessions, only 6.64% of sessions get deleted overall
+
+
+
github.com/evalstate
+

Thoughts and Guidance

+
    +
  • + +
  • +
  • +

    SDK DevEx differs between Transports and Capability usage - consider deployment options carefully and be intentional. Don't forget to Use extra/related-request-id and configure JSON-RPC mode. fast-agent can help with diagnosis and debugging.

    +
  • +
  • + +
  • +
  • +

    Consider whether Server -> Client features are necessary for your use-case - especially in an uncontrolled environment. If they are, harder!

    +
  • +
  • +

    Don't rely on Clients managing sessions - for now consider what you want to use Mcp-Session-Id for.

    +
  • +
+
+
+
github.com/evalstate
+

Some pain points

+
    +
  • +

    GET Handler: For Interactive Hosts it's expensive (especially for speculative Tool Change Notifications). For Transactional Hosts it's unnecessary. Can be used for SSE Failure resumption - hard in practice. Management in elastic environments tricky.

    +
  • +
  • +

    MCP Protocol Overhead - JSON-RPC Packaging requires inspection for Processing and Return - prohibiting standard HTTP Caching. Protocol is "Chatty" in practice.

    +
  • +
  • +

    Sessions are coupled to the Transport implementation and State. Deploying in a Cluster means Sticky Sessions. Server Initiated Requests must be identified by both Mcp-Session-Id + JSON-RPC-RequestId

    +
  • +
  • +

    Timeout Handling - Progress Notifications resetting HTTP timeouts for example is not consistent Client behaviour.

    +
  • +
+
+
+
github.com/evalstate
+

Transport WG / Relevant SEPs

+
    +
  • +

    Handle inconsistencies between transports

    +
  • +
  • +

    Separate JSON-RPC layer from Protocol Data Layer.

    +
  • +
  • +

    SEP #1442 - Make MCP Stateless by Default: Move State captured in Initialize to Request/Response cycle.

    +
  • +
  • +

    Pure HTTP Transport - https://github.com/mikekistler/pure-http-transport

    +
  • +
+
+
+
github.com/evalstate
+ +

Thanks to the Transport Working Group

+ +
    +
  1. Everything Server PR 1: https://github.com/modelcontextprotocol/servers/pull/2789
  2. +
  3. Everything Server PR 2: https://github.com/modelcontextprotocol/servers/pull/2672
  4. +
  5. Hugging Face MCP Server: https://huggingface.co/mcp
  6. +
  7. MCP community Working Groups https://modelcontextprotocol-community.github.io/working-groups/
  8. +
+
+
+
github.com/evalstate
+
+

educational, bit of data, what next

Stateless JSON-RPC. All we can do is respond. Fine! + +If you don't need state. MCP SDK can still do some of the lifting for you.

when i was here last time, i said the great thing about MCP was it just worked

we have lots of options for Streamable HTTP and not much time, so we'll build up

<div class="bottom-image"> + <img src="./images/capabilities_stateless_1.png" alt="MCP Capabilities - Stateless" /> +</div>

> +<div class="bottom-image"> + <img src="./images/capabilities_stateless_1.png" alt="MCP Capabilities - Stateless" /> +</div>

![w:300](./images/session_per_chat.png)

Usage Guide: +- Session deletion icon: <span class="icon-delete"><img src="./images/trash-2.svg" alt="Delete" /></span> +- Alert/warning icon: <span class="icon-alert"><img src="./images/circle-alert.svg" alt="Alert" /></span> +- Enabled capability: <span class="capability-icon"><img src="./images/[icon].svg" /></span> +- Disabled capability: <span class="capability-icon disabled"><img src="./images/[icon].svg" /></span> + - folders.svg = Roots + - cpu.svg = Sampling + - message-circle-question-mark.svg = Elicitation +- Icons are placed in the <div class="client-icons"> container +- Enabled capabilities: bold blue color with light blue background +- Disabled capabilities: subtle gray with minimal background +- Delete/Alert icons: red color with light red background

\ No newline at end of file