Diagnosis
The solar__solar_conditions MCP tool (and dependent solar_band_outlook) consistently returns nulls:
{"sfi":null,"sfi_timestamp":null,"kp":null,"kp_timestamp":null,"noaa_r_scale":"0","noaa_s_scale":"0","noaa_g_scale":"0"}
While other solar tools (solar_alerts, solar_wind, solar_xray, solar_forecast) succeed with live data.
Root Cause (cite-by-grep in client.py)
In src/solar_mcp/client.py:conditions() (called by the tool):
-
SFI fetch: self._get_json(f"{_SWPC}/products/summary/10cm-flux.json")
- Current response (verified live):
[{"flux":128,"time_tag":"..."}] (list of dicts)
- Code assumption:
if isinstance(sfi_data, dict): ... .get("Flux") or .get("flux") (and TimeStamp). Skips for list → sfi=None.
-
Kp fetch: self._get_json(f"{_SWPC}/products/noaa-planetary-k-index.json")
- Current: list of dicts
[{"time_tag":"...","Kp":0.67,...}, ...]
- Code assumption:
if isinstance(latest, list) and len(latest)>=2: float(latest[1]) (legacy list-of-lists). Fails → kp=None.
-
Scales parse partially succeeds but yields raw "0" (instead of "R0" etc.).
No exception raised (graceful degradation), so server.py:solar_conditions returns the partial null dict (not {"error":...}).
_get_json + caching + or {} / or [] hid the shape mismatch.
Other tools use different endpoints (still compatible).
Mocks were also in legacy format.
This matches the observed behavior in fleet (e.g., Grok solar brief calls).
Evidence
- Direct
curl + python inspection of live SWPC endpoints (2026-06-15).
solar__get_version_info: solar-mcp 0.2.0 / noaa-swpc-v1.
- Live repro via MCP tool calls + fallback web/NOAA pages.
- Code review of
client.py:125-187 (and band_outlook:411-416 which bails on nulls).
The endpoints were updated post-0.2.0 release (code written ~May 2026 for older shapes).
Solution (implemented on branch)
- Made
conditions() parsing robust: handles current list-of-dicts + legacy formats for both SFI and Kp.
- Normalize scales
"0" → "R0"/"S0"/"G0" for consistency with tests/docs.
- Updated
_MOCK_* data to current shapes (unit tests now exercise new paths).
- Added to Unreleased in CHANGELOG.md.
- Verified: live
client.conditions() now returns real SFI=128, Kp=0.67 (latest), normalized scales, band_outlook.
- (Editable install in workspace picks up src via .pth; MCP calls succeed.)
Branch: fix/solar-conditions-parsing
PR will follow.
Recommended follow-ups
- Run full L3 live tests:
pytest tests/test_live.py --live
- Consider defensive
{"error": ...} if parse still fails.
- Bump
__spec_version__ on next release if more drifts.
- Monitor these two endpoints (NOAA JSON shapes not guaranteed stable).
- Fleet: re-deploy solar-mcp 0.2.1+ across nodes (M3, 9975WX, etc.) once tagged.
This restores solar_conditions for the observability plane / HF propagation use (cross-ref ionis-mcp, observability-plane.md, etc.).
Fixes the nulls seen in recent solar brief queries.
Diagnosis
The
solar__solar_conditionsMCP tool (and dependentsolar_band_outlook) consistently returns nulls:{"sfi":null,"sfi_timestamp":null,"kp":null,"kp_timestamp":null,"noaa_r_scale":"0","noaa_s_scale":"0","noaa_g_scale":"0"}While other solar tools (
solar_alerts,solar_wind,solar_xray,solar_forecast) succeed with live data.Root Cause (cite-by-grep in client.py)
In
src/solar_mcp/client.py:conditions()(called by the tool):SFI fetch:
self._get_json(f"{_SWPC}/products/summary/10cm-flux.json")[{"flux":128,"time_tag":"..."}](list of dicts)if isinstance(sfi_data, dict): ... .get("Flux") or .get("flux")(and TimeStamp). Skips for list →sfi=None.Kp fetch:
self._get_json(f"{_SWPC}/products/noaa-planetary-k-index.json")[{"time_tag":"...","Kp":0.67,...}, ...]if isinstance(latest, list) and len(latest)>=2: float(latest[1])(legacy list-of-lists). Fails →kp=None.Scales parse partially succeeds but yields raw
"0"(instead of"R0"etc.).No exception raised (graceful degradation), so
server.py:solar_conditionsreturns the partial null dict (not{"error":...})._get_json+ caching +or {}/or []hid the shape mismatch.Other tools use different endpoints (still compatible).
Mocks were also in legacy format.
This matches the observed behavior in fleet (e.g., Grok solar brief calls).
Evidence
curl+ python inspection of live SWPC endpoints (2026-06-15).solar__get_version_info: solar-mcp 0.2.0 / noaa-swpc-v1.client.py:125-187(and band_outlook:411-416 which bails on nulls).The endpoints were updated post-0.2.0 release (code written ~May 2026 for older shapes).
Solution (implemented on branch)
conditions()parsing robust: handles current list-of-dicts + legacy formats for both SFI and Kp."0"→"R0"/"S0"/"G0"for consistency with tests/docs._MOCK_*data to current shapes (unit tests now exercise new paths).client.conditions()now returns real SFI=128, Kp=0.67 (latest), normalized scales, band_outlook.Branch:
fix/solar-conditions-parsingPR will follow.
Recommended follow-ups
pytest tests/test_live.py --live{"error": ...}if parse still fails.__spec_version__on next release if more drifts.This restores solar_conditions for the observability plane / HF propagation use (cross-ref ionis-mcp, observability-plane.md, etc.).
Fixes the nulls seen in recent solar brief queries.