Skip to content

Configuration

Mert Cobanov edited this page Aug 1, 2026 · 1 revision

Configuration

All settings are read from environment variables. A .env file in the working directory is picked up automatically. Only DATABASE_URL is required.

Variable Default Notes
DATABASE_URL required postgresql://user:pass@host:5432/teslamate
AUTH_TOKEN empty Enables bearer auth on the HTTP endpoint. Generate one with teslamate-mcp gen-token
HOST 0.0.0.0 HTTP bind host
PORT 8888 HTTP bind port
POOL_MIN_SIZE 1 psycopg pool floor
POOL_MAX_SIZE 10 psycopg pool ceiling
STATEMENT_TIMEOUT_MS 30000 Connection-level statement_timeout bounding every query
QUERY_TIMEOUT_MS 5000 Tighter statement_timeout applied to run_sql specifically
CUSTOM_SQL_ROW_LIMIT 1000 LIMIT injected when run_sql doesn't supply one
REPORT_TIMEZONE UTC IANA timezone for daily/weekly/monthly report buckets
ENABLE_CHARGING_WRITES false Registers set_charging_cost — see Write Tools
OTEL_EXPORTER_OTLP_ENDPOINT empty Enables OpenTelemetry export when set
LOG_LEVEL INFO Standard Python log level
DEBUG false Starlette debug mode — keep off in production

Notes on individual settings

DATABASE_URL

Point this at the TeslaMate database. If TeslaMate runs in Docker with the database published on the host, the port is usually 5433 rather than 5432, because the container maps 5433:5432.

A read-only role is a good idea even though the server never writes on its default configuration:

CREATE ROLE teslamate_ro LOGIN PASSWORD '';
GRANT CONNECT ON DATABASE teslamate TO teslamate_ro;
GRANT USAGE ON SCHEMA public TO teslamate_ro;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO teslamate_ro;

STATEMENT_TIMEOUT_MS vs QUERY_TIMEOUT_MS

STATEMENT_TIMEOUT_MS is applied as a libpq connection option, so it bounds every query the server can issue — bundled reports included. It is a safety net against a pathological query pinning a PostgreSQL backend indefinitely.

QUERY_TIMEOUT_MS is the tighter bound run_sql sets inside its own read-only transaction, on the assumption that model-authored SQL deserves less rope than the queries shipped with the server.

If your DATABASE_URL already carries a libpq options= parameter, the server leaves it alone and STATEMENT_TIMEOUT_MS has no effect.

AUTH_TOKEN

Only affects the HTTP transport; stdio inherits the trust of the process that launched it. When empty, the HTTP endpoint is unauthenticated and the server logs a warning at startup. Comparison is timing-safe.

/health is deliberately exempt from authentication so container health checks and external monitors can reach it.

REPORT_TIMEZONE

Reports that bucket by day, week, or month use this to decide where midnight falls. The default of UTC means a drive at 01:30 local time may land in the previous day's bucket. Set it to your own IANA zone (Europe/Istanbul, America/Los_Angeles, …) and the buckets follow local midnight. Validated at startup — an unknown zone fails fast rather than erroring on the first query.

Health endpoint

GET /health returns 200 with:

{"status": "ok", "version": "0.10.0", "database": "ok"}

It runs a real SELECT 1 against the pool. If the database is unreachable it returns 503 with "status": "degraded" and a detail field, which is what the Docker HEALTHCHECK keys off — a container that cannot reach PostgreSQL is reported unhealthy rather than looking fine while failing every call.

Clone this wiki locally