@noodleseed/agent-kit 0.14.0 → 0.15.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 (114) hide show
  1. package/manifest.json +545 -5
  2. package/package.json +1 -1
  3. package/skills/claude-code/SKILL.md +1 -1
  4. package/skills/claude-code/examples/acme-bistro/README.md +51 -0
  5. package/skills/claude-code/examples/acme-bistro/design/UX-Document.md +435 -0
  6. package/skills/claude-code/examples/acme-bistro/design/api-contract.md +161 -0
  7. package/skills/claude-code/examples/acme-bistro/design/wireframe.html +573 -0
  8. package/skills/claude-code/examples/acme-bistro/noodle.json +5 -0
  9. package/skills/claude-code/examples/acme-bistro/package.json +20 -0
  10. package/skills/claude-code/examples/acme-bistro/src/helpers.ts +7 -0
  11. package/skills/claude-code/examples/acme-bistro/src/server.ts +149 -0
  12. package/skills/claude-code/examples/acme-bistro/src/views/menu-cart.tsx +159 -0
  13. package/skills/claude-code/examples/acme-bistro/src/views/widget-style.css +228 -0
  14. package/skills/claude-code/examples/acme-bistro/test/server.test.ts +21 -0
  15. package/skills/claude-code/examples/acme-bistro/vitest.config.ts +7 -0
  16. package/skills/claude-code/examples/acme-discovery/README.md +85 -0
  17. package/skills/claude-code/examples/acme-discovery/design/UX-Document.md +441 -0
  18. package/skills/claude-code/examples/acme-discovery/design/wireframe.html +670 -0
  19. package/skills/claude-code/examples/acme-discovery/noodle.json +5 -0
  20. package/skills/claude-code/examples/acme-discovery/package.json +20 -0
  21. package/skills/claude-code/examples/acme-discovery/src/helpers.ts +7 -0
  22. package/skills/claude-code/examples/acme-discovery/src/server.ts +202 -0
  23. package/skills/claude-code/examples/acme-discovery/src/views/discovery-carousel.tsx +155 -0
  24. package/skills/claude-code/examples/acme-discovery/src/views/widget-style.css +207 -0
  25. package/skills/claude-code/examples/acme-discovery/test/server.test.ts +24 -0
  26. package/skills/claude-code/examples/acme-discovery/vitest.config.ts +7 -0
  27. package/skills/claude-code/examples/acme-tasks/README.md +80 -0
  28. package/skills/claude-code/examples/acme-tasks/design/UX-Document.md +277 -0
  29. package/skills/claude-code/examples/acme-tasks/design/wireframe.html +603 -0
  30. package/skills/claude-code/examples/acme-tasks/noodle.json +5 -0
  31. package/skills/claude-code/examples/acme-tasks/package.json +20 -0
  32. package/skills/claude-code/examples/acme-tasks/src/helpers.ts +6 -0
  33. package/skills/claude-code/examples/acme-tasks/src/server.ts +141 -0
  34. package/skills/claude-code/examples/acme-tasks/src/views/task-list.tsx +177 -0
  35. package/skills/claude-code/examples/acme-tasks/src/views/widget-style.css +227 -0
  36. package/skills/claude-code/examples/acme-tasks/test/server.test.ts +22 -0
  37. package/skills/claude-code/examples/acme-tasks/vitest.config.ts +7 -0
  38. package/skills/claude-code/examples/food-ordering/README.md +82 -0
  39. package/skills/claude-code/examples/food-ordering/noodle.json +5 -0
  40. package/skills/claude-code/examples/food-ordering/package.json +22 -0
  41. package/skills/claude-code/examples/food-ordering/src/helpers.ts +34 -0
  42. package/skills/claude-code/examples/food-ordering/src/server.ts +412 -0
  43. package/skills/claude-code/examples/food-ordering/src/views/capabilities-card.tsx +155 -0
  44. package/skills/claude-code/examples/food-ordering/src/views/ordering-flow.tsx +659 -0
  45. package/skills/claude-code/examples/food-ordering/src/views/widget-style.css +682 -0
  46. package/skills/claude-code/examples/food-ordering/test/server.test.ts +58 -0
  47. package/skills/claude-code/examples/food-ordering/vitest.config.ts +30 -0
  48. package/skills/claude-code/examples/hello/README.md +13 -0
  49. package/skills/claude-code/examples/hello/noodle.json +5 -0
  50. package/skills/claude-code/examples/hello/package.json +16 -0
  51. package/skills/claude-code/examples/hello/src/server.ts +29 -0
  52. package/skills/claude-code/examples/hello/test/server.test.ts +8 -0
  53. package/skills/claude-code/examples/weather/README.md +54 -0
  54. package/skills/claude-code/examples/weather/noodle.json +4 -0
  55. package/skills/claude-code/examples/weather/package.json +16 -0
  56. package/skills/claude-code/examples/weather/src/server.ts +190 -0
  57. package/skills/claude-code/examples/weather/test/server.test.ts +8 -0
  58. package/skills/claude-code/references/examples.md +16 -7
  59. package/skills/codex/SKILL.md +1 -1
  60. package/skills/codex/examples/acme-bistro/README.md +51 -0
  61. package/skills/codex/examples/acme-bistro/design/UX-Document.md +435 -0
  62. package/skills/codex/examples/acme-bistro/design/api-contract.md +161 -0
  63. package/skills/codex/examples/acme-bistro/design/wireframe.html +573 -0
  64. package/skills/codex/examples/acme-bistro/noodle.json +5 -0
  65. package/skills/codex/examples/acme-bistro/package.json +20 -0
  66. package/skills/codex/examples/acme-bistro/src/helpers.ts +7 -0
  67. package/skills/codex/examples/acme-bistro/src/server.ts +149 -0
  68. package/skills/codex/examples/acme-bistro/src/views/menu-cart.tsx +159 -0
  69. package/skills/codex/examples/acme-bistro/src/views/widget-style.css +228 -0
  70. package/skills/codex/examples/acme-bistro/test/server.test.ts +21 -0
  71. package/skills/codex/examples/acme-bistro/vitest.config.ts +7 -0
  72. package/skills/codex/examples/acme-discovery/README.md +85 -0
  73. package/skills/codex/examples/acme-discovery/design/UX-Document.md +441 -0
  74. package/skills/codex/examples/acme-discovery/design/wireframe.html +670 -0
  75. package/skills/codex/examples/acme-discovery/noodle.json +5 -0
  76. package/skills/codex/examples/acme-discovery/package.json +20 -0
  77. package/skills/codex/examples/acme-discovery/src/helpers.ts +7 -0
  78. package/skills/codex/examples/acme-discovery/src/server.ts +202 -0
  79. package/skills/codex/examples/acme-discovery/src/views/discovery-carousel.tsx +155 -0
  80. package/skills/codex/examples/acme-discovery/src/views/widget-style.css +207 -0
  81. package/skills/codex/examples/acme-discovery/test/server.test.ts +24 -0
  82. package/skills/codex/examples/acme-discovery/vitest.config.ts +7 -0
  83. package/skills/codex/examples/acme-tasks/README.md +80 -0
  84. package/skills/codex/examples/acme-tasks/design/UX-Document.md +277 -0
  85. package/skills/codex/examples/acme-tasks/design/wireframe.html +603 -0
  86. package/skills/codex/examples/acme-tasks/noodle.json +5 -0
  87. package/skills/codex/examples/acme-tasks/package.json +20 -0
  88. package/skills/codex/examples/acme-tasks/src/helpers.ts +6 -0
  89. package/skills/codex/examples/acme-tasks/src/server.ts +141 -0
  90. package/skills/codex/examples/acme-tasks/src/views/task-list.tsx +177 -0
  91. package/skills/codex/examples/acme-tasks/src/views/widget-style.css +227 -0
  92. package/skills/codex/examples/acme-tasks/test/server.test.ts +22 -0
  93. package/skills/codex/examples/acme-tasks/vitest.config.ts +7 -0
  94. package/skills/codex/examples/food-ordering/README.md +82 -0
  95. package/skills/codex/examples/food-ordering/noodle.json +5 -0
  96. package/skills/codex/examples/food-ordering/package.json +22 -0
  97. package/skills/codex/examples/food-ordering/src/helpers.ts +34 -0
  98. package/skills/codex/examples/food-ordering/src/server.ts +412 -0
  99. package/skills/codex/examples/food-ordering/src/views/capabilities-card.tsx +155 -0
  100. package/skills/codex/examples/food-ordering/src/views/ordering-flow.tsx +659 -0
  101. package/skills/codex/examples/food-ordering/src/views/widget-style.css +682 -0
  102. package/skills/codex/examples/food-ordering/test/server.test.ts +58 -0
  103. package/skills/codex/examples/food-ordering/vitest.config.ts +30 -0
  104. package/skills/codex/examples/hello/README.md +13 -0
  105. package/skills/codex/examples/hello/noodle.json +5 -0
  106. package/skills/codex/examples/hello/package.json +16 -0
  107. package/skills/codex/examples/hello/src/server.ts +29 -0
  108. package/skills/codex/examples/hello/test/server.test.ts +8 -0
  109. package/skills/codex/examples/weather/README.md +54 -0
  110. package/skills/codex/examples/weather/noodle.json +4 -0
  111. package/skills/codex/examples/weather/package.json +16 -0
  112. package/skills/codex/examples/weather/src/server.ts +190 -0
  113. package/skills/codex/examples/weather/test/server.test.ts +8 -0
  114. package/skills/codex/references/examples.md +16 -7
