new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

MCP · Building servers and clients · all subjects

transports: http

82 notes in this subject, read out of this brain and free to use. This is page 1 of 2.

Spring AI supports STDIO and Streamable HTTP transports

The Spring AI MCP client supports multiple clients with multiple transport types: STDIO and Streamable HTTP. To connect to a remote MCP server over Streamable HTTP set `spring.ai.mcp.client.streamable-http.connections.server1.url=http://localhost:8080`. The WebFlux-based Streamable HTTP transport (`spring-ai-starter-mcp-client-webflux`) is recommended for production deployments.

Streamable HTTP scaffolds: Cloudflare Workers and Express/FastMCP

For remote Streamable HTTP servers, reference scaffolds exist for Cloudflare Workers and for portable Express (TypeScript) / FastMCP (Python) setups.

Remote MCP server URL must be a full https URL ending in the MCP path

When registering a remote MCP server in a client, you supply the complete URL including the https:// protocol and any path components. The canonical example server URL used in the official docs is https://example-server.modelcontextprotocol.io/mcp — note the /mcp path, which is the conventional endpoint path for the Streamable HTTP transport.

MCP-Protocol-Version header on Streamable HTTP

On the Streamable HTTP transport, the protocol version value is also carried in the `MCP-Protocol-Version` HTTP header, in addition to the `io.modelcontextprotocol/protocolVersion` key in the request's `_meta` field.

stderr is not captured under Streamable HTTP

For servers using the Streamable HTTP transport, the client does not capture stderr. Use your own server-side log aggregation or OpenTelemetry for logs, and standard HTTP tooling such as curl or the browser DevTools Network panel to inspect requests and SSE streams.

Inspector honors HTTPS_PROXY / HTTP_PROXY / NO_PROXY

Connections to remote HTTP/SSE servers honor the conventional proxy environment variables: `HTTPS_PROXY` / `HTTP_PROXY` (and lowercase forms) select the proxy and `NO_PROXY` exempts hosts. No Inspector-specific flag is needed, and the proxy agent is loaded lazily so runs without a proxy pay no cost. The same applies to the web client's backend.

Legacy sessions use Mcp-Session-Id and HTTP DELETE teardown

A legacy Streamable HTTP connection may carry a server-assigned session id in the `Mcp-Session-Id` header, which the client tears down with an HTTP `DELETE` request.

Modern HTTP connections are sessionless and per-request

A modern (2026-07-28) HTTP connection is sessionless and per-request: with no session id the client SDK sends no `DELETE` to the server, so disconnecting is purely local state cleanup.

401 from an HTTP MCP server triggers OAuth in the Inspector

No OAuth setup is needed in advance for a protected HTTP MCP server: when the server answers `401`, the Inspector runs the OAuth authorization flow and then retries the connection.

Inspector HTTP/SSE connection flags

Connect the Inspector to a remote MCP server with `mcp-inspector --server-url https://api.example.com/mcp --transport http --header "X-Tenant: acme"`. `--transport` accepts `http` (Streamable HTTP) and `sse`; `--header` adds custom request headers.

Inspect HTTP/SSE traffic in the TUI Network tab

The Inspector TUI's Network tab (key `n`) shows raw HTTP traffic for SSE and Streamable HTTP servers, while the Protocol tab (key `p`) shows JSON-RPC request, response and notification history — useful for diagnosing why a server behaves differently across clients.

Python: running a server on streamable-http at the root path

A Python MCP server is started with `mcp_server.run(transport='streamable-http', host=config.HOST, port=config.PORT, streamable_http_path='/')`. The `streamable_http_path` argument controls the URL path the MCP endpoint is mounted at; setting it to '/' serves MCP at the server root.

TypeScript Streamable HTTP session management pattern

A Streamable HTTP MCP server keeps a `transports: { [sessionId: string]: StreamableHTTPServerTransport }` map. On POST it reads the `mcp-session-id` header: if present and known it reuses the transport; if absent and `isInitializeRequest(req.body)` is true it creates `new StreamableHTTPServerTransport({ sessionIdGenerator: () => randomUUID(), onsessioninitialized: id => transports[id] = transport })`, sets `transport.onclose` to delete the entry, and connects a fresh McpServer; otherwise it returns HTTP 400 with JSON-RPC error code -32000 'Bad Request: No valid session ID provided'. GET and DELETE require an existing session id or respond 400 'Invalid or missing session ID'.

