Skip to content

solidworks_mcp.security.auth

solidworks_mcp.security.auth

Authentication and authorization for SolidWorks MCP Server.

Attributes

F module-attribute

F = TypeVar('F', bound=Callable[..., Awaitable[Any]])

Classes

SolidWorksMCPConfig

Bases: BaseModel

Main configuration for SolidWorks MCP Server.

Attributes:

Name Type Description
adapter_type AdapterType

The adapter type value.

allowed_hosts list[str]

The allowed hosts value.

allowed_origins list[str]

The allowed origins value.

api_key SecretStr | None

The api key value.

api_key_required bool

The api key required value.

api_keys list[str]

The api keys value.

cache_dir Path | None

The cache dir value.

circuit_breaker_enabled bool

The circuit breaker enabled value.

circuit_breaker_threshold int

The circuit breaker threshold value.

circuit_breaker_timeout int

The circuit breaker timeout value.

complexity_parameter_threshold int

The complexity parameter threshold value.

complexity_score_threshold float

The complexity score threshold value.

connection_pool_size int

The connection pool size value.

connection_pooling bool

The connection pooling value.

cors_origins list[str]

The cors origins value.

data_dir Path

The data dir value.

database_url str

The database url value.

debug bool

The debug value.

deployment_mode DeploymentMode

The deployment mode value.

enable_analysis_tools bool

The enable analysis tools value.

enable_audit_logging bool

The enable audit logging value.

enable_circuit_breaker bool

The enable circuit breaker value.

enable_connection_pooling bool

The enable connection pooling value.

enable_cors bool

The enable cors value.

enable_design_tables bool

The enable design tables value.

enable_intelligent_routing bool

The enable intelligent routing value.

enable_macro_recording bool

The enable macro recording value.

enable_pdm bool

The enable pdm value.

enable_rate_limiting bool

The enable rate limiting value.

enable_response_cache bool

The enable response cache value.

enable_sql_integration bool

The enable sql integration value.

enable_windows_validation bool

The enable windows validation value.

host str

The host value.

log_file Path | None

The log file value.

log_level str

The log level value.

max_connections int

The max connections value.

max_retries int

The max retries value.

mock_solidworks bool

The mock solidworks value.

model_config Any

The model config value.

pdm_server str | None

The pdm server value.

pdm_vault str | None

The pdm vault value.

port int

The port value.

rate_limit_enabled bool

The rate limit enabled value.

rate_limit_per_minute int

The rate limit per minute value.

response_cache_max_entries int

The response cache max entries value.

response_cache_ttl_seconds int

The response cache ttl seconds value.

security_level SecurityLevel

The security level value.

solidworks_path str | None

The solidworks path value.

solidworks_year int | None

The solidworks year value.

sql_connection str | None

The sql connection value.

state_file str | None

The state file value.

testing bool

The testing value.

timeout_seconds float

The timeout seconds value.

worker_processes int

The worker processes value.

Attributes
can_use_solidworks property
can_use_solidworks: bool

Check if SolidWorks integration is possible.

Returns:

Name Type Description
bool bool

True if use solidworks, otherwise False.

is_windows property
is_windows: bool

Check if running on Windows.

Returns:

Name Type Description
bool bool

True if windows, otherwise False.

Functions
from_env classmethod
from_env(env_file: str | None = None) -> SolidWorksMCPConfig

Build configuration from environment variables.

Parameters:

Name Type Description Default
env_file str | None

The env file value. Defaults to None.

None

Returns:

Name Type Description
SolidWorksMCPConfig SolidWorksMCPConfig

The result produced by the operation.

