spaceweather-mcp 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,29 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+
7
+ # Build artifacts
8
+ build/
9
+ dist/
10
+
11
+ # Virtual envs
12
+ .venv/
13
+ venv/
14
+
15
+ # Tooling caches
16
+ .pytest_cache/
17
+ .ruff_cache/
18
+ .mypy_cache/
19
+
20
+ # Local Claude Code settings
21
+ .claude/settings.local.json
22
+
23
+ # MCP registry publisher binary
24
+ mcp-publisher.exe
25
+ mcp-publisher.tar.gz
26
+
27
+ # OS
28
+ .DS_Store
29
+ Thumbs.db
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 matt
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,90 @@
1
+ Metadata-Version: 2.4
2
+ Name: spaceweather-mcp
3
+ Version: 0.1.0
4
+ Summary: Space-weather and geomagnetic conditions (NOAA SWPC planetary Kp, solar wind, storm scales, alerts, 27-day outlook) as a Model Context Protocol server.
5
+ Project-URL: Homepage, https://github.com/hoon1983/spaceweather-mcp
6
+ Project-URL: Repository, https://github.com/hoon1983/spaceweather-mcp
7
+ Project-URL: Issues, https://github.com/hoon1983/spaceweather-mcp/issues
8
+ Author: matt
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: aurora,geomagnetic,heliophysics,kp-index,mcp,model-context-protocol,noaa,solar-wind,space-weather,swpc
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Scientific/Engineering
21
+ Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
22
+ Classifier: Topic :: Scientific/Engineering :: Physics
23
+ Requires-Python: >=3.11
24
+ Requires-Dist: fastmcp>=3.0
25
+ Requires-Dist: httpx[http2]>=0.27
26
+ Requires-Dist: pydantic>=2.7
27
+ Description-Content-Type: text/markdown
28
+
29
+ # spaceweather-mcp
30
+
31
+ <!-- mcp-name: io.github.hoon1983/spaceweather-mcp -->
32
+
33
+ A Model Context Protocol server for **space weather and geomagnetic conditions** — solar flares, the solar wind, geomagnetic storms (Kp/Dst), radiation storms, sunspot regions, aurora forecasts, and a catalogued event history — so an AI agent can answer "what's the sun/space weather doing right now, and will I see aurora?" from authoritative data.
34
+
35
+ Sibling to [seismic-mcp](https://github.com/hoon1983/seismic-mcp): that one reconciles earthquakes across agencies; this one reports solar/geomagnetic conditions. They install side by side.
36
+
37
+ ## Status
38
+
39
+ **15 tools across 4 data sources — all live and verified.** Everything is U.S./NASA public domain except the Kyoto Dst index, which is non-commercial and clearly labeled (and kept segregated from the public-domain feeds).
40
+
41
+ ## Tools
42
+
43
+ **NOAA SWPC** (public domain)
44
+ | Tool | Returns |
45
+ | --- | --- |
46
+ | `get_conditions_now` | One-call snapshot: Kp, Bz/Bt, wind speed/density, G/S/R, storm flag, summary |
47
+ | `get_kp_index` | Observed planetary Kp series (~1 week) |
48
+ | `get_kp_forecast` | NOAA 3-day Kp forecast |
49
+ | `get_solar_wind` | L1 magnetic field + plasma (`window`: `1-day`/`7-day`) |
50
+ | `get_alerts` | Recent SWPC alerts/watches/warnings |
51
+ | `get_noaa_scales` | G/S/R scales for today + 3 days |
52
+ | `get_27day_outlook` | Daily F10.7 flux, Ap, largest Kp for 27 days |
53
+ | `get_solar_flares` | Recent GOES X-ray flares (C/M/X class events) |
54
+ | `get_radiation_storm` | Current proton flux + NOAA S-scale (radiation storm) |
55
+ | `get_solar_regions` | Today's sunspot regions + C/M/X flare probabilities |
56
+ | `get_aurora_forecast` | OVATION aurora probability (pass lat/lon for a local %) |
57
+
58
+ **NASA DONKI** (public domain) — `get_space_weather_events` (CME / GST / FLR / SEP / IPS / HSS event catalog)
59
+
60
+ **USGS Geomagnetism** (public domain) — `list_observatories`, `get_observatory` (magnetometer X/Y/Z/F)
61
+
62
+ **Kyoto WDC** (non-commercial) — `get_dst` (hourly disturbance storm-time index)
63
+
64
+ ## Run
65
+
66
+ ```bash
67
+ uv run spaceweather-mcp # stdio MCP server
68
+ uv run pytest # tests
69
+ ```
70
+
71
+ Add to `claude_desktop_config.json` (after publishing to PyPI):
72
+
73
+ ```json
74
+ { "mcpServers": { "spaceweather": { "command": "uvx", "args": ["spaceweather-mcp"] } } }
75
+ ```
76
+
77
+ ## Data sources, attribution & licensing
78
+
79
+ - **NOAA SWPC** (`services.swpc.noaa.gov`) — U.S. public domain. Credit NOAA SWPC.
80
+ - **NASA DONKI** via CCMC (`kauai.ccmc.gsfc.nasa.gov/DONKI`) — U.S. public domain (no API key needed). Credit NASA/CCMC DONKI.
81
+ - **USGS Geomagnetism** (`geomag.usgs.gov`) — U.S. public domain. Credit the U.S. Geological Survey. (Sourced directly from USGS, not via INTERMAGNET, to keep public-domain status.)
82
+ - **Kyoto WDC for Geomagnetism** — Dst index, **non-commercial use only**: acknowledge "WDC for Geomagnetism, Kyoto", cite the Dst DOI; real-time values are provisional. The non-commercial restriction is documented in the `get_dst` tool description and the `DstReading` schema (both surfaced to MCP clients), and this feed is kept separate from the public-domain ones.
83
+
84
+ > ⚠️ Only the Kyoto Dst feed is non-commercial. It is segregated, and its non-commercial terms are stated in the tool/schema docs the client sees, so a downstream commercial user is not silently bound by those terms.
85
+
86
+ **Deliberately not included:** INTERMAGNET and SILSO sunspot number (both CC BY-**NC** — would taint the otherwise commercially-usable server); JPL Horizons ephemeris (different domain). F10.7 is available via `get_27day_outlook`; GFZ Hp30/Hp60 high-cadence indices (CC BY 4.0) are a possible future add.
87
+
88
+ ## Safety
89
+
90
+ Informational only. **Not** for operational decisions affecting power grids, aviation, satellites, or human safety — consult official NOAA SWPC products for those. Real-time values are preliminary and routinely revised.
@@ -0,0 +1,62 @@
1
+ # spaceweather-mcp
2
+
3
+ <!-- mcp-name: io.github.hoon1983/spaceweather-mcp -->
4
+
5
+ A Model Context Protocol server for **space weather and geomagnetic conditions** — solar flares, the solar wind, geomagnetic storms (Kp/Dst), radiation storms, sunspot regions, aurora forecasts, and a catalogued event history — so an AI agent can answer "what's the sun/space weather doing right now, and will I see aurora?" from authoritative data.
6
+
7
+ Sibling to [seismic-mcp](https://github.com/hoon1983/seismic-mcp): that one reconciles earthquakes across agencies; this one reports solar/geomagnetic conditions. They install side by side.
8
+
9
+ ## Status
10
+
11
+ **15 tools across 4 data sources — all live and verified.** Everything is U.S./NASA public domain except the Kyoto Dst index, which is non-commercial and clearly labeled (and kept segregated from the public-domain feeds).
12
+
13
+ ## Tools
14
+
15
+ **NOAA SWPC** (public domain)
16
+ | Tool | Returns |
17
+ | --- | --- |
18
+ | `get_conditions_now` | One-call snapshot: Kp, Bz/Bt, wind speed/density, G/S/R, storm flag, summary |
19
+ | `get_kp_index` | Observed planetary Kp series (~1 week) |
20
+ | `get_kp_forecast` | NOAA 3-day Kp forecast |
21
+ | `get_solar_wind` | L1 magnetic field + plasma (`window`: `1-day`/`7-day`) |
22
+ | `get_alerts` | Recent SWPC alerts/watches/warnings |
23
+ | `get_noaa_scales` | G/S/R scales for today + 3 days |
24
+ | `get_27day_outlook` | Daily F10.7 flux, Ap, largest Kp for 27 days |
25
+ | `get_solar_flares` | Recent GOES X-ray flares (C/M/X class events) |
26
+ | `get_radiation_storm` | Current proton flux + NOAA S-scale (radiation storm) |
27
+ | `get_solar_regions` | Today's sunspot regions + C/M/X flare probabilities |
28
+ | `get_aurora_forecast` | OVATION aurora probability (pass lat/lon for a local %) |
29
+
30
+ **NASA DONKI** (public domain) — `get_space_weather_events` (CME / GST / FLR / SEP / IPS / HSS event catalog)
31
+
32
+ **USGS Geomagnetism** (public domain) — `list_observatories`, `get_observatory` (magnetometer X/Y/Z/F)
33
+
34
+ **Kyoto WDC** (non-commercial) — `get_dst` (hourly disturbance storm-time index)
35
+
36
+ ## Run
37
+
38
+ ```bash
39
+ uv run spaceweather-mcp # stdio MCP server
40
+ uv run pytest # tests
41
+ ```
42
+
43
+ Add to `claude_desktop_config.json` (after publishing to PyPI):
44
+
45
+ ```json
46
+ { "mcpServers": { "spaceweather": { "command": "uvx", "args": ["spaceweather-mcp"] } } }
47
+ ```
48
+
49
+ ## Data sources, attribution & licensing
50
+
51
+ - **NOAA SWPC** (`services.swpc.noaa.gov`) — U.S. public domain. Credit NOAA SWPC.
52
+ - **NASA DONKI** via CCMC (`kauai.ccmc.gsfc.nasa.gov/DONKI`) — U.S. public domain (no API key needed). Credit NASA/CCMC DONKI.
53
+ - **USGS Geomagnetism** (`geomag.usgs.gov`) — U.S. public domain. Credit the U.S. Geological Survey. (Sourced directly from USGS, not via INTERMAGNET, to keep public-domain status.)
54
+ - **Kyoto WDC for Geomagnetism** — Dst index, **non-commercial use only**: acknowledge "WDC for Geomagnetism, Kyoto", cite the Dst DOI; real-time values are provisional. The non-commercial restriction is documented in the `get_dst` tool description and the `DstReading` schema (both surfaced to MCP clients), and this feed is kept separate from the public-domain ones.
55
+
56
+ > ⚠️ Only the Kyoto Dst feed is non-commercial. It is segregated, and its non-commercial terms are stated in the tool/schema docs the client sees, so a downstream commercial user is not silently bound by those terms.
57
+
58
+ **Deliberately not included:** INTERMAGNET and SILSO sunspot number (both CC BY-**NC** — would taint the otherwise commercially-usable server); JPL Horizons ephemeris (different domain). F10.7 is available via `get_27day_outlook`; GFZ Hp30/Hp60 high-cadence indices (CC BY 4.0) are a possible future add.
59
+
60
+ ## Safety
61
+
62
+ Informational only. **Not** for operational decisions affecting power grids, aviation, satellites, or human safety — consult official NOAA SWPC products for those. Real-time values are preliminary and routinely revised.
@@ -0,0 +1,64 @@
1
+ [project]
2
+ name = "spaceweather-mcp"
3
+ version = "0.1.0"
4
+ description = "Space-weather and geomagnetic conditions (NOAA SWPC planetary Kp, solar wind, storm scales, alerts, 27-day outlook) as a Model Context Protocol server."
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ authors = [{ name = "matt" }]
8
+ license = { text = "MIT" }
9
+ keywords = [
10
+ "mcp",
11
+ "model-context-protocol",
12
+ "space-weather",
13
+ "geomagnetic",
14
+ "kp-index",
15
+ "solar-wind",
16
+ "aurora",
17
+ "noaa",
18
+ "swpc",
19
+ "heliophysics",
20
+ ]
21
+ classifiers = [
22
+ "Development Status :: 3 - Alpha",
23
+ "Environment :: Console",
24
+ "Intended Audience :: Science/Research",
25
+ "Operating System :: OS Independent",
26
+ "Programming Language :: Python :: 3",
27
+ "Programming Language :: Python :: 3.11",
28
+ "Programming Language :: Python :: 3.12",
29
+ "Programming Language :: Python :: 3.13",
30
+ "Topic :: Scientific/Engineering",
31
+ "Topic :: Scientific/Engineering :: Physics",
32
+ "Topic :: Scientific/Engineering :: Atmospheric Science",
33
+ ]
34
+ dependencies = [
35
+ "fastmcp>=3.0",
36
+ "httpx[http2]>=0.27",
37
+ "pydantic>=2.7",
38
+ ]
39
+
40
+ [project.scripts]
41
+ spaceweather-mcp = "spaceweather_mcp.server:main"
42
+
43
+ [project.urls]
44
+ Homepage = "https://github.com/hoon1983/spaceweather-mcp"
45
+ Repository = "https://github.com/hoon1983/spaceweather-mcp"
46
+ Issues = "https://github.com/hoon1983/spaceweather-mcp/issues"
47
+
48
+ [dependency-groups]
49
+ dev = [
50
+ "pytest>=8",
51
+ "pytest-asyncio>=0.23",
52
+ ]
53
+
54
+ [build-system]
55
+ requires = ["hatchling"]
56
+ build-backend = "hatchling.build"
57
+
58
+ [tool.hatch.build.targets.wheel]
59
+ packages = ["src/spaceweather_mcp"]
60
+
61
+ [tool.pytest.ini_options]
62
+ testpaths = ["tests"]
63
+ asyncio_mode = "auto"
64
+ filterwarnings = ["ignore::DeprecationWarning"]
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.hoon1983/spaceweather-mcp",
4
+ "description": "Space weather and geomagnetic conditions (NOAA SWPC, NASA DONKI, USGS Geomag, Kyoto Dst) as a Model Context Protocol server.",
5
+ "repository": {
6
+ "url": "https://github.com/hoon1983/spaceweather-mcp",
7
+ "source": "github"
8
+ },
9
+ "version": "0.1.0",
10
+ "packages": [
11
+ {
12
+ "registryType": "pypi",
13
+ "identifier": "spaceweather-mcp",
14
+ "version": "0.1.0",
15
+ "transport": {
16
+ "type": "stdio"
17
+ }
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,3 @@
1
+ """spaceweather-mcp: space-weather and geomagnetic conditions as an MCP server."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,51 @@
1
+ """Tiny async TTL cache with in-flight de-duplication.
2
+
3
+ SWPC products update every 1-5 minutes; a short TTL turns a burst of tool
4
+ calls (and a UI poll loop) into a single upstream fetch. The per-key lock
5
+ collapses concurrent misses so we never fire the same request twice at once.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import asyncio
11
+ import time
12
+ from typing import Awaitable, Callable, TypeVar
13
+
14
+ T = TypeVar("T")
15
+
16
+
17
+ class TTLCache:
18
+ def __init__(self, ttl_seconds: float = 60.0) -> None:
19
+ self.ttl = ttl_seconds
20
+ self._store: dict[str, tuple[float, object]] = {}
21
+ self._locks: dict[str, asyncio.Lock] = {}
22
+
23
+ async def get_or_fetch(self, key: str, fetch: Callable[[], Awaitable[T]]) -> T:
24
+ hit = self._store.get(key)
25
+ if hit is not None and (time.monotonic() - hit[0]) < self.ttl:
26
+ return hit[1] # type: ignore[return-value]
27
+
28
+ lock = self._locks.setdefault(key, asyncio.Lock())
29
+ async with lock:
30
+ # Re-check: another coroutine may have filled it while we waited.
31
+ hit = self._store.get(key)
32
+ if hit is not None and (time.monotonic() - hit[0]) < self.ttl:
33
+ return hit[1] # type: ignore[return-value]
34
+ value = await fetch()
35
+ self._store[key] = (time.monotonic(), value)
36
+ self._prune()
37
+ return value
38
+
39
+ def _prune(self) -> None:
40
+ """Drop expired entries (and their now-idle locks) so the cache stays
41
+ bounded even when callers key on ever-changing URLs (time windows)."""
42
+ now = time.monotonic()
43
+ for k in [k for k, (ts, _) in self._store.items() if (now - ts) >= self.ttl]:
44
+ self._store.pop(k, None)
45
+ lk = self._locks.get(k)
46
+ if lk is not None and not lk.locked():
47
+ self._locks.pop(k, None)
48
+
49
+ def clear(self) -> None:
50
+ self._store.clear()
51
+ self._locks.clear()
@@ -0,0 +1,210 @@
1
+ """Canonical schemas for space-weather data returned by the MCP tools.
2
+
3
+ All times are timezone-aware UTC. Missing numeric values are ``None`` (never
4
+ NaN) so the output is always valid JSON.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from datetime import datetime
10
+ from typing import Optional
11
+
12
+ from pydantic import BaseModel, Field
13
+
14
+
15
+ class KpReading(BaseModel):
16
+ """One observed planetary K-index sample (3-hour cadence, NOAA SWPC)."""
17
+
18
+ time: datetime
19
+ kp: float = Field(..., description="Planetary K-index, 0-9. >=5 is geomagnetic storm level.")
20
+ a_running: Optional[float] = Field(None, description="Running estimate of the daily Ap index.")
21
+ station_count: Optional[int] = None
22
+
23
+
24
+ class KpForecastPoint(BaseModel):
25
+ time: datetime
26
+ kp: float
27
+ observed: str = Field("predicted", description="'observed', 'estimated', or 'predicted'.")
28
+
29
+
30
+ class SolarWindMag(BaseModel):
31
+ """Interplanetary magnetic field, GSM coordinates (nT)."""
32
+
33
+ time: datetime
34
+ bx: Optional[float] = None
35
+ by: Optional[float] = None
36
+ bz: Optional[float] = Field(None, description="Southward (negative) Bz couples energy into the magnetosphere.")
37
+ bt: Optional[float] = Field(None, description="Total field magnitude.")
38
+
39
+
40
+ class SolarWindPlasma(BaseModel):
41
+ time: datetime
42
+ density: Optional[float] = Field(None, description="Proton density, particles/cm^3.")
43
+ speed: Optional[float] = Field(None, description="Bulk solar wind speed, km/s.")
44
+ temperature: Optional[float] = Field(None, description="Kelvin.")
45
+
46
+
47
+ class SolarWind(BaseModel):
48
+ window: str
49
+ mag: list[SolarWindMag]
50
+ plasma: list[SolarWindPlasma]
51
+
52
+
53
+ class Alert(BaseModel):
54
+ """A NOAA SWPC alert/watch/warning bulletin."""
55
+
56
+ product_id: str
57
+ issued: datetime
58
+ message: str
59
+
60
+
61
+ class ScaleValue(BaseModel):
62
+ scale: Optional[int] = Field(None, description="0-5 on the NOAA scale (0 = none).")
63
+ text: Optional[str] = Field(None, description="e.g. 'Minor', 'Moderate', 'Strong'.")
64
+
65
+
66
+ class ScaleDay(BaseModel):
67
+ index: int = Field(..., description="0 = current/today, 1-3 = following days.")
68
+ date_stamp: Optional[str] = None
69
+ g: Optional[ScaleValue] = Field(None, description="G - geomagnetic storm.")
70
+ s: Optional[ScaleValue] = Field(None, description="S - solar radiation storm.")
71
+ r: Optional[ScaleValue] = Field(None, description="R - radio blackout.")
72
+
73
+
74
+ class NoaaScales(BaseModel):
75
+ days: list[ScaleDay]
76
+
77
+
78
+ class OutlookRow(BaseModel):
79
+ date: str
80
+ radio_flux_107: int = Field(..., description="F10.7 cm solar radio flux (sfu).")
81
+ planetary_a: int = Field(..., description="Predicted planetary Ap index.")
82
+ largest_kp: int = Field(..., description="Largest predicted Kp for the day.")
83
+
84
+
85
+ class Outlook(BaseModel):
86
+ issued: str
87
+ rows: list[OutlookRow]
88
+
89
+
90
+ class ConditionsNow(BaseModel):
91
+ """A single-call snapshot of current space-weather conditions."""
92
+
93
+ kp: Optional[float] = None
94
+ kp_time: Optional[datetime] = None
95
+ bz_nt: Optional[float] = None
96
+ bt_nt: Optional[float] = None
97
+ solar_wind_speed_kms: Optional[float] = None
98
+ density_per_cc: Optional[float] = None
99
+ scale_g: Optional[ScaleValue] = None
100
+ scale_s: Optional[ScaleValue] = None
101
+ scale_r: Optional[ScaleValue] = None
102
+ geomagnetic_storm: bool = Field(False, description="True when current Kp >= 5.")
103
+ summary: str = Field("", description="Human-readable one-line status.")
104
+
105
+
106
+ class Observatory(BaseModel):
107
+ """A magnetic observatory whose data is queryable via get_observatory."""
108
+
109
+ id: str = Field(..., description="3-letter IAGA code, e.g. 'BOU', 'HON'.")
110
+ name: str
111
+ latitude: float
112
+ longitude: float
113
+ network: str = "USGS"
114
+
115
+
116
+ class ObservatorySeries(BaseModel):
117
+ """Ground magnetometer time series for one observatory (USGS Geomagnetism)."""
118
+
119
+ station: str
120
+ name: Optional[str] = None
121
+ latitude: Optional[float] = None
122
+ longitude: Optional[float] = None
123
+ sampling_period_s: int
124
+ data_type: str = Field(..., description="variation | adjusted | quasi-definitive | definitive")
125
+ times: list[datetime]
126
+ values: dict[str, list[Optional[float]]] = Field(
127
+ default_factory=dict, description="Per-element series (nT), e.g. {'X': [...], 'Y': [...]}."
128
+ )
129
+ latest: dict[str, Optional[float]] = Field(
130
+ default_factory=dict, description="Most recent finite value per element (nT)."
131
+ )
132
+
133
+
134
+ class DstReading(BaseModel):
135
+ """One hourly Dst (disturbance storm-time) index value, in nT (Kyoto WDC).
136
+
137
+ Dst measures the ring-current depression during geomagnetic storms: roughly
138
+ > -30 quiet, -30..-50 unsettled, -50..-100 moderate storm, -100..-250 intense,
139
+ < -250 great storm.
140
+
141
+ NON-COMMERCIAL data: cite "WDC for Geomagnetism, Kyoto" and the Dst DOI;
142
+ real-time values are provisional ("quicklook") and subject to revision.
143
+ """
144
+
145
+ time: datetime
146
+ dst_nt: int
147
+
148
+
149
+ class SolarFlare(BaseModel):
150
+ """One GOES X-ray flare event (NOAA SWPC)."""
151
+
152
+ begin_time: Optional[datetime] = None
153
+ begin_class: Optional[str] = None
154
+ max_time: Optional[datetime] = None
155
+ max_class: Optional[str] = Field(None, description="Peak GOES class, e.g. 'C3.2', 'M2.1', 'X1.0'.")
156
+ max_flux: Optional[float] = Field(None, description="Peak long-channel flux, W/m^2.")
157
+ end_time: Optional[datetime] = None
158
+ satellite: Optional[int] = None
159
+
160
+
161
+ class RadiationStatus(BaseModel):
162
+ """Current solar radiation (energetic proton) environment, NOAA SWPC GOES."""
163
+
164
+ time: Optional[datetime] = None
165
+ flux_by_energy: dict[str, Optional[float]] = Field(
166
+ default_factory=dict, description="Latest integral proton flux (pfu) per energy threshold, e.g. {'>=10 MeV': 0.3}."
167
+ )
168
+ s_scale: int = Field(0, description="NOAA S (radiation storm) scale 0-5, from the >=10 MeV flux.")
169
+ s_text: str = ""
170
+ radiation_storm: bool = Field(False, description="True when S >= 1 (>=10 MeV flux >= 10 pfu).")
171
+
172
+
173
+ class SolarRegion(BaseModel):
174
+ """An active sunspot region with flare probabilities (NOAA SWPC)."""
175
+
176
+ region: Optional[int] = None
177
+ observed_date: Optional[str] = None
178
+ location: Optional[str] = None
179
+ latitude: Optional[float] = None
180
+ longitude: Optional[float] = None
181
+ area: Optional[int] = None
182
+ number_spots: Optional[int] = None
183
+ spot_class: Optional[str] = None
184
+ mag_class: Optional[str] = None
185
+ c_flare_probability: Optional[int] = None
186
+ m_flare_probability: Optional[int] = None
187
+ x_flare_probability: Optional[int] = None
188
+ proton_probability: Optional[int] = None
189
+
190
+
191
+ class AuroraForecast(BaseModel):
192
+ """OVATION short-term auroral-oval forecast (NOAA SWPC)."""
193
+
194
+ observation_time: Optional[datetime] = None
195
+ forecast_time: Optional[datetime] = None
196
+ latitude: Optional[float] = None
197
+ longitude: Optional[float] = None
198
+ aurora_probability: Optional[int] = Field(None, description="Auroral activity probability (%) at the requested point.")
199
+ global_max_probability: Optional[int] = Field(None, description="Peak probability anywhere on the oval.")
200
+ note: str = ""
201
+
202
+
203
+ class SpaceWeatherEvent(BaseModel):
204
+ """A catalogued space-weather event from NASA DONKI (CME/GST/FLR/SEP/IPS/HSS)."""
205
+
206
+ event_type: str
207
+ event_id: str
208
+ time: Optional[datetime] = None
209
+ summary: str = Field("", description="Type-specific highlight, e.g. 'max Kp 6.33' or 'class M2.1'.")
210
+ link: Optional[str] = Field(None, description="DONKI detail page for the full record.")