Query the 885-plant US solar distress dataset programmatically. All data is public, all endpoints are free, no API key required. Built for analysts who live in Excel and AI assistants that need structured data.
All endpoints return JSON by default. Add ?format=csv to any endpoint for an Excel-ready download. No authentication required.
https://solar-distress-map.vercel.appList and filter all 885 plants. Results are sorted by distress score descending. Supports pagination.
| Parameter | Type | Description |
|---|---|---|
| state | string | US state code, e.g. TX, CA, FL |
| nerc_region | string | MRO, NPCC, RFC, SERC, TRE, WECC |
| min_gap | number | Upper bound on gap (negative = underperforming). e.g. -0.15 returns plants worse than -15% |
| min_score | number | Minimum distress score (0-100) |
| min_mw | number | Minimum capacity in MW AC |
| distress_flavor | string | hail-impaired, curtailment-suspect, chronic-underperformer, vintage-risk, mild-underperformer, no-signal |
| owner | string | Case-insensitive partial match on owner/operator name |
| curtailment_suspect | boolean | true or false |
| residual_flag | boolean | true returns plants with unexplained gap (gap <= -10%, not curtailment) |
| limit | number | Max results (default 50, max 500) |
| offset | number | Pagination offset (default 0) |
| format | string | json (default) or csv |
curl "https://solar-distress-map.vercel.app/api/plants?nerc_region=SERC&min_gap=-0.15&limit=5"
# CSV for Excel:
curl "https://solar-distress-map.vercel.app/api/plants?nerc_region=SERC&min_gap=-0.15&format=csv" -o serc_screen.csv{
"plants": [
{
"plant_id": 59513,
"plant_name": "Meadows PV 1",
"owner": "Fresh Air Energy XVIII, LLC",
"state": "NC",
"nerc_region": "SERC",
"capacity_ac_mw": 20,
"cod_year": 2016,
"gap_pct_12mo": -0.843,
"distress_score": 87,
"distress_flavor": "chronic-underperformer",
"curtailment_suspect": false
},
...
],
"total": 53,
"offset": 0,
"limit": 5
}Full record for a single plant. Returns enriched data (flags, gap decomposition, narrative) for top-20 distress plants.
| Parameter | Type | Description |
|---|---|---|
| format | string | json (default) or csv |
curl "https://solar-distress-map.vercel.app/api/plants/59513"{
"plant": {
"plant_id": 59513,
"plant_name": "Meadows PV 1",
"gap_pct_12mo": -0.843,
"distress_score": 87,
"flags": ["RESIDUAL", "GAP"],
"gap_decomposition": {
"curtailment": 0,
"hail": -0.02,
"vintage": -0.04,
"hybrid": 0,
"residual": -0.783
},
"narrative": "...",
...
},
"source": "top20"
}Monthly capacity factor vs peer median for a plant. Shows gap_pct per month.
| Parameter | Type | Description |
|---|---|---|
| format | string | json (default) or csv |
curl "https://solar-distress-map.vercel.app/api/plants/59513/performance"
# CSV time series for charting in Excel:
curl "https://solar-distress-map.vercel.app/api/plants/59513/performance?format=csv" -o performance.csv{
"plant_id": 59513,
"plant_name": "Meadows PV 1",
"monthly_data": [
{
"year": 2024,
"month": 1,
"net_gen_mwh": 892,
"capacity_factor": 0.060,
"peer_median_cf": 0.133,
"gap_pct": -0.549
},
...
]
}Hail events within 50km of a plant, sorted by date descending. Full event history available for top-20 distress plants.
| Parameter | Type | Description |
|---|---|---|
| format | string | json (default) or csv |
curl "https://solar-distress-map.vercel.app/api/plants/66410/hail"{
"plant_id": 66410,
"plant_name": "Grizzly Ridge Solar",
"event_count": 59,
"max_hail_in_24mo": 2.75,
"events": [
{ "event_date": "2025-05-28", "mag_in": 2.75, "lat": 31.57, "lon": -98.24 },
...
]
}Top N plants by distress score nationally or within a region.
| Parameter | Type | Description |
|---|---|---|
| n | number | Number of plants (default 20, max 200) |
| state | string | Filter by state |
| nerc_region | string | Filter by NERC region |
| min_score | number | Minimum distress score |
| format | string | json (default) or csv |
curl "https://solar-distress-map.vercel.app/api/distress/top?nerc_region=SERC&n=10"{
"plants": [ ... ],
"total": 10,
"query": { "n": 10, "nerc_region": "SERC" }
}Aggregate distress statistics by NERC region: plant count, median gap, % underperforming, flavor breakdown.
| Parameter | Type | Description |
|---|---|---|
| nerc_region | string | Specific region, or omit for all regions |
| format | string | json (default) or csv |
curl "https://solar-distress-map.vercel.app/api/summary"{
"regions": [
{
"nerc_region": "SERC",
"plant_count": 323,
"median_gap_pct": -0.007,
"pct_gap_lt_neg15": 0.164,
"pct_gap_lt_neg25": 0.062,
"avg_distress_score": 22.7,
"flavor_counts": { "chronic-underperformer": 16, ... }
},
...
],
"national": { ... }
}The MCP server exposes the same dataset as tools for Claude, Cursor, and any MCP-compatible client. No data download — it's a thin client that calls the REST API.
git clone https://github.com/goodvibes413/solar-distress-map.git
cd solar-distress-map/mcp-server
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt # mcp + httpx onlyAdd to ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"solar-distress": {
"command": "/path/to/mcp-server/.venv/bin/python",
"args": ["/path/to/mcp-server/server.py"]
}
}
}claude mcp add solar-distress \
/path/to/mcp-server/.venv/bin/python \
-- /path/to/mcp-server/server.pyRestart Claude Desktop. Look for the hammer icon (⚒) in the chat input. Ask: “What NERC regions do you have data for?”
Claude calls these automatically based on what you ask. You don't invoke them directly.
| Tool | What it does | Key arguments |
|---|---|---|
| screen_plants | Filter all 885 plants by any combination of criteria | state, nerc_region, min_gap, min_score, min_mw, distress_flavor, residual_flag |
| export_screen_to_csv | Same filters, always returns CSV. Use when you want a spreadsheet. | same as screen_plants |
| get_plant_detail | Full record for a single plant: flags, decomposition, narrative | plant_id |
| explain_distress | Plain-English analysis of what's driving a plant's underperformance | plant_id |
| get_performance_history | Monthly capacity factor vs peer median time series | plant_id, months (default 24) |
| get_hail_timeline | Hail events within 50km sorted by date, with magnitude in inches | plant_id |
| get_distress_leaders | Top N most distressed plants nationally or within a region | n, state, nerc_region |
| get_region_summary | Aggregate stats per NERC region: count, median gap, % underperforming | nerc_region (optional) |
| compare_plants | Side-by-side comparison of 2-5 plants by key metrics | plant_ids[] |
| find_by_owner | All plants matching an owner name (partial, case-insensitive) | owner_name |
| get_methodology | Full methodology: peer cohort logic, gap formula, decomposition rules | none |
What an analyst would spend 2-3 hours doing across EIA, NOAA, and Excel. With the MCP connected, this takes 30 seconds.