Pascal 3D Editor について
Pascal 3D EditorのMCPサーバーは、互換性のあるAIホストから編集可能な建築シーングラフを操作できます。ヘッドレス実行やローカル保存に対応し、エディターと共有すると変更がリアルタイムに反映されます。
主な機能
- 01建築シーンの作成と変更
- 02シーン操作の検証
- 03取り消し可能な変更履歴
- 04ローカルSQLiteシーン保存
- 05エディターへのリアルタイム反映
- 06stdioとループバックHTTPに対応
活用シーン
- 01AIホストで建築レイアウトを下書き
- 02壁、ドア、家具の追加
- 03保存済みシーンをエディターと編集
- 04カスタムホストでシーンツールを実行
MCP 対応
部屋の作成、アイテム配置、取り消しなどのシーン操作を、MCPツール、リソース、プロンプトとして提供します。MCPクライアントはstdioまたはループバックHTTPで接続でき、ローカルストレージを介して実行中のエディターとシーンを共有できます。
設定
リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。
https://editor.pascal.app/api/mcpclaude mcp add --transport http app-pascal-editor https://editor.pascal.app/api/mcp{"mcpServers":{"app-pascal-editor":{"type":"http","url":"https://editor.pascal.app/api/mcp"}}}Cursor で開く{"servers":{"app-pascal-editor":{"type":"http","url":"https://editor.pascal.app/api/mcp"}}}VS Code で開く{"mcpServers":{"app-pascal-editor":{"type":"http","url":"https://editor.pascal.app/api/mcp"}}}{"mcpServers":{"app-pascal-editor":{"serverUrl":"https://editor.pascal.app/api/mcp"}}}コマンドはターミナルで実行し、JSON は各クライアントの MCP 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。
ツール
詳細
@pascal-app/mcp
Pascal 3D エディター用の Model Context Protocol サーバーです。MCP 対応の AI ホストから
@pascal-app/core のシーングラフを操作します。
ホスト型 Pascal MCP エンドポイントと、Claude Code、Codex、 Cursor、OpenClaw 向けのすぐに使えるセットアップ方法については、AI エージェントを接続するをご覧ください。ホスト型エンドポイントでは Pascal アカウント内のプロジェクトを編集します。このパッケージは、カスタムホストとローカルのシーンストレージ向けの オープンソースのローカルサーバーです。
このサーバーは、ブラウザー、WebGPU、React、外部データベースサービスなしで、Node.js 22.13 以降または Bun 上でヘッドレス実行できます。エディター UI で使用されているシーンの変更操作(壁の作成、アイテムの配置、開口部の切り抜き、取り消しなど)を、MCP ツール、リソース、プロンプトとして公開します。
推奨されるローカルセットアップ
プロジェクトを自動的に共有するローカルエディターと MCP を利用するには、Pascal CLI をインストールします。
npx @pascal-app/cli editor
pascal mcp setup codex
pascal editor を実行すると、エディターと認証済み MCP サービスが同時に起動します。
pascal mcp connect は、動的なループバックポートを検出する安定した stdio コネクターです。そのため、MCP クライアントの設定に変動するポートもシークレットも含める必要がありません。
MCP サーバーを組み込む場合、カスタムストアを指定する場合、または Pascal エディターを使わずに MCP を実行する場合は、このパッケージを直接使用してください。
パッケージを直接インストールする
bun add @pascal-app/mcp
@pascal-app/core はピア依存関係です。ローカルストアは、Bun 上では Bun SQLite を、Node.js 上では Node.js 組み込みの SQLite ドライバーを使用します。
クイックスタート
stdio 経由でサーバーを 1 行で起動します。
bunx @pascal-app/mcp
# or
npm exec --package=@pascal-app/mcp -- pascal-mcp
ディスクから初期シーンを読み込みます。
bunx @pascal-app/mcp --stdio --scene ./my-scene.json
ループバック HTTP 経由で公開します。
bunx @pascal-app/mcp --http --port 8787
ループバック以外のホストにバインドするには、ベアラートークンが必要です。
PASCAL_MCP_HTTP_TOKEN="$(openssl rand -hex 32)" \
bunx @pascal-app/mcp --http --host 0.0.0.0 --port 8787 --cors-origin https://editor.example
ローカルシーンストレージ
MCP 経由で保存されたシーンは、ローカルの SQLite データベースに保存されます。
~/.pascal/data/pascal.db
MCP サーバーと実行中のエディターで別のディレクトリを共有する場合は PASCAL_DATA_DIR を、正確なデータベースファイルのパスを指定する必要がある場合は PASCAL_DB_PATH を設定します。ストアは WAL モードとトランザクションによるバージョンチェックを使用するため、別々のローカルプロセスから同じシーンデータベースを保存したり開いたりできます。
ワークスペースの開発中は、両方を同じデータディレクトリで実行してください。
# Terminal 1: run the editor
PASCAL_DATA_DIR="$HOME/.pascal/data" bun run dev
# Terminal 2 or an MCP host: run the server
PASCAL_DATA_DIR="$HOME/.pascal/data" bun packages/mcp/dist/bin/pascal-mcp.js
ローカルのジオメトリアーティファクト
スクリプトで作成されたオブジェクトの GLB とソースは、ローカルの SQLite シーンデータベースの隣にある <database-path>.artifacts/<sha256> に保存されます。保存されたシーンはここに格納されます(--scene を指定した場合も同様ですが、これは最初のシーンを初期設定するだけです)。このディレクトリはデータベースと一緒に保持してください。ファイルはハッシュと照合して検証され、一度だけ書き込まれるため、保存済みシーンと取り消し履歴では元のジオメトリが維持されます。スタンドアロンエディターも、同じデータベース側のストアを読み書きします。
ローカル MCP のコンパイルは、PASCAL_SERVER_SCRIPT_COMPILE=1 を設定した場合にのみ有効になります。コンパイルは、環境変数を継承せず、期限付きで別プロセス内で実行されます。信頼できないコード向けのサンドボックスではありません。Blender (bpy) モジュールは PASCAL_BLENDER が指定する Blender バイナリ(blender -b)で実行されます。同じ注意事項が適用されます。Blender ジオメトリスクリプトでその方法を説明しています。コンパイルを有効にしなくても、get_source で保存済みスクリプトを読み取れます。
エディターへのリアルタイム更新
エディターと MCP サーバーが同じ PASCAL_DATA_DIR を共有している場合、読み込み済みの保存シーンに対する MCP の変更は SQLite に永続化され、ローカルの scene_events ストリームに記録されます。エディターページは、サーバー送信イベントを使って /api/scenes/:id/events を購読するため、開いているブラウザータブはエージェントがシーンを編集する際に、シーングラフのスナップショットを適用できます。
このフローは、意図的にローカルで軽量に設計されています。
- エディターでシーンを開くか作成し、ローカルデータベースに保存します。
- MCP で
load_sceneを使ってそのシーンを読み込みます。 create_room、add_door、furnish_room、add_wall、place_items、set_zoneなどの MCP 変更ツールを実行します。
各変更では、書き込み前に保存済みシーンのバージョンが確認されます。ブラウザーまたは別の MCP プロセスが先に新しいバージョンを保存していた場合、MCP ツールは
live_sync_version_conflict を返します。続行する前に、load_scene でシーンを再読み込みしてください。
マネージド CLI クライアントの設定
Claude Desktop、Cursor、および互換クライアントに推奨される JSON 設定は次のとおりです。
~/Library/Application Support/Claude/claude_desktop_config.json(macOS)または %APPDATA%\Claude\claude_desktop_config.json(Windows)を編集します。
{
"mcpServers": {
"pascal": {
"command": "pascal",
"args": ["mcp", "connect"]
}
}
}
Claude Code
CLI を使用する場合:
pascal mcp setup claude
または、リポジトリのルートにある .mcp.json に追加します。
{
"mcpServers": {
"pascal": {
"command": "pascal",
"args": ["mcp", "connect"]
}
}
}
マネージド CLI を使わずにパッケージ開発のテストを行うには、まずビルドし、ビルド済みのバイナリを Claude Code に指定します。
{
"mcpServers": {
"pascal": {
"command": "node",
"args": ["/absolute/path/to/editor/packages/mcp/dist/bin/pascal-mcp.js"],
"env": {
"PASCAL_DATA_DIR": "/Users/you/.pascal/data"
}
}
}
}
Codex CLI
CLI を使用する場合:
pascal mcp setup codex
公開前にローカルのワークスペースでテストする場合:
bun run --cwd packages/mcp build
codex mcp add pascal-dev \
--env PASCAL_DATA_DIR="$HOME/.pascal/data" \
-- node "$PWD/packages/mcp/dist/bin/pascal-mcp.js"
これにより、~/.codex/config.toml に次のようなエントリーが書き込まれます。
[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"
Cursor の設定
Cursor の設定(settings.json)で次のように指定します。
{
"mcp.servers": {
"pascal": {
"command": "pascal",
"args": ["mcp", "connect"]
}
}
}
プログラムからの使用
インメモリトランスポートを使用して、独自の Node.js または Bun プロセスにサーバーを組み込みます。次の例では、1 つのスクリプト内でクライアントとサーバーの完全なペアを実行します。エージェントフレームワークやテストに便利です。
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)
独自の operations を渡すホスト(createPascalMcpServer({ operations }))では、runInScene(run) を実装できます。すべてのツールハンドラーはその中で開始し、await の後もその中で再開されるため、ツールが生成する ID と実行を計画する操作は、シーンの同期スコープ内で処理されます。これは任意です。指定しない場合、ハンドラーは従来どおりランダムな ID を使って実行されます。デタッチされたシーンで計算する実装では、SceneBridge.runInScene に委譲する runInScene を用意してください。そうしないと、ツールの ID がシーンの ID と一致せず、再計算された効果も一致しません。
コンパイル可能なバージョンについては、examples/embed-in-agent.ts を参照してください。
プラグインツールとユーザーのフロア
プラグインの 'operation' ツールは、共通ツールと同じランナーに登録されます。ランナーは入力を解析し、1 つの履歴ステップとして結果を適用して、achieved と拒否内容を返します。注釈はホストのものであり、プラグインのコントラクトから読み取られることはありません。
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 },
})
}
コントラクトの形式、バージョン、信頼ルールについては、プラグインの作成を参照してください。
座標の規約
Pascal のシーンは右手座標系で、X と Z が地面の平面を形成し、Y が上方向です。長さの単位はメートルで、回転はラジアン単位のオイラー角タプル [x, y, z] として格納されます。
平面図 → ワールド。 渡すすべての 2D 点は、階層/建物のローカルな地面平面座標 [x, z] です。これには wall.start/wall.end や、slab、zone、ceiling の polygon/holes 配列も含まれます。デフォルトの建物トランスフォームが単位行列の場合、ワールド空間では次のように表示されます。
[x, z] → (x, y, z) // the 2nd component is world Z (depth), not "up"
格納される規約では符号の反転はありません。ツールは 2 つ目の成分をワールド Z としてそのまま扱います。垂直方向の y は、レベルシステムがレベルの高さを累積して計算した、所属レベルの積み上げ高さに、要素自体の高さを加えた値から始まります。スラブにはさらに絶対値の elevation が設定されます。
エディターの外部で座標を計算する場合の注意点。 Pascal のビューポートでは、ワールド軸に独自の回転が加わります。2D 平面図パネルでは、ユーザーのビュー回転(北向きの基準は 0°、FLOORPLAN_VIEW_ROTATION_DEG が基準値、北はワールド −Z)に応じてコンテンツが回転します。また、3D の「上面」スナップでは現在のカメラ方位が保たれるため、アイソメトリックのデフォルト位置から実行すると、軸に沿ったビューになるまでワールド軸と画面軸が約 45°ずれます。そのため、土地測量、北が上の敷地図、2D プロットライブラリなどでよく使われる「Y = 北、上から見た状態」として作成したレイアウトは、Pascal で表示すると元のレイアウトに対して回転して到着します(使用するビューポートやカメラの状態によっては、さらに反転する場合もあります)。エディター内蔵の 2D および 3D ツールは、格納された座標と内部的に一貫しているため、これはプログラムで作成したジオメトリにのみ影響します。外部で計算した座標を信頼する前に、既知の基準点に合わせて拡大縮小したガイド画像を配置し、位置合わせを確認してください。作成側で必要な回転(または反転)を適用して、一致させます。
軸に沿った基準例、下記の 30° 回転例、そして外部座標に関する注意点を示す「ページ上の意図とワールド上の結果」を並べた L 字形の例を含む、これらすべてを実演するサンプルは、examples/coordinate-conventions-demo.md と examples/coordinate-conventions-demo.json にあります。次のコマンドで JSON を読み込みます。
bunx @pascal-app/mcp --stdio --scene examples/coordinate-conventions-demo.json
例 — 最初の角を中心に 30° 回転させた 6 × 4 m のスラブ(座標は小数第 3 位に丸めています。辺の長さは約 6 m/4 m です。軸に沿っていないため、実際に座標変換が行われます)。
{
"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]]
}
}
これは地面(Y = 0)に平らに配置され、+X 軸から 30°ずれた方位に沿って約 6 m、その垂直方向に 4 m 広がります。つまり、ワールドの (x, z) をそのまま占めます。
別の注意点として、壁に取り付ける要素の座標は平面図の座標ではなく、壁ローカル座標です。格納されるドア/窓の position[0] は壁に沿った距離(メートル)で、壁に取り付ける要素の回転も壁ローカルです。
ツール
すべてのツールは、入力と出力を Zod で検証します。変更ツールは Zundo の temporal ミドルウェアによって、1 つの取り消し可能なステップとして記録されます。
ツールの入力スキーマで拒否された引数は、ほかの拒否と同様にコードを示すツールエラーとして、JSON テキスト { error, code: "invalid_input" } が返されます。引数の形状または型が正しくないため、error を読み、修正して再度呼び出してください。これはツールが実行される前の、スキーマによる拒否です。ツール自身が発生させるコード(apply_patch の invalid_update と invalid_parent、部屋の cannot_enclose)は { error, code, ...details } として返され、apply_patch では patchIndex と id も追加されます。エージェントが height を指定せずに作成するレベル(apply_patch の create、または値をクリアする更新)には、そのレベルに含まれるものからエディター自身の読み込み時に算出される高さが設定されます。これは最も高い壁または天井の頂上の高さで、空のレベルの場合はデフォルトの階高である 2.5 m です。apply_patch は、高さを補完したレベルごとに 1 行ずつ notes でその旨を示します。add_level は省略可能な height を受け取り、同じデフォルト値を使用します。
共有ツールが受け取るすべての長さと角度は、ひとつの表記規則に従います。単位のない数値はフィールドに記載された単位(メートル、度、ラジアン)で解釈され、テキストにはインチ、フィート、ミリメートルを含む独自の単位を指定できます。屋根勾配は度、またはライズ/ランで指定します。
{ "wallHeight": "9 ft", "overhang": "18 in", "pitch": "6:12" }
"26.6"、"26.6°"、"0.46 rad"、"6/12"、"6 in 12"、"6 on 12" も解釈されます。分と秒は拒否されます('6"' は建築用のインチ表記です)。また、"1/4 pitch" のような「ピッチ」の分数も拒否されます。これはライズ/スパンを表すためです。
| 名前 | 目的 | 主な入力 | 出力 |
|---|---|---|---|
get_scene | シーンの完全なグラフを返します。 | — | { nodes, rootNodeIds, collections } |
get_node | IDでノード全体を取得します。保存済みフィールドに加え、シーンがそのノードについて決定する情報(壁または天井の resolvedHeight と heightIsExplicit、壁の resolvedThickness、ドアまたは窓の resolvedOpening、レベルまたは床スラブの displayName)、親を先頭とする祖先、および仕上げに使われるシーンマテリアルを返します。スキーマで拒否されるノードは、派生情報なしで保存済みの状態が返されます。 | { id } | { node, ancestorIds, missingChildIds?, materials? }、または拒否 node_not_found |
find_by_type | 1種類の条件に一致するすべての項目を検索します。種類別のノード(コアまたはプラグインのあらゆる種類)、カテゴリ別のアイテム、照明、作成オブジェクト内の型付きパーツ、窓、ドアを対象にできます。レベル、親、ゾーン(そのレベル上、平面上の点で判定し、穴は除外)、またはインポート元ID(provenance.refs[].id または旧形式の metadata.sourceIds。完全一致またはプレフィックス)で絞り込めます。種類を指定しない場合は、フィルターに一致するすべてのノードを返します。各結果にはノードのID、名前、種類、レベル、親、およびメタデータと来歴が含まれます(1 KBを超えるものは omitted に記載されます)。 | { type?, levelId?, parentId?, zoneId?, sourceId?, sourceIdPrefix?, limit? } | { type?, count, nodes, parts, results[], truncated?, hint? }。結果は最大 limit 件(既定値200)まで列挙されます。拒否:unknown_type、level_not_found、node_not_found、zone_not_found、not_a_zone |
list_levels | すべての建物のレベルを床の順に一覧表示し、役割(階、屋根専用、支持)、地面との位置関係(gradeStanding、isGroundLevel)、および建物ごとの地盤面レベルを返します。 | — | { activeSceneId, activeLevelId, levelCount, occupiedStoryCount, supportLevelCount, roofLevelIds, groundLevels[], levels[] } |
get_level_summary | 1つのレベルの簡潔な概要を返します。役割、数、開口部のある壁、面積付きゾーン、床スラブ、天井、アイテム、階段、屋根、その他すべての種類が含まれます。最下階の場合は levelId を省略します。 | { levelId?, level? } | { levelId, role, counts, walls, zones, slabs, ceilings, items, stairs, roofs, other } |
get_walls | レベル上の壁について、長さ、保存された高さと解決済みの高さ、および子のドア/窓を返します。 | { levelId?, level? } | { levelId, walls[] } |
get_zones | 穴のある部屋/ゾーンのポリゴン、面積(穴を除外)、境界、および床の選択肢を返します。 | { levelId?, level? } | { levelId, zones[] } |
get_site | 建物が建つ敷地を、そのレベル座標で返します(建物がまだない区画の場合は敷地座標)。区画とその面積、通常は住宅が占める建築面積(30~45%)、セットバック内の建築可能エリアとその中心・面積・各辺の間口と奥行き・正面の辺、区画の間口と奥行きを持つ道路側、北の向き、地面(傾斜の有無。平坦か未計測かを判定)、住所、区画情報と用途地域、新規プロジェクト用のプレースホルダーかどうか、建築面積の適合状況と庭を返します。 | { building?, site? } | { siteId, buildingId, pose, lot, placeholder, buildable, street, ground, northDeg, address, parcel, zone, footprint, others, summary }。拒否:no_site、building_required、site_not_found、not_a_site、building_not_on_site |
place_building | 建物ノードだけを移動して、敷地上に建物を配置します(壁のレベル座標は維持されます)。建築面積、これから描く輪郭、または既存の壁を使い、建築可能エリアの中央か指定された庭の位置に配置します。壁のある住宅は rotationDeg を指定しない限り回転を維持し、まだ壁がない住宅は道路に対して直角に配置されます。 | { building?, outline?, yards?: { front?, rear?, left?, right? }, rotationDeg? } | { buildingId, position, rotationDeg, moved, footprint, yards, fit, overhang, movedWithIt?, message }。拒否:no_site、needs_footprint、other_building_on_site、no_street、yards_conflict、yards_infeasible、building_required |
measure | 2つのノードのワールド座標上の基準点間の距離を返します(ホスト付きのドア、窓、アイテムはホスト経由で解決。すべてのノード種類に対応)。該当する場合は面積も返します。 | { fromId, toId } | { distanceMeters, fromPoint?, toPoint?, areaSqMeters?, units: 'meters' } |
view_scene | エージェントが選んだ視点(方位、住宅の道路側から見た側面、道路の高さにある目線、写真のカメラ、正面、上空)から、完成した建物、各階、屋根を、シーン本来の照明または写真の照明で表示し、画像を返します。領域を指定した場合は、写真の切り抜きも併せて返します。interior: { zoneId } は、部屋の中の目線の高さ(既定値は1.6 m)に立ち、角から一歩入って部屋を見渡します。interior: { levelId } は1つの階の内部を表示します。他の階、屋根、天井は除外され、その階にあるもの(壁、開口部、家具)は、画像表示に限り階高の0.65の位置で切断されます。画像サイズは、maxPx(64~1920)で長辺を小さく指定しない限り、1920 × 1200です。サーバーにはレンダラーがありません。ホストの sceneViews が、ユーザーの開いているエディタータブを通じて描画します。読み取り専用です。 | { target?, interior?, from?, elevation?, eyeHeight?, position?, fov?, projection?, camera?, lighting?, maxPx?, photo? } | 画像コンテンツと { status, camera, size, tab, capturedAt }。拒否:view_unavailable、no_project、which_building(道路側を指定し、対象を指定していない場合に、複数の敷地に建物がある)、no_current_camera(camera: 'current':サーバーからユーザーのカメラが見えない)、camera_and_viewpoint(エージェント自身の視点とカメラの両方を指定)、photo_crop_unavailable、interior_level_invalid、interior_hidden、interior_transform_unsupported、interior_target_elsewhere。ホストされたサーバーでは、editor_tab_required、editor_tab_hidden、editor_tab_busy(タブは開いているものの処理中または読み込み中で、リンクなし:数秒待ってからもう一度呼び出してください。ユーザーには尋ねないでください)、editor_tab_timeout(タブが表示を引き受けた後、応答を停止)。エディターを開くことについて拒否時に表示される内容は、ユーザーの「エージェントが私の代わりにエディターを開いてよい」設定(最初に確認、許可、禁止)に従います。 |
search_assets | ホストのアイテムライブラリ(スタンドアロンサーバーでは組み込みリスト)を検索します。1回の呼び出しで複数のクエリを指定でき、名前、ID、カテゴリ、タグに一致します。何も見つからないクエリには、add_object でアイテムを作成するためのヒントが返されます。 | { queries: [{ query, category? }] } | { groups: [{ query, total, results[] }], total, hint? }。拒否:no_catalog |
design_brief | リクエスト全体を一度、設計概要として読み取ります。axes(リクエストを軸ごとに読み取ったもの:action、size、pieces、openings、style、materials、dressing。各軸には制限があり、ユーザー自身の言葉を quote として記録し、短い行で解釈を示します。pieces は minimum または exact として指定するか、3語以上の設計説明で自由指定できます。軸がない場合は axis_missing、引用がチャット内のユーザーメッセージにない場合は axis_quote_not_in_request、自由指定の軸に設計説明がない場合は axis_open_without_design で拒否されます。MCP経由では、メッセージがないため、軸の引用は必須ですが照合されません)。8番目の軸は source(open、catalog、brand とその brand、または existing)です。自由指定の場合の vision、部屋の装飾をレイヤーごとに示す beyond(テキスタイル、照明、窓、壁、床、植物、オブジェクト、小型家具。それぞれにアイテムを指定するか、{ none: why } を指定)。dressing 軸が自由指定なら8項目中6項目が必要で、足りない場合は beyond_too_thin。制限付きの場合は不要ですが、最低数として指定された項目だけでは制限と見なされず、dressing_bounded_by_minimum で拒否されます。内容は dressing として返されます。open 以外のソースを定めるユーザーの言葉(sourceQuote。必須。ブランド、カタログ、または既存のものを示す2語以上。ここではリクエストとの照合は行われません)。ソースが open の場合は、配置済みの技術設備を asIs に記載します(衛生設備、家電、固定設備。各アイテムは事前に view_assets で表示し、それぞれに理由を付けます。家具は作成します)。家具の配置または作成を伴うツール:place_items、furnish_room、place_in_room(カタログのもの)、add_object、place_design(作成したもの)は、run_batch 内での呼び出しも含め、先に design_brief がなければ実行前に拒否されます。search_assets と view_assets は引き続き利用できます。ソース open では作成したアイテムを有効にし、asIs に指定された場合のみ技術設備を配置し、furnish_room は無効にします(brief_source_open)。catalog、brand、existing ではカタログのツールと、不足分の作成が有効になります。バッチ内に拒否された呼び出しがある場合、バッチ全体が拒否されます。概要はセッション単位です。シーンを読み込むか消去すると新しいセッションになり、次の design_brief で置き換えられます。シーンは変更されません。 | ||
view_assets | カタログアイテムを1~6点、IDで指定して画像表示します。各アイテムには寸法、カテゴリ、塗装可能な面の名前がラベル表示されます(モデルの slot_<id> マテリアル。paint では role として指定)。画像コンテンツとして返されます。呼び出し前に画像と面を読み込みます(ホストされたサーバーではサムネイルを取得し、512 px以下に縮小します。スタンドアロンサーバーの組み込みリストには取得元のホストがないため、寸法を返し、画像がないことを伝えます)。オプトイン方式です。呼び出さない限り何も変更されません。 | { ids: string[] (1 to 6) } | { items: [{ id, name, category, dimensions, surfaces, picture, unavailable? }], shown, note? } と、表示された各アイテムのラベル付き画像。拒否:unknown_asset、no_catalog |
search_materials | マテリアルライブラリを検索または閲覧します。1回の呼び出しで複数のクエリを指定でき、ライブラリ内の表記(timber は wood、render は stucco)、色合い、表面に一致します。単語のないクエリでは、種類、表面、またはライブラリ全体を名前で一覧表示します。検索は一度に12件、閲覧は150件を表示します。長い一覧では残りの件数(more)と、次の一覧のオフセット(next)を示します。Pascal のライブラリと、ホストが登録したマテリアルを読み取ります(エディターはライブラリを登録します。このサーバーは登録しません)。読み取り専用です。 | { queries: [{ query?, kind?, surface?, offset? }] } | { groups: [{ query?, kind?, surface?, offset?, results: [{ ref, label, kind, surfaces, color? }], missing?, more?, next? }] } |
paint | 1回の呼び出しで、壁、床スラブ、天井、屋根、その他すべての表面を持つパーツ(柱、フェンス、ドア、窓、階段、ブロック、キャビネット、棚など)に、エディターの「ペイント」と同様に仕上げを指定します。色(ライブラリ内の最も近い色)、library: または scene: の参照、シーンマテリアルとして保持するネイティブマテリアル(同一のものがあれば再利用)、または消去を指定できます。role で表面を選択します(壁の exterior/interior 面。部屋がある場合はその部屋、ない場合は保存済みの面を使用します。部屋が面の一部にしかない場合は拒否されます。名前によるスロット、屋根の top/edge/wall または fascia。破風板と鼻隠し板は各セグメントが保持します。ガラス張りの屋根では glazing-frame、glazing-glass、glazing-solid。役割を指定しない場合はフレームと不透明パネルが対象となり、ガラスは維持されます)。屋根は表面ごとに1つの仕上げを表示するため、セグメントの仕上げは屋根に適用され、屋根の仕上げを変更すると各セグメント固有の仕上げが解除されます。壁面は全体に塗装され、部屋の壁の仕上げの上に適用されます。塗装済みのパーツはその仕上げを維持し、note に記載されます。 | { targets[], role?, color?, material?, materialName?, erase? }(仕上げは1つ) | { ok, painted[], finish, materialId?, material?, createdMaterial?, note?, achieved }。拒否:target_not_found、unknown_role、side_unknown、unknown_material、materials_unavailable、not_paintable |
create_story_shell | フットプリントから、1階分のレベル所有の階シェル(周囲の壁)を作成します。床スラブと天井は囲まれた部屋から派生します。createSlab/createCeiling/slabElevation は部屋の意図として記録されます。各階に1回だけ使用します。 | { levelId, footprint, wallHeight?, wallThickness?, createSlab?, createCeiling? } | { wallIds, zoneIds, slabId, ceilingId, createdIds } |
create_stair | エディターの階段ツールと同様に、直線、L字、U字の階段を作成します。階段はある場合は次の上階へ(ない場合は作成)、階段が切り抜く床開口部を所有します。または上階なし(toLevelId: null)にできます。(x, z) は一番下の段鼻の中央、rotation は度数です(0は +Z 方向に上ります)。 | { x, z, levelId?, toLevelId?, rotation?, layout?, turn?, lowerSteps?, width?, length?, height?, steps?, railingMode?, railingStyle?, railingMaterial? } | { stairId, segmentIds, upperLevelId, createdUpperLevel, layout, stepCount, rise, length, footprint, arrival, slabHoleCut, openingIds? }。拒否:roof_level、not_above、level_not_found、slab_not_found/ceiling_not_found、slab_not_on_level/ceiling_not_on_level、stair_layout、stair_layout_required、no_level_above |
measure_stair | 実際の蹴上げ寸法、歩行線上の踏み面寸法、勾配、均一性、到達位置、床/天井/階段本体に対する頭上空間、および設計目標の診断情報を読み取ります。 | { stairId, available?: { width, length } } | { measurements, layouts } |
fit_stair | 均一な蹴上げに調整するか、幅に合わせた踊り場または90度回転する踏み板を備える直線/L字/U字のプリセットに階段の連鎖を置き換えます。1回の取り消し可能な編集で実行します。 | { stairId, fitRun?, targets?, layout?, turn?, width?, landingDepth?, turningStrategy?, innerGap?, walkingLineOffset?, division? } | { stairId, measurements } |
create_roof | 最上階のフットプリント(壁の輪郭、なければ床スラブ、さらにそれもなければ部屋)を覆う屋根を作成します。長方形ごとに1セグメントを作成するか、独自の長方形(width、depth、center)を指定できます。屋根は、その階の上にある建物の屋根レベルに配置されます(既存のものを再利用します。直上に空のレベルしかない場合はそれを使い、それ以外は Roof という名前で作成します)。屋根はその階の壁の上端に立ちます。手動の屋根ツールも同じ規則に従います。roofType: "barrel" は各セグメントをアーチ状にします(depth はスパン、barrelRise はスパンの半分以下、barrelSegments は4~32の面数です)。roofSystem: "glazed" は、glazing で指定した切妻屋根、片流れ屋根、またはバレル屋根を、ガラス板と枠組みで構成します(ガラス屋根を参照)。 | { levelId? (or level), roofType?, roofSystem? ('standard' | 'glazed'), glazing?, barrelRise?, barrelSegments?, pitch? (degrees, or rise over run: "6:12"), overhang? (the eaves' reach past the walls in plan), wallHeight?, wallThickness?, width?, depth?, center?, materialPreset?, fasciaHeight?, fasciaMaterialPreset?, name? } | { roofId, roofLevelId, createdRoofLevelId, coveredLevelId, segmentIds, roofType, achieved }。拒否:storey_above、roof_exists、building_required(複数の建物があり、名前付きのレベルがない)、storey_without_building、conflicting_level、no_levels、no_rooms、rectangle_incomplete、unknown_material(屋根または破風板の仕上げ) |
move_roofs_to_roof_level | ある階の壁上に配置された屋根を、屋根の規則が定めるレベル(最上階の上にある建物の屋根レベル。存在しない場合は作成。下階ではその上の階)に移動します。手作業で屋根パネルを移動する場合と同じ動作です。各屋根は元の位置を保ち、セグメント、仕上げ、IDも維持されます。屋根レベルがまだなかったプロジェクトで、verify_scene が roof_mixed_in_storey を報告した場合に使用します。 | { levelId } | { roofIds, roofLevelId, createdRoofLevelId, achieved }。拒否:level_not_found、no_roof_on_walls |
create_room | ポリゴンから部屋を作成します。辺ごとに壁を1つ作成し(既存の壁に沿う辺ではその壁を再利用)、部屋のゾーンを作成します。同じ呼び出しで、辺(wallIndex)と t を指定してドアと窓を宣言できます。配置には add_door と add_window の規則が適用され、配置をスキップした場合は skippedOpenings に記載されます。床スラブと天井は派生するものであり、直接作成されません。outdoor: true はテラスを作成します。壁がない部分には区切り線(エディターの Separator。壁のない部屋境界)を設け、独自の壁や天井は作成しません。ポリゴンのすべての辺が既存の壁に沿っていて(作成対象がなく)、その壁が作る部屋にポリゴンが収まる場合は、既存の部屋を指定し、2つ目のゾーンは重ねません。その部屋の zoneId が返されます。既存の部屋に固有の名前がある場合(エディターが付けた数字の名前ではなく、「Room N」以外の名前。誰が付けたかは問いません)、呼び出しは拒否されます(room_named_by_person。部屋名を含むメッセージが返されます)。rename: true を渡せるのは、ユーザーが名前変更を依頼した場合だけです。それ以外はユーザーに確認してください。依頼なしに部屋の名前を変更することはありません。同じ名前がすでに付いている場合は、作成するものがないことを伝えます。outdoor: true のテラスを完全に壁で囲まれた中庭に重ねると、その部屋を屋外として指定します。この拒否はエージェントに限られます。エディター本来の部屋ツールは従来どおり動作し、ユーザーは部屋を直接見て名前を付けられます。 | { name, polygon, levelId?, color?, wallHeight?, wallThickness?, outdoor?, rename?, doors?, windows? } | { zoneId, slabId, ceilingId, wallIds, reusedWalls, areaSqMeters, doorIds, windowIds, skippedOpenings? }。拒否:cannot_enclose、outdoor_room_overlap、room_named_by_person |
add_door | エディターの配置規則に従い、直線の壁に t(壁に沿った位置、0..1)でドアを追加します。扉なしの通路(openingKind: "opening")も作成できます。ドアは壁上に収まるように移動され、その場合は clamped で報告されます。doorType、style、輪郭(openingShape)は参照に一致させ、code では参照にないものを作成し、nodeId ではスクリプトで定義したドアを再作成します。 | { wallId, t?, width?, height?, openingKind?, hingesSide?, swingDirection?, doorType?, style?, openingShape?, code?, nodeId?, force? } | { doorId, wallId, localX, t, clamped, achieved }。拒否:wall_not_found、not_a_wall、curved_wall、wall_too_short、opening_overlap(force を指定した場合を除く) |
add_window | add_door と同じ方法で窓を追加します。sillHeight(床から窓の下端までの高さ)を指定しない限り、窓は壁の上下中央に配置されます。windowType、columns/rows、style(固定窓の格子。別の種類では拒否され、style_needs_fixed_window が返されます)、および輪郭は参照に一致させます。 | { wallId, t?, width?, height?, sillHeight?, windowType?, columns?, rows?, style?, openingShape?, code?, nodeId?, force? } | { windowId, wallId, localX, t, clamped, sillHeight, achieved }。拒否は add_door と同じです。 |
furnish_room | ホストのアイテムカタログから部屋の種類に合った家具を配置します。主要な家具はドアの反対側の壁に置き、残りは側壁に沿って配置します。ドアのクリアゾーンや他のアイテムには置きません。収まらない家具は位置をずらし、それでも収まらなければスキップして、理由を skipped に記載します。 | { zoneId?, polygon?, levelId?, roomType, doorWallIndex? } | { placed, itemIds, skipped, doorWallIndex, doorsDetected }。拒否:room_required、roof_level、level_not_found、no_catalog |
add_corner_window | 2つの壁が交わる角を囲む窓を追加します。壁ごとに1つずつ、どちらも角まで伸ばして接合します。ガラスは一体化されるか(固定窓)、細い方立で接合されます(その他の窓種別。枠は維持)。角度は10°~170°です(直角、出窓の135°、鋭角など)。corner は levelId の壁が端点で接する位置です(既定では表示中の階。上下階が重なる場合、各階の角の点を共有します)。[x, z] は get_walls が端点を返すレベルの平面座標です。width は角から各壁に沿ってガラスが伸びる距離(既定値は1.2 m)で、widths を使うと壁IDごとに上書きできます。post は 'none'(ガラスを一体化。固定窓の既定値)または 'post'(その他の窓種別の既定値かつ唯一の選択肢)です。height の既定値は1.5 mです。sillHeight(床から窓の下端までの高さ)を指定しない限り、窓は壁の上下中央に配置されます。角で3つ以上の壁が接する場合に限り、wallIds(2つのID)が必要です。windowType と style は add_window と同じです(スタイルの指定には固定窓が必要です)。手動では、角で終わる窓を選び、窓パネルの Corner セクション(角を囲む、こちら側、反対側、固定窓の一体ガラスまたは角の方立、解除)を使います。 | { corner: [x, z], levelId? (or level), wallIds?, width?, widths?, height?, sillHeight?, post?, windowType?, style? } | { windowIds, wallIds, angle, post, achieved }。拒否:no_corner(2つの壁がそこで接していない)、corner_ambiguous(3つ以上が接している:wallIds を指定)、corner_angle(10°未満または170°超:add_window を使用)、corner_not_fused(固定窓以外で post: 'none' を指定)、width_exceeds_wall、style_needs_fixed_window |
merge_windows | エディターの「Merge windows」ボタンと同じように、既存の2つの窓を1つにします。作り直しは行いません。角で交わる2つの壁にある窓がそれぞれ角から0.30 m以内にある場合、2つを1つの角窓(add_corner_window の結果と同じ)にします。それぞれの幅を保ったまま角まで移動し、ガラスを一体化します(固定窓の場合。その他の窓種別は方立で接合)。両方の高さ、窓台の高さ、種類は最初の窓に統一されるため、希望する外観の窓を先に指定してください。角度が170°を超えるか10°未満の場合は拒否されます。同じ壁にある2つの窓の間隔が0.30 m以下で、その間に何もない場合は、重なっている場合や片方がもう片方の内側にある場合も含め、2つの窓を結合部分の範囲全体にわたる1つの窓にします。下側の窓台から上側の窓上端までを覆い、最初の窓の種類とスタイルを使用します。角や幅の広い1つの開口部としてすでに作成済みの2つの窓に使用します(verify_scene の corner_unjoined は、最初のペアの名前を示します)。新しいペアを作成するには add_corner_window を使います。手動では、窓を2つ選択して複数選択パネルの「Merge windows」を使うか、角で待機している窓の近くに窓を配置またはドラッグしてクリック/リリースします(Altキーを使うと通常の窓を配置します)。 | { windowIds: [a, b] } | { kind: 'corner' | 'same_wall', windowIds, removedIds, achieved }。拒否:window_not_found、not_a_window、same_window、window_not_on_wall、window_already_joined(先に結合を解除)、windows_already_joined、windows_not_adjacent、opening_between、walls_not_meeting、corner_angle、window_not_at_corner、height_exceeds_wall、opening_overlap |
apply_patch | 作成/更新/削除/移動をまとめて実行し、検証とドライランを行ってから確定します。既定ではバッチを優先します。1つの作成手順に含まれるすべての作成/更新/削除操作を、1回のアトミックな呼び出しにまとめてください(順序は安定しており、後続の操作から先に作成したIDを参照できます)。1操作ずつの呼び出しを繰り返さないでください。シーン内にすでに存在するIDで作成しようとすると拒否されます(node_exists)。置き換えるには、同じパッチ内で先に削除してください。更新では、id または type の変更(identity_change)、object または children の変更(immutable_field)、存在しない親または子を持たない親の下へのノードの移動(invalid_parent)、スキーマ違反の追加(invalid_update)はできません。削除によって再生成される既定の雨樋と縦樋は、後続の呼び出しでのみ指定できます(regenerated_default)。拒否はツールエラーとなり、JSONテキスト { code, patchIndex, id, message } が返されます。height を指定せずに作成したレベル、または更新時に height を消去したレベルには、レベルの内容からエディターが読み込み時に導き出す高さが設定されます(空のレベルは2.5 m)。notes にはレベルごとに1行ずつ記載されます。パッチによって屋根を作成するか、その屋根を屋根を支える壁のある階に移動した場合、屋根はそれらの壁の上のレベルに配置されます。屋根ごとに1行ずつ notes に記載されます。その屋根レベルと同じ高さかそれ以上に新しい階を作成すると、屋根は上に移動します。次の場合は拒否されます。屋根レベルに階のコンテンツを配置する(roof_level)、階のコンテンツを持つレベルを屋根レベルとして宣言する(roof_level_holds_storey)、床インデックスの指定により屋根レベルを階の下に配置する(roof_level_on_top)。 | { patches: Patch[] } | { applied: number, notes?: string[] } |
add_level | エディターと同じように、建物に空のレベルを追加します。階の最上部、屋根レベルの下(屋根レベルは1つ上に移動)、または地下階として最下部に追加できます。最下部に追加する場合、地上階を含む既存のすべての階は位置を維持します。シーン内に建物が1つだけの場合は buildingId を省略します。 | { buildingId?, position?, name?, height? } | { levelId, buildingId, floorIndex, height, shiftedLevelIds? }。拒否:building_required、building_not_found、no_building |
set_ground_level | レベルを建物の地上階に設定します。レベルパネルの「Set as ground floor」と同じ動作です。建物はそのレベルを地上階として登録し、建物の基礎施工と同じ方法で配置され、床が地盤面の上に来ます。基礎上端の高さは8 in、0.203 m(ブロック造の場合。既定値および米国の場合)または0.15 m(欧州の現場打ちコンクリートの場合)です。変更されるのは高さだけで、平面位置は変わりません。床インデックスは付け直され、このレベルが0となり、それより下のレベルは地下階になります。 | { levelId } | { levelId, buildingId, floorElevation, aboveGrade, foundation { region, construction, basis }, movedBuildingBy, renumbered, unchanged? }。拒否:level_not_found、not_a_level、no_building、not_a_storey |
add_wall | レベルに壁を追加します。直線の壁、または curveOffset を指定した円弧の壁を作成できます。最下階では levelId を省略します。 | { start, end, levelId?, thickness?, height?, curveOffset? } | { wallId, levelId, length }。拒否:roof_level、wall_too_short、level_not_found |
add_fence | レベル上の点に沿ってフェンスを追加します。辺ごとにフェンスを1つ作成します。closed を指定すると最初の点までつなぎ、区画の境界を囲みます。style で別の種類を指定しない限り、目隠しパネルを使用します。 | { points, closed?, height?, style?, baseStyle?, materialPreset?, levelId? } | { count, fenceIds, levelId, length, achieved }。拒否:fence_too_short、roof_level、unknown_material、level_not_found |
place_items | カタログアイテムを1回の呼び出しで配置します。各アイテムは個別に配置されるか拒否されます。レベルの (x, z) に配置します。配置先はレベルの床、または各アイテムが指定するホスト(targetNodeId)です。ホストには、壁(底面の高さを示す y が必須)、天井、床上に立つアイテムを指定できます。床に配置するアイテムがドアの開閉クリアランス内にある場合は拒否され、ドアのIDと、すべてのドアを避ける位置が示されます(blocks_door)。部屋のどの向きでも収まらないアイテムは too_large_for_room で拒否されます。 | { items: [{ assetId, x, z, y?, targetNodeId?, rotation? }], levelId? } | { levelId, items: [{ ok, itemId?, hostId?, restingOn?, code? }] }。アイテムごとの拒否:asset_not_found、outside_rooms、blocks_door、too_large_for_room、height_required、item_too_tall、unsupported_host、host_not_found、host_not_on_level |
place_design | validate_design に合格した1つのデザイン(プロシージャルなアイテムレシピ、オブジェクト、またはJSON文字列)を作成します。取り付け位置でホストを指定します。レベル/床スラブ/ゾーン、デザインの表面(surfaceId)、直線の壁面、または天井を指定できます。作成専用で、取り消し操作は1回です。コード付きの拒否に対応し、インラインのデザインは最大24 KiBです。 | { design, hostId, position, rotation?, side?, surfaceId?, parameters?, slots?, name?, id? } | { designId, parentId, surfaceId } |
set_zone | レベル上にゾーン/部屋のポリゴンを作成します。すでに部屋を囲んでいる壁の上では、その部屋を指定し、2つ目のゾーンは決して作成しません。名前が「Room N」のまま、またはすでに label と一致する場合は、そのラベルが設定されます。ユーザーが別の名前を付けている場合は拒否されます。 | { levelId, polygon, label, properties? } | { zoneId } |
duplicate_level | エディターと同じようにレベルをコピーします(そのレベル上に部屋があるユニットも含まれます。平面の参照、スキャン、スポーンはコピーされません)。上下いずれかに追加し、それを超える階の位置をずらします。 | { levelId, position?, name?, preset? } | { newLevelId, name, floorIndex, shiftedLevelIds, copied, skipped, newNodeIds[] } |
delete_node | エディターの「Delete」と同じように、ノードとその配下すべてを削除します。 | { id } | { deletedIds: [] } |
clear_scene | プロジェクトを意図的に空にし、既定の敷地、建物、レベルに戻します。プロジェクトを空にする唯一の方法です。空の状態にする書き込みは、誤って消去されないよう保護するストアによって拒否され(scene_wipe_blocked)、セッションには保存済みのプロジェクトが保持されます。 | { reason } | { cleared: { removed }, version, graphHash } |
undo | 履歴を時間順にさかのぼります。 | { steps? } | { undone: number } |
redo | 履歴を時間順に進めます。 | { steps? } | { redone: number } |
export_json | シーングラフをJSONとしてシリアライズします。 | { pretty? } | { json: string } |
export_glb | スタブです。GLBのエクスポートにはブラウザレンダラーが必要です。 | — | not_implemented をスローします。 |
validate_design | 読み取り専用です。デザイン(プロシージャルなアイテムレシピ、オブジェクト、またはJSON文字列)を検証し、寸法を測定します。pascal://schema/design に対する正式な検証元です。 | { design, parameters? } | { valid, diagnostics[], design, sweep, measurements } |
verify_scene | 唯一のシーン検査ツールです。スキーマの有効性、レベルごとの数、役割、壁が囲む空間、空のレベル、型付きの実用上の問題を確認します(ノードの各フィールドについて、スキーマ違反を schema_invalid として nodeId と path 付きで報告します。スキーマが認識しないノード種類は種類ごとに1回報告します。また、部屋がない空間や部屋が複数ある空間、壁で閉じられていない部屋や名前のない部屋、階段のない階、壁から外れた開口部、床スラブから外れた階段、通行を妨げるドア、敷地境界を越えた住宅、必要な庭の範囲に入った住宅などを確認します)。 | — | { valid, levels[], issues: { type, message, … }[], hasIssues } |
check_collisions | アイテム同士の重なりと、範囲外への配置を検出します。 | { levelId? } | { collisions: { aId, bId, kind }[] } |
analyze_floorplan_image | ビジョンツールです。間取り図の画像から壁、部屋、概算寸法を抽出します。 | { image, scaleHint? } | { walls, rooms, approximateDimensions, confidence } |
analyze_room_photo | ビジョンツールです。部屋の写真から概算寸法と設備を抽出します。 | { image } | { approximateDimensions, identifiedFixtures, identifiedWindows } |
| ビジョンツールを使用するには、MCP ホストがサンプリング機能 | |||
(createMessage)をサポートしている必要があります。サポートしていないホストでは、構造化された | |||
sampling_unavailable エラーが返されます。 |
廃止されたツールは一覧から削除されますが、引き続き応答します。その名前で呼び出すと、コード tool_retired、置き換え先のツール(replacement)、およびそのツールの使用方法を含むエラーが返されます。validate_scene は verify_scene に、find_nodes は find_by_type に、describe_node は get_node に置き換えられました(@pascal-app/core/agent-tools の RETIRED_MCP_TOOLS)。
// 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 } }
gableOverhang は、屋根セグメントが切妻端の壁(切妻屋根またはマンサード屋根の端、片流れ屋根の側面)より張り出す長さを、平面図上のメートル単位で表します。省略した場合、端部は軒先と同じ位置まで伸びます。屋根パネルの「切妻の張り出し」スライダーは、同じフィールドを編集します。
リソース
| URI | MIME | 目的 |
|---|---|---|
pascal://scene/current | application/json | { nodes, rootNodeIds, collections } の完全なスナップショット。 |
pascal://scene/current/summary | text/markdown | ノード数、バウンディングボックス、階ごとの面積を含む、人が読みやすい概要。 |
pascal://agent/guide | text/markdown | エージェント向けの、MCP を優先する建築ワークフロー、シーンの不変条件、ツールの選択方針。ホストサーバーでは、プロジェクト内の他のチャット、ファイル、メンバーも参照できます(search_project_chats、read_project_chat、get_project_assets、read_project_asset、list_project_members)。これらは引用データとして読み取られ、指示として扱われることはありません。 |
pascal://catalog/items | application/json | 一般的な住宅用家具や設備を含む、依存関係のない組み込みカタログのサブセット。 |
pascal://constraints/{levelId} | application/json | 指定された階のスラブの平面形状と壁のポリゴン。プランナーのコンテキストとして役立ちます。 |
pascal://schema/design | application/json | 設計コントラクト:core の RecipeSchema から生成された JSON Schema、制限、validate_design のみがチェックするルール、および例。 |
プロンプト
| 名前 | 引数 | 目的 |
|---|---|---|
from_brief | { brief: string, constraints?: string } | 文章による概要(例:「80 m²の2ベッドルームのアパート」)を、空のサイトから始めて apply_patch の呼び出しを段階的に連ねる形にするためのガイド付きワークフローです。 |
iterate_on_feedback | { feedback: string } | 最小限の差分を作成するための指示です。現在のシーンを確認し、フィードバックを満たす最小のパッチセットを提案します。 |
renovation_from_photos | { currentPhotos: string[], referencePhotos: string[], goals: string } | ビジョンツールとシーン変更ツールを連携させ、写真に基づいたリノベーション計画を作成します。 |
制限事項
export_glbはnot_implementedを返します。GLB のエクスポートには Three.js レンダラーが必要であり、多大な追加作業なしではヘッドレス環境から利用できません。- ビジョンツールには、MCP ホストのサンプリング対応が必要です。Claude Desktop は対応していますが、一部の MCP クライアントは対応していません。
- 組み込みの MCP カタログは意図的に小規模にしています。ホストアプリケーションは、MCP パッケージがエディター UI バンドルに依存することなく、追加のツールやリソースを通じて独自の、より充実したカタログを公開できます。
- システム(壁の留め加工、スラブの三角形分割、CSG の切り抜き、屋根や階段の生成)は、エディター内の React フックで実行されます。ヘッドレスモードでは派生ジオメトリは再生成されませんが、すべてのノードデータは引き続き完全に操作できます。レンダリング済みのジオメトリが必要な場合は、ブラウザホストで
@pascal-app/viewerを実行してください。 - Core の
loadAssetUrl/saveAssetはブラウザー専用です。asset://<id>URL を参照するアイテムは Node では解決できません。アイテムのアセットをブラウザー外で使用する必要がある場合は、絶対 URL またはdata:URL を指定してください。 - レンダラーが
dirtyNodesを消費しないため、ヘッドレスモードではdirtyNodesが蓄積します。利用側で可観測性が重要な場合は、bridge.flushDirty()を呼び出してください。
開発
bun install
bun run --cwd packages/mcp build
bun test
stdio バイナリをエンドツーエンドでスモークテストします。
bun run --cwd packages/mcp smoke
ライセンス
MIT
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。