-
Notifications
You must be signed in to change notification settings - Fork 2
MCP Tools Reference
All tools are registered in server/fastmcp_server.py::create_app() and return typed Pydantic models (server/schemas.py) — MCP clients see a real outputSchema, not ad-hoc JSON. duration_s/timeout_s parameters are capped by Settings.max_duration_s (default 30s) everywhere they appear — see Configuration.
These read from the server's continuously-running frame history buffer (server/live_state.py) and return near-instantly — they never block waiting for new traffic, and won't miss frames sent between calls.
read_can_frames(duration_s: float = 1.0) -> List[FrameOut]
Every raw frame seen in the last duration_s seconds.
decode_can_frame(arbitration_id: int, data: List[int]) -> DecodeResult
Decode one frame's bytes into named signals using the loaded DBC. Not tied to live traffic — pass any arbitration_id/data you like.
filter_frames(arbitration_id: Optional[int] = None, signal_name: Optional[str] = None, duration_s: float = 1.0) -> List[FrameOut]
Like read_can_frames, filtered by arbitration ID and/or a decoded signal name.
monitor_signal(signal_name: str, duration_s: float = 2.0) -> List[SignalSample]
Timestamped samples of one decoded signal over the window.
get_vehicle_snapshot() -> VehicleSnapshot
The last known value of every signal seen so far — one entry per signal, not per frame — with an age_s freshness indicator (how long ago that value last updated). A single-call overview instead of decoding a stream of raw frames yourself. Built on the same signal tracking the dashboard uses, so it's effectively free.
These send something on the bus and wait for a reply, so they open (and always clean up) their own bus connection.
send_obd_request(service: int, pid: Optional[int] = None, timeout_s: float = 2.0) -> ObdResponse
Standard OBD-II (SAE J1979) request. Known PIDs get a decoded value (coolant temp, speed, fuel level, fuel type); Mode 03 (service=3) returns any active fault-injection DTCs. See Diagnostics and OBD-II for the full PID table.
send_diagnostic_request(service_id: int, parameter_id: int = 0, data_field: int = 0, timeout_s: float = 2.0) -> DiagnosticResult
UDS-style diagnostic request (vehicle.dbc's DIAGNOSTIC_REQUEST). Because that message has no per-ECU target field, every request is functionally addressed to all four simulated ECUs — expect up to 4 responses. See Diagnostics and OBD-II for supported service IDs.
activate_fault_scenario(preset: Optional[str] = None, timeout_s: float = 2.0) -> FaultScenarioResult
Activate a named fault scenario (overheat, abs_fault, low_fuel), or clear the active one with preset=None. See Fault Injection for what each preset does and which DTCs it sets.
Full DBC dump: nodes, messages (id, length, cycle time, senders), and every signal's bit layout, scale/offset, range, unit, and choices. Use this for discovery instead of guessing signal names; mcp-can dbc-info is the CLI equivalent for a quick look without an MCP client.
| Route | Purpose |
|---|---|
GET /healthz |
Health check: 200 if the DBC loaded successfully, 503 otherwise |
GET /dashboard |
The live dashboard page — see Dashboard |
GET /dashboard/stream |
SSE stream backing the dashboard |
GET /.well-known/oauth-authorization-server/sse, GET /.well-known/oauth-protected-resource
|
Stub discovery endpoints so MCP Inspector's auth probing doesn't block (this server has no auth) |
Every tool's return type lives in server/schemas.py:
| Model | Used by |
|---|---|
FrameOut |
read_can_frames, filter_frames
|
SignalSample |
monitor_signal |
DecodeResult |
decode_can_frame |
ObdResponse |
send_obd_request |
DiagnosticEcuResponse / DiagnosticResult
|
send_diagnostic_request |
FaultScenarioResult |
activate_fault_scenario |
SignalState / VehicleSnapshot
|
get_vehicle_snapshot |
All of them include a status/message pattern for error cases rather than raising through the MCP transport — check status before trusting the rest of the payload.
Getting started
Reference
Simulation features
Operating it
Contributing