HS256 with shared secret
Use HS256 when the token issuer and the MCP server share the same symmetric secret. The MCP server validates a Bearer token on every request — suitable for production when you control both sides of authentication.
Use this method for private deployments where you issue JWTs yourself. For OAuth/OIDC providers with key rotation, RS256 with JWKS is the better fit.
1. Generate a shared secret
Create a strong random secret. Use the same value in superset_config.py and wherever you sign JWT tokens.
Option A — OpenSSL (recommended):
openssl rand -base64 42
Option B — Python:
python3 -c "import secrets; print(secrets.token_urlsafe(32))"
Copy the output and store it in a password manager or secrets vault. Example output:
K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=
Never commit MCP_JWT_SECRET to git, paste it in chat, or hardcode it in client apps. Treat it like a password.
2. Configure superset_config.py
Disable development auth and enable JWT validation. Paste the secret you generated in step 1:
MCP_AUTH_ENABLED = True
MCP_DEV_USERNAME = None # disable dev-mode impersonation
MCP_JWT_ALGORITHM = "HS256"
MCP_JWT_SECRET = "K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols="
MCP_JWT_ISSUER = "superset-mcp"
MCP_JWT_AUDIENCE = "superset-mcp-clients"
Replace the example secret with your own generated value. Set the issuer and audience to values you will also use when signing tokens — they must match exactly.
Restart both processes after saving the config:
./run_superset.sh
./run_superset_mcp.sh
3. Generate a JWT for AI clients
The token must be signed with the same secret, algorithm, issuer, and audience. The sub claim must match an existing Superset username (for example admin).
Activate your Superset virtual environment and run:
import datetime
import jwt
SECRET = "K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=" # same as MCP_JWT_SECRET
ISSUER = "superset-mcp"
AUDIENCE = "superset-mcp-clients"
USERNAME = "admin" # must exist in Superset ab_user table
payload = {
"sub": USERNAME,
"iss": ISSUER,
"aud": AUDIENCE,
"exp": datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(hours=24),
}
token = jwt.encode(payload, SECRET, algorithm="HS256")
print(token)
Save as generate_mcp_token.py and run:
source /app/superset/superset_env/bin/activate
python generate_mcp_token.py
Copy the printed token — you will pass it as Authorization: Bearer <token> in your AI client config.
If tokens are rejected, enable server-side logging:
MCP_JWT_DEBUG_ERRORS = True
Check that iss, aud, and exp in the token match your config and that the token has not expired.