CT

cobanov/teslamate-mcp

开发工具
141 stars 0 forks 质量 61 趋势 45

A Model Context Protocol (MCP) server that provides access to your TeslaMate database, allowing AI assistants to query Tesla vehicle data and analytics.

概览

Connect your AI assistant to your TeslaMate data. This is a Model Context Protocol (MCP) server. It reads your TeslaMate PostgreSQL database. It gives MCP clients (Claude Desktop, Cursor, and others) 57 tools, 11 prompts, and interactive charts. · Tool reference · Configuration · Deployment - "Is my battery really degrading?" — the server estimates usable capacity in kWh from your charging sessions. - "How much range do I lose while parked?" — the server finds vampire drain between drives. - "Show the route of my longest drive." — the server returns the GPS track, with an interactive map on chart-capable clients. - "Compare my driving this month with last month." — one call returns both windows, per metric. - "Can I reach Ankara (450 km) at 5°C without charging?" — the server estimates the arrival battery % from your own drives at that temperature. - "Why isn't my car sleeping?" — the server reads TeslaMate's state log and lists the periods the car stayed awake while parked.

README

What you can ask

  • “Is my battery really degrading?” — the server estimates usable capacity in kWh from your charging sessions.
  • “How much range do I lose while parked?” — the server finds vampire drain between drives.
  • “Show the route of my longest drive.” — the server returns the GPS track, with an interactive map on chart-capable clients.
  • “Compare my driving this month with last month.” — one call returns both windows, per metric.
  • “Can I reach Ankara (450 km) at 5°C without charging?” — the server estimates the arrival battery % from your own drives at that temperature.
  • “Why isn’t my car sleeping?” — the server reads TeslaMate’s state log and lists the periods the car stayed awake while parked.
  • “What did my car do on Saturday?” — one call returns the drives, charges, and parked time in order.

Highlights

  • 47 SQL report tools. Battery capacity and degradation, sleep and state history, a timeline of each day, trips, range estimates, fast-charging speeds, charging costs (with estimates for missing ones) and fuel savings, elevation, vampire drain, geofences, driving patterns, routes, and search tools for drives and charging sessions.
  • 8 interactive charts (MCP Apps). Charging curves (one session, or several overlaid), battery degradation, drive and trip maps with elevation profiles, a monthly or yearly activity dashboard, a map of visited places, and consumption against temperature. On clients without chart support, the same tools return plain rows.
  • Guidance for the assistant. MCP instructions and 11 prompts map questions to tools, and get_unit_preferences lets the assistant answer in the units set in TeslaMate.
  • Typed inputs and outputs. Each report tool declares its parameters and result columns in a .toml file. The server validates the declarations at startup. Parameters bind as SQL placeholders, never as string concatenation.
  • Safe custom SQL. run_sql runs your SELECT inside a PostgreSQL READ ONLY transaction, with timeouts and a row cap. The transaction always rolls back.
  • Optional cost writes, with confirmation. One opt-in tool writes charging costs. A column-scoped database grant limits what it can touch. Clients with MCP elicitation show a confirmation dialog first.
  • Local-time reports. Set REPORT_TIMEZONE and daily, weekly, and monthly buckets follow your local midnight.
  • Two transports. Run teslamate-mcp stdio for local clients. Run teslamate-mcp http for remote clients, with bearer-token auth and a /health probe.

Requirements

  • TeslaMate with its PostgreSQL database.
  • Python 3.11+ for a local install, or Docker for a server install.

Quick start — local (stdio)

  1. Install:

    git clone https://github.com/cobanov/teslamate-mcp.git
    cd teslamate-mcp
    cp env.example .env      # set DATABASE_URL
    uv sync
    
  2. Add the server to your MCP client. Example for Claude Desktop or Cursor:

    {
      "mcpServers": {
        "teslamate": {
          "command": "uv",
          "args": ["--directory", "/path/to/teslamate-mcp", "run", "teslamate-mcp", "stdio"]
        }
      }
    }
    

Quick start — Docker