Serving an MCP App over Streamable HTTP with Express

Expose the MCP App server over HTTP by creating an Express app with `cors()` and `express.json()`, then handling `POST /mcp`: construct `new StreamableHTTPServerTransport({ sessionIdGenerator: undefined, enableJsonResponse: true })`, register `res.on("close", () => transport.close())`, `await server.connect(transport)`, and `await transport.handleRequest(req, res, req.body)`. The example listens on port 3001, giving endpoint `http://localhost:3001/mcp`.

Client credentials only apply to HTTP transports

The client-credentials flow is used with HTTP-based MCP connections: the access token is carried in the HTTP `Authorization: Bearer` header, and the SDK examples all use the Streamable HTTP transport (StreamableHTTPClientTransport in TypeScript, streamable_http_client in Python). It does not apply to stdio-based local servers.

Remote URL variable properties: default, choices, isSecret, isRequired

Each entry in a remote's `variables` map supports `description`, `isRequired`, `choices` (an array of allowed values), `default`, and `isSecret`. Example: url "https://api.example.com/{region}/mcp" with region having choices ["us-east-1", "eu-west-1", "ap-southeast-1"] and default "us-east-1".

URL template variables in remotes for multi-tenant endpoints

Remote entries can define URL template variables with `{curly_braces}` notation, e.g. "url": "https://{tenant_id}.analytics.example.com/mcp" plus a `variables` object mapping `tenant_id` to {"description": "...", "isRequired": true}. Users supply the value at configuration time and the client resolves the template (e.g. to https://us-cell1.analytics.example.com/mcp). This supports multi-tenant deployments from a single server definition.

server.json remotes property for remote MCP servers

The MCP Registry publishes remote MCP servers via the `remotes` array in `server.json`. Each entry has at minimum a `type` (either `"streamable-http"` or `"sse"`) and a `url`, e.g. {"type": "streamable-http", "url": "https://analytics.example.com/mcp"}. The file also carries `$schema` (https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json), `name` (reverse-DNS style like `com.example/acme-analytics`), `title`, `description`, and `version`.

Remote server must be publicly accessible at its URL

A remote MCP server published to the registry MUST be publicly accessible at the URL specified in its `remotes` entry.

Declaring required HTTP headers for a remote MCP server

A `remotes` entry can include a `headers` array telling MCP clients which HTTP headers to send. Each header object has `name` (e.g. "X-API-Key"), `description`, `isRequired`, and `isSecret`. This is how a remote server declares an API-key style authentication header that clients must populate.

HTTP-based servers may log to stdout

For HTTP-based MCP servers, logging to standard output is fine because it does not interfere with HTTP responses. The stdout prohibition only applies to stdio transport, where stdout carries JSON-RPC framing.

Spring AI HTTP/Streamable server property

The Spring AI `starter-webflux-server` example builds an HTTP-based MCP server with the WebFlux starter; set `spring.ai.mcp.server.protocol=STREAMABLE` to serve it over Streamable HTTP. It demonstrates defining and registering MCP Tools, Resources, and Prompts via Spring Boot auto-configuration.

Streamable HTTP GET stream server request restrictions

In Streamable HTTP standalone GET-initiated SSE streams, the server MAY send JSON-RPC notifications and pings on the stream. These messages SHOULD be unrelated to any concurrently-running JSON-RPC request from the client, EXCEPT that `roots/list`, `sampling/createMessage`, and `elicitation/create` requests MUST NOT be sent on standalone streams.

Streamable HTTP POST stream server request requirements

In Streamable HTTP, the server MAY send JSON-RPC requests and notifications before sending the JSON-RPC response. These messages MUST relate to the originating client request.

Streamable HTTP tools/call request example

Example tools/call request: POST /mcp HTTP/1.1 Content-Type: application/json MCP-Protocol-Version: 2026-07-28 Mcp-Method: tools/call Mcp-Name: get_weather { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "get_weather", "arguments": { "location": "Seattle, WA" }, "_meta": { "io.modelcontextprotocol/protocolVersion": "2026-07-28", "io.modelcontextprotocol/clientInfo": { "name": "ExampleClient", "version": "1.0.0" }, "io.modelcontextprotocol/clientCapabilities": {} } } }

