Skip to content

feat: add support for custom HTTP headers in StreamableHttpClient - #655

Merged
alexhancock merged 2 commits into
modelcontextprotocol:mainfrom
arichyx:feat/reqwest-support-custom-headers
Feb 13, 2026
Merged

feat: add support for custom HTTP headers in StreamableHttpClient#655
alexhancock merged 2 commits into
modelcontextprotocol:mainfrom
arichyx:feat/reqwest-support-custom-headers

Conversation

@arichyx

Copy link
Copy Markdown
Contributor

This PR adds support for custom HTTP headers in the StreamableHttpClient transport, allowing users to pass additional headers when connecting to remote MCP servers.

Motivation and Context

When connecting to the GitHub MCP server remotely, custom headers are required to filter and control server behavior. Specifically, the GitHub MCP server uses the X-MCP-Toolsets header to allow clients to specify which toolsets to load (e.g., X-MCP-Toolsets: issues to only load issue-related tools).

Reference: https://github.com/github/github-mcp-server/blob/main/docs/remote-server.md

The Rust SDK did not previously support custom headers, making it impossible to use these filtering capabilities. This PR addresses that limitation by adding custom header support to the StreamableHttpClient transport configuration.

How Has This Been Tested?

  • Unit tests: Added tests for configuration API, including default behavior, single/multiple headers, and interaction with existing auth_header
  • Integration test: Added end-to-end test that spins up a test HTTP server and verifies custom headers are correctly sent in MCP protocol requests
  • Test scenarios:
    • Default empty headers (backward compatibility)
    • Single custom header
    • Multiple custom headers
    • Custom headers combined with auth_header
    • Headers sent during initialize, initialized notification, and regular requests

All tests pass locally with just test.

Breaking Changes

None. This is a fully backward-compatible addition. Existing code continues to work without modification, as custom headers default to an empty HashMap.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Implementation details:

  • Added custom_headers: HashMap<HeaderName, HeaderValue> field to StreamableHttpClientTransportConfig
  • Added custom_headers() builder method for fluent API configuration
  • Updated StreamableHttpClient trait's post_message method signature to accept custom headers
  • Modified reqwest implementation to apply custom headers to all HTTP requests
  • Updated auth client wrapper to forward custom headers

Example usage:

use std::collections::HashMap;use http::{HeaderName,HeaderValue};use rmcp::transport::streamable_http_client::StreamableHttpClientTransportConfig;// Configure custom headers for GitHub MCP serverletmut headers = HashMap::new();
headers.insert(HeaderName::from_static("x-mcp-toolsets"),HeaderValue::from_static("issues"));let config = StreamableHttpClientTransportConfig::with_uri("https://mcp.github.com").custom_headers(headers);

@github-actionsgithub-actionsBot added T-dependencies Dependencies related changes T-test Testing related changes T-config Configuration file changes T-core Core library changes T-transport Transport layer changes labels Feb 13, 2026
@alexhancock
alexhancock self-requested a review February 13, 2026 15:28

@alexhancockalexhancock left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good idea - thanks for the contribution. I left one recommendation in the code.

