World Model MCP — Live Tool Exercise Suite

SkillAI & models

Comprehensive exercise script to verify all 15 world-model-mcp MCP tools in a live chat session. Builds a coherent test world, exercises every tool, and validates outputs.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the World Model MCP — Live Tool Exercise Suite skill

What this skill tells your AI

The instructions your AI receives, as published by putervision/world-model-mcp in .agents/skills/world-model-mcp-exercises/SKILL.md and read by ahel’s review.

This skill provides a complete, ordered exercise script that tests all 15 world-model-mcp MCP tools in a live chat session. It builds a coherent "Medieval Courtyard" test world from scratch and exercises every tool action, then cleans up.

Purpose: Smoke-test and verify that the world-model-mcp server is functioning correctly after deployment, upgrade, or code changes.


Prerequisites

  • world-model-mcp MCP server must be running and connected (check with get_spatial_map)
  • Use project: "exercise-test" for all calls to avoid contaminating real project data
  • Each step builds on the previous — execute in order

Exercise Sequence (15 Tools, 25+ Calls)

Step 1: update_entity — Create Entities

Create a set of test entities forming a Medieval Courtyard scene.

Call 1a — Create the Player Agent:

{
  "tool": "update_entity",
  "arguments": {
    "name": "Knight",
    "type": "agent",
    "status": "active",
    "position": { "x": 0, "y": 0, "z": 0 },
    "orientation": { "pitch": 0, "yaw": 90, "roll": 0 },
    "bounding_box": { "width": 1.0, "height": 2.0, "depth": 1.0 },
    "confidence": 1.0,
    "properties": { "health": 100, "armor": "plate", "weapon": "sword" },
    "tags": ["player", "warrior", "friendly"],
    "project": "exercise-test"
  }
}

Expected: Returns entity_id (ULID string), version: 1.

Call 1b — Create a Treasure Chest:

{
  "tool": "update_entity",
  "arguments": {
    "name": "Treasure Chest",
    "type": "container",
    "position": { "x": 10, "y": 0, "z": 5 },
    "bounding_box": { "width": 1.2, "height": 0.8, "depth": 0.8 },
    "properties": { "is_locked": true, "contents": "gold_coins" },
    "tags": ["loot", "interactive"],
    "project": "exercise-test"
  }
}

Call 1c — Create a Stone Wall (obstacle):

{
  "tool": "update_entity",
  "arguments": {
    "name": "Stone Wall",
    "type": "obstacle",
    "position": { "x": 5, "y": 0, "z": 3 },
    "bounding_box": { "width": 8.0, "height": 3.0, "depth": 1.0 },
    "confidence": 1.0,
    "tags": ["structure", "blocking"],
    "project": "exercise-test"
  }
}

Call 1d — Create a Watchtower (landmark):

{
  "tool": "update_entity",
  "arguments": {
    "name": "Watchtower",
    "type": "landmark",
    "position": { "x": 15, "y": 0, "z": -10 },
    "bounding_box": { "width": 4.0, "height": 12.0, "depth": 4.0 },
    "properties": { "floors": 3, "has_ladder": true },
    "tags": ["structure", "climbable", "vantage_point"],
    "project": "exercise-test"
  }
}

Call 1e — Create a Goblin (NPC):

{
  "tool": "update_entity",
  "arguments": {
    "name": "Goblin Scout",
    "type": "npc",
    "position": { "x": 12, "y": 0, "z": 8 },
    "bounding_box": { "width": 0.8, "height": 1.2, "depth": 0.8 },
    "confidence": 0.7,
    "properties": { "hostile": true, "patrol_route": "east_wall" },
    "tags": ["enemy", "patrol"],
    "project": "exercise-test"
  }
}

✅ Verify: Save all returned entity_id values — they are needed in subsequent steps.


Step 2: query_entities — Search & Locate

Call 2a — Full-text search:

{
  "tool": "query_entities",
  "arguments": {
    "query": "chest treasure",
    "project": "exercise-test"
  }
}

Expected: Returns Treasure Chest entity.

Call 2b — Proximity search (find entities near the Knight):

{
  "tool": "query_entities",
  "arguments": {
    "near_position": { "x": 0, "y": 0, "z": 0 },
    "max_distance": 15,
    "project": "exercise-test"
  }
}

Expected: Returns Knight, Stone Wall, Treasure Chest (all within 15 units).

Call 2c — Entity location lookup with history:

{
  "tool": "query_entities",
  "arguments": {
    "entity_id": "<KNIGHT_ID>",
    "include_history": true,
    "history_limit": 10,
    "project": "exercise-test"
  }
}

Expected: Returns entity details with history array.

Call 2d — Filter by type:

