Skip to main content
Glama
blakepennel

location-platform

by blakepennel

πŸ“ location-platform

Ask your AI assistant where you've been β€” and where you are right now.

Self-hosted MCP servers that turn your Google Maps Timeline and live location into tools for Claude, ChatGPT, or any MCP client.

Node Python TypeScript MCP Docker Tests License


Why

Google stopped offering Timeline on the web, and your location history now lives only on your phone (plus an encrypted cloud backup). This project pulls that history back out, keeps it on your own server, and lets an LLM answer questions about it β€” alongside a separate live feed for "where am I right now?".

Related MCP server: Google Workspace MCP Server

What you can ask

"Where was I last Tuesday around 3pm?" β†’ where_was_i finds the visit or trip covering that moment.

"How much time did I spend at the gym in September?" β†’ search_places + time_at_place totals every visit.

"Summarize my week." β†’ summarize_week returns days, top places, distance, and how you got around.

"When was the last time I went to that taco place downtown?" β†’ visit_history lists every visit, newest first.

"How far did I drive this month vs. walk?" β†’ distance_traveled breaks it down by activity.

"Where am I right now, and have I moved since noon?" β†’ where_am_i + movement_since from the live feed, with data age shown.

How it works

flowchart LR
    subgraph google["Google"]
        TB[(Timeline<br/>cloud backup)]
        LS[(Maps Location<br/>Sharing)]
    end

    subgraph server["Your server (Docker)"]
        TS[timeline-sync<br/><sub>Python Β· every 6 h</sub>]
        TJ[/Timeline.json/]
        TM[timeline-mcp<br/><sub>13 tools</sub>]
        LP[live poller<br/><sub>every 60 s</sub>]
        LD[(live.sqlite)]
        LM[live-location-mcp<br/><sub>5 tools</sub>]
        AUTH{{OAuth 2.1}}
    end

    TB --> TS --> TJ --> TM
    LS --> LP --> LD --> LM
    TM & LM --- AUTH
    AUTH --> C[Claude]
    AUTH --> G[ChatGPT]

History and live are deliberately two separate systems. Timeline is Google's semantic reconstruction (visits, trips, activities, Place IDs) and arrives hours late. Live Location Sharing is raw point observations, seconds old. They live in separate databases behind separate MCP servers and are never merged. The model picks the right tool, and every answer says how old its data is.

Features

πŸ—ΊοΈ Full Timeline history

Syncs straight from Google's encrypted Timeline backup (no phone export, no Takeout) and follows every backup corpus, so nothing is cut off.

🏷️ Real place names

Resolves Place IDs to names automatically after each sync.

πŸ“‘ Live location

Polls Google Maps Location Sharing through a dedicated recipient account. The session refreshes itself with cookie rotation and a persistent browser profile.

πŸ” Hands-off re-auth

When Google revokes the Timeline token, a persistent browser signs back in. The password is sealed by the host's TPM 2.0 (systemd-creds), so a stolen disk or backup can't use it. It stops and asks for a human on any CAPTCHA or unexpected challenge.

πŸ” Two auth layers

Google credentials never leave the server. MCP clients get only short-lived, audience-bound OAuth 2.1 tokens (RFC 9728 discovery, PKCE, JWKS verification).

🎚️ Precision controls

Three levels with a per-server cap on what an LLM may see: semantic (place names only, no coordinates), approximate (~1 km), or exact.

🧾 Logs that can't leak

Structured logs with automatic redaction of tokens, cookies, keys, and anything that looks like a coordinate.

πŸ§ͺ Synthetic by default

Every test and fixture uses invented coordinates. A leak scanner checks the repo for secrets and real locations.

🐳 One docker compose up

OAuth server, both MCP servers, the poller, the sync scheduler, and noVNC browser views. Ports bind to 127.0.0.1 only.

πŸ’¬ ChatGPT without exposure

Optional OpenAI Secure MCP Tunnel services: an outbound-only connection, with nothing published to the internet.

Tools

Tool

where_was_i

A point in time

visits Β· timeline_between

A day or range

summarize_day Β· summarize_week

Digests

search_places Β· visit_history

Find a place

time_at_place

Total dwell time

visits_near

Radius search

trips Β· activities

Movement

distance_traveled

Distance by mode

timeline_status

Data freshness

Tool

where_am_i

Latest fix

recent_locations

Points in a window

where_was_i_recently

Nearest fix to a time

movement_since

Distance and moves

location_status

Poller health

Every tool is read-only and annotated as such. There is no SQL, file access, or bulk-export tool.

Quick start

Try it with synthetic data. No Google account needed.

git clone --recurse-submodules https://github.com/blakepennel/location-platform.git
cd location-platform
npm install
cd timeline-sync && python -m venv .venv && .venv/bin/pip install -e ".[dev]" && cd ..
cp .env.example .env

npm run seed   # invented Timeline + live observations
npm run dev    # OAuth :8700 Β· timeline-mcp :8701 Β· live-location-mcp :8702

Point an MCP client at http://localhost:8701/mcp or http://localhost:8702/mcp. It discovers the OAuth server and opens a sign-in page. For Claude Code, the stdio transport skips OAuth entirely; see DEVELOPMENT.md.

Running it for real (a home server, your own Google data):

docker compose up -d --build

DOCKER.md walks through the one-time Google steps, the noVNC browser logins, TPM setup for automatic re-auth, and connecting Claude and ChatGPT.

Project layout

location-platform/
β”œβ”€β”€ timeline-sync/       Python Β· syncs + decrypts the Timeline backup (wraps arkenoi/timeline-export)
β”œβ”€β”€ timeline-mcp/        TypeScript Β· historical MCP server over its own SQLite index
β”œβ”€β”€ live-location-mcp/   TypeScript Β· live poller + MCP server
β”œβ”€β”€ mcp-auth/            OAuth 2.1 resource-server verifier + local dev authorization server
β”œβ”€β”€ shared/              logging/redaction, time/geo, sqlite, HTTP host
β”œβ”€β”€ schemas/             export contract + status JSON schemas
β”œβ”€β”€ tools/               dev runner, e2e harness, seed data, leak scanner, re-auth driver
└── docker/              container entrypoints (noVNC, sync loop, Google browser)

Testing

npm test           # 246 Node + ~125 Python tests
npm run test:e2e   # full stack: OAuth + both servers + a real MCP client
npm run leak-scan  # secrets and real-coordinate scan

Docs

ARCHITECTURE.md

Diagrams and data flow

DOCKER.md

Deploying on a server

DEVELOPMENT.md

Local setup and real Google onboarding

AUTH.md

The two authentication layers

SECURITY.md Β· THREAT_MODEL.md

What's protected, and from whom

Per-project READMEs

timeline-sync Β· timeline-mcp Β· live-location-mcp

Disclaimer

This is a personal project that reads your own data through undocumented Google endpoints: the Timeline cloud backup via arkenoi/timeline-export (a pinned submodule under its own MIT license), and Maps Location Sharing. Google can change or block them at any time, and using them may conflict with Google's Terms of Service. It is not affiliated with or endorsed by Google. Use it only with accounts you own, at your own risk.

License

MIT

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    A
    maintenance
    A local-first MCP server that enables AI agents to read user-authorized Google Health API v4 data from Fitbit, Pixel Watch, and partners via OAuth, with tokens never leaving the machine.
    26
    604 npm
    64
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    A local-first, privacy-first MCP server that passively indexes personal digital activity (screenshots, clipboard, notes, downloads, links) into a local database, enabling LLMs like Claude to access your context without cloud storage.
    4
    MIT