メインコンテンツまでスキップ

読む — model_summary / layers / spaces / canonical_json

建物を読むだけの四つ。どれも何も書かない。引数はすべて entry の .muro パス file で、呼ぶたびにゼロから合成される。

この頁の出力はすべて実際に走らせて得たものである。絶対パスは <abs> に縮めてある。

ざっと

ツール何を返すかいつ呼ぶか
model_summary建物一棟の要約最初に一度。次に何を読むかを決めるため
layers全レイヤーの全文書き換える前に、原本を読むため
spaces空間の一覧パス・面積・出所層を数え上げるため
canonical_json合成後の単一モデル機械に渡す・外と繋ぐ・差分を取るため

model_summary

Summary of the building: name, levels, layer composition, zones, door/window assets, areas, and check counts. Call this first

{"name": "model_summary", "arguments": {"file": "<abs>/examples/two-rooms.muro"}}

file のみ、必須。

{
 "name": "二室",
 "unit": "mm",
 "layers": [
  "<abs>/examples/two-rooms.muro"
 ],
 "levels": [
  {
   "name": "L1",
   "z": 0,
   "h": 2400,
   "slab": 150
  }
 ],
 "spaces": 3,
 "boundaries": 3,
 "zones": [],
 "assets": [],
 "totalFloorM2": 32.4,
 "semiOutdoorM2": 0,
 "floorsM2": {
  "L1": {
   "rooms": 2,
   "subtotalM2": 32.4
  }
 },
 "byUseM2": {
  "(unspecified)": 32.4
 },
 "check": {
  "errors": 0,
  "warnings": 0
 },
 "hint": "Read layer contents with layers, check with check, and edit with write_layer (check is the gatekeeper). Architectural verdicts come from validate."
}
フィールド中身
name unit書かれた建物名と単位
layers合成に参加した全レイヤーの絶対パス。辞書順である (layers と同じ並び)
levels宣言順ではなく z の昇順。hslab書かれたときだけ出る
spaces空間の数 (領域を持たない空間・exteriorvoid も含む)
boundaries導出後の境界の本数
zonespathname (書かれたときだけ)・site: true (敷地ゾーンのときだけ)・areaM2
assets建具アセットの name / kind (door または window) / attrs 全部
totalFloorM2屋内の延べ床面積
semiOutdoorM2半屋外の面積。延べ床には入っていない
floorsM2レベル別の {rooms, subtotalM2}
byUseM2use 別の面積。use が決まらない空間は (unspecified) に寄る
check{errors, warnings} の件数だけ。本文は返らない
sitePolygonspolygon を持つゾーンのパス。一つも無ければキーごと出ない
hintエージェント向けの固定文

数え方の約束

boundaries は導出後の本数である。接する空間の既定は壁なので、boundary を一行も書かなくても境界は現れる。だから layers が返す原本の boundary 行数より多くなることがある。書かれた構成の側の数を見たいときは canonical_json を使う。

totalFloorM2 は屋内だけを数える。exteriorvoid、および半屋外と判定された空間は入らない。半屋外の分は semiOutdoorM2 に別掲される。floorsM2 に出るのも屋内の室だけで、屋内の室を一つも持たないレベルはキーごと出ない。

zones[].areaM2 は二通りある。敷地ゾーン (site:1) に polygon が書かれていれば、その多角形の面積である。それ以外は、そのパスの下にある屋内空間の床面積の合計である。だから庭と通路だけを従えた敷地ゾーンは 0 と出る。

 "zones": [
  {
   "path": "/site",
   "name": "敷地",
   "site": true,
   "areaM2": 0
  },
  {
   "path": "/home",
   "name": "住戸",
   "areaM2": 92.75
  }
 ],

(examples/house/main.muro に掛けた同じ出力の zones の部分。/site の下は庭と通路だけなので、屋内の合計は 0 になる。敷地面積そのものを問うなら site を呼ぶ — そちらは 126.24 を返す。)