{
  "tool": "query_entities",
  "arguments": {
    "type": "npc",
    "project": "exercise-test"
  }
}

Expected: Returns Goblin Scout only.


Step 3: set_relation — Record Spatial Relationships

Call 3a — Chest is next to Wall:

{
  "tool": "set_relation",
  "arguments": {
    "source_id": "<CHEST_ID>",
    "relation": "next_to",
    "target_id": "<WALL_ID>",
    "distance": 3.6,
    "project": "exercise-test"
  }
}

Call 3b — Goblin is near the Watchtower:

{
  "tool": "set_relation",
  "arguments": {
    "source_id": "<GOBLIN_ID>",
    "relation": "near",
    "target_id": "<WATCHTOWER_ID>",
    "distance": 18.4,
    "project": "exercise-test"
  }
}

Expected: Returns relation_id for each.


Step 4: get_spatial_map — Export World State

Call 4a — JSON export:

{
  "tool": "get_spatial_map",
  "arguments": {
    "format": "json",
    "project": "exercise-test"
  }
}

Call 4b — Summary overview:

{
  "tool": "get_spatial_map",
  "arguments": {
    "format": "summary",
    "project": "exercise-test"
  }
}

Expected: total_entities: 5, total_relations: 2, bounding box extents.

Call 4c — glTF 3D export:

{
  "tool": "get_spatial_map",
  "arguments": {
    "format": "gltf",
    "project": "exercise-test"
  }
}

Expected: Valid glTF 2.0 JSON with asset.version: "2.0", nodes, meshes.


Step 5: simulate_movement — Physics & Navigation

Call 5a — Simulate Knight movement (collision check):

{
  "tool": "simulate_movement",
  "arguments": {
    "entity_id": "<KNIGHT_ID>",
    "delta_position": { "x": 5, "y": 0, "z": 3 },
    "check_collisions": true,
    "project": "exercise-test"
  }
}

Expected: Collision detected with Stone Wall.

Call 5b — Navigate around obstacle:

{
  "tool": "simulate_movement",
  "arguments": {
    "mode": "navigate",
    "start_entity_id": "<KNIGHT_ID>",
    "target_entity_id": "<CHEST_ID>",
    "project": "exercise-test"
  }
}

Expected: Returns navigation waypoints.


Step 6: ingest_observation — Perception Bridging

Call 6a — Ingest vision detections:

{
  "tool": "ingest_observation",
  "arguments": {
    "observer_pose": {
      "position": { "x": 0, "y": 2, "z": 0 },
      "orientation": { "pitch": 0, "yaw": 45, "roll": 0 }
    },
    "field_of_view": { "fov_horizontal": 90, "fov_vertical": 60 },
    "detections": [
      {
        "label": "Treasure Chest",
        "class_name": "container",
        "estimated_position": { "x": 10.2, "y": 0.1, "z": 5.1 },
        "confidence": 0.92
      },
      {
        "label": "Unknown Barrel",
        "class_name": "object",
        "estimated_position": { "x": 3, "y": 0, "z": -2 },
        "confidence": 0.65
      }
    ],
    "project": "exercise-test"
  }
}

Expected: Treasure Chest re-identified (matched), Unknown Barrel created as new entity.

Call 6b — Reconciliation mode:

{
  "tool": "ingest_observation",
  "arguments": {
    "reconcile": true,
    "observer_pose": {
      "position": { "x": 0, "y": 2, "z": 0 },
      "orientation": { "pitch": 0, "yaw": 45, "roll": 0 }
    },
    "field_of_view": { "fov_horizontal": 90, "fov_vertical": 60 },
    "detections": [
      {
        "label": "Treasure Chest",
        "class_name": "container",
        "estimated_position": { "x": 10, "y": 0, "z": 5 },
        "confidence": 0.95
      }
    ],
    "project": "exercise-test"
  }
}

Expected: Returns reconciliation report with confirmed, new, missing, displaced arrays.


Step 7: get_expected_view — Frustum Visibility

{
  "tool": "get_expected_view",
  "arguments": {
    "observer_position": { "x": 0, "y": 2, "z": 0 },
    "observer_orientation": { "pitch": 0, "yaw": 45, "roll": 0 },
    "fov_degrees": 90,
    "max_distance": 50,
    "project": "exercise-test"
  }
}

Expected: Returns list of visible_entities with distances and angular offsets.


Step 8: link_to_goal — State Memory Integration

Call 8a — Link entity to a task:

{
  "tool": "link_to_goal",
  "arguments": {
    "action": "link",
    "task_id": "test-task-001",
    "entity_id": "<CHEST_ID>",
    "relationship": "target",
    "notes": "Retrieve treasure from locked chest",
    "project": "exercise-test"
  }
}

