@noodleseed/agent-kit 0.92.0 → 0.94.0

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.
Files changed (44) hide show
  1. package/manifest.json +353 -321
  2. package/package.json +1 -1
  3. package/skills/claude-code/SKILL.md +1 -1
  4. package/skills/claude-code/authoring-mcp-servers/SKILL.md +1 -1
  5. package/skills/claude-code/building-mcp-apps/SKILL.md +1 -1
  6. package/skills/claude-code/connecting-apis-to-mcp/SKILL.md +1 -1
  7. package/skills/claude-code/creating-product-agent-guides/SKILL.md +1 -1
  8. package/skills/claude-code/debugging-mcp-delivery/SKILL.md +1 -1
  9. package/skills/claude-code/deploying-mcp-services/SKILL.md +1 -1
  10. package/skills/claude-code/designing-mcp-products/SKILL.md +1 -1
  11. package/skills/claude-code/embedding-mcp-assistants/SKILL.md +1 -1
  12. package/skills/claude-code/embedding-mcp-assistants/references/embedded-assistant.md +2 -0
  13. package/skills/claude-code/examples/acme-discovery/README.md +39 -1
  14. package/skills/claude-code/examples/acme-discovery/site/index.html +189 -0
  15. package/skills/claude-code/examples/acme-discovery/src/server.ts +12 -0
  16. package/skills/claude-code/examples/acme-discovery/test/server.test.ts +18 -0
  17. package/skills/claude-code/examples/acme-discovery/test/site-page.test.ts +50 -0
  18. package/skills/claude-code/executing-noodle-plans/SKILL.md +1 -1
  19. package/skills/claude-code/publishing-mcp-integrations/SKILL.md +1 -1
  20. package/skills/claude-code/references/embedded-assistant.md +2 -0
  21. package/skills/claude-code/reporting-noodle-feedback/SKILL.md +1 -1
  22. package/skills/claude-code/verifying-mcp-delivery/SKILL.md +1 -1
  23. package/skills/claude-code/wrapping-existing-applications/SKILL.md +1 -1
  24. package/skills/codex/SKILL.md +1 -1
  25. package/skills/codex/authoring-mcp-servers/SKILL.md +1 -1
  26. package/skills/codex/building-mcp-apps/SKILL.md +1 -1
  27. package/skills/codex/connecting-apis-to-mcp/SKILL.md +1 -1
  28. package/skills/codex/creating-product-agent-guides/SKILL.md +1 -1
  29. package/skills/codex/debugging-mcp-delivery/SKILL.md +1 -1
  30. package/skills/codex/deploying-mcp-services/SKILL.md +1 -1
  31. package/skills/codex/designing-mcp-products/SKILL.md +1 -1
  32. package/skills/codex/embedding-mcp-assistants/SKILL.md +1 -1
  33. package/skills/codex/embedding-mcp-assistants/references/embedded-assistant.md +2 -0
  34. package/skills/codex/examples/acme-discovery/README.md +39 -1
  35. package/skills/codex/examples/acme-discovery/site/index.html +189 -0
  36. package/skills/codex/examples/acme-discovery/src/server.ts +12 -0
  37. package/skills/codex/examples/acme-discovery/test/server.test.ts +18 -0
  38. package/skills/codex/examples/acme-discovery/test/site-page.test.ts +50 -0
  39. package/skills/codex/executing-noodle-plans/SKILL.md +1 -1
  40. package/skills/codex/publishing-mcp-integrations/SKILL.md +1 -1
  41. package/skills/codex/references/embedded-assistant.md +2 -0
  42. package/skills/codex/reporting-noodle-feedback/SKILL.md +1 -1
  43. package/skills/codex/verifying-mcp-delivery/SKILL.md +1 -1
  44. package/skills/codex/wrapping-existing-applications/SKILL.md +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noodleseed/agent-kit",
3
- "version": "0.92.0",
3
+ "version": "0.94.0",
4
4
  "private": false,
5
5
  "description": "Self-checking, self-updating agent skills for the Noodle Seed CLI. Authored in this repo by @noodle-borg/agent-kit; this is the published, independently-versioned canonical skills artifact the CLI fetches and verifies.",
6
6
  "license": "Apache-2.0",
@@ -3,7 +3,7 @@ name: noodle-seed
3
3
  description: "Use when building, validating, testing, deploying, or operating a local or hosted Noodle Seed MCP server or app authored in TypeScript with the noodle CLI."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:13ddce01769caae4 -->
6
+ <!-- noodle-skill version:0.94.0 hash:13ddce01769caae4 -->
7
7
 
8
8
  # Noodle Seed
9
9
 
