@womp/mcp-ui 0.1.9 → 0.1.11

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
@@ -203,10 +203,17 @@ recognises it. Where the card differs, it is because MCP differs:
203
203
  `scripts/gen-pantone.mjs <path to swan-frontend's PantoneCoatedColors.js>`;
204
204
  regenerate it if the frontend's list changes. Colour never re-quotes — it
205
205
  never changes the price.
206
- - **Hollow never orders.** Escape holes are placed in the editor, so choosing
207
- Hollow shows its price and turns the button into "Continue on womp.com",
208
- which calls `prepare_print` and opens the project. The backend refuses
209
- `hollow: true` outright; the card never sends it.
206
+ - **Hollow never orders, and since v1 is not even shown.** Escape holes are
207
+ placed in the editor, so choosing Hollow shows its price and turns the button
208
+ into "Continue on womp.com", which calls `prepare_print` and opens the
209
+ project. The backend refuses `hollow: true` outright; the card never sends it.
210
+ The whole section is driven by the quote's `hollow` row, which swan-backend
211
+ stopped publishing (`gc.mcp.printHollowPricing`, off) — so the card hides it
212
+ with no change of its own, published version included.
213
+ - **Which materials appear is the backend's call.** The tiles are the quote's
214
+ `materials` array verbatim, and swan-backend now sends only what chat sells
215
+ (`gc.mcp.printMaterials`; v1 is Clear + Tinted clear). With no Enterprise entry
216
+ in the list the disclosure below hides itself — again, no card change.
210
217
  - **Gated Enterprise materials stay visible**, with a crown, behind a
211
218
  disclosure. Tapping one keeps the current selection and shows the
212
219
  contact-sales note (the backend's `contactUrl`) — the panel's dialog, flattened.
@@ -221,6 +228,26 @@ snapped Tinted clear back to Clear on every re-quote), `materialLabel`,
221
228
  list with `swatchUrl`, `finishes`, `colorRequired` / `colorOptional`,
222
229
  `available` and `contactUrl`.
223
230
 
231
+ **The card's knob turns must be published, or the model orders the defaults.**
232
+ A card's own tool calls go host → server → iframe and never enter the
233
+ conversation, so the model's view of the print is frozen at the arguments it
234
+ opened the card with: tune it, ask for the cart in chat, and you get a 10 cm
235
+ white one. So every change (`markDirty()`, which every control already goes
236
+ through) schedules a `syncConfig()` that does two things:
237
+
238
+ - calls **`sync_print_config`** — an app-ONLY tool (`visibility: ["app"]`, kept
239
+ out of the model's tool list) that parks the selection server-side, where
240
+ `add_to_cart` and `prepare_print` read it. This is the load-bearing half.
241
+ Colour and finish changes do not re-quote, so `estimate_print` could not have
242
+ been the sync point.
243
+ - calls **`updateModelContext`** via `pushModelContext` (shared/bridge.ts),
244
+ which is the MCP Apps channel for the same fact and lets the model *talk*
245
+ about the right print. Host-gated, and Claude web was reported to drop the
246
+ payload ([claude-ai-mcp#102]), so it is a bonus, never the mechanism. The
247
+ harness advertises the capability and logs what arrives.
248
+
249
+ [claude-ai-mcp#102]: https://github.com/anthropics/claude-ai-mcp/issues/102
250
+
224
251
  **Layout trap that cost an hour:** a grid container's implicit `auto` track
225
252
  grows to its items' min-content, and a bare `<input type="number">` is ~150px
226
253
  wide intrinsically — three of them widened every row past the card's edge while
@@ -228,9 +255,16 @@ the card itself stayed 360px. Every grid in the card is
228
255
  `grid-template-columns: minmax(0, 1fr)` and the inputs have `width: 0` as their
229
256
  flex basis. If a row overflows, look there first.
230
257
 
231
- The stub takes three switches for the states a default account never shows:
258
+ The stub takes five switches for the states a default account never shows:
232
259
  `FAKE_ENTERPRISE=1` (Enterprise materials orderable), `FAKE_PRO=1` (hollow
233
- priced as available), `FAKE_REPAIRED=1` (the repaired / non-manifold callouts).
260
+ priced as available), `FAKE_REPAIRED=1` (the repaired / non-manifold callouts),
261
+ `FAKE_ALL_MATERIALS=1` (the whole catalog, i.e. before the v1 narrowing) and
262
+ `FAKE_HOLLOW=1` (quotes carry the hollow row again, which brings the card's
263
+ Solid/Hollow section back). The last two default to what swan-backend now
264
+ defaults to, so the card meets the shipped contract here.
265
+ It also keeps the last `sync_print_config` and merges it into `add_to_cart` /
266
+ `prepare_print` the way the server does — module scope, not inside
267
+ `buildServer()`, which runs per request exactly as swan-backend's does.
234
268
 
235
269
  ### The upload card sends bytes from inside the iframe
236
270
 
@@ -281,6 +315,10 @@ yarn dev # vite; opens the harness at /dev/host/index.html
281
315
 
282
316
  Two terminals, then edit `src/` and watch the card hot-reload.
283
317
 
318
+ Someone else already on :3001? `node dev/server.mjs 3002`, then open the harness
319
+ with `?mcp=http://127.0.0.1:3002/mcp` — two sessions, one checkout, no fighting
320
+ over the port.
321
+
284
322
  ### The harness (`dev/host/`)
285
323
 
286
324
  A real MCP Apps host: `AppBridge` from `@modelcontextprotocol/ext-apps`, driving
@@ -296,6 +334,7 @@ It is deliberately faithful where being unfaithful would hide a bug:
296
334
  | host style variables sent **only** over the bridge (and a toggle to withhold them) | a `var()` shipped without a fallback |
297
335
  | the card's own `get_generation` polling, proxied to a real MCP server | a running state that never resolves |
298
336
  | **"built resource" mode** — the exact HTML `resources/read` returns, in a sandboxed opaque-origin iframe | an asset `vite-plugin-singlefile` failed to inline (blank card) |
337
+ | `updateModelContext` advertised and logged, and a stub that remembers `sync_print_config` across requests | a card whose selection never leaves the iframe — press `add_to_cart` (it sends the mesh and nothing else) and read what the stub merged |
299
338
 
300
339
  `FAKE_DURATION_MS=8000 yarn dev:mcp` lengthens a fake generation, so the
301
340
  running → polling → complete transition is worth watching. The print stubs