Call 8b — Get goal-relevant context:

{
  "tool": "link_to_goal",
  "arguments": {
    "action": "get_context",
    "task_id": "test-task-001",
    "current_agent_position": { "x": 0, "y": 0, "z": 0 },
    "radius": 30,
    "project": "exercise-test"
  }
}

Expected: Returns linked entities, nearby entities, and spatial context slice.


Step 9: record_outcome — Log Action Results

Call 9a — Record successful movement:

{
  "tool": "record_outcome",
  "arguments": {
    "action_name": "move_to",
    "entity_id": "<KNIGHT_ID>",
    "success": true,
    "resulting_position": { "x": 8, "y": 0, "z": 4 },
    "task_id": "test-task-001",
    "project": "exercise-test"
  }
}

Call 9b — Record property mutation:

{
  "tool": "record_outcome",
  "arguments": {
    "action_name": "unlock",
    "entity_id": "<CHEST_ID>",
    "success": true,
    "property_changes": { "is_locked": false },
    "project": "exercise-test"
  }
}

Expected: Both return updated entity state.


Step 10: manage_spatial_spec — SDD Contracts

Call 10a — Register a spec:

{
  "tool": "manage_spatial_spec",
  "arguments": {
    "action": "set",
    "name": "courtyard-bounds",
    "description": "All entities must remain within the courtyard perimeter",
    "bounds": {
      "min": { "x": -20, "y": -1, "z": -20 },
      "max": { "x": 30, "y": 15, "z": 20 }
    },
    "constraints": [
      { "type": "no_overlap", "description": "No two solid entities may intersect" }
    ],
    "project": "exercise-test"
  }
}

Call 10b — Verify the spec:

{
  "tool": "manage_spatial_spec",
  "arguments": {
    "action": "verify",
    "name": "courtyard-bounds",
    "project": "exercise-test"
  }
}

Expected: Returns passed: true with verification details.

Call 10c — List all specs:

{
  "tool": "manage_spatial_spec",
  "arguments": {
    "action": "list",
    "project": "exercise-test"
  }
}

Step 11: create_evidence_pack — Cryptographic Proof

{
  "tool": "create_evidence_pack",
  "arguments": {
    "task_id": "test-task-001",
    "entity_ids": ["<KNIGHT_ID>", "<CHEST_ID>"],
    "project": "exercise-test"
  }
}

Expected: Returns evidence pack with sha256_hash, entity_snapshots, created_at.


Step 12: use_spatial_blackboard — Multi-Agent Coordination

Call 12a — Post a navigation intent:

{
  "tool": "use_spatial_blackboard",
  "arguments": {
    "action": "post",
    "topic": "navigation-intent",
    "sender": "agent-knight",
    "payload": {
      "destination": { "x": 10, "y": 0, "z": 5 },
      "eta_seconds": 15
    },
    "ttl_seconds": 120,
    "project": "exercise-test"
  }
}

Call 12b — Read the blackboard:

{
  "tool": "use_spatial_blackboard",
  "arguments": {
    "action": "read",
    "topic": "navigation-intent",
    "project": "exercise-test"
  }
}

Expected: Returns posted message with sender, payload, expiry.

Call 12c — Claim a mutex lock:

{
  "tool": "use_spatial_blackboard",
  "arguments": {
    "action": "claim",
    "topic": "chest-access",
    "sender": "agent-knight",
    "resource_id": "<CHEST_ID>",
    "duration_seconds": 30,
    "project": "exercise-test"
  }
}

Expected: Returns claimed: true.

Call 12d — Release the lock:

{
  "tool": "use_spatial_blackboard",
  "arguments": {
    "action": "release",
    "topic": "chest-access",
    "sender": "agent-knight",
    "resource_id": "<CHEST_ID>",
    "project": "exercise-test"
  }
}

Step 13: manage_snapshot — Snapshots & Time Travel

Call 13a — Save a snapshot:

{
  "tool": "manage_snapshot",
  "arguments": {
    "action": "save",
    "name": "before-battle",
    "description": "World state before engaging the goblin",
    "project": "exercise-test"
  }
}

Call 13b — Modify world, then save another snapshot:

First call record_outcome to destroy the Goblin:

{
  "tool": "record_outcome",
  "arguments": {
    "action_name": "attack",
    "entity_id": "<GOBLIN_ID>",
    "success": true,
    "destroyed": true,
    "project": "exercise-test"
  }
}

Then save:

{
  "tool": "manage_snapshot",
  "arguments": {
    "action": "save",
    "name": "after-battle",
    "description": "World state after defeating the goblin",
    "project": "exercise-test"
  }
}

Call 13c — Diff the two snapshots:

