@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.
- package/manifest.json +353 -321
- package/package.json +1 -1
- package/skills/claude-code/SKILL.md +1 -1
- package/skills/claude-code/authoring-mcp-servers/SKILL.md +1 -1
- package/skills/claude-code/building-mcp-apps/SKILL.md +1 -1
- package/skills/claude-code/connecting-apis-to-mcp/SKILL.md +1 -1
- package/skills/claude-code/creating-product-agent-guides/SKILL.md +1 -1
- package/skills/claude-code/debugging-mcp-delivery/SKILL.md +1 -1
- package/skills/claude-code/deploying-mcp-services/SKILL.md +1 -1
- package/skills/claude-code/designing-mcp-products/SKILL.md +1 -1
- package/skills/claude-code/embedding-mcp-assistants/SKILL.md +1 -1
- package/skills/claude-code/embedding-mcp-assistants/references/embedded-assistant.md +2 -0
- package/skills/claude-code/examples/acme-discovery/README.md +39 -1
- package/skills/claude-code/examples/acme-discovery/site/index.html +189 -0
- package/skills/claude-code/examples/acme-discovery/src/server.ts +12 -0
- package/skills/claude-code/examples/acme-discovery/test/server.test.ts +18 -0
- package/skills/claude-code/examples/acme-discovery/test/site-page.test.ts +50 -0
- package/skills/claude-code/executing-noodle-plans/SKILL.md +1 -1
- package/skills/claude-code/publishing-mcp-integrations/SKILL.md +1 -1
- package/skills/claude-code/references/embedded-assistant.md +2 -0
- package/skills/claude-code/reporting-noodle-feedback/SKILL.md +1 -1
- package/skills/claude-code/verifying-mcp-delivery/SKILL.md +1 -1
- package/skills/claude-code/wrapping-existing-applications/SKILL.md +1 -1
- package/skills/codex/SKILL.md +1 -1
- package/skills/codex/authoring-mcp-servers/SKILL.md +1 -1
- package/skills/codex/building-mcp-apps/SKILL.md +1 -1
- package/skills/codex/connecting-apis-to-mcp/SKILL.md +1 -1
- package/skills/codex/creating-product-agent-guides/SKILL.md +1 -1
- package/skills/codex/debugging-mcp-delivery/SKILL.md +1 -1
- package/skills/codex/deploying-mcp-services/SKILL.md +1 -1
- package/skills/codex/designing-mcp-products/SKILL.md +1 -1
- package/skills/codex/embedding-mcp-assistants/SKILL.md +1 -1
- package/skills/codex/embedding-mcp-assistants/references/embedded-assistant.md +2 -0
- package/skills/codex/examples/acme-discovery/README.md +39 -1
- package/skills/codex/examples/acme-discovery/site/index.html +189 -0
- package/skills/codex/examples/acme-discovery/src/server.ts +12 -0
- package/skills/codex/examples/acme-discovery/test/server.test.ts +18 -0
- package/skills/codex/examples/acme-discovery/test/site-page.test.ts +50 -0
- package/skills/codex/executing-noodle-plans/SKILL.md +1 -1
- package/skills/codex/publishing-mcp-integrations/SKILL.md +1 -1
- package/skills/codex/references/embedded-assistant.md +2 -0
- package/skills/codex/reporting-noodle-feedback/SKILL.md +1 -1
- package/skills/codex/verifying-mcp-delivery/SKILL.md +1 -1
- 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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
6
|
+
<!-- noodle-skill version:0.94.0 hash:379ab9f64878f1fe -->
|
|
7
7
|
|
|
8
8
|
# wrapping-existing-applications
|
|
9
9
|
|
package/skills/codex/SKILL.md
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|