@@ -0,0 +1,30 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ resolve: {
5
+ alias: {
6
+ '@noodleseed/one': new URL('../../packages/authoring/src/index.ts', import.meta.url).pathname,
7
+ '@noodle-borg/capabilities': new URL(
8
+ '../../packages/capabilities/src/index.ts',
9
+ import.meta.url,
10
+ ).pathname,
11
+ '@noodle-borg/compiler': new URL('../../packages/compiler/src/index.ts', import.meta.url)
12
+ .pathname,
13
+ '@noodle-borg/compute': new URL('../../packages/compute/src/index.ts', import.meta.url)
14
+ .pathname,
15
+ '@noodle-borg/connector-defs': new URL(
16
+ '../../packages/connector-defs/src/index.ts',
17
+ import.meta.url,
18
+ ).pathname,
19
+ '@noodle-borg/connector-http': new URL(
20
+ '../../packages/connector-http/src/index.ts',
21
+ import.meta.url,
22
+ ).pathname,
23
+ '@noodle-borg/runtime': new URL('../../packages/runtime/src/index.ts', import.meta.url)
24
+ .pathname,
25
+ },
26
+ },
27
+ test: {
28
+ include: ['test/**/*.test.ts'],
29
+ },
30
+ });
@@ -0,0 +1,13 @@
1
+ # hello — minimal TypeScript quickstart
2
+
3
+ The smallest deployable Noodle app: a single `greet` tool authored in TypeScript with no
4
+ connectors, secrets, flows, widgets, or handoff policy. It still uses the current server options form
5
+ so new authors see where server-level branding belongs. Use it to smoke the author loop
6
+ (`noodle validate` / `noodle dev`) or a first deploy.
7
+
8
+ ```sh
9
+ noodle dev examples/hello/src/server.ts --app hello
10
+ noodle deploy examples/hello/src/server.ts --org acme --app hello
11
+ ```
12
+
13
+ It is also the fixture for `pnpm smoke:dev` and the e2e harness, so keep its tool surface stable.
@@ -0,0 +1,5 @@
1
+ {
2
+ "entrypoint": "src/server.ts",
3
+ "name": "hello",
4
+ "template": "hello"
5
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "hello",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "test": "vitest run",
8
+ "validate": "noodle validate",
9
+ "dev": "noodle dev",
10
+ "deploy": "noodle deploy"
11
+ },
12
+ "devDependencies": {
13
+ "@noodleseed/one": "latest",
14
+ "vitest": "latest"
15
+ }
16
+ }
@@ -0,0 +1,29 @@
1
+ import { server, tool, z } from '@noodleseed/one';
2
+
3
+ export default server(
4
+ 'hello',
5
+ {
6
+ title: 'Hello',
7
+ version: '1.0.0',
8
+ branding: {
9
+ name: 'Hello',
10
+ accent: '#1D9E75',
11
+ radius: 'md',
12
+ density: 'comfortable',
13
+ },
14
+ },
15
+ [
16
+ tool('greet', {
17
+ description: 'Greet someone by name.',
18
+ input: z.object({
19
+ name: z.string(),
20
+ }),
21
+ output: z.object({
22
+ message: z.string(),
23
+ }),
24
+ fulfil: ({ input }) => {
25
+ return { message: `Hello, ${input.name}!` };
26
+ },
27
+ }),
28
+ ],
29
+ );
@@ -0,0 +1,8 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import app from '../src/server.js';
3
+
4
+ describe('hello example', () => {
5
+ it('exports a Noodle server definition', () => {
6
+ expect(typeof app.toManifest).toBe('function');
7
+ });
8
+ });
@@ -0,0 +1,54 @@
1
+ # Weather Briefing
2
+
3
+ A single declarative tool that shows the runtime's breadth working together, with **no auth and no API
4
+ keys**. The `weather_briefing` tool takes a city name and runs a **three-step flow**:
5
+
6
+ Capability slots: HTTP connector authoring, ordered fulfilment flows, query/response mapping, and sandboxed
7
+ compute.
8
+
9
+ 1. **`geo.search`** → geocode the city to coordinates (Open-Meteo Geocoding API)
10
+ 2. **`forecast.current`** → fetch current weather for those coordinates (Open-Meteo Forecast API)
11
+ 3. **`brief.summarize`** → derive a human-readable briefing in a **WASM/QuickJS compute sandbox**
12
+
13
+ It exercises, in one TypeScript-authored app:
14
+
15
+ - **Server-level branding** with semantic tokens carried through the runtime artifact for any generated
16
+ app surface.
17
+ - **Ordered flow execution** with outputs threaded between steps (`${steps.geo.latitude}` → next step).
18
+ - **Two HTTP connectors on two different hosts**, each with its own egress allowlist.
19
+ - **Query parameters** (`query: [...]`) and a constant query baked into the path (`?current_weather=true`).
20
+ - **Deep response mapping** with the `${...}` language (`${response.results[0].latitude}`,
21
+ `${response.current_weather.temperature}`).
22
+ - **Sandboxed compute** (no network/fs/env/clock) turning raw numbers into conditions + advice.
23
+ - **Typed input/output schemas** emitted as JSON Schema 2020-12.
24
+
25
+ ## Run it locally
26
+
27
+ From the repo root, with the workspace built (`pnpm build`):
28
+
29
+ ```bash
30
+ : # 1. boot the local loopback dev server
31
+ node packages/cli/dist/cli.js dev examples/weather/src/server.ts --app weather
32
+
33
+ : # 2. in another shell, call the printed local endpoint
34
+ URL=http://127.0.0.1:<port>/o/local/weather/dev/mcp
35
+ curl -s "$URL" \
36
+ -H 'content-type: application/json' \
37
+ -H 'accept: application/json, text/event-stream' \
38
+ -H 'mcp-protocol-version: 2025-11-25' \
39
+ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"weather_briefing","arguments":{"city":"Paris"}}}'
40
+ ```
41
+
42
+ Example result (live data, abbreviated):
43
+
44
+ ```json
45
+ {
46
+ "place": "Paris", "country": "France",
47
+ "temperature_c": 25.1, "windspeed_kmh": 8.3,
48
+ "conditions": "overcast",
49
+ "headline": "Paris, France: 25°C, overcast.",
50
+ "advice": "Comfortable conditions — no special prep needed."
51
+ }
52
+ ```
53
+
54
+ Try other cities (`Reykjavik`, `Singapore`, `Denver`) to see the conditions and advice change.
@@ -0,0 +1,4 @@
1
+ {
2
+ "entrypoint": "src/server.ts",
3
+ "name": "weather"
4
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "weather",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "test": "vitest run",
8
+ "validate": "noodle validate",
9
+ "dev": "noodle dev",
10
+ "deploy": "noodle deploy"
11
+ },
12
+ "devDependencies": {
13
+ "@noodleseed/one": "latest",
14
+ "vitest": "latest"
15
+ }
16
+ }
@@ -0,0 +1,190 @@
1
+ import { connector, server, tool, z } from '@noodleseed/one';
2
+
3
+ // The same Weather Briefing server, authored in TypeScript with the Noodle authoring SDK.
4
+ //
5
+ // The SDK owns the *manifest*: the tool, its Zod-typed input/output schemas, and the flow — which you
6
+ // write as ordinary code in `fulfil` and the SDK records symbolically into ordered steps.
7
+ //
8
+ // HTTP and compute connectors are authored here too, so the public developer entrypoint is one
9
+ // self-contained server.ts. The SDK still compiles this to internal manifest/catalog data for the runtime.
10
+
11
+ const geocoding = connector('open_meteo_geocoding')
12
+ .version('1.0.0')
13
+ .http({
14
+ baseUrl: 'https://geocoding-api.open-meteo.com',
15
+ allowedOrigins: ['https://geocoding-api.open-meteo.com'],
16
+ operations: {
17
+ search: {
18
+ type: 'read',
19
+ method: 'GET',
20
+ path: '/v1/search',
21
+ query: ['name'],
22
+ input: { name: { type: 'string', required: true } },
23
+ output: {
24
+ latitude: { type: 'number', required: true },
25
+ longitude: { type: 'number', required: true },
26
+ place: { type: 'string' },
27
+ country: { type: 'string' },
28
+ },
29
+ response: {
30
+ latitude: '${response.results[0].latitude}',
31
+ longitude: '${response.results[0].longitude}',
32
+ place: '${response.results[0].name}',
33
+ country: '${response.results[0].country}',
34
+ },
35
+ },
36
+ },
37
+ });
38
+
39
+ const forecast = connector('open_meteo_forecast')
40
+ .version('1.0.0')
41
+ .http({
42
+ baseUrl: 'https://api.open-meteo.com',
43
+ allowedOrigins: ['https://api.open-meteo.com'],
44
+ operations: {
45
+ current: {
46
+ type: 'read',
47
+ method: 'GET',
48
+ path: '/v1/forecast?current_weather=true',
49
+ query: ['latitude', 'longitude'],
50
+ input: {
51
+ latitude: { type: 'number', required: true },
52
+ longitude: { type: 'number', required: true },
53
+ },
54
+ output: {
55
+ temperature: { type: 'number' },
56
+ windspeed: { type: 'number' },
57
+ weathercode: { type: 'number' },
58
+ },
59
+ response: {
60
+ temperature: '${response.current_weather.temperature}',
61
+ windspeed: '${response.current_weather.windspeed}',
62
+ weathercode: '${response.current_weather.weathercode}',
63
+ },
64
+ },
65
+ },
66
+ });
67
+
68
+ const brief = connector('weather_brief')
69
+ .version('1.0.0')
70
+ .compute('summarize', {
71
+ type: 'read',
72
+ input: {
73
+ place: { type: 'string', required: true },
74
+ country: { type: 'string' },
75
+ temperature: { type: 'number', required: true },
76
+ windspeed: { type: 'number', required: true },
77
+ weathercode: { type: 'number', required: true },
78
+ },
79
+ output: {
80
+ conditions: { type: 'string', required: true },
81
+ headline: { type: 'string', required: true },
82
+ advice: { type: 'string', required: true },
83
+ },
84
+ // A real function — type-checked here, serialized to source and run in the sandbox. It must be
85
+ // self-contained: no imports, no closure over outer variables, synchronous.
86
+ run: (input) => {
87
+ const codes: Record<number, string> = {
88
+ 0: 'clear sky',
89
+ 1: 'mainly clear',
90
+ 2: 'partly cloudy',
91
+ 3: 'overcast',
92
+ 45: 'fog',
93
+ 48: 'depositing rime fog',
94
+ 51: 'light drizzle',
95
+ 53: 'moderate drizzle',
96
+ 55: 'dense drizzle',
97
+ 61: 'slight rain',
98
+ 63: 'moderate rain',
99
+ 65: 'heavy rain',
100
+ 71: 'slight snow',
101
+ 73: 'moderate snow',
102
+ 75: 'heavy snow',
103
+ 77: 'snow grains',
104
+ 80: 'slight rain showers',
105
+ 81: 'moderate rain showers',
106
+ 82: 'violent rain showers',
107
+ 85: 'slight snow showers',
108
+ 86: 'heavy snow showers',
109
+ 95: 'thunderstorm',
110
+ 96: 'thunderstorm with hail',
111
+ 99: 'thunderstorm with heavy hail',
112
+ };
113
+ const code = Number(input.weathercode);
114
+ const conditions = codes[code] || 'unknown conditions';
115
+ const temp = Math.round(Number(input.temperature));
116
+ const wind = Math.round(Number(input.windspeed));
117
+ const where = input.country ? `${input.place}, ${input.country}` : input.place;
118
+ const headline = `${where}: ${temp}°C, ${conditions}.`;
119
+ const tips: string[] = [];
120
+ if (temp <= 0) tips.push("bundle up, it's freezing");
121
+ else if (temp <= 10) tips.push('wear a warm coat');
122
+ else if (temp >= 28) tips.push("stay hydrated, it's hot");
123
+ if (code >= 95) tips.push('thunderstorms expected — seek shelter');
124
+ else if (code >= 71 && code <= 86 && code !== 80 && code !== 81 && code !== 82)
125
+ tips.push('snow — dress warm and tread carefully');
126
+ else if (code >= 51 && code <= 82) tips.push('bring an umbrella');
127
+ if (wind >= 30) tips.push('expect strong winds');
128
+ const advice = tips.length
129
+ ? `${tips.join('; ')}.`
130
+ : 'Comfortable conditions — no special prep needed.';
131
+ return { conditions, headline, advice };
132
+ },
133
+ });
134
+
135
+ export default server(
136
+ 'weather_briefing',
137
+ {
138
+ title: 'Weather Briefing',
139
+ version: '1.0.0',
140
+ use: { geo: geocoding, forecast, brief },
141
+ branding: {
142
+ name: 'Weather Briefing',
143
+ accent: '#0284C7',
144
+ radius: 'md',
145
+ density: 'comfortable',
146
+ },
147
+ },
148
+ [
149
+ tool('weather_briefing', {
150
+ description:
151
+ 'Look up a city, fetch its current weather, and return a human-readable briefing. Runs a ' +
152
+ 'three-step flow: geocode the city, fetch the forecast, then derive the briefing in a sandboxed compute step.',
153
+ input: z.object({
154
+ city: z.string(),
155
+ }),
156
+ output: z.object({
157
+ place: z.string(),
158
+ country: z.string(),
159
+ temperature_c: z.number(),
160
+ windspeed_kmh: z.number(),
161
+ conditions: z.string(),
162
+ headline: z.string(),
163
+ advice: z.string(),
164
+ }),
165
+ fulfil: ({ input, connectors }) => {
166
+ const located = connectors.geo.search({ name: input.city });
167
+ const weather = connectors.forecast.current({
168
+ latitude: located.latitude,
169
+ longitude: located.longitude,
170
+ });
171
+ const briefing = connectors.brief.summarize({
172
+ place: located.place,
173
+ country: located.country,
174
+ temperature: weather.temperature,
175
+ windspeed: weather.windspeed,
176
+ weathercode: weather.weathercode,
177
+ });
178
+ return {
179
+ place: located.place,
180
+ country: located.country,
181
+ temperature_c: weather.temperature,
182
+ windspeed_kmh: weather.windspeed,
183
+ conditions: briefing.conditions,
184
+ headline: briefing.headline,
185
+ advice: briefing.advice,
186
+ };
187
+ },
188
+ }),
189
+ ],
190
+ );
@@ -0,0 +1,8 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import app from '../src/server.js';
3
+
4
+ describe('weather example', () => {
5
+ it('exports a Noodle server definition', () => {
6
+ expect(typeof app.toManifest).toBe('function');
7
+ });
8
+ });
@@ -1,15 +1,24 @@
1
1
  # Examples