cp env.example .env          # set DATABASE_URL, and set AUTH_TOKEN for remote use
docker compose up -d

The MCP endpoint is http://localhost:8888/mcp. The health probe is http://localhost:8888/health. It runs a SELECT 1 against the database and returns 503 when the database is unreachable.

A multi-arch image (linux/amd64, linux/arm64) is published to GHCR on each release:

docker run --rm -e DATABASE_URL=... -p 8888:8888 ghcr.io/cobanov/teslamate-mcp:latest

Deploy on Unraid, behind Cloudflare

You can reach this server from claude.ai, Claude Desktop, and mobile — with OAuth login and with no open ports on your home network.

The Unraid + Cloudflare deployment guide shows the full path:

  1. Run the container on Unraid with the included Community Apps template.
  2. Publish it through a Cloudflare Tunnel. No inbound firewall rules are necessary.
  3. Put a Cloudflare Zero Trust MCP Server Portal in front. The portal handles OAuth for Claude clients and sends the bearer token upstream.

The guide includes the exact dashboard fields, verification commands for each phase, and a troubleshooting table.

The portal rewrites ui:// resource URIs, so the interactive charts (show_* tools) do not render through it. To get them, connect Claude through Cloudflare Access directly. The guide’s direct connection section shows how.

Tools

Each report tool accepts optional filters: car_name everywhere, plus days, limit, and thresholds where they apply. A call with no arguments returns the full report.

Tools return metric values (km, km/h, °C, bar, m) and rated range. get_unit_preferences reads the units chosen in TeslaMate’s settings (km or mi, °C or °F, bar or psi, rated or ideal range) so the assistant can convert when it answers; the charts stay metric.

The server also sends MCP instructions: how to read units, time zones and costs, and which tool answers which kind of question.

Reports (22)

Group Tools
Vehicle get_basic_car_information, get_current_car_status, get_software_update_history, get_unit_preferences
Battery get_battery_health_summary, get_battery_degradation_over_time, get_daily_battery_usage_patterns, get_tire_pressure_weekly_trends
Driving get_monthly_driving_summary, get_daily_driving_patterns, get_longest_drives_by_distance, get_total_distance_and_efficiency, get_drive_summary_per_day, get_visited_places
Efficiency get_efficiency_by_month_and_temperature, get_average_efficiency_by_temperature, get_efficiency_by_elevation, get_drive_efficiency_points, get_unusual_power_consumption
Charging get_charging_by_location, get_all_charging_sessions_summary, get_most_visited_locations

Insights (8)

Tool What it returns
get_battery_capacity_trend Usable capacity in kWh, estimated from charging sessions (energy added ÷ SOC gained), per month and car
get_vampire_drain Range lost while parked between drives; gaps that contain a charge do not count
get_charging_efficiency kWh added vs kWh drawn per car, split into AC and DC
get_charging_by_geofence Charging totals per TeslaMate geofence, plus an “Ungeofenced” group
get_soc_hygiene Share of samples above 80% and below 20% state of charge
get_period_comparison The last N days vs the N days before, one row per metric
get_activity_report A month by day or a year by month: drives, distance, consumption, charging, and cost per bucket, empty days included
get_trip_energy_estimate “Will I make it?”: energy and battery % a drive of a given distance takes, from this car’s own drives at a similar temperature (optionally motorway drives only), with a conservative figure and the arrival battery %

Timeline and car state (3)

TeslaMate logs whether each car is online, asleep, or offline. get_current_car_status reads that log too, and reports whether the car is driving, charging, online, asleep, or offline right now.

Tool What it returns
get_timeline What the car did, in order: drives, charges, the time parked between them, and software updates, with places, battery %, kWh, and cost; answers “what did my car do on Saturday?”
get_state_history Per car and local day: hours online, asleep, and offline, driving and charging hours, idle awake hours (online while parked and not charging), and wake-ups
get_idle_awake_periods The online periods that kept the car awake while parked, longest first, with where it was parked; answers “why isn’t my car sleeping?”