request = request.bearer_auth(auth_header);
}
// Apply custom headers
for (name, value) in custom_headers {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps disallow any of the headers that are controlled by the default client logic?

ACCEPTHEADER_SESSION_ID etc

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would check https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#streamable-http for a full list

MCP-Protocol-Version is another one that comes to mind

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. I've updated the PR to add the check.

@alexhancock
alexhancock merged commit 016b7d3 into modelcontextprotocol:mainFeb 13, 2026
11 checks passed
@alexhancock

Copy link
Copy Markdown
Contributor

Nice one @Arichy - thanks

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

Labels

T-configConfiguration file changesT-coreCore library changesT-dependenciesDependencies related changesT-testTesting related changesT-transportTransport layer changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@arichyx@alexhancock
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
feat: add support for custom HTTP headers in StreamableHttpClient by arichyx · Pull Request #655 · modelcontextprotocol/rust-sdk · GitHub
Skip to content

feat: add support for custom HTTP headers in StreamableHttpClient - #655

Merged
alexhancock merged 2 commits into
modelcontextprotocol:mainfrom
arichyx:feat/reqwest-support-custom-headers
Feb 13, 2026
Merged

feat: add support for custom HTTP headers in StreamableHttpClient#655
alexhancock merged 2 commits into
modelcontextprotocol:mainfrom
arichyx:feat/reqwest-support-custom-headers

Conversation

@arichyx

Copy link
Copy Markdown
Contributor

This PR adds support for custom HTTP headers in the StreamableHttpClient transport, allowing users to pass additional headers when connecting to remote MCP servers.

Motivation and Context

When connecting to the GitHub MCP server remotely, custom headers are required to filter and control server behavior. Specifically, the GitHub MCP server uses the X-MCP-Toolsets header to allow clients to specify which toolsets to load (e.g., X-MCP-Toolsets: issues to only load issue-related tools).

Reference: https://github.com/github/github-mcp-server/blob/main/docs/remote-server.md

The Rust SDK did not previously support custom headers, making it impossible to use these filtering capabilities. This PR addresses that limitation by adding custom header support to the StreamableHttpClient transport configuration.

How Has This Been Tested?

  • Unit tests: Added tests for configuration API, including default behavior, single/multiple headers, and interaction with existing auth_header
  • Integration test: Added end-to-end test that spins up a test HTTP server and verifies custom headers are correctly sent in MCP protocol requests
  • Test scenarios:
    • Default empty headers (backward compatibility)
    • Single custom header
    • Multiple custom headers
    • Custom headers combined with auth_header
    • Headers sent during initialize, initialized notification, and regular requests

All tests pass locally with just test.

Breaking Changes

None. This is a fully backward-compatible addition. Existing code continues to work without modification, as custom headers default to an empty HashMap.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Implementation details:

  • Added custom_headers: HashMap<HeaderName, HeaderValue> field to StreamableHttpClientTransportConfig
  • Added custom_headers() builder method for fluent API configuration
  • Updated StreamableHttpClient trait's post_message method signature to accept custom headers
  • Modified reqwest implementation to apply custom headers to all HTTP requests
  • Updated auth client wrapper to forward custom headers

Example usage:

use std::collections::HashMap;use http::{HeaderName,HeaderValue};use rmcp::transport::streamable_http_client::StreamableHttpClientTransportConfig;// Configure custom headers for GitHub MCP serverletmut headers = HashMap::new();
headers.insert(HeaderName::from_static("x-mcp-toolsets"),HeaderValue::from_static("issues"));let config = StreamableHttpClientTransportConfig::with_uri("https://mcp.github.com").custom_headers(headers);

@github-actionsgithub-actionsBot added T-dependencies Dependencies related changes T-test Testing related changes T-config Configuration file changes T-core Core library changes T-transport Transport layer changes labels Feb 13, 2026
@alexhancock
alexhancock self-requested a review February 13, 2026 15:28

@alexhancockalexhancock left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good idea - thanks for the contribution. I left one recommendation in the code.

request = request.bearer_auth(auth_header);
}
// Apply custom headers
for (name, value) in custom_headers {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps disallow any of the headers that are controlled by the default client logic?

ACCEPTHEADER_SESSION_ID etc

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would check https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#streamable-http for a full list

MCP-Protocol-Version is another one that comes to mind

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. I've updated the PR to add the check.

@alexhancock
alexhancock merged commit 016b7d3 into modelcontextprotocol:mainFeb 13, 2026
11 checks passed
@alexhancock

Copy link
Copy Markdown
Contributor

Nice one @Arichy - thanks

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

Labels

T-configConfiguration file changesT-coreCore library changesT-dependenciesDependencies related changesT-testTesting related changesT-transportTransport layer changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@arichyx@alexhancock
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat: add support for custom HTTP headers in StreamableHttpClient by arichyx · Pull Request #655 · modelcontextprotocol/rust-sdk · GitHub
Skip to content

feat: add support for custom HTTP headers in StreamableHttpClient - #655

Merged
alexhancock merged 2 commits into
modelcontextprotocol:mainfrom
arichyx:feat/reqwest-support-custom-headers
Feb 13, 2026
Merged

feat: add support for custom HTTP headers in StreamableHttpClient#655
alexhancock merged 2 commits into
modelcontextprotocol:mainfrom
arichyx:feat/reqwest-support-custom-headers

Conversation

@arichyx

Copy link
Copy Markdown
Contributor

This PR adds support for custom HTTP headers in the StreamableHttpClient transport, allowing users to pass additional headers when connecting to remote MCP servers.

Motivation and Context

When connecting to the GitHub MCP server remotely, custom headers are required to filter and control server behavior. Specifically, the GitHub MCP server uses the X-MCP-Toolsets header to allow clients to specify which toolsets to load (e.g., X-MCP-Toolsets: issues to only load issue-related tools).

Reference: https://github.com/github/github-mcp-server/blob/main/docs/remote-server.md

The Rust SDK did not previously support custom headers, making it impossible to use these filtering capabilities. This PR addresses that limitation by adding custom header support to the StreamableHttpClient transport configuration.

How Has This Been Tested?

  • Unit tests: Added tests for configuration API, including default behavior, single/multiple headers, and interaction with existing auth_header
  • Integration test: Added end-to-end test that spins up a test HTTP server and verifies custom headers are correctly sent in MCP protocol requests
  • Test scenarios:
    • Default empty headers (backward compatibility)
    • Single custom header
    • Multiple custom headers
    • Custom headers combined with auth_header
    • Headers sent during initialize, initialized notification, and regular requests

All tests pass locally with just test.

Breaking Changes

None. This is a fully backward-compatible addition. Existing code continues to work without modification, as custom headers default to an empty HashMap.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Implementation details:

  • Added custom_headers: HashMap<HeaderName, HeaderValue> field to StreamableHttpClientTransportConfig
  • Added custom_headers() builder method for fluent API configuration
  • Updated StreamableHttpClient trait's post_message method signature to accept custom headers
  • Modified reqwest implementation to apply custom headers to all HTTP requests
  • Updated auth client wrapper to forward custom headers

Example usage:

use std::collections::HashMap;use http::{HeaderName,HeaderValue};use rmcp::transport::streamable_http_client::StreamableHttpClientTransportConfig;// Configure custom headers for GitHub MCP serverletmut headers = HashMap::new();
headers.insert(HeaderName::from_static("x-mcp-toolsets"),HeaderValue::from_static("issues"));let config = StreamableHttpClientTransportConfig::with_uri("https://mcp.github.com").custom_headers(headers);

@github-actionsgithub-actionsBot added T-dependencies Dependencies related changes T-test Testing related changes T-config Configuration file changes T-core Core library changes T-transport Transport layer changes labels Feb 13, 2026
@alexhancock
alexhancock self-requested a review February 13, 2026 15:28

@alexhancockalexhancock left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good idea - thanks for the contribution. I left one recommendation in the code.

request = request.bearer_auth(auth_header);
}
// Apply custom headers
for (name, value) in custom_headers {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps disallow any of the headers that are controlled by the default client logic?

ACCEPTHEADER_SESSION_ID etc

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would check https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#streamable-http for a full list

MCP-Protocol-Version is another one that comes to mind

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. I've updated the PR to add the check.

@alexhancock
alexhancock merged commit 016b7d3 into modelcontextprotocol:mainFeb 13, 2026
11 checks passed
@alexhancock

Copy link
Copy Markdown
Contributor

Nice one @Arichy - thanks

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

Labels

T-configConfiguration file changesT-coreCore library changesT-dependenciesDependencies related changesT-testTesting related changesT-transportTransport layer changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@arichyx@alexhancock
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat: add support for custom HTTP headers in StreamableHttpClient by arichyx · Pull Request #655 · modelcontextprotocol/rust-sdk · GitHub
Skip to content

feat: add support for custom HTTP headers in StreamableHttpClient - #655

Merged
alexhancock merged 2 commits into
modelcontextprotocol:mainfrom
arichyx:feat/reqwest-support-custom-headers
Feb 13, 2026
Merged

feat: add support for custom HTTP headers in StreamableHttpClient#655
alexhancock merged 2 commits into
modelcontextprotocol:mainfrom
arichyx:feat/reqwest-support-custom-headers

Conversation

@arichyx

Copy link
Copy Markdown
Contributor

This PR adds support for custom HTTP headers in the StreamableHttpClient transport, allowing users to pass additional headers when connecting to remote MCP servers.

Motivation and Context

When connecting to the GitHub MCP server remotely, custom headers are required to filter and control server behavior. Specifically, the GitHub MCP server uses the X-MCP-Toolsets header to allow clients to specify which toolsets to load (e.g., X-MCP-Toolsets: issues to only load issue-related tools).

Reference: https://github.com/github/github-mcp-server/blob/main/docs/remote-server.md

The Rust SDK did not previously support custom headers, making it impossible to use these filtering capabilities. This PR addresses that limitation by adding custom header support to the StreamableHttpClient transport configuration.

How Has This Been Tested?

  • Unit tests: Added tests for configuration API, including default behavior, single/multiple headers, and interaction with existing auth_header
  • Integration test: Added end-to-end test that spins up a test HTTP server and verifies custom headers are correctly sent in MCP protocol requests
  • Test scenarios:
    • Default empty headers (backward compatibility)
    • Single custom header
    • Multiple custom headers
    • Custom headers combined with auth_header
    • Headers sent during initialize, initialized notification, and regular requests

All tests pass locally with just test.

Breaking Changes

None. This is a fully backward-compatible addition. Existing code continues to work without modification, as custom headers default to an empty HashMap.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Implementation details:

  • Added custom_headers: HashMap<HeaderName, HeaderValue> field to StreamableHttpClientTransportConfig
  • Added custom_headers() builder method for fluent API configuration
  • Updated StreamableHttpClient trait's post_message method signature to accept custom headers
  • Modified reqwest implementation to apply custom headers to all HTTP requests
  • Updated auth client wrapper to forward custom headers

Example usage:

use std::collections::HashMap;use http::{HeaderName,HeaderValue};use rmcp::transport::streamable_http_client::StreamableHttpClientTransportConfig;// Configure custom headers for GitHub MCP serverletmut headers = HashMap::new();
headers.insert(HeaderName::from_static("x-mcp-toolsets"),HeaderValue::from_static("issues"));let config = StreamableHttpClientTransportConfig::with_uri("https://mcp.github.com").custom_headers(headers);

@github-actionsgithub-actionsBot added T-dependencies Dependencies related changes T-test Testing related changes T-config Configuration file changes T-core Core library changes T-transport Transport layer changes labels Feb 13, 2026
@alexhancock
alexhancock self-requested a review February 13, 2026 15:28

@alexhancockalexhancock left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good idea - thanks for the contribution. I left one recommendation in the code.

request = request.bearer_auth(auth_header);
}
// Apply custom headers
for (name, value) in custom_headers {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps disallow any of the headers that are controlled by the default client logic?

ACCEPTHEADER_SESSION_ID etc

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would check https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#streamable-http for a full list

MCP-Protocol-Version is another one that comes to mind

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. I've updated the PR to add the check.

@alexhancock
alexhancock merged commit 016b7d3 into modelcontextprotocol:mainFeb 13, 2026
11 checks passed
@alexhancock

Copy link
Copy Markdown
Contributor

Nice one @Arichy - thanks

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

Labels

T-configConfiguration file changesT-coreCore library changesT-dependenciesDependencies related changesT-testTesting related changesT-transportTransport layer changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@arichyx@alexhancock
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' feat: add support for custom HTTP headers in StreamableHttpClient by arichyx · Pull Request #655 · modelcontextprotocol/rust-sdk · GitHub
Skip to content

feat: add support for custom HTTP headers in StreamableHttpClient - #655

Merged
alexhancock merged 2 commits into
modelcontextprotocol:mainfrom
arichyx:feat/reqwest-support-custom-headers
Feb 13, 2026
Merged

feat: add support for custom HTTP headers in StreamableHttpClient#655
alexhancock merged 2 commits into
modelcontextprotocol:mainfrom
arichyx:feat/reqwest-support-custom-headers

Conversation

@arichyx

Copy link
Copy Markdown
Contributor

This PR adds support for custom HTTP headers in the StreamableHttpClient transport, allowing users to pass additional headers when connecting to remote MCP servers.

Motivation and Context

When connecting to the GitHub MCP server remotely, custom headers are required to filter and control server behavior. Specifically, the GitHub MCP server uses the X-MCP-Toolsets header to allow clients to specify which toolsets to load (e.g., X-MCP-Toolsets: issues to only load issue-related tools).

Reference: https://github.com/github/github-mcp-server/blob/main/docs/remote-server.md

The Rust SDK did not previously support custom headers, making it impossible to use these filtering capabilities. This PR addresses that limitation by adding custom header support to the StreamableHttpClient transport configuration.

How Has This Been Tested?

  • Unit tests: Added tests for configuration API, including default behavior, single/multiple headers, and interaction with existing auth_header
  • Integration test: Added end-to-end test that spins up a test HTTP server and verifies custom headers are correctly sent in MCP protocol requests
  • Test scenarios:
    • Default empty headers (backward compatibility)
    • Single custom header
    • Multiple custom headers
    • Custom headers combined with auth_header
    • Headers sent during initialize, initialized notification, and regular requests

All tests pass locally with just test.

Breaking Changes

None. This is a fully backward-compatible addition. Existing code continues to work without modification, as custom headers default to an empty HashMap.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Implementation details:

  • Added custom_headers: HashMap<HeaderName, HeaderValue> field to StreamableHttpClientTransportConfig
  • Added custom_headers() builder method for fluent API configuration
  • Updated StreamableHttpClient trait's post_message method signature to accept custom headers
  • Modified reqwest implementation to apply custom headers to all HTTP requests
  • Updated auth client wrapper to forward custom headers

Example usage:

use std::collections::HashMap;use http::{HeaderName,HeaderValue};use rmcp::transport::streamable_http_client::StreamableHttpClientTransportConfig;// Configure custom headers for GitHub MCP serverletmut headers = HashMap::new();
headers.insert(HeaderName::from_static("x-mcp-toolsets"),HeaderValue::from_static("issues"));let config = StreamableHttpClientTransportConfig::with_uri("https://mcp.github.com").custom_headers(headers);

@github-actionsgithub-actionsBot added T-dependencies Dependencies related changes T-test Testing related changes T-config Configuration file changes T-core Core library changes T-transport Transport layer changes labels Feb 13, 2026
@alexhancock
alexhancock self-requested a review February 13, 2026 15:28

@alexhancockalexhancock left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good idea - thanks for the contribution. I left one recommendation in the code.

request = request.bearer_auth(auth_header);
}
// Apply custom headers
for (name, value) in custom_headers {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps disallow any of the headers that are controlled by the default client logic?

ACCEPTHEADER_SESSION_ID etc

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would check https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#streamable-http for a full list

MCP-Protocol-Version is another one that comes to mind

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. I've updated the PR to add the check.

@alexhancock
alexhancock merged commit 016b7d3 into modelcontextprotocol:mainFeb 13, 2026
11 checks passed
@alexhancock

Copy link
Copy Markdown
Contributor

Nice one @Arichy - thanks

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

Labels

T-configConfiguration file changesT-coreCore library changesT-dependenciesDependencies related changesT-testTesting related changesT-transportTransport layer changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@arichyx@alexhancock
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat: add support for custom HTTP headers in StreamableHttpClient by arichyx · Pull Request #655 · modelcontextprotocol/rust-sdk · GitHub
Skip to content

feat: add support for custom HTTP headers in StreamableHttpClient - #655

Merged
alexhancock merged 2 commits into
modelcontextprotocol:mainfrom
arichyx:feat/reqwest-support-custom-headers
Feb 13, 2026
Merged

feat: add support for custom HTTP headers in StreamableHttpClient#655
alexhancock merged 2 commits into
modelcontextprotocol:mainfrom
arichyx:feat/reqwest-support-custom-headers

Conversation

@arichyx

Copy link
Copy Markdown
Contributor

This PR adds support for custom HTTP headers in the StreamableHttpClient transport, allowing users to pass additional headers when connecting to remote MCP servers.

Motivation and Context

When connecting to the GitHub MCP server remotely, custom headers are required to filter and control server behavior. Specifically, the GitHub MCP server uses the X-MCP-Toolsets header to allow clients to specify which toolsets to load (e.g., X-MCP-Toolsets: issues to only load issue-related tools).

Reference: https://github.com/github/github-mcp-server/blob/main/docs/remote-server.md

The Rust SDK did not previously support custom headers, making it impossible to use these filtering capabilities. This PR addresses that limitation by adding custom header support to the StreamableHttpClient transport configuration.

How Has This Been Tested?

  • Unit tests: Added tests for configuration API, including default behavior, single/multiple headers, and interaction with existing auth_header
  • Integration test: Added end-to-end test that spins up a test HTTP server and verifies custom headers are correctly sent in MCP protocol requests
  • Test scenarios:
    • Default empty headers (backward compatibility)
    • Single custom header
    • Multiple custom headers
    • Custom headers combined with auth_header
    • Headers sent during initialize, initialized notification, and regular requests

All tests pass locally with just test.

Breaking Changes

None. This is a fully backward-compatible addition. Existing code continues to work without modification, as custom headers default to an empty HashMap.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Implementation details:

  • Added custom_headers: HashMap<HeaderName, HeaderValue> field to StreamableHttpClientTransportConfig
  • Added custom_headers() builder method for fluent API configuration
  • Updated StreamableHttpClient trait's post_message method signature to accept custom headers
  • Modified reqwest implementation to apply custom headers to all HTTP requests
  • Updated auth client wrapper to forward custom headers

Example usage:

use std::collections::HashMap;use http::{HeaderName,HeaderValue};use rmcp::transport::streamable_http_client::StreamableHttpClientTransportConfig;// Configure custom headers for GitHub MCP serverletmut headers = HashMap::new();
headers.insert(HeaderName::from_static("x-mcp-toolsets"),HeaderValue::from_static("issues"));let config = StreamableHttpClientTransportConfig::with_uri("https://mcp.github.com").custom_headers(headers);

@github-actionsgithub-actionsBot added T-dependencies Dependencies related changes T-test Testing related changes T-config Configuration file changes T-core Core library changes T-transport Transport layer changes labels Feb 13, 2026
@alexhancock
alexhancock self-requested a review February 13, 2026 15:28

@alexhancockalexhancock left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good idea - thanks for the contribution. I left one recommendation in the code.

request = request.bearer_auth(auth_header);
}
// Apply custom headers
for (name, value) in custom_headers {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps disallow any of the headers that are controlled by the default client logic?

ACCEPTHEADER_SESSION_ID etc

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would check https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#streamable-http for a full list

MCP-Protocol-Version is another one that comes to mind

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. I've updated the PR to add the check.

@alexhancock
alexhancock merged commit 016b7d3 into modelcontextprotocol:mainFeb 13, 2026
11 checks passed
@alexhancock

Copy link
Copy Markdown
Contributor

Nice one @Arichy - thanks

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

Labels

T-configConfiguration file changesT-coreCore library changesT-dependenciesDependencies related changesT-testTesting related changesT-transportTransport layer changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@arichyx@alexhancock
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); feat: add support for custom HTTP headers in StreamableHttpClient by arichyx · Pull Request #655 · modelcontextprotocol/rust-sdk · GitHub
Skip to content