@@ -3,7 +3,7 @@ name: authoring-mcp-servers
3
3
  description: "Use when creating or extending a headless Noodle Seed MCP server, tool, resource, prompt, or typed model-facing capability."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:dd57a15df15d10b2 -->
6
+ <!-- noodle-skill version:0.94.0 hash:dd57a15df15d10b2 -->
7
7
 
8
8
  # authoring-mcp-servers
9
9
 
@@ -3,7 +3,7 @@ name: building-mcp-apps
3
3
  description: "Use when a Noodle Seed MCP App, widget, interactive card, visual interaction, or host-visible UI is the primary requested outcome."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:98c7b07c82a7d7ce -->
6
+ <!-- noodle-skill version:0.94.0 hash:98c7b07c82a7d7ce -->
7
7
 
8
8
  # building-mcp-apps
9
9
 
@@ -3,7 +3,7 @@ name: connecting-apis-to-mcp
3
3
  description: "Use when all four API-evidence inputs exist—and only then: API base URL, authentication scheme, representative safe read, and observed response."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:8020811f1769c538 -->
6
+ <!-- noodle-skill version:0.94.0 hash:8020811f1769c538 -->
7
7
 
8
8
  # connecting-apis-to-mcp
9
9
 
@@ -3,7 +3,7 @@ name: creating-product-agent-guides
3
3
  description: "Use when a Noodle Seed MCP server needs a new or revised product agent guide, App Package skill, or explicit product-skill regeneration."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:0e06e11254563b6a -->
6
+ <!-- noodle-skill version:0.94.0 hash:0e06e11254563b6a -->
7
7
 
8
8
  # creating-product-agent-guides
9
9
 
@@ -3,7 +3,7 @@ name: debugging-mcp-delivery
3
3
  description: "Use when an existing Noodle Seed MCP project has a concrete validation, runtime, connector, App, host, deployment, or production failure."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:8d75ad13f4b3120a -->
6
+ <!-- noodle-skill version:0.94.0 hash:8d75ad13f4b3120a -->
7
7
 
8
8
  # debugging-mcp-delivery
9
9
 
@@ -3,7 +3,7 @@ name: deploying-mcp-services
3
3
  description: "Use when the user explicitly requests a Noodle Seed hosted link, configuration write, deployment, access change, rollback, or connection write."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:3a1e14ff9b98ddbd -->
6
+ <!-- noodle-skill version:0.94.0 hash:3a1e14ff9b98ddbd -->
7
7
 
8
8
  # deploying-mcp-services
9
9
 
@@ -3,7 +3,7 @@ name: designing-mcp-products
3
3
  description: "Use when a Noodle Seed MCP product idea needs conversational fit, user benefit, scope, interaction, or evidence design before implementation."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:a21b2ed9997f9454 -->
6
+ <!-- noodle-skill version:0.94.0 hash:a21b2ed9997f9454 -->
7
7
 
8
8
  # designing-mcp-products
9
9
 
@@ -3,7 +3,7 @@ name: embedding-mcp-assistants
3
3
  description: "Use when embedding a Noodle assistant into an existing SaaS or web application with browser, identity, session, and credential boundaries."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:d554d661ed7ac7be -->
6
+ <!-- noodle-skill version:0.94.0 hash:d554d661ed7ac7be -->
7
7
 
8
8
  # embedding-mcp-assistants
9
9
 
@@ -197,6 +197,8 @@ Omitted UI fields retain the complete managed baseline: a bottom-center frosted
197
197
 
198
198
  Set `webmcp: { enabled: true }` on the assistant to let a browser agent reach this session's tools through the page's WebMCP API, and set it on an individual access surface to override that default in either direction — a marketing surface can opt in while a signed-in one opts out, or the reverse. Off unless set, and inert in browsers without `document.modelContext`. It governs discovery: whether the embed registers the tools this session already projects, narrowed to those that are both app-callable and model-visible. Every call executes over the same apps-bridge path the assistant's own calls take, so a browser agent gets the session's authority and nothing more, and a `confirm: true` tool still stops for a human in the panel rather than being accepted on the agent's behalf. It is not a second authorization boundary — the session is the only one. Bridge calls spend their own per-session and per-day budgets instead of model turns, and the surface's daily kill switch stops them too. Prefer this over hand-registering page-local tools that borrow the visitor's session: those carry no scoped authority, policy, or audit trail.
199
199
 
