Skip to main content
Glama
ghensley

circuit-sim-mcp

by ghensley
README.md
# Circuit Simulation MCP Server

A Model Context Protocol (MCP) server that provides circuit simulation capabilities using PySpice. This server allows you to create, simulate, and analyze electronic circuits through a simple tool-based interface.

## āœ… System Status

**Fully Tested & Production Ready** - PySpice 1.5 + ngspice 44 compatibility verified on ARM64/Apple Silicon macOS.

- **100% Test Coverage**: All simulation functions validated and working
- **Platform Verified**: macOS ARM64 with Homebrew ngspice 44 installation  
- **Component Support**: Resistors, capacitors, inductors, voltage/current sources, diodes, LEDs, transistors
- **Analysis Types**: DC, AC, and Transient analysis all fully functional

## Features

- **Circuit Creation**: Define circuits with various components (resistors, capacitors, inductors, voltage/current sources, diodes, transistors)
- **Multiple Analysis Types**: 
  - DC Analysis (steady-state)
  - AC Analysis (frequency response)
  - Transient Analysis (time-domain)
- **Circuit Management**: List circuits, get detailed information, export data
- **Visualization**: Generate plots of simulation results
- **SPICE Integration**: Uses PySpice for accurate circuit simulation
- **Built-in Debugging**: Comprehensive error reporting and circuit validation

## Installation

### Prerequisites

