quest'n'click 4.5.0 · r1

Built for quest'n'click 4.5.0, revision r1. Whether it is published, and which one is current, is recorded at publication.json.

MCP tools

Français · Type: reference · Audience: author, contributor · Context: local Studio · Status: ready · Applies from: 4.5.0

The local Studio · contract: stable · verified by CI (support matrix of 4.4.0, 2026-10-23): Chromium end to end (the Studio's checks); Windows: the unit suite only · automated checks: jobs e2e, windows; CI plan e2e, windows; 2 test files · people's passes: studio-hero-matrix not run (#238) · known limits: demo-writes

Every tool an AI assistant can call on a quest-n-click game: the local MCP server, the remote MCP of a hosted Studio and the Studio's Assistant all serve the same registry, tools/studio/tools.ts. The tool sections below are generated from that registry (npm run wiki -- generate studio.mcp-tools): the English text is the description an MCP client receives, word for word.

Where the tools run

stdout carries the protocol only; the server's logs go to stderr. A failing operation (an unknown room, a bad path, a broken edit…) is a tool error with its message, never a crash: the server keeps running.

How to read a tool's section

Which tools each backend offers

BackendTools left out
Local server (npm run mcp, quest-n-click mcp, the dev server's Assistant): tools/studio/backend.tsnone
A hosted Studio (npm run mcp -- --server <url>, /mcp): tools/studio/http-backend.tsscreenshot, search_docs, list_docs, read_doc, run_tests, asset_prompts, speedrun_verify
The demo's Assistant, in the browser: src/studio/assistant.tsevery tool that needs an ability, except the documentation tools when the demo's snapshot holds the pages; set_value answers that it needs the dev server

Limit · demo-writes In the demo, the tools write to the visitor's copy in the browser only, and set_value is refused: structured writes edit the room's code through the TypeScript parser of the dev server.

The tools

list_rooms

Game overview. The current game: id, title, hero, rooms (id, name, decor), characters, items, verbs, checkpoints (named save states usable by solve and screenshot) and the image ids of the asset manifest with their size. Read-only.

Input:

No argument.

get_room

Read a room. One room: def (the RoomDef as loaded: props, actors, hotspots, look lines, reactions on, talk, hints, onEnter), layout (geometry from layout/&lt;id>.json), texts (every editable string literal with its JSON path, value, kind, line and speaker) and file. Use the path of a text with set_text. Read-only.

Input:

FieldTypeRequiredMeans
idstringyesRoom id, e.g. "house" (see list_rooms).

set_layout

Write a room layout. Replaces layout/&lt;id>.json with layout (the whole Layout object, same shape as get_room returns: props, hotspots, actors, walk, scale, entries…). Read the room first and change only what you must; never invent coordinates the human has not given you.

Input:

FieldTypeRequiredMeans
idstringyesRoom id, e.g. "house" (see list_rooms).
layoutobjectyesThe complete Layout object.

set_text

Edit a text of a room. Edits one string literal of rooms/&lt;id>.ts in place, addressed by its path from get_room texts (e.g. "look.pantry[1]", "on[3].do[0]", "talk.grandma[0].topic", "hints[2].lines[0]", "props.lamp.name"). value replaces the string. value: null deletes a list line, or a whole look.<id>. A path ending in "[+]" appends a line: "look.piano[+]", "hints[2].lines[+]", "on[3].do[+]" (a bare string in a command list is a hero line). Ids, image refs, flags and conditions are not texts and are refused. Paths after an append or a deletion shift: call get_room again. Result { ok, line, changed } (changed false: the value was already there).

Input:

FieldTypeRequiredMeans
idstringyesRoom id, e.g. "house" (see list_rooms).
pathstringyesJSON path of the text under defineRoom({...}); may end in "[+]" to append.
valuestring | nullyesThe new text, or null to delete.

set_value

Write a structured value in a room. Writes a structured value (3.4) at a path of rooms/&lt;id>.ts, as code in the file's style: a reaction ("on[3]", or "on[&lt;length>]" to add one), a condition ("on[3].if"), a command list ("on[3].do", "onEnter"), the room's stage ("stage": layers, lights, emitters, transition, links; CONTENT_GUIDE "The stage"), its painter ("renderer": "dom" | "canvas"). With id: "@game" the game file instead, for its objectives only ("objectives.&lt;id>": { title, done, optional?, parent? }, or one of its fields; list_rooms shows them). value is the JSON of it; omit it (null) to remove the path. dry: true returns the diff only. Otherwise the game is reloaded and validated after the write: an edit that adds a validation error is taken back and refused with the errors. Result { ok, line, changed, diff }.

Input:

FieldTypeRequiredMeans
idstringyesRoom id, e.g. "house" (see list_rooms).
pathstringyesPath under defineRoom({...}): "stage", "renderer", "on[3]", "on[3].if", "on[3].do", "onEnter"; with id "@game": "objectives.&lt;id>".
valueany JSON | nullyesThe value as JSON (a condition, a command list, a stage…); null removes the path.
drybooleannoOnly return the diff, write nothing.

add_entity

Add a prop, hotspot or actor. Adds an entry to rooms/&lt;id>.ts (section created if absent), its optional first look line, and a place in the layout: prop foot at at (height 60), hotspot 60 × 60 box centred on at, actor feet at at. name is required for props and hotspots; img is a prop image id (list_rooms images); char is the actor character id. at defaults to [320, 300]: then ask the human (add_note) to drag it in place in the Studio. 409 if the id exists.

Input:

FieldTypeRequiredMeans
idstringyesRoom id, e.g. "house" (see list_rooms).
kind"prop" | "hotspot" | "actor"yes
entityIdstringyesThe new entity id (letters, digits, _ and -).
namestringnoDisplay name.
imgstringnoProp image id.
charstringnoActor character id.
at[number, number]no[x, y] in the logical 640 × 400 room space.
lookstringnoFirst look line.

get_storyboard

Read the storyboard. storyboard.json: { boards: [...] } with panels, lines, hints and talk topics. The storyboard is the source of truth for text: change it first, then the rooms. Read-only.

Input:

No argument.

set_storyboard

Write the storyboard. Replaces storyboard.json with storyboard (must be { boards: [...] }; send the whole object as read with get_storyboard, modified). Written compactly; an unchanged storyboard is not rewritten. Result { ok, changed }.

Input:

FieldTypeRequiredMeans
storyboard{ boards }yesThe whole storyboard.

get_notes

Read the notes. notes.json, the shared log between the human and the AI: { entries: [{ id, about, author, text, at, task? }] }. The human answers your questions here; entries with task: true are requests from the human for you to do. Read-only.

Input:

No argument.

add_note

Write a note to the human. Appends a note to notes.json (shown in the Studio Notes tab). Use it when unsure what the human wants, or to ask them to place something. about is a room id, a panel id, room.entity or free text. author defaults to the name of your MCP client.

Input:

FieldTypeRequiredMeans
aboutstringnoWhat it is about.
authorstringnoWho writes (default: the MCP client name, or "ai").
textstringyesThe note.

validate

Validate the game. Static checks: broken ids, missing look lines, flags never set or read, minigame params. Result { ok, errors, warnings, ms }. Run after every content change.

Input:

No argument.

solve

Solve the game. Explores the game states to prove it can be finished, from New Game or from checkpoint from. Result { status, exit, headline, mode, finished, states, truncated, path, roomsReached, flagsReached, itemsNeverUsed, unusedItems, deadEnds, softlocks, errors, from, ms }. status/exit/headline are exactly what npm run solve prints (0 solved, 2 truncated: nothing proved, 1 a bug to fix). prove: true runs the exhaustive search (softlocks complete). profile: true adds why the search is slow or big.

Input:

FieldTypeRequiredMeans
fromstringnoCheckpoint id (list_rooms checkpoints).
profilebooleannoAdd the solver profile as text: what the states are made of, what the search cost, independent dimensions, monotonic things.
provebooleannoExhaustive search: every reachable state and the softlocks (slow on a big game; default: the fast witness).
reality"closed" | "adversarial" | { scenario, signals }noA game with reality.signals (4.1.1): the world to solve in. closed (default) no signal, a scenario { scenario, signals } in that order, adversarial any declared signal at any point. A simulation: no service is contacted.

content_report

Content profiler. Game-design profiler, as Markdown: per room (zones, props, actors, exits, rules, topics, hints, scripts; things with no look line, verbs that only get fallbacks, props that never change), per item (obtained where, how many rules use it, consumed), per character (rooms, topics, lines, unreachable topics), unreachable rooms and exits with no way back. Read it to decide what to write next. Read-only.

Input:

No argument.

get_ir

The game as the tools see it. The game's intermediate representation (4.1.12): rooms, entities, rules, topics, listeners, scripts, objectives, Reality policies and the trusted extensions by name, each id with the file and line that writes it (provenance). The same JSON as npm run ir -- --json. Read-only.

Input:

No argument.

world_graph

World map. The rooms and the ways between them (declared exits, goto commands, map places) as a DOT graph, with unreachable rooms and exits with no way back. Read-only.

Input:

No argument.

dialogue_tree

Dialogue tree. The conversation of a character in a room as an indented tree: topics (with their conditions), lines, choices and their options, branches. Derived from the talk topics, nothing else to maintain. Read-only.

Input:

FieldTypeRequiredMeans
idstringyesRoom id.
actorstringnoActor id (default: every character with topics).

puzzle_graph

Puzzle graph. What every rule, topic, script and listener needs (conditions, items) and changes (items, flags, props, places, events). Without id: the overview as Markdown (every item and flag with what produces and uses it, flags read but never set, things produced but never used). With id (an item, flag, prop, place or event): its card: acquired by, consumed by, used by, requires first, unlocks, downstream. Read it before changing a puzzle. Read-only.

Input:

FieldTypeRequiredMeans
idstringnoAn item, flag, prop (room.prop), place or event id; none for the overview.

storyboard_coverage

Storyboard coverage. The storyboard (get_storyboard) checked against the content, as Markdown: per board and panel, whether its room, speakers, lines, talk topics, sounds and actions ("Open the armchair", "Use pipe with tank") exist in the game: ok, partial (the pieces exist, no rule answers; a close line), missing, or unknown (prose). Read it to find what of the story is not implemented yet. Read-only.

Input:

No argument.

playtests

Playtests. The sessions players shared from their phones (games/&lt;id>/playtests/*.session.json, ids only) replayed on the current content and summed up, as Markdown: time per room, where players stall (the same action again and again without effect), hints shown, where they stopped, minigames played, sessions the content has outgrown. Read it to know where the game is harder than you think. Read-only.

Input:

No argument.

lint

Content lint. What the validator cannot say and the solver does not say loudly, as Markdown: conditions nothing can satisfy, rules another rule hides, items no rule needs or nothing gives, hints that cannot fire, choices with a dead option, and, from a solver run, live actions never run and rooms never reached. Each finding names its content path, its stable id and what to do. prove: true runs the exhaustive search first (slow on a big game). Read it before asking a human for a review. Read-only.

Input:

FieldTypeRequiredMeans
provebooleannoRun the exhaustive proof first (default: the fast witness).

screenshot

Screenshot a room. Renders a room (optionally at a checkpoint) with the real engine through the running dev server (default http://localhost:5173/, env WEB_SCUMM_DEV_URL; start it with npm run studio or npm run dev) and Playwright. Returns the PNG path (relative to the repository) to open and look at, or an explanation when unavailable.

Input:

FieldTypeRequiredMeans
roomstringyesRoom id, e.g. "house" (see list_rooms).
checkpointstringnoCheckpoint id.

search_docs

Search the documentation. Searches the documentation pages (the wiki written under wiki/, 4.5.0) by words, in French or English: page titles and questions first, then aliases, keywords and identifiers (a DSL command, an npm script, an HTTP code such as 423), then section headings, then section text. Accents and case do not matter; the glossary adds the other language's words (verrou, lease). Each result is id#section with its title, type, context, versions, status, score, the reason of the match and an excerpt with the words found in bold: read it with read_doc { id, section }. No confident match gives an empty list and the index pages to try. version leaves out what does not apply to that version. Read-only.

Input:

FieldTypeRequiredMeans
querystringyesWords or a question, in French or English.
lang"en" | "fr"noOnly pages in this language (default: both).
audience"player" | "author" | "admin" | "contributor"no
context"engine-repo" | "created-project" | "studio-local" | "studio-demo" | "studio-hosted" | "bridge" | "player"no
versionstringnoA product version (4.5.0): only what applies to it.
type"tutorial" | "howto" | "reference" | "explanation" | "troubleshooting" | "index"no
includeArchivedbooleannoAlso deprecated and archived pages, and with version the pages that do not apply, marked so.
limitinteger 1..20noResults per answer (default 5, at most 20).
cursorstringnoThe cursor of a previous answer to the same request, for more.

list_docs

List the documentation pages. The documentation pages there are to read (wiki/, 4.5.0), filtered by audience, context, type, language or state: id, title, type, audience, context, versions, state, languages and section ids. A page still to write is not listed. Read-only.

Input:

FieldTypeRequiredMeans
audience"player" | "author" | "admin" | "contributor"no
context"engine-repo" | "created-project" | "studio-local" | "studio-demo" | "studio-hosted" | "bridge" | "player"no
type"tutorial" | "howto" | "reference" | "explanation" | "troubleshooting" | "index"no
lang"en" | "fr"no
state"draft" | "ready"nodraft pages exist in the repository only.

read_doc

Read a documentation page. Reads the documentation. Recommended: search_docs, then read_doc { id, section } for the section it found (lang en or fr, default en; maxChars 20000 by default, at most 100000, and a cursor for the rest), with where the text comes from (version, commit, doc revision) at its top. name instead returns a whole, large historical page in one block, rebuilt from the sections of the documentation: CONTENT_GUIDE (the game format, the DSL of rooms, conditions and commands), ENGINE, TOOLS, STUDIO, WORKFLOW, AUDIO (music and effects), UPGRADING (v2 to v3), CLASSICS (the famous mechanics of the genre, each with its DSL: read it before asking for a new command); with name, the other arguments are ignored. Give either name or id, not both. Read-only.

Input:

FieldTypeRequiredMeans
name"CONTENT_GUIDE" | "ENGINE" | "TOOLS" | "STUDIO" | "WORKFLOW" | "AUDIO" | "UPGRADING" | "CLASSICS"noOne of the eight historical pages, whole (the other arguments are then ignored).
idstringnoA page id from search_docs or list_docs, e.g. "create.rooms".
sectionstringnoA section id of that page (its <a name>), e.g. "walkable-zones".
lang"en" | "fr"noThe page's language (default en).
cursorstringnoThe cursor of the previous answer, for the rest of the text.
maxCharsinteger 1..100000noAt most this many characters per answer (default 20000).

run_tests

Run the tests. Runs npx vitest run (engine tests and the game walkthrough) and returns the summary lines and the failures. Takes a few seconds to a minute. Read-only.

Input:

No argument.

asset_prompts

Art prompts. The image-model prompts for the game's art (same as npm run prompts): one STYLE block, then one ready-to-paste prompt per sheet (characters with the engine's pose rows and special poses, mouth kits, object sheets cell by cell, backgrounds with LOCATION and EMPTY SPOTS, furniture) and a checklist to cut and import them. Hand the sections to the human as-is; never write a sprite prompt by hand. missing: true keeps only the sheets with images not cut yet. Returns the markdown, and { missing, sheets } as structured content. Read-only.

Input:

FieldTypeRequiredMeans
missingbooleannoOnly the sheets with at least one missing image, and only their missing cells.

speedrun_verify

Verify a speedrun. Replays a speedrun envelope (.wsrun, 4.1.14) against the current game: reloads the exact rules of its category, replays its inputs with its seed, recomputes the in-game time, the splits, the final state and the hash chain, and checks the category’s rules. Returns { verdict, code, reason, trust }: valid is the only rankable verdict, inconclusive is never valid, and a verifier grants at most replay-valid. Pass the file path under the game project, or the envelope text. Read-only.

Input:

FieldTypeRequiredMeans
pathstringnoPath of the .wsrun file, relative to the repository or project.
envelopestringnoThe .wsrun text itself (instead of a path).

Resources

The local server also gives two resources, as JSON: webscumm://game (the same as list_rooms) and webscumm://room/<id> (the same as get_room). They keep the former name's scheme, webscumm://.

Errors


Edit the source of this page · Report an error