200
+ Set `continuity: { enabled: true }` on a public or mixed access surface to let an anonymous visitor keep the conversation they can see when they navigate to another page of the same site. Off unless set, and refused on an authenticated surface, which reattaches through a backend-verified sign-in instead. It restores the visible text on a fresh session and never the old one: no tool authority, no share of a spent turn budget, and no pending confirmation carried across, so an unanswered confirmation stays unanswered. `windowSeconds` defaults to 300 with a 600 ceiling, `maxRestores` to 3 with a ceiling of 10, and 0 for either disables continuity outright; an operator may lower what you declare and can never raise it. The handle lives in `sessionStorage` so it dies with the tab, is single-use, and is valid only for the embed, origin, and visitor it was issued to. Declare it when a marketing site spreads one conversation across several pages; leave it off when anonymous conversation text should not survive a navigation at all.
201
+
200
202
  Give every business action a portable `tool(..., { title: "Complete task", description: "This will mark the task complete for everyone.", input: z.object({ task: z.string().meta({ title: "Task" }) }) })` title. The standard confirmation uses the tool title/description plus schema field `title`, `description`, and `format`; it shows Confirm and Don't proceed and keeps technical action details secondary. `behavior.showConfirmationDetails` defaults to `true`; set it to `false` to remove only the built-in card's Additional details disclosure and connector mechanics. The business review and decisions remain, `confirm: true` still suspends until acceptance, and headless/BYO `data-confirmation` stays unchanged. Do not put JSON or implementation names in business-facing copy.
201
203
 
202
204
  ## Configure and deploy
