wadi-mcp 0.1.19 → 0.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -20,7 +20,7 @@ repo; this server replaces them for agents that speak MCP.)
20
20
  | `wadi_examples` | List, or fetch the full source of, a validated example `.wdl` (`minimal` / `two_room` / `two_story` / `coastal` / `complete`). Copy from these. |
21
21
  | `wadi_reference` | The authoring docs, embedded: `guide`, `dsl`, `conventions`, `coordinate-system`, `parametric-conventions`, `roof-v2-guide`, `data-model`. |
22
22
  | `wadi_view_3d` | Load a `.wdl` into the **running Wadi desktop app's** live 3D view (so you + the user see the same model). Needs the app open. |
23
- | `wadi_capture_3d` | Render a `.wdl` in the running app and return a **real 3D image** (the textured model). Needs the app open. |
23
+ | `wadi_capture_3d` | Render a `.wdl` in the running app and return a **real 3D image** (the textured model). Choose the shot with `camera` (a named exterior angle: `iso`/`front`/`back`/`left`/`right`/`top`) or `room` (first-person interior); `isolate`/`layers` show-only or toggle layers before the shot (by id or label). The response lists the house's layers so you can refine. Needs the app open. |
24
24
 
25
25
  The last two reach the desktop app over a localhost bridge (`127.0.0.1:8765`, override
26
26
  `WADI_APP_PORT`); when the app isn't running they return a "open the Wadi app" message and
package/dist/server.mjs CHANGED
@@ -419128,7 +419128,7 @@ async function appCapture(config3, view) {
419128
419128
  if (!r2.ok) throw new Error(`app /capture returned ${r2.status}`);
419129
419129
  const j = await r2.json();
419130
419130
  if (!j.ok || !j.png) throw new Error(j.error || "capture failed");
419131
- return { data: j.png, mime: j.mime || "image/jpeg" };
419131
+ return { data: j.png, mime: j.mime || "image/jpeg", layers: j.layers };
419132
419132
  }
419133
419133
  var APP_NOT_RUNNING = "The Wadi desktop app isn't running, so live 3D isn't available. Open the Wadi app (it serves the bridge on 127.0.0.1:" + PORT + "), or use `wadi_preview` for headless 2D drawings (plans / elevations / roof).";
419134
419134
 