2
2
 
3
- Flagship examples (one per capability). Each lives in the Noodle Seed repository under `examples/<name>/` (`server.ts`, `src/views/*.tsx`, `README.md`, and a `design/` folder for the design-first flagships). Read the matching example for the pattern you need; extend an existing flagship rather than inventing a new shape.
3
+ Flagship examples, one per capability. The **bundled** rows ship inside this skill under `examples/<name>/` (the real `server.ts`, `src/views/*.tsx`, and for the design-first flagships — a `design/` set); read them locally at the paths shown. The rest live only in the Noodle Seed repository under `examples/<name>/` on GitHub. Extend an existing flagship rather than inventing a new shape.
4
+
5
+ ## Bundled in this skill — read locally
6
+
7
+ Paths are relative to this skill directory. Assets (images/fonts) are omitted from the bundle; fetch the full runnable example from the repository if you need them. Verify any edit with `noodle validate --json` then `noodle test --json`.
8
+
9
+ | Example | Use when | Read |
10
+ | :-- | :-- | :-- |
11
+ | `hello` | Minimal TypeScript quickstart — a single tool, no connectors/widgets. | `examples/hello/src/server.ts` |
12
+ | `weather` | HTTP connectors, multi-step flows, and the sandboxed compute connector. | `examples/weather/src/server.ts` |
13
+ | `food-ordering` | Consumer ordering MCP App widgets, app-only helpers, cart state, assets, branding, and handoff. | `examples/food-ordering/src/server.ts` |
14
+ | `acme-discovery` | Top-of-funnel discovery→handoff: a discovery carousel, a `create_handoff` deep link, and a design-first UX spec + wireframe. | `examples/acme-discovery/src/server.ts` + `design/` |
15
+ | `acme-tasks` | A two-way productivity app designed around its top-3 prioritized flows (capture/prioritize/complete), with a design-first flow spec + wireframe. | `examples/acme-tasks/src/server.ts` + `design/` |
16
+ | `acme-bistro` | End-to-end ordering with a payment-only handoff; ships a gold-standard `design/` set (UX doc, wireframe with compliance audit, API contract). | `examples/acme-bistro/src/server.ts` + `design/` |
17
+
18
+ ## In the repository only — `examples/<name>/` on GitHub
4
19
 