@@ -7,7 +7,8 @@ deep link. It pairs a `tool` discovery carousel with a model-visible `create_han
7
7
  server-level `handoff.allowedDomains`.
8
8
 
9
9
  Capability slots: top-of-funnel funnel discipline, discovery carousel widget, `create_handoff` deep-link
10
- handoff with attribution, `handoff.allowedDomains`, the **public website assistant surface**, and a worked
10
+ handoff with attribution, `handoff.allowedDomains`, the **public website assistant surface** with its
11
+ **WebMCP browser-agent bridge** on a real demo page (`site/index.html`), and a worked
11
12
  **design-first** artifact (the UX spec + wireframe below). It shows the "design the experience, then build
12
13
  it" flow the `noodle-seed` skill's `references/experience-design.md` teaches.
13
14
 
@@ -64,6 +65,43 @@ on whichever origin the backend designates:
64
65
  The ticket spend after account creation is identical to the one after sign-in; the service never
65
66
  operates a login of its own.
66
67
 
68
+ ## Browser agents on Acme's page
69
+
70
+ `site/index.html` is the marketing page itself: static markup, four listings, and the one line a
71
+ customer pastes.
72
+
73
+ ```html
74
+ <script src="https://cloud.noodleseed.dev/v1/assistant/embed.js" data-embed-id="pub_…"></script>
75
+ ```
76
+
77
+ Because the marketing surface sets `webmcp: { enabled: true }`, that same line does a second job in a
78
+ browser that supports WebMCP: the embed registers the session's projected tools with
79
+ `document.modelContext`, so a browser agent — Gemini-in-Chrome, Claude-in-Chrome — can call
80
+ `discover_getaways` or `create_handoff` without a human typing in the panel.
81
+
82
+ What it does **not** do is widen anything. A bridged call carries exactly the embed session's
83
+ authority: the surface's six-capability allowlist, the same policy and budgets, the same audit trail,
84
+ and the same confirmation card on `capture_lead` — the visitor still approves the lead in the panel,
85
+ because a browser agent's consent is not the visitor's. The switch governs *discovery*, not
86
+ permission: it decides whether an agent learns the tools are there. The signed-in account surface
87
+ below leaves it off, which is the point of setting it per surface.
88
+
89
+ Browsers without `document.modelContext` are unaffected; the page and the panel behave exactly as
90
+ they did before.
91
+
92
+ To run it:
93
+
94
+ ```sh
95
+ noodle dev # the server, in one terminal
96
+ npx serve site # the page, in another (any static server works)
97
+ ```
98
+
99
+ `noodle dev` serves the MCP endpoint, not HTML, so the page needs its own server. For a real
100
+ end-to-end run, `noodle deploy` this example, paste the minted `pub_…` id into `site/index.html`, and
101
+ add the origin you serve the page from to the `publicWebsite` `origins` list — the session exchange
102
+ refuses any origin that is not listed. WebMCP itself ships behind an origin trial in Chrome 149+, so
103
+ a browser without the trial enabled shows the assistant panel and no bridge.
104
+
67
105
  ## The consultative sales gateway
68
106
 
69
107
  When a visitor's plans firm up but they would rather not sign up, the assistant may — with explicit
@@ -0,0 +1,189 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Acme Getaways — small-group trips</title>
7
+ <style>
8
+ :root {
9
+ --ac-teal: #0ea5a4;
10
+ --ac-ink: #0b1b1b;
11
+ --ac-slate: #234a48;
12
+ --ac-line: #e6e8ec;
13
+ }
14
+ * {
15
+ box-sizing: border-box;
16
+ }
17
+ body {
18
+ margin: 0;
19
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
20
+ background: #f4f5f7;
21
+ color: #1a1d22;
22
+ line-height: 1.55;
23
+ }
24
+ header {
25
+ background: var(--ac-ink);
26
+ color: #fff;
27
+ border-bottom: 3px solid var(--ac-teal);
28
+ padding: 34px 24px 30px;
29
+ }
30
+ header .wrap,
31
+ main {
32
+ max-width: 900px;
33
+ margin: 0 auto;
34
+ }
35
+ header h1 {
36
+ margin: 0;
37
+ font-size: 28px;
38
+ letter-spacing: -0.5px;
39
+ }
40
+ header h1 span {
41
+ color: var(--ac-teal);
42
+ }
43
+ header p {
44
+ margin: 6px 0 0;
45
+ font-size: 14px;
46
+ color: #9db3b1;
47
+ }
48
+ main {
49
+ padding: 32px 24px 96px;
50
+ }
51
+ .lede {
52
+ font-size: 16px;
53
+ color: var(--ac-slate);
54
+ margin: 0 0 28px;
55
+ max-width: 60ch;
56
+ }
57
+ .listings {
58
+ display: grid;
59
+ gap: 16px;
60
+ grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
61
+ list-style: none;
62
+ margin: 0;
63
+ padding: 0;
64
+ }
65
+ .listing {
66
+ background: #fff;
67
+ border: 1px solid var(--ac-line);
68
+ border-radius: 12px;
69
+ padding: 18px 20px;
70
+ }
71
+ .listing-name {
72
+ margin: 0;
73
+ font-size: 18px;
74
+ color: var(--ac-ink);
75
+ }
76
+ .listing-region {
77
+ margin: 2px 0 12px;
78
+ font-size: 12px;
79
+ letter-spacing: 0.6px;
80
+ text-transform: uppercase;
81
+ color: var(--ac-teal);
82
+ font-weight: 700;
83
+ }
84
+ .listing p {
85
+ margin: 0 0 12px;
86
+ font-size: 14px;
87
+ color: #4a545c;
88
+ }
89
+ .listing dl {
90
+ display: flex;
91
+ gap: 20px;
92
+ margin: 0;
93
+ font-size: 13px;
94
+ color: var(--ac-slate);
95
+ }
96
+ .listing dt {
97
+ font-size: 11px;
98
+ letter-spacing: 0.5px;
99
+ text-transform: uppercase;
100
+ color: #8a929c;
101
+ }
102
+ .listing dd {
103
+ margin: 0;
104
+ font-weight: 600;
105
+ }
106
+ footer {
107
+ border-top: 1px solid var(--ac-line);
108
+ margin-top: 40px;
109
+ padding-top: 20px;
110
+ font-size: 13px;
111
+ color: #8a929c;
112
+ }
113
+ </style>
114
+ </head>
115
+ <body>
116
+ <header>
117
+ <div class="wrap">
118
+ <h1><span>Acme</span> Getaways</h1>
119
+ <p>Small-group trips, planned in a conversation.</p>
120
+ </div>
121
+ </header>
122
+
123
+ <main>
124
+ <p class="lede">
125
+ Four places we know well. Ask the assistant in the corner to narrow them down, or let the
126
+ browser agent you already run do it for you — it can call the same tools, under the same
127
+ rules.
128
+ </p>
129
+
130
+ <ul class="listings">
131
+ <li class="listing">
132
+ <h3 class="listing-name">Coral Bay</h3>
133
+ <p class="listing-region">Adriatic coast</p>
134
+ <p>Calm swimming coves and a walkable old town — easy for a relaxed first trip.</p>
135
+ <dl>
136
+ <div><dt>From</dt><dd>$890</dd></div>
137
+ <div><dt>Best months</dt><dd>May–Sep</dd></div>
138
+ </dl>
139
+ </li>
140
+ <li class="listing">
141
+ <h3 class="listing-name">Monte Alto</h3>
142
+ <p class="listing-region">Northern Alps</p>
143
+ <p>Ski-in village with beginner slopes and long groomed runs.</p>
144
+ <dl>
145
+ <div><dt>From</dt><dd>$1,120</dd></div>
146
+ <div><dt>Best months</dt><dd>Dec–Mar</dd></div>
147
+ </dl>
148
+ </li>
149
+ <li class="listing">
150
+ <h3 class="listing-name">Old Quarter</h3>
151
+ <p class="listing-region">Central Europe</p>
152
+ <p>Dense museum district and food halls, all reachable on foot.</p>
153
+ <dl>
154
+ <div><dt>From</dt><dd>$640</dd></div>
155
+ <div><dt>Best months</dt><dd>Apr–Oct</dd></div>
156
+ </dl>
157
+ </li>
158
+ <li class="listing">
159
+ <h3 class="listing-name">Harbor City</h3>
160
+ <p class="listing-region">Pacific rim</p>
161
+ <p>Waterfront nightlife and day-trip islands a short ferry away.</p>
162
+ <dl>
163
+ <div><dt>From</dt><dd>$980</dd></div>
164
+ <div><dt>Best months</dt><dd>Sep–Nov</dd></div>
165
+ </dl>
166
+ </li>
167
+ </ul>
168
+
169
+ <footer>
170
+ A fictional brand, for demonstration. Every destination, price, and link is invented.
171
+ </footer>
172
+ </main>
173
+
174
+ <!--
175
+ The whole integration: one line, the same one a customer pastes.
176
+
177
+ The embed mounts <noodle-assistant>, mints a session against the public surface declared in
178
+ `src/server.ts`, and — because that surface sets `webmcp: { enabled: true }` — registers the
179
+ session's projected tools with `document.modelContext` where the browser offers it. A browser
180
+ agent then sees `discover_getaways`, `create_handoff`, `capture_lead` and the rest, and calling
181
+ one carries exactly this session's authority: the same allowlist, the same confirmation cards,
182
+ the same budgets and audit trail as the panel. Browsers without the API ignore all of it.
183
+
184
+ The id below is fictional. Run `noodle deploy` on this example to mint your own, paste it here,
185
+ and add this page's origin to the `publicWebsite` origins list.
186
+ -->
187
+ <script src="https://cloud.noodleseed.dev/v1/assistant/embed.js" data-embed-id="pub_examplepublicembedid00"></script>
188
+ </body>
189
+ </html>
@@ -343,6 +343,18 @@ export default server(
343
343
  access: [
344
344
  publicWebsite({
345
345
  origins: ['https://getaways.acme.example'],
346
+ // A browser agent on Acme's marketing page (Gemini-in-Chrome, Claude-in-Chrome) discovers
347
+ // exactly the capabilities listed below and reaches them over the same authorization,
348
+ // confirmation, budget, and audit path the panel's own calls take: `capture_lead` still
349
+ // stops for its confirmation card. `site/index.html` is the page this runs on.
350
+ webmcp: { enabled: true },
351
+ // A visitor who asks about Coral Bay on one page and clicks through to another would
352
+ // otherwise arrive at an empty panel and have to start over. This carries the text they
353
+ // have already read onto the next page, on a fresh session — never the old session's
354
+ // authority, budget, or a half-answered confirmation (ADR 0223). Opt-in because anonymous
355
+ // conversation text is Acme's content on Acme's page; the defaults below are deliberately
356
+ // tighter than the platform ceiling.
357
+ continuity: { enabled: true, windowSeconds: 300, maxRestores: 3 },
346
358
  capabilities: [
347
359
  destinations,
348
360
  discoverGetaways,
@@ -69,6 +69,24 @@ describe('acme-discovery example', () => {
69
69
  expect(manifest.server.assistant?.labels?.signUpAction).toBe('Create free account');
70
70
  });
71
71
 
72
+ it('opens the marketing surface to browser agents and leaves the account surface closed', async () => {
73
+ const manifest = await app.toManifest();
74
+ const surfaces = manifest.server.assistant?.surfaces ?? [];
75
+
76
+ // Both front doors, asserted by count first: without it the per-surface claims below read a
77
+ // missing surface as `undefined` and pass, so deleting a surface would silently satisfy them.
78
+ expect(surfaces).toHaveLength(2);
79
+ // ADR 0220: the opt-in governs *discovery* — whether the embed registers this session's already
80
+ // projected tools with `document.modelContext`. A browser agent on Acme's marketing page reaches
81
+ // exactly the six capabilities above, over the same authorization, confirmation, and budget path
82
+ // the panel's own calls take. `capture_lead` still stops for its confirmation card.
83
+ expect(surfaces[0]?.webmcp).toEqual({ enabled: true });
84
+ // Per-surface opt-in exists so the two front doors can answer differently, and here they do: the
85
+ // signed-in account surface carries a traveler's identity, so its tools are not advertised to
86
+ // whatever agent happens to be running in that browser.
87
+ expect(surfaces[1]?.webmcp).toBeUndefined();
88
+ });
89
+
72
90
  it('declares the grounded knowledge component and its live site scope', async () => {
73
91
  const manifest = (await app.toManifest()) as { server: { knowledge?: unknown[] } };
74
92
  // One declaration: controlled files plus the live public site, compiled later into the
@@ -0,0 +1,50 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { describe, expect, it } from 'vitest';
4
+ import app from '../src/server.js';
5
+
6
+ /**
7
+ * `site/index.html` is the demo half of the WebMCP story (ADR 0220): the marketing page a browser
8
+ * agent actually visits. The compiled server says the marketing surface opts in; only a real page
9
+ * running the real snippet shows what that buys.
10
+ *
11
+ * These guard the two properties that make the demo honest rather than the markup, which is meant to
12
+ * be edited: the page mounts the published one-liner and nothing else, and it never advertises a
13
+ * getaway the server cannot discuss.
14
+ */
15
+
16
+ const page = readFileSync(join(import.meta.dirname, '..', 'site', 'index.html'), 'utf8');
17
+
18
+ describe('the acme-discovery demo page', () => {
19
+ it('mounts the assistant with the published one-line snippet', () => {
20
+ expect(page).toContain('<script src="https://cloud.noodleseed.dev/v1/assistant/embed.js"');
21
+ expect(page).toMatch(/data-embed-id="pub_[a-z0-9]{20,64}"/u);
22
+ });
23
+
24
+ it('carries bootstrap markup only, so the page never borrows the session itself', () => {
25
+ // The bridge lives in the embed bundle, where it runs under the session's authority and budgets.
26
+ // Page-local JavaScript reaching for the same tools would carry none of that, so there is none:
27
+ // the demo's only script is the snippet above, and it has no body of its own.
28
+ expect(page.match(/<script\b/gu)).toHaveLength(1);
29
+ expect(page).toMatch(/data-embed-id="pub_[a-z0-9]{20,64}"><\/script>/u);
30
+ });
31
+
32
+ it('is a placeholder deployment, not a live embed anyone can point at', () => {
33
+ // Copying this file must not aim a stranger's page at a real deployment, so the id is fictional
34
+ // and the README says how to mint your own.
35
+ expect(page).toContain('pub_examplepublicembedid00');
36
+ expect(page).toContain('noodle deploy');
37
+ });
38
+
39
+ it('offers only getaways the server can actually discuss', async () => {
40
+ const catalog = JSON.stringify(await app.toManifest());
41
+ const offered = [...page.matchAll(/<h3 class="listing-name">([^<]+)<\/h3>/gu)].map(
42
+ (match) => match[1],
43
+ );
44
+
45
+ expect(offered.length).toBeGreaterThan(2);
46
+ for (const name of offered) {
47
+ expect(catalog, `${name} is on the page but not in the server's catalog`).toContain(name);
48
+ }
49
+ });
50
+ });
@@ -3,7 +3,7 @@ name: executing-noodle-plans
3
3
  description: "Use when the user asks to execute an approved, decision-complete implementation plan for a Noodle Seed project task by task with test-first changes, review, recovery, and final verification."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:6a9f132ddb79352e -->
