How to Configure Bearer Token Authentication for streamable-http Transport in MCP OpenStack Ops

Bearer token authentication in streamable-http mode is configured via CLI flags (--auth-enable, --secret-key) or environment variables (REMOTE_AUTH_ENABLE, REMOTE_SECRET_KEY), which instantiate a StaticTokenVerifier that validates the Authorization: Bearer <token> header on every HTTP request.

The MCP OpenStack Ops server supports two transport modes: the default stdio for local execution and streamable-http for network-accessible endpoints. When operating in streamable-http mode, enabling bearer token authentication ensures that only requests with valid credentials can access OpenStack operations. This guide explains how the authentication system is architected, configured, and enforced according to the source code in src/mcp_openstack_ops/mcp_main.py.

Understanding the Authentication Architecture

Core Components

The authentication stack relies on three primary components implemented in src/mcp_openstack_ops/mcp_main.py:

  • StaticTokenVerifier (imported from fastmcp): A class that maintains a static mapping of secret keys to token metadata (client ID and scopes). It validates incoming Bearer tokens against this mapping.
  • _build_static_token_auth(): A factory function (lines 61‑68) that constructs the StaticTokenVerifier using the user-supplied secret key.
  • MCP instance wiring: The mcp.auth attribute is assigned the verifier instance (lines 98‑101), enabling the fastmcp framework to automatically enforce authentication on HTTP routes.

Configuration Sources

Authentication parameters can be supplied through two mutually supportive channels:

  1. Command-line arguments defined in lines 28‑44:

    • --auth-enable / --auth-disable (mutually exclusive flags)
    • --secret-key <KEY> (required when auth is enabled)
  2. Environment variables processed in lines 78‑82:

    • REMOTE_AUTH_ENABLE (boolean string: true/false)
    • REMOTE_SECRET_KEY (the secret key string)

The configuration parser prioritizes CLI flags over environment variables, falling back to env vars only when CLI arguments are omitted.

Step-by-Step Configuration Flow

1. Parsing and Validation

When the server initializes, the main() function evaluates the transport type and authentication settings (lines 84‑95). For streamable-http transport, the logic enforces the following constraints:

  • If --auth-enable is set but --secret-key is empty, the server logs an error and exits immediately.
  • If authentication is disabled for streamable-http, a warning is emitted alerting the operator that the endpoint is unprotected.
if transport_type == "streamable-http":
    if auth_enable:
        if not secret_key:
            logger.error("ERROR: Authentication is enabled but no secret key provided.")
            return
        logger.info("Authentication enabled for streamable-http transport")
    else:
        logger.warning("WARNING: streamable-http mode without authentication enabled!")

2. Building the Token Verifier

When authentication is enabled, the _build_static_token_auth() function (lines 61‑68) creates a StaticTokenVerifier instance. This verifier maps the secret key to a token payload containing a client ID and scopes:

def _build_static_token_auth(secret_key: str) -> StaticTokenVerifier:
    tokens = {
        secret_key: {
            "client_id": "openstack-ops-client",
            "scopes": ["read", "write"],
        }
    }
    return StaticTokenVerifier(tokens=tokens)

3. Wiring into the MCP Instance

Before starting the server, the code assigns the verifier to the mcp.auth attribute (lines 98‑101). This integration point allows the fastmcp framework to intercept incoming HTTP requests and validate the Authorization header:

if auth_enable:
    mcp.auth = _build_static_token_auth(secret_key)
else:
    mcp.auth = None

4. Server Startup and Enforcement

Finally, the server starts with the streamable-http transport (lines 104‑106). If mcp.auth is set, every request must include a valid Bearer token:

if transport_type == "streamable-http":
    mcp.run(transport="streamable-http", host=host, port=port)

Requests presenting an invalid or missing token receive a 401 Unauthorized response from the underlying fastmcp library.

Practical Configuration Examples

Starting the Server with CLI Authentication

Enable bearer token authentication by providing both the enable flag and a secret key:

python -m mcp_openstack_ops \
    --type streamable-http \
    --host 0.0.0.0 \
    --port 8080 \
    --auth-enable \
    --secret-key mySuperSecretKey123

Configuring via Environment Variables

For containerized deployments, use environment variables instead of CLI flags:

export FASTMCP_TYPE=streamable-http
export FASTMCP_HOST=0.0.0.0
export FASTMCP_PORT=8080
export REMOTE_AUTH_ENABLE=true
export REMOTE_SECRET_KEY=mySuperSecretKey123

python -m mcp_openstack_ops

Making Authenticated Requests

When authentication is enabled, clients must include the Bearer token in the Authorization header. The token value is exactly the secret key configured at startup:

import requests

url = "http://localhost:8080/v1/openstack/instances"
headers = {"Authorization": "Bearer mySuperSecretKey123"}

response = requests.get(url, headers=headers)
print(response.status_code)  # 200 if valid

print(response.json())

Handling Unauthenticated Requests

Requests without the Authorization header are rejected with 401 Unauthorized:

import requests

url = "http://localhost:8080/v1/openstack/instances"
response = requests.get(url)  # No headers

print(response.status_code)  # 401

Security Behavior Matrix

The following table summarizes the runtime behavior based on configuration choices:

Configuration Transport Authentication State Behavior
--type streamable-http --auth-enable --secret-key <key> streamable-http Enabled Server requires Authorization: Bearer <key> on all requests; invalid/missing tokens return 401.
--type streamable-http (no auth flags) streamable-http Disabled Server starts with warning; accepts all requests without token validation.
--type stdio stdio N/A Authentication flags ignored; local transport has no network exposure.

Summary

  • Bearer token authentication for streamable-http transport is implemented using fastmcp's StaticTokenVerifier class, configured in src/mcp_openstack_ops/mcp_main.py.
  • Configuration occurs via CLI flags (--auth-enable, --secret-key) or environment variables (REMOTE_AUTH_ENABLE, REMOTE_SECRET_KEY), with CLI taking precedence.
  • The _build_static_token_auth() function creates a static mapping of the secret key to client metadata, which is assigned to mcp.auth before server startup.
  • When enabled, the server requires an Authorization: Bearer <token> header on every HTTP request, rejecting unauthenticated calls with a 401 response.
  • The stdio transport mode ignores authentication settings entirely, as it operates locally without network exposure.

Frequently Asked Questions

How do I enable bearer token authentication without using CLI arguments?

Set the environment variables REMOTE_AUTH_ENABLE=true and REMOTE_SECRET_KEY=your_secret_key before starting the server. The application checks these variables when CLI flags are omitted, as implemented in lines 78‑82 of src/mcp_openstack_ops/mcp_main.py.

What happens if I enable authentication but forget to provide a secret key?

The server detects this configuration error during startup (lines 84‑95) and exits immediately with an error message: "ERROR: Authentication is enabled but no secret key provided." This prevents the server from running in an insecure state where authentication is expected but cannot be validated.

Is bearer token authentication available in stdio transport mode?

No. The authentication system is only relevant for the streamable-http transport. When running with --type stdio (the default), the server operates locally via standard input/output, and the mcp.auth attribute is ignored by the transport layer. The code explicitly only validates auth configuration when transport_type == "streamable-http".

What is the format of the required Authorization header?

Clients must send the header Authorization: Bearer <token>, where <token> is the exact string provided via --secret-key or REMOTE_SECRET_KEY. The StaticTokenVerifier from the fastmcp library performs an exact string match against the configured secret; there is no JWT decoding or asymmetric signature verification in this implementation.

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 →