MCP-CAN
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MCP-CANmonitor engine speed for 3 seconds"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
๐ MCP-CAN: Vehicle CAN Bus, OBD-II and J1939 Diagnostics for LLMs (Model Context Protocol)
๐ Virtual CAN + MCP Server
MCP-CAN is a Model Context Protocol (MCP) server that exposes automotive CAN bus, OBD-II (SAE J1979), UDS, and SAE J1939 diagnostic data to LLMs and AI agents. It ships a built-in virtual CAN bus with an ECU simulator, decodes traffic via a DBC database (cantools), and serves MCP tools over SSE or streamable-HTTP. No CAN hardware, adapter, or vehicle is required by default; optional SocketCAN/vCAN on Linux.
Use it to let an LLM read live CAN frames, decode signals, run OBD-II PID and UDS diagnostic requests, inspect J1939 PGNs/SPNs and DM1 trouble codes, and drive fault-injection scenarios, all against a simulated vehicle.
Keywords: MCP server, Model Context Protocol, CAN bus, CANbus, OBD-II, OBD2, on-board diagnostics, SAE J1939, UDS, ECU simulator, vehicle diagnostics, automotive, DBC, python-can, cantools, SocketCAN, LLM tools, AI agents.
โจ Highlights
MCP server for CAN/OBD/UDS-diagnostics/J1939 โ LLM/SLM (tools + DBC metadata, SSE or streamable-HTTP).
Virtual CAN backend (python-can) out of the box; optional SocketCAN/vCAN on Linux.
DBC-driven encoding/decoding via
cantools.ECU simulator that streams multiple messages, plus OBD-II, UDS-style, and SAE J1939 responders.
SAE J1939 (heavy-duty, 29-bit extended IDs): ID decomposition (priority/PGN/source+destination address), a curated PGN/SPN catalog (EEC1, EEC2, ET1, CCVS1, LFE1, DD1), Request PGN (
0xEA00) round trips, and DM1 active-DTC (SPN/FMI) broadcasts. Runs alongside the 11-bit bus; toggle withMCP_CAN_J1939_ENABLED.Correlated driving-dynamics signal generation, plus named fault-injection scenarios (
overheat,abs_fault,low_fuel) with matching DTCs.Typer CLI:
mcp-can(simulate, server, demo, frames, decode, monitor, dbc-info, obd-request, diag-request, fault, j1939-decode, j1939-pgns, j1939-request, j1939-dtcs).Structured tool output (typed Pydantic models), duration-capped tool calls,
/healthz, colorized logging.Read-only live web dashboard (
/dashboard): signal values and recent frames, updated over SSE.Dockerfile + docker compose for server + simulator.
Unit tests, type hints, lint config (ruff, mypy); see
CONTRIBUTING.md.
Related MCP server: connected-vehicle-health
๐ Repository Layout
src/mcp_can/cli.pyโ Typer commandsbus.pyโ python-can helpersdbc.pyโ DBC loading/decodingobd.pyโ OBD-II (SAE J1979) request/response helpersdiagnostics.pyโ UDS-style diagnostic service/response-code logicj1939.pyโ SAE J1939: 29-bit ID decomposition, PGN/SPN catalog, DM1 DTCs, Request PGNconfig.pyโ env settings (MCP_CAN_*) + logging setupmodels.pyโ internal bus-layer dataclass (Frame)simulator/runner.pyโ ECU simulator + OBD/diagnostic responderssimulator/j1939_runner.pyโ J1939 broadcasters (EEC1/ET1/CCVS1/โฆ), Request PGN responder, DM1 emittersimulator/state.pyโ correlated driving-dynamics state (RPM/speed/throttle/etc.)simulator/faults.pyโ named fault-injection presets + activation protocolserver/fastmcp_server.pyโ MCP tools/resources + dashboard routesserver/schemas.pyโ Pydantic models for MCP tool structured outputserver/live_state.pyโ background bus listener backing the dashboardserver/templates/dashboard.htmlโ the dashboard page itself
vehicle.dbcโ sample CAN database (incl. a UDS-like diagnostic schema)simulate-ecus.py,can-mcp.pyโ standalone run-without-installing entrypointsdocker/compose.yml,Dockerfiletests/โ unit testsCONTRIBUTING.md,CHANGELOG.md
โ Prerequisites
Python 3.10+
(Optional) Docker / Docker Compose
(Optional) Ollama if you want a local LLM backend
๐ฆ Install (Python)
From repo root:
pip install -r requirements.txt
pip install -e .๐ Quickstart (Simulator + MCP Server)
Two terminals:
# Terminal A: start ECU simulator on virtual bus0
mcp-can simulate
# Terminal B: start MCP server (SSE on 6278)
mcp-can server --port 6278Single-process (helps on Windows if virtual backend doesn't share across processes):
mcp-can demo --port 6278Sample interactions:
mcp-can frames --seconds 2
mcp-can decode 0x100 "01 02 03 04 05 06 07 08" # pretty table by default, --json for scripting
mcp-can dbc-info # table of every message/signal in the DBC
mcp-can monitor ENGINE_SPEED --seconds 3
mcp-can obd-request --service 0x01 --pid 0x0D
mcp-can diag-request --service-id 0x22 --parameter-id 0x05 # READ_DATA_BY_ID
mcp-can j1939-pgns # J1939 PGN/SPN catalog
mcp-can j1939-request 0xF004 # ask ECUs to send EEC1 (engine speed)
mcp-can j1939-dtcs # read the latest DM1 active-DTC broadcast๐ Live Dashboard
With mcp-can demo (or server) running, open http://localhost:6278/dashboard in a browser: live signal values grouped by ECU message, and a scrolling feed of recent frames, updating ~2x/second over Server-Sent Events. It's read-only (view only, no controls to send frames) and self-contained: no build step, no external assets, works offline. Like everything bus-related here, it only shows data when the simulator shares the same process as the server (mcp-can demo); pointed at a bare mcp-can server with no simulator, it just shows "waiting for CAN traffic."

๐ ๏ธ Available MCP Tools & Resources
Name | Type | Description |
| tool | Raw frames from the last |
| tool | Decode one frame's bytes into named signals. |
| tool | Like |
| tool | Timestamped samples of one decoded signal, from the same history buffer. |
| tool | Last known value of every signal seen so far, one entry per signal (not per frame) with an |
| tool | Standard OBD-II (SAE J1979) request; decodes known PIDs (coolant temp, speed, fuel level, fuel type). |
| tool | UDS-style diagnostic request ( |
| tool | Activate (or clear) a named fault-injection preset ( |
| tool | Decompose a 29-bit J1939 ID (priority / PGN / source + destination address) and decode known SPNs from the payload. |
| tool | The J1939 PGN/SPN catalog this server can decode and request (bit layout, scaling, units). |
| tool | Send a J1939 Request PGN ( |
| tool | Most recent J1939 DM1 broadcast: lamp status plus every active SPN/FMI. Served from the frame history buffer. |
| resource ( | Full DBC dump: nodes, messages, signals. |
read_can_frames/filter_frames/monitor_signal/read_j1939_dtcs are served from a single continuously-running history buffer (server/live_state.py) rather than each opening its own bus listener: they return immediately and won't miss frames sent between calls. send_obd_request/send_diagnostic_request/request_j1939_pgn are request/response and still wait live for a reply. In both cases, duration_s/timeout_s is capped by MCP_CAN_MAX_DURATION_S (default 30s; the history buffer retains at least that much, or 60s, whichever is larger). All tools return typed, structured content (see server/schemas.py) rather than ad-hoc JSON.
๐ฉบ About the diagnostic responder
vehicle.dbc defines a UDS-like diagnostic schema: DIAGNOSTIC_REQUEST (one shared request frame) and four DIAGNOSTIC_RESPONSE_<ECU> messages, one per ECU, but the request has no per-ECU target field. The simulator treats every request as functionally addressed to all four ECUs, so send_diagnostic_request/diag-request may return more than one response. Supported services: START_DIAGNOSTIC_SESSION (0x10) and RESET_ECU (0x11) are acknowledged OK; READ_DATA_BY_ID (0x22) returns a deterministic canned value derived from the parameter ID; ROUTINE_CONTROL/READ_MEMORY/WRITE_MEMORY and anything unrecognized return SERVICE_NOT_SUPPORTED; see diagnostics.py::handle_service.
โ ๏ธ Fault injection
Three named scenarios (simulator/faults.py::PRESETS) let you force the simulator into a specific fault state instead of waiting on random signal generation:
overheatโENGINE_TEMPpinned to its hottest reportable value,SYSTEM_STATUSset toFAULT_PRESENT, DTCP0217(Engine Overtemp Condition).abs_faultโ all fourWHEEL_SPEED_*signals stuck at zero,SYSTEM_STATUSset toFAULT_PRESENT, DTCC0035(Left Front Wheel Speed Sensor Circuit).low_fuelโFUEL_LEVELpinned critically low; no DTC (a low-fuel light isn't a stored trouble code on a real vehicle either).
Activating a scenario sends a small control frame on the bus (like OBD/diagnostic requests, this is a round trip to whichever process is running the simulator, so it needs mcp-can demo/simulate already running) and overrides the named signals until cleared. Any DTCs the active scenario sets show up in send_obd_request/obd-request's Mode 03 (service=3) response. Use mcp-can fault list or the activate_fault_scenario tool's docstring to see the current preset descriptions; pass preset=None (CLI: clear) to deactivate.
๐ SAE J1939 (heavy-duty)
Alongside the light-vehicle 11-bit bus, the simulator also speaks SAE J1939 โ the protocol on trucks, buses and off-highway equipment. J1939 rides 29-bit extended CAN IDs whose arbitration field is itself structured data: a 3-bit priority, an 18-bit Parameter Group Number (PGN), and an 8-bit source address (plus, for peer-to-peer "PDU1" PGNs, a destination address). src/mcp_can/j1939.py is a self-contained implementation of that layer (not DBC-driven โ vehicle.dbc models an 11-bit light-vehicle bus).
What's simulated (simulator/j1939_runner.py), driven by the same correlated driving-dynamics state as the 11-bit signals:
PGN | Acronym | Contents |
| EEC1 | Engine speed (SPN 190), actual engine percent torque (SPN 513) |
| EEC2 | Accelerator pedal position (SPN 91), percent load (SPN 92) |
| ET1 | Engine coolant temperature (SPN 110), fuel temperature (SPN 174) |
| CCVS1 | Wheel-based vehicle speed (SPN 84) |
| LFE1 | Engine fuel rate (SPN 183), throttle valve position (SPN 51) |
| DD1 | Fuel level (SPN 96) |
| DM1 | Active diagnostic trouble codes (SPN + FMI), broadcast at 1 Hz |
Request PGN (
0xEA00):request_j1939_pgn/mcp-can j1939-request <pgn>send a request; the simulator re-broadcasts the requested PGN once.DM1 / DTCs:
read_j1939_dtcs/mcp-can j1939-dtcsread the latest DM1. The fault-injection presets map to J1939 DTCs too โoverheatโ SPN 110 FMI 0,abs_faultโ SPN 84 FMI 5,low_fuelโ SPN 96 FMI 18 โ and the malfunction-indicator lamp turns on while a preset is active.J1939 signals also appear in
get_vehicle_snapshotand the dashboard, grouped underJ1939:<acronym>.Set
MCP_CAN_J1939_ENABLED=falsefor an 11-bit-only bus.
๐ MCP Inspector (GUI for your tools)
Use the official Inspector to explore and call your MCP tools without writing a host:
npx @modelcontextprotocol/inspectorWhen prompted, connect to your server:
URL:
http://localhost:6278/sse
You can then list tools/resources and call one (e.g. monitor ENGINE_SPEED for 5 seconds) and view structured output live.
๐ค Using with Ollama (local LLM)
Ensure Ollama is running:
ollama serveand pull a model:ollama pull llama3Run simulator + MCP server (see Quickstart).
Point your MCP-capable host at
http://localhost:6278/sseand configure its model endpoint tohttp://localhost:11434with your model name (e.g.,llama3).Prompt the host: "Monitor ENGINE_SPEED for 5 seconds", "List all DBC messages", or "Send a READ_DATA_BY_ID diagnostic request for parameter 5."
If you need a minimal host, pair @modelcontextprotocol/sdk with Ollama (see SDK docs) or use Inspector for manual tool calls.
Example host config (OpenAI-compatible endpoint to local Ollama):
{
"model": {
"type": "openai-compatible",
"baseUrl": "http://localhost:11434/v1",
"model": "llama3"
},
"mcpServers": {
"can-mcp-server": {
"serverUrl": "http://localhost:6278/sse"
}
}
}โจ๏ธ CLI Reference
mcp-can simulateโ start ECU simulator usingvehicle.dbc.mcp-can server [--port 6278] [--transport sse|streamable-http|stdio]โ run the MCP server.mcp-can demo [--port] [--transport]โ simulator + server in one process.mcp-can frames --seconds 1.0โ capture raw frames as JSON.mcp-can decode <id> <data> [--json]โ decode a single frame (table by default;idhex/decimal,dataspace/comma-separated bytes).mcp-can snapshot --seconds 1.0 [--json]โ latest value of every signal seen while listening.mcp-can dbc-info [message]โ table of every message/signal in the DBC, or just one message's.mcp-can monitor <signal> --seconds 2.0 [--json]โ watch one signal (live output by default).mcp-can obd-request --service <hex|int> [--pid <hex|int>]โ OBD-II request; response includes a decoded value for known PIDs.mcp-can diag-request --service-id <hex|int> [--parameter-id] [--data-field]โ UDS-style diagnostic request; prints every ECU's response.mcp-can fault <preset|clear|list>โ activate/clear a fault-injection scenario in a running simulator, or list available presets.mcp-can j1939-decode <id> <data> [--json]โ decompose a 29-bit J1939 ID and decode known SPNs.mcp-can j1939-pgnsโ list the J1939 PGNs/SPNs this project can decode.mcp-can j1939-request <pgn> [--timeout 2.0]โ send a J1939 Request PGN (0xEA00) and print decoded responses.mcp-can j1939-dtcs [--seconds 3.0]โ listen for a J1939 DM1 broadcast and print its active trouble codes.
server/demo/simulate all print colorized logs (via rich) instead of raw text.
โ๏ธ Configuration
Env vars (prefix MCP_CAN_):
CAN_INTERFACE(defaultvirtual)CAN_CHANNEL(defaultbus0)DBC_PATH(defaultvehicle.dbc)MCP_PORT(default6278)MCP_TRANSPORT(defaultsse;streamable-httprequires a newermcpSDK; the server logs a clear error and exits if the installed version doesn't support it, rather than crashing on an SDK traceback)MAX_DURATION_S(default30.0) โ caps every tool'sduration_s/timeout_sJ1939_ENABLED(defaulttrue) โ run the SAE J1939 side of the simulator alongside the 11-bit signalsLOG_LEVEL(defaultINFO)CORS_ALLOW_ORIGINS(default["*"], JSON array e.g.["https://your-host.example"]) โ allowed browser origins for the SSE endpoint. Credentialed requests (allow_credentials) are only enabled once this is narrowed to specific origins; wildcard + credentials is a combination browsers reject outright, so it's never turned on for the default"*". Override before any real deployment.
You can set these in a .env file at repo root.
๐ณ Docker
Build:
docker build -t mcp-can .Run (combined server + simulator):
docker run -d --name mcp-can -p 6278:6278 -p 5000:5000 -p 8080:8080 mcp-canCompose (from docker/):
docker compose up -d --buildThe compose file currently runs
serverandsimulatoras separate containers; like running them as two separate local processes, they won't share the virtual CAN bus unless the host provides a real sharedvcan0interface. For a working combined setup today, use the single-container Dockerfile above (mcp-can demo).
๐งช Development & Testing
See CONTRIBUTING.md for the full guide. Quick version:
pip install -r requirements.txt
pip install -e .
pip install pytest ruff mypy
ruff check .
mypy src
pytest -q๐ง Troubleshooting
No frames? Ensure both simulator and server use the same interface/channel (
virtual/bus0by default), and, on Windows, that they're the same process (mcp-can demo) rather than two separate ones.DBC missing? Set
MCP_CAN_DBC_PATHor placevehicle.dbcin repo root.Docker networking: expose
6278so your MCP host can reach it.streamable-httptransport fails immediately? Your installedmcppackage predates its support; the log line tells you. Switch tosseorpip install -U mcp(staying below2.0.0).
๐ License
MIT (see LICENSE). Educational/prototyping use only; use certified hardware for real automotive work.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Protocol-native energy infrastructure orchestration for AI data centers. Provides 46 MCP tools across 8 grid protocols (IEC-61850, DNP3, Modbus, OCPP, OpenADR, IEEE 2030.5, IEC 60870-5-104, ICCP) with 5 core API primitives: connect, dispatch, settle, comply, and intel. Enables AI agents to programmatically interact with substations, grid interfaces, and energy assets for real-time workload-grid coordination.
Deterministic reasoning stack for AI agents: simulate, decide & compute, plus cross-domain tools.
Gateway between LLM agents and world data through eight tools and a bundled endpoint catalog.
MCP-first toolbox for agents: KV storage, auth, queue, and utility tools. Free in early access.
Related MCP Servers
AlicenseNot gradedqualityCmaintenanceCarVector is a Model Context Protocol server that gives AI agents real vehicle data โ specifications and representative images, federal recall campaigns, and OBD-II DTC reference โ instead of hallucinating them. Open-source client (npx -y carvector-mcp), authenticated with your own key; free tier, no credit card. Four tools: search_vehicles, get_vehicle, get_recalls, lookup_dtc.126MIT- FlicenseAqualityCmaintenanceExposes a connected-vehicle OBD-II/telematics platform to AI agents, enabling vehicle health scoring, live data queries, DTC decoding, maintenance prediction, and gated remote commands via a pluggable data layer.9-

canforge-mcpofficial
AlicenseAqualityBmaintenanceLocal, read-only MCP server for inspecting DBC files and decoding CAN capture logs, with bounded and composable tools.13MIT- AlicenseAqualityBmaintenanceA local-first, read-only MCP server for vehicle diagnostics that exposes structured OBD-II tools for reading PIDs, DTCs, and ECU snapshots without raw protocol access.7Apache 2.0
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/farzadnadiri/MCP-CAN'
If you have feedback or need assistance with the MCP directory API, please join our Discord server