Source code in src/solidworks_mcp/config.py
@classmethod
def from_env(cls, env_file: str | None = None) -> SolidWorksMCPConfig:
    """Build configuration from environment variables.

    Args:
        env_file (str | None): The env file value. Defaults to None.

    Returns:
        SolidWorksMCPConfig: The result produced by the operation.
    """
    import json

    env_prefix = "SOLIDWORKS_MCP_"
    raw_values: dict[str, Any] = {}

    list_like_fields = {"cors_origins", "allowed_hosts", "api_keys"}

    def _coerce_env_value(key: str, value: Any) -> Any:
        """Build internal coerce env value.

        Args:
            key (str): The key value.
            value (Any): The value value.

        Returns:
            Any: The result produced by the operation.
        """
        if not isinstance(value, str):
            return value
        if key in list_like_fields:
            stripped = value.strip()
            if stripped.startswith("[") and stripped.endswith("]"):
                try:
                    parsed = json.loads(stripped)
                    if isinstance(parsed, list):
                        return parsed
                except Exception:
                    # Leave original value for Pydantic to validate/report.
                    return value
        return value

    if env_file and Path(env_file).exists():
        for key, value in dotenv_values(env_file).items():
            if key and key.startswith(env_prefix) and value is not None:
                field_name = key[len(env_prefix) :].lower()
                raw_values[field_name] = _coerce_env_value(field_name, value)

    for key, value in os.environ.items():
        if key.startswith(env_prefix):
            field_name = key[len(env_prefix) :].lower()
            raw_values[field_name] = _coerce_env_value(field_name, value)

    return cls(**raw_values)
get_database_config
get_database_config() -> dict[str, Any]

Get database configuration.

Returns:

Type Description
dict[str, Any]

dict[str, Any]: A dictionary containing the resulting values.

Source code in src/solidworks_mcp/config.py
def get_database_config(self) -> dict[str, Any]:
    """Get database configuration.

    Returns:
        dict[str, Any]: A dictionary containing the resulting values.
    """
    return {
        "url": self.database_url,
        "echo": self.debug,
    }
get_security_config
get_security_config() -> dict[str, Any]

Get security configuration.

Returns:

Type Description
dict[str, Any]

dict[str, Any]: A dictionary containing the resulting values.

Source code in src/solidworks_mcp/config.py
def get_security_config(self) -> dict[str, Any]:
    """Get security configuration.

    Returns:
        dict[str, Any]: A dictionary containing the resulting values.
    """
    return {
        "api_key": self.api_key.get_secret_value() if self.api_key else None,
        "allowed_hosts": self.allowed_hosts,
        "enable_cors": self.enable_cors,
        "cors_origins": self.cors_origins,
        "enable_rate_limiting": self.enable_rate_limiting,
        "rate_limit_per_minute": self.rate_limit_per_minute,
        "security_level": self.security_level,
    }
model_post_init
model_post_init(__context: Any) -> None

Post-initialization setup.

Parameters:

Name Type Description Default
__context Any

The context value.

required

Returns:

Name Type Description
None None

None.

Source code in src/solidworks_mcp/config.py
def model_post_init(self, __context: Any) -> None:
    """Post-initialization setup.

    Args:
        __context (Any): The context value.

    Returns:
        None: None.
    """
    if self.cache_dir is None:
        self.cache_dir = self.data_dir / "cache"
    if self.log_file is None:
        self.log_file = self.data_dir / "logs" / "server.log"

    # Ensure data directories exist
    self.data_dir.mkdir(parents=True, exist_ok=True)
    self.cache_dir.mkdir(parents=True, exist_ok=True)
    self.log_file.parent.mkdir(parents=True, exist_ok=True)

    # Set testing defaults
    if self.testing:
        self.mock_solidworks = True
        self.adapter_type = AdapterType.MOCK
set_cache_dir classmethod
set_cache_dir(v: Path | None, info: ValidationInfo) -> Path

Set default cache directory.

Parameters:

Name Type Description Default
v Path | None

The v value.

required
info ValidationInfo

The info value.

required

Returns:

Name Type Description
Path Path

The result produced by the operation.

Source code in src/solidworks_mcp/config.py
@field_validator("cache_dir")
@classmethod
def set_cache_dir(cls, v: Path | None, info: ValidationInfo) -> Path:
    """Set default cache directory.

    Args:
        v (Path | None): The v value.
        info (ValidationInfo): The info value.

    Returns:
        Path: The result produced by the operation.
    """
    if v is None:
        data_dir = cast(
            Path,
            info.data.get("data_dir", Path.home() / ".solidworks_mcp"),
        )
        return data_dir / "cache"
    return v