6
+ <!-- noodle-skill version:0.94.0 hash:6a9f132ddb79352e -->
7
7
 
8
8
  # Execute a Noodle Seed implementation plan
9
9
 
@@ -3,7 +3,7 @@ name: publishing-mcp-integrations
3
3
  description: "Use when preparing, reviewing, or submitting a Noodle Seed MCP integration to a host or app directory."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:0ccafb222038f553 -->
6
+ <!-- noodle-skill version:0.94.0 hash:0ccafb222038f553 -->
7
7
 
8
8
  # publishing-mcp-integrations
9
9
 
@@ -197,6 +197,8 @@ Omitted UI fields retain the complete managed baseline: a bottom-center frosted
197
197
 
198
198
  Set `webmcp: { enabled: true }` on the assistant to let a browser agent reach this session's tools through the page's WebMCP API, and set it on an individual access surface to override that default in either direction — a marketing surface can opt in while a signed-in one opts out, or the reverse. Off unless set, and inert in browsers without `document.modelContext`. It governs discovery: whether the embed registers the tools this session already projects, narrowed to those that are both app-callable and model-visible. Every call executes over the same apps-bridge path the assistant's own calls take, so a browser agent gets the session's authority and nothing more, and a `confirm: true` tool still stops for a human in the panel rather than being accepted on the agent's behalf. It is not a second authorization boundary — the session is the only one. Bridge calls spend their own per-session and per-day budgets instead of model turns, and the surface's daily kill switch stops them too. Prefer this over hand-registering page-local tools that borrow the visitor's session: those carry no scoped authority, policy, or audit trail.
