get_scene
Get scene
Returns the full scene graph: flat node dictionary, root node IDs, collections, and explicit installed plugin IDs when present.
无需输入参数。
app.pascal由 pascal.app 发布官方发布者v1.0.6更新于 Nov 6, 2026
Create, inspect, validate, and save editable 3D building scenes with Pascal's MCP server.
Pascal 3D 建筑编辑器的 MCP 服务器,让助手创建、查看、校验并保存可编辑的 3D 建筑场景。
Web executable,通过 Streamable HTTP。 远程服务在工作区中配置后即可从网页运行时运行。
把这段提示词粘贴到 Claude Code、Codex、Cursor 等智能体,或 SourceWeft 对话中。智能体会读取该服务器的安装指南,先向你展示发布者、端点和登录方式,经你同意后再把它添加到你的客户端。密钥不会写进任何命令。
阅读 https://sourceweft.com/mcp/app.pascal%2Feditor/install.md,并按其中说明把这个 MCP 服务器接入我的客户端。修改任何配置之前,先告诉我它的发布者、端点和登录方式,等我确认。不要把 API 密钥写进命令或我会提交的文件;问我密钥应从哪里获取。把它添加到你客户端的 mcpServers 配置中。 客户端会在首次连接时完成 OAuth 登录。
{
"mcpServers": {
"pascal-3d-editor": {
"type": "http",
"url": "https://editor.pascal.app/api/mcp"
}
}
}Also listed on Smithery.
Model Context Protocol server for the Pascal 3D editor. Drives the
@pascal-app/core scene graph from any MCP-compatible AI host.
For the hosted Pascal MCP endpoint and copy-ready setup for Claude Code, Codex, Cursor, and OpenClaw, read Connect an AI agent. The hosted endpoint edits projects in a Pascal account; this package is the open-source, local server for custom hosts and local scene storage.
Listed in the official MCP Registry as
app.pascal/editor.
The server runs headlessly in Node.js (22.23.4+ on 22.x, 24.22.1+ on 24.x, or 26.12.1+) or Bun, with no browser, WebGPU, React, or external database service. It exposes the same scene mutations used by the editor UI (create walls, place items, cut openings, undo, etc.) as MCP tools, resources, and prompts.
For a local editor and MCP that share projects automatically, install the Pascal CLI:
pascal editor starts the editor and an authenticated MCP service together.
pascal mcp connect is a stable stdio connector that discovers the dynamic loopback
port, so MCP client configuration contains neither a changing port nor a secret.
Use this package directly when embedding the MCP server, supplying a custom store, or running MCP without the Pascal editor.
@pascal-app/core is a peer dependency. The local store uses Bun SQLite under Bun and
Node's built-in SQLite driver under Node.js.
Launch the server over stdio in one line:
Load an initial scene from disk:
Expose it over loopback HTTP:
Binding a non-loopback host requires a bearer token:
Scenes saved through MCP are stored in a local SQLite database:
Set PASCAL_DATA_DIR when you want the MCP server and the running editor to
share a different directory, or PASCAL_DB_PATH when you need an exact database
file path. The store uses WAL mode and transactional version checks so separate
local processes can save and open the same scene database.
During workspace development, run both sides with the same data directory:
Scripted objects keep their GLB and source in <database-path>.artifacts/<sha256> beside the
local SQLite scene database, where saved scenes live (also with --scene, which only seeds the
first scene); keep that directory with the database. Files are verified against their hash and
written once, so saved scenes and undo history keep their original geometry. The standalone
editor reads and writes the same database-side store.
Local MCP compilation is opt-in with PASCAL_SERVER_SCRIPT_COMPILE=1. It runs in a separate
process without inherited environment variables, with a deadline; this is not a sandbox for
untrusted code. Blender (bpy) modules run in the Blender binary PASCAL_BLENDER names
(blender -b), with the same caveat; Blender geometry scripts
walks through one. get_source can read saved scripts without enabling compilation.
When the editor and MCP server share the same PASCAL_DATA_DIR, MCP mutations
against a loaded saved scene are persisted to SQLite and recorded in a local
scene_events stream. The editor page subscribes to that stream at
/api/scenes/:id/events with server-sent events, so an open browser tab can
apply scene graph snapshots as the agent edits the scene.
The flow is intentionally local and lightweight:
load_scene.create_room, add_door, furnish_room,
add_wall, place_items, or set_zone.Each mutation version-checks the saved scene before writing. If the browser or
another MCP process saved a newer version first, the MCP tool returns
live_sync_version_conflict; reload the scene with load_scene before
continuing.
The recommended JSON configuration for Claude Desktop, Cursor, and compatible clients is:
Edit ~/Library/Application Support/Claude/claude_desktop_config.json
(macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
Via the CLI:
Or add to .mcp.json at the repo root:
For package-development testing without the managed CLI, build first and point Claude Code at the built binary:
Via the CLI:
For local workspace testing before publish:
This writes an entry like this to ~/.codex/config.toml:
In Cursor settings (settings.json):
Embed the server in your own Node.js or Bun process using the in-memory transport. The example below runs a full client/server pair inside a single script — useful for agent frameworks and tests.
A host that passes its own operations (createPascalMcpServer({ operations })) may implement
runInScene(run): every tool handler starts inside it, and tools re-enter it after their awaits,
so the ids a tool mints and the operations it plans run in the scene's synchronous scope. It is
optional; without it handlers run as they always have, with random ids. An implementation that
computes on a detached scene must provide it, delegating to SceneBridge.runInScene, or its tools'
ids will not be the scene's and a recomputed effect will not match.
See examples/embed-in-agent.ts for a
compilable version.
A plugin's 'operation' tools register with the same runner as the shared
tools: it parses the input, applies the outcome as one history step and answers
with achieved and the refusals. The annotations are the host's, never read
from the plugin's contract.
The contract shapes, versions and trust rules are in plugin authoring.
Pascal is a right-handed scene where X and Z form the ground plane and Y
is up. Lengths are in metres; rotations are radians, stored as Euler
[x, y, z] tuples.
Plan → world. Every 2-D point you pass is a level/building-local
ground-plane coordinate
[x, z] — this includes wall.start / wall.end and the polygon / holes
arrays of slab, zone, and ceiling. With the default identity building
transform, it appears in world space as:
There is no sign flip in the stored convention: tooling consumes the second
component as world Z directly. The vertical y starts from the owning level's
stacked height as computed by the level system from accumulated level heights,
plus the element's own height; slabs additionally carry an absolute
elevation.
Heads-up when you compute coordinates outside the editor. Pascal's
viewports apply their own rotations on top of the world axes: the 2-D plan
panel rotates its content by the user's view rotation (north-aligned = 0°,
FLOORPLAN_VIEW_ROTATION_DEG baseline, north = world −Z), and
the 3-D "top-down" snap preserves the camera's current azimuth, so when invoked
from the iso default position, world and screen axes are offset by ~45° until
you orbit to an axis-aligned view. So a layout authored as if
"Y = north, viewed top-down" — common in land surveys, north-up site plans,
and 2-D plotting libraries — will arrive rotated relative to its source
when viewed in Pascal (and possibly further reflected, depending on which
viewport and camera state you're in). The editor's own 2-D and 3-D tools are
internally consistent with their stored coordinates, so this only affects
geometry authored programmatically. To verify orientation before trusting
externally-computed coordinates, place a scaled guide image at known anchor
points and check alignment; apply whatever rotation (or reflection) your
authoring side needs to match.
A worked demonstration of all of this — axis-aligned baseline, the rotated
30° example below, and a paired "page-intent vs world-result" L for the
external-coordinate gotcha — lives in
examples/coordinate-conventions-demo.md
and examples/coordinate-conventions-demo.json.
Load the JSON with
bunx @pascal-app/mcp --stdio --scene examples/coordinate-conventions-demo.json.
Example — a 6 × 4 m slab rotated 30° about its first corner (coordinates rounded to 3 dp; sides ≈ 6 m / 4 m; not axis-aligned, so the mapping is actually exercised):
This lands flat on the ground (Y = 0), about 6 m along a heading 30° off the +X axis and 4 m along its perpendicular — i.e. occupying world (x, z) directly.
One separate gotcha: wall-attached coordinates are wall-local, not plan
coordinates. Stored door/window position[0] is metres along the wall, and
wall-attached rotations are wall-local too.
All tools validate their inputs and outputs with Zod. Mutation tools are captured by Zundo's temporal middleware as a single undoable step.
Arguments a tool's input schema rejects come back as a tool error whose JSON
text is { error, code: "invalid_input" }, as every other refusal names its
code: the arguments are the wrong shape or type, so read error, fix them and
call again. It is the schema's refusal, before the tool ran; the codes a tool
raises itself (apply_patch's invalid_update and invalid_parent, a room's
cannot_enclose) come back as { error, code, ...details }, and apply_patch
adds patchIndex and id. A level an agent writes without a height (a
create in apply_patch, or an update that clears it) is given the height the
editor's own load would derive from what the level holds: the top of its
tallest wall or ceiling, and for an empty level the default storey height, 2.5 m.
apply_patch says so in notes, one line per level filled. add_level takes
an optional height and uses the same default.
Every length and angle a shared tool takes reads one notation: a bare number is in the unit the field states (metres, degrees, radians), and text carries its own unit, inches, feet and millimetres included. A roof pitch is degrees or rise over run:
"26.6", "26.6°", "0.46 rad", "6/12", "6 in 12" and "6 on 12" are
read too. Minutes and seconds are refused ('6"' is a builder's inches), and so
is a "pitch" fraction like "1/4 pitch", which is rise over span.
The vision tools require the MCP host to support the sampling capability
(createMessage). Hosts that don't will see a structured
sampling_unavailable error.
A retired tool is listed no more and still answered: a call to its name
returns an error with the code tool_retired, the tool that replaced it
(replacement) and how to use that one. validate_scene retired into
verify_scene, find_nodes into find_by_type and describe_node into
get_node (RETIRED_MCP_TOOLS in @pascal-app/core/agent-tools).
gableOverhang is a roof segment's own reach past its gable-end walls (a
gable's or gambrel's ends, a shed's sides), in plan metres; left out, the ends
reach as far as the eaves. The roof panel's "Gable overhang" slider edits the
same field.
export_glb returns not_implemented. GLB export depends on the Three.js
renderer and isn't reachable headlessly without a large additional effort.@pascal-app/viewer in a browser
host.loadAssetUrl / saveAsset are browser-only; items that reference
asset://<id> URLs aren't resolvable in Node. Supply absolute URLs or
data: URLs for item assets if you need them usable outside the browser.dirtyNodes accumulates in headless mode because no renderer consumes it.
Call bridge.flushDirty() if observability matters to your consumer.Smoke-test the stdio binary end-to-end:
MIT
来源:packages/mcp/README.md,提交 0602f9e
Get scene
Returns the full scene graph: flat node dictionary, root node IDs, collections, and explicit installed plugin IDs when present.
无需输入参数。
Validate design
Check a design (procedural item recipe) without changing the scene. Returns `valid`, coded `diagnostics` with paths (errors block placement, warnings flag floating or unbalanced parts), the parameter `sweep`, and `measurements` at the given parameters: bounds, per-part bounds and instances, true triangle counts, draw groups per slot, datum contact and connected components. It is the authority: some rules are not expressible in pascal://schema/design. Repair and re-validate until `valid` is true. Version 2 designs validate fully but carry a design_version_not_enabled warning: placement accepts version 1 only until the next release.
design必填parametersPlace design
Create one instance of a design (procedural item recipe, object or JSON string) in the scene. The design must pass validate_design. Its mounting picks the host: floor designs go on a level (or a slab or zone of it) or on a named surface of a placed design; wall-side designs on a straight wall face; ceiling designs under a ceiling. Only creates: refusals carry a code (invalid_design with diagnostics, design_version_not_enabled for version 2 designs until the next release, design_too_large above 24 KiB, invalid_placement, node_exists, host_not_found, wrong_host, unknown_surface, does_not_fit) and change nothing.
idnamesideslotsdesign必填hostId必填position必填rotationsurfaceIdparametersMeasure stair
Inspect actual flight risers, walking-line going, slope, arrival, uniformity, headroom against floors, ceilings and stair bodies, and design-target diagnostics without changing measured geometry.
stairId必填availableFit stair
Explicitly replace stair riser proportions with uniform risers from design targets. Optionally fit going by changing flight runs or arc sweep; preserves landing elevations. Optional straight, L or U layout replaces the flight chain with width-sized turning landings or quarter-turn winders. Winder going is measured along the selected walking line. One atomic edit.
turnwidthfitRunlayoutstairId必填targetsdivisioninnerGaplandingDepthturningStrategywalkingLineOffsetFind by type
Find everything of one type in the scene, wherever it lives: nodes of that kind (column, door, window, wall, stair, imported-mesh, a plugin's kind…), items of that category, lights (any item that emits light), and typed parts inside scripted objects, windows and doors (a porch's columns, a window's grille). Narrow it to a level, a parent, a zone or an importer's source ids; without a type, every node the other filters match. A word that names nothing (no node kind, nor an item category or part type in this scene) is refused with the kinds the scene holds. Each result gives the node's id, name, kind, level and parent, with its metadata and provenance when it has them (one over 1 KB is named in omitted instead); get_node reads a node whole. Parts are read-only: they come back with their object's id, the part id and, for objects directly on a level, its bounds in level coordinates; edit them through their object. count says how many match; past limit (200 unless asked) the rest are left out of results, with truncated: narrow the call or raise limit.
typelimitzoneIdlevelIdparentIdsourceIdsourceIdPrefixList levels
List every level of every building in floor order: id, name, floorIndex, building (parentId), role (occupied storey, roof-only level or support level), child count, gradeStanding (at-grade, partly-below-grade or below-grade against the ground line and the terrain), isGroundLevel, and which one the person is viewing (isActive); groundLevels names, per building, the level at grade (levelId, whether the building names it, floorElevation, gradeElevation, floorOverGrade, seated). A roof-only level is the roof, not a storey.
无需输入参数。
Get node
Get the full data of any node by its id: its fields as stored, with what the scene decides for it beside them (a wall's or a ceiling's resolvedHeight, and heightIsExplicit, false when it follows its storey; a wall's resolvedThickness; a door's or window's resolvedOpening, its floor and what it hangs from; the displayName a level or a floor plate is shown by); its ancestorIds, its parent first (a door's wall, then the level, the building, the site); and the scene materials (scene:<id>) its finishes use. A container's node lists its children as stored; any that name no node are listed again in missingChildIds. A node its schema rejects comes back as stored, with nothing derived (verify_scene says what is wrong).
id必填Get level summary
Summarise one level so nothing on it goes unseen: its role and counts, then walls (length, heights, doors and windows), zones (name, area, size, floor_choices), slabs, ceilings, items (floor, wall and ceiling), floor openings, stairs, roofs, and anything else by type. Zone polygons: get_zones; a node's full data: get_node.
levellevelIdGet walls
Get the walls of a level: start and end in metres, length, stored and resolved height, thickness, and their doors and windows. wallFaceChains gives base-chain provenance for geometric faces a (left of start → end) and b (right): ref (authored face slot), legacy (inline spec), or default (declared fallback ref). These are not final rendered finishes: room intent, face paint regions, exterior assembly cladding and reference availability can change appearance. A chosen white or default-matching ref is legitimate; fallback alone is not a defect or a requirement to paint.
levellevelIdGet zones
Get the zones (rooms) of a level: name, colour, polygon and holes in metres, area in m² (holes taken out), bounding size, and floor_choices: the floor plates the room can take (key, plateId, name, current; drawn and mezzanine flags). A room shares its floor plate with the rooms next to it unless detached. Persisted authored wall intent is wallMaterial (string, or null when absent) and wallOverrides (records of wallId, geometric face a or b, and finish; [] when absent). This is not a final rendered finish or visual verification: local overrides and face paint can take precedence, and absent room intent is not a defect or a requirement to paint.
levellevelIdDuplicate level
Copy a level with everything on it, as the editor does: fresh ids, internal links kept, and units whose rooms are all on that level copied too; plan references, scans and spawn points stay behind. The copy goes above the original (or below it) and the floors past it move up one.
namepresetlevelIdpositionSet ground level
Make a level the building's ground floor: the one standing at grade, its floor 8 in over the ground (about 6 in on cast concrete foundations, 12 in on stone: the building's foundation construction seats it; the result names it). A building's levels stack on a ground line; the levels with a lower floor index are below grade (basements), the ones at or over it are not, and list_levels reads it as groundLevels (levelId, floorElevation, floorOverGrade, seated) and each level's gradeStanding (at-grade, partly-below-grade, below-grade) and isGroundLevel. This names the level on the building, seats the building so that level's floor datum, the top of the foundation where the wood framing starts, stands 0.203 m (8 in) over grade on a block foundation, 0.15 m on cast concrete (Europe), 0.3 m on stone (a historic style) (flat site: world Y 0.203; sculpted terrain: 0.203 m over the mean ground height under its floor), moving the building in height only — the plan stays where it is and every level keeps its place relative to the others — and renumbers the floor indices so it is 0 and the ones under it are -1, -2…. A level added below (add_level position below) stacks under the lowest level without moving the ground floor. A roof level or a support level cannot be the ground floor (not_a_storey). One undo step. Refusals: level_not_found, not_a_level, no_building, not_a_storey. Answering unchanged: true when the level is already the named ground floor, at that seat, at index 0.
levelId必填Verify scene
Optional whole-scene evidence: per-level content, roles (storey, roof-only, support) and the spaces its walls enclose, then every problem found, each with a type: empty levels, walls with no room or door, a space the walls enclose with no room over it (space_no_room) or with several and no wall between them (space_many_rooms), a room the walls do not close (room_not_enclosed) or with no name (room_unnamed), rooms with no floor or ceiling, storeys with no stair, roof levels misused, walls intersecting a covering slab or ending coplanar with its walking surface (wall_covering_slab_contact, with wallId and slabId), openings off their wall, stairs off their slab or blocked, furniture blocking a door or overlapping, a house past its lot line or in its required yards, every node field its schema rejects (schema_invalid, with its nodeId and path; valid is then false, and the level holding the node lists it as unread and is measured once it is fixed), a node kind no schema here knows, once per kind (schema_unknown_kind, info: a plugin kind), a hidden site (site_hidden). Static authored ceiling objects report transformed bounds extending above their ceiling attachment and bounds overlapping solid covering slab bands, with node IDs and measured metres; stored and derived slab holes are subtracted. Wall-mounted objects report a front oriented toward their host; static authored wall bounds report wall-body overlap and extension through the opposite face. With settled editor meshes, catalog wall bounds and large competing coplanar faces against the host or another item on the same wall are also measured within 1 mm. Hidden back-to-wall contact is not competing face evidence. These are observations, not instructions to change the scene or proof of exact mesh intersection. Bounds are measured in the owning building frame, including stacked level elevations. Unknown catalog raw bounds without meshes, animated models, unsupported attachment frames, unresolved scripted wall cuts, roo
无需输入参数。
Set a checkpoint
A named moment in your work (a roof, a floor, a batch of walls) that verify_scene({ since: name }) can compare against: it lists what was created, changed and deleted since, grouped by level and kind with a view each, and what you made that is gone. "start", the beginning of your work, is always one; a name used again replaces the first; a session keeps at most 8. A checkpoint is kept with your session, not in the project: it changes nothing in the scene, enters no undo, and does not restore anything. Refused: too_many_checkpoints (naming them), scene_too_large, name_required.
name必填Write the design brief
The design brief of the request, written once for the whole request (piece by piece when the request invites it): the request read axis by axis (action, size, pieces, openings, style, materials, source, dressing), each axis bounded by the person's own words or open with a design statement, a vision, and where the objects come from. It is recorded as the design record of the turn and answers with what it unlocks. It changes nothing in the scene. Furnishings are placed or made after a brief: place_items, furnish_room, place_in_room (the catalog's) and add_object, place_design (the agent's own), also inside run_batch. Before one, search_assets and view_assets read the catalog and every other tool works as usual; rooms, walls, openings and finishes are not furnishings. Bounded and open, in four readings. "a 4 by 5 m bedroom with a double bed, two nightstands, a wardrobe, one window, one door": action, size, pieces (as a minimum: those pieces must be there, more may come) and openings bounded; style, materials, source and dressing open. "add a lamp next to the sofa": action and dressing bounded by "add a lamp" (one object in a room that exists); style open, its design statement saying how this lamp is designed. "a bedroom with only a bed and a lamp": pieces exact and dressing bounded by "only a bed and a lamp"; style and materials open, the bed and the lamp designed, not defaulted. "Build a house": the action bounded only by "a house"; every other axis open, the dressing included. source open: the pieces are made (add_object, place_design), view_assets shows the catalog's pieces for reference, and furnish_room, which places a whole stock set, stays closed. asIs keeps technical equipment only (sanitaryware, kitchen and laundry appliances, heating and similar services): each piece is named with a reason and was shown by view_assets earlier in the same turn (chat) or session (MCP); furniture is made, not kept as it is. source catalog, brand or existing: place_items, furnish
asIsaxesbrandbeyond必填source必填vision必填sourceQuoteAdd wall
Add a single wall between two points on a level, straight or, with curveOffset, an arc. Refused with a code: a level that is not a storey (a declared roof level), and a wall shorter than 1 cm. On a level below grade, a wall against the ground (on the outline of the walls of the level) is a foundation wall, built of what the building's region says: 8 in CMU with 2x4 pressure-treated furring laid flat inside (0.241 m) in the United States and where the scene does not say where the building stands, 25 cm cast concrete insulated and waterproofed outside (0.354 m) in Europe; the result names the region it read; a partition inside the outline is an ordinary wall; the result says which.
end必填levelstart必填heightlevelIdthicknesscurveOffsetAdd fence
Add a fence along points on a level: one fence per side, a whole run or a lot's boundary (closed) in one call. Privacy (solid panels) by default; picket for a picket fence, slat for vertical slats, rail for open rails, horizontal for cladding boards, guard for a deck's barrier. Fences stand on the level, as the editor's fence tool puts them. Refused with a code: a side shorter than 10 cm (fence_too_short), a roof level (roof_level).
levelstyleclosedheightpoints必填levelIdbaseStylematerialPresetAdd corner window
A window that wraps the corner where two walls meet: one window on each wall, both running to the corner and joined, the glass fused at the corner (post none, a fixed window's default) or meeting at a thin post (post post). Any angle the walls make, a bay's 135° as well as a square or an acute corner. The corner is the point the two walls end at ([x, z], as get_walls gives their ends); width is how far the glass runs along each wall from the corner, the same on both unless widths names a wall. Each side is placed by add_window's rules (height, sillHeight, windowType, style the same on both sides; with no sillHeight, centred on the lower of the two walls). The walls are the level's (levelId, default the floor the person is viewing): stacked storeys share their corners' points. Refused with a code: no_corner where no two walls of the level end at the point, corner_ambiguous where more than two do (name two with wallIds), corner_angle for a corner nearly folded back or nearly straight, corner_not_fused for post none on a window type other than fixed, width_exceeds_wall. Returns windowIds and wallIds; the editor's window panel shows the pair under Corner.
postlevelstylewidthcorner必填heightwidthslevelIdwallIdssillHeightwindowTypeMerge windows
Make two windows that exist one window, as the editor's Merge windows does: nothing is recreated. On two walls that meet at a corner, each window within 0.30 m of that corner, they become one corner window (the add_corner_window result): each is slid to the corner keeping its width, the glass fused (post none), and both take the first window's height, sill and type, so name first the window whose look you want; the corner is refused over 170° or under 10° (walls_not_meeting, corner_angle, window_not_at_corner, height_exceeds_wall). On one wall, two windows with at most 0.30 m between them and nothing between become one window spanning both outer edges, from the lower sill to the higher head, with the first window's type and style (windows_not_adjacent, opening_between). Refused with a code and a sentence that says why: window_not_found, not_a_window, same_window, window_not_on_wall, window_already_joined (unwrap it first), windows_already_joined, opening_overlap (sliding to the corner would land on another opening). Returns kind (corner or same_wall), the windows that stay (windowIds) and the one that went (removedIds). Use it for two windows already built that open a corner or one wide opening; add_corner_window builds a new pair, and verify_scene's corner_unjoined names two windows this joins.
windowIds必填Add level
Add an empty level to a building, as the editor does: above its top storey, under the building's roof level, which moves up one so the roof stays on top; or below its lowest level for a basement, which goes one storey under the lowest level and every existing level keeps its place, the ground floor included. On a scene with no building (a new or cleared scene), it starts the scene as the editor does: a site, a building and its ground level. A level that ends up below grade says in its result how a new wall on it is built (wallConstruction): a wall against the ground is a foundation wall, built of what the building's region says: 8 in CMU with 2x4 pressure-treated furring laid flat inside (0.241 m) in the United States and where the scene does not say where the building stands, 25 cm cast concrete insulated and waterproofed outside (0.354 m) in Europe; the result names the region it read, a partition is an ordinary wall. To copy a floor with its content, use duplicate_level.
nameheightpositionbuildingIdCreate stair
Create a staircase rising from a level, as the editor's stair tool builds one: straight, L (a flight, a landing as deep as the stair is wide, a flight turned 90°) or U (a flight, a landing across, a flight back beside the first). It rises to the level above and owns the floor opening it cuts in every floor it passes; when no level stands above, a blank one is made for it. toLevelId null makes a flight to no level (porch steps, a deck, a raised platform): it rises height, cuts nothing and makes no level. Refused with a code: a flight to or from a declared roof level, and a toLevelId that is not above the level it rises from. GEOMETRY (get this wrong and the stair pokes through a wall): - (x, z) is the middle of the bottom riser, where the flight starts. The first flight runs from there along the climb: at rotation 0 it covers x − width/2 .. x + width/2 and z .. z + its run. - rotation in degrees about Y: 0 climbs toward +Z, 90 → +X, 180 → −Z, 270 → −X. Point the climb into the room, away from the wall the bottom step sits against. - An L or U turns to the climber's left or right (turn). The result gives the whole footprint and the point the top step arrives at. - Keep 0.9 m clear at the foot and at the head of the flight, and the whole footprint inside one room on both levels (a hall is typical): read the room's outline first (get_zones). OPENINGS: by default the stair owns the opening over its flights and keeps it as the stair moves (openingOffset widens it). An opening of another size, centre or turn, through a slab or ceiling you name, or through one of the two only, is cut as an opening the stair owns, as given.
x必填z必填nameturnlevelstepswidthheightlayoutlengthlevelIdrotation另有 15 个Create roof
Cap a storey with a roof over its footprint (its walls' outline, else its floor plates, else its rooms), swept in the building's own axes into rectangles, one roof segment each. Without a roofType: a gable for one rectangle, hips for a few wings, flat for a large block. The roof goes on the building's roof level above the top storey (the empty level directly above when it is the only one; made, named Roof, when there is none), and stands on the storey's wall tops, so exploded and solo level views lift it off the plan. Glazed construction supports gable, straight shed and barrel. Barrel depth is the span; barrelRise is at most half the span. glazing controls frame, glass, grids and panels. Paint glazing-frame, glazing-glass or glazing-solid. Call it once the storeys and their exterior walls stand. Refused with a code: storey_above (another storey stands above: a roof caps the top one; a lower wing's roof is drawn with the Roof tool), building_required (no level named on a site of several buildings: pass a level of the one to roof), roof_exists (the storey already has a roof: edit it, or delete_node it first when the person asked for a new one), no_rooms (no rooms or closed walls on any level of the building: pass width and depth to roof a rectangle of your own).
namedepthlevelpitchwidthcenterglazinglevelIdoverhangroofTypebarrelRiseroofSystem另有 6 个Move roofs to the roof level
Move the roofs a storey holds on its own walls to the level the roof rule gives them, as a roof's panel does by hand (Move to the roof level): over the top storey, the building's roof level (made, named Roof, when there is none); under an upper storey, that storey. Each roof stands exactly where it stood, its segments, finishes and id kept: only the level holding it changes, so exploded and solo level views show the storey's plan with no roof over it. For a project built before roofs had their own level, when verify_scene reports roof_mixed_in_storey. Refused with a code: level_not_found, no_roof_on_walls (the storey holds no roof standing on its walls; a porch roof on its beam and a lower wing's roof on the storey above already sit where they belong). Returns the roofs moved (roofIds), the level they went to (roofLevelId) and the roof level made for them (createdRoofLevelId).
levelId必填Place items
Place one or more catalog items (furniture, fixtures, plants, art, lights) in one call. Each assetId is a known catalog id, available from search_assets results or existing scene item data, never guessed. Positions are level (x, z) metres. An item stands on the floor of the level, or on the host it names (targetNodeId): a wall (art, a sconce: y is the height of its bottom above the floor, required; it goes on the side of the wall the point is on), a ceiling (a pendant, a downlight: it hangs flush under it), or an item standing on the floor (a lamp on a nightstand: it rests on its top; on an object built with add_object it rests on the real surface under the point, such as a porch landing, or a ceiling item hangs from the underside above it, such as a sloped vault, and the result names it in restingOn). A room, a slab or a level as the target means its floor. Each item is placed or refused on its own (asset_not_found; outside_rooms: an indoor item on the floor outside every room of a level that has rooms — garden and outdoor items may stand outside; height_required, item_too_tall, unsupported_host, host_not_found, host_not_on_level; blocks_door: a floor item standing where a door needs space, with a spot in its room that clears every door; too_large_for_room: a floor item its room cannot hold in any turn).
items必填levellevelIdDelete node
Delete a node with everything under it, as the editor's Delete does: a wall goes with its doors and windows, a level with everything on it. The floors above a deleted level keep their index.
id必填Create room
Create a room on a level from its polygon: a wall per edge, an edge a wall already runs along reusing that wall (rooms share their boundary with their neighbour), and the room zone that names it. The floor plate and the ceiling are derived from the room — never author a slab or a ceiling for it. Declare the room's doors and windows in the same call by polygon edge (wallIndex) and t along it, no wall ids needed; each is placed with add_door's and add_window's rules, and one that cannot be is skipped and listed in skippedOpenings with its code. Returns zoneId, slabId, ceilingId, wallIds in edge order (null where no wall), doorIds, windowIds. outdoor: true draws a terrace instead: separators where no wall runs, no walls of its own and no ceiling. Where the walls already enclose a room the reconciler numbered, the call names that room instead of adding a second one; where they enclose a room with a name of its own (not a number the editor gave it), it is refused (room_named_by_person) unless rename is true, which you pass only when the person asked for the rename, so a name is never changed silently.
name必填colordoorslevelrenamelevelIdoutdoorpolygon必填windowswallHeightwallThicknessFurnish room
Place the catalog's fixed furniture set for a room type: one set per type, not matched to a style. The bed, sofa, counters or toilet go against the wall facing the door, the rest along a side wall, each set off its wall by its own depth. Name the room by zoneId (its level and outline come with it), or give its polygon and level. The door wall is the edge a door of the room stands on, else doorWallIndex, else edge 0. Nothing lands in a door's clear zone or on another item: a piece that does not fit is nudged, else skipped, and skipped says why. Items stand on the room's level. The set per room type: bedroom: double-bed (a side of 3.2 m or more) or single-bed, two bedside-table, dresser (10 m² or more), closet (13 m² or more); kitchen: kitchen (back wall of 2.6 m or more) or kitchen-counter, stove (back wall of 3.5 m or more), fridge; bathroom: toilet, bathroom-sink, bathtub (6.5 m² or more) or shower-square; living: sofa, coffee-table, livingroom-chair, tv-stand; dining: dining-table, two dining-chair (four when both sides are 3 m or more); laundry: washing-machine, drying-rack; entry and hallway: coat-rack (both sides 1.4 m or more); storage: closet. The result lists each piece placed with its size and id, and each piece skipped with its reason. view_scene with interior { zoneId } shows the room from inside, at a person's height.
levelzoneIdlevelIdpolygonroomType必填doorWallIndexPaint
Give walls, slabs, ceilings, roofs, columns, fences, doors, windows, stairs, blocks, cabinets, shelves, items and the other built parts a finish in one call, as the editor's Paint does. Give one finish: color (#rrggbb, painted with the nearest of the library's flat colours, said with how near); material, a library:<id> (find it with search_materials) or scene:<id> ref, or a native material {properties: {color, roughness, metalness}} for an exact finish, kept as a scene material (materialName names a new one) and reused when the scene holds an equal one; or erase: true, back to the surface's default. role picks the surface: a wall's face a or b, or exterior and interior (the faces turned out of its rooms or into them, else by its stored sides; a partition is interior on both; a wall whose sides are unknown, or with rooms along only part of a face, is refused: name its face, a or b), its trims aSkirting, bSkirting, aCrown, bCrown, aChairRail, bChairRail (skirting, crown or chairRail: that trim on both faces), a curtain wall's curtain-frame, curtain-glass, curtain-solid; a slab's surface, side, edge, riser, underside or foundation; a ceiling's surface; a roof's top (the covering), edge (the gable ends and the trim band), wall (the soffit and the deck edge, and the fascia and rake boards unless they have their own) or fascia (the fascia and rake boards, a fascia band); a glazed roof's glazing-frame, glazing-glass or glazing-solid; a column's shaft, base, capital or frame; a fence's posts, infill, base or rail; a door's panel, frame, glass or hardware; a window's frame or glass; a stair's treads, body or railing; a block's body; a cabinet's front, carcass, countertop, plinth, hardware or glass; another part's own slots, which a refusal names; an item's surfaces by the names its model gives them (its painted ones are in get_node's slots), which paint cannot check. Without a role: both faces of a wall, a slab's or a ceiling's surface, a roof's top, a glazed roof's frame an
rolecolorerasetargets必填materialmaterialNamePlace an item in a room
Put one floor-standing catalog item in a room where it fits, without working out a position. Wall/ceiling-attached assets need a host: place_items accepts targetNodeId and, for a wall, y for the bottom height. A wall-bound floor piece (fridge, counter, stove, sink, TV stand, dresser, wardrobe, sofa, bed, bedside table, toilet, bath, shower, bookcase, cabinet) stands against a wall, centred in the widest free stretch of that wall (clear of every door and every other item), its front toward the room; it is never put in the middle, and when no wall has room the answer says how wide the widest free stretch is. A free-standing piece (dining table, rug, coffee table, plant, armchair) takes the middle of the room, or goes with what it belongs with: a coffee table and an armchair face the sofa. A chair goes around its table, one call per chair, facing the table, and is refused when the room has no table. Explicit edge, align, offset or inset instead requests a wall free run for any floor piece. Name the room by its zoneId (create_room, get_zones), or by its polygon and level. The item is a catalog id from search_assets. To furnish a whole room by its type in one call, use furnish_room.
edgealigninsetlevelfacingoffsetzoneIdassetId必填levelIdpolygonrotationDegallowDuplicate另有 1 个Get site
Read the site a building stands on, in its level coordinates: the lot and its area, with the footprint a house usually covers on it (30 to 45%); the buildable area inside the setbacks with its centre, its area, each edge's frontage and depth, and its front edge (behind the street; while no street is recorded, behind the edge facing north, which the setbacks take as the front); the street side with the lot's frontage and depth on it; north; the ground (sloped with its fall, read flat, or not read); the address, parcel and zoning when known; whether the lot is only the new-project placeholder; and where the footprint sits now with its yards.
sitebuildingPlace building
Stand a building on its site before or after its walls go up. It moves only the building node, so walls, levels and roofs keep their coordinates and move with it. The footprint (outline, the plan you are about to draw, in the coordinates you will draw it; else the walls standing) lands centred in the buildable area, or at the yards a site plan or the person gives. A building with walls keeps its rotation unless rotationDeg is given (get_site's squareRotationDeg squares it to the street); one with none yet is turned square to the street. Fences, paths and plants on its levels move with it.
yardsoutlinebuildingrotationDegSearch assets
Search the item library (furniture, fixtures, lights, plants, outdoor) by keyword, with one or several queries in a call. The catalog is a limited set that varies by server: what a search returns is what exists. Results provide valid asset ids and placement facts when these are not already known. A query matches the items whose name, id, category or tags hold every one of its words. Returns one group per query, each item with its id, name, category, dimensions [width, height, depth] in metres and attachTo (null on the floor, else 'wall', 'wall-side' or 'ceiling'). Related lookups (sofa, coffee table, tv stand) can share a call.
queries必填View catalog items
Pictures of catalog items by id, each with its size and the names of its paintable surfaces (paint takes one as role).
ids必填Search materials
Search or browse the material library (the finishes paint gives), several queries in one call: find a library material's ref here rather than guessing it. The library is Pascal's materials and, in the editor, the ones it holds besides (the community's, yours, your workspace's). A query's words match the words of a material's id, name and kind, or a piece of its id (plank48, cco), building words as the library writes them (timber is wood, weatherboard is siding, render is stucco), colour words by its shade (dark, light, white, grey) and surface words (roof, wall, floor, ceiling) by what it suits; a word of one or two letters, or one as common as 'the', searches nothing. Without a query, a browse lists by name every material of its kind, or that suits its surface (flat colours suit every one), or the whole library. Returns one group per query: each material's ref (library:<id>), name, kind, the surfaces it suits and its colour, best first (a browse by name), 12 at a time for a search and 150 for a browse; the words no material answers (missing), so a finish the library lacks is said, not guessed; and on a long list how many more there are (more) and the offset that lists them (next).
queries必填Cut floor or ceiling opening
Create a persistent opening on a room or level from a polygon or rectangle. A floor cut also opens the automatic ceiling directly below; a ceiling cut can also open the floor above. Use cutsAdjacent:false for a one-surface cut. A mezzanine room cuts only its own plate. levelIds repeats the opening as a shaft on several levels.
rectzoneIddrawnOnlevelIdpolygonlevelIdscutsPrimarycutsAdjacentRemove floor opening
Remove an authored floor or ceiling opening and restore the derived surfaces it cut.
id必填Set floor and foundation
Supply slabId or slabIds; grouped plates receive the same floor-top displacement, while edge slots apply only to the first plate. A ground-contact floor has two inputs: thickness (slab, min 0.01 m, grows upward from the foundation) and foundationHeight (0 = on the ground, no foundation; > 0 = raised on a solid foundation; foundation.type "solid" alone raises it 0.3 m, "none" puts it on the ground). The floor top is derived and never floats: grade + foundationHeight + thickness; everything the floor carries (walls, openings, items, rooms, storeys above) moves with the top. Legacy floorHeight (a target top) maps to foundationHeight = top - grade - thickness, never below 0; null = on the ground. On upper plates the underside stays on the walls below: thickness (or floorHeight as a target top) changes the top; only ground-contact plates accept a foundation. Explicit room floors translate with the floor to preserve steps.
patch必填slabIdslabIdsSet room floor construction
Edit the single floor volume associated with a room, with the same patch as set_floor_foundation. On a ground-contact floor: thickness (slab on the foundation, grows upward, min 0.01 m) and foundationHeight (0 = on the ground; > 0 = raised on a solid foundation); the top is derived as grade + foundationHeight + thickness and carries everything on the floor. A drawn slab takes thickness, finishes and a numeric floorHeight (its top) only. Supply slabId when the room spans multiple construction domains; an absorbed legacy slab is edited through its derived base plate.
patch必填slabIdzoneId必填Rebase floor reference
Change or clear one or more footprint reference datums in one atomic edit, compensating supported storey offsets so existing world geometry stays in place. Supply slabIds together for a shared storey.
slabIdslabIdsreferenceFloorElevation必填Create mezzanine
Add an open-below room inside a host reference polygon, with a separate thin plate and railings on open edges. Minimum area 1 m²; elevation defaults to half the storey snapped to 0.05 m, thickness to 0.2 m. Elevation must exceed thickness and stay at least 0.3 m below the resolved footprint plane; overlapping mezzanines are refused. The host floor and walls stay intact.
polygon必填elevationthicknesshostZoneId必填Move or rotate room
Move room intent and contents. Shared walls and openings stay with neighbours; the room takes plain copies. Rotation is radians about Y, before translation, about the room centroid unless a pivot is supplied. Crossings split walls and overlaps re-derive rooms. Force can reposition obstructing openings when they fit; otherwise the edit is refused.
forcerotatezoneId必填translateDuplicate room
Copy room intent and contents with fresh IDs; shared walls are copied without openings. Rotation is radians about Y before translation. Collinear destination walls are merged, preserving their IDs and hosted children. Crossings split walls and rooms re-derive; overlap is allowed. Force can reposition obstructing openings only when they fit.
forcerotatezoneId必填translate必填Rotate room a quarter turn
Rotate a room by quarterTurns 1 or -1 about its centroid, then align its first reference vertex to gridStep (default 0.5 m). Crossings split walls and collinear overlaps merge. Force can reposition obstructing openings only when they fit.
forcezoneId必填gridStepquarterTurns必填Keep outside dimensions
Keep the building's outer size: put exterior wall faces on their fixed reference lines, moving wall bodies inward so walls thicken inward and later thickness edits preserve outer dimensions. Supply either levelId or zoneIds.
levelIdzoneIdsSet room intent
Update room name, floor finish/elevation/regions, floor.footprint ("new" mints a unique floor key tied to this creator room, an existing key joins that floor on this level, null returns to the shared floor). Touching rooms with the same key share a base plate; disconnected pieces share construction settings. Conversion preserves world geometry in one edit and refuses when infeasible. get_zones exposes floor_choices. A keyed floor uses "<creator room name> floor" while the creator remains on that key; otherwise it uses the largest named room. Existing keys such as "own" without a creator use that fallback. A user-given plate name wins; the shared floor stays "Shared floor". Keyed rooms can have raised or sunken floor.elevation, stored as a level-local walking top. Slab thickness, foundation height and edge finish use set_room_floor_construction, updating every piece of the key. Update ceiling paint regions (ceiling.regions: [x, z] polygons with a finish, later wins), step finishes (floorStepFinish for every step of the room; floorStepOverrides: [{ key, step?, finish }] per doorway, key = the door id the step sits under or the lower room id), wall material and construction opt-outs. daylight { artificialLight, mechanicalVentilation } declares a habitable room lit and aired by artificial means (the IRC R303.1 exceptions to daylight; both true), stored in the room's metadata; a bedroom, living room or kitchen needs a window to outside or this declaration, above and below grade alike. Absent fields are unchanged; null clears.
patch必填zoneId必填Divide room
Divide a room with an open path (endpoints snap to its boundary; the seed side keeps its id) or a closed island (outer room keeps its id). The two rooms are parted by a separator (the editor's Separator: a room boundary with no wall), not a wall. Supply path or the legacy two-point cut. Islands need 0.25 m² and 5 cm wall clearance.
cutpathclosedzoneId必填endBoundaryIdstartBoundaryIdMerge rooms
Merge two rooms by removing the separators they share (the editor's Separator: a room boundary with no wall). Walls are preserved; wall-only boundaries return a conflict.
zoneIds必填Delete room
Delete a room. A room Divide made, which shares a separator (the editor's Separator: a room boundary with no wall) with a room on its outline, merges back into that room: the separators go, walls and items stay (mode "merge"). A room whose every boundary is a wall shared with other rooms is refused with a "shared-walls" conflict and nothing changes (mode "blocked"); delete one of its walls instead. Otherwise the room goes with its unshared walls, separators and their openings (mode "delete"), and contents chooses whether its items are kept or deleted. Returns the disposition payload.
zoneId必填contents必填Run a batch of scene tools
Optionally run several scene tools in one call: in order, each on the scene the calls before it left, applied as one undo step, with a report per call. Supports repeated or known-in-advance work; individual calls remain available. A call cannot use an id another call of the same batch creates; created ids are available in the report for subsequent calls. onRefusal stop (default): a refused call stops the batch and nothing is applied; skip: the others are applied and each refusal is reported; add_object calls are independent of each other under both: one that fails is reported with its own error and the others are applied, each with the receipt a single add_object gives. Tools: paint, search_materials, list_levels, get_node, get_level_summary, get_walls, get_zones, duplicate_level, verify_scene, delete_node, measure_stair, fit_stair, find_by_type, create_roof, add_wall, add_fence, add_level, create_stair, add_corner_window, merge_windows, add_column, add_object, place_design, place_in_room.
calls必填onRefusalList collections
List the scene's collections with their elements (id, name, type, level), and the templates a collection can start from.
collectionIdEdit collection
Create, rename, recolour or delete a collection, or add and remove its elements. A collection is a named set of any scene elements (lights, windows, doors, columns, objects built with add_object…), listed in the editor's Collections; being in one changes nothing about the elements. Without collectionId the call works on the scene's collection with that template, or else that name, and creates it when there is none.
addnamecolordeleteremovetemplatecollectionIdAdd column
Add a structural or decorative column at (x, z), or rebuild one by nodeId. Supports native fields or optional code using the same module and conventions as add_object, with floor mount and its bottom centre at the support point. Params named height, width and depth drive the native size controls. Only add columns when requested.
xyzcodenametagsdepthlevelstylewidthheightnodeId另有 7 个Build object
Author parametric Three.js furniture, decor and custom objects of any shape, dimensions or style, whether or not the catalog holds something similar (the catalog is a limited set that varies by server). Examples include a low oak table, a slatted bench, a paper lantern, built-ins, custom columns and capitals, mouldings and trim, panels, exposed beams, ceiling bodies, canopies, a porch and railings. Pascal runs the module in a sandbox, stores the result and places it as one object the user can move, paint, and ask you to edit again. Module shape (import THREE from the three package as usual; the addons below too): // also available: three/addons/utils/BufferGeometryUtils.js, three/addons/geometries/{RoundedBoxGeometry,ConvexGeometry,LoftGeometry,ParametricGeometry}.js, three-bvh-csg (Brush, Evaluator, SUBTRACTION, ADDITION, INTERSECTION) export const params = { width: { default: 4.8, min: 3, max: 8, step: 0.1, unit: 'm', label: 'Width' } } export const mount = 'floor' // 'floor' | 'wall-side' (on a wall face) | 'wall' (through a wall, like a window) | 'ceiling' export default function build({ params, THREE }) { const group = new THREE.Group(); /* … */ return group } One object is one feature that changes together: a table, a bench, a porch, a railing run, a fireplace surround, a ceiling with its beams. Never a whole house, and never walls, rooms, floors, roofs, stairs, doors or windows: those have their own tools. A new object's reason records its design intent: what the authored shape, dimensions or style contributes to the request. The scene check lists every authored object with its reason; no catalog-exhaustion proof is required. On a floor, a plain box with a wall's size or a floor plate is refused with the tool to use (use_walls, use_slab); a detailed object with a wall's size (a bookcase, a screen), or one named after something Pascal builds, is built with a hint naming the tool. Conventions (they make the object work in Pascal; follow them): - Me
codenamesidetagsnodeIdparamsreasoncategorylanguageparentIdpositionrotation另有 1 个Author scene
Turn a whole design you wrote as free three.js into an editable Pascal scene, in one call. You read your own module however you like (its source, running it and reading the objects, both) and hand over a conversion payload: levels, walls with their openings, rooms, slabs, columns, railings, every piece of furniture as an authored object with its own module, and lights. Pascal does the rest server-side: compiles and stores each item, places it, derives the rooms and their floors, paints, runs its checks, saves, and answers with a gate report you iterate against. Nothing you hand over is silently dropped: what cannot be placed comes back by name with a reason, and what Pascal corrected (a wall end snapped onto the centerline it meets) is listed. Coordinates: metres, plan x/z, Y up, each level's floor at y = 0 in its own frame. A wall is its centerline; walls meet where centerlines meet, so end a partition on the centerline of the wall it runs into. An opening's 'along' is measured from the wall's start to the opening's centre; give each opening its type (how it opens) and style (its look), or its own module for a shape they cannot express. An item's position is where its bottom centre stands; its module follows the add_object contract (metres, Y up, built in its installed orientation; at most 300k triangles and 32 materials per item; name materials slot_<finish>; drawers, doors and lids as animation clips; a THREE light named light:<id> where a bulb is). A hex colour is written as an exact material, one per distinct colour. Pascal builds a wall's cap, the floor plate and the ceiling itself: fold a module's caps, underlays and floor planks into the wall, the room's floor finish and the room (say so in notes), never into slabs or regions: baseboards are the wall's skirting, a plank or tile floor is the room's floorCode, tiles, panelling or boards on a wall are its faceLeft / faceRight (or the room's wallCode); a slab is a terrace, a platform, a balcony. Build the build
moduleadapterpayload必填replacesceneIdbuildingIdRead object script
The module (three.js or Blender bpy, named by language) an object (or a window, door or column built from code) runs, with its params and their current values; a room's id reads its floor script, the module that builds its floor finish; a wall's id with face reads that face's script (face may be left out when only one face has one). Optional source evidence when the current module is needed. An edited module can be passed back with the same nodeId: to add_object for an object, to add_window / add_door / add_column for their respective kinds.
facenodeId必填Measure
Measure the distance (in meters) between two nodes, or the net area of a polygon node when fromId === toId. Distance is between world-space reference points, returned as fromPoint/toPoint: a positioned node's origin in its host's frame (an item's base, a door's or window's centre in its wall), a wall's or fence's midpoint at its base, a slab's, ceiling's or zone's polygon centroid on its plane, a block's or imported mesh's vertex-bounds centre, a level's plan centre on its base plane, and another container's descendants' centre. `approximate` lists nodes whose renderer derives the pose from data not modelled here (a downspout at its gutter outlet, a gutter at the eave), with the reason.
toId必填fromId必填Look at the scene
Look at the building in 3D from a viewpoint you pick and get the picture back: the finished house, every storey and the roof by default, or an explicit Solo/Exploded level presentation, whatever view mode the person has on. Use it to compare what you built with a reference and say what differs before you fix it: the facade from the photo's own camera (camera: its position, aim, field of view and aspect), rendered at the photo's aspect to lay beside it; or from the photo's side at street height (from 'street', 'street-left', …, eyeHeight 1.7), in its light (lighting); one face square on (projection orthographic); the massing from above, or an aerial view (elevation 40). The view frames the target (a building, a level, a wall or a zone; the whole building, its roof included, by default) from outside, unless you place the eye yourself with position or camera. To stand inside a room and see its furniture and finishes at a person's height, give interior {zoneId} (a room: an id from get_zones or create_room): the eye stands in the room a step in from a corner, looking across it, with the cut below; from picks the side of the room it stands on, target something in the room to look at it. To see inside a floor, give interior {levelId}: the other floors and that floor's roofs and ceilings are left out of the picture, and everything on it, walls, openings and furniture alike, is cut at 0.65 of the storey's height (about two thirds), so a tall wardrobe or a door head is cut, not short; a roof level has no inside; with no eye given it looks down into the floor, or into the room or zone you target. A level below grade, targeted alone, is looked into the same way (from outside the ground would cover it), the ground over it drawn as a faint veil. The live view is not changed. A door, a window or an item on a floor frames at detail scale, an opening seen from its outside face: a close-up to lay beside the photo's crop of the same element, to see what differs. Over the MCP the user'
fovfrommaxPxphotocameratargetinteriorlightingpositionelevationeyeHeightprojection另有 1 个Create story shell
Create one level-owned building shell from a footprint: the perimeter walls. The floor plate and the ceiling are DERIVED from the rooms the walls enclose — never author a slab or a ceiling here, and never pass boundary/autoFromWalls; createSlab / createCeiling / slabElevation are recorded as room intent instead. Use once per story; do not make first-floor walls span multiple stories.
levelId必填footprint必填createSlabnamePrefixwallHeightceilingHeightcreateCeilingslabElevationwallThicknessslabMaterialPresetwallMaterialPresetceilingMaterialPresetAdd door
Add a door to an existing straight wall at t (0..1 along it), or a passage with no leaf (openingKind opening: a cased opening, an arch). The door slides to stay on the wall and reports clamped. Refused with a code, as in the editor: curved walls, walls shorter than the door, and overlapping another door, window or wall item unless force is set. Match the reference with the outline (rectangle, rounded, arch), doorType and style; what they cannot express (glass strips, a pattern of lites, carved panels) is written as a script in code, never left as not possible.
tcodenametagsforcestylewidthheightnodeIdparamswallIdcategory另有 11 个Add window
Add a window to an existing straight wall at t (0..1 along it), centred vertically on the wall, or on sillHeight above the floor when given. It slides to stay on the wall and under the wall's ceiling, and reports clamped. Refused with a code, as in the editor: curved walls, walls shorter than the window, overlapping another door, window or wall item unless force is set, and a style on a window that is not Fixed (style_needs_fixed_window). Match the reference with the outline (rectangle, rounded, arch), windowType and panes (columns × rows, or a style); what they cannot express (glass strips, leaded lites, a feature frame) is written as a script in code, never left as not possible.
tcodenamerowstagsforcestylewidthheightnodeIdparamswallId另有 10 个Apply patch
Apply a batch of create/update/delete operations atomically. All patches are validated before any are applied; the entire batch forms a single undo step. Batch-first is the default: prefer one apply_patch call containing all create/update/delete ops for a build step, in stable order so later ops can reference ids created by earlier ops. A single call is atomic (all or nothing) and pays the snapshot and save cost once; do not loop one-op calls. A create whose id already exists fails the whole patch with node_exists; to replace a node, delete it earlier in the same patch. An update cannot change id or type (identity_change) or object or children (immutable_field); restating the current value is fine. A parentId change must name an existing node that holds children (invalid_parent). An update cannot add schema issues to a node (invalid_update). After a delete or a roof update that regenerates a roof's default gutters, those gutters and their downspouts are addressable only in a later call (regenerated_default). A roof created or moved onto the storey whose walls carry it goes to the level above them (the roof level over a top storey), said in notes; storey content (walls, zones, slabs, ceilings, items, stairs) on a roof level (roof_level), a walled level declared the roof level (roof_level_holds_storey) and floor indexes putting a roof level under a storey (roof_level_on_top) are refused. Refusals come back as a tool error whose text is JSON {code, patchIndex, id, message}.
patches必填Clear the project
Empty the project on purpose, back to the default scaffold: a site, a building and one level of the standard storey height. It is the only way to empty a project: a write that would empty it is refused (scene_wipe_blocked), since that is far more often an accident. Call it only when the person asked to start over, and say what they asked in reason.
reason必填Create unit
Create a named unit in a building, optionally referencing zones across its levels.
kindname必填colorbuildingId必填memberZoneIdsSet unit members
Replace the zones referenced by a unit. Every zone must belong to a level in the same building.
unitId必填memberZoneIds必填List units
List units with their member zones and current area reports, optionally filtered by building.
buildingIdSet zone
Create a polygonal zone on the given level. label is stored as the zone name and properties are merged into metadata. A polygon along walls that already enclose a room is that room, never a second zone: a room still named "Room N", or already named label, takes the label and properties; a room a person named otherwise is refused (rename it with update_node only when the person asked).
label必填levelId必填polygon必填propertiesUndo
Undo the most recent N steps in the scene history (default 1). Returns the number of steps actually undone.
stepsRedo
Redo the next N previously-undone steps (default 1). Returns the number of steps actually redone.
stepsExport JSON
Return the scene as a serialized JSON string. Pass `pretty: true` to indent with 2 spaces.
prettyExport GLB
GLB export is not available in headless mode — it requires the Three.js renderer, which is browser-only. Returns a structured `not_implemented` tool error.
无需输入参数。
Check collisions
Assess declared item footprints with a rotation-aware plan AABB test. Supports an explicit minimum clearance and reports units, source dimensions, skipped evidence, and unsupported checks. Optionally scope to one level or floor-standing items.
levelIdcandidatefloorOnlyminimumClearanceList scene templates
List the seed Pascal scene templates available to `create_from_template`. Returns the id, display name, one-line description and node count for each.
无需输入参数。
Create scene from template
Instantiate a seed Pascal scene template into the bridge. Regenerates all ids before applying. When `save: true` and a SceneStore is wired, also persists the new scene and returns the SceneMeta.
id必填namesaveprojectIdCreate house from brief
High-level hosted workflow for external agents: choose a starter house from a brief, create/save/publish it, and return the editor URL. Use semantic tools afterward for exact customization.
brief必填roomsstyleprojectIdconstraintslandscapingprojectNamebedroomCountCreate project
Create a browser-visible Pascal project for the authenticated user. Use this before save_scene when the user asks for a new project.
idname必填isPrivateGet project status
Authoritative status/debug call for a Pascal project: editor URL, browser-visible version, latest saved version, published version, node count, and graph hash.
id必填Save scene
Save the current scene (or a provided graph) to the SceneStore. Without id or projectId it saves to the project this session is bound to (create_project or load_scene). Defaults to a browser-visible draft save so agents can iterate without creating many project versions. Use saveMode: "checkpoint" for meaningful version history.
idname必填graphpublishreplacesaveModeprojectIdthumbnailexpectedVersionincludeCurrentSceneLoad scene
Load a scene from the SceneStore into the bridge. Returns the scene metadata. Throws `scene_not_found` if the id does not exist.
id必填List scenes
List scenes in the SceneStore. Optionally filter by `projectId` and cap results with `limit` (default 100).
limitprojectIdDelete scene
Remove a stored scene by id. In Pascal this never deletes the project: it hides it from Pascal's public listings until it is next saved with content, and answers `deleted: false, hidden: true` with a message; its owner can delete it from the projects page. Only someone who can manage the project may hide it. A local scene store deletes the scene. Optionally pass `expectedVersion` for optimistic concurrency.
id必填expectedVersionRename scene
Rename a scene in the SceneStore. Returns the updated SceneMeta. Optionally pass `expectedVersion` for optimistic concurrency.
id必填newName必填expectedVersionGenerate variants
Generate N variations of a base scene by forking and applying seeded mutations. Example: "give me 5 variations of this kitchen". If `save=true`, each variant is persisted via scene operations and returned with an id + URL; otherwise the graph is returned inline.
saveseedvarycountbaseSceneIdPhoto to Pascal scene
Orchestrator: analyse a floor-plan photo via MCP sampling, translate the structured vision result into a Pascal SceneGraph (site → building → level with walls and zones), optionally save it, and swap the bridge to the new scene. Requires host support for sampling.
namesaveimage必填scaleHintdefaultWallHeightdefaultWallThicknessAnalyze floor-plan image
Defer to the MCP host (via sampling) to extract walls, rooms, and approximate dimensions from a floor-plan image. Requires host support for sampling.
image必填scaleHintAnalyze room photo
Defer to the MCP host (via sampling) to extract approximate dimensions, fixtures, and windows from a single-room photograph. Requires host support for sampling.
image必填已满足适用检查项的 100%
该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

由 GitHub 账号 sadri-dridi 发布
一个远程 MCP 服务器,提供小型实用工具:字符串、时间、URL、JSON 与路径检查,以及少量查询,多数只返回计数或结构并丢弃输入值。

由 GitHub 账号 sadri-dridi 发布
一个远程 MCP 服务器,提供小型实用工具:词元计数、时间查询、URL 与 JSON 检查,以及把智能体导向第三方网关的推广索引工具。

由 GitHub 账号 sadri-dridi 发布
远程 MCP 端点,提供轻量、基本无状态的实用检查(时间、URL/JSON 校验、HTTP 状态、简单查询)以及若干推广类索引工具。

由 GitHub 账号 sadri-dridi 发布
一个远程 MCP 服务器,提供时间、URL 与主机名解析、HTTP 状态检查、简单校验和少量索引查询等小型实用工具。

由 GitHub 账号 pascalorg 发布
让助手通过 Pascal 托管编辑器创建、检查、校验并保存可编辑的 3D 建筑场景。
npx @pascal-app/cli editorpascal mcp setup codexbun add @pascal-app/mcpbunx @pascal-app/mcp# ornpm exec --package=@pascal-app/mcp -- pascal-mcpbunx @pascal-app/mcp --stdio --scene ./my-scene.jsonbunx @pascal-app/mcp --http --port 8787PASCAL_MCP_HTTP_TOKEN="$(openssl rand -hex 32)" \ bunx @pascal-app/mcp --http --host 0.0.0.0 --port 8787 --cors-origin https://editor.example~/.pascal/data/pascal.db# Terminal 1: run the editorPASCAL_DATA_DIR="$HOME/.pascal/data" bun run dev
# Terminal 2 or an MCP host: run the serverPASCAL_DATA_DIR="$HOME/.pascal/data" bun packages/mcp/dist/bin/pascal-mcp.js{ "mcpServers": { "pascal": { "command": "pascal", "args": ["mcp", "connect"] } }}pascal mcp setup claude{ "mcpServers": { "pascal": { "command": "pascal", "args": ["mcp", "connect"] } }}{ "mcpServers": { "pascal": { "command": "node", "args": ["/absolute/path/to/editor/packages/mcp/dist/bin/pascal-mcp.js"], "env": { "PASCAL_DATA_DIR": "/Users/you/.pascal/data" } } }}pascal mcp setup codexbun run --cwd packages/mcp buildcodex mcp add pascal-dev \ --env PASCAL_DATA_DIR="$HOME/.pascal/data" \ -- node "$PWD/packages/mcp/dist/bin/pascal-mcp.js"[mcp_servers.pascal-dev]command = "node"args = ["/absolute/path/to/editor/packages/mcp/dist/bin/pascal-mcp.js"]
[mcp_servers.pascal-dev.env]PASCAL_DATA_DIR = "/Users/you/.pascal/data"{ "mcp.servers": { "pascal": { "command": "pascal", "args": ["mcp", "connect"] } }}import { createPascalMcpServer, SceneBridge } from '@pascal-app/mcp'import { Client, InMemoryTransport } from '@modelcontextprotocol/client'
const bridge = new SceneBridge()// Or over a detached scene a host opened (`@pascal-app/core/runtime`): every tool then reads and// writes that scene, with its ids, and the host turns it into a patch.// const bridge = new SceneBridge({ runtime: openDetachedScene(snapshot, options) })bridge.loadDefault()const server = createPascalMcpServer({ bridge })
const [srvT, cliT] = InMemoryTransport.createLinkedPair()const client = new Client({ name: 'my-agent', version: '0.1.0' })await Promise.all([server.connect(srvT), client.connect(cliT)])
const tools = await client.listTools()console.log('available tools:', tools.tools.map((t) => t.name))
const scene = await client.callTool({ name: 'get_scene', arguments: {} })console.log(scene)import { createSceneOperations } from '@pascal-app/mcp/operations'import { registerOperationTool } from '@pascal-app/mcp/tools/shared-tools'import { signageAgentTools } from 'acme-signage/agent-tools'import { signageAgentOperations } from 'acme-signage/agent-operations'
const operations = createSceneOperations({ bridge, // The floor the person is viewing: a tool call that names no level reads it. // Leave it out on a host with no view, and the lowest storey is read. activeLevelId: () => myHost.viewedLevelId(),})
for (const contract of signageAgentTools.tools) { if (contract.runsIn !== 'operation') continue registerOperationTool(server, operations, { contract, operation: signageAgentOperations[contract.name], annotations: { readOnlyHint: false, destructiveHint: false }, })}[x, z] → (x, y, z) // the 2nd component is world Z (depth), not "up"{ "op": "create", "parentId": "<levelId>", "node": { "type": "slab", "elevation": 0.0, "polygon": [[0, 0], [5.196, 3.0], [3.196, 6.464], [-2.0, 3.464]] }}{ "wallHeight": "9 ft", "overhang": "18 in", "pitch": "6:12" }// find_nodes { zoneId } → find_by_type, with or without a type{ "name": "find_by_type", "arguments": { "type": "window", "zoneId": "zone_kitchen" } }{ "name": "find_by_type", "arguments": { "sourceIdPrefix": "ground/exterior-01" } }// describe_node → get_node: resolvedHeight, resolvedThickness, ancestorIds, displayName…{ "name": "get_node", "arguments": { "id": "wall_host" } }// validate_scene → verify_scene: schema_invalid issues by nodeId and path, room findings{ "name": "verify_scene", "arguments": {} }// The lot before the house: frontage, depth, each buildable edge as a front, the ground{ "name": "get_site", "arguments": {} }// An L stair with a glass railing, and porch steps to no level{ "name": "create_stair", "arguments": { "x": 2, "z": 1, "layout": "l", "turn": "left", "lowerSteps": 6, "railingStyle": "glass" } }{ "name": "create_stair", "arguments": { "x": 0, "z": -4, "toLevelId": null, "steps": 3, "height": "0.5 m" } }// A glazed barrel roof over a 6 × 4 m rectangle{ "name": "create_roof", "arguments": { "roofType": "barrel", "roofSystem": "glazed", "width": 6, "depth": 4, "barrelRise": 1.4, "barrelSegments": 12 } }// Gable ends reaching 0.6 m past their walls, apart from the eaves{ "name": "apply_patch", "arguments": { "patches": [{ "op": "update", "id": "rseg_main", "data": { "gableOverhang": 0.6 } }] } }// Find a finish, then paint every exterior wall face with it{ "name": "search_materials", "arguments": { "queries": [{ "query": "white render", "surface": "wall" }] } }{ "name": "paint", "arguments": { "targets": ["wall_a", "wall_b"], "role": "exterior", "material": "library:<id>" } }// The house as a street photo shows it, at dusk, small{ "name": "view_scene", "arguments": { "from": "street-left", "lighting": "dusk", "maxPx": 960 } }bun installbun run --cwd packages/mcp buildbun testbun run --cwd packages/mcp smoke