Install
$ agentstack add mcp-amyjeanes-gmod-mcp-server ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
GMod MCP Server
A Model Context Protocol (MCP) bridge between an AI coding assistant and a running Garry's Mod session. Lets the assistant invoke tools (e.g. run Lua, inspect state) inside the live game, instead of relying on static analysis and copy-pasted console output.
The repo is the GMod addon: clone it directly into garrysmod/addons/. The .NET MCP server lives in server/ and is ignored by the GMod engine.
Quick start
- Install the addon
`` cd garrysmod/addons git clone https://github.com/AmyJeanes/GMod-MCP-Server.git ``
- Build the MCP server
`` cd GMod-MCP-Server/server/GModMcpServer dotnet build ``
- Register the MCP server with your client (e.g. Claude Code):
`` claude mcp add gmod -- dotnet run --project /absolute/path/to/server/GModMcpServer ``
- Launch GMod via the
host_launchtool, or start it yourself. The bridge runs regardless, but tool dispatch requires opting in: in the GMod developer console, runmcp_enable 1. Sensitive tools additionally need their capability granted — see [Capabilities](#capabilities). - Verify: the host and game tools (see [Tools](#tools)) appear in your assistant's tool list, and
host_statusreportsbridge.reachable: trueonce GMod is running and responsive.
How it works
GMod cannot run a listening socket from pure Lua, and http.Fetch/HTTP() block private-IP destinations on listen and singleplayer servers. This addon uses file-based IPC via garrysmod/data/mcp/ — the server-realm and client-realm bridges run independent poll loops, the .NET host polls the response files, and big payloads like screenshots never traverse net.WriteString. No binary modules required.
Each .NET MCP host generates a per-process session GUID and prefixes its request IDs with it, so multiple MCP clients (Claude Code + MCP Inspector + …) can share the same GMod instance without stealing each other's responses.
See docs/protocol.md for the wire format.
Tools
These are the built-in tools, grouped by where they run. This is not an exhaustive list of what a live game exposes: any addon can register its own tools (MCP:AddFunction) and capabilities (MCP:AddCapability), which then appear alongside the built-ins — the TARDIS addon does exactly this to add its tardis_* tools.
Host tools
Implemented by the .NET MCP server itself — available even when GMod isn't running.
| Tool | Description | | --- | --- | | host_launch | Launch Garry's Mod and wait until the MCP bridge is fully ready before returning. | | host_close | Close the running GMod process (located by name, regardless of who launched it). | | host_status | Report whether GMod is running, whether the MCP bridge is reachable (a live ping is sent when GMod is detected), and the current tool count and capability state. | | host_changelevel | Change the map of the already-running GMod server and block until the new map is ready before returning (the in-game sibling of host_launch's readiness wait). | | mcp_reload | Reload the in-game MCP addon (re-run its Lua and restart the bridge) and block until the bridge is back and ready before returning — the host-managed equivalent of running mcp_reload in the GMod console, but without the timeout a bare reload causes (the reload tears the bridge down mid-call). |
Game tools
Dispatched into the running game over the file bridge. The framework appends _sv (server realm) or _cl (client realm) to each name, so the realm is always visible.
| Tool | Realm | Requires | Description | | --- | --- | --- | --- | | bot_remove_sv | server | world_control | Remove (kick) bots from the server. | | bot_spawn_sv | server | world_control | Spawn one or more bots on the server (needs a listen server -- maxplayers>1). | | console_cmd_cl | client | unsafe | Run a raw console command in this realm (server: game.ConsoleCommand; client: the local console). | | console_cmd_sv | server | unsafe | Run a raw console command in this realm (server: game.ConsoleCommand; client: the local console). | | console_read_cl | client | — | Read recently captured console output and Lua errors that fired outside a tool call (background hooks, timers, autorefresh, other addons) in this realm. | | console_read_sv | server | — | Read recently captured console output and Lua errors that fired outside a tool call (background hooks, timers, autorefresh, other addons) in this realm. | | constraint_find_sv | server | — | List an entity's physics constraints and its whole constraint network -- the structured answer to "what is this welded/no-collided/roped to?" and "why does this prop fall through or not collide?". | | cvar_set_cl | client | unsafe | Set a console variable, wait for it to settle, and report the actual stabilized value. | | cvar_set_sv | server | unsafe | Set a console variable, wait for it to settle, and report the actual stabilized value. | | cvar_state_cl | client | — | Structured snapshot of one or more console variables -- current value (as string/int/float/bool), default, decoded FCVAR flags, help text and min/max bounds, in a single read. | | cvar_state_sv | server | — | Structured snapshot of one or more console variables -- current value (as string/int/float/bool), default, decoded FCVAR flags, help text and min/max bounds, in a single read. | | debug_clear_cl | client | — | Remove every hook the debug tools installed in this realm -- debugrecord sampling hooks and (later) debugdraw render hooks, all under the mcp_debug_ id namespace. | | debug_clear_sv | server | — | Remove every hook the debug tools installed in this realm -- debugrecord sampling hooks and (later) debugdraw render hooks, all under the mcp_debug_ id namespace. | | debug_draw_cl | client | unsafe | Install a persistent client-side render hook that runs your draw Lua every frame, for visual debugging you can then screenshot -- mark an entity, outline a volume, draw a path, label something on the HUD. | | debug_hooks_cl | client | — | Inspect the hook registry -- answer "did my hook register, and where is it defined?" without hand-dumping hook.GetTable(). | | debug_hooks_sv | server | — | Inspect the hook registry -- answer "did my hook register, and where is it defined?" without hand-dumping hook.GetTable(). | | debug_record_cl | client | unsafe | Record a value each time a hook fires, for a bounded window, then return the time series -- a managed sampling probe that owns the hook lifecycle (unique namespaced hook, duration cap, auto-remove on end/stop/error) so you never hand-roll hook.Add/poll/hook.Remove. | | debug_record_interactive_cl | client | unsafe | ARM an on-screen, player-driven recorder for a repro the user must physically perform (walk a path, time a portal crossing, mash a seam) -- the interactive sibling of debugrecord. | | debug_record_interactive_sv | server | unsafe | Arm the paired SERVER-realm capture for an interactive recording -- the server half of debugrecordinteractivecl (which owns the on-screen UI and human timing). | | debug_record_read_cl | client | — | Collect the series from a debugrecordinteractive recorder. | | debug_record_read_sv | server | — | Collect the SERVER-realm series from a debugrecordinteractive (server) recorder, by link_id. | | debug_record_sv | server | unsafe | Record a value each time a hook fires, for a bounded window, then return the time series -- a managed sampling probe that owns the hook lifecycle (unique namespaced hook, duration cap, auto-remove on end/stop/error) so you never hand-roll hook.Add/poll/hook.Remove. | | entity_create_sv | server | world_control | Spawn one entity server-side -- Create, SetModel, SetPos, Spawn, Activate -- optionally frozen and coloured, and tagged for later cleanup by entityremove. | | entity_find_cl | client | — | Find entities and return compact rows -- index, class, model, pos and distance -- instead of a raw dump. | | entity_find_sv | server | — | Find entities and return compact rows -- index, class, model, pos and distance -- instead of a raw dump. | | entity_remove_sv | server | world_control | Remove entities server-side and wait until they are actually gone before reporting (:Remove is deferred, so a same-call count would be stale). | | entity_set_sv | server | world_control | Mutate one entity's transform, render and physics state by index, then confirm. | | entity_state_cl | client | — | Nil-safe structured snapshot of one entity by index -- identity, transform, render (incl. | | entity_state_sv | server | — | Nil-safe structured snapshot of one entity by index -- identity, transform, render (incl. | | file_exists_cl | client | — | Check whether a single path exists in the GMod virtual filesystem, and report whether it's a file or folder plus its size and modified time -- file.Exists/IsDir/Size/Time. | | file_exists_sv | server | — | Check whether a single path exists in the GMod virtual filesystem, and report whether it's a file or folder plus its size and modified time -- file.Exists/IsDir/Size/Time. | | file_find_cl | client | — | List files and folders in the GMod virtual filesystem matching a glob -- file.Find(pattern, path). | | file_find_sv | server | — | List files and folders in the GMod virtual filesystem matching a glob -- file.Find(pattern, path). | | game_set_cl | client | world_control | Set curated client-only game knobs, then confirm. | | game_set_sv | server | world_control | Set one or more curated, safe server-tuning knobs, wait for them to settle, and report the actual values. | | game_state_sv | server | — | Structured snapshot of server-wide game state in one read -- current map, gamemode, hostname, singleplayer/dedicated flags, max player slots, player/bot/human counts, a lean roster of every player (name/userid/entindex/isbot/ishost/team -- drill into one with playerstate or entitystate), a tuning block with the live values of gameset's knobs (gravity, timescale, phystimescale, fakelag), and cheats_enabled (svcheats) -- which gates whether gameset's timescale/fakelag will take. | | hook_call_cl | client | unsafe | Fire a GMod hook and report the result -- the dispatch companion to debughooks (which only reads the registry). | | hook_call_sv | server | unsafe | Fire a GMod hook and report the result -- the dispatch companion to debughooks (which only reads the registry). | | job_cancel_cl | client | — | Abort a background job started with async=true, tearing down its hooks and side effects immediately (e.g. | | job_cancel_sv | server | — | Abort a background job started with async=true, tearing down its hooks and side effects immediately (e.g. | | job_collect_cl | client | — | Fetch the result of a background job started by calling a tool with async=true, identified by the job_id the arm returned. | | job_collect_sv | server | — | Fetch the result of a background job started by calling a tool with async=true, identified by the job_id the arm returned. | | job_list_cl | client | — | List background jobs (from async=true arms) in this realm: jobid, the tool, status (armed / finished / cancelled), seconds elapsed since arming, and whether it's collectable now. | | job_list_sv | server | — | List background jobs (from async=true arms) in this realm: jobid, the tool, status (armed / finished / cancelled), seconds elapsed since arming, and whether it's collectable now. | | light_projected_cl | client | — | Create, update, or remove a clientside ProjectedTexture -- a spotlight test-light rig, the projected-light sibling of debugdraw. | | lua_run_cl | client | unsafe | Compile and execute Lua source in this realm. | | lua_run_sv | server | unsafe | Compile and execute Lua source in this realm. | | model_info_cl | client | — | Structured info about a model ASSET without spawning a prop -- read straight from the model file via util.GetModelInfo (no entity, no spawn), so it is synchronous and realm-identical. | | model_info_sv | server | — | Structured info about a model ASSET without spawning a prop -- read straight from the model file via util.GetModelInfo (no entity, no spawn), so it is synchronous and realm-identical. | | player_lua_run_sv | server | unsafe | Compile and execute Lua source on a target player's client realm and return the result. | | player_set_sv | server | player_control | Set a player or bot's pose and state, then wait for it to settle and confirm it stuck. | | player_state_cl | client | — | Structured snapshot of a player (or all players) -- identity, vitals, eye position/aim, velocity, movement state (movetype, onground, crouching, ducking, frozen, godmode, waterlevel), view offset and collision hull, model/animation sequence, playermodel and weapon colours, and active weapon, in one read. | | player_state_sv | server | — | Structured snapshot of a player (or all players) -- identity, vitals, eye position/aim, velocity, movement state (movetype, onground, crouching, ducking, frozen, godmode, waterlevel), view offset and collision hull, model/animation sequence, playermodel and weapon colours, and active weapon, in one read. | | player_trace_cl | client | — | Raycast from a player's eyes along their view and report what they're looking at -- the hit entity (index and class; drill in with entitystate), hit position, distance from the eye, surface normal, and surface material/texture. | | player_trace_sv | server | — | Raycast from a player's eyes along their view and report what they're looking at -- the hit entity (index and class; drill in with entitystate), hit position, distance from the eye, surface normal, and surface material/texture. | | player_walk_cl | client | player_control | Walk the local (host) player naturally by driving the real movement code (CUserCmd each tick) via CreateMove, so grounded-locomotion bugs reproduce -- unlike teleport or +forward. | | player_walk_sv | server | player_control | Walk a target player or bot naturally by driving its CUserCmd each tick via StartCommand -- the canonical way to control bots. | | reload_file_cl | client | — | Hot-reload one on-disk Lua source file by re-running it in this realm -- a targeted alternative to mcpreload (which rebuilds the whole MCP addon) and the engine's autorefresh (which only fires for some edits), for iterating on a single file in any addon. | | reload_file_sv | server | — | Hot-reload one on-disk Lua source file by re-running it in this realm -- a targeted alternative to mcpreload (which rebuilds the whole MCP addon) and the engine's autorefresh (which only fires for some edits), for iterating on a single file in any addon. | | screenshot_cl | client | — | Capture a JPEG of what the player actually sees on screen - the genuine rendered frame (HUD, portals, post-processing all as-live), not a re-render, so the image matches the game exactly. | | world_trace_cl | client | — | Raycast from an arbitrary origin and report what the ray hits -- the hit entity (index and class; drill in with entitystate), hit position, distance, surface normal and material, plus the origin's point-contents and the trace's solid flags. | | world_trace_sv | server | — | Raycast from an arbitrary origin and report what the ray hits -- the hit entity (index and class; drill in with entitystate), hit position, distance, surface normal and material, plus the origin's point-contents and the trace's solid flags. |
Capabilities
Security gates a tool can require (requires = { ... }). Each derives an archived mcp_allow_ convar; grant it in the GMod developer console (e.g. mcp_allow_unsafe 1) to enable the tools that depend on it. Only the built-in unsafe is listed here — addons can declare their own.
| Capability |
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: AmyJeanes
- Source: AmyJeanes/GMod-MCP-Server
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.