MCP 服务器

epwforge-mcp

io.github.guzz-labs/epwforge-mcp
数据与分析 科学与工程 公开且可连接 MCP 2026-07-28

此 MCP 可以做什么

Finds weather stations, analyzes and charts EPW weather data, and generates weather and design-condition files for building and climate analysis.

analyze_weather
Compute design conditions, HDD/CDD, monthly stats, and peak heating/cooling days for one or more EPW files. Accepts a `url` (existing EPW), `urls` (compare 2+), or `config` (synthesize on the fly with morphing/UHI/events/smoke). Config mode runs the full generation pipeline server-side but returns only stats — never the EPW content. **Token-saver: pass `compact: true` to get a ~10-field headline response (~100 tokens) instead of the full ~800-token payload.** Use compact for sanity-checking, dashboards, or when chaining many calls; full when you need monthly arrays / peak days / full ASHRAE. Optional `include_full_ashrae` adds ASHRAE 0.4/1/2% cooling + 99.6/99% heating design conditions with mean coincident dewpoint. Optional `include_improbability` (config mode) adds a stress-test score. Optional `include_idf` adds ready-to-paste EnergyPlus SizingPeriod:DesignDay objects. Optional `units` ('imperial' default | 'metric'). **Presentation: when calling with `urls` (multiple files), the response includes a `comparisons` array — render it as a markdown table to the user. Lead with the headline delta, not the raw data.** No auth required; no credits charged.
输入模式
{'type': 'object', 'properties': {'url': {'type': 'string', 'description': 'EPW URL to analyze (single file)'}, 'urls': {'type': 'array', 'items': {'type': 'string'}, 'maxItems': 10, 'minItems': 2, 'description': 'Multiple EPW URLs for comparison (first = baseline). Max 10.'}, 'units': {'enum': ['imperial', 'metric'], 'type': 'string', 'description': "Output units (default: imperial). When 'metric', temperatures are °C, wind m/s, precip mm, distance km/m."}, 'config': {'type': 'object', 'required': ['lat', 'lon'], 'properties': {'lat': {'type': 'number', 'maximum': 90, 'minimum': -90, 'description': 'Latitude, decimal degrees'}, 'lon': {'type': 'number', 'maximum': 180, 'minimum': -180, 'description': 'Longitude, decimal degrees'}, 'ssp': {'enum': ['ssp126', 'ssp245', 'ssp370', 'ssp585'], 'type': 'string', 'description': 'CMIP6 emission scenario. ssp370 is the recommended high-end for design; ssp585 (SSP5-8.5) is an opt-in extreme stress-test pathway (~4.4°C, low likelihood per IPCC AR6 / CMIP7) for worst-case analysis.'}, 'uhi': {'enum': ['none', 'suburban', 'urban', 'dense_urban'], 'type': 'string', 'description': 'Urban Heat Island preset'}, 'year': {'enum': [2030, 2035, 2040, 2045, 2050, 2060, 2070, 2080, 2090, 2100], 'type': 'integer', 'description': 'Future horizon'}, 'basis': {'enum': ['tmy', 'amy'], 'type': 'string', 'description': 'Weather file basis (default: tmy)'}, 'smoke': {'type': 'boolean', 'description': 'Enable wildfire smoke overlay'}, 'events': {'type': 'string', 'description': 'Comma-separated events. Valid: heatwave, coldsnap, hothumid, coldwindy. Pairs auto-compound (heat+humid, cold+wind).'}, 'amy_year': {'type': 'integer', 'description': 'Year for AMY basis'}, 'intensity': {'type': 'string', 'description': 'Per-event "type:1-7" intensity (1-10 with stress_test=true). 5 = typical extreme, 7 = severe ~50-yr return.'}, 'percentile': {'enum': [5, 10, 25, 50, 75, 90, 95], 'type': 'integer', 'description': 'Warming percentile (default: 50)'}, 'tmy_period': {'enum': ['full', '2011-2025', '2009-2023', '2007-2021', '2004-2018'], 'type': 'string', 'description': 'TMYx vintage. Default 2011-2025.'}, 'event_duration': {'type': 'integer', 'maximum': 30, 'minimum': 3, 'description': "Event length in days (3-30, default 14). **For stress-test scenarios use 14-21 days** — shorter durations don't capture sustained operational impact (charging schedules, occupancy patterns, equipment cycling). 7 days is too short for any design or resilience analysis. Use 7-10 only for transient short-duration events."}, 'intensity_auto': {'type': 'boolean', 'description': 'Auto-fill unspecified intensities from IPCC AR6 (default: true)'}, 'smoke_duration': {'type': 'integer', 'maximum': 30, 'minimum': 3, 'description': 'Smoke days (3-30, default: 7)'}, 'smoke_intensity': {'type': 'integer', 'maximum': 10, 'minimum': 1, 'description': 'Smoke severity 1-10 → peak AOD 0.1-6.0'}}, 'description': 'Synthesize an EPW server-side and analyze it. Stats only — file never returned. lat + lon required. Same morph/UHI/event params as generate_weather_file.'}, 'compact': {'type': 'boolean', 'description': 'Return a ~10-field headline-only response (~100 tokens) instead of the full ~800-token payload. Drops monthly arrays, peak days, n_hours, weather_basis blob. Good for sanity checks, dashboards, batched chained calls. Set to false (default) when you need the full payload.'}, 'include_idf': {'type': 'boolean', 'description': 'Add ready-to-paste EnergyPlus SizingPeriod:DesignDay IDF objects to the response. AEC-facing. Ignored when compact=true.'}, 'include_full_ashrae': {'type': 'boolean', 'description': 'Add ASHRAE 0.4%/1%/2% cooling DB + 99.6%/99% heating DB design conditions to the response. Free. Ignored when compact=true.'}, 'include_improbability': {'type': 'boolean', 'description': "Add EPWForge's stress-test improbability score (config mode only). Indicates how extreme the synthesized scenario is vs historical baselines."}}}
chart_weather
Render an SVG chart from EPW data. Eight chart types: `diurnal` (~10 KB, monthly hourly profile), `temp_carpet` (heatmap of hour × day-of-year — ~30 KB preview / ~150 KB full), `wind_rose` (~12 KB, polar bars by direction × speed), `monthly_boxplot` (~6 KB, Q1/median/Q3 + whiskers per month), `utci_carpet` (~90 KB, outdoor heat-stress hour × day, colored by UTCI category — Bröde 2012, shaded Tmrt), `economizer_carpet` (~90 KB, air-side economizer free / integrated / locked-out hour × day under ASHRAE 90.1 high-limit), `pv_tilt_azimuth` (~60 KB, annual PV generation across full tilt × azimuth space, isotropic-sky POA at lat from EPW header — optimum orientation marked), `solar_under_events` (~12 KB, weekly GHI of the modified scenario vs the no-overlay reference; bands color event-affected weeks. Requires `config` — server runs the pipeline twice, with and without overlays), `comparison` (~10 KB, design-condition deltas across EPWs). Accepts `url` (single), `urls` (2+ for comparison), or `config` (synthesize on the fly). Config mode is anon-safe — runs pipeline, returns SVG only. No auth required. **Token budget**: SVGs are returned inline by default. Large outputs (>50 KB) auto-upload to Blob storage (when configured) and return a URL instead, keeping your context lean. Always check `svg_size_kb` in the response. **Presentation: when handing the chart to the user, just link or embed it — don't narrate what's in it. Let the chart speak.**
输入模式
{'type': 'object', 'properties': {'url': {'type': 'string', 'description': 'EPW URL (single-EPW charts: diurnal, temp_carpet, wind_rose, monthly_boxplot, utci_carpet, economizer_carpet, pv_tilt_azimuth)'}, 'urls': {'type': 'array', 'items': {'type': 'string'}, 'maxItems': 10, 'minItems': 2, 'description': 'EPW URLs for chart_type=comparison (first = baseline)'}, 'config': {'type': 'object', 'required': ['lat', 'lon'], 'properties': {'lat': {'type': 'number', 'maximum': 90, 'minimum': -90, 'description': 'Latitude, decimal degrees'}, 'lon': {'type': 'number', 'maximum': 180, 'minimum': -180, 'description': 'Longitude, decimal degrees'}, 'ssp': {'enum': ['ssp126', 'ssp245', 'ssp370', 'ssp585'], 'type': 'string', 'description': 'CMIP6 emission scenario. ssp370 is the recommended high-end for design; ssp585 (SSP5-8.5) is an opt-in extreme stress-test pathway (~4.4°C, low likelihood per IPCC AR6 / CMIP7) for worst-case analysis.'}, 'uhi': {'enum': ['none', 'suburban', 'urban', 'dense_urban'], 'type': 'string', 'description': 'Urban Heat Island preset'}, 'year': {'enum': [2030, 2035, 2040, 2045, 2050, 2060, 2070, 2080, 2090, 2100], 'type': 'integer', 'description': 'Future horizon'}, 'basis': {'enum': ['tmy', 'amy'], 'type': 'string', 'description': 'Weather file basis (default: tmy)'}, 'smoke': {'type': 'boolean', 'description': 'Enable wildfire smoke overlay'}, 'events': {'type': 'string', 'description': 'Comma-separated events. Valid: heatwave, coldsnap, hothumid, coldwindy. Pairs auto-compound (heat+humid, cold+wind).'}, 'amy_year': {'type': 'integer', 'description': 'Year for AMY basis'}, 'intensity': {'type': 'string', 'description': 'Per-event "type:1-7" intensity (1-10 with stress_test=true). 5 = typical extreme, 7 = severe ~50-yr return.'}, 'percentile': {'enum': [5, 10, 25, 50, 75, 90, 95], 'type': 'integer', 'description': 'Warming percentile (default: 50)'}, 'tmy_period': {'enum': ['full', '2011-2025', '2009-2023', '2007-2021', '2004-2018'], 'type': 'string', 'description': 'TMYx vintage. Default 2011-2025.'}, 'event_duration': {'type': 'integer', 'maximum': 30, 'minimum': 3, 'description': "Event length in days (3-30, default 14). **For stress-test scenarios use 14-21 days** — shorter durations don't capture sustained operational impact (charging schedules, occupancy patterns, equipment cycling). 7 days is too short for any design or resilience analysis. Use 7-10 only for transient short-duration events."}, 'intensity_auto': {'type': 'boolean', 'description': 'Auto-fill unspecified intensities from IPCC AR6 (default: true)'}, 'smoke_duration': {'type': 'integer', 'maximum': 30, 'minimum': 3, 'description': 'Smoke days (3-30, default: 7)'}, 'smoke_intensity': {'type': 'integer', 'maximum': 10, 'minimum': 1, 'description': 'Smoke severity 1-10 → peak AOD 0.1-6.0'}}, 'description': 'Synthesize an EPW and chart it. Same params as generate_weather_file. SVG only — no file delivery.'}, 'pv_tilt': {'type': 'number', 'description': "pv_tilt_azimuth only. Optional — marks the user's planned tilt (deg, 0=horizontal) on the heatmap alongside the optimum."}, 'econ_mode': {'enum': ['drybulb', 'enthalpy'], 'type': 'string', 'description': "economizer_carpet only. 'drybulb' (default) limits OA by Tdb; 'enthalpy' limits by moist-air enthalpy — more honest in humid climates (captures latent load)."}, 'chart_type': {'enum': ['diurnal', 'temp_carpet', 'wind_rose', 'monthly_boxplot', 'utci_carpet', 'economizer_carpet', 'pv_tilt_azimuth', 'solar_under_events', 'comparison'], 'type': 'string', 'description': 'Default: diurnal'}, 'pv_azimuth': {'type': 'number', 'description': "pv_tilt_azimuth only. Optional — marks the user's planned compass azimuth (deg, 0=N, 180=S) on the heatmap."}, 'resolution': {'enum': ['preview', 'full'], 'type': 'string', 'description': "temp_carpet only. 'preview' (default) ~30 KB with 32 color buckets — visually identical at typical render sizes. 'full' ~150 KB with per-cell rgb() — use only when saving to file or when you specifically need exact color fidelity."}, 'econ_high_limit_f': {'type': 'number', 'description': 'economizer_carpet only. ASHRAE 90.1 high-limit shutoff. Defaults: 75°F (drybulb mode) or 28 BTU/lb (enthalpy mode).'}, 'econ_supply_air_f': {'type': 'number', 'description': 'economizer_carpet only. Supply-air temperature setpoint (°F). Default 55.'}}}
explore_design_conditions
Interactive single-site design-conditions explorer. Returns full ASHRAE design conditions + diurnal chart for the requested scenario. In MCP Apps-capable hosts (Claude Desktop, ChatGPT, VS Code, Goose), the response renders as a widget with sliders for SSP / year / percentile / UHI — dragging a slider re-calls this tool live. Use when a user wants to interactively tune a single site. For multi-site comparison, use analyze_weather(urls=[...]) instead. Defaults to present-day TMY (no morph) — pass ssp+year for future scenarios. P75 default percentile is design-realistic; P50 underestimates the tail. No auth required.
输入模式
{'type': 'object', 'required': ['lat', 'lon'], 'properties': {'lat': {'type': 'number', 'maximum': 90, 'minimum': -90, 'description': 'Latitude, decimal degrees'}, 'lon': {'type': 'number', 'maximum': 180, 'minimum': -180, 'description': 'Longitude, decimal degrees'}, 'ssp': {'enum': ['ssp126', 'ssp245', 'ssp370', 'ssp585'], 'type': 'string', 'description': 'CMIP6 emission scenario. Omit for present-day TMY. ssp370 is the recommended high-end; ssp585 (SSP5-8.5) is an opt-in extreme stress-test pathway for worst-case analysis.'}, 'uhi': {'enum': ['none', 'suburban', 'urban', 'dense_urban'], 'type': 'string', 'description': 'Urban Heat Island preset'}, 'year': {'enum': [2030, 2035, 2040, 2045, 2050, 2060, 2070, 2080, 2090, 2100], 'type': 'integer', 'description': 'Future horizon. Pair with ssp.'}, 'percentile': {'type': 'integer', 'maximum': 95, 'minimum': 5, 'description': 'Warming percentile. P75 design-realistic; P50 median.'}, 'allow_custom_location': {'type': 'boolean', 'description': 'Required when no OneBuilding station within 50 km'}}}
find_station
Search the GuzzStations catalog (17,000+ weather stations worldwide, self-hosted mirror of OneBuilding TMYx). Returns matching stations with EPW URLs ready to pass to analyze_weather or chart_weather. Optionally enriches with AMY extreme years (hottest / coldest / most-humid on record) and CMIP6 climate deltas. No auth required.
输入模式
{'type': 'object', 'properties': {'lat': {'type': 'number', 'maximum': 90, 'minimum': -90, 'description': 'Latitude — when set, results sorted by proximity'}, 'lon': {'type': 'number', 'maximum': 180, 'minimum': -180}, 'ssp': {'enum': ['ssp126', 'ssp245', 'ssp370', 'ssp585'], 'type': 'string', 'description': 'SSP scenario (only used with include_climate_deltas). ssp370 is the recommended high-end; ssp585 (SSP5-8.5) is an opt-in extreme stress-test pathway for worst-case analysis.'}, 'year': {'enum': [2030, 2035, 2040, 2045, 2050, 2060, 2070, 2080, 2090, 2100], 'type': 'integer', 'description': 'Future horizon (only used with include_climate_deltas)'}, 'query': {'type': 'string', 'description': 'Search by city / state (case-insensitive partial match)'}, 'country': {'type': 'string', 'description': "ISO 3-letter country code filter, e.g. 'USA', 'GBR'"}, 'percentile': {'enum': [5, 10, 25, 50, 75, 90, 95], 'type': 'integer', 'description': 'Warming percentile (only used with include_climate_deltas, default 50)'}, 'max_results': {'type': 'integer', 'maximum': 50, 'minimum': 1, 'description': 'Max stations (default: 10)'}, 'site_elevation_m': {'type': 'number', 'description': 'Site elevation in metres. Strongly recommended when lat/lon are set: elevation difference predicts whether a station is representative about 3x better than distance does, and supplying it turns the recommendation from a distance guess into a measured call.'}, 'include_amy_extremes': {'type': 'boolean', 'description': 'When true and lat+lon are set, also returns the hottest / coldest / most-humid years on record (per ERA5, 1950–present). Useful for picking AMY basis years.'}, 'include_climate_deltas': {'type': 'boolean', 'description': 'When true with lat+lon+ssp+year, also returns the monthly CMIP6 delta-T per month and per variable. Lets agents reason about specific shifts before generating files.'}}}
generate_weather_file
Generate and deliver an EPW or DDY file. A paid tool — charges credits per call: 1 for a single file, 1 per scenario for a scenarios batch (max 10), 10 for a per-model CMIP6 ensemble. Requires auth (Bearer API key or OAuth). Credits come from a Forge pass ($9.99/wk = 2 non-expiring credits, or $99/yr) or a top-up pack; see the epwforge://catalog/pricing resource. No account? Buy a fixed-price guest bundle — see preview_forge_bundle. For free analysis without credits, use analyze_weather or chart_weather on a real published EPW URL.
输入模式
{'type': 'object', 'required': ['lat', 'lon'], 'properties': {'lat': {'type': 'number', 'maximum': 90, 'minimum': -90, 'description': 'Latitude, decimal degrees'}, 'lon': {'type': 'number', 'maximum': 180, 'minimum': -180, 'description': 'Longitude, decimal degrees'}, 'ssp': {'enum': ['ssp126', 'ssp245', 'ssp370', 'ssp585'], 'type': 'string', 'description': 'CMIP6 emission scenario. ssp370 is the recommended high-end for design; ssp585 (SSP5-8.5) is an opt-in extreme stress-test pathway (~4.4°C, low likelihood per IPCC AR6 / CMIP7) for worst-case analysis.'}, 'uhi': {'enum': ['none', 'suburban', 'urban', 'dense_urban'], 'type': 'string', 'description': 'Urban Heat Island preset'}, 'year': {'enum': [2030, 2035, 2040, 2045, 2050, 2060, 2070, 2080, 2090, 2100], 'type': 'integer', 'description': 'Future horizon'}, 'basis': {'enum': ['tmy', 'amy'], 'type': 'string', 'description': 'Weather file basis (default: tmy)'}, 'smoke': {'type': 'boolean', 'description': 'Enable wildfire smoke overlay'}, 'events': {'type': 'string', 'description': 'Comma-separated events. Valid: heatwave, coldsnap, hothumid, coldwindy. Pairs auto-compound (heat+humid, cold+wind).'}, 'format': {'enum': ['epw', 'ddy'], 'type': 'string', 'description': 'Output format (default: epw)'}, 'amy_year': {'type': 'integer', 'description': 'Year for AMY basis'}, 'ensemble': {'type': 'boolean', 'description': 'Generate a per-model CMIP6 ensemble (~20 EPWs, one per climate model). Costs 10 credits. Requires ssp + year.'}, 'intensity': {'type': 'string', 'description': 'Per-event "type:1-7" intensity (1-10 with stress_test=true). 5 = typical extreme, 7 = severe ~50-yr return.'}, 'scenarios': {'type': 'array', 'items': {'type': 'object', 'required': ['lat', 'lon'], 'properties': {'lat': {'type': 'number', 'maximum': 90, 'minimum': -90, 'description': 'Latitude, decimal degrees'}, 'lon': {'type': 'number', 'maximum': 180, 'minimum': -180, 'description': 'Longitude, decimal degrees'}, 'ssp': {'enum': ['ssp126', 'ssp245', 'ssp370', 'ssp585'], 'type': 'string', 'description': 'CMIP6 emission scenario. ssp370 is the recommended high-end for design; ssp585 (SSP5-8.5) is an opt-in extreme stress-test pathway (~4.4°C, low likelihood per IPCC AR6 / CMIP7) for worst-case analysis.'}, 'uhi': {'enum': ['none', 'suburban', 'urban', 'dense_urban'], 'type': 'string', 'description': 'Urban Heat Island preset'}, 'year': {'enum': [2030, 2035, 2040, 2045, 2050, 2060, 2070, 2080, 2090, 2100], 'type': 'integer', 'description': 'Future horizon'}, 'basis': {'enum': ['tmy', 'amy'], 'type': 'string', 'description': 'Weather file basis (default: tmy)'}, 'label': {'type': 'string'}, 'smoke': {'type': 'boolean', 'description': 'Enable wildfire smoke overlay'}, 'events': {'type': 'string', 'description': 'Comma-separated events. Valid: heatwave, coldsnap, hothumid, coldwindy. Pairs auto-compound (heat+humid, cold+wind).'}, 'amy_year': {'type': 'integer', 'description': 'Year for AMY basis'}, 'intensity': {'type': 'string', 'description': 'Per-event "type:1-7" intensity (1-10 with stress_test=true). 5 = typical extreme, 7 = severe ~50-yr return.'}, 'percentile': {'enum': [5, 10, 25, 50, 75, 90, 95], 'type': 'integer', 'description': 'Warming percentile (default: 50)'}, 'tmy_period': {'enum': ['full', '2011-2025', '2009-2023', '2007-2021', '2004-2018'], 'type': 'string', 'description': 'TMYx vintage. Default 2011-2025.'}, 'event_duration': {'type': 'integer', 'maximum': 30, 'minimum': 3, 'description': "Event length in days (3-30, default 14). **For stress-test scenarios use 14-21 days** — shorter durations don't capture sustained operational impact (charging schedules, occupancy patterns, equipment cycling). 7 days is too short for any design or resilience analysis. Use 7-10 only for transient short-duration events."}, 'intensity_auto': {'type': 'boolean', 'description': 'Auto-fill unspecified intensities from IPCC AR6 (default: true)'}, 'smoke_duration': {'type': 'integer', 'maximum': 30, 'minimum': 3, 'description': 'Smoke days (3-30, default: 7)'}, 'smoke_intensity': {'type': 'integer', 'maximum': 10, 'minimum': 1, 'description': 'Smoke severity 1-10 → peak AOD 0.1-6.0'}}}, 'maxItems': 10, 'description': 'Batch mode — array of configs, each generated in parallel. Same shape as the top-level config. When set, top-level config params are ignored. Costs 1 credit per scenario (up to 10).'}, 'percentile': {'enum': [5, 10, 25, 50, 75, 90, 95], 'type': 'integer', 'description': 'Warming percentile (default: 50)'}, 'tmy_period': {'enum': ['full', '2011-2025', '2009-2023', '2007-2021', '2004-2018'], 'type': 'string', 'description': 'TMYx vintage. Default 2011-2025.'}, 'include_ddy': {'type': 'boolean', 'description': 'When format=epw, also include the matching DDY in the response (single-file only).'}, 'stress_test': {'type': 'boolean', 'description': 'Unlock intensity 8-10. Default false.'}, 'event_duration': {'type': 'integer', 'maximum': 30, 'minimum': 3, 'description': "Event length in days (3-30, default 14). **For stress-test scenarios use 14-21 days** — shorter durations don't capture sustained operational impact (charging schedules, occupancy patterns, equipment cycling). 7 days is too short for any design or resilience analysis. Use 7-10 only for transient short-duration events."}, 'intensity_auto': {'type': 'boolean', 'description': 'Auto-fill unspecified intensities from IPCC AR6 (default: true)'}, 'smoke_duration': {'type': 'integer', 'maximum': 30, 'minimum': 3, 'description': 'Smoke days (3-30, default: 7)'}, 'smoke_intensity': {'type': 'integer', 'maximum': 10, 'minimum': 1, 'description': 'Smoke severity 1-10 → peak AOD 0.1-6.0'}}}
preview_forge_bundle
Preview a fixed-price Forge bundle for a location — the no-account way to buy weather files. Returns the exact scenario breakdown, file count, price, and a purchase link the user opens for guest checkout. Bundles: Carbon (10 scenarios), Titanium (30), Damascus (64); each scenario delivered as EPW + DDY + STAT + PVsyst. Free, no auth, creates no order.
输入模式
{'type': 'object', 'required': ['bundle_id'], 'properties': {'lat': {'type': 'number', 'description': 'Site latitude (optional — for a location-specific summary).'}, 'lon': {'type': 'number', 'description': 'Site longitude.'}, 'location': {'type': 'string', 'description': "Optional human label for the site, e.g. 'Boston, MA'."}, 'bundle_id': {'enum': ['carbon', 'titanium', 'damascus'], 'type': 'string', 'description': 'Which bundle to preview.'}}}
已添加
preview_forge_bundle
2026年9月17日 12:42
已添加
generate_weather_file
2026年9月17日 12:42
已添加
explore_design_conditions
2026年9月17日 12:42
已添加
chart_weather
2026年9月17日 12:42
已添加
analyze_weather
2026年9月17日 12:42
已添加
find_station
2026年9月17日 12:42