Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

ERAD MCP Server

The ERAD MCP (Model Context Protocol) Server provides a powerful interface for running hazard simulations, querying assets, exploring historic hazards, and analyzing distribution system resilience through AI assistants like Claude Desktop and GitHub Copilot.

Overview

The MCP server exposes ~25 tools organized into functional categories:

The server is built with a modular architecture for easy maintenance and extensibility. Each tool category is implemented in its own Python module, making it straightforward to add new capabilities or customize existing ones.

Installation

The MCP server is included with ERAD. Install with MCP support:

pip install NREL-erad

Quick Start

Start the Server

# Direct invocation
erad server mcp

# Or via Python module (uses the modular erad.mcp package)
python -m erad.mcp

# Or using the dedicated command
erad-mcp

Configure in VS Code

Add to your .vscode/settings.json:

{
  "github.copilot.chat.mcp": {
    "servers": {
      "erad": {
        "command": "erad-mcp",
        "args": []
      }
    }
  }
}

Configure in Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):

{
  "mcpServers": {
    "erad": {
      "command": "erad-mcp",
      "args": []
    }
  }
}

Core Concepts

Stateful Architecture

The MCP server maintains state in memory:

This enables workflows like:

  1. Load asset system → get ID

  2. Create hazard system → get ID

  3. Add historic hurricane to hazard system

  4. Run simulation with both IDs → get result ID

  5. Query assets from asset system ID

  6. Generate scenarios from result ID

  7. Export tracked changes

System IDs

Most operations return a system ID (8-character string) that you use in subsequent operations:

load_distribution_model → asset_system_id: "a1b2c3d4"
create_hazard_system → hazard_system_id: "e5f6g7h8"
run_simulation(a1b2c3d4, e5f6g7h8) → simulation_id: "i9j0k1l2"

model_ref Interoperability

Model-loading tools support both legacy path inputs and model_ref:

model_ref shape

{
  "model_id": "abc123def456",
  "version": 2
}

Direct path-carrying references are also valid:

{
  "stored_path": "/abs/path/to/model.json"
}

Resolution order

  1. stored_path

  2. path

  3. source_path

  4. Registry lookup by model_id / version

Registry lookup uses model_ref.registry_db first, then DIST_STACK_MODEL_REGISTRY_DB.

Example payload

{
  "model_ref": {
    "model_id": "abc123def456",
    "version": 2
  }
}

Architecture

The MCP server is built with a modular architecture for maintainability and extensibility. The implementation is organized into focused modules:

Module Structure

src/erad/mcp/
├── server.py          # Main MCP server, tool registration, request routing
├── state.py           # ServerState class for in-memory system management
├── helpers.py         # Shared utility functions (cache, serialization)
├── simulation.py      # 5 simulation tools
├── assets.py          # 4 asset query tools
├── hazards.py         # 6 historic hazard tools
├── fragility.py       # 2 fragility curve tools
├── export.py          # 3 export tools
├── cache.py           # 2 cache management tools
├── documentation.py   # 1 documentation search tool
├── utilities.py       # 3 utility tools
└── resources.py       # MCP resource protocol handlers

Key Components

server.py: Main MCP server implementation with tool registration and request routing. Uses MCP’s @app.list_tools(), @app.call_tool(), and @app.read_resource() decorators.

state.py: Global ServerState singleton that maintains:

Tool Modules: Each module exports async tool functions that:

Extending the Server

To add a new tool:

  1. Create the tool function in the appropriate module (or create a new module):

# In src/erad/mcp/my_module.py
from .state import state

async def my_new_tool(args: dict) -> dict:
    """Tool description."""
    try:
        param = args.get("param")
        # Implementation
        return {"result": "success", "data": result}
    except Exception as e:
        return {"error": str(e)}
  1. Register in server.py by adding to handle_list_tools():

Tool(
    name="my_new_tool",
    description="Tool description",
    inputSchema={
        "type": "object",
        "properties": {
            "param": {"type": "string", "description": "Parameter"}
        },
        "required": ["param"]
    }
)
  1. Route in server.py by adding to handle_call_tool():

elif name == "my_new_tool":
    result = await my_new_tool(arguments)

For more details, see src/erad/mcp/README.md.

Tool Reference

Simulation Tools

load_distribution_model

