← Engineering Log
MCP server authorization

MCP Server Authorization Header: Setup and Best Practices

What Is the MCP Server Authorization Header

The MCP server authorization header is an HTTP header sent with requests to authenticate and authorize access between an MCP (Model Context Protocol) client and a backend server or external API. It follows the standard HTTP Authorization header format and tells the server who is making the request and whether they have permission to access a resource.

In the context of MCP, authorization headers are critical when your MCP server acts as a proxy or gateway to protected APIs—such as internal services, third-party data providers, or enterprise backends. Without proper authorization, requests will be rejected with 401 Unauthorized or 403 Forbidden responses.


Why Authorization Headers Matter in MCP

MCP servers often bridge AI models with real-world tools and data sources. These integrations almost always require authentication. Here's why authorization headers are especially important in this context:

  • Security enforcement: Protected APIs won't respond to unauthenticated requests.
  • Access scoping: Tokens can restrict what data or actions an AI model can access.
  • Auditability: Using identifiable credentials makes it possible to trace requests and monitor usage.
  • Compliance: Many enterprise environments require authenticated service-to-service communication.

Without correct header configuration, your MCP tools will silently fail or return error responses that are difficult to debug.


Supported Authorization Header Types

Bearer Token Authentication

Bearer tokens are the most common authorization mechanism used with MCP servers. They are typically JWTs (JSON Web Tokens) or opaque access tokens issued by an OAuth 2.0 provider.

Format:

Authorization: Bearer <your_token>

Use bearer tokens when:

  • You're connecting to OAuth 2.0-protected APIs (e.g., Google, GitHub, Salesforce)
  • Your backend uses JWT-based authentication
  • You need short-lived, rotatable credentials

Bearer tokens should be treated as secrets. Never hardcode them in source code.

API Key via Authorization Header

Some services accept API keys through the Authorization header rather than a custom header like X-API-Key.

Format:

Authorization: ApiKey <your_api_key>

Or, in some implementations:

Authorization: Bearer <your_api_key>

Use this method when:

  • The target API explicitly documents this pattern
  • You're integrating with services like Elasticsearch or certain internal APIs
  • Long-lived credentials are acceptable and properly secured

Always verify the exact format required by the target API's documentation.


How to Configure Authorization Headers in MCP

Setting Headers in MCP Server Config

Many MCP server implementations support header injection through a configuration file or environment-based setup. The exact configuration structure varies by implementation and host environment. The following example illustrates a common pattern, but consult your specific MCP server's documentation for the authoritative format.

Example: mcp_config.json

{
  "servers": {
    "my-api-server": {
      "url": "https://api.example.com",
      "headers": {
        "Authorization": "Bearer ${MY_API_TOKEN}"
      }
    }
  }
}

Key points:

  • Use environment variable interpolation (${VAR_NAME}) to avoid storing secrets in config files, if your implementation supports it.
  • Set the environment variable in your deployment environment (e.g., Docker secrets, AWS Secrets Manager, .env file for local dev).
  • Restart the MCP server after updating environment variables.

Setting the environment variable:

export MY_API_TOKEN="your-secret-token-here"

Passing Headers from MCP Client

In some architectures, the MCP client (not the server) is responsible for injecting authorization headers per request. This is common when:

  • Different users have different credentials
  • You're forwarding user-scoped OAuth tokens
  • The server is multi-tenant

The following examples illustrate the general pattern. Class names, constructor signatures, and transport APIs differ across SDK versions and languages, so refer to your SDK's current documentation for accurate usage.

Example using the MCP TypeScript SDK:

const client = new Client({
  transport: new StreamableHTTPClientTransport(
    new URL("https://your-mcp-server.com"),
    {
      requestInit: {
        headers: {
          Authorization: `Bearer ${userToken}`,
        },
      },
    }
  ),
});

Example in Python:

from mcp.client.session import ClientSession
from mcp.client.streamable_http import streamablehttp_client

async with streamablehttp_client(
    "https://your-mcp-server.com",
    headers={"Authorization": f"Bearer {user_token}"}
) as (read, write, _):
    async with ClientSession(read, write) as session:
        await session.initialize()

When passing tokens from the client, ensure the MCP server is configured to forward or validate these headers appropriately rather than override them with server-level credentials.


Common Errors and Troubleshooting

Error Likely Cause Fix
401 Unauthorized Missing or invalid token Verify token is correct and not expired
403 Forbidden Token lacks required scope Check API permissions/scopes
400 Bad Request Malformed header value Ensure correct format (Bearer <token>)
Header not forwarded MCP config missing header key Add header to server or transport config
Token expired silently No refresh logic implemented Implement token refresh or use long-lived API keys

Debugging tips:

  • Use a tool like curl to test the raw API request with the same token before configuring MCP.
  • Enable request logging on your MCP server to inspect outgoing headers.
  • Check for trailing whitespace or newline characters in token values—these cause silent failures.
  • Confirm that environment variables are actually loaded at runtime, not just set in your shell session.

Security Best Practices

Handling authorization headers incorrectly is one of the most common sources of security vulnerabilities in MCP integrations. Follow these practices:

  • Never hardcode credentials in source files, config files committed to version control, or client-side code.
  • Use environment variables or secret managers (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault) to inject credentials at runtime.
  • Rotate tokens regularly. Prefer short-lived bearer tokens over long-lived API keys where possible.
  • Apply least privilege. Use tokens scoped to only the permissions your MCP server actually needs.
  • Validate tokens server-side if your MCP server accepts tokens from clients—don't trust header values blindly.
  • Use HTTPS exclusively. Authorization headers transmitted over plain HTTP are exposed in plaintext.
  • Log carefully. Never log the full Authorization header value. Log only metadata like a token prefix or request ID.
  • Audit regularly. Review which services have access and revoke credentials that are no longer needed.

FAQ

Q: Can I use multiple authorization headers in a single MCP request? HTTP does not support duplicate Authorization headers in a standard request. If you need to authenticate with multiple services, configure separate MCP server entries—each with its own credentials—and route requests appropriately.

Q: How do I handle token expiration in MCP? Implement a token refresh mechanism before the token expires and update the header configuration dynamically. For OAuth 2.0 flows, use refresh tokens to obtain new access tokens automatically. Some MCP frameworks support middleware hooks where you can inject refreshed tokens.

Q: Is the Authorization header different from X-API-Key? Yes. Authorization is a standard HTTP header defined in RFC 9110 (which obsoletes RFC 7235), while X-API-Key is a custom header used by some APIs. Always check the target API's documentation to use the correct header. MCP supports configuring custom headers, so both patterns can work depending on your server implementation.

Q: What if my MCP server sits behind a reverse proxy that strips authorization headers? Configure your reverse proxy (e.g., Nginx, AWS ALB) to explicitly allow and forward the Authorization header. In Nginx, you can use proxy_set_header Authorization $http_authorization; within your location block to explicitly pass the header upstream. Stripping auth headers is a common default behavior intended for security but can block legitimate service-to-service communication.