{
  "tool": "manage_snapshot",
  "arguments": {
    "action": "diff",
    "snapshot_a": "before-battle",
    "snapshot_b": "after-battle",
    "project": "exercise-test"
  }
}

Expected: Shows Goblin Scout as removed or status_changed to destroyed.

Call 13d — List all snapshots:

{
  "tool": "manage_snapshot",
  "arguments": {
    "action": "list",
    "project": "exercise-test"
  }
}

Call 13e — Undo last mutation:

{
  "tool": "manage_snapshot",
  "arguments": {
    "action": "undo",
    "entity_id": "<GOBLIN_ID>",
    "project": "exercise-test"
  }
}

Expected: Goblin Scout restored to active status.


Step 14: generate_game_inputs — Playwright Automation

Call 14a — Generate WASD movement inputs:

{
  "tool": "generate_game_inputs",
  "arguments": {
    "action": "generate_inputs",
    "entity_id": "<KNIGHT_ID>",
    "target_entity_id": "<CHEST_ID>",
    "control_profile": {
      "scheme": "wasd",
      "move_speed": 5.0,
      "turn_speed": 90.0
    },
    "project": "exercise-test"
  }
}

Expected: Returns timed keydown/keyup action sequence.

Call 14b — Project 3D → 2D screen coordinates:

{
  "tool": "generate_game_inputs",
  "arguments": {
    "action": "project_screen",
    "world_position": { "x": 10, "y": 0, "z": 5 },
    "camera": {
      "position": { "x": 0, "y": 2, "z": 0 },
      "orientation": { "pitch": 0, "yaw": 45, "roll": 0 },
      "fov_degrees": 60
    },
    "viewport": { "width": 1920, "height": 1080 },
    "project": "exercise-test"
  }
}

Expected: Returns screen_x, screen_y pixel coordinates.

Call 14c — Unproject 2D → 3D ray:

{
  "tool": "generate_game_inputs",
  "arguments": {
    "action": "unproject_ray",
    "screen_x": 960,
    "screen_y": 540,
    "camera": {
      "position": { "x": 0, "y": 2, "z": 0 },
      "orientation": { "pitch": 0, "yaw": 45, "roll": 0 },
      "fov_degrees": 60
    },
    "viewport": { "width": 1920, "height": 1080 },
    "ground_elevation": 0,
    "project": "exercise-test"
  }
}

Expected: Returns ray_origin, ray_direction, ground_intercept.


Step 15: wait_for_spatial_state — Async Polling

{
  "tool": "wait_for_spatial_state",
  "arguments": {
    "entity_id": "<KNIGHT_ID>",
    "condition": "active",
    "timeout_ms": 3000,
    "poll_interval_ms": 250,
    "project": "exercise-test"
  }
}

Expected: Returns immediately with met: true since Knight is already active.


Verification Checklist

After completing all 15 steps, validate:

#ToolExercised ActionsPass Criteria
1update_entitycreate, update5 entities created with valid ULIDs
2query_entitiesFTS, proximity, entity_id lookup, type filterAll return correct results
3set_relationadd relation2 relations created
4get_spatial_mapjson, summary, gltf5 entities, valid glTF 2.0
5simulate_movementsimulate (collision), navigateCollision detected, waypoints returned
6ingest_observationbasic ingest, reconcileRe-identification + new entity, reconciliation report
7get_expected_viewfrustum queryVisible entities returned
8link_to_goallink, get_contextGoal linked, context slice returned
9record_outcomemove, unlockEntity position and properties updated
10manage_spatial_specset, verify, listSpec passes verification
11create_evidence_packcreateSHA-256 hash in response
12use_spatial_blackboardpost, read, claim, releaseMessages visible, mutex works
13manage_snapshotsave, diff, list, undoDiff shows goblin change, undo restores
14generate_game_inputsgenerate, project, unprojectWASD actions, screen coords, ray
15wait_for_spatial_statewait (active)met: true returned

Cleanup

After all exercises pass, the test data lives in a separate "exercise-test" project database and does not affect other projects. The database file is located at:

.world-model-mcp/exercise-test.db

To clean up, simply delete this file or run:

rm -f .world-model-mcp/exercise-test.db

Troubleshooting

IssueResolution
Tool not foundVerify MCP server is running: node dist/index.js or world-model-mcp run
Project auto-detection failsPass "project": "exercise-test" explicitly in every call
Entity ID not foundEnsure you captured the entity_id from Step 1 and substituted <KNIGHT_ID> etc.
Collision not detectedVerify Stone Wall bounding box overlaps with the movement path
Snapshot diff emptyEnsure the Goblin was destroyed between the two snapshots

Signals

GitHub stars
16
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
world-model-mcp-exercises
Source
github.com/putervision/world-model-mcp