Load a distribution system model from file or cache.

Parameters:

Returns:

Example:

{
  "source": "/path/to/model.json",
  "from_cache": false
}

create_hazard_system

Create a new empty hazard system.

Returns:

load_historic_hurricane

Load a historic hurricane from the database.

Parameters:

Example:

{
  "hazard_system_id": "e5f6g7h8",
  "hurricane_sid": "2017228N14314"
}

run_simulation

Run a hazard simulation.

Parameters:

Returns:

generate_scenarios

Generate Monte Carlo failure scenarios.

Parameters:

Returns:

Asset Query Tools

query_assets

Query and filter assets from a loaded system.

Parameters:

Returns:

get_asset_details

Get detailed information about a specific asset.

Parameters:

get_asset_statistics

Calculate statistics about assets.

Parameters:

Returns:

get_network_topology

Get network topology as node/edge lists.

Parameters:

Returns:

Historic Hazard Tools

list_historic_hurricanes

List available hurricanes from database.

Parameters:

Returns:

list_historic_earthquakes

List available earthquakes.

Parameters:

Returns:

list_historic_wildfires

List available wildfires.

Parameters:

Returns:

load_historic_earthquake

Load a historic earthquake.

Parameters:

load_historic_wildfire

Load a historic wildfire.

Parameters:

Fragility Curve Tools

list_fragility_curves

List available fragility curve sets and hazard types.

Returns:

get_fragility_curve_parameters

Get fragility curve parameters for specific asset/hazard combination.

Parameters:

Returns:

Export Tools

export_to_sqlite

Export simulation results to SQLite database.

Parameters:

export_to_json

Export asset or hazard system to JSON.

Parameters:

export_tracked_changes

Export Monte Carlo scenario tracked changes.

Parameters:

Cache Management Tools

list_cached_models

List all cached distribution and hazard models.

Parameters:

Returns:

get_cache_info

Get cache directory paths and usage statistics.

Returns:

Documentation Tools

search_documentation

Search ERAD documentation for topics.

Parameters:

Returns:

Utility Tools

list_asset_types

List all available asset types in ERAD.

Returns:

list_loaded_systems

List all currently loaded systems in memory.

Returns:

clear_system

Remove a system from memory.

Parameters:

MCP Resources

The server also exposes resources for direct access:

Workflow Examples

Example 1: Basic Simulation

1. list_cached_models → See available models
2. load_distribution_model(from_cache=true, source="my_model")
   → Returns asset_system_id: "abc123"
3. create_hazard_system → Returns hazard_system_id: "def456"
4. list_historic_hurricanes(year=2017)
5. load_historic_hurricane(hazard_system_id="def456", hurricane_sid="2017228N14314")
6. run_simulation(asset_system_id="abc123", hazard_system_id="def456")
   → Returns simulation_id: "ghi789"
7. get_asset_statistics(asset_system_id="abc123") → See impact
8. export_to_sqlite(asset_system_id="abc123", output_path="results.db")

Example 2: Monte Carlo Analysis

1. Load model and run simulation (steps 1-6 from Example 1)
2. generate_scenarios(simulation_id="ghi789", num_samples=100, seed=42)
   → Get scenario summaries
3. export_tracked_changes(simulation_id="ghi789", output_path="scenarios.json")
4. query_assets(asset_system_id="abc123", max_survival_probability=0.5)
   → Find most vulnerable assets

Example 3: Multi-Hazard Analysis

1. load_distribution_model
2. create_hazard_system → hazard_id_1
3. load_historic_hurricane(hazard_id_1, sid="...")
4. run_simulation → simulation_id_1
5. create_hazard_system → hazard_id_2
6. load_historic_earthquake(hazard_id_2, code="...")
7. run_simulation → simulation_id_2
8. Compare results using query_assets and statistics

Troubleshooting

Database Not Found

If historic hazard queries fail:

Out of Memory

For large models:

Import Errors

Ensure all dependencies installed:

pip install "NREL-erad[dev]"

Advanced Usage

Custom Fragility Curves

Currently, custom curves must be added to hazard systems before simulation. Support for dynamic curve creation is planned.

Batch Operations

Multiple simulations can run in parallel by creating separate hazard systems for each scenario.

Network Analysis

Use get_network_topology with NetworkX for:

See Also