Skip to main content
Glama
puran-water

Corrosion Engineering MCP Server

by puran-water
interfaces.py7.61 kB
""" Abstract base classes defining plugin contracts for all tiers. These interfaces enable: - Swapping chemistry backends (phreeqpython ↔ Reaktoro ↔ IPhreeqcPy) - Pluggable mechanistic models (NORSOK ↔ MULTICORP ↔ custom) - Consistent tool orchestration across tiers - Type safety and IDE support Design Philosophy (from Codex review): - Adopt a plug-in contract per tier: Tier 0 (semantic), Tier 1 (chemistry), Tier 2 (mechanistic), Tier 3 (UQ) with shared pydantic schemas so you can swap models without rewriting orchestration. """ from abc import ABC, abstractmethod from typing import Any, Dict, List, Optional from pydantic import BaseModel # ============================================================================ # Tier 0: Handbook Lookup Interfaces # ============================================================================ class HandbookLookup(ABC): """ Abstract base for Tier 0 semantic search tools. Implementations wrap corrosion_kb semantic search (2,980 vector chunks) to provide fast screening (<0.5 sec) for material compatibility, typical rates, and mechanism guidance. """ @abstractmethod def query(self, query_text: str, filters: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: """ Query the handbook knowledge base. Args: query_text: Natural language query filters: Optional filters (e.g., material, environment) Returns: Dictionary with results, sources, and confidence """ pass # ============================================================================ # Tier 1: Chemistry Backend Interfaces # ============================================================================ class ChemistryBackend(ABC): """ Abstract base for chemistry engines (phreeqpython, Reaktoro, IPhreeqcPy). Design Pattern: - Separate PHREEQC I/O from reaction logic - Lightweight adapter around phreeqpython - Lets you prototype Reaktoro or IPhreeqcPy backends later while keeping identical JSON payloads Current Implementation: PhreeqcAdapter (phreeqpython backend) Future Options: ReaktoroAdapter, IPhreeqcPyAdapter """ @abstractmethod def speciate( self, temperature_C: float, pressure_bar: float, water: Dict[str, float], gases: Optional[Dict[str, float]] = None, ions: Optional[Dict[str, float]] = None, ) -> Dict[str, Any]: """ Calculate aqueous speciation. Args: temperature_C: Temperature in Celsius pressure_bar: Pressure in bar water: Water properties (pH, alkalinity, etc.) gases: Partial pressures (pCO2_bar, pH2S_bar, pO2_bar) ions: Ion concentrations (Cl_mg_L, SO4_mg_L, etc.) Returns: Dictionary with: - pH: Final pH - activities: Species activities {species: value} - ionic_strength: Ionic strength (mol/L) - saturation_indices: Saturation indices {mineral: SI} - concentrations: Species concentrations {species: mg/L} """ pass @abstractmethod def get_backend_name(self) -> str: """Return name of chemistry backend (e.g., 'phreeqpython', 'reaktoro')""" pass # ============================================================================ # Tier 2: Mechanistic Model Interfaces # ============================================================================ class MechanisticModel(ABC): """ Abstract base for Tier 2 physics-based corrosion models. All mechanistic models should: - Accept chemistry context (from Tier 1) - Return standardized CorrosionResult with uncertainty - Include model provenance and validation dataset references - Support multiple model backends where applicable (e.g., NORSOK vs MULTICORP) """ @abstractmethod def predict_rate( self, material: str, chemistry: Dict[str, Any], conditions: Dict[str, Any], ) -> Dict[str, Any]: """ Predict corrosion rate for given material and conditions. Args: material: Material identifier (e.g., "CS", "316L", "duplex") chemistry: Speciation result from Tier 1 chemistry backend conditions: Process conditions (T_C, v_m_s, geometry, etc.) Returns: Dictionary matching CorrosionResult schema: - rate_mm_per_y: Corrosion rate (median) - rate_p05_mm_per_y: 5th percentile - rate_p95_mm_per_y: 95th percentile - mechanism: Dominant corrosion mechanism - model_name: Model identifier - validation_dataset: Reference dataset - confidence: "high", "medium", "low" - sources: Literature citations """ pass @abstractmethod def get_model_name(self) -> str: """Return model identifier (e.g., 'NORSOK_M506', 'MULTICORP', 'ChiltonColburn')""" pass @abstractmethod def get_validation_dataset(self) -> Optional[str]: """Return validation dataset identifier (e.g., 'NORSOK_validation', 'OhioU_FREECORP')""" pass # ============================================================================ # Tier 3: Uncertainty Quantification Interfaces # ============================================================================ class UncertaintyQuantifier(ABC): """ Abstract base for Tier 3 uncertainty propagation tools. Design Pattern: - Async Monte Carlo with variance reduction (Latin Hypercube) - Wrap any Tier 1-2 tool to propagate input uncertainties - Return tornado diagrams and sensitivity analysis """ @abstractmethod async def propagate_uncertainty( self, model_call: str, base_inputs: Dict[str, Any], distributions: Dict[str, Dict[str, Any]], n_samples: int = 1000, ) -> Dict[str, Any]: """ Propagate input uncertainties via Monte Carlo. Args: model_call: Tool name to wrap (e.g., "corrosion.uniform.co2_h2s.rate") base_inputs: Nominal input values distributions: Input distributions {param: {type, mean, std, ...}} n_samples: Number of Monte Carlo samples Returns: Dictionary with: - median: Median output value - p05: 5th percentile - p95: 95th percentile - tornado: Sensitivity ranking {param: variance_contribution} - samples: Full sample array (optional) """ pass # ============================================================================ # Material Database Interfaces # ============================================================================ class MaterialDatabase(ABC): """ Abstract base for material property databases. Enables querying: - Alloy compositions - PREN values (Pitting Resistance Equivalent Number) - CPT (Critical Pitting Temperature) - Galvanic series positions - Cost factors """ @abstractmethod def get_material_properties(self, material_id: str) -> Dict[str, Any]: """Get all properties for a material""" pass @abstractmethod def calculate_pren(self, material_id: str) -> float: """Calculate PREN = %Cr + 3.3*%Mo + 16*%N""" pass @abstractmethod def estimate_cpt(self, material_id: str) -> float: """Estimate Critical Pitting Temperature (°C)""" pass

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/puran-water/corrosion-engineering-mcp'

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