set_log_file classmethod
set_log_file(v: Path | None, info: ValidationInfo) -> Path

Set default log file path.

Parameters:

Name Type Description Default
v Path | None

The v value.

required
info ValidationInfo

The info value.

required

Returns:

Name Type Description
Path Path

The result produced by the operation.

Source code in src/solidworks_mcp/config.py
@field_validator("log_file")
@classmethod
def set_log_file(cls, v: Path | None, info: ValidationInfo) -> Path:
    """Set default log file path.

    Args:
        v (Path | None): The v value.
        info (ValidationInfo): The info value.

    Returns:
        Path: The result produced by the operation.
    """
    if v is None:
        data_dir = cast(
            Path,
            info.data.get("data_dir", Path.home() / ".solidworks_mcp"),
        )
        return data_dir / "logs" / "server.log"
    return v
sync_legacy_alias_fields
sync_legacy_alias_fields() -> SolidWorksMCPConfig

Sync test/developer alias fields into canonical runtime fields.

Several fixtures and scripts still populate compatibility fields such as rate_limit_enabled and connection_pooling. Runtime code reads the canonical fields, so normalize them here after validation.

Returns:

Name Type Description
SolidWorksMCPConfig SolidWorksMCPConfig

The result produced by the operation.

Source code in src/solidworks_mcp/config.py
@model_validator(mode="after")
def sync_legacy_alias_fields(self) -> SolidWorksMCPConfig:
    """Sync test/developer alias fields into canonical runtime fields.

    Several fixtures and scripts still populate compatibility fields such as
    ``rate_limit_enabled`` and ``connection_pooling``. Runtime code reads the canonical
    fields, so normalize them here after validation.

    Returns:
        SolidWorksMCPConfig: The result produced by the operation.
    """
    self.enable_circuit_breaker = self.circuit_breaker_enabled
    self.enable_connection_pooling = self.connection_pooling
    self.connection_pool_size = self.max_connections
    self.enable_rate_limiting = self.rate_limit_enabled
    if self.allowed_origins and not self.cors_origins:
        self.cors_origins = list(self.allowed_origins)
    return self
validate_adapter_type classmethod
validate_adapter_type(v: AdapterType, info: ValidationInfo) -> AdapterType

Validate adapter type based on platform.

Parameters:

Name Type Description Default
v AdapterType

The v value.

required
info ValidationInfo

The info value.

required

Returns:

Name Type Description
AdapterType AdapterType

The result produced by the operation.

Source code in src/solidworks_mcp/config.py
@field_validator("adapter_type")
@classmethod
def validate_adapter_type(cls, v: AdapterType, info: ValidationInfo) -> AdapterType:
    """Validate adapter type based on platform.

    Args:
        v (AdapterType): The v value.
        info (ValidationInfo): The info value.

    Returns:
        AdapterType: The result produced by the operation.
    """
    return v
validate_complexity_parameter_threshold classmethod
validate_complexity_parameter_threshold(v: int) -> int

Validate the complexity parameter threshold.

Parameters:

Name Type Description Default
v int

The v value.

required

Returns:

Name Type Description
int int

The computed numeric result.

Raises:

Type Description
ValueError

Complexity_parameter_threshold must be >= 1.

Source code in src/solidworks_mcp/config.py
@field_validator("complexity_parameter_threshold")
@classmethod
def validate_complexity_parameter_threshold(cls, v: int) -> int:
    """Validate the complexity parameter threshold.

    Args:
        v (int): The v value.

    Returns:
        int: The computed numeric result.

    Raises:
        ValueError: Complexity_parameter_threshold must be >= 1.
    """
    if v < 1:
        raise ValueError("complexity_parameter_threshold must be >= 1")
    return v
validate_complexity_score_threshold classmethod
validate_complexity_score_threshold(v: float) -> float

Validate the complexity score threshold.

Parameters:

Name Type Description Default
v float

The v value.

required

Returns:

Name Type Description
float float

The computed numeric result.

Raises:

Type Description
ValueError