199
199
 
200
+ Set `continuity: { enabled: true }` on a public or mixed access surface to let an anonymous visitor keep the conversation they can see when they navigate to another page of the same site. Off unless set, and refused on an authenticated surface, which reattaches through a backend-verified sign-in instead. It restores the visible text on a fresh session and never the old one: no tool authority, no share of a spent turn budget, and no pending confirmation carried across, so an unanswered confirmation stays unanswered. `windowSeconds` defaults to 300 with a 600 ceiling, `maxRestores` to 3 with a ceiling of 10, and 0 for either disables continuity outright; an operator may lower what you declare and can never raise it. The handle lives in `sessionStorage` so it dies with the tab, is single-use, and is valid only for the embed, origin, and visitor it was issued to. Declare it when a marketing site spreads one conversation across several pages; leave it off when anonymous conversation text should not survive a navigation at all.
201
+
200
202
  Give every business action a portable `tool(..., { title: "Complete task", description: "This will mark the task complete for everyone.", input: z.object({ task: z.string().meta({ title: "Task" }) }) })` title. The standard confirmation uses the tool title/description plus schema field `title`, `description`, and `format`; it shows Confirm and Don't proceed and keeps technical action details secondary. `behavior.showConfirmationDetails` defaults to `true`; set it to `false` to remove only the built-in card's Additional details disclosure and connector mechanics. The business review and decisions remain, `confirm: true` still suspends until acceptance, and headless/BYO `data-confirmation` stays unchanged. Do not put JSON or implementation names in business-facing copy.