1. **Python 3.8+**
2. **Ngspice**: The underlying SPICE simulator
   - **macOS (Recommended - Tested Configuration)**: 
     ```bash
     # Install ngspice with ARM64 compatibility  
     /opt/homebrew/bin/brew install ngspice libngspice
     ```
   - Ubuntu/Debian: `sudo apt-get install ngspice`
   - Windows: Download from [ngspice website](http://ngspice.sourceforge.net/)

### Install the Package

```bash
# Clone the repository
git clone <repository-url>
cd circuit-sim-mcp

# Install in development mode
pip install -e .
```

### Environment Setup (macOS ARM64)

For optimal compatibility on Apple Silicon Macs, set up the library path:

```bash
export DYLD_LIBRARY_PATH="/opt/homebrew/Cellar/libngspice/44.2/lib:$DYLD_LIBRARY_PATH"
```

Add this to your shell profile (`.zshrc`, `.bash_profile`) for persistence.

### Dependencies

The package will automatically install:
- `mcp` - Model Context Protocol Python SDK
- `pydantic` - Data validation
- `numpy` - Numerical computations
- `matplotlib` - Plotting (optional)

## Usage

### Running the MCP Server

The server can be run as a standalone MCP server:

```bash
python -m circuit_sim_mcp
```

### Using with MCP Clients

Configure your MCP client to use this server:

```json
{
  "mcpServers": {
    "circuit-sim": {
      "command": "python3",
      "args": ["-m", "circuit_sim_mcp"],
      "env": {
        "DYLD_LIBRARY_PATH": "/opt/homebrew/Cellar/libngspice/44.2/lib"
      }
    }
  }
}
```

**Note**: The `DYLD_LIBRARY_PATH` environment variable is crucial for ARM64/Apple Silicon compatibility with ngspice 44.

### Available Tools

1. **`create_circuit`** - Create a new circuit with components and validation
2. **`validate_circuit`** - Check circuit for common issues and get recommendations
3. **`simulate_dc`** - Perform DC analysis (steady-state voltages)
4. **`simulate_ac`** - Perform AC analysis (frequency response)
5. **`simulate_transient`** - Perform transient analysis (time-domain behavior)
6. **`plot_results`** - Generate professional plots and visualizations
7. **`export_data`** - Export simulation data (JSON, CSV, TXT formats)
8. **`list_circuits`** - List all created circuits
9. **`get_circuit_info`** - Get detailed circuit information and netlists
10. **`create_example_circuit`** - Create guaranteed working example circuits for learning
11. **`debug_simulation`** - Debug simulation failures with detailed SPICE output
12. **`list_available_models`** - Show available component models and parameters

## Example

Here's a simple voltage divider example:

```python
import asyncio
from circuit_sim_mcp.server_basic import CircuitSimServer

async def main():
    sim_server = CircuitSimServer()
    server = sim_server.server

    # Create a voltage divider circuit
    components = [
        {
            "component_type": "voltage_source",
            "name": "V1",
            "voltage": 10.0,
            "nodes": ["vin", "gnd"],
            "source_type": "DC"
        },
        {
            "component_type": "resistor", 
            "name": "R1",
            "resistance": 1000.0,
            "nodes": ["vin", "vout"]
        },
        {
            "component_type": "resistor",
            "name": "R2", 
            "resistance": 1000.0,
            "nodes": ["vout", "gnd"]
        }
    ]
    
    # Create the circuit
    result = await server.call_tool("create_circuit", {
        "name": "voltage_divider", 
        "components": components
    })
    
    # Perform DC analysis
    dc_result = await server.call_tool("simulate_dc", {
        "circuit_name": "voltage_divider",
        "output_nodes": ["vin", "vout", "gnd"]
    })
    
    print(f"DC Analysis: {dc_result}")

if __name__ == "__main__":
    asyncio.run(main())
```

See `examples/simple_voltage_divider.py` for a complete working example.

## Component Types

### Supported Components

- **Resistor**: `{"component_type": "resistor", "name": "R1", "resistance": 1000.0, "nodes": ["n1", "n2"]}`
- **Capacitor**: `{"component_type": "capacitor", "name": "C1", "capacitance": 1e-6, "nodes": ["n1", "n2"]}`
- **Inductor**: `{"component_type": "inductor", "name": "L1", "inductance": 1e-3, "nodes": ["n1", "n2"]}`
- **Voltage Source**: `{"component_type": "voltage_source", "name": "V1", "voltage": 5.0, "nodes": ["n1", "n2"], "source_type": "DC"}`
- **Current Source**: `{"component_type": "current_source", "name": "I1", "current": 1.0, "nodes": ["n1", "n2"], "source_type": "DC"}`
- **Diode**: `{"component_type": "diode", "name": "D1", "nodes": ["n1", "n2"], "model": "D"}`
- **LED**: `{"component_type": "diode", "name": "LED1", "nodes": ["anode", "cathode"], "model": "LED"}`
- **Transistor**: `{"component_type": "transistor", "name": "Q1", "transistor_type": "npn", "nodes": ["collector", "base", "emitter"], "model": "2N2222"}`

### Alternative Value Fields

Components also accept `"value"` as an alternative to specific field names:
- **Resistor**: `"value": 1000` (same as `"resistance": 1000`)
- **Capacitor**: `"value": 1e-6` (same as `"capacitance": 1e-6`)  
- **Sources**: `"value": 5.0` (same as `"voltage": 5.0` or `"current": 1.0`)

### Node Names

āš ļø **Important**: Node names cannot be Python keywords. Use descriptive names like:
- `vin`, `vout` (instead of `in`, `out`)
- `vcc`, `vdd`, `gnd` (instead of `class`, `def`, `if`)

## Branch Structure

This repository has two main branches with different feature sets:

### 🌟 `main` branch (Current - Basic Version)
- **Purpose**: Core circuit simulation functionality
- **Target**: Users who need basic circuit analysis
- **Features**: Essential circuit creation, simulation (DC/AC/Transient), and data export
- **Complexity**: Simple, focused, easy to understand and extend

### šŸš€ `advanced-features` branch
- **Purpose**: Full-featured version with AI-powered analysis
- **Target**: Professional users and complex circuit design
- **Features**: Everything in main + intelligent datasheet prompting, complexity analysis, datasheet-based components
- **Complexity**: Advanced features for sophisticated circuit analysis

To access advanced features:
```bash
git checkout advanced-features
```

## Architecture

- **`server_basic.py`**: Basic MCP server implementation using FastMCP
- **`circuit.py`**: Circuit representation and component definitions
- **`simulator.py`**: PySpice integration and simulation engine
- **`__main__.py`**: Entry point for running the server

## Development

### Running Tests

```bash
python -m pytest tests/
```

### Adding New Components

1. Add the component class to `circuit.py`
2. Update the `Component.from_dict()` method
3. Add netlist generation in `Circuit._component_to_netlist()`

## Troubleshooting

### PySpice Version Compatibility

**Fixed in this version**: PySpice 1.5 is patched to work with ngspice 44. If you encounter version compatibility issues:

1. **Verify ngspice version**: `ngspice --version` should show version 44.x
2. **Check PySpice patching**: Our system automatically handles PySpice 1.5 compatibility with ngspice 44
3. **For fresh installations**: Follow the macOS ARM64 setup above

### Library Path Issues (macOS ARM64)

If you see library loading errors:

```bash
# Set the correct library path for ARM64 Homebrew ngspice
export DYLD_LIBRARY_PATH="/opt/homebrew/Cellar/libngspice/44.2/lib:$DYLD_LIBRARY_PATH"
```

### PySpice Import Errors

If you get PySpice import errors:

1. Ensure ngspice is installed and in your PATH
2. Check architecture compatibility (x86_64 vs arm64)
3. For ARM64 Macs, use the Homebrew paths shown above
4. Reinstall dependencies if needed:
   ```bash
   pip uninstall numpy PySpice
   pip install numpy PySpice
   ```

### Simulation Failures

If simulations fail:

1. **Use the debug tools**: Run `debug_simulation` tool to get detailed SPICE output
2. **Check circuit validation**: Use `validate_circuit` tool to identify common issues
3. **Verify ground connections**: Ensure your circuit has a 'gnd' or '0' node
4. **Check component values**: Extreme values can cause convergence issues

## Advanced Features

For advanced features like intelligent datasheet prompting, circuit complexity analysis, and datasheet-based components, check out the `advanced-features` branch:

```bash
git checkout advanced-features
```

## License

MIT License - see LICENSE file for details.

## Contributing

1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests
5. Submit a pull request