v0.9.1 — 35 tools, typed parameters, MCP SDK v2
The first release since v0.3.1, and a big one: the server grows from 20 tools to 35, every query becomes filterable, and the transport moves to MCP SDK v2.
Nearly all of the work in this release was contributed by @batubozkan, who developed this feature line in a fork and offered it upstream in #9 and #10. Thank you — this is a substantial body of well-tested work.
Highlights
Typed parameters on every query
Each query's .toml sidecar now declares [[params]] — type, default, min/max, enum — validated at startup and bound through psycopg named placeholders. Every one of the original 18 reports gained optional filters (car_name, days windows, limit, per-tool thresholds). Calling a tool with no arguments still returns the full classic report, so nothing breaks.
[[output]] declarations give each tool a typed per-column outputSchema, and results now come back as structured content.
12 new queries (20 → 35 tools)
Search & detail: search_drives, search_charging_sessions, get_drive_details, get_charging_curve, get_charging_costs
New analytics: get_battery_capacity_trend (real kWh capacity estimated from charge sessions rather than rated-range heuristics), get_vampire_drain (range lost while parked, excluding gaps containing a charge), get_charging_efficiency (kWh added vs drawn, AC/DC split), get_charging_by_geofence, get_soc_hygiene, get_period_comparison, get_drive_route
MCP Apps
show_charging_curve, show_battery_degradation, and show_drive_route render interactive, fully self-contained SVG charts in the conversation on Apps-capable clients, and degrade to plain rows everywhere else.
Platform
- MCP SDK v2 / spec 2026-07-28 — stateless HTTP, with the legacy
initializehandshake retained for older clients - Connection-pool fix — the per-session pool leaked connections until PostgreSQL ran out of slots under real streamable-HTTP traffic; one pool is now shared across sessions
REPORT_TIMEZONEso daily/weekly/monthly buckets follow local midnight instead of UTC/mcpand/mcp/are both served directly — no more 307 redirect, which broke proxies holding an immutable saved URLget_database_schema(table, refresh)for scoped lookups and on-demand refresh- Optional OpenTelemetry export
- Opt-in
set_charging_costbehindENABLE_CHARGING_WRITES(default off), scoped to a single column and backed by a column-scoped database grant
Three bug fixes that made v0.3.1 partly unusable
http --json-responsecrashed at startup. The published Docker image's defaultCMDpasses that flag, sodocker compose upand the GHCR:latestimage failed to boot at all.- Wheel builds failed on hatchling ≥ 1.19 because
queries/was included twice — which also broke the repo's own Dockerfile. get_battery_health_summarynow casts tonumericbeforeROUND, fixing the query on TeslaMate schemas where the range columns aredouble precision.
Tests
39 → 119, including every bundled query running against a seeded TeslaMate-shaped PostgreSQL via testcontainers.
Verification
Before merging, both pull requests were checked against a live TeslaMate database (~3.1M position rows): 119 tests pass, ruff check and format are clean, the Docker image builds and runs healthy, all 35 tools register, and sampled tool calls return real data over the MCP protocol.
Known issue
get_battery_health_summary and get_current_car_status use a correlated subquery over positions (WHERE p.date = (SELECT MAX(date) FROM positions p2 WHERE p2.car_id = p.car_id)) that does not complete on a large database — and the predefined-query path applies no statement_timeout, so the call hangs rather than erroring. Both are being fixed in the next release.
Upgrade note: this release requires mcp[cli]>=2.0.0. OpenTelemetry is currently a hard dependency.