gmod-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| GMOD_MCP_REPO | No | The root directory of the Garry's Mod addon project. If not set, the daemon walks up from the cwd looking for tools/lint.sh and CLAUDE.md, or uses .gmod-mcp/config.json. |
Capabilities
Features and capabilities supported by this server
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| healthA | gmod-mcp daemon status: version, detected repo root, presence of the tools/ scripts, state directory. Also probes the addon (3s) and reports the transport state -- whether this daemon owns the shared directory (a second Claude Code session starts a second daemon, which breaks every bridge tool), what is in flight, and any server handler the daemon declares but the game has not registered. |
| lintA | Runs tools/lint.sh on an addon (name or path). Returns structured findings (file, line, rule) and the exit code. Exit 0 means clean. |
| start_serverB | Starts the dedicated server through tools/start-server.sh [map] [gamemode] [tickrate] and records the log's boot boundary. Script defaults: rp_nycity_day/darkrp/33. |
| stop_serverB | Stops the dedicated server through tools/stop-server.sh. |
| sync_configA | Reapplies server-config/ and (re)creates the symlinks through tools/sync-server-config.sh. check:true compares without writing (--check). |
| read_logsA | Reads the server logs. source=game (Lua errors, -condebug) or stdout (the wrapper). sinceBoot:true bounds output to the current boot. errorsOnly:true returns structured runtime findings. |
| packageA | Builds an addon's .gma through tools/package-gma.sh, linting first and refusing on failure. Output lands in dist/. |
| read_runtimeA | Snapshot of server state: map, gamemode, CurTime, player and entity counts, uptime. |
| read_playersA | Lists players: name, SteamID, team/job, ping, position, health. |
| read_entitiesA | Lists entities, filterable by class. Returns index, class, model and position. |
| inspect_entityC | Details of one entity by index: class, model, health, owner, key-values. |
| read_hooksB | Registered hooks (hook.GetTable), filterable by event. Returns event -> identifiers. |
| read_convarsB | Server convar values. Without |
| read_net_messagesB | Registered net messages (util.AddNetworkString) and whether a net.Receive exists. |
| read_timersA | State of named timers: exists, time left, repetitions left. GMod cannot enumerate timers, so |
| run_console_commandA | Runs a server console command (game.ConsoleCommand -- queued, around 0.25s of latency). |
| send_debugA | Prints a message server-side, useful for marking the log or tracing. |
| run_testA | Runs a GLua test file server-side and returns {passed, failed, results}. path is relative to lua/, e.g. 'myaddon/tests/x.lua'. The file returns a table { [name] = function(t) end }. |
| run_luaA | GUARDED. Runs arbitrary Lua server-side (RunString) and returns the resulting value. Requires confirm:true. Audited. |
| read_panelsB | Derma/VGUI panel tree: class, name, visibility, size, position both parent-relative (x/y) and absolute (screen_x/screen_y), whether mouse input is enabled, and on_screen. Filter on on_screen: |
| inspect_panelA | Finds a panel by NAME, class and/or displayed text, and returns its screen rectangle, its text, whether it holds keyboard focus, and the other matches. NAME is the registered vgui name (R_CharCreate, R_UI_Button, echat.textentry) and is what you want: |
| read_panel_textA | Dumps what the interface DISPLAYS, as text: name, class, screen rectangle and text content of each panel under a named root. Use this instead of capture_screen to assert a value -- a capture travels in 7KB chunks paced one per frame, and a number read off a compressed JPEG is not an assertion. Text comes from GetText, GetValue, or a .label/.text/.title field (kit buttons paint their label and answer '' to GetText). The list is depth-first with depth relative to the root, so the parent chain is recoverable from the ordering: the DTextEntry that follows the DLabel 'Prénom' is that field. capture_screen remains the tool for anything visual -- z-order, overlap, a missing glyph. |
| capture_screenA | Captures the client's screen on the next frame and returns it as a viewable image. Every byte travels in 7KB chunks paced by frame, so a full-resolution capture takes seconds and dominates any act-then-look loop: the default half scale at quality 60 is 4-6x cheaper and still legible for a Derma layout. Pass region (from read_panels' screen_x/screen_y) to capture just one panel. A capture that would exceed the client's channel budget is refused with its size rather than sent: a full-screen quality-80 capture measured 424KB and timed the client out of the server. Requires an active GMod client. |
| read_consoleB | CLIENT Lua errors captured since load. GMod does not expose the console buffer itself. |
| read_viewA | What the client sees and is pointed at: eye position and angles, aim trace (class, index, distance, hit position), health, weapon, cursor position and visibility, the hovered panel, the panel holding keyboard focus, and the current scripted-input mode. This is the cheap half of an act-then-look loop -- one chunk, no image -- and answers 'am I aimed at the door' without a screenshot. |
| client_inputA | Drives the connected GMod client: movement, aim, keys, Derma clicks, typing, chat. Modal -- 'world' drives movement through CreateMove, 'ui' hands input to the panel system, and the two are mutually exclusive; the action switches mode for you. Durations are SECONDS (CreateMove runs at the client's cmdrate, so tick counts are not a duration), clamped to 5s, and everything resets after 30s or on |
| read_client_convarsC | Client-side convar values. Without names, returns a common subset. |
| patch_fileA | Replaces a file's contents (inside the repo) after backing it up. Returns a patch id for restore_patch, plus the unified diff. rationale explains the change. |
| restore_patchC | Reverts a patch by id, restoring the previous state. |
| reload_fileA | Triggers GMod's Lua autorefresh for a file by bumping its mtime. Best-effort: it covers edits, while new files and autoruns still need a restart. |
| reload_addonA | Touches every .lua file of an addon to trigger autorefresh. Best-effort; structural changes still need a restart. |
| validateC | Verdict for the loop: the addon's lint plus the current boot's runtime errors. ok=true when lint is clean AND no runtime error was seen. |
| run_iterationA | One full iteration: optional patch -> reload (or a restart note) -> validate. Returns the applied patch and the verdict. This is the core of the edit/observe/fix loop. |
| batchA | Runs up to 32 server tools in ONE bridge round trip instead of one per call. A round trip costs about 0.4s, so any act-then-look sequence is dominated by transport unless it is batched. Each step reports its own ok/data/error; a step failing is data, not a transport error. IMPORTANT: with settleMs 0 every step runs in the SAME server tick, and some engine effects only land at the end of a frame -- a removed entity still reads as valid. Set settleMs (100 is usually enough) whenever a step must observe what an earlier one did. Any arg value may be {"__step": 1, "get": "index"} to read a field from an earlier step's result, so spawn-then-act still costs one round trip. |
| spawn_entityA | GUARDED. Creates and spawns an entity at a position. Returns its EntIndex, which the other world tools take as a target. Requires confirm:true. |
| world_editA | GUARDED. Acts on one entity or player: remove, teleport, set_ang, freeze, unfreeze, set_health, set_armor, give, strip. target is an entity index or a player's SteamID/name. Requires confirm:true. |
| set_player_stateA | GUARDED, DarkRP. Sets a player's money, job, salary or RP name. Money is in INTEGER CENTS (1.50$ is 150) and goes through the r-capitalism ledger when it is loaded, so the audited invariant stays intact. Fails with a named error when DarkRP is absent. Requires confirm:true. |
| force_hookA | GUARDED. Runs hook.Run(name, ...) to exercise a gamemode path without reproducing the situation. JSON cannot carry an Entity, so arguments may be tagged: {"__ent": 3}, {"__ply": "STEAM_0:1:2"}, {"__vec": [x,y,z]}, {"__ang": [p,y,r]}. Requires confirm:true. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ProjectSocietyStudio/gmod-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server