gta-sa-mcp
Click on "Deploy 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., "@gta-sa-mcpreload myplugin.asi from C:/build and show its latest log lines"
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.
gta-sa-mcp
MCP server that lets a coding agent drive a live GTA San Andreas process — read game state, spawn stuff, run any SCM opcode, poke memory, and hot-reload the plugin you're building without restarting the game.
Built for GTA SA 1.0 US plugin development. 73 tools, one named pipe, zero game restarts.
What it's for
You're writing a .asi plugin with plugin-sdk. Normally every test cycle is: build → copy .asi → restart game → load save → drive to a spot → check. That's minutes per iteration.
With this, the agent does:
game_launch # boots + skips intro automatically
plugin_reload({pluginName:"myplugin.asi", path:"C:/build/myplugin.asi"})
plugin_log_read({pluginName:"myplugin.asi"})
screenshot…and sees the result. Iteration is seconds.
Concrete uses:
Use | How |
Plugin dev loop |
|
Verify behaviour |
|
Set up a scenario |
|
Test hotkeys |
|
Reverse engineering |
|
Call anything |
|
Cinematic shots |
|
Not for: playing the game, speedrunning, or Definitive Edition (classic 1.0 US only).
Related MCP server: LÖVE2D MCP Server
Install
1. Requirements
GTA San Andreas 1.0 US (Compact or Hoodlum exe)
ASI Loader in the game folder — Ultimate ASI Loader
Bun ≥ 1.0
Windows (the bridge is Win32-only)
2. Drop in the bridge
Download debug_bridge.asi from the latest release and copy it next to gta_sa.exe.
The bridge is dormant unless mcp_debug.lock exists in the game directory — if you launch the game normally, it does nothing and costs nothing.
3. Get the server
git clone https://github.com/mbahArip/gta-sa-mcp.git
cd gta-sa-mcp
bun install4. Find your game path
Resolution order: --gamePath= arg → GTASA_PATH env → Windows registry → error. If GTA SA is in the default Rockstar/Steam location, the registry works and you can skip this.
Use with a coding agent
The server speaks stdio MCP. Point any MCP client at it.
opencode / jcode (~/.config/opencode/opencode.json)
{
"mcp": {
"gta-sa-mcp": {
"type": "local",
"enabled": true,
"command": ["bun", "run", "C:/path/to/gta-sa-mcp/src/index.ts"],
"environment": {
"GTASA_PATH": "D:/Games/gta sa/GTA San Andreas"
}
}
}
}Claude Desktop / Cursor / Antigravity (mcpServers shape)
{
"mcpServers": {
"gta-sa-mcp": {
"command": "bun",
"args": ["run", "C:/path/to/gta-sa-mcp/src/index.ts"],
"env": {
"GTASA_PATH": "D:/Games/gta sa/GTA San Andreas"
}
}
}
}Use forward slashes in paths. Restart the client after editing.
First session
game_launchLaunches the game, creates mcp_debug.lock, waits for the pipe. The bridge auto-skips the intro cutscene so you land in gameplay.
Then confirm:
game_status # { running, bridgeConnected, state }
game_state # { scene: "in_game", ... }The one rule
Gameplay commands only execute when scene === "in_game". During loading, menu, pause, or a cutscene they queue and expire after 15 seconds with:
queued command expired waiting for gameplay (15s)That is not a bug — check game_state first. game_state itself always answers immediately (served from a 100 ms cache).
Tool reference
73 tools across 11 modules. Full parameter docs: docs/COMMANDS.md.
Module | # | Tools |
| 7 |
|
| 11 |
|
| 10 |
|
| 9 |
|
| 18 | time, weather, timescale, gravity, traffic/ped density, explosions, objects, pickups, fire, pool dump, radar blips |
| 7 |
|
| 2 |
|
| 4 |
|
| 3 |
|
| 1 |
|
| 1 |
|
Escaping the tool surface
Anything not wrapped is still reachable:
sdk_lookup({ category: "vehicles", query: "infernus" }) # → 411
script_call_opcode({ opcode: 0x0107, types: "int", values: "8" }) # SET_WEATHER rainyscript_call_opcode runs raw SCM commands, so the whole game script API is in reach without waiting for a tool wrapper.
Plugin development
Loop
game_state # must be in_game
plugin_unload({ pluginName: "myplugin.asi" })
# msbuild /p:Configuration=Release /p:Platform=Win32
plugin_load({ path: "myplugin.asi" })
plugin_log_read({ pluginName: "myplugin.asi", clear: true })
screenshotOr, when the build lands somewhere else and the module name stays stable:
plugin_reload({ pluginName: "myplugin.asi", path: "C:/build/myplugin.asi" })Hot reload gotchas
File lock. Windows locks a loaded DLL against writes.
plugin_reloadto the same path can't work if the build failed mid-write — unload first, build, then load. Building to a scratch dir and reloading from there avoids the issue entirely.No rollback. Unload happens before load. A broken build leaves the feature gone, not the old version running. Read the error:
126= missing dependency,193= wrong architecture (must be Win32 x86),998= bad path.Verify it actually reloaded. If your refcount is >1,
FreeLibrarydrops a count andLoadLibraryAreturns the existing module — stale code, silently. Compare the returnedhandleto the previous one.Freeing a hooked plugin crashes. Revert every
injector::patch and unregister everyEvents::handler before unload.debug_bridge.asicannot protect you from a jump into freed memory.Bridge can't reload itself. Restart the game to update
debug_bridge.asi.
Plugin-side requirements
// 1. Log buffer for plugin_log_read
extern "C" __declspec(dllexport) char GtaMcpDebugLog[4096] = {};
extern "C" __declspec(dllexport) int GtaMcpDebugLen = 0;
// 2. Unload export — bridge calls this before FreeLibrary
extern "C" __declspec(dllexport) void GtaMcpUnload() {
Events::gameProcessEvent -= myHandler;
Events::drawingEvent -= myDraw;
patch::NopRestore(/* ... */);
}The bridge also accepts PluginUnload and OnUnload as fallback names. Log writes go through the exported buffer, so GtaMcpDebugLen must track the byte count.
Log is capped at 4096 bytes; clear: true zeroes it.
Build the bridge from source
Needs Visual Studio 2022 (v145 toolset) and a plugin-sdk checkout.
# plugin-sdk must be a sibling of this repo, or point the env var at it
git clone https://github.com/DK22Pac/plugin-sdk ../plugin-sdk-sa# sibling layout (default)
msbuild bridge/debug_bridge.vcxproj /p:Configuration=Release /p:Platform=Win32
# custom plugin-sdk location
set PLUGIN_SDK_ROOT=C:\dev\plugin-sdk
msbuild bridge/debug_bridge.vcxproj /p:Configuration=Release /p:Platform=Win32Output: bridge/Release/debug_bridge.asi. Copy it to the game folder.
Platform=Win32 is mandatory — GTA SA is 32-bit. An x64 build fails to load with error 193.
Debugging without the MCP layer
bun tools/pipe-test.ts game_state
bun tools/pipe-test.ts vehicle_spawn modelId=477 offsetX=0
bun tools/pipe-test.ts player_teleport x=2495 y=-1687 z=13Raw pipe client, no MCP. Useful when the server itself is suspect.
Architecture
agent ──stdio MCP──> src/index.ts ──named pipe──> debug_bridge.asi ──> GTA SA
(Bun/TS) \\.\pipe\gtasa_mcp_bridge (in-process, game thread)src/pipe.ts— pipe client, newline-delimited JSON, 20 s default timeout, 100 msgame_statecachesrc/process.ts— launch/detect/kill,mcp_debug.locksentinelsrc/config.ts— path resolutionsrc/tools/*.ts— one file per domain, each exports aregister*Tools(server)bridge/Main.cpp— pipe server thread + all command handlers
Threading. Commands arrive on a pipe thread, get queued, and are drained inside Events::gameProcessEvent on the game thread — so handlers can touch game memory safely. Only game_state is answered off the pipe thread (it reads nothing that needs the game thread), which is why it responds during loading.
Protocol.
// request
{"id": 1, "cmd": "vehicle_spawn", "modelId": 411}
// response
{"id": 1, "ok": true, "data": {"handle": 12}}
{"id": 1, "ok": false, "error": "..."}Commands queue while not in_game, with a 15 s TTL. Failures surface as ok: false, never fabricated data.
Environment variables
Variable | Default | Purpose |
| (registry) | Game directory |
|
| Pipe connect timeout (ms) |
|
| Max wait for process to appear (ms) |
|
| plugin-sdk location, build time only |
Troubleshooting
Symptom | Cause |
| Bridge not loaded, |
| Scene isn't |
| Plugin built x64; rebuild |
| Missing dependency DLL next to the plugin |
| By design — restart the game |
| Add both exports to your plugin |
| A stale |
License
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
AI-native programming language and toolchain for accountable, verifiable agent-driven development.
Agent Replay Debugger MCP — record every agent step + deterministic replay. Step-debugger for
Persistent memory, hybrid search and a goal graph for AI agents, over stdio or remote HTTP.
Shared control plane for AI coding agents — tasks, memory, decisions, file locks. 12 tools.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceEnables local FiveM development by letting an AI assistant execute JavaScript/Lua on the server or client, automate NUI interactions, capture game screenshots, manage resources, and run repeatable tests with screenshot evidence.4MIT
- AlicenseAqualityBmaintenanceEnables AI assistants to interact with running games in real time — introspecting game state, simulating keyboard and mouse input to actually play, capturing screenshots, executing Lua code, hot-reloading files, and receiving push notifications when state changes.8MIT

PyMemoryEditorofficial
AlicenseAqualityAmaintenanceLet an AI agent read, write and scan the memory of running processes on Windows, Linux and macOS, Cheat Engine style: value scans, refinement and pointer chains.149,570 PyPI226MIT- AlicenseAqualityAmaintenanceLets AI agents build, run and live-test FiveM servers by sending server and client console commands over RCON and devcon, driving the game window with keyboard, mouse and screenshot automation, and invoking in-game natives, exports and NUI callbacks through a companion bridge resource.2357 npm17MIT