Streamable HTTP resources/read request example

Example resources/read request: POST /mcp HTTP/1.1 Content-Type: application/json MCP-Protocol-Version: 2026-07-28 Mcp-Method: resources/read Mcp-Name: file:///projects/myapp/config.json { "jsonrpc": "2.0", "id": 2, "method": "resources/read", "params": { "uri": "file:///projects/myapp/config.json", "_meta": { "io.modelcontextprotocol/protocolVersion": "2026-07-28", "io.modelcontextprotocol/clientInfo": { "name": "ExampleClient", "version": "1.0.0" }, "io.modelcontextprotocol/clientCapabilities": {} } } }

Streamable HTTP x-mcp-header extension for custom headers

MCP servers MAY designate specific tool parameters to be mirrored into HTTP headers using an x-mcp-header extension property in the parameter's schema within the tool's inputSchema. Clients MUST support this feature. When a server's tool definition includes x-mcp-header annotations, conforming clients MUST mirror the designated parameter values into HTTP headers.

Streamable HTTP x-mcp-header constraints on property type

The x-mcp-header property MUST only be applied to parameters with primitive types (integer, string, boolean). Parameters with type number are not permitted. Integer values MUST be within the safe range for JavaScript (−2^53+1 to 2^53−1).

Streamable HTTP x-mcp-header constraints on schema reachability

The x-mcp-header annotation MUST only be applied to properties that are statically reachable from the schema root: reachable via a chain consisting solely of properties keys. The chain MUST NOT pass through items (or any other array keyword), composition keywords (oneOf, anyOf, allOf, not), conditional keywords (if/then/else), or $ref. Nested object properties are permitted as long as every step in the chain is a properties key.

Streamable HTTP x-mcp-header constraints on header name

The x-mcp-header property MUST NOT be empty, MUST match HTTP field-name token syntax (1*tchar, RFC 9110 Section 5.1), MUST NOT contain control characters including carriage return (CR, \r) or line feed (LF, \n), and MUST be case-insensitively unique among all x-mcp-header values in the inputSchema.

Streamable HTTP x-mcp-header header extraction behavior

Header extraction is defined as reading the instance value at the exact property path of the annotated property (the chain of properties keys leading to it). If no value is present at that path in the call arguments, the header is omitted.

Streamable HTTP client rejection of malformed tool definitions

Clients using the Streamable HTTP transport MUST reject tool definitions where any x-mcp-header value violates the constraints. Rejection means the client MUST exclude the invalid tool from the result of tools/list. Clients SHOULD log a warning when rejecting a tool definition, including the tool name and the reason for rejection.

Streamable HTTP clients on non-HTTP transports may ignore x-mcp-header

Clients using other transports (e.g., stdio) MAY ignore x-mcp-header annotations entirely.

Streamable HTTP example tool definition with x-mcp-header

Example tool definition: { "name": "execute_sql", "description": "Execute SQL on Google Cloud Spanner", "inputSchema": { "type": "object", "properties": { "region": { "type": "string", "description": "The region to execute the query in", "x-mcp-header": "Region" }, "query": { "type": "string", "description": "The SQL query to execute" } }, "required": ["region", "query"] } }

Streamable HTTP resulting request with x-mcp-header

When the tool definition includes x-mcp-header annotations, the resulting HTTP request includes the mirrored header. Example: POST /mcp HTTP/1.1 Content-Type: application/json MCP-Protocol-Version: 2026-07-28 Mcp-Method: tools/call Mcp-Name: execute_sql Mcp-Param-Region: us-west1 { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "_meta": {...}, "name": "execute_sql", "arguments": { "region": "us-west1", "query": "SELECT * FROM users" } } }

Streamable HTTP parameter value type conversion to string

When encoding parameter values before including them in HTTP headers, convert the parameter value to its string representation: for string type, use the value as-is; for integer type, convert to decimal string representation (e.g., 42, -7); for boolean type, convert to lowercase "true" or "false".

Streamable HTTP Base64 encoding of non-ASCII header values

Per RFC 9110, HTTP header field values must consist of visible ASCII characters (0x21-0x7E), space (0x20), and horizontal tab (0x09). When a value cannot be safely represented as a plain ASCII header value (e.g., it contains non-ASCII characters, control characters, or has leading/trailing whitespace), clients MUST use Base64 encoding of the UTF-8 representation with format: Mcp-Param-{Name}: =?base64?{Base64EncodedValue}?=