5
20
  | Example | Use when |
6
21
  | :-- | :-- |
7
- | `hello` | Minimal TypeScript quickstart — a single tool, no connectors/widgets. |
8
- | `weather` | HTTP connectors, multi-step flows, and the sandboxed compute connector. |
9
- | `food-ordering` | Consumer ordering MCP App widgets, app-only helpers, cart state, assets, branding, and handoff. |
10
- | `acme-discovery` | Top-of-funnel discovery→handoff: a discovery carousel, a `create_handoff` deep link, and a design-first UX spec + wireframe. |
11
- | `acme-tasks` | A two-way productivity app designed around its top-3 prioritized flows (capture/prioritize/complete), with a design-first flow spec + wireframe. |
12
- | `acme-bistro` | End-to-end ordering with a payment-only handoff; ships a gold-standard `design/` set (UX doc, wireframe with compliance audit, API contract). |
13
22
  | `customer-auth` | End-user (customer) auth via OIDC/Firebase bridge with delegated credentials. |
14
23
  | `stateful-draft` | Durable, caller-scoped widget state handles with optimistic revisions. |
15
24
  | `perplexity` | A real SaaS API with bearer auth and a managed `secret`. |
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  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
- version: 0.14.0
4
+ version: 0.15.0
5
5
  hash: e623fd6ca7caad0f