@@ -419234,14 +419234,17 @@ server.registerTool(
419234
419234
  "wadi_capture_3d",
419235
419235
  {
419236
419236
  title: "Capture a 3D image of a Wadi design",
419237
- description: 'Render a Wadi DSL house in the RUNNING Wadi desktop app and return a real 3D PNG \u2014 the actual textured model, not a 2D drawing. Requires the Wadi app to be open. Pass `room` (a room name from the .wdl, e.g. "Bedroom") to place the camera INSIDE that room for a first-person look \u2014 the best way to check FURNITURE PLACEMENT and ORIENTATION, which a plan can\'t show. Omit `room` for the outside orbit view. The PNG is BOTH returned inline AND written to a file whose path is in the text. (Headless 2D plans/elevations/roof: wadi_preview.)',
419237
+ description: 'Render a Wadi DSL house in the RUNNING Wadi desktop app and return a real 3D PNG \u2014 the actual textured model, not a 2D drawing. Requires the Wadi app to be open.\nCAMERA: pass `room` (a room name, e.g. "Bedroom") for a first-person INTERIOR look (best for checking furniture placement/orientation), OR `camera` for a named EXTERIOR angle (iso | front | back | left | right | top). Omit both for the current outside orbit.\nLAYERS: pass `isolate` (a list of layer ids/labels) to show ONLY those, or `layers` (a map of id/label \u2192 on/off) to toggle specific ones \u2014 e.g. isolate the structure to shoot the frame, or hide the roof to see the plan of walls. The response lists every available layer (id + label) so you can refine a follow-up shot. Layer changes are restored after the capture.\nThe PNG is BOTH returned inline AND written to a file whose path is in the text. (Headless 2D plans/elevations/roof: wadi_preview.)',
419238
419238
  inputSchema: {
419239
419239
  wdl: external_exports.string().describe("The full .wdl source text."),
419240
- room: external_exports.string().optional().describe("A room name (as written in the .wdl) to view from inside. Omit for the outside orbit view."),
419240
+ room: external_exports.string().optional().describe("A room name (as written in the .wdl) to view from INSIDE (first-person). Takes precedence over `camera`."),
419241
+ camera: external_exports.enum(["iso", "front", "back", "left", "right", "top"]).optional().describe("A named EXTERIOR camera angle. Ignored if `room` is given. Omit for the current outside orbit."),
419242
+ isolate: external_exports.array(external_exports.string()).optional().describe("Show ONLY these layers (ids or labels, case-insensitive); hide all others. See the returned layer list."),
419243
+ layers: external_exports.record(external_exports.string(), external_exports.boolean()).optional().describe('Toggle specific layers by id or label, e.g. { "Roof": false, "Structure": true }.'),
419241
419244
  out_dir: external_exports.string().optional().describe("Absolute directory to save the PNG to. Default: the OS temp dir. The saved path is returned in the text.")
419242
419245
  }
419243
419246
  },
419244
- async ({ wdl, room: room3, out_dir }) => {
419247
+ async ({ wdl, room: room3, camera, isolate, layers, out_dir }) => {
419245
419248
  let config3;
419246
419249
  try {
419247
419250
  config3 = compileConfig(wdl);
@@ -419250,12 +419253,17 @@ server.registerTool(
419250
419253
  }
419251
419254
  if (!await appReachable()) return { content: [{ type: "text", text: APP_NOT_RUNNING }] };
419252
419255
  try {
419253
- const img = await appCapture(config3, room3 ? { room: room3 } : void 0);
419254
- const file2 = savePng(Buffer.from(img.data, "base64"), out_dir, room3 ? `wadi_3d_${room3.replace(/\W+/g, "_")}.png` : "wadi_3d.png");
419255
- const label = room3 ? `3D interior view of "${room3}" (from the live app)` : "3D view (from the live app)";
419256
+ const view = { room: room3, camera, isolate, layers };
419257
+ const hasView = room3 || camera || isolate?.length || layers && Object.keys(layers).length;
419258
+ const img = await appCapture(config3, hasView ? view : void 0);
419259
+ const slug = room3 ? `wadi_3d_${room3.replace(/\W+/g, "_")}` : camera ? `wadi_3d_${camera}` : "wadi_3d";
419260
+ const file2 = savePng(Buffer.from(img.data, "base64"), out_dir, `${slug}.png`);
419261
+ const label = room3 ? `3D interior view of "${room3}"` : camera ? `3D exterior view (${camera})` : "3D view (outside orbit)";
419262
+ const shown = isolate?.length ? ` \xB7 showing only: ${isolate.join(", ")}` : "";
419263
+ const layerList = img.layers?.length ? "\nAvailable layers (id \u2014 label): " + img.layers.map((l) => `${l.id} \u2014 ${l.label}`).join(" \xB7 ") + "\nPass `isolate` or `layers` (id or label) to control what's visible." : "";
419256
419264
  return {
419257
419265
  content: [
419258
- { type: "text", text: `\u2014 ${label} \u2014 saved to: ${file2}` },
419266
+ { type: "text", text: `\u2014 ${label}${shown} (from the live app) \u2014 saved to: ${file2}${layerList}` },
419259
419267
  { type: "image", data: img.data, mimeType: img.mime }
419260
419268
  ]
419261
419269
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wadi-mcp",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "description": "MCP server for the Wadi house designer — check, preview, and reference the Wadi DSL (.wdl) without the repo.",
5
5
  "type": "module",
6
6
  "license": "MIT",