MCP Server · OBD-II
OBD-II MCP Server
A car's live diagnostics, exposed to LLM agents as MCP tools
Overview
Every car built since the mid-90s has an OBD-II port that speaks a standard diagnostic protocol — engine RPM, coolant temperature, trouble codes, emissions readiness, the lot. Reading it normally means a handheld scanner or hand-rolled serial code. This is an MCP server that puts all of that behind a set of tools an LLM can call. Plug an inexpensive ELM327 adapter into the car, point an MCP client at the server, and the model can ask the vehicle questions directly: what's running hot, what codes are stored, what the freeze-frame looked like when a fault tripped, whether there's an open recall. It's what connects an agent to the actual hardware in the driveway.
Demo
These tools, running on a real car. The live values streaming on the left — RPM, coolant temp, engine load — are this server reading a 2015 F-150 over an ELM327 adapter. When the agent in Mechanics Sidekick pulls the trouble codes and freeze frame, those calls land here.
Technology Stack
Server
- Python 3.11+
- FastMCP
- stdio transport
- pytest (148 tests)
Vehicle I/O
- python-OBD
- pyserial
- ELM327 adapter
- ELM327-emulator (CI)
Data & Lookups
- httpx
- NHTSA vPIC + recalls
- Wal33D DTC database
- OBDb signal sets
The Tools It Exposes
Eleven tools, grouped by what they do. An MCP client sees all of them with typed schemas and one-line descriptions.
Vehicle identity
get_vehicle_info— VIN, protocol, voltage; VIN decoded to year/make/model via NHTSAlist_supported_pids— what the ECU advertises
Live data
read_live_data— snapshot of requested PIDs (RPM, speed, temps…)record_session— time-bounded PID timeseries, stored as an MCP resourceread_freeze_frame— sensor snapshot from when a code set
Health & emissions
read_dtcs— stored / pending codes, with manufacturer-specific decodingread_readiness_monitors— emissions monitor statusclear_dtcs— clear codes (destructive; consent-gated)
Reference
lookup_recalls_and_complaints— NHTSA recalls + complaintslist_manufacturer_signals— bundled Mode 22 signal catalogueping— health check
Architecture & Design Choices
It speaks MCP over stdio, so any client launches it as a subprocess. The ELM327 handshake is slow, so a single connection is opened once in the server's lifespan and pooled for the life of the process rather than re-dialed per call. The same pyserial URL scheme covers a USB cable, a Bluetooth adapter, a WiFi ELM327 clone, or a simulator — which is how the 148-test suite runs in CI against Ircama's ELM327 emulator with no hardware attached.
OBD is flaky by nature, so errors split two ways. A dead adapter or a failed bus init is a real failure — that surfaces as a tool error. But a single PID the ECU doesn't support isn't a failure; partial results are the normal case. So per-PID outcomes like NOT_SUPPORTED or NO_DATA come back in-band as data, not exceptions. The model gets to see exactly what the car could and couldn't answer instead of the whole call blowing up.
Clearing trouble codes also wipes emissions readiness monitors and can mask a fault that's about to recur, so clear_dtcs is the one destructive tool — and it's gated behind MCP elicitation. The server asks the host to confirm with the user before it runs, and fails closed if the host doesn't support that handshake. Mechanics Sidekick, the assistant that consumes this server, goes a step further and denylists the tool entirely, staying read-only against the car.
What Works Today
v0.1.0, 148 tests, CI green. Validated against the ELM327 simulator and confirmed on a real vehicle — a 2015 F-150. Live PID reads, trouble codes with manufacturer-specific decoding, freeze-frame data, emissions readiness, VIN decode through NHTSA, recall and complaint lookups, and time-bounded session recording all work end to end. Manufacturer Mode 22 signals currently ship as metadata (Ford Mustang and F-150). Licensed Apache-2.0.