6
6
  ---
7
7
 
@@ -0,0 +1,51 @@
1
+ # Acme Bistro — end-to-end ordering with payment-only handoff
2
+
3
+ A Noodle MCP App for **Acme Bistro**, a fictional restaurant. It is the flagship for the **end-to-end
4
+ transaction** pattern: the customer browses the menu and builds the order *in chat*, and the order
5
+ completes in chat — only **payment** hands off, via a signed checkout deep link (the card never touches
6
+ the app). It pairs a `toolWithWidget` menu/cart with `toolForWidget` cart helpers and a model-visible
7
+ `create_checkout` tool backed by `handoff.allowedDomains`.
8
+
9
+ Capability slot: **end-to-end in-chat transaction + payment-only handoff**, plus a worked **design-first**
10
+ deliverable set (`design/` — a UX Document, a single-file HTML wireframe with an embedded OpenAI Apps SDK
11
+ compliance audit, and a Recommended API contract). It sets the quality bar the `noodle-seed` skill's
12
+ `references/experience-design.md` and `references/chatgpt-compliance.md` teach. (Distinct from
13
+ `food-ordering`, which is the broad widget-composition proof; this one owns the design-first end-to-end +
14
+ compliance exemplar.)
15
+
16
+ ## Design deliverables (the standard to match)
17
+
18
+ - [`design/UX-Document.md`](design/UX-Document.md) — the house-style UX Document.
19
+ - [`design/wireframe.html`](design/wireframe.html) — the single-file wireframe (open in a browser) with the
20
+ embedded OpenAI Apps SDK compliance audit.
21
+ - [`design/api-contract.md`](design/api-contract.md) — the Recommended API shapes for the partner's kitchen/
22
+ ordering backend.
23
+
24
+ ## Local author loop
25
+
26
+ ```sh
27
+ noodle validate
28
+ noodle test
29
+ noodle dev
30
+ ```
31
+
32
+ In another terminal:
33
+
34
+ ```sh
35
+ noodle tools list
36
+ noodle tools call show_menu --args '{"customer":"Asha"}'
37
+ noodle tools call create_checkout --args '{"customer":"Asha","cartToken":"stone_pizzax2-lemon_tartx1","total":36}'
38
+ noodle check --target chatgpt
39
+ ```
40
+
41
+ ## Deploy
42
+
43
+ ```sh
44
+ noodle link --org demo --app acme-bistro
45
+ noodle deploy --access owner-only
46
+ noodle open
47
+ ```
48
+
49
+ This example has no connector secrets and does not include tokens, caller-key mechanisms, or
50
+ `.env.noodle` values. The menu, prices, and URLs are fictional; payment is handled off-app on
51
+ `acme.example`, never in chat.