The ownership map
Follow the diagram from top to bottom. Each layer has a narrow responsibility; no connection method becomes a second copy of the game.
Owns the actual scene, UI controls, gameplay values, and input state.
Collects only the UI and world information the game is allowed to publish on each update.
Keeps the current snapshots and change numbers, queues action requests, and correlates host completion results.
The stdio MCP server reaches the game bridge over WebSocket.
Page tools use an engine-owned port in the same browser tab.
Use local bindings or the game bridge directly; they do not pass through the two MCP connectors.
A current snapshot is rebuilt as the game updates
At each completed UI publication, the adapter publishes one consistent Semantic UI Tree. The World Object Tree is a separate, read-only view of explicitly exposed game-world objects and has its own publication cycle. Gua Runtime atomically swaps in each completed snapshot; it does not become the owner of the underlying button, door, enemy, or score.
| Field | Plain-language meaning | Why it matters |
|---|---|---|
frameSequence | Within one tree, how many host frames for that tree have been completed in this session. | Shows that a newer publication was observed even when that tree's semantic content stayed the same. |
revision | Within one tree, how many times its published semantic content changed. | UI changes advance the UI revision; World changes advance the separate World revision. |
sessionEpoch | Which reset-isolated session the snapshot belongs to. | The UI and World trees share this value so consumers can reject stale or mixed-session evidence. |
An action request and a visible change are separate evidence
- A consumer sends an operation
For example, click a semantic button or press a game action.
- Gua Runtime queues a request
The request receives a stable
requestId. Being accepted into the queue is not success. - The engine adapter consumes it
The adapter finds the current host target, rechecks permissions and state where required, then performs the engine operation.
- The host reports correlated completion
A success or failure result with the same request ID proves that the game-side operation was processed.
- The consumer waits for the expected state
If the click should open a menu, completion alone does not prove that the menu is visible. Read fresh snapshots until the menu state appears.
Condition waits keep checking new state
A state wait obtains fresh snapshots until its supported condition succeeds or its timeout expires. Transports that propagate caller cancellation can stop it earlier. wait_for_node waits for an ID to be present, while wait_for_world_object waits for a World selector to match. For a nearby World selector, every poll resolves the reference and candidates again within that one newly projected snapshot; it never combines a current object with a position or match retained from an older frame. Testing clients can use richer fresh-snapshot predicates such as WaitForStateAsync. This makes the condition—not machine speed—the definition of success.
A successful World query reports the World snapshot's sessionEpoch, frameSequence, and revision. Keep these together with the matches when recording evidence; they identify the exact projected snapshot that was evaluated.
“Wait until the Loading node appears.” It can finish as soon as that supported condition is true. If visibility also matters, check it in the fresh snapshot rather than assuming ID presence means visible.
“Wait 2 seconds.” A client sleep or Recording delay only lets time pass; it does not prove that the requested state appeared.
Use a fixed delay only when elapsed time is itself part of the behavior. For ordinary synchronization, prefer a bounded state wait with a useful timeout.
Held game input belongs to a connection
Stateful game input such as holding W is tracked under the owner that created it: a WebSocket connection, local input session, Inspector connection, or browser page bridge. Its lease bounds how long it may remain held. Release, lease expiry, disconnect, reset, session disposal, tool unregistration, or engine shutdown returns that owner's input to neutral without releasing another owner's controls.
What MCP and WebMCP share—and what differs
| Concern | gui-mcp | gua-webmcp |
|---|---|---|
| Shared Gua behavior | Host-authorized semantic snapshots and actions, request-ID-correlated host completion, condition waits, and owner-scoped input cleanup. | |
| Observation and action profile | Uses the profile fixed by the native host. It is Debug by default; a player-facing host must explicitly select Player and configure its policy. | Always uses the host's Player projection and Player action authorization. Page tools cannot request Debug. |
| Where the connector runs | A separate stdio MCP server. | Inside the exported game's browser page. |
| Path to the runtime | WebSocket game bridge. | Engine-owned JavaScript port in the same tab. |
| Connection owner | Each WebSocket connection has its own input owner. | Each registered page bridge has its own input owner. |
What Gua does not keep
Gua does not store the AI's conversation, plan, chain of thought, or partially completed reasoning. It stores only bounded protocol state such as published snapshots, request and completion bookkeeping, and connection-owned input state. Whether an AI can do other work while a tool call is waiting depends on that AI client and execution environment, not on Gua.