| name | moddev-usage |
| description | Use when an agent needs to operate a local ModDev game session through its built-in HTTP service, exported skills, and request API for Minecraft debugging or automation. |
ModDev Usage
Overview
The local ModDev HTTP service is a loopback endpoint exposed by the game mod itself. Resolve a live baseUrl first, then read skills and execute operations through POST /api/v1/requests.
Required Flow
- Try the default probe
GET http://127.0.0.1:47812/api/v1/status.
- If the default probe fails, read
<gradleProject>/build/moddevmcp/game-instances.json.
- Probe each candidate
baseUrl from the registry with GET /api/v1/status and keep only live instances.
- Continue only if
serviceReady=true.
- After you have a live
baseUrl, read the exported entry skill from ~/.moddev/skills/skills/moddev-usage.md when available, or fetch GET <baseUrl>/api/v1/skills/moddev-usage/markdown.
- Treat client UI work as ready only if
gameReady=true and connectedSides includes client.
- Discover available skills and operations before guessing names:
GET /api/v1/categories
GET /api/v1/skills
GET /api/v1/operations
- Prefer reading the specific skill markdown before issuing a request.
Discovery Rules
moddev-usage is the required starting skill.
- Some exported skills are guidance-only. They explain workflow and do not map to an executable operation.
- Category skills summarize a capability area and point to operation skills.
- Operation skills show the exact
operationId, input shape, and a minimal curl example.
Request Rules
Send all executable work through POST /api/v1/requests.
Do not control the game through OS-level or shell-level input injection.
- do not use PowerShell, Windows APIs, or external automation helpers to send keyboard input
- do not use PowerShell, Windows APIs, or external automation helpers to move or click the mouse
- do not treat simulated user input outside the ModDev runtime as an acceptable fallback
- if a game interaction is needed, use the exposed ModDev operations and the skill guidance for them
Envelope fields:
requestId
operationId
targetSide
input
Interpret targetSide strictly:
- omit it when the operation does not support side selection
- omit it when exactly one eligible side is connected
- send it when multiple eligible sides are connected
- if the service returns
target_side_required, retry with an explicit side
targetSide is required only when both eligible sides are live for that operation.
Minimal example:
curl -X POST http://127.0.0.1:47812/api/v1/requests \
-H "Content-Type: application/json" \
-d '{"requestId":"check-1","operationId":"status.get","input":{}}'
Preferred Order
For any new session:
GET http://127.0.0.1:47812/api/v1/status
- if needed, read
<gradleProject>/build/moddevmcp/game-instances.json and probe listed candidates with GET /api/v1/status
- pick a live
baseUrl
GET <baseUrl>/api/v1/skills/moddev-usage/markdown
- read the relevant category or operation skill
POST <baseUrl>/api/v1/requests
For UI work:
- verify
connectedSides includes client
- use
status.live_screen
- use
ui.inspect
- use
ui.snapshot or ui.action only when needed
- use
ui.capture to export proof images when requested
- prefer
source=auto or explicit source=framebuffer when you need a reliable full-screen image
UI interactions must stay inside the ModDev runtime. Do not bypass ui.* operations with shell scripts or system automation.
For capture requests:
source=auto is framebuffer-first and is the recommended default for reliable real-image export
source=framebuffer is the most general option and should be preferred when you need the actual current screen or world image
source=offscreen is narrower and only suitable for compatible vanilla GUI screens; do not assume it works for every screen
source=render is a last-resort fallback and may produce a diagnostic rendering rather than the exact on-screen pixels
For commands:
command.list
command.suggest
command.execute
For local worlds:
world.list
world.join with worldId when re-entering an existing save
world.create when a fresh singleplayer world is required
- after
world.create succeeds, treat the returned worldId as the stable save id for later calls
For hotswap:
hotswap.reload
- if it returns a structured execution error, fix the code or restart the game instead of blindly retrying
Failure Handling
Report the exact failure layer:
- service missing:
/api/v1/status is unavailable
- service not ready:
serviceReady=false
- game not ready:
gameReady=false
- side unavailable: requested side is absent from
connectedSides
- invalid request:
errorCode=invalid_request
- execution failure: use the returned
errorCode and errorMessage
For local world failures:
world_not_found means an existing target save was not resolved
world_name_ambiguous means the visible name matched multiple saves
world_create_failed or world_join_failed means the game did not complete the requested transition
- if the game visibly entered the new world but the response reports
world_not_found, treat that as a runtime bug, not a caller mistake
Do not claim a skill or operation exists unless it is visible from the current service or exported skill tree.