@noodleseed/agent-kit 0.92.0 → 0.93.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 +349 -317
- 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/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 +5 -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/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/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 +5 -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/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
|
@@ -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,11 @@ 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 },
|
|
346
351
|
capabilities: [
|
|
347
352
|
destinations,
|
|
348
353
|
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.93.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.93.0 hash:0ccafb222038f553 -->
|
|
7
7
|
|
|
8
8
|
# publishing-mcp-integrations
|
|
9
9
|
|
|
@@ -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.93.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.93.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.93.0 hash:379ab9f64878f1fe -->
|
|
7
7
|
|
|
8
8
|
# wrapping-existing-applications
|
|
9
9
|
|