polygon を持つ例に掛ければ、多角形の面積がそのまま出て sitePolygons も現れる。

 "zones": [
  {
   "path": "/site",
   "name": "敷地",
   "site": true,
   "areaM2": 1097.8
  },
 "sitePolygons": [
  "/site"
 ],

(examples/tower/main.muro に掛けた同じ出力の抜粋。)


layers

Returns every layer (.muro file) taking part in the composition, in strength order (later layers are stronger), with its source — this is how you read the original

{"name": "layers", "arguments": {"file": "<abs>/main.muro"}}

file のみ、必須。返るのは {file, source} の配列で、source はそのファイルの全文をそのまま持つ。

次の二枚を合成した場合。

# main.muro — entry
koyu 1.0
name 二層
unit mm

grid X 0 3600 7200
grid Y 0 4500
level L1 0 h:2400 slab:150

import ./L1.muro
# L1.muro
space /L1/a room X1..X2 Y1..Y2 name:居室A
space /L1/b room X2..X3 Y1..Y2 name:居室B
space /out exterior name:外部

boundary /L1/b /out t:150
  door w:900 h:2100 edge:S name:玄関

main.muro を entry にして呼ぶと、こう返る。

[
 {
  "file": "<abs>/tiny/L1.muro",
  "source": "# L1.muro\nspace /L1/a room X1..X2 Y1..Y2 name:居室A\nspace /L1/b room X2..X3 Y1..Y2 name:居室B\nspace /out exterior name:外部\n\nboundary /L1/b /out t:150\n  door w:900 h:2100 edge:S name:玄関\n"
 },
 {
  "file": "<abs>/tiny/main.muro",
  "source": "# main.muro — entry\nkoyu 1.0\nname 二層\nunit mm\n\ngrid X 0 3600 7200\ngrid Y 0 4500\nlevel L1 0 h:2400 slab:150\n\nimport ./L1.muro\n"
 }
]

並びは辞書順である — 強度順序ではない

返る配列は絶対パスの辞書順に並ぶ。合成の強度順序ではない。上の例がそれを見せている — 強度では main.muro が最も弱い base 層で L1.muro がその上に載るが、L1main より辞書順で前に来るので、layers は逆に並べて返す。

強度順序を見たいときは koyu layers を使う。同じ二枚に対してこう出る。

Layers (weakest first — later layers are stronger):
  0	<abs>/tiny/main.muro
  1	<abs>/tiny/L1.muro

どの層がどの属性の最終値を与えたかは koyu layers --attrs が見せる。この面は MCP に無い。

見えるのは合成に参加した層だけ

import で辿り着けないファイルは返らない。ディレクトリに .muro が転がっていても、誰も import していなければ layers には現れず、check も中身を見ない。

entry 自身は必ず含まれる。


spaces

List of spaces: path, type, level, area, semi-outdoor flag, and originating layer. Optionally filtered by level

{"name": "spaces", "arguments": {"file": "<abs>/examples/two-rooms.muro"}}
引数必須中身
fileentry の .muro パス
levelレベル名。書けばそのレベルの空間だけに絞る
[
 {
  "path": "/L1/a",
  "type": "room",
  "name": "居室A",
  "level": "L1",
  "areaM2": 16.2,
  "semiOutdoor": false,
  "layer": "<abs>/examples/two-rooms.muro"
 },
 {
  "path": "/L1/b",
  "type": "room",
  "name": "居室B",
  "level": "L1",
  "areaM2": 16.2,
  "semiOutdoor": false,
  "layer": "<abs>/examples/two-rooms.muro"
 },
 {
  "path": "/out",
  "type": "exterior",
  "name": "外部",
  "semiOutdoor": false,
  "layer": "<abs>/examples/two-rooms.muro"
 }
]
フィールド中身
path空間のパス
type書かれた型 (room ldk hall exterior void …)
namename: があればその値、無ければパスの最終要素
level所属レベル。決まっていなければキーごと出ない
areaM2壁芯の床面積。領域を持たない空間ではキーごと出ない
semiOutdoor半屋外と判定されたか
layerその空間を宣言した層の絶対パス

上の /out がその両方を見せている — exterior に領域もレベルも無いので、levelareaM2 も出ない。

母集団は絞られていない。exteriorvoid も領域を持たない空間も、全部が並ぶ。屋内かどうかで数えたいなら semiOutdoortype を自分で見る。面積の合計が要るだけなら model_summary のほうが早い。

level で絞ると、外部と敷地をまたいで同じレベルの空間が並ぶ。

[
 {
  "path": "/site/garden",
  "type": "garden",
  "name": "南庭",
  "level": "L1",
  "areaM2": 41.12,
  "semiOutdoor": true,
  "layer": "<abs>/examples/house/site.muro"
 },

({"file": "<abs>/examples/house/main.muro", "level": "L1"} の返りの先頭。同じ呼び出しは 6 件を返す。)

layer は編集の宛先を決める鍵である。ここに出たパスが、そのまま write_layerlayer 引数になる。


canonical_json

The canonical JSON (machine format — one composed model, byte-stable). The ground for diffing and for external connections

{"name": "canonical_json", "arguments": {"file": "<abs>/examples/two-rooms.muro"}}

file のみ、必須。合成後の一棟を、機械が読む単一の JSON にして返す。

{
 "format": "koyu-canonical/1.0",
 "koyu": "1.0",
 "name": "二室",
 "unit": "mm",
 "grid": {
  "X": [
   0,
   3600,
   7200
  ],
  "Y": [
   0,
   4500
  ]
 },
 "levels": {
  "L1": {
   "z": 0,
   "h": 2400,
   "slab": 150
  }
 },

(先頭の抜粋。同じ呼び出しは spacesboundaries を続けて返す。)

書かれた構成だけが入る。導出された既定の壁は入らない。扉を一枚も書かない二室の例で、check"boundaries": 1 と答えるが、canonical_jsonboundaries は空である。「何が書かれたか」を数えたいときはこちらを見る。

字下げは空白 1 個で、koyu json が書くファイルとはバイト列が一致しない。MCP のツール応答はすべて空白 1 個で書かれるからである。キーの順序と値はどちらも同じなので、読み込んで比べるぶんには一致する。バイト単位で安定した形が要るときは CLI 側を使う。

関連