Skip to content
PuniDocs
Open Puni

WebMCP


The tools Puni's pages register in a browser that supports WebMCP, the loop they follow, and the one thing the browser must have.

When a browser exposes document.modelContext, Puni's landing page, library and studio register tools on the page. An agent driving that browser gets the signed-in session for free: no token, no server, the scene that is open.

#Tools on the landing page

ToolDoes
puni_get_startedWhere the person signs in to begin; it does not sign in or open anything
puni_read_contract, puni_read_runtimeThe command contract; the app's builds

#Tools on the library

ToolDoes
puni_list_projectsYour scenes with their revisions
puni_open_projectOpens one in the studio
puni_create_compositionA new blank scene, saved and opened
puni_search_projectsKeyword search, or semantic with mode: "semantic"
puni_read_contract, puni_read_runtimeThe command contract; the app's builds
puni_read_projectA saved scene's structure at the revision search returned
puni_preview_scene_index, puni_index_scene_descriptionWhat semantic search would send, then sending it on request
puni_remove_scene_embedding, puni_refresh_scene_searchRemove a scene from semantic search; bring its entry up to date

The search and index tools are on the studio too. Project summaries use actionCount for action definitions and clipCount for timeline clips. Legacy stored metadata has actionCount: null until resaved; counts from a loaded document are exact. Checkpoint actions aliases actionCount.

#Tools in the studio

ToolDoes
puni_read_sceneThe open scene's document, selection, playhead time and save state
puni_select_objects, puni_seek_timelineSelection and time, the way a pointer would
puni_apply_commandOne validated, undoable authoring command, saved at once
puni_historyUndo or redo the latest edit, then save
puni_inspect_construction, puni_save_construction_motionTake a structured object apart for inspection; keep that as timeline motion
puni_save_object, puni_use_objectKeep a selection as a library object; bring one into this scene
puni_export_compositionThe scene as a project file, a GLB or a PNG
puni_read_viewerWhat the page is drawing: its load state, frame rate, draw calls and GPU resources
puni_sculpt_objectA front picture (an https URL) with optional extra views, or a prompt, into an object; on the person's own keys, or Puni's credits where offered
puni_get_sculpt, puni_add_sculptProgress and the add commands; or add the ready sculpt to the open scene
puni_segment_sculptSplit a ready sculpt into named parts, textures kept

#When the tools arrive

A page's own tools register as soon as it mounts. Six retrieval tools load separately and register a moment later, on the library and in the studio alike: puni_search_projects, puni_read_project, puni_preview_scene_index, puni_index_scene_description, puni_remove_scene_embedding and puni_refresh_scene_search. An agent that lists tools the instant a page opens can see the page's tools without those six; list again.

If the six fail to load, the page tries once more after two seconds. If they are still missing it says so once in the console, the page's other tools keep working, and reloading the page brings them back. Leaving a page unregisters every tool it registered.

#The loop

  1. puni_read_scene and puni_read_contract.
  2. puni_apply_command for each edit (its fields are in puni_read_contract). It is immediate and saved, the way a pointer's edit is, and puni_history undoes it.
  3. puni_read_scene again, and puni_read_viewer for what the page is drawing.

There is nothing to commit: each edit saves a new revision. Undo it with puni_history, because a browser edit over browser work leaves no checkpoint. To look at pixels before writing, call puni_render_view from MCP tools with a commandsJson batch: it draws the saved revision with the batch applied and saves nothing.

#Brand type and geometry

Upload fonts and images through the MCP upload_asset tool. The browser tools do not expose that upload call. They can apply a text module with the retained font in module.assets and its URI in fontAsset. Record provenance, including the licence.

Leave fontAsset absent to keep the built-in typeface. Missing or invalid custom font bytes refuse without substitution. A profile can use exact SVG path data in its outline, with inset bevel and bevelSegments for its edge. If an older module rejects a new property, update its definition from the current contract first.

#The browser must draw

puni_read_viewer answers with what the page has drawn, and drawing needs WebGL. Some hosted browsers, ChatGPT's among them, have no WebGL. There the viewer reports an error and never a drawn scene, so builds are blind. Read How agents see.

#Limits

Leaving the scene unregisters the tools.

Read MCP tools for the same loop from outside the browser.

Was this useful?