Skip to main content
Glama

OpenSCAD MCP Server

by jhacksman
stl_validator.py4.73 kB
import os import logging import subprocess import tempfile from typing import Tuple, Optional logger = logging.getLogger(__name__) class STLValidator: """ Validates STL files to ensure they are manifold (watertight) and suitable for 3D printing. """ @staticmethod def validate_stl(stl_file: str) -> Tuple[bool, Optional[str]]: """ Validate an STL file to ensure it is manifold and suitable for 3D printing. Args: stl_file: Path to the STL file to validate Returns: Tuple of (is_valid, error_message) """ if not os.path.exists(stl_file): return False, f"STL file not found: {stl_file}" # Check file size file_size = os.path.getsize(stl_file) if file_size == 0: return False, "STL file is empty" # Basic validation - check if the file starts with "solid" for ASCII STL # or contains binary header for binary STL try: with open(stl_file, 'rb') as f: header = f.read(5) if header == b'solid': # ASCII STL is_valid, error = STLValidator._validate_ascii_stl(stl_file) else: # Binary STL is_valid, error = STLValidator._validate_binary_stl(stl_file) return is_valid, error except Exception as e: logger.error(f"Error validating STL file: {str(e)}") return False, f"Error validating STL file: {str(e)}" @staticmethod def _validate_ascii_stl(stl_file: str) -> Tuple[bool, Optional[str]]: """Validate an ASCII STL file.""" try: with open(stl_file, 'r') as f: content = f.read() # Check if the file has the correct structure if not content.strip().startswith('solid'): return False, "Invalid ASCII STL: Missing 'solid' header" if not content.strip().endswith('endsolid'): return False, "Invalid ASCII STL: Missing 'endsolid' footer" # Count facets and vertices facet_count = content.count('facet normal') vertex_count = content.count('vertex') if facet_count == 0: return False, "Invalid ASCII STL: No facets found" if vertex_count != facet_count * 3: return False, f"Invalid ASCII STL: Expected {facet_count * 3} vertices, found {vertex_count}" return True, None except Exception as e: logger.error(f"Error validating ASCII STL: {str(e)}") return False, f"Error validating ASCII STL: {str(e)}" @staticmethod def _validate_binary_stl(stl_file: str) -> Tuple[bool, Optional[str]]: """Validate a binary STL file.""" try: with open(stl_file, 'rb') as f: # Skip 80-byte header f.seek(80) # Read number of triangles (4-byte unsigned int) triangle_count_bytes = f.read(4) if len(triangle_count_bytes) != 4: return False, "Invalid binary STL: File too short" # Convert bytes to integer (little-endian) triangle_count = int.from_bytes(triangle_count_bytes, byteorder='little') # Check file size expected_size = 84 + (triangle_count * 50) # Header + count + triangles actual_size = os.path.getsize(stl_file) if actual_size != expected_size: return False, f"Invalid binary STL: Expected size {expected_size}, actual size {actual_size}" return True, None except Exception as e: logger.error(f"Error validating binary STL: {str(e)}") return False, f"Error validating binary STL: {str(e)}" @staticmethod def repair_stl(stl_file: str) -> Tuple[bool, Optional[str]]: """ Attempt to repair a non-manifold STL file. Args: stl_file: Path to the STL file to repair Returns: Tuple of (success, error_message) """ # This is a placeholder for STL repair functionality # In a real implementation, you would use a library like admesh or meshlab # to repair the STL file logger.warning(f"STL repair not implemented: {stl_file}") return False, "STL repair not implemented"

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/jhacksman/OpenSCAD-MCP-Server'

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