201
203
 
202
204
  ## Configure and deploy
@@ -3,7 +3,7 @@ name: reporting-noodle-feedback
3
3
  description: "Use when a Noodle Seed bug, misleading instruction, missing capability, or concrete product improvement should be proposed to the user."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:660cc6ad9469d90f -->
6
+ <!-- noodle-skill version:0.94.0 hash:660cc6ad9469d90f -->
7
7
 
8
8
  # reporting-noodle-feedback
9
9
 
@@ -3,7 +3,7 @@ name: verifying-mcp-delivery
3
3
  description: "Use when proving a Noodle Seed MCP project works at a named compile, local, connector, App, host, deployment, or production evidence level."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:292253cbaed9a3c5 -->
6
+ <!-- noodle-skill version:0.94.0 hash:292253cbaed9a3c5 -->
7
7
 
8
8
  # verifying-mcp-delivery
9
9
 
@@ -3,7 +3,7 @@ name: wrapping-existing-applications
3
3
  description: "Use when an existing application has no stable usable API and needs a read-only, identity-first Noodle Seed integration plan before implementation."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:379ab9f64878f1fe -->
6
+ <!-- noodle-skill version:0.94.0 hash:379ab9f64878f1fe -->
7
7
 
8
8
  # wrapping-existing-applications
9
9
 
@@ -3,7 +3,7 @@ name: noodle-seed
3
3
  description: "Use when building, validating, testing, deploying, or operating a local or hosted Noodle Seed MCP server or app authored in TypeScript with the noodle CLI."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:13ddce01769caae4 -->
6
+ <!-- noodle-skill version:0.94.0 hash:13ddce01769caae4 -->
7
7
 
8
8
  # Noodle Seed
9
9
 
@@ -3,7 +3,7 @@ name: authoring-mcp-servers
3
3
  description: "Use when creating or extending a headless Noodle Seed MCP server, tool, resource, prompt, or typed model-facing capability."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:dd57a15df15d10b2 -->
6
+ <!-- noodle-skill version:0.94.0 hash:dd57a15df15d10b2 -->
7
7
 
8
8
  # authoring-mcp-servers
9
9
 
@@ -3,7 +3,7 @@ name: building-mcp-apps
3
3
  description: "Use when a Noodle Seed MCP App, widget, interactive card, visual interaction, or host-visible UI is the primary requested outcome."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:98c7b07c82a7d7ce -->
6
+ <!-- noodle-skill version:0.94.0 hash:98c7b07c82a7d7ce -->
7
7
 
8
8
  # building-mcp-apps
9
9
 
@@ -3,7 +3,7 @@ name: connecting-apis-to-mcp
3
3
  description: "Use when all four API-evidence inputs exist—and only then: API base URL, authentication scheme, representative safe read, and observed response."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:8020811f1769c538 -->
6
+ <!-- noodle-skill version:0.94.0 hash:8020811f1769c538 -->
7
7
 
8
8
  # connecting-apis-to-mcp
9
9
 
