A world to build on.
Microworld generates initial world data. You decide how to render it, what players can do, and where to store their changes.
Your first world
Send a QUERY request with a JSON body. No account or API key is required.
curl --request QUERY https://microworld.kaf.sh/api/world --header 'Content-Type: application/json' --data '{
"generatorVersion": "1",
"seed": "my-first-world",
"preset": "overworld",
"window": { "x": 0, "y": 0, "width": 32, "height": 32 }
}'Or request a window from your browser or game client:
const response = await fetch("https://microworld.kaf.sh/api/world", {
method: "QUERY",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
generatorVersion: "1",
seed: "my-first-world",
preset: "overworld",
window: { x: 0, y: 0, width: 32, height: 32 },
}),
});
if (!response.ok) throw new Error(await response.text());
const world = await response.json();One world, many windows
World coordinates are nonnegative safe integers. Each axis contains Number.MAX_SAFE_INTEGER cells, so the final cell coordinate is 9007199254740990. The window must fit entirely within the world.
A chunk is 16 × 16 cells. To fetch chunk cx, cy, request x: cx * 16, y: cy * 16, width: 16, and height: 16. Windows need not align with chunks. Request several chunks together to reduce HTTP overhead.
The playground pans inside its loaded window. A game that needs to keep exploring should request neighboring windows as the player moves and cache them locally.
Read the world data
Elevation and biome arrays use row-major order. The array index for a local cell is y * width + x.
| Field | Meaning |
|---|---|
generatorVersion | The algorithm version used for this response. |
seed, preset, window | The requested world identity and window. |
configuration | Resolved terrain settings and placement rules. |
elevation | One integer per cell, between 0 and 65535. Relative height, not meters. |
biome | One biome identifier per cell, such as forest or ocean. |
objects | Placed objects intersecting the window, with world coordinates and footprints. |
tiles | Nonempty template cells inside the requested window, with their owning object IDs. |
for (let y = 0; y < world.window.height; y++) {
for (let x = 0; x < world.window.width; x++) {
const i = y * world.window.width + x;
drawCell(x, y, world.biome[i], world.elevation[i]);
}
}Object origins can lie outside the requested window when their footprints cross its edge. Deduplicate objects by ID when combining windows.
Start somewhere interesting
Presets supply terrain and placement defaults. Override individual terrain fields. A supplied placements array replaces the preset's placement rules; use an empty array to disable objects.
| Preset | World |
|---|---|
overworld | Continents, forests, deserts and mountain ranges. |
chess | An alternating board ready for your own pieces. |
rpg | Broad terrain with towns, ruins and woodland. |
hell | Lava seas, ash wastes and basalt ridges. |
islands | Scattered islands and shallow sandy shores. |
sky-islands | Floating meadows above an empty void. |
ocean | Deep water, reefs and rare islands. |
arena | Repeating 64-cell arenas with shared entrances. |
maze | Connected region mazes with matching border gates. |
moon | Impact basins and mineral deposits. |
wetlands | Marshes, pools and fungal groves. |
Terrain controls
| Setting | Range | Purpose |
|---|---|---|
scale | 4–4096 | Size of terrain features in cells. |
seaLevel | 0–65535 | Water threshold for terrain presets. |
roughness | 0–1 | Strength of smaller terrain details. |
moisture | 0–1 | Climate moisture bias. |
temperature | 0–1 | Climate temperature bias. |
Structured presets such as chess, arena, and maze define their own geometry. Not every terrain control changes every preset.
{
"seed": "archipelago",
"preset": "islands",
"terrain": { "scale": 64, "seaLevel": 32000 },
"placements": [],
"window": { "x": 0, "y": 0, "width": 128, "height": 128 }
}Name your own biomes
Pass a biomes array to classify terrain using your own identifiers. Each definition can constrain elevation, moisture, and temperature. Rules use the first matching custom definition; cells that do not match keep their preset biome. Mark water biomes with water: true so placement proximity rules recognize them.
"biomes": [
{ "id": "silver-lake", "maxElevation": 28000, "water": true },
{ "id": "enchanted-woods", "minMoisture": 0.6 },
{ "id": "meadow" }
]Use the same identifiers in placement rules and in your renderer. Custom biome rules apply to structured presets too, so leave them out when you want to retain a chessboard or maze's built-in labels.
Put things in their place
Rules describe candidates on a deterministic placement grid. A candidate appears only when it passes its probability, biome, elevation, and spacing checks. A placement request never guarantees an exact object count.
{
"seed": "woodland",
"preset": "overworld",
"placements": [{
"id": "trees",
"object": "oak",
"pitch": 12,
"probability": 0.7,
"minSpacing": 3,
"biomes": ["forest", "grassland"],
"minElevation": 29000,
"maxElevation": 45000,
"maxRelief": 3000
}],
"window": { "x": 0, "y": 0, "width": 64, "height": 64 }
}pitch sets the candidate grid spacing. width and height define footprints. maxRelief limits the elevation difference across a footprint. nearWater limits distance to water, up to 16 cells. See the full API contract for collision priority, spacing semantics, and all validation rules.
Give structures some substance
Use a built-in template such as cottage or ruin, or pass a rectangular array of tile names. A null cell emits no tile. Inline template dimensions must match the footprint.
{
"id": "shelters",
"object": "shelter",
"pitch": 32,
"width": 3,
"height": 3,
"biomes": ["grassland"],
"rotations": [0, 90, 180, 270],
"template": [
["wall", "wall", "wall"],
["wall", "floor", "wall"],
["wall", "door", "wall"]
]
}Templates provide tile identifiers, not textures or procedural interiors. Your renderer maps each identifier to an image, color, or game entity. The server clips emitted tiles to the requested window while preserving the full object's identity.
Give your agent a world
The stateless MCP endpoint is https://microworld.kaf.sh/mcp. It targets the MCP 2026-07-28 specification. Use a client that supports that protocol version and its stateless HTTP transport.
| Tool | Purpose |
|---|---|
list_presets | Discover the preset library. |
get_preset | Read a preset's defaults and customization options. |
generate_world | Generate a window with the same inputs as the QUERY API. |
Try asking your agent: "Show me Microworld's presets, then generate a 32 × 32 island world with seed driftwood." The API and MCP share the same generator and validation. No session or account is required.
See the transport contract and wire examples for the exact request headers and JSON-RPC messages.
Keep requests bounded
The default limits are 256 cells per side, 65,536 cells per window, and 8 placement rules. The hosted service may enforce lower limits. Complex placement rules can reach the work budget before the cell limit.
Always check the HTTP status before reading world data. Invalid inputs, oversized requests, and generation work limits produce errors. Reduce your window or simplify placements when a request exceeds the budget. Avoid retrying invalid requests unchanged.
Public hosting has finite capacity. Cache generated windows, generate on demand, and use your own deployment if your game needs dedicated capacity.
Keep your world yours
Save the seed, generator version, preset, and configuration alongside your game. Pin generatorVersion: "1" when reproducibility matters. Omitting the version selects the server's default.
Microworld generates the initial state only. Store cut trees, opened doors, moved pieces, and player buildings in your own persistence layer, then apply them over the generated world.
Microworld is open source under Apache 2.0. You can inspect the implementation, contribute presets, or run your own Worker.