feat: add support for custom HTTP headers in StreamableHttpClient - #655

Merged
alexhancock merged 2 commits into
modelcontextprotocol:mainfrom
arichyx:feat/reqwest-support-custom-headers
Feb 13, 2026
Merged

feat: add support for custom HTTP headers in StreamableHttpClient#655
alexhancock merged 2 commits into
modelcontextprotocol:mainfrom
arichyx:feat/reqwest-support-custom-headers

Conversation

@arichyx

Copy link
Copy Markdown
Contributor

This PR adds support for custom HTTP headers in the StreamableHttpClient transport, allowing users to pass additional headers when connecting to remote MCP servers.

Motivation and Context

When connecting to the GitHub MCP server remotely, custom headers are required to filter and control server behavior. Specifically, the GitHub MCP server uses the X-MCP-Toolsets header to allow clients to specify which toolsets to load (e.g., X-MCP-Toolsets: issues to only load issue-related tools).

Reference: https://github.com/github/github-mcp-server/blob/main/docs/remote-server.md

The Rust SDK did not previously support custom headers, making it impossible to use these filtering capabilities. This PR addresses that limitation by adding custom header support to the StreamableHttpClient transport configuration.

How Has This Been Tested?

  • Unit tests: Added tests for configuration API, including default behavior, single/multiple headers, and interaction with existing auth_header
  • Integration test: Added end-to-end test that spins up a test HTTP server and verifies custom headers are correctly sent in MCP protocol requests
  • Test scenarios:
    • Default empty headers (backward compatibility)
    • Single custom header
    • Multiple custom headers
    • Custom headers combined with auth_header
    • Headers sent during initialize, initialized notification, and regular requests