Complexity_score_threshold must be in (0, 1].

Source code in src/solidworks_mcp/config.py
@field_validator("complexity_score_threshold")
@classmethod
def validate_complexity_score_threshold(cls, v: float) -> float:
    """Validate the complexity score threshold.

    Args:
        v (float): The v value.

    Returns:
        float: The computed numeric result.

    Raises:
        ValueError: Complexity_score_threshold must be in (0, 1].
    """
    if v <= 0 or v > 1:
        raise ValueError("complexity_score_threshold must be in (0, 1]")
    return v
validate_port classmethod
validate_port(v: int) -> int

Validate the port.

Parameters:

Name Type Description Default
v int

The v value.

required

Returns:

Name Type Description
int int

The computed numeric result.

Raises:

Type Description
ValueError

Port must be between 1 and 65535.

Source code in src/solidworks_mcp/config.py
@field_validator("port")
@classmethod
def validate_port(cls, v: int) -> int:
    """Validate the port.

    Args:
        v (int): The v value.

    Returns:
        int: The computed numeric result.

    Raises:
        ValueError: Port must be between 1 and 65535.
    """
    if v < 1 or v > 65535:
        raise ValueError("Port must be between 1 and 65535")
    return v
validate_response_cache_max_entries classmethod
validate_response_cache_max_entries(v: int) -> int

Validate response cache size.

Parameters:

Name Type Description Default
v int

The v value.

required

Returns:

Name Type Description
int int

The computed numeric result.

Raises:

Type Description
ValueError

Response_cache_max_entries must be >= 1.

Source code in src/solidworks_mcp/config.py
@field_validator("response_cache_max_entries")
@classmethod
def validate_response_cache_max_entries(cls, v: int) -> int:
    """Validate response cache size.

    Args:
        v (int): The v value.

    Returns:
        int: The computed numeric result.

    Raises:
        ValueError: Response_cache_max_entries must be >= 1.
    """
    if v < 1:
        raise ValueError("response_cache_max_entries must be >= 1")
    return v
validate_response_cache_ttl_seconds classmethod
validate_response_cache_ttl_seconds(v: int) -> int

Validate default response cache TTL.

Parameters:

Name Type Description Default
v int

The v value.

required

Returns:

Name Type Description
int int

The computed numeric result.

Raises:

Type Description
ValueError

Response_cache_ttl_seconds must be >= 1.

Source code in src/solidworks_mcp/config.py
@field_validator("response_cache_ttl_seconds")
@classmethod
def validate_response_cache_ttl_seconds(cls, v: int) -> int:
    """Validate default response cache TTL.

    Args:
        v (int): The v value.

    Returns:
        int: The computed numeric result.

    Raises:
        ValueError: Response_cache_ttl_seconds must be >= 1.
    """
    if v < 1:
        raise ValueError("response_cache_ttl_seconds must be >= 1")
    return v
validate_timeout classmethod
validate_timeout(v: float) -> float

Validate the timeout.

Parameters:

Name Type Description Default
v float

The v value.

required

Returns:

Name Type Description
float float

The computed numeric result.

Raises:

Type Description
ValueError

Timeout_seconds must be > 0.

Source code in src/solidworks_mcp/config.py
@field_validator("timeout_seconds")
@classmethod
def validate_timeout(cls, v: float) -> float:
    """Validate the timeout.

    Args:
        v (float): The v value.

    Returns:
        float: The computed numeric result.

    Raises:
        ValueError: Timeout_seconds must be > 0.
    """
    if v <= 0:
        raise ValueError("timeout_seconds must be > 0")
    return v

Functions

require_auth

require_auth(config: SolidWorksMCPConfig) -> Callable[[F], F]

Decorate a coroutine with authentication checks.

Parameters:

Name Type Description Default
config SolidWorksMCPConfig

Configuration values for the operation.

required

Returns:

Type Description
Callable[[F], F]

Callable[[F], F]: The result produced by the operation.

Source code in src/solidworks_mcp/security/auth.py
def require_auth(config: SolidWorksMCPConfig) -> Callable[[F], F]:
    """Decorate a coroutine with authentication checks.

    Args:
        config (SolidWorksMCPConfig): Configuration values for the operation.

    Returns:
        Callable[[F], F]: The result produced by the operation.
    """

    def decorator(func: F) -> F:
        """Wrap a coroutine with request-level authentication checks.

        Args:
            func (F): The func value.

        Returns:
            F: The result produced by the operation.

        Raises:
            RuntimeError: Authentication failed: invalid api_key.
        """

        @wraps(func)
        async def wrapper(*args: Any, **kwargs: Any) -> Any:
            """Run the wrapped coroutine after API key validation.

            Args:
                *args (Any): Additional positional arguments forwarded to the call.
                **kwargs (Any): Additional keyword arguments forwarded to the call.

            Returns:
                Any: The result produced by the operation.

            Raises:
                RuntimeError: Authentication failed: invalid api_key.
            """
            security_level = str(getattr(config, "security_level", "minimal"))
            if security_level == "minimal":
                return await func(*args, **kwargs)

            api_key_required = bool(getattr(config, "api_key_required", False))
            api_key = getattr(config, "api_key", None)
            api_keys = getattr(config, "api_keys", [])
            if not (api_key_required or api_key or api_keys):
                return await func(*args, **kwargs)

            payload = kwargs.get("input_data")
            if payload is None and args:
                payload = args[0]

            payload_dict: dict[str, Any] = {}
            if payload is not None and hasattr(payload, "model_dump"):
                payload_dict = cast(dict[str, Any], payload.model_dump())
            elif isinstance(payload, dict):
                payload_dict = payload

            provided_key_value = payload_dict.get("api_key")
            provided_key = str(provided_key_value) if provided_key_value else ""

            expected_key = ""
            if api_key is not None and hasattr(api_key, "get_secret_value"):
                expected_key = api_key.get_secret_value()
            elif isinstance(api_key, str):
                expected_key = api_key
            elif api_keys:
                expected_key = api_keys[0]

            if not validate_api_key(
                provided_key=provided_key, expected_key=expected_key
            ):
                raise RuntimeError("authentication failed: invalid api_key")

            return await func(*args, **kwargs)

        return wrapper  # type: ignore[return-value]

    return decorator

setup_authentication

setup_authentication(mcp: Any, config: SolidWorksMCPConfig) -> None

Configure authentication middleware hooks.

Parameters:

Name Type Description Default
mcp Any

The mcp value.

required
config SolidWorksMCPConfig

Configuration values for the operation.

required

Returns:

Name Type Description
None None

None.

Source code in src/solidworks_mcp/security/auth.py
def setup_authentication(mcp: Any, config: SolidWorksMCPConfig) -> None:
    """Configure authentication middleware hooks.

    Args:
        mcp (Any): The mcp value.
        config (SolidWorksMCPConfig): Configuration values for the operation.

    Returns:
        None: None.
    """
    api_key = getattr(config, "api_key", None)
    api_keys = getattr(config, "api_keys", [])
    api_key_required = bool(getattr(config, "api_key_required", False))
    auth_mode = "api_key" if (api_key or api_keys or api_key_required) else "none"
    try:
        mcp._security_auth_enabled = True
        mcp._security_auth_mode = auth_mode
    except (AttributeError, TypeError):
        # Some tests intentionally pass plain object() instances without __dict__.
        return

validate_api_key

validate_api_key(provided_key: str, expected_key: str) -> bool

Validate API key using constant-time comparison.

Parameters:

Name Type Description Default
provided_key str

The provided key value.

required
expected_key str

The expected key value.

required

Returns:

Name Type Description
bool bool

True if validate api key, otherwise False.

Source code in src/solidworks_mcp/security/auth.py
def validate_api_key(provided_key: str, expected_key: str) -> bool:
    """Validate API key using constant-time comparison.

    Args:
        provided_key (str): The provided key value.
        expected_key (str): The expected key value.

    Returns:
        bool: True if validate api key, otherwise False.
    """
    if not provided_key or not expected_key:
        return False

    return secrets.compare_digest(provided_key, expected_key)