Search and detail (5)

Tool What it returns
search_drives Drives filtered by date range, location text, distance, and car; sortable
search_charging_sessions Charging sessions filtered by date range, location, energy, and car
get_drive_details Full statistics for one drive
get_drive_route GPS track points for one drive, downsampled
get_charging_curve Power and SOC curve for one charging session, downsampled

Costs (3)

A session with no cost recorded counts as unknown, not free: averages per kWh use only the sessions that have a cost, and each report says how many sessions lack one.

Tool What it returns
get_charging_costs Costs grouped by month, location, or car, with the number of sessions that have no cost
get_charging_cost_estimates An estimated cost for each session with none: free Supercharging, a price you give, the geofence tariff, what you paid at the same place, or the typical price for that charger type
get_fuel_savings What the same distance would have cost in fuel, against what charging cost, per car

Trips (3)

TeslaMate ends a drive every time the car parks, so a road trip with a WC break and a charging stop is several drives. The trip tools merge a car’s consecutive drives while each stop in between stays short: up to max_stop_minutes (default 30) without charging, or max_charging_stop_minutes (default 120) when a charging session happened during the stop. Overnight stops end a trip.

Tool What it returns
get_trips One row per trip: legs, stops and charging stops, distance, driving vs stopped time, moving speed, battery % at start and end, kWh added on the way; filter by date, car, distance, legs, or a place the trip passed through
get_trip_details One trip’s timeline: each drive, and each stop with where and how long, plus kWh and battery % for charging stops
get_trip_route GPS track of a whole trip across its drives, downsampled, with the stop before each leg

Fast charging (3)

A session is DC when a sample came from a fast charger, or had no AC phases while power flowed; a Tesla-branded fast charger is a Supercharger.

Tool What it returns
get_fast_charging_sessions DC sessions with peak power, average power, average power across 20–80% (the fair comparison), minutes from 20% to 80%, whether the battery heater ran, and cost
get_fast_charging_by_location The same per location and charger type: which fast chargers are fastest and cheapest for your car
get_charging_curve_comparison Power against battery % for several sessions, for overlaying their curves

Charts (8)

show_charging_curve, show_charging_curve_comparison, show_battery_degradation, show_drive_route, show_trip_route, show_activity_report, show_visited_places, and show_efficiency_vs_temperature are the chart versions of their get_* tools. On chart-capable clients they draw an interactive chart in the conversation. On other clients they return the same rows as the get_* tool. The route and trip maps draw the track over a low-detail basemap (Esri gray canvas, light or dark to match the client); the trip map also marks every stop, with charging stops highlighted. Both maps draw an elevation profile under the track; hovering it finds the place on the map. show_activity_report is a monthly or yearly dashboard, show_visited_places maps where the car parks (sized by arrivals, charging places highlighted), and show_efficiency_vs_temperature plots every drive’s consumption against outside temperature with the 5 °C average. Set MAP_TILES=false to keep the maps fully offline.

Custom (2)

  • get_database_schema — lists all tables, shows the columns of one table, and re-reads the schema when you pass refresh=true.
  • run_sql — runs one custom SELECT or WITH … SELECT.

Prompts (11)

Ready-made workflows that name the tools to call, in order: status_report, summarize_driving, analyze_battery_health, analyze_charging, find_anomalies, weather_efficiency, diagnose_sleep, plan_trip, review_trip, monthly_recap, and charging_costs_and_savings. With cost writes on, backfill_costs_from_receipts joins them.

Cost writes (opt-in, off by default)

Set ENABLE_CHARGING_WRITES=true to register set_charging_cost(charging_process_id, cost). It sets the cost of one charging session. This is the same field that the TeslaMate UI edits. A backfill_costs_from_receipts prompt guides the receipt-matching workflow.

Give the database role write access to that single column only:

GRANT UPDATE (cost) ON charging_processes TO teslamate_ro;

This grant is the security boundary. The tool cannot write anything else. On clients with MCP elicitation, the user confirms each write in a dialog. run_sql stays read-only in all cases.