Streamable HTTP Base64 sentinel pattern matching

To avoid ambiguity, clients MUST also Base64-encode any plain-ASCII value that matches the sentinel pattern (i.e., starts with =?base64? and ends with ?=).

Streamable HTTP client behavior for constructing tools/call requests

When constructing a tools/call request via HTTP transport, the client MUST: 1) Extract the values for any standard headers from the request body (e.g., method, params.name, params.uri). 2) Append the Mcp-Method header and, if applicable, Mcp-Name header to the request. 3) Inspect the tool's inputSchema for properties marked with x-mcp-header and extract the value at each annotated property's exact property path, omitting the header when no value is present. 4) Encode the values according to the value encoding rules. 5) Append a Mcp-Param-{Name}: {Value} header to the request.

Streamable HTTP client retry behavior on HeaderMismatch error

If the server rejects a request with a HeaderMismatch error because required Mcp-Param-* headers are missing or do not match the body, the client SHOULD call tools/list to check for changes to the tool's inputSchema, then retry the original request with the appropriate headers.

Streamable HTTP intermediate server handling of custom headers

Intermediate servers that do not recognize an Mcp-Param-{Name} header MUST forward it and otherwise ignore it, as required by the HTTP Semantics RFC.

Streamable HTTP server validation of custom header values

Servers MUST reject requests with a recognized Mcp-Param-{Name} header that contains invalid characters. Any server that processes the message body MUST validate that encoded header values, after decoding if Base64-encoded, match the corresponding values in the request body. Servers MUST reject requests with 400 Bad Request HTTP status and JSON-RPC error code -32020 (HeaderMismatch) if any validation fails.

Streamable HTTP header-body validation scenario table

Header-body validation scenarios: | Scenario | Client Behavior | Server Behavior | | Parameter value provided | Client MUST include the header | Server MUST validate header matches body | | Parameter value is null | Client MUST omit the header | Server MUST NOT expect the header | | Parameter not in arguments | Client MUST omit the header | Server MUST NOT expect the header | | Client omits header but value is in body | Non-conforming client | Server MUST reject the request |

Streamable HTTP header names are case-insensitive

Header names are case-insensitive per RFC 9110. Clients and servers MUST use case-insensitive comparisons for header names. Header values (such as method names) are case-sensitive.

Streamable HTTP server must reject requests with mismatched headers and body

Servers that process the request body MUST reject requests where the values specified in the headers do not match the corresponding values in the request body. This prevents potential security vulnerabilities when different components in the network rely on different sources of truth.

Streamable HTTP integer parameter validation should be numeric

When validating integer parameter values, servers SHOULD compare the header value and the body value numerically rather than as strings (e.g., 42.0 and 42 are considered equal).

Streamable HTTP HeaderMismatch error code -32020

When rejecting a request due to header validation failure, servers MUST return HTTP status 400 Bad Request and MUST include a JSON-RPC error response using error code -32020 (HeaderMismatch). The error message describes the validation failure, such as: "Header mismatch: Mcp-Name header value 'foo' does not match body value 'bar'"

Streamable HTTP validation failure conditions

Validation failure conditions include: 1) A required standard header (MCP-Protocol-Version, Mcp-Method, Mcp-Name) is missing. 2) A header value does not match the corresponding request body value. For headers that permit Base64 sentinel encoding (Mcp-Name and Mcp-Param-{Name}), servers MUST decode encoded values before comparing them to the body value. 3) A header value contains invalid characters.

Streamable HTTP intermediary validation behavior

Intermediaries MUST return an appropriate HTTP error status (e.g., 400 Bad Request) for validation failures but are not required to return a JSON-RPC error response. Intermediaries that enforce policy based on mirrored headers (e.g., routing or rate-limiting by tenant) SHOULD verify that the MCP-Protocol-Version header indicates a version that requires header-body validation. If the version is older or the header is absent, the intermediary SHOULD reject the request rather than trusting unvalidated header values.

Streamable HTTP backward compatibility detection flow

