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:
Simulation: Load models, run hazard simulations, generate Monte Carlo scenarios
Asset Analysis: Query assets, get statistics, explore network topology
Historic Hazards: Load earthquakes, hurricanes, and wildfires from database
Fragility Curves: Query default curves and parameters
Export: Save results to SQLite, JSON, GeoJSON
Cache Management: List and manage cached models
Documentation: Search ERAD docs and examples
Utilities: List asset types, manage loaded systems
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-eradQuick 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-mcpConfigure 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:
Asset Systems: Loaded distribution models with unique IDs
Hazard Systems: Loaded hazard models with unique IDs
Simulation Results: Completed simulations with result IDs
This enables workflows like:
Load asset system → get ID
Create hazard system → get ID
Add historic hurricane to hazard system
Run simulation with both IDs → get result ID
Query assets from asset system ID
Generate scenarios from result ID
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:
load_distribution_model:sourceormodel_refload_hazard_model:file_pathormodel_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¶
stored_pathpathsource_pathRegistry 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 handlersKey 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:
asset_systems: Dict of loaded distribution modelshazard_systems: Dict of loaded hazard modelssimulation_results: Dict of completed simulationshazard_simulators: Dict of active simulators
Tool Modules: Each module exports async tool functions that:
Take a
dictof parametersAccess shared state from
state.pyReturn a
dictresult (JSON-serializable)Handle errors gracefully with error messages in results
Extending the Server¶
To add a new tool:
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)}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"]
}
)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:
source(string): File path or cached model namefrom_cache(boolean): Load from cache (true) or file (false)
Returns:
system_id: Asset system ID for use in other toolsasset_count: Number of assets loaded
Example:
{
"source": "/path/to/model.json",
"from_cache": false
}create_hazard_system¶
Create a new empty hazard system.
Returns:
system_id: Hazard system ID
load_historic_hurricane¶
Load a historic hurricane from the database.
Parameters:
hazard_system_id(string): Hazard system to add tohurricane_sid(string): Hurricane SID (e.g., “2017228N14314”)
Example:
{
"hazard_system_id": "e5f6g7h8",
"hurricane_sid": "2017228N14314"
}run_simulation¶
Run a hazard simulation.
Parameters:
asset_system_id(string): Asset system IDhazard_system_id(string): Hazard system IDcurve_set(string, optional): Fragility curve set name (default: “DEFAULT_CURVES”)
Returns:
simulation_id: Simulation result IDtimesteps: Number of simulation timestepstimestamps: List of simulation timestamps
generate_scenarios¶
Generate Monte Carlo failure scenarios.
Parameters:
simulation_id(string): Completed simulation IDnum_samples(integer, optional): Number of scenarios (default: 1)seed(integer, optional): Random seed (default: 0)
Returns:
num_samples: Number generatedtotal_tracked_changes: Total tracked changesscenarios: Dictionary of scenario summaries
Asset Query Tools¶
query_assets¶
Query and filter assets from a loaded system.
Parameters:
asset_system_id(string): Asset system IDasset_type(string, optional): Filter by typemin_survival_probability(number, optional): Min survival thresholdmax_survival_probability(number, optional): Max survival thresholdlatitude_min,latitude_max(number, optional): Latitude boundslongitude_min,longitude_max(number, optional): Longitude bounds
Returns:
filtered_count: Number of matching assetsassets: List of asset details
get_asset_details¶
Get detailed information about a specific asset.
Parameters:
asset_system_id(string): Asset system IDasset_name(string): Asset name
get_asset_statistics¶
Calculate statistics about assets.
Parameters:
asset_system_id(string): Asset system ID
Returns:
statistics: Object with counts, survival probability stats
get_network_topology¶
Get network topology as node/edge lists.
Parameters:
asset_system_id(string): Asset system ID
Returns:
node_count,edge_count: Topology sizenodes,edges: Graph structure
Historic Hazard Tools¶
list_historic_hurricanes¶
List available hurricanes from database.
Parameters:
year(integer, optional): Filter by yearlimit(integer, optional): Max results (default: 50)
Returns:
hurricanes: List withsid,name,season
list_historic_earthquakes¶
List available earthquakes.
Parameters:
min_magnitude(number, optional): Minimum magnitudelimit(integer, optional): Max results (default: 50)
Returns:
earthquakes: List withearthquake_code,date,magnitude, location
list_historic_wildfires¶
List available wildfires.
Parameters:
year(integer, optional): Filter by yearlimit(integer, optional): Max results (default: 50)
Returns:
wildfires: List withfire_name,fire_year
load_historic_earthquake¶
Load a historic earthquake.
Parameters:
hazard_system_id(string): Hazard system IDearthquake_code(string): Earthquake code (e.g., “ISCGEM851547”)
load_historic_wildfire¶
Load a historic wildfire.
Parameters:
hazard_system_id(string): Hazard system IDwildfire_name(string): Fire name (e.g., “GREAT LAKES FIRE”)
Fragility Curve Tools¶
list_fragility_curves¶
List available fragility curve sets and hazard types.
Returns:
curve_sets: List of curve set nameshazard_types: Dictionary of hazard types with asset coverage
get_fragility_curve_parameters¶
Get fragility curve parameters for specific asset/hazard combination.
Parameters:
hazard_type(string): Hazard parameter (e.g., “wind_speed”, “flood_depth”)asset_type(string): Asset type
Returns:
curves: List of matching curves with distribution and parameters
Export Tools¶
export_to_sqlite¶
Export simulation results to SQLite database.
Parameters:
asset_system_id(string): Asset system with resultsoutput_path(string): Output file path
export_to_json¶
Export asset or hazard system to JSON.
Parameters:
system_id(string): System ID to exportsystem_type(string): “asset” or “hazard”output_path(string): Output file path
export_tracked_changes¶
Export Monte Carlo scenario tracked changes.
Parameters:
simulation_id(string): Simulation with tracked changesoutput_path(string): Output file path
Cache Management Tools¶
list_cached_models¶
List all cached distribution and hazard models.
Parameters:
model_type(string, optional): “distribution”, “hazard”, or “both” (default: “both”)
Returns:
distribution_models,hazard_models: Lists with name, filename, description
get_cache_info¶
Get cache directory paths and usage statistics.
Returns:
distribution_cache,hazard_cache: Objects with directory, model count, size
Documentation Tools¶
search_documentation¶
Search ERAD documentation for topics.
Parameters:
query(string): Search query
Returns:
results: List of matching files with snippets
Utility Tools¶
list_asset_types¶
List all available asset types in ERAD.
Returns:
asset_types: List of asset type strings
list_loaded_systems¶
List all currently loaded systems in memory.
Returns:
asset_systems,hazard_systems,simulations: Currently loaded items
clear_system¶
Remove a system from memory.
Parameters:
system_id(string): System ID to removesystem_type(string): “asset”, “hazard”, or “simulation”
MCP Resources¶
The server also exposes resources for direct access:
erad://docs/{path}- Documentation fileserad://cached-model/{name}- Cached distribution modelserad://asset-system/{id}- Loaded asset systems
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 assetsExample 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 statisticsTroubleshooting¶
Database Not Found¶
If historic hazard queries fail:
The database auto-downloads on first use (~500MB)
Check
~/.cache/erad/erad_data.sqliteexistsManually download from:
https://storage.googleapis.com/erad_v2_dataset/erad_data.sqlite
Out of Memory¶
For large models:
Use
clear_systemto remove unused systemsProcess assets in batches using
query_assetsfiltersGenerate fewer Monte Carlo samples
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:
Shortest path analysis
Centrality calculations
Community detection
Critical node identification
See Also¶
CLI Documentation - Command-line interface
Data Models - Asset and hazard model specifications
API Reference - Python API documentation
src/erad/mcp/README.md- Detailed module architecture and development guide