Skip to content

Streamable HTTP: client sets Mcp-Name raw and does not Base64-encode a non-header-safe name #1243

Description

@arpankernel

Describe the bug

The Streamable HTTP client sets the Mcp-Name header from the raw name without Base64-wrapping a value that is not header-safe. The 2026-07-28 transport spec requires the client to encode such a value with the =?base64?...?= sentinel, the same rule it applies to Mcp-Param-*.

mcp/streamable_headers.go, setStandardHeaders (main line 210):

if name, ok := extractName(msg.Method, msg.Params); ok {
    header.Set(nameHeader, name)
}

The value is set directly, unlike the Mcp-Param-* path, which runs each value through encodeHeaderValue (line ~250) and Base64-wraps it when requiresBase64Encoding is true.

Transport page, "Value encoding":

The same encoding rule applies to the Mcp-Name header value. Tool and prompt names are only SHOULD-constrained to header-safe characters, so a name (or resource URI) outside the safe set is carried as: Mcp-Name: =?base64?{Base64EncodedValue}?=

Impact

A tool name or resource URI containing non-ASCII, control, or whitespace characters is sent as a raw header value. Depending on the HTTP stack it is either mangled or produces an invalid header, and a spec-compliant server that expects the sentinel encoding will not match it.

Suggested fix

Run the Mcp-Name value through encodeHeaderValue (or the same requiresBase64Encoding plus Base64 wrap) before setting the header, mirroring Mcp-Param-*.

This is the client-side counterpart to #1234 (server-side decode), fixed in #1242.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions