How to Configure Custom Headers for MCP Server Authentication in Dify Plugins

The MCP client classes in the junjiem/dify-plugin-agent-mcp_sse repository accept a headers dictionary that is automatically attached to every HTTP request sent to an MCP server, enabling authentication via standard HTTP headers.

The junjiem/dify-plugin-agent-mcp_sse plugin provides Dify agents with the ability to connect to MCP (Model Context Protocol) servers using either SSE or Streamable HTTP transports. When these servers require authentication, you must configure custom headers to pass credentials such as Bearer tokens or API keys. This guide explains exactly how the header injection mechanism works and how to configure it properly.

Understanding the MCP Client Architecture

The plugin implements two concrete client classes—McpSseClient and McpStreamableHttpClient—that handle the underlying HTTP communication. Both classes utilize the httpx library for HTTP requests and support custom header injection during initialization.

Where Headers Are Read

The factory method McpClients.init_client (located in utils/mcp_client.py, lines 49‑62) extracts the optional headers field from each server's configuration dictionary. This factory inspects the transport type (sse or streamable_http) and instantiates the appropriate client class, forwarding the headers parameter directly to the constructor.

How Headers Are Applied

Both client implementations pass the received headers dictionary to the underlying httpx.Client instance upon initialization:

  • SSE Client: In utils/mcp_client.py (lines 94‑95), the McpSseClient creates an httpx.Client(headers=self._headers), ensuring all SSE connections include the custom headers.
  • Streamable HTTP Client: In utils/mcp_client.py (lines 41‑43), the McpStreamableHttpClient similarly initializes httpx.Client(headers=self._headers) for all RPC method calls.

Because the headers are bound to the httpx.Client instance, every subsequent operation—including initialize, list_tools, and call_tool—automatically includes the configured authentication headers.

Configuring Custom Headers in Your Dify Plugin

You can supply custom headers through the Dify plugin configuration interface using either YAML syntax (for declarative setup) or Python dictionaries (for programmatic instantiation).

YAML Configuration Example

When configuring the plugin through Dify's interface or a configuration file, structure your mcpServers entry with a headers sub-dictionary:

mcpServers:
  my_secure_server:
    url: "https://mcp.example.com/api"
    transport: "sse"  # or "streamable_http"

    headers:
      Authorization: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
      X-API-Key: "sk_live_1234567890abcdef"
      X-Custom-Header: "custom-value"
    timeout: 60
    sse_read_timeout: 120  # Only required for SSE transport

The headers object supports any valid HTTP header name. Standard authentication patterns include Authorization for Bearer tokens or X-API-Key for service-specific credentials.

Python Dictionary Configuration

If you are instantiating the McpClients class directly within Python code, pass the headers as part of the server configuration dictionary:

from utils.mcp_client import McpClients

servers_config = {
    "my_secure_server": {
        "url": "https://mcp.example.com/api",
        "transport": "streamable_http",
        "headers": {
            "Authorization": "Bearer <your-access-token>",
            "X-Request-ID": "unique-trace-id-12345"
        },
        "timeout": 30,
    }
}

# Initialize clients with custom headers

clients = McpClients(servers_config, resources_as_tools=True)

Upon instantiation, the McpClients factory iterates through the configuration, detects the headers key, and passes it to the respective McpSseClient or McpStreamableHttpClient constructor.

Supported Authentication Header Patterns

The implementation supports any headers compatible with Python's httpx library. Common authentication patterns include:

  • Bearer Token Authentication: Use the Authorization header with a Bearer prefix for OAuth 2.0 or JWT-based authentication.
  • API Key Authentication: Use custom headers such as X-API-Key or api-key depending on the MCP server's requirements.
  • Custom Corporate Headers: Include headers like X-Request-ID, X-Correlation-ID, or X-Client-Version for tracing and audit purposes.

Since the headers are passed directly to the underlying HTTP client without transformation, you can implement any authentication scheme that relies on HTTP headers.

Summary

  • The junjiem/dify-plugin-agent-mcp_sse plugin supports custom headers through the headers configuration key in mcpServers definitions.
  • The McpClients.init_client factory in utils/mcp_client.py (lines 49‑62) extracts headers and passes them to McpSseClient or McpStreamableHttpClient.
  • Both client implementations bind the headers to an httpx.Client instance (lines 41‑43 for HTTP, lines 94‑95 for SSE), ensuring automatic inclusion in all RPC calls.
  • Configuration supports standard authentication patterns including Authorization (Bearer tokens) and custom headers like X-API-Key.

Frequently Asked Questions

What file contains the header configuration logic for MCP clients?

The header configuration logic resides in utils/mcp_client.py. Specifically, the McpClients.init_client factory method (lines 49‑62) reads the headers field from the server configuration, and the client constructors (lines 41‑43 for McpStreamableHttpClient and lines 94‑95 for McpSseClient) apply these headers to the underlying httpx.Client.

Can I use both SSE and Streamable HTTP transports with custom headers?

Yes. Both transport implementations support custom headers identically. When you specify transport: "sse" or transport: "streamable_http" in your configuration, the init_client factory instantiates the appropriate class (McpSseClient or McpStreamableHttpClient) and passes the headers dictionary to both. The headers are then bound to the HTTP client in both cases.

How do I rotate or update authentication headers without restarting the Dify plugin?

The current implementation in utils/mcp_client.py initializes headers during client instantiation and binds them to the httpx.Client. To update headers dynamically, you would need to reinitialize the McpClients instance with updated configuration dictionaries containing the new header values. There is no built-in method to hot-swap headers on an active client connection; creating a new client instance with the updated headers configuration is the recommended approach.

Are there any restrictions on header names or values?

No specific restrictions are imposed by the plugin code beyond what Python's httpx library and HTTP standards enforce. You can use standard headers like Authorization or X-API-Key, as well as custom X- prefixed headers. The values are passed directly to httpx.Client(headers=...) without sanitization or transformation, so ensure your values are valid HTTP header strings (e.g., no newlines or non-ASCII characters unless properly encoded).

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →