Skip to content

solidworks_mcp

solidworks_mcp

SolidWorks MCP Server - Python Implementation with FastMCP and PydanticAI.

This is a comprehensive Python implementation of the SolidWorks MCP server, providing 88+ tools for SolidWorks automation with enhanced security, configurability, and modern Python architectures.

Original TypeScript implementation rights and IP remain with the original author. This Python implementation adds FastMCP integration, PydanticAI capabilities, and comprehensive testing for local and remote deployment scenarios.

Author: Andrew Bartels (hobby mechanical engineer learning LLMs and MCP) License: MIT

Attributes

__all__ module-attribute

__all__ = ['create_server', 'main', 'SolidWorksMCPConfig', '__version__']

__version__ module-attribute

__version__ = '0.0.1'

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

__dir__

__dir__() -> list[str]

Build internal dir.

Returns:

Type Description
list[str]

list[str]: A list containing the resulting items.

Source code in src/solidworks_mcp/__init__.py
def __dir__() -> list[str]:
    """Build internal dir.

    Returns:
        list[str]: A list containing the resulting items.
    """
    return sorted(set(globals()) | set(__all__))

__getattr__

__getattr__(name: str) -> Any

Build internal getattr.

Parameters:

Name Type Description Default
name str

The name value.

required

Returns:

Name Type Description
Any Any

The result produced by the operation.

Raises:

Type Description
AttributeError

If the operation cannot be completed.

Source code in src/solidworks_mcp/__init__.py
def __getattr__(name: str) -> Any:
    """Build internal getattr.

    Args:
        name (str): The name value.

    Returns:
        Any: The result produced by the operation.

    Raises:
        AttributeError: If the operation cannot be completed.
    """
    if name in {"create_server", "main"}:
        from .server import create_server, main

        exports = {
            "create_server": create_server,
            "main": main,
        }
        return exports[name]

    raise AttributeError(f"module {__name__!r} has no attribute {name!r}")