Subaru STARLINK MCP for Grok Bot
by elderibeiro
README.md
# Subaru STARLINK MCP for Grok Bot
A public recovery base for talking to MySubaru / STARLINK from Grok Bot over
stdio. No secrets live here. No VIN, no PIN, no passwords, no device ids.
This is a **local-first** MCP: your Grok Bot computer talks to the unofficial
MySubaru API through [G-Two/subarulink](https://github.com/G-Two/subarulink)
(`subarulink` 0.7.19 on PyPI). There is no extra SaaS in the middle.
**This project is not affiliated with, endorsed by, or supported by Subaru,
Subaru of America, Subaru Corporation, or STARLINK.** STARLINK and MySubaru
are trademarks of their owners.
The Python client is [G-Two/subarulink](https://github.com/G-Two/subarulink),
Apache-2.0, reverse-engineered from the MySubaru mobile app. This repo's
scripts and docs are MIT, Copyright 2026 Elder Lira.
Username and PIN come from `pass` or env. Never a hardcoded address.
On Grok Bot, `$HOME` is often `/home/box` and the Unix user is `box`. Treat
those as examples. Use `$HOME` / `GROK_HOME` on your machine.
## Why
The official MySubaru app is fine on a phone. On a Grok Bot VM you want
stdio MCP: status, locate, climate presets, and (only when you explicitly
ask) lock / unlock / remote start. Local wrapper, local `pass`, no third-party
cloud that holds your MySubaru password.
## Architecture
```mermaid
flowchart LR
Bot[Grok Bot]
Spec["Subaru specialist bot<br/>optional"]
MCP[local stdio MCP]
Lib["subarulink 0.7.19"]
API[MySubaru unofficial API]
Car[your car]
Bot --> Spec
Spec --> MCP
Bot --> MCP
MCP --> Lib --> API --> Car
```
The specialist bot is optional. Grok Bot can call this MCP directly.
Secrets never go on argv, git, or tool arguments:
```mermaid
flowchart LR
Pass["pass keys<br/>subaru/username<br/>subaru/password<br/>subaru/pin<br/>subaru/device-id"]
Wrap[wrapper]
Env[process env]
MCP[MCP stdio]
Pass --> Wrap --> Env --> MCP
```
## Remote start
Exact preset name match. A mismatch **stops**, lists the real names, and never
substitutes.
```mermaid
flowchart TD
Ask[user asks to remote start] --> List[list climate presets]
List --> Match{exact name match<br/>case-insensitive?}
Match -->|yes| Start[remote_start with canonical name]
Match -->|no| Stop[stop — list names, do not start]
```
## Why subarulink 0.7.19
Grok Bot's Python is **3.13**. `subarulink==0.7.21` needs **Python >= 3.14**
and will not install.
`0.7.19` still has g2 remote start with named climate presets:
- `remote_start(vin, preset_name)` — VIN stays in process memory, never in tools
- `list_climate_preset_names(vin)`
- `get_climate_preset_by_name(vin, name)`
After you have Python 3.14+, you can bump (see below). You would pick up
MySubaru **g2v33**, Crosstrek **Full Cool** seat sanitizer, and a 240-minute
session age check.
## Vehicle generation
Works with **2019–2022 g2** gasoline STARLINK (not PHEV). A 2021 Crosstrek
Sport is a worked example, not the only vehicle.
- Remote start / lock need **MySubaru Security / Companion+** and vehicle
feature **RES**.
- USA and Canada only. The reverse-engineered API can break without notice.
- Crosstrek **heated seats cannot be activated remotely** (the option is
ignored by the car). Create climate presets in the official MySubaru app.
- Telematics snapshots are **not OBD-II**. They are often stale until
`update()` / locate wakes the module. That wake can drain the **12V**
battery if you overuse it.
| | MySubaru telematics (this MCP) | OBD-II |
|---|---|---|
| Path | Phone-app API → STARLINK module | Diagnostic port / dongle |
| Freshness | Often stale until a wake | Live while plugged in |
| Needs | Active MySubaru plan | Physical adapter |
| Lock / remote start | Yes, with Security / Companion+ | No |
If the account has one vehicle, tools take no VIN. If there are several, pass
the MySubaru **nickname**, or set `SUBARU_NICKNAME`. Never pass a VIN to a tool.
## Tools (16)
Reads (no extra confirmation):
- `subaru_status` — compact telematics snapshot (does not wake the car)
- `subaru_refresh_status` — `update()` wake, then snapshot (**12V drain**)
- `subaru_list_climate_presets` — names only
- `subaru_get_climate_preset(name)` — sanitized fields; `INVALID_PRESET` + names
- `subaru_locate` — wake, then lat/long only if `LOCATION_VALID` (**12V drain**)
- `subaru_tire_pressure` — TPMS or `UNSUPPORTED`
- `subaru_fuel_status`
- `subaru_odometer`
Controls — call only on **explicit user intent** for that exact action:
- `subaru_lock`
- `subaru_unlock`
- `subaru_remote_start(preset_name)` — list, exact match, never substitute
- `subaru_remote_stop`
- `subaru_horn` / `subaru_horn_stop`
- `subaru_flash_lights` / `subaru_lights_stop`
There is no generic execute / raw API tool. Success is claimed only when
`Controller` returned `True`. VIN / password / PIN / token / cookie are
stripped from errors and logs.
## Install
1. Clone **this** repo.
2. After clone, `chmod +x scripts/*.sh scripts/*.py` (the GitHub API cannot set executable bits).
3. Python 3.13 venv (Grok Bot example: `$HOME/.local/opt/subaru-mcp`):
```sh
python3.13 -m venv "$HOME/.local/opt/subaru-mcp/.venv"
cp -R src "$HOME/.local/opt/subaru-mcp/"
"$HOME/.local/opt/subaru-mcp/.venv/bin/pip" install -r requirements.txt
```
4. Copy `scripts/subaru-mcp-wrapper.py` and `scripts/subaru-mcp-login.sh`
somewhere on `PATH` (Grok Bot example: `$HOME/.local/bin/`). Point
`SUBARU_MCP_SRC` / `SUBARU_MCP_PYTHON` at the venv if you install elsewhere.
5. Store secrets (never paste them into chat or git):
```sh
pass insert -e subaru/username
pass insert -e subaru/password
pass insert -e subaru/pin
```
6. First-run 2FA (does **not** lock, unlock, or start the car):
```sh
scripts/subaru-mcp-login.sh
```
If the device is already registered it prints success without a VIN. If 2FA
is required it asks for a 6-digit code with hidden input (contact values are
masked). `subaru/device-id` is generated automatically if missing
(`$HOME/.local/share/subaru-mcp/device_id`, mode `0600`).
7. Register the MCP with Grok Bot.
## Grok Bot AddMcpServer example
Command is the wrapper. **Never** put password or PIN in env or git.
```json
{
"command": "/usr/bin/python3",
"args": ["/path/to/subaru-starlink-mcp-grokbot/scripts/subaru-mcp-wrapper.py"],
"env": {
"SUBARU_COUNTRY": "USA",
"SUBARU_DEVICE_NAME": "grok-bot"
}
}
```
Optional: `GROK_HOME`, `SUBARU_MCP_SRC`, `SUBARU_MCP_PYTHON`,
`SUBARU_USERNAME` (if you refuse `pass` for the username only),
`SUBARU_NICKNAME`. Do not set `SUBARU_PASSWORD`, `SUBARU_PIN`, or
`SUBARU_DEVICE_ID` in this registration.
On a Grok Bot VM the wrapper default layout is
`$HOME/.local/opt/subaru-mcp/` (example Unix user `box`, `$HOME=/home/box`).
If username / password / PIN are missing, the MCP **still starts** (stdio
handshake succeeds). Tools return `[AUTH_NOT_CONFIGURED]` with `pass insert`
hints.
## 12V drain
`subaru_refresh_status` and `subaru_locate` wake the STARLINK module. Do not
poll. A parked car with a weak 12V battery can fail to start after too many
wakes.
## How to bump subarulink after Python 3.14
1. `python3 --version` — needs 3.14+ for `subarulink==0.7.21+`.
2. Read https://pypi.org/project/subarulink/ (`requires_python`, changelog).
3. In the venv: `pip install 'subarulink==NEW'` and pin it in `requirements.txt`.
4. Confirm `Controller.remote_start(vin, preset_name)` and
`list_climate_preset_names` still exist (or update `session.py`).
5. Run `pytest` (mocks only). Optional manual login — still **no**
lock/start from automation.
## Tests
Mocks only. No live MySubaru network. **No live lock or remote start.**
```sh
python3.13 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/pytest
```
Fake VINs in tests are obviously fake (`JF2GTADC1MH000001`). They never leave
the test process.
## Unofficial API warning
Subaru has no public STARLINK API. USA/Canada only. This stack can stop
working when MySubaru changes. Use at your own risk.
## Attribution
- This project is **not affiliated with Subaru**.
- MySubaru / STARLINK client: [G-Two/subarulink](https://github.com/G-Two/subarulink) (Apache-2.0).
- This repository: MIT, Copyright 2026 Elder Lira.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues