TeslaFi MCP Server
A Model Context Protocol server for the TeslaFi API that lets MCP clients query live vehicle data, drive and charge history, commute patterns, and optionally send commands.
README
TeslaFi MCP Server
A Model Context Protocol (MCP) server for the TeslaFi API. It lets MCP clients such as Claude Desktop query your vehicle's live data, stored drive and charge history, and commute patterns — and, only if you explicitly opt in, send vehicle commands.
Example: "How many times did I drive from Home to Acme HQ last month, and what did charging cost me?"
What can you ask?
Once connected, your MCP client can answer questions like these — and combine the underlying data in ways no fixed dashboard can.
Live status
- "Is my car charging right now, and what's it set to stop at?"
- "What's my battery level — is that enough for a 150 km round trip?"
- "What's my range — show it in miles instead."
- "Where's my car parked, and is it locked?"
- "How many kilometres has my car done?"
- "Check my tyre pressures (in bar) — anything low?"
- "What software version is the car on, and is an update pending?"
Driving & charging history
- "List my drives from last weekend."
- "How far did I drive in June, and what was my longest trip? Use miles."
- "Show this month's charging sessions — how much energy did I add in total?"
- "How often do I charge away from home?"
- "What's my total distance on record — and remember it only goes back to when I joined TeslaFi, so don't call it lifetime."
Commutes & places
- "How many times did I commute to the office last month?"
- "What are my ten most-visited places this year?" (includes places you've never tagged in TeslaFi — inferred from repeated addresses)
- "Which weekdays did I work from home in June?"
Reports & analysis (the client combines tools and does the math)
- "Build me a mileage expense report for July: date, from, to, distance — as a table I can paste into a spreadsheet."
- "Compare my energy use this month against last month."
- "Estimate my charging cost per kilometre, assuming €0.30/kWh at home and €0.55/kWh supercharging."
Vehicle commands (only with the explicit opt-in — see below)
- "Warm the cabin to 21 °C."
- "Turn on the driver's seat heater, full blast."
- "Set the charge limit to 90% for tomorrow's long trip."
- "Flash the lights so I can find the car in this car park."
- "Lock the car."
- "The car's asleep — wake it and start charging." (waking must be asked for explicitly; a plain command never wakes a sleeping car)
- "How much of my monthly TeslaFi command quota have I used?"
Tools
| Tool | Purpose |
|---|---|
tesla_get_current_data |
Live / last-known vehicle data (state, battery, range, charging, location). |
tesla_get_drives |
Stored drive history, with optional date-range filtering. |
tesla_get_charges |
Stored charge sessions, with optional date-range filtering. |
tesla_get_trips_for_month |
All drives in a given calendar month, normalized. |
tesla_analyze_home_work_trips |
Count home-to-work and work-to-home commutes in a month (e.g. Home ↔ Acme HQ). |
tesla_get_locations |
Unique locations and visit counts derived from drive history — both TeslaFi-tagged locations (named: true, e.g. Home/Work/Superchargers) and frequently-visited untagged addresses inferred from repeated drives (named: false). |
tesla_send_command |
Send a vehicle control command — disabled by default, see Vehicle commands. Car commands never wake a sleeping car unless you pass wake_seconds or no_wake: false. |
Units
Every data-returning tool (tesla_get_current_data, tesla_get_drives,
tesla_get_charges, tesla_get_trips_for_month,
tesla_analyze_home_work_trips, tesla_get_locations) accepts an optional
units argument — "metric", "imperial", or "both" — and every response
carries a top-level units field stating the system that was applied.
Physical quantities are self-describing. Field names carry the unit as a
suffix (_km/_mi, _kmh/_mph, _c/_f, _bar/_psi, _kwh, _m/_ft,
_pct), and every markdown number is printed next to its unit (314 km,
24 °C, 3.1 bar, 18.6 kWh, 72 %). With units: "both" both suffixed
fields are emitted for each quantity.
Effective-unit resolution (used when units is not passed), in order:
- the explicit
unitstool argument; - the
TESLAFI_UNITSenvironment variable (metric/imperial, case-insensitive; any other value ignored); - your TeslaFi account preference (the feed's
measurefield), remembered in memory from the most recent feed response this session; - metric.
The OS locale is not visible to the server.
TESLAFI_UNITSis the documented way for a client to pin a default so you don't have to passunitson every call.
Live feed vs. history. Live feed values (tesla_get_current_data) are
Tesla-native (miles, mph, °C, psi, metres) regardless of your account setting,
so they are converted to the chosen system. History records
(drives/charges/trips) already carry both unit systems, so the server
selects the pre-existing field for the chosen system rather than
re-converting — no double-conversion or rounding drift. Percentages, kWh, and
currency are never converted; only their unit label is attached.
Compact output and include_raw
tesla_get_drives, tesla_get_charges, and tesla_get_trips_for_month return
compact records by default (physical fields use the unit-suffixed names
above, for the applied system):
- Drives:
id,date,start_location,end_location, thendistance_km/distance_mi,efficiency_wh_km/efficiency_wh_mi,speed_avg_kmh/speed_avg_mph,speed_max_kmh/speed_max_mph,temperature_avg_c/temperature_avg_f(°C-only source, converted for imperial),tpms_avg_bar/tpms_avg_psi(bar-only source, converted for imperial), anddrive_kwh(kWh — never converted). Everything else stays in the raw record (include_raw). - Charges:
id,date,location,energy_added_kwh(kWh — never converted) - Trips: a normalized shape with start/end location, ISO timestamps,
distance_km/distance_mi, and duration in minutes
All three tools accept an optional include_raw boolean (default false).
Only when it is true is the full raw TeslaFi record embedded (under a raw
key) alongside each summary — raw records are large, so request them only when
you need fields the summaries don't carry.
History coverage metadata
tesla_get_drives, tesla_get_charges, and tesla_get_trips_for_month also
return, alongside total/returned/offset/limit/has_more:
date_range:{ earliest, latest }computed from the full fetched dataset for the query (before pagination). When no date filter is supplied,earliestis effectively your TeslaFi join date. No extra network call is made — it is derived from the records already fetched.coverage_note: a short sentence noting that TeslaFi history only goes back to when you joined, so a "lifetime" figure derived from these records excludes any distance/energy before that date.
These let a client label totals honestly (the markdown likewise says, e.g.,
2,526 drives on record (since 2023-12-18); showing 1–50).
tesla_analyze_home_work_trips matches location names loosely
(case-insensitive substring match) and caps the embedded matched-trip list at
500 entries, setting trips_truncated: true when the cap is hit; the
summary counts always cover the full month.
Getting a TeslaFi API token
- Log in to TeslaFi and open https://teslafi.com/api.php (Settings → TeslaFi API).
- Generate (or copy) your API token.
- If you plan to use vehicle commands, also enable the specific commands you want on the Commands tab of that page.
Installation
Option A: MCP extension bundle (recommended)
- Download
teslafi-mcp.mcpbfrom the latest GitHub Release. - Open it with Claude Desktop (double-click, or Settings → Extensions → Install extension).
- Paste your TeslaFi API token when prompted. Vehicle commands stay off unless you enable the "Enable vehicle commands" option.
Option B: manual configuration
git clone https://github.com/Zenotech-bv/teslafi-mcp.git
cd teslafi-mcp
npm install
npm run build
Then add the server to your claude_desktop_config.json:
{
"mcpServers": {
"teslafi": {
"command": "node",
"args": ["/path/to/teslafi-mcp/dist/index.js"],
"env": {
"TESLA_API_TOKEN": "your_teslafi_token_here"
}
}
}
}
Configuration
All configuration is via environment variables:
| Variable | Required | Default | Description |
|---|---|---|---|
TESLA_API_TOKEN |
Yes* | — | Your TeslaFi API token. |
TESLAFI_API_TOKEN |
Yes* | — | Alias for TESLA_API_TOKEN; either works. |
TESLAFI_ENABLE_COMMANDS |
No | unset (off) | Enables the tesla_send_command tool. Only true, 1, or yes (case-insensitive) enable it; any other value keeps the server read-only. |
TESLAFI_UNITS |
No | unset (Automatic) | Default unit system for physical quantities when a tool call omits units. metric or imperial (case-insensitive) pins a default; any other value (including the extension's "Automatic") defers to your TeslaFi account's measure setting, then metric. The OS locale is not visible to the server, so this is the documented way for a client to pin a default without passing units on every call. |
TESLAFI_CACHE_TTL_SECONDS |
No | 60 |
TTL of the in-memory history cache, in seconds. Set to 0 to disable caching; invalid values fall back to the default. |
TESLAFI_CHECK_UPDATES |
No | unset (off) | Opt in to a check for a newer GitHub release. Only true, 1, or yes (case-insensitive) enable it; any other value keeps it off. When on, the server makes a single unauthenticated request to api.github.com (no TeslaFi token or data sent) and, if a newer release exists, appends a one-line notice to data-tool markdown output once per session. See Update checks (opt-in). |
* One of the two token variables must be set; TESLA_API_TOKEN takes
precedence.
Note for extension-bundle users: the "Enable vehicle commands" checkbox maps to
TESLAFI_ENABLE_COMMANDS. When left off it passes the literal string "false",
which is not in the truthy set (true/1/yes) and therefore keeps commands
disabled — only ticking the checkbox enables them. The Units dropdown maps
to TESLAFI_UNITS; its default "Automatic (account default)" passes a value
the server ignores, so units fall back to your TeslaFi account setting (then
metric) until you choose Metric or Imperial.
Vehicle commands (opt-in)
tesla_send_command is registered but disabled by default. When disabled,
calling it returns a clear error explaining how to enable it — nothing is sent
to your car. To use it you must:
- Set
TESLAFI_ENABLE_COMMANDS=truein the server's environment (or tick "Enable vehicle commands" when installing the extension bundle), and - Enable the individual commands on TeslaFi's Commands tab at https://teslafi.com/api.php.
Supported commands
Commands are validated against a fixed local allowlist — the 24 commands
below, matching TeslaFi's official API documentation (the command list
shown on the logged-in API settings page at https://teslafi.com/api.php).
Anything not on the list, any parameter key not valid for the given command,
and the reserved keys token, command, wake, and noWake are rejected by
this server itself, before any network request is made. Numeric parameters are
also value-checked locally (ranges noted below), so an out-of-range value
never costs a quota request.
Benign (polling, logging, horn, lights, climate):
| Command | Parameters |
|---|---|
wake |
— (resume TeslaFi polling: sets the idle timer to 0 and re-enables polling) |
wake_up |
— (wake the vehicle) |
sleep |
time (optional; minutes for the sleep attempt) |
enableLogging |
— |
command_count |
— (read-only: current command/wake quota usage) |
honk |
— |
flash_lights |
— |
auto_conditioning_start / auto_conditioning_stop |
— |
set_temps |
temp (Celsius, one decimal allowed; 15–28) |
seat_heater |
heater (0 = driver, 1 = passenger, 2 = rear left, 4 = rear center, 5 = rear right — there is no seat 3), level (0–3; 0 = off). Conditioning must be turned on first. |
steering_wheel_heater |
statement (true/false). Conditioning must be turned on first. |
set_preconditioning_max |
statement (true/false) — Max Defrost; when turned off, conditioning remains on |
preset |
number (preset ID, required), statement (optional; true sends an email confirmation). The controls the preset drives must themselves be enabled. |
Consequential (logging off, locks, charging, security):
| Command | Parameters |
|---|---|
disableLogging |
— (stops TeslaFi's data logging for your account) |
door_lock / door_unlock |
— |
charge_start / charge_stop |
— |
charge_port_door_open / charge_port_door_close |
— |
set_charge_limit |
charge_limit_soc (50–100) |
set_charging_amps |
charging_amps (1–80) |
set_sentry_mode |
sentryMode (true/false) |
Two global modifiers control what happens when the car is asleep:
wake_seconds(1–60, TeslaFi's documented maximum — maps to&wake=X): TeslaFi sends a wake and pauses up to that many seconds before issuing the command; the request timeout is extended to cover the wait. Note this costs a wake request from the monthly quota (see below).no_wake: true(maps to&noWake=true): the command is not sent at all while the vehicle is sleeping.
Wake-conserving default — car commands never wake a sleeping car. For car commands (honk, lights, climate, seat/wheel heaters, presets, charging, charge port, locks, sentry — everything that acts on the vehicle itself), passing neither
wake_secondsnorno_wakesendsnoWake=trueautomatically: a sleeping car is never woken implicitly, so no monthly wake request is ever spent without you asking for it. If the car was asleep, the tool output states the command was not sent and lists the options (retry withwake_seconds, or wait until the car wakes). To wake the car, passwake_seconds; to restore TeslaFi's own default (wake the car and pause up to 15 s), passno_wake: falseexplicitly. Account-side commands (wake,wake_up,sleep,enableLogging,disableLogging,command_count) are handled by TeslaFi itself and never takenoWake(no_wake: trueon them is rejected locally).
The two modifiers are mutually exclusive; supplying both is rejected locally with a clear error.
Command quotas
TeslaFi allows 500 command requests and 50 wake requests per month,
resetting on the 1st. A command issued while the car is asleep costs
1 command + 1 wake; if the wake quota is exhausted while the car is
asleep, the command is not sent and the API returns an error. Every command
and data response embeds a tesla_request_counter object
({"commands": N, "wakes": N, ...}), updated immediately on API command
calls and otherwise every 30 minutes. This server surfaces it as a
Quota: N/500 commands, M/50 wakes used this month line in the
tesla_send_command and tesla_get_current_data markdown output (and it is
present in the structured output whenever TeslaFi includes it); the
command_count command returns the counters on demand.
The server is quota-careful on top of that:
- Wake-conserving default — car commands never spend a wake request implicitly; see the wake-conserving default above.
- High-usage warnings — the server remembers the last
tesla_request_counterit saw (from any command or data response, in memory only). Once usage reaches 80% of an allowance (≥ 400/500 commands or ≥ 40/50 wakes), everytesla_send_commandmarkdown result is prefixed with a warning line such asWARNING: 43/50 monthly wake requests used. - Proactive rate-limit pacing — data responses also embed a
rate_limitobject ({"limit": 15, "remaining": N, "reset_in_seconds": N}). When the last response reportedremaining: 0, the server waits out the remainder of the reported reset window (capped at 60 s) before the next request, instead of firing one that is guaranteed to be rejected with HTTP 429. - Exhausted-allowance errors are terminal — a TeslaFi error indicating the monthly command or wake allowance is used up is never retried, and is surfaced as an actionable message: the command was not sent, the last known usage, that allowances reset on the 1st of the month, and that extra requests can be purchased from TeslaFi support. (TeslaFi does not document the exact error payload, so the match is heuristic; ordinary auth or malformed-request errors are never classified this way.)
Update checks (opt-in)
The server can tell you when a newer release is available, but this is off by default because it adds a second network destination.
-
How to enable it — set
TESLAFI_CHECK_UPDATES=true(or1/yes) in the server's environment, or tick Check for updates when installing the extension bundle (it maps to the same variable). Any other value keeps it off. -
What it does — when enabled, the server makes a single unauthenticated
GETtohttps://api.github.com/repos/Zenotech-bv/teslafi-mcp/releases/latest, reads the releasetag_name, and compares it to the running version using a numericmajor.minor.patchcomparison. If a release is strictly newer, a one-line notice is appended to the markdown output of the next data tool, e.g.:ℹ️ A newer TeslaFi MCP release is available: v2.5.0 (you have v2.4.0) — https://github.com/Zenotech-bv/teslafi-mcp/releases
The notice appears at most once per session and never in
response_format: "json"output, so JSON stays pure and parseable. -
What it never sends — the GitHub request carries no TeslaFi token, no
Authorizationheader, and no TeslaFi data of any kind. It follows no redirects (maxRedirects: 0) and honors no proxy (proxy: false), just like the TeslaFi requests. The result is kept in memory only; nothing is written to disk. -
Fail-safe — the check is fire-and-forget: any failure (network error, timeout, rate limit, malformed response) is silently ignored and never affects a tool result. When disabled, no GitHub request is ever made and the only network destination remains
www.teslafi.com. -
Private-repo note — while the repository is private, GitHub returns 404 to unauthenticated callers, which is swallowed as "no update"; the notice therefore only ever appears once the repository is public.
Performance notes
- History caching —
history.phpresponses (drives and charges) are cached in memory for 60 seconds by default (TESLAFI_CACHE_TTL_SECONDS;0disables), keyed by endpoint + date range, so pagination and the commute-analysis tools reuse a single fetch. Failures are never cached, and nothing is written to disk. - Adaptive request spacing — outbound requests are always spaced at least 1
second apart, and on top of that an in-memory token bucket paces sustained
load to stay within TeslaFi's advertised per-window budget. The bucket is
self-tuning: its capacity and refill rate are derived from the
rate_limitobject TeslaFi embeds in responses ({"limit": 15, "remaining": N, "reset_in_seconds": 60}→ a bucket of ~15 tokens refilling at ~limit/window, i.e. ~4 s per token for 15/60). Each request spends one token. This intentionally allows an initial burst up to the advertised budget — so a handful of tool calls stay fast — then glides down to the steady refill rate under sustained use, converging toward the reset instead of bursting to the wall and stalling. Before anyrate_limithas been observed (and whenever the advertised limit or window is missing, zero, or nonsensical) pacing falls back to the 1 s floor alone; any single computed wait is capped (never more than one window, and never more than 60 s) so a garbled value cannot hang a request. The pacing is purely internal — no tool parameter or output changed. - Proactive rate-limit backstop — when the embedded
rate_limitlast reportedremaining: 0, the next request additionally waits out the remainder of the reported reset window (capped at 60 s) instead of firing a guaranteed HTTP 429. This remains a backstop beneath the token bucket; all pacing state is in-memory only. - Retries — transient failures are retried up to 2 times with exponential
backoff and jitter. An HTTP 429 is retried only when TeslaFi supplies a
Retry-Afterof at most 60 s; a 429 without that header, or asking for a longer wait, fails immediately with a rate-limit error (mentioning the requested wait) instead of blocking the client. Reads are retried freely on network errors and 5xx. Vehicle commands are only retried for failures where the request provably never reached TeslaFi (DNS/connection errors, 429 rejections with an honoredRetry-After) — never for mid-flight errors such as timeouts or resets, so a command cannot be executed twice. - Wake handling —
wake_seconds(1–60 s) extends the default 30 s request timeout by the wake window, so wake-assisted commands don't time out spuriously.
Privacy & Security
- Stateless — no database, no persistent state between requests. The only
cache is a short-lived in-memory one (see
TESLAFI_CACHE_TTL_SECONDS). - Zero disk writes — the server never writes your vehicle data, token, or anything else to disk.
- Zero telemetry — no analytics, no crash reporting, no phoning home.
- No data retention — responses are passed to your MCP client and then discarded.
- Single network destination (by default) — by default the only host this
server ever contacts is
www.teslafi.com, over HTTPS. HTTP redirects are never followed (maxRedirects: 0), so even a server-issued redirect cannot send the token-bearing request to another host or downgrade it to plain HTTP. Proxy environment variables (HTTP_PROXY/HTTPS_PROXY/NO_PROXY) are ignored (proxy: false), so requests always go directly towww.teslafi.com. The one exception is opt-in: enablingTESLAFI_CHECK_UPDATESadditionally contactsapi.github.com— unauthenticated, with no TeslaFi token or data sent, and with the samemaxRedirects: 0/proxy: falsehardening — solely to read the latest release tag. It is off by default; see Update checks (opt-in). - Read-only by default — vehicle commands require the explicit
TESLAFI_ENABLE_COMMANDS=trueopt-in described above. - Token handling — your token is never written to logs, error messages, or tool output. Note that TeslaFi's API design places the token in URL query parameters; see SECURITY.md for what that means and how it is mitigated.
To report a vulnerability, see SECURITY.md.
Development
npm install
npm run dev # run from source with auto-reload
npm run build # compile TypeScript to dist/
npm test # run the test suite
Note:
npm testrequires Node 20 or newer — the vitest toolchain does not run on Node 18. Node 18 is only supported for running the built server.
A helper script dumps a real sample of your TeslaFi data so field mappings can be verified against your account:
npm run build
TESLA_API_TOKEN=xxxx npm run inspect -- --month 2026-07
See CONTRIBUTING.md for contribution guidelines.
Requirements
- Node.js 18 or newer to run the built server (development and
npm testrequire Node 20 or newer — see Development) - A TeslaFi account and API token
License
MIT © 2026 Matt Stevens
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.