generate_client_token.py•3.02 kB
"""Generate a JWT client token for the Slack MCP server.
This script loads an RSA key pair from the environment (or generates a new one if not provided)
and generates a JWT token for authenticating with the Slack MCP server.
"""
import argparse
import os
from pydantic import SecretStr
from fastmcp.server.auth.providers.bearer import RSAKeyPair
from dotenv import load_dotenv
# Load environment variables from .env file if present
load_dotenv()
# Read RSA key pair from environment variables or generate a new one if not available
import base64
private_key_b64 = os.getenv("RSA_PRIVATE_KEY")
public_key_b64 = os.getenv("RSA_PUBLIC_KEY")
if private_key_b64 and public_key_b64:
from pydantic import SecretStr
# Decode from base64 to PEM string
private_key = base64.b64decode(private_key_b64.encode()).decode("utf-8")
public_key = base64.b64decode(public_key_b64.encode()).decode("utf-8")
key_pair = RSAKeyPair(private_key=SecretStr(private_key), public_key=public_key)
print("Using RSA keys from environment variables (base64 decoded)")
else:
# Generate new keys for development or if keys are not provided
print("WARNING: RSA keys not found in environment variables, generating temporary keys")
key_pair = RSAKeyPair.generate()
print("\033[93m")
print("Add these keys to your .env file to avoid generating new keys each time:")
print(f"RSA_PRIVATE_KEY='{key_pair.private_key.get_secret_value()}'")
print(f"RSA_PUBLIC_KEY='{key_pair.public_key}'")
print("\033[0m")
def generate_client_token(subject, issuer, audience, scopes, expires_in_seconds):
return key_pair.create_token(
subject=subject,
issuer=issuer,
audience=audience,
scopes=scopes,
expires_in_seconds=expires_in_seconds,
)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Generate a JWT client token.")
parser.add_argument(
"--subject",
default="slack-mcp-server",
help="JWT subject (default: slack-mcp-server)",
)
parser.add_argument(
"--issuer",
default="slack-mcp-server",
help="JWT issuer (default: slack-mcp-server)",
)
parser.add_argument(
"--audience",
default="slack-mcp-client",
help="JWT audience (default: slack-mcp-client)",
)
parser.add_argument(
"--scopes", default="read", help="Comma-separated scopes (default: read)"
)
parser.add_argument(
"--expires-in",
type=int,
default=3600 * 24,
help="Token expiry in seconds (default: 86400)",
)
args = parser.parse_args()
scopes = [scope.strip() for scope in args.scopes.split(",") if scope.strip()]
token = generate_client_token(
subject=args.subject,
issuer=args.issuer,
audience=args.audience,
scopes=scopes,
expires_in_seconds=args.expires_in,
)
print("\033[92m")
print("Client JWT token:")
print(f"Bearer {token}")
print("\033[0m")