Repository navigation
Expose Core measurement-quality reasons and energy provenance through MCP diagnostics #42
Description
Problem
FTW Cloud's MCP connector can read live values and historical series, but it does not expose the diagnostic reasons and underlying energy/measurement provenance needed to troubleshoot a house-load failure. This forced the operator to use SSH, Docker and a direct LAN API request despite having an authorized FTW1 MCP connection with ftw.diag.run scope.
Real-world case on Core v0.152.1-beta.1, with the new Docker 0.x deployment. Related Core issue: srcfl/ftw#1744.
What MCP exposed
status: freshgrid_w,battery_w,pv_w,ev_wand driver/source freshness, but noload_wfield/value and no household-load failure reason.health_get: meter live and 3 drivers OK / 1 offline, but no indication of which source invalidated the house balance.history_query:load_w = nullin every bucket checked, without the reason for the gap. This is aggregated history rather than Core's energy ledger with source, coverage and quality.drivers_statusandconfig_getare useful, but alone cannot explain theload_estimatefailure.diag_runandevents_listare listed ininternal/mcp/tools.gowith descriptions explicitly stating they are not yet served by the box (currentlyE_UNKNOWN_OP). An authorized diagnostic scope therefore does not provide the promised checks.
What the local FTW Core API exposed
The same box answered the read-only GET /api/status over LAN:
grid_w: -109.96
bat_w: -3874
load_w: null
history_reason: missing:easee:ev
load_estimate:
watts: null
energy_wh: null
method: reported_energy_balance_v3
reason: missing:easee:ev
Further read-only configuration inspection showed:
drivers:
- name: easee_cloud
lua: drivers/easee_cloud.lua
loadpoints:
- id: Laddbox
driver_name: easeeThis reveals a dangling charger binding (easee vs easee_cloud) rather than a site-meter issue. The operator had previously tested both Zap and Pixii as site meters without resolving it. The mismatch and runtime error are verified; relinking the loadpoint was suggested, but the fix outcome has not yet been verified.
Why this matters
The MCP response told us that house-load history was unavailable, not why. We could not distinguish missing:easee:ev from timing, staleness, skew or invalid-balance causes until the owner executed a terminal command. The phone app's instantaneous balance and the web UI's qualified interval estimate also differed, making this diagnostic metadata essential.
Requested change
- Add a read-only, scoped diagnostic view/tool of the current Core measurement quality, preferably reusing Core's existing
/api/statussemantics. Exposeload_w,history_quality,history_reasonandload_estimatemetadata (watts,reason,method,from_ms,to_ms,end_age_ms,timing_basis,energy_basis, etc.), with explicit null/unknown states. - Provide a source/flow-level reason and a safe driver↔loadpoint association where possible, so
missing:<driver>:evcan be diagnosed without manual LAN access. Respect redaction for addresses, secrets, credentials, device serials, and personal identity. - Expose or provide safe read-only equivalents for
/api/energy/history(Wh, quality, provenance, sample counts) and/api/series//api/series/catalog(raw observations and timestamps), so missing energy or bad time coverage can be traced rather than inferred from aggregatedhistory_query. - Implement and validate
diag_run(andevents_listwhen ready), or do not present unavailable operations as functional diagnostics; return a clear capability/unsupported response. - Keep the connector least-privilege: authorized diagnostic scope, explicit allowlist and response sanitization, read-only only; do not offer arbitrary HTTP passthrough, configuration mutation, control or credentials.
- Add end-to-end tests for a missing/dangling EV flow and for interval-quality failures. Confirm that MCP exposes the same reason as local Core while not leaking restricted data.
Ownership / implementation pointers
- Cloud/MCP:
srcfl/ftw-cloud/internal/mcp/tools.go(the exposed MCP tool list and constrained live/history reads). - Core:
srcfl/ftw/go/internal/api/api_history_quality.gocomputeshistory_reasonandload_estimate, whilego/internal/api/api_agent_catalog.goenumerates available read-only diagnostic routes, including status, energy history, and original series. Coordinate through the existing scoped agent protocol rather than bypassing it.
This is a tooling/observability request distinct from srcfl/ftw#1744, the underlying dangling-loadpoint configuration issue.
Activity
frahlg commentedon Oct 19, 2026
Partly addressed by #41 and srcfl/ftw#1743, both merged today.
The full technical MCP profile already has
api_catalogandapi_readfor Core's listed read-only routes, including/api/status,/api/energy/historyand/api/series. #41 directs troubleshooting through that path, explains why redactedconfig_getcannot prove an exact charger binding, and marks HTTP failures from diagnostic reads as MCP errors while preserving the path, status and response. Core #1743 adds exact charger-binding evidence to its diagnostic catalogue. Tests cover preservation of the binding names and error handling for a refused read.I am keeping this issue open. #41 does not add a sanitized measurement-quality view to the public profile, implement
diag_run/events_list, or add the requested end-to-end missing-flow and interval-quality tests. The public profile still excludesapi_catalog/api_read; full technical diagnostics deliberately retain technical identifiers, so they are not the restricted view requested here.The actual client profile, grant, running versions and failed call still need checking before calling the reported access problem resolved. These merges are not evidence of a Cloud deployment, a Core release, or recovery on the affected box.
frahlg commentedon Oct 19, 2026
Completed in #41 and #43, both now merged, with srcfl/ftw#1746 as the paired Core change.
The new
measurement_diagnosticstool is available in both MCP profiles under the existing diagnostic grant. Its fixed read-only views expose measurement reasons and null states, safe charger associations, energy quality/provenance/sample counts, and stored series with their timestamps and resolution. Opaque selections replace names and hardware identifiers; private fields stay out. It accepts no arbitrary HTTP path, configuration write or control.Unavailable
diag_runandevents_listoperations no longer appear in tool discovery. Cached calls return an explicit unsupported MCP error without contacting Core. HTTP failures and incomplete replies also return errors rather than diagnostic success.Full vet/race/dev-tag/import checks and CI passed. End-to-end tests exercise OAuth, TLS and Noise through real Core read handlers and SQLite: missing/disabled EV reasons match Core, explicit repair restores live household load, an incomplete interval remains unknown, and energy provenance plus stored series survive the MCP path. Tests also cover denied grants, unsafe arguments, private-field removal and unsupported/error responses.
Closing the implementation request. No Cloud deployment, Core release or box update was performed. The reporter's actual client profile, grant and runtime access have not been verified by these tests; a remaining live access failure needs its exact call and running versions.