A client that supports both modern (per-request-metadata) MCP versions and a legacy version that requires an initialize handshake MAY detect which era the server implements by attempting a modern request first. On 400 Bad Request, the client SHOULD inspect the response body before falling back: modern servers use 400 for UnsupportedProtocolVersionError, MissingRequiredClientCapabilityError, and header-validation failures. If the body contains a recognized modern JSON-RPC error, the server speaks a modern version of MCP. If the body is empty or is not a recognized modern JSON-RPC error, fall back to initialize.

Streamable HTTP earlier revisions (2025-03-26 through 2025-11-25) differences

Protocol versions 2025-03-26 through 2025-11-25 also used Streamable HTTP transport but in a different shape: servers could assign a session via the Mcp-Session-Id header (terminated with HTTP DELETE), clients could open a standalone SSE stream with HTTP GET to receive server-initiated messages, servers could send JSON-RPC requests on SSE streams, and streams were resumable via Last-Event-ID. None of these mechanisms are part of revision 2026-07-28.

Streamable HTTP server behavior for older client traffic

A server that supports only revision 2026-07-28 and receives traffic from an older client SHOULD respond as follows: HTTP GET or DELETE to the MCP endpoint should respond with 405 Method Not Allowed. An Mcp-Session-Id header on a request should be ignored, and the server should not mint or echo session IDs. A Last-Event-ID header should be ignored; streams are not resumable.

Streamable HTTP servers and clients supporting earlier protocol versions

Servers and clients that need to interoperate with counterparts speaking protocol versions 2025-03-26 through 2025-11-25 implement the behavior described in the corresponding revision (for example, 2025-11-25: Streamable HTTP), in addition to the version-negotiation fallback.

Streamable HTTP HTTP+SSE transport deprecated in 2025-03-26

The HTTP+SSE transport from protocol version 2024-11-05 has been deprecated since protocol version 2025-03-26 and is classified as Deprecated. New implementations SHOULD NOT adopt it; existing implementations SHOULD migrate to Streamable HTTP. It is eligible for removal in a future revision.

Streamable HTTP server backward compatibility with HTTP+SSE clients

Servers wanting to support older HTTP+SSE clients should continue to host both the SSE and POST endpoints of the old transport, alongside the new MCP endpoint defined for Streamable HTTP. It is also possible to combine the old POST endpoint and the new MCP endpoint, but this may introduce unneeded complexity.

Streamable HTTP client backward compatibility with HTTP+SSE servers

Clients wanting to support older HTTP+SSE servers should: 1) Accept an MCP server URL from the user, which may point to either old or new transport. 2) Attempt to POST a request to the server URL with Accept header listing application/json and text/event-stream. If it succeeds, assume Streamable HTTP transport. 3) If it fails with 400, 404, or 405 status AND the response body is not a recognized modern JSON-RPC error, issue a GET request expecting SSE stream with endpoint event as first event. When endpoint event arrives, assume old HTTP+SSE transport.

Streamable HTTP value encoding examples table

Value encoding examples: | Original Value | Reason | Encoded Header Value | | "us-west1" | Plain ASCII | Mcp-Param-Region: us-west1 | | "Hello, 世界" | Contains non-ASCII | Mcp-Param-Greeting: =?base64?SGVsbG8sIOS4lueVjA==?= | | " padded " | Leading/trailing spaces | Mcp-Param-Text: =?base64?IHBhZGRlZCA=?= | | "line1\nline2" | Contains newline | Mcp-Param-Text: =?base64?bGluZTEKbGluZTI=?= | | "=?base64?literal?=" | Matches sentinel pattern | Mcp-Param-Val: =?base64?PT9iYXNlNjQ/bGl0ZXJhbD89?= |

Streamable HTTP replaced HTTP+SSE in protocol 2025-03-26

Streamable HTTP was introduced in protocol version 2025-03-26 as a replacement for the HTTP+SSE transport from protocol version 2024-11-05.

Streamable HTTP 2026-07-28 revision removed GET stream endpoint and protocol-level sessions

Revision 2026-07-28 of Streamable HTTP removed the GET stream endpoint and removed protocol-level sessions. Clients must ensure they handle backwards compatibility correctly.

Streamable HTTP server exposes single POST endpoint

In Streamable HTTP transport, the server operates as an independent process that can handle multiple client connections. The server exposes a single HTTP endpoint (the MCP endpoint) that accepts POST requests.

Give your agent this brain