MCP server for BeamNG.drive (Steam consumer build) with an AI race-engineer loop
37 tools with generally clear naming (verb_noun pattern) and detailed descriptions (100-300 chars typical). Most parameters have type definitions and descriptions. However, output schemas are not explicitly documented in the source code, only inferred from docstrings. Several tools lack parameter constraints (enums for mode/level choices). Error handling guidance is minimal. Tool composition is strong (each does one thing), but some tools combine multiple concerns (e.g., spawn also loads scenarios). No evidence of secret injection patterns or permission gates.
Analyze a recorded lap CSV: validity, lap time, speed/grip/braking/balance metrics, corners, and driver-technique tips.
Apply a race_engineer plan (or an explicit {$var: value} map), optionally persisting it as a .pc build. Applying RESPAWNS the car.
Driver-technique coach: read a lap and return tips (braking, coasting, corner speed, steering, throttle commitment) grounded in measured channels.
Lap-to-lap comparison: baseline vs candidate, with deltas on time/speed/grip/balance/braking and a verdict.
ATTACH to the BeamNG.drive game the user is ALREADY running (default). Does NOT launch the game, load a scenario, or spawn anything — it just opens the tech socket so other tools can read/modify the player's current car. The user must have opened it in-game first (console `~`): extensions.load('tech/techCore'); tech_techCore.openServer(25252). Disconnecting an attached session LEAVES THE GAME RUNNING. Pass launch=True only to have the server start (and own) its own instance.
Output schemas not explicitly documented. Tool descriptions infer return structure but no formal schema definitions visible in source code. LLMs cannot reliably predict response fields for chaining.
Missing parameter constraints (enums). Tools like spawn (level, ai_mode), run_test (ai_mode), and set_control accept free-form strings where enums would prevent hallucinated values.
Error handling lacks recovery guidance. Tools return errors via _call() wrapper but no actionable next steps (e.g., 'Connection failed. Try doctor() first'). Agents cannot self-correct.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 69 | 2026-07-28+ | v2 |
List the vehicles already in the running game, flagging the car the user is driving. Read-only; spawns nothing.
Close the BeamNGpy session and clear all session state.
Health-check EVERYTHING (run this first when anything misbehaves, or for first-time setup): game install + user folder paths, whether the game is listening on the tech socket, OutGauge/MotionSim protocol settings — including the known settings corruption that silently breaks every vehicle spawn game-wide — port collisions, a live OutGauge probe, and the beamngpy/game version pairing. Each finding comes with the exact fix. Needs no connection.
Draw the racing line (from a lap) on the in-game map.
Execute raw Lua code in the game and return the result (power-user only).
Return the part-config (installed parts + saved tuning vars) of the car you're CURRENTLY driving (vid=None). For the FULL tunable surface (every $var, not just the saved subset) use get_tuning_full.
Return the FULL tunable surface: every $var with its current value, min/max, unit, title.
Return the path to the most recent recorded lap CSV.
List available .pc configs in the user vehicles folder.
List drivable models from install content/vehicles + user vehicles.
Report pit-wall session state (active, laps recorded, current analysis).
Generate a matplotlib plot of a recorded lap (speed, g-forces, steering, throttle/brake over distance).
Driver feel + the recorded lap -> a ranked $var setup plan + brief.
Read a .pc config JSON from the user folder (confined).
List recent recorded lap CSVs (most recent first).
Cleanly close and reopen the attach connection — recovers a stale GE session (e.g. after the game was restarted). Does NOT clear a game-side per-vehicle socket wedge; that needs a BeamNG.drive restart.
ACTIVE MODE (drives the car): spawn-if-needed, enable the BeamNGpy AI, sample telemetry for duration_s, return a summary. Only when the user explicitly asks for a test run.
Save the current car's config as a .pc file.
Apply a part-config to the car you're CURRENTLY driving (vid=None): pass a full or partial part-config tree (as from get_config). NOTE: applying a config RESPAWNS the car at its location (BeamNG repairs it and resets damage — exactly like the in-game parts menu).
ACTIVE MODE (only when the user explicitly asks Claude to drive): send driving inputs to the current car (vid=None). Does nothing unless called.
Apply a {$var: value} map to the current car (or vid). Respawns the car.
ACTIVE MODE (takes over the session): spawn a NEW vehicle, creating/ loading a scenario if none is active. NOT used for normal 'change car config' — that operates on your current car via get_config/set_config. Use spawn only if you explicitly want a fresh test car on a test level.
Start recording a drive log (telemetry CSV).
Start a pit-wall session: record laps, auto-analyze, and coach the driver between runs.
Start a parameter sweep: vary one or more $vars over a range and record lap times.
Report connection state, active scenario, spawned vehicles, config.
Stop the current drive log and return its path.
Stop the pit-wall session.
Stop the current parameter sweep.
Report parameter sweep state (active, progress, results so far).
Poll live telemetry of the car you're CURRENTLY driving (vid=None): Electrics channels (rpm, wheelspeed, gear, throttle, brake, fuel, oil/water temps, boost, per-wheel brake temps...) plus Damage/GForces and State kinematics.
Write/overwrite a .pc config
Destructive operations (eval_lua, write_pc, set_config) lack confirmation/dry-run patterns. eval_lua is marked IRREVERSIBLE but has no safeguards. Agents can execute arbitrary Lua without review.
No permission gates or scope declarations. Tools like eval_lua and write_pc have no access control. No audit trail visible for who called what and when.