Skip to content

feat(mcp): support custom HTTP headers for non-OAuth MCP servers (#639)#704

Open
reidliu41 wants to merge 1 commit intonearai:mainfrom
reidliu41:feat/639-mcp-custom-headers
Open

feat(mcp): support custom HTTP headers for non-OAuth MCP servers (#639)#704
reidliu41 wants to merge 1 commit intonearai:mainfrom
reidliu41:feat/639-mcp-custom-headers

Conversation

@reidliu41
Copy link
Contributor

Many MCP servers (Browser-Use, internal services) authenticate via
static HTTP headers rather than OAuth. Previously these servers could
not be connected because IronClaw only supported the OAuth flow.

Add a headers field to McpServerConfig that lets users declare
arbitrary HTTP headers injected into every MCP request. Key design
decisions:

  • has_custom_headers() is independent of requires_auth() so
    existing OAuth semantics are untouched
  • Case-insensitive Authorization conflict detection prevents double
    auth header injection
  • HeaderName/HeaderValue validation at config time rejects CRLF
    injection
  • CLI --header "Name:Value" arg, mcp test header-only passthrough,
    and mcp list --verbose value masking

Usage:
ironclaw mcp add browser-use https://api.browser-use.com
--header "Authorization:Bearer sk-xxx"

Fixes #639

@github-actions github-actions bot added scope: channel/cli TUI / CLI channel scope: tool/mcp MCP client scope: extensions Extension management size: L 200-499 changed lines risk: medium Business logic, config, or moderate-risk modules labels Mar 8, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances IronClaw's compatibility by introducing the capability to configure and utilize custom HTTP headers for MCP server connections. This change broadens the range of supported authentication mechanisms beyond OAuth, enabling seamless interaction with various internal services and browser-use cases that rely on static header-based authentication. The implementation includes robust handling of header parsing, validation, and intelligent conflict resolution for Authorization headers, ensuring both functionality and security.

Highlights

  • Custom HTTP Headers Support: Implemented support for custom HTTP headers in McpServerConfig, allowing connection to MCP servers that use static header authentication instead of OAuth.
  • CLI Integration: The ironclaw mcp add command now accepts a --header "Name:Value" argument to easily configure custom headers for new servers.
  • Authorization Header Conflict Resolution: Added logic to prevent double injection of Authorization headers. If a custom Authorization header is provided, the automatic OAuth Bearer token injection is suppressed.
  • Header Validation and Security: Implemented validation for custom header names and values at configuration time to prevent CRLF injection and ensure header safety.
  • Secure Display of Headers: Header values are now masked in the mcp list --verbose output to prevent sensitive information from being leaked in logs or the terminal.
Changelog
  • src/app.rs
    • Updated client creation logic to consider custom headers when determining if an authenticated client is required.
  • src/cli/mcp.rs
    • Added a new --header argument to the mcp add command for specifying custom HTTP headers.
    • Modified the add_server function to accept and process custom headers.
    • Updated mcp list output to display custom header configuration and mask header values.
    • Adjusted mcp test logic to correctly handle servers configured with custom headers.
  • src/extensions/manager.rs
    • Modified the get_mcp_client method to check for custom headers when deciding whether to create an authenticated client.
  • src/tools/mcp/client.rs
    • Implemented the injection of custom HTTP headers into outgoing requests.
    • Added logic to conditionally inject OAuth Bearer tokens, suppressing them if a custom Authorization header is already present.
    • Introduced new unit and integration tests to verify custom header injection and Authorization header suppression.
  • src/tools/mcp/config.rs
    • Added a headers field to the McpServerConfig struct to store custom HTTP headers.
    • Implemented with_headers, has_custom_headers, and has_custom_auth_header methods for managing and querying custom headers.
    • Added validation within McpServerConfig::validate to ensure custom header names and values are valid and prevent CRLF injection.
    • Updated serialization and deserialization logic to correctly handle the new headers field.
Activity
  • The pull request was opened to address issue Support custom headers for MCP auth #639, which requested support for custom HTTP headers for non-OAuth MCP servers.
  • The author implemented a headers field in McpServerConfig to store custom headers.
  • The CLI was updated to allow users to specify custom headers via a new --header argument.
  • Logic was added to the McpClient to inject these custom headers into requests and to handle potential conflicts with OAuth Authorization headers.
  • Validation was introduced to ensure the safety and correctness of header names and values.
  • The mcp list --verbose command was updated to mask sensitive header values for security.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions github-actions bot added the contributor: new First-time contributor label Mar 8, 2026
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for custom HTTP headers for MCP servers. While the implementation includes robust validation and masking of sensitive header values in CLI output, a critical security concern was identified regarding the plaintext storage of these headers in configuration files and the database. It is strongly recommended to encrypt these headers using the existing SecretsStore or ensure restricted filesystem permissions for configuration files, aligning with best practices for handling sensitive tokens. Additionally, a minor suggestion is provided to improve code readability and maintainability in the header processing logic.

/// Used for MCP servers that require non-OAuth authentication
/// (e.g., `X-API-Key`, `Authorization: Bearer <static-token>`).
#[serde(default, skip_serializing_if = "Option::is_none")]
pub headers: Option<HashMap<String, String>>,
Copy link
Contributor

Choose a reason for hiding this comment

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

security-medium medium

Insecure Storage of Sensitive Custom Headers

Severity: Medium
Sub-category: Insecure Data Handling

Description:
Custom HTTP headers provided via the --header flag are stored in plaintext in the mcp-servers.json configuration file and the database settings table. These headers are intended for authentication (e.g., Authorization: Bearer <token>) and frequently contain sensitive API keys or session tokens. Storing them in plaintext increases the risk of credential theft if the configuration file or database is accessed by unauthorized users or compromised. While the application correctly masks these values when displaying them in the terminal, the underlying storage remains unencrypted.

Impact:
An attacker with local access to the user's filesystem or access to the database can retrieve sensitive API keys and tokens, potentially gaining unauthorized access to the associated MCP servers and services.

Remediation:
Sensitive headers should be stored in the encrypted SecretsStore instead of the plaintext configuration. Alternatively, the application should ensure that the mcp-servers.json file is created with restricted file permissions (e.g., 0600 on Unix-like systems) to prevent other users on the same machine from reading its contents.

References
  1. This rule highlights the necessity of supporting custom headers for service-specific requirements, which often involve sensitive authentication tokens. Consequently, the secure storage and handling of these headers are paramount to prevent credential leakage.

Comment on lines +182 to +195
let has_custom_auth = if let Some(ref config) = self.server_config
&& config.has_custom_headers()
{
let has_auth = config.has_custom_auth_header();
if let Some(ref headers) = config.headers {
for (name, value) in headers {
// Headers were validated at config time (CRLF-safe)
req_builder = req_builder.header(name.as_str(), value.as_str());
}
}
has_auth
} else {
false
};
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This block for adding custom headers and checking for a custom Authorization header is a bit complex, as it mixes a side effect (modifying req_builder) inside an expression. This can be refactored for better readability and maintainability by separating the action of adding headers from the check for the authorization header.

            let has_custom_auth = if let Some(config) = self.server_config.as_ref() {
                if let Some(headers) = &config.headers {
                    for (name, value) in headers {
                        // Headers were validated at config time (CRLF-safe)
                        req_builder = req_builder.header(name.as_str(), value.as_str());
                    }
                    config.has_custom_auth_header()
                } else {
                    false
                }
            } else {
                false
            };

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

Labels

contributor: new First-time contributor risk: medium Business logic, config, or moderate-risk modules scope: channel/cli TUI / CLI channel scope: extensions Extension management scope: tool/mcp MCP client size: L 200-499 changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support custom headers for MCP auth

1 participant