Skip to main content
Glama
token_generator.py8.05 kB
"""Token generation utilities for MCP proxy authentication. This module provides secure token generation and validation utilities for API authentication in the MCP proxy server. """ import hashlib import hmac import secrets import time import uuid from dataclasses import dataclass from typing import Any @dataclass class TokenInfo: """Information about a generated token.""" token: str token_type: str created_at: float expires_at: float | None = None class TokenGenerator: """Secure token generator for API authentication.""" @staticmethod def generate_api_key(length: int = 32) -> str: """Generate a secure API key using cryptographically strong random bytes. Args: length: The length of the token in bytes (default: 32) Returns: A hexadecimal string token """ return secrets.token_hex(length) @staticmethod def generate_uuid_token() -> str: """Generate a UUID-based token. Returns: A UUID4 string """ return str(uuid.uuid4()) @staticmethod def generate_base64_token(length: int = 32) -> str: """Generate a base64-encoded token. Args: length: The length of the token in bytes (default: 32) Returns: A base64 URL-safe string token """ return secrets.token_urlsafe(length) @staticmethod def generate_prefixed_token(prefix: str = "mcp", length: int = 32) -> str: """Generate a token with a prefix for easy identification. Args: prefix: The prefix to add to the token (default: "mcp") length: The length of the random part in bytes (default: 32) Returns: A prefixed token string """ token_part = secrets.token_hex(length) return f"{prefix}_{token_part}" @staticmethod def generate_timestamped_token(secret_key: str | None = None) -> TokenInfo: """Generate a token with timestamp for expiration tracking. Args: secret_key: Optional secret key for HMAC signing Returns: TokenInfo object containing token and metadata """ timestamp = int(time.time()) random_part = secrets.token_hex(16) if secret_key: # Create HMAC signature for additional security message = f"{timestamp}:{random_part}" signature = hmac.new( secret_key.encode(), message.encode(), hashlib.sha256 ).hexdigest()[:16] # Take first 16 chars token = f"mcp_{timestamp}_{random_part}_{signature}" else: token = f"mcp_{timestamp}_{random_part}" return TokenInfo( token=token, token_type="timestamped", created_at=float(timestamp), ) @staticmethod def validate_token_format(token: str) -> bool: """Validate basic token format. Args: token: The token to validate Returns: True if token format is valid, False otherwise """ if not token or len(token) < 8: return False # Check for common weak patterns weak_patterns = [ "123456", "password", "admin", "test", "demo", "secret", "key", "token", "api" ] token_lower = token.lower() for pattern in weak_patterns: if pattern in token_lower: return False return True @staticmethod def extract_timestamp_from_token(token: str) -> float | None: """Extract timestamp from a timestamped token. Args: token: The timestamped token Returns: The timestamp as float, or None if not a valid timestamped token """ try: if not token.startswith("mcp_"): return None parts = token.split("_") if len(parts) < 3: return None timestamp_str = parts[1] return float(timestamp_str) except (ValueError, IndexError): return None @classmethod def generate_secure_token(cls, token_type: str = "api_key", **kwargs: Any) -> TokenInfo: """Generate a secure token of the specified type. Args: token_type: Type of token to generate ("api_key", "uuid", "base64", "prefixed", "timestamped") **kwargs: Additional arguments for specific token types Returns: TokenInfo object containing the generated token and metadata """ current_time = time.time() if token_type == "api_key": length = kwargs.get("length", 32) token = cls.generate_api_key(length) elif token_type == "uuid": token = cls.generate_uuid_token() elif token_type == "base64": length = kwargs.get("length", 32) token = cls.generate_base64_token(length) elif token_type == "prefixed": prefix = kwargs.get("prefix", "mcp") length = kwargs.get("length", 32) token = cls.generate_prefixed_token(prefix, length) elif token_type == "timestamped": secret_key = kwargs.get("secret_key") return cls.generate_timestamped_token(secret_key) else: raise ValueError(f"Unknown token type: {token_type}") return TokenInfo( token=token, token_type=token_type, created_at=current_time, ) def generate_production_token() -> str: """Generate a production-ready API token. This is a convenience function that generates a secure token suitable for production use. Returns: A secure API token string """ return TokenGenerator.generate_prefixed_token("mcp_api", 32) def main() -> None: """Command-line interface for token generation.""" import argparse parser = argparse.ArgumentParser(description="Generate secure API tokens for MCP proxy") parser.add_argument( "--type", choices=["api_key", "uuid", "base64", "prefixed", "timestamped"], default="api_key", help="Type of token to generate (default: api_key)" ) parser.add_argument( "--length", type=int, default=32, help="Length of the token in bytes (default: 32)" ) parser.add_argument( "--prefix", default="mcp", help="Prefix for prefixed tokens (default: mcp)" ) parser.add_argument( "--count", type=int, default=1, help="Number of tokens to generate (default: 1)" ) parser.add_argument( "--production", action="store_true", help="Generate production-ready token (overrides other options)" ) args = parser.parse_args() if args.production: print("Production Token:") print(generate_production_token()) print("\nStore this token securely and do not share it!") return print(f"Generating {args.count} token(s) of type '{args.type}':") print() for i in range(args.count): if args.count > 1: print(f"Token {i + 1}:") token_info = TokenGenerator.generate_secure_token( token_type=args.type, length=args.length, prefix=args.prefix, ) print(f" Token: {token_info.token}") print(f" Type: {token_info.token_type}") print(f" Length: {len(token_info.token)} characters") if args.count > 1: print() print("Store these tokens securely and do not share them!") if __name__ == "__main__": main()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/gws8820/secure-mcp-proxy'

If you have feedback or need assistance with the MCP directory API, please join our Discord server