Your first game extension
Dependencies
Use the API version matching the Agent Bridge release. In a Java-only common module:
repositories {
maven {
url = uri("https://miyomiyo-mods.pages.dev/maven")
content { includeGroup("dev.miyomiyo.agentbridge") }
}
}
dependencies {
compileOnly "dev.miyomiyo.agentbridge:agent-bridge-api:1.0.0"
}
Agent Bridge supplies the API at runtime. Do not shade it into your MOD. Declare a client dependency on MOD ID mcagent in your loader metadata. Keep client integration classes off a dedicated server. For optional integration, check installation before loading classes that reference the API.
Register a query
VisitExtension.java is a complete Java-only example. It counts dimension transitions in the current world visit. Compile it against the game API and diagnostic API; it requires no host implementation, Minecraft or JSON library.
Put the following line in META-INF/services/dev.miyomiyo.agentbridge.api.AgentExtension:
example.VisitExtension
The public no-argument constructor and register must be passive: no world access, file I/O, background jobs or agent connections. Registration is accepted or rejected as one batch. Do not retain the registrar.
The example contributes mc_query(source="example_visit:visit", parameters={}). Prefer a query for observations. Add a separate tool only when it represents an operation; detailed advice belongs in an on-demand guide.
Tools and settings
ToolDefinition declares its world/location scope, effect and replay policy. READ_ONLY observes, ASSISTANCE manages assistance, and GAME_CHANGE requires cheat mode plus confirmation for that operation. The command auto-allow setting does not authorize extension changes.
ToolResult.ok reports success. partial reports incomplete observations. Use presented only after useful assistance has actually been shown; it is not a progress acknowledgement and does not complete a task.
Use settings for a page and its store; the host lays out fields and owns drafts. Use the client API for an independent settings-screen entry. Settings and secrets are not automatically sent to the model. Store only overrides; a value equal to the current default should be omitted.
Add a presentation to the shared UI tool
Use ExtensionRegistrar.ui(UiDefinition, ToolHandler) to extend mc_ui_put without adding a separate tool. name selects the surface; parametersSchema describes that presentation's arguments. All calls share the target, taskId, opId, surface and parameters envelope.
The registered name, capability description and complete argument schema appear in standard MCP tools/list. Describe what the feature does there; use guides for longer syntax and examples, rather than hiding capabilities behind a guide lookup.
UI operations use world scope, assistance effects and task-operation replay. The handler owns admission, presentation, cancellation and cleanup after leaving the world. Names must be unique across all extensions and cannot replace built-in question.
Adding screens or HUDs
The client API is a separate JAR. Add the matching artifact to a development project configured for Minecraft and its loader.
| Target | Maven artifact | Gradle configuration |
|---|---|---|
| Fabric 1.21.1 | agent-bridge-client-api-fabric |
modCompileOnly |
| NeoForge 1.21.1 | agent-bridge-client-api-neoforge |
compileOnly |
| NeoForge 26.2 | agent-bridge-client-api-neoforge26 |
compileOnly |
Use the group and version from the example above. The Fabric artifact uses intermediary Minecraft names; Loom remaps them into your development mappings. Its POM brings in the game and diagnostic APIs. Do not embed the client API in your extension: Agent Bridge provides these types at runtime. Javadoc includes protected constructors on public screen bases for extension subclasses.
Use the shared settings UI
Register SettingsForm and SettingField for declarative settings. The host form owns layout, editors, visibility conditions and saving state. For a custom screen, use the same components from dev.miyomiyo.agentbridge.client.settings in the client API.
| Type | Purpose |
|---|---|
SettingsScreen |
Optional screen base with shared background, title and layout frame |
SettingsLayout |
Width-aware frames and multi-column rows |
SettingsWidgets |
Styled buttons and text editors |
SettingsButton / SettingsSlider |
Components retaining Minecraft input, focus and narration |
SettingsStyle / SettingsTheme |
Navigation, action and selection styles, and shared colors |
For example, place a button inside SettingsScreen.init():
var frame = settingsFrame(320, 48);
addRenderableWidget(SettingsWidgets.button(
Component.translatable("gui.back"), button -> onClose())
.bounds(frame.left(), height - 32, frame.width(), 20).build());
Call renderSettingsFrame(graphics, frame) from renderContents. Custom screens own their draft, persistence, cancellation and return to the parent. Rendering a component or resizing the screen does not save settings. Registration still accepts any Minecraft Screen.
Screen coverage and input focus
ClientOverlayScreen and SettingsScreen default to OVERLAY, leaving gameplay visible. To cover the whole window, declare the presentation in the constructor:
super(title, ScreenPresentation.FULLSCREEN, 0xEF111923);
The shared base draws the backdrop and requests Minecraft's standard pause. Only a private single-player world actually pauses; multiplayer and LAN-published worlds continue. UI, communication and background work do not need custom stop/resume logic. If InvMove is installed, fullscreen movement is disabled on every connection type.
A custom native Screen can expose coverage through ScreenPresentation.Host. Such a screen owns its backdrop and native pause request. ClientConfirmationScreen provides the same declaration for native confirmation dialogs. No screen names or settings/report categories are used to infer coverage.
Use Minecraft's single-line or multiline text widgets and expose the current focused child through ContainerEventHandler.getFocused() in nested containers. InvMove integration observes that focus path. An overlay without text focus defers to InvMove's normal settings; a visible cursor alone does not disable movement.
Registering shortcuts
Declare a ShortcutKey and KeyModifiers through ClientRegistrar.shortcut. Actions sharing a key ID use one Minecraft key mapping with distinct modifier combinations. Input received outside gameplay is discarded rather than replayed later.
The host's ShortcutKey.ASSISTANT defaults to G (plain: conversation/setup; Shift: mouse controls). ShortcutKey.LAYOUT is unbound by default. Reports registers its own H mapping for the inbox. Extensions may supply their own IDs and translation keys; duplicate key/modifier pairs are rejected. Declare bindings at normal key-registration time, not each time a world is entered.