@@ -3,7 +3,7 @@ name: creating-product-agent-guides
3
3
  description: "Use when a Noodle Seed MCP server needs a new or revised product agent guide, App Package skill, or explicit product-skill regeneration."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:0e06e11254563b6a -->
6
+ <!-- noodle-skill version:0.94.0 hash:0e06e11254563b6a -->
7
7
 
8
8
  # creating-product-agent-guides
9
9
 
@@ -3,7 +3,7 @@ name: debugging-mcp-delivery
3
3
  description: "Use when an existing Noodle Seed MCP project has a concrete validation, runtime, connector, App, host, deployment, or production failure."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:8d75ad13f4b3120a -->
6
+ <!-- noodle-skill version:0.94.0 hash:8d75ad13f4b3120a -->
7
7
 
8
8
  # debugging-mcp-delivery
9
9
 
@@ -3,7 +3,7 @@ name: deploying-mcp-services
3
3
  description: "Use when the user explicitly requests a Noodle Seed hosted link, configuration write, deployment, access change, rollback, or connection write."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:3a1e14ff9b98ddbd -->
6
+ <!-- noodle-skill version:0.94.0 hash:3a1e14ff9b98ddbd -->
7
7
 
8
8
  # deploying-mcp-services
9
9
 
@@ -3,7 +3,7 @@ name: designing-mcp-products
3
3
  description: "Use when a Noodle Seed MCP product idea needs conversational fit, user benefit, scope, interaction, or evidence design before implementation."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:a21b2ed9997f9454 -->
6
+ <!-- noodle-skill version:0.94.0 hash:a21b2ed9997f9454 -->
7
7
 
8
8
  # designing-mcp-products
9
9
 
@@ -3,7 +3,7 @@ name: embedding-mcp-assistants
3
3
  description: "Use when embedding a Noodle assistant into an existing SaaS or web application with browser, identity, session, and credential boundaries."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.92.0 hash:d554d661ed7ac7be -->
6
+ <!-- noodle-skill version:0.94.0 hash:d554d661ed7ac7be -->
7
7
 
8
8
  # embedding-mcp-assistants
9
9
 
@@ -197,6 +197,8 @@ Omitted UI fields retain the complete managed baseline: a bottom-center frosted
197
197
 
198
198
  Set `webmcp: { enabled: true }` on the assistant to let a browser agent reach this session's tools through the page's WebMCP API, and set it on an individual access surface to override that default in either direction — a marketing surface can opt in while a signed-in one opts out, or the reverse. Off unless set, and inert in browsers without `document.modelContext`. It governs discovery: whether the embed registers the tools this session already projects, narrowed to those that are both app-callable and model-visible. Every call executes over the same apps-bridge path the assistant's own calls take, so a browser agent gets the session's authority and nothing more, and a `confirm: true` tool still stops for a human in the panel rather than being accepted on the agent's behalf. It is not a second authorization boundary — the session is the only one. Bridge calls spend their own per-session and per-day budgets instead of model turns, and the surface's daily kill switch stops them too. Prefer this over hand-registering page-local tools that borrow the visitor's session: those carry no scoped authority, policy, or audit trail.
199
199
 
200
+ Set `continuity: { enabled: true }` on a public or mixed access surface to let an anonymous visitor keep the conversation they can see when they navigate to another page of the same site. Off unless set, and refused on an authenticated surface, which reattaches through a backend-verified sign-in instead. It restores the visible text on a fresh session and never the old one: no tool authority, no share of a spent turn budget, and no pending confirmation carried across, so an unanswered confirmation stays unanswered. `windowSeconds` defaults to 300 with a 600 ceiling, `maxRestores` to 3 with a ceiling of 10, and 0 for either disables continuity outright; an operator may lower what you declare and can never raise it. The handle lives in `sessionStorage` so it dies with the tab, is single-use, and is valid only for the embed, origin, and visitor it was issued to. Declare it when a marketing site spreads one conversation across several pages; leave it off when anonymous conversation text should not survive a navigation at all.
201
+
200
202
  Give every business action a portable `tool(..., { title: "Complete task", description: "This will mark the task complete for everyone.", input: z.object({ task: z.string().meta({ title: "Task" }) }) })` title. The standard confirmation uses the tool title/description plus schema field `title`, `description`, and `format`; it shows Confirm and Don't proceed and keeps technical action details secondary. `behavior.showConfirmationDetails` defaults to `true`; set it to `false` to remove only the built-in card's Additional details disclosure and connector mechanics. The business review and decisions remain, `confirm: true` still suspends until acceptance, and headless/BYO `data-confirmation` stays unchanged. Do not put JSON or implementation names in business-facing copy.
201
203
 
202
204
  ## Configure and deploy