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

> Learn to configure Bearer token authentication for streamable-http transport in MCP OpenStack Ops. Secure your HTTP requests with CLI flags or environment variables.

- Repository: [JungJungIn/mcp-openstack-ops](https://github.com/call518/mcp-openstack-ops)
- Tags: how-to-guide
- Published: 2026-02-26

---

**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`](https://github.com/call518/mcp-openstack-ops/blob/main/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`](https://github.com/call518/mcp-openstack-ops/blob/main/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.

```python
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:

```python
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:

```python
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:

```python
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:

```bash
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:

```bash
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:

```python
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:

```python
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`](https://github.com/call518/mcp-openstack-ops/blob/main/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`](https://github.com/call518/mcp-openstack-ops/blob/main/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.