Skip to main content
Glama
connected-vehicle-health

connected-vehicle-health

by imsnawaz
README.md
# Connected Vehicle Health — MCP Server

An [MCP](https://modelcontextprotocol.io) server that exposes a connected-vehicle
OBD-II / telematics platform to AI agents. It maps raw OBD-II PIDs and CAN signals
into a rolled-up **vehicle health score** and provides tools for querying live data,
decoding diagnostic trouble codes (DTCs), forecasting maintenance, and issuing gated
remote commands.

The data layer is **pluggable** (`src/provider.ts`). Two backends ship:

- **`salesforce`** (default) — live data from a Salesforce org's standard `Asset`
  object (the vehicle; VIN in `SerialNumber`) joined to the custom
  `Vehicle_Telemetry__c` object (`VIN__c == Asset.SerialNumber`).
- **`simulator`** — an in-memory mixed fleet (ICE, diesel, EV) with deterministic
  signals and injectable faults; zero external dependencies.

Select with `VEHICLE_DATA_SOURCE=salesforce|simulator`. The tool/resource layer is
identical for both.

> **Full reference:** see [`DOCUMENTATION.md`](./DOCUMENTATION.md) for architecture,
> the complete tool/resource/type schema, the Salesforce field mapping, the scoring
> model, and extension points.

## What it exposes

### Tools

| Tool | Type | Purpose |
| --- | --- | --- |
| `list_vehicles` | read | Enumerate the fleet with profile + last-seen |
| `get_vehicle_health` | read | Overall + per-domain health score (0–100) |
| `read_live_pids` | read | Snapshot of selected live PID / CAN values |
| `get_dtcs` | read | Active stored / pending / permanent codes |
| `get_parameter_history` | read | Reproducible time-series for one PID |
| `decode_dtc` | read | Explain a code: causes, symptoms, fixes |
| `predict_maintenance` | compute | Ranked component failure risks |
| `clear_dtcs` | **action** | Reset codes / MIL (requires `confirm=true`) |
| `send_command` | **action** | Remote lock/climate/immobilize (requires `confirm=true`) |

### Resources

| URI | Content |
| --- | --- |
| `vehicle://{vin}/profile` | Make, model, year, powertrain, odometer |
| `vehicle://{vin}/health` | Latest health snapshot |
| `vehicle://{vin}/trips` | Recent trips + behavior events |
| `fleet://summary` | Fleet-wide health roll-up |
| `dtc://catalog` | DTC knowledge base |

## Health model

Seven domains, each scored 0–100 and weighted into the overall score. EVs drop
`emissions` and `fuel`; the remaining weights are renormalized to 100%.

| Domain | Weight | Driven by |
| --- | --- | --- |
| Powertrain | 25% | Misfires, timing, load |
| Emissions | 15% | Lambda, catalyst temp, EGR |
| Fuel | 12% | Short/long fuel trims |
| Battery | 18% | 12V voltage/SoH, HV SoH, cell delta |
| Thermal | 12% | Coolant, oil, HV pack temp |
| Driveline | 10% | Trans temp, tire pressures |
| DTC | 8% | Active code count + severity |

Overall status: `good` (≥80), `attention` (≥60), `critical` (<60).

**Sparse sources score honestly.** A domain is only scored when its signals are
present; domains with no data are omitted and the weights are renormalized over the
domains that *were* scored. So a Salesforce vehicle that reports only coolant temp,
battery %, tire pressure, and DTC codes is scored on `thermal`, `battery`, `driveline`,
and `dtc` — `powertrain`/`emissions`/`fuel` are simply not fabricated.

## Salesforce integration

The `salesforce` backend reads the org directly with [`jsforce`](https://jsforce.github.io/):

| Canonical field | Salesforce source | Notes |
| --- | --- | --- |
| VIN | `Asset.SerialNumber` | Drives vehicle identity |
| Make / model / year | parsed from `Asset.Name` | e.g. `2019 Honda Accord` |
| Powertrain | inferred | EV if make is EV-only or `Engine_Temp_F__c` ≈ 0 |
| Odometer | `Vehicle_Telemetry__c.Odometer_Miles__c` | miles → km |
| Coolant temp | `Engine_Temp_F__c` | °F → °C (omitted for EVs) |
| Tire pressure | `Tire_Pressure_PSI__c` | PSI → kPa (applied to all four) |
| Battery | `Battery_Percent__c` | HV SoC for EVs; 12V proxy for ICE |
| DTCs | `DTC_Codes__c` | comma/space-separated; decoded via the catalog |

The fleet is driven by the VINs present in `Vehicle_Telemetry__c`, so only vehicles
that actually report telemetry appear — unrelated `Asset` records are ignored.

### Authentication (first match wins)

1. `SF_ACCESS_TOKEN` + `SF_INSTANCE_URL`
2. `SF_USERNAME` + `SF_PASSWORD` (+ `SF_SECURITY_TOKEN`, `SF_LOGIN_URL`)
3. **Salesforce CLI** — `sf org display --target-org $SF_TARGET_ORG` (default alias
   `vehicleHealth`). Easiest for local dev; just be logged in via `sf org login web`.

See `.env.example`. An expired CLI session is refreshed automatically on the next query.

### Actions on the Salesforce backend

Per-capability flags gate the two action tools:

| Action | Salesforce | Behavior |
| --- | --- | --- |
| `clear_dtcs` | **enabled** (`supportsClearDtcs`) | Inserts a new `Vehicle_Telemetry__c` snapshot carrying the latest readings with `DTC_Codes__c` emptied and a current timestamp. This becomes the newest reading, so subsequent reads report no active codes — a scan-tool-style clear that never mutates history. Requires `confirm=true`. |
| `send_command` | **disabled** (`supportsRemoteCommands`) | This org has no telematics command channel, so remote commands return a clear message and are not dispatched. |

Both actions are fully functional under the `simulator` backend.

## Setup

Requires Node.js 18+.

```bash
cd connected-vehicle-mcp
npm install
npm run build      # compile TypeScript to dist/
```

Run directly during development (no build step):

```bash
npm run dev
```

Inspect interactively with the MCP Inspector:

```bash
npm run inspect
```

## Register with an MCP client

The server speaks **stdio**. Add it to your client config. For Cursor
(`.cursor/mcp.json` or the workspace `.mcp.json`):

```json
{
  "mcpServers": {
    "connected-vehicle-health": {
      "type": "stdio",
      "command": "node",
      "args": ["/Users/sarfaraz.nawaz/Dev/PruJap/connected-vehicle-mcp/dist/index.js"],
      "env": {
        "VEHICLE_DATA_SOURCE": "salesforce",
        "SF_TARGET_ORG": "vehicleHealth"
      }
    }
  }
}
```

For Claude Desktop, add the same block to `claude_desktop_config.json`. To run
disconnected from an org, set `"VEHICLE_DATA_SOURCE": "simulator"`.

## Try it

Once connected to the org, ask the agent things like:

- "List the fleet and show any vehicle with health under 80." (Camry is critical)
- "Why is the check-engine light on for the 2018 Toyota Camry?" (reads + decodes DTCs)
- "Show the coolant temperature history for the Accord." (`get_parameter_history`)
- "Predict upcoming maintenance for the Camry." (overheat + misfire + low tires)
- "Is the Model 3's battery degrading?" (surfaces `P0A80` — replace hybrid battery pack)

## Safety & security notes

This simulator is for development. Before pointing it at real vehicles:

- **Gate all actions.** `clear_dtcs` and `send_command` require `confirm=true` and are
  annotated `destructiveHint`. Drive-affecting commands (`immobilize`/`mobilize`) should
  additionally require a second human approval and are always logged.
- **Scope auth per VIN** with short-lived tokens; never grant fleet-wide actuation by default.
- **Rate-limit and audit** every action; the simulator keeps an in-memory command log as a stand-in.
- **Treat VIN, GPS, and driver identity as PII.** Do not log to stdout (reserved for the MCP stream).

## Project layout

```
src/
  index.ts               MCP server: tool + resource registration, stdio transport
  provider.ts            DataProvider interface + factory (salesforce | simulator)
  salesforceProvider.ts  Live org backend: Asset + Vehicle_Telemetry__c via jsforce
  simulatorProvider.ts   In-memory simulator backend
  fleet.ts               Deterministic signal simulator + fault injection
  health.ts              Domain scoring + predictive-maintenance rules
  pids.ts                OBD-II PID catalog (PID → unit → reader)
  dtcCatalog.ts          DTC knowledge base + classifier for decode_dtc
  audit.ts               In-memory action/command audit log
  types.ts               Shared domain types
```

TDQS

A4/5.0

Scored across 9 tools

Disambiguation5/5

Each tool has a distinct purpose: vehicle listing, health scoring, DTC management (decode, get, clear), parameter history, live PIDs, maintenance prediction, and remote commands. No overlap.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in snake_case, e.g., list_vehicles, get_dtcs, send_command. No mixing of conventions.

Tool Count5/5

Nine tools is well-scoped for a vehicle health domain covering diagnostics, health monitoring, historical data, live data, predictions, and commands. Not over- or under-tooled.

Completeness5/5

The tool surface covers the full lifecycle: vehicle discovery, health assessment, DTC handling (get, decode, clear), parameter history, live readings, predictive maintenance, and remote commands. No obvious gaps for the stated purpose.

Maintenance

ActivityInactive
ResponsivenessNo recent community issues