Configuration

The server reads all settings from environment variables. It also reads a .env file. Only DATABASE_URL is required.

Variable Default Purpose
DATABASE_URL required postgresql://user:pass@host:5432/teslamate
AUTH_TOKEN empty Turns on bearer auth for the HTTP endpoint
CF_ACCESS_TEAM_DOMAIN empty Cloudflare Access team domain; accepts Access-verified requests
CF_ACCESS_AUD empty Audience tag of that Access application (set with the above)
HOST 0.0.0.0 HTTP bind host
PORT 8888 HTTP bind port
POOL_MIN_SIZE 1 Minimum pool connections
POOL_MAX_SIZE 10 Maximum pool connections
STATEMENT_TIMEOUT_MS 30000 statement_timeout for every query, including reports
QUERY_TIMEOUT_MS 5000 Tighter statement_timeout for run_sql
CUSTOM_SQL_ROW_LIMIT 1000 Most rows run_sql returns, whatever its LIMIT
REPORT_TIMEZONE UTC IANA timezone for report buckets
MAP_TILES true Basemap under the route, trip, and places maps (Esri tiles)
ENABLE_CHARGING_WRITES false Registers set_charging_cost
LOG_LEVEL INFO Python log level
DEBUG false Starlette debug mode; keep off in production

Generate a bearer token:

uv run teslamate-mcp gen-token

Add your own query

No code change is necessary. The server finds new queries at startup.

  1. Put a SELECT in src/teslamate_mcp/queries/your_query.sql.

  2. Add your_query.toml next to it:

    name = "get_your_data"
    description = "What this returns, units, grouping, and available filters."
    
    [[params]]                 # optional: typed tool arguments
    name = "car_name"
    type = "string"            # string | integer | number | boolean
    description = "Case-insensitive substring match on the car's name."
    
    [[params]]
    name = "limit"
    type = "integer"
    description = "Maximum number of rows returned."
    default = 10
    minimum = 1
    maximum = 100
    
    [[output]]                 # optional: one entry per result column
    name = "car_name"
    type = "string"
    
  3. Write parameters as %(car_name)s placeholders in the SQL. Do not build SQL from strings. Cast the first use of each placeholder, for example %(limit)s::int. Write a literal % as %%. The reserved %(tz)s placeholder binds REPORT_TIMEZONE.

  4. Restart the server. The registry validates the pair and registers the tool. Run teslamate-mcp list-tools to confirm.

The startup validation rejects a query when a declared parameter is missing from the SQL, or when the SQL uses an undeclared parameter.

Security

  • run_sql runs in a READ ONLY transaction that always rolls back. Timeouts and a row cap apply.
  • Connect with a SELECT-only PostgreSQL role, not TeslaMate’s own teslamate user. TeslaMate’s Compose makes that user a superuser, and a read-only transaction still lets a superuser read server files through run_sql. SECURITY.md has the CREATE ROLE snippet.
  • The maps’ basemap tiles are fetched from Esri by the viewer’s browser, which reveals the rough area being viewed. MAP_TILES=false turns this off.
  • The HTTP transport compares bearer tokens with a timing-safe function. Behind Cloudflare Access, it can instead verify the signed Cf-Access-Jwt-Assertion (signature, issuer, audience, expiry).
  • Report vulnerabilities through private security advisories. See SECURITY.md.

Development

uv sync                          # install with dev dependencies
uv run ruff check src tests      # lint
uv run ruff format src tests     # format
uv run pytest                    # database tests need Docker or TESLAMATE_TEST_DATABASE_URL (a scratch database)

License

MIT — see LICENSE.

View this README on GitHub

安装

docker run --rm -e DATABASE_URL=... -p 8888:8888 ghcr.io/cobanov/teslamate-mcp:latest

配置

{ "mcpServers": { "teslamate": { "command": "uv", "args": ["--directory", "/path/to/teslamate-mcp", "run", "teslamate-mcp", "stdio"] } } }