All tests pass locally with just test.

Breaking Changes

None. This is a fully backward-compatible addition. Existing code continues to work without modification, as custom headers default to an empty HashMap.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Implementation details:

  • Added custom_headers: HashMap<HeaderName, HeaderValue> field to StreamableHttpClientTransportConfig
  • Added custom_headers() builder method for fluent API configuration
  • Updated StreamableHttpClient trait's post_message method signature to accept custom headers
  • Modified reqwest implementation to apply custom headers to all HTTP requests
  • Updated auth client wrapper to forward custom headers

Example usage:

use std::collections::HashMap;use http::{HeaderName,HeaderValue};use rmcp::transport::streamable_http_client::StreamableHttpClientTransportConfig;// Configure custom headers for GitHub MCP serverletmut headers = HashMap::new();
headers.insert(HeaderName::from_static("x-mcp-toolsets"),HeaderValue::from_static("issues"));let config = StreamableHttpClientTransportConfig::with_uri("https://mcp.github.com").custom_headers(headers);

@github-actionsgithub-actionsBot added T-dependencies Dependencies related changes T-test Testing related changes T-config Configuration file changes T-core Core library changes T-transport Transport layer changes labels Feb 13, 2026
@alexhancock
alexhancock self-requested a review February 13, 2026 15:28

@alexhancockalexhancock left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good idea - thanks for the contribution. I left one recommendation in the code.

request = request.bearer_auth(auth_header);
}
// Apply custom headers
for (name, value) in custom_headers {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps disallow any of the headers that are controlled by the default client logic?

ACCEPTHEADER_SESSION_ID etc

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would check https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#streamable-http for a full list

MCP-Protocol-Version is another one that comes to mind

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. I've updated the PR to add the check.

@alexhancock
alexhancock merged commit 016b7d3 into modelcontextprotocol:mainFeb 13, 2026
11 checks passed
@alexhancock

Copy link
Copy Markdown
Contributor

Nice one @Arichy - thanks

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

Labels

T-configConfiguration file changesT-coreCore library changesT-dependenciesDependencies related changesT-testTesting related changesT-transportTransport layer changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@arichyx@alexhancock