{
  "markdown": "# fivem-mcp\n\n[![npm version](https://img.shields.io/npm/v/fivem-mcp-server)](https://www.npmjs.com/package/fivem-mcp-server)\n[![license: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![CI](https://github.com/ziyacivan/fivem-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/ziyacivan/fivem-mcp/actions/workflows/ci.yml)\n\nAn MCP (Model Context Protocol) server that lets AI agents — Claude, Qwen, or anything\nthat speaks MCP — **build, run and live-test FiveM servers** from the same machine.\n\nIt is the missing test layer for the \"did it actually work in-game?\" question: the agent\ncan run real console commands, watch both the server log and the *live F8 console of a\nrunning FiveM client*, wait for specific output, and react — without you touching the\nkeyboard.\n\n```\nagent (Claude / Qwen / …)\n   │  MCP over stdio\n   ▼\nfivem-mcp-server ──► UDP RCON / getinfo ──► FXServer (game port, e.g. 30120)\n                   ──► TCP devcon (29200/29300) ──► FiveM Legacy client F8 console\n                   ──► tail ─────────────────────► FXServer's redirected stdout log\n```\n\n## Status\n\nv0.5 drives the whole loop: server console (RCON), client F8 console (devcon), the game\nwindow (launch, focus, screenshot, keyboard/mouse) and an in-game bridge (`mcpb`) for\nnatives, exports and NUI callbacks — plus ready-made test prompts. Tools answer with\nstructured content, carry MCP annotations, and stop as soon as the client cancels. All of it live-verified\nagainst a real FXServer + FiveM Legacy client (see `docs/plan.md` and `scripts/live-*.mjs`).\n\n## Where it is published\n\n| Channel | Address |\n| --- | --- |\n| npm | [fivem-mcp-server](https://www.npmjs.com/package/fivem-mcp-server) — `npx -y fivem-mcp-server` |\n| MCP Registry | `io.github.ziyacivan/fivem-mcp` ([registry.modelcontextprotocol.io](https://registry.modelcontextprotocol.io)) |\n| Source releases | [GitHub Releases](https://github.com/ziyacivan/fivem-mcp/releases), tagged `vX.Y.Z` |\n\nThe repository's GitHub **Packages** sidebar is deliberately empty: the artifact lives on\nnpmjs.com, not GitHub Packages — the latter would force a scoped `@ziyacivan/` package name\nand a second registry for no benefit.\n\n## Requirements\n\n- Node 22+ (Windows, macOS or Linux for the server side; the client devcon works\n  wherever the FiveM client runs — this tool must run on that machine for the\n  `client_*` tools since devcon binds to localhost by default).\n- A running FXServer you administer (`rcon_password` set for `server_command`).\n- The Legacy FiveM client for the client-console tools (Enhanced removed the\n  client devcon ports; see [docs/protocol.md](docs/protocol.md)).\n- The keyboard/mouse/screenshot tools are **Windows-only** and run on the machine\n  with the game. On other platforms every tool except those is served normally.\n\n## Install\n\nPublished on npm — no clone needed. Add it to **Claude Code** in one line:\n\n```sh\nclaude mcp add fivem -s user \\\n  -e FIVEM_RCON_PASSWORD=your-rcon-password \\\n  -e FIVEM_SERVER_LOG=C:\\FXServer\\my-data\\server.log \\\n  -- npx -y fivem-mcp-server\n```\n\n(`-s user` = available in every project; drop it for a per-project entry. Verify with `claude mcp get fivem` — status should read ✓ Connected. Remove with `claude mcp remove fivem -s user`.)\n\nFor a **shared project config**, put `.mcp.json` in the repo root and commit it —\nClaude Code asks to approve it on first open, and env values can be interpolated\nfrom your local `.env`-less shell via `${VAR}` expansion:\n\n```json\n{\n  \"mcpServers\": {\n    \"fivem\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"fivem-mcp-server\"],\n      \"env\": {\n        \"FIVEM_RCON_PASSWORD\": \"${FIVEM_RCON_PASSWORD}\",\n        \"FIVEM_SERVER_LOG\": \"${FIVEM_SERVER_LOG}\"\n      }\n    }\n  }\n}\n```\n\nFor **Claude Desktop** (or any client with JSON config), add to\n`claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"fivem\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"fivem-mcp-server\"],\n      \"env\": { \"FIVEM_RCON_PASSWORD\": \"your-rcon-password\" }\n    }\n  }\n}\n```\n\nThe server is also listed in the MCP Registry as\n`io.github.ziyacivan/fivem-mcp`. Building from source (development):\n\n```sh\ngit clone https://github.com/ziyacivan/fivem-mcp\ncd fivem-mcp && pnpm install && pnpm build\nclaude mcp add fivem -- node ./dist/index.js        # points at your working copy\n```\n\n## Configuration (environment)\n\n| Variable | Default | Meaning |\n| --- | --- | --- |\n| `FIVEM_HOST` | `127.0.0.1` | Machine running the FiveM client (devcon host) |\n| `FIVEM_EXECUTABLE` | `%LOCALAPPDATA%\\FiveM\\FiveM.exe` | FiveM.exe for the `launch` tool |\n| `FIVEM_CLIENT_DEVCON_PORT` | `29200` then `29300` | Override the client devcon port |\n| `FIVEM_RCON_ADDRESS` | `FIVEM_HOST:30120` | FXServer game port (UDP RCON + getinfo) |\n| `FIVEM_RCON_PASSWORD` | — | Matches `rcon_password` in `server.cfg`; needed by `server_command` |\n| `FIVEM_SERVER_LOG` | — | Path to FXServer's redirected stdout; enables server-side `read_console` / `wait_for_console`. Not needed by the bridge since v0.5 (results poll in-band) — it is the pre-0.5 fallback transport |\n| `FIVEM_MCPB_TOKEN` | — | Matches `mcpb_token` on the server; sent with every bridge request |\n| `FIVEM_CONSOLE_CAPACITY` | `5000` | Client console lines kept in the ring buffer |\n| `FIVEM_QUIET_MS` | `400` | Consider command output done after this quiet period |\n| `FIVEM_COMMAND_TIMEOUT_MS` | `5000` | Default max wait for `client_command` output |\n| `FIVEM_MCP_DEBUG` | — | `1` traces devcon frames and RCON round-trips on stderr |\n\n## Tools\n\n| Tool | What it does |\n| --- | --- |\n| `status` | Connection state: RCON, log file, client devcon. Call first. |\n| `server_info` | `getinfo` over UDP — hostname, players, max clients, protocol, game build. **No credentials needed.** |\n| `server_command` | Any server console command over UDP RCON; returns the captured output. |\n| `client_command` | Types into the F8 console of a running Legacy client over devcon (nothing steals focus). This is the **local console command** layer — `connect`, `quit`, tooling; `RegisterCommand` chat commands are a different system (use `server_command`, which runs with console privileges, or the input/bridge tools). Returns the console lines it printed. |\n| `read_console` | Recent lines: client = live devcon stream (with `afterSeq` paging), server = tail of `FIVEM_SERVER_LOG`. Filter by `channel`/`contains`/`pattern`. |\n| `wait_for_console` | Block until a line matching a regex appears — your assertion primitive. |\n| `list_commands` | Every command the client console knows (devcon handshake). |\n| `launch` | Start FiveM, optionally straight into `host:port` (default: the configured server). |\n| `quit_game` | Graceful `quit` over devcon; `force` kills the FiveM process tree. |\n| `window_status` | Game window existence, title, pid, rect, foreground state. |\n| `focus_window` / `restore_focus` | Bring the game forward / give focus back to your window. Input tools focus automatically. |\n| `screenshot` | PNG of the game window (PrintWindow, screen-BitBlt fallback). Downscaled — default 900, optional `crop` rect. Every shot costs transcript tokens all session: prefer text probes, shoot small. |\n| `press_key` / `hold_key` / `release_key` | Real scan-code input — GTA's DirectInput ignores VK-only injection. Held keys are released if the process dies. |\n| `type_text` | Literal Unicode events — the channel the F8 console and chat NUI read. |\n| `mouse_move` / `click` / `scroll` | Relative moves drive the camera; absolute coordinates position the cursor for NUI. |\n| `wait` | Pause between actions (loading screens, walk cycles). |\n| `read_client_log` | The newest `CitizenFX_log_*.log` from the FiveM install. |\n| `bridge` | Invoke the `mcpb` bridge resource: `ping`, `players`, `poll`, `call_export`, `trigger_event` (server half) and `ping`, `position`, `teleport`, `freeze`, `call_native`, `send_nui`, `nui_callback` (client half). `op` is validated against the chosen target. |\n\n## Prompts\n\nTwo workflows are shipped as MCP prompts, distilled from the live-verified loops:\n\n- **`test_resource(resource, expectations?)`** — clean restart → console error scan →\n  client-half scan → in-game scenario (keys, screenshot, bridge state) → evidence-backed\n  PASS/FAIL report where anything unverifiable is said so out loud.\n- **`smoke_check`** — one fast sweep: connections, which server, error tails on both sides,\n  window + screenshot, persisted client log. OK/WARN/DOWN per line.\n\n## The bridge resource (`bridge/`)\n\nClient-side testing (natives, NUI callbacks, position) is outside what devcon and RCON can\nreach — the small companion resource closes that gap and ships in this repo.\n\n```sh\n# on the dev server\ncp -r bridge/ <server-data>/resources/mcpb     # or a junction\n# server.cfg:\n#   ensure mcpb\n#   setr mcpb_enabled true\n#   setr mcpb_token <a-random-token>\n#   setr mcpb_event_allowlist  my:event,other:event      # trigger_event may fire only these\n#   setr mcpb_export_allowlist myres:*,other:method       # optional; empty = any export\n#   setr mcpb_native_allowlist SetEntityHealth,GetGameTimer   # optional; empty = any native\n#   setr mcpb_client_timeout_ms 8000                      # a silent client fails fast\n#   setr mcpb_verbose true                                # echo requests to both consoles\n```\n\nand point this server at it with `FIVEM_MCPB_TOKEN`. Then:\n\n```\nbridge { target: \"client\", src: 1, op: \"position\" }\nbridge { target: \"server\", op: \"call_export\", args: \"{\\\"resource\\\":\\\"myres\\\",\\\"method\\\":\\\"money\\\",\\\"args\\\":[1]}\" }\n```\n\nClient results come back through an in-band queue polled over RCON (~100 ms granularity\nsince v0.5 — no log file needed; pre-0.5 resources still fall back to the log tail).\n\n**Dev servers only.** `mcpb_enabled` defaults to `false`, the command is accepted only from\nthe console/RCON (never from a player), and the token is checked when set — but\n`call_native` is exactly as safe as the console it runs behind. Keep RCON and this bridge\noff anything you care about; see [SECURITY.md](SECURITY.md). The full wire contract: [docs/protocol.md §4](docs/protocol.md).\n\n## Typical loop (what an agent does)\n\n1. `server_command: \"ensure my-resource\"`\n2. `wait_for_console: target=server, pattern=\"Started resource my-resource|Error\"`\n3. `client_command: \"connect localhost:30120\"` drives the join itself, then\n   `read_console: target=client` catches client-side console output that never\n   reaches the server log.\n\n## Security notes — read before exposing anything\n\n- **The client devcon socket has no authentication.** Anyone who can reach it can run\n  local console commands in that game client (connect, quit, ...). FiveM binds it to\n  `127.0.0.1` unless the client is started with `-devcon` (then `0.0.0.0`); this tool\n  assumes the loopback default and never needs more. Do not tunnel it.\n- **RCON is the server's admin root.** Keep `rcon_password` strong; `FIVEM_RCON_PASSWORD`\n  lives in your MCP config — protect that file the same way.\n- FXServer itself has no server-side devcon socket on current builds (verified\n  2026-09-02), which is why the server half is RCON + log tail.\n- Treat `server_command` as giving the agent root on your box the moment it can\n  `exec` anything; run it only against **development** servers.\n\n## Development\n\n```sh\npnpm test        # vitest: fake devcon/rcon servers, byte-level SendInput/PNG checks, bridge contract, docs drift\npnpm typecheck\npnpm check       # biome\npnpm build       # -> dist/\npnpm run ci      # all of the above (plain `pnpm ci` is a pnpm builtin and errors)\n```\n\nReleasing: move the `Unreleased` changelog notes under the new version heading, then\n`pnpm version <patch|minor|major>` (bumps and syncs `server.json` + the bridge manifest,\nand tags), `npm publish` from your machine (`prepublishOnly` runs the full gate), and\n`git push --follow-tags`. The Release workflow then re-runs the gate, creates the GitHub\nRelease from `CHANGELOG.md`, and registers the version with the MCP Registry.\nSee [CONTRIBUTING.md](CONTRIBUTING.md).\n\nLive verification against a real server/game: `pnpm live:probe`, `live:e2e`, `live:m2`, `live:m3`.\n\nThe wire protocol (DevCon frames, RCON/getinfo OOB datagrams, the Cfx string hash)\nis documented byte-by-byte in [docs/protocol.md](docs/protocol.md), derived from the\nopen-source CitizenFX server, `citizenfx/fivem@03dcc562`. Live-verified: RCON reply\nformat, `getinfo` response and the `>8`-byte challenge drop were confirmed against a\nreal FXServer on 2026-09-02.\n\n## License\n\nMIT. The FiveM/CitizenFX name is a trademark of Cfx.re; this project is not affiliated\nwith or endorsed by Cfx.re.\n",
  "bytes": 12642,
  "sha": "b2b463f9b65ca2bf13ba5fae065bcf12963300d7a460f4de695b122861e90c9b",
  "repo_slug": "ziyacivan/fivem-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_ziyacivan_fivem_mcp_feb443af/readme"
}