@noodleseed/agent-kit 0.68.0 → 0.70.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 +325 -277
- 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 +1 -1
- package/skills/claude-code/examples/acme-discovery/src/knowledge/faq.txt +10 -0
- package/skills/claude-code/examples/acme-discovery/src/knowledge/product.md +7 -0
- package/skills/claude-code/examples/acme-discovery/src/server.ts +28 -2
- package/skills/claude-code/examples/acme-discovery/test/server.test.ts +10 -0
- package/skills/claude-code/examples/food-ordering/README.md +79 -10
- package/skills/claude-code/examples/food-ordering/src/agent-guide.ts +48 -0
- package/skills/claude-code/examples/food-ordering/src/server.ts +112 -0
- package/skills/claude-code/examples/food-ordering/test/server.test.ts +48 -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/authoring-workflow.md +20 -0
- package/skills/claude-code/references/cli-commands.md +1 -1
- package/skills/claude-code/references/compile-errors.md +2 -0
- package/skills/claude-code/references/embedded-assistant.md +13 -3
- package/skills/claude-code/references/product-agent-guides.md +2 -2
- package/skills/claude-code/references/publishing.md +18 -1
- package/skills/claude-code/references/sdk-surface.md +4 -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 +1 -1
- package/skills/codex/examples/acme-discovery/src/knowledge/faq.txt +10 -0
- package/skills/codex/examples/acme-discovery/src/knowledge/product.md +7 -0
- package/skills/codex/examples/acme-discovery/src/server.ts +28 -2
- package/skills/codex/examples/acme-discovery/test/server.test.ts +10 -0
- package/skills/codex/examples/food-ordering/README.md +79 -10
- package/skills/codex/examples/food-ordering/src/agent-guide.ts +48 -0
- package/skills/codex/examples/food-ordering/src/server.ts +112 -0
- package/skills/codex/examples/food-ordering/test/server.test.ts +48 -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/authoring-workflow.md +20 -0
- package/skills/codex/references/cli-commands.md +1 -1
- package/skills/codex/references/compile-errors.md +2 -0
- package/skills/codex/references/embedded-assistant.md +13 -3
- package/skills/codex/references/product-agent-guides.md +2 -2
- package/skills/codex/references/publishing.md +18 -1
- package/skills/codex/references/sdk-surface.md +4 -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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noodleseed/agent-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.70.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.70.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.70.0 hash:11523cb33b9473c0 -->
|
|
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.70.0 hash:9fd67d4d24328e15 -->
|
|
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.70.0 hash:21bbd3ec441ffd30 -->
|
|
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.70.0 hash:0fa48a82fe836cf0 -->
|
|
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.70.0 hash:aa715bae12041d7c -->
|
|
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.70.0 hash:93e735b7ffb45df1 -->
|
|
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.70.0 hash:78a6f181b61f92f1 -->
|
|
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.70.0 hash:cc54a67f21c0ecdb -->
|
|
7
7
|
|
|
8
8
|
# embedding-mcp-assistants
|
|
9
9
|
|
|
@@ -28,7 +28,7 @@ There is no second tool set and no second app — one `server.ts`, projected ont
|
|
|
28
28
|
and closed by default: a tool added to this server later is unreachable from the website until someone
|
|
29
29
|
lists it. A tool that needed a signed-in user could not be listed here at all (the compiler rejects it);
|
|
30
30
|
serve those from `authenticatedWebsite({ origins })` instead, where Acme's own backend proves who the
|
|
31
|
-
visitor is
|
|
31
|
+
visitor is, or add `signIn: true` so visitors sign in mid-conversation through Acme own login.
|
|
32
32
|
|
|
33
33
|
## Design spec (write this before the code)
|
|
34
34
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
ACME GETAWAYS FAQ
|
|
2
|
+
|
|
3
|
+
Q: Does the assistant book and take payment?
|
|
4
|
+
A: No. The assistant shapes the trip and hands off to Acmes own checkout with a signed link.
|
|
5
|
+
|
|
6
|
+
Q: How current are prices?
|
|
7
|
+
A: Starting prices come from Acmes live site; the assistant cites the page it used.
|
|
8
|
+
|
|
9
|
+
Q: Can I compare destinations?
|
|
10
|
+
A: Yes, ask for a shortlist by vibe, month, or budget.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Acme Getaways product guide
|
|
2
|
+
|
|
3
|
+
Acme Getaways curates four destination types: beach, mountains, culture, and city escapes. Every listing shows a real starting price and the best months to travel. Bookings, payments, and date selection happen on Acmes own site through a signed handoff link; the assistant never takes payment details.
|
|
4
|
+
|
|
5
|
+
## Cancellation and support
|
|
6
|
+
|
|
7
|
+
All trips can be cancelled free within 48 hours of the handoff. Support runs seven days a week through the chat on book.acme.example.
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
annotations,
|
|
3
3
|
embeddedAssistant,
|
|
4
|
+
file,
|
|
5
|
+
knowledge,
|
|
4
6
|
openAICompatible,
|
|
5
7
|
publicWebsite,
|
|
6
8
|
secret,
|
|
7
9
|
server,
|
|
10
|
+
site,
|
|
8
11
|
tool,
|
|
9
12
|
variable,
|
|
10
13
|
z,
|
|
@@ -196,6 +199,27 @@ const shortlistGetaway = tool('shortlist_getaway', {
|
|
|
196
199
|
}),
|
|
197
200
|
});
|
|
198
201
|
|
|
202
|
+
// Grounding beyond the catalog: two controlled files answer policy/pricing/support questions with
|
|
203
|
+
// citations, and Acme's live public site stays current through its search provider — no sync job,
|
|
204
|
+
// no handwritten search tool. One declaration, one generated `search_destinations` capability.
|
|
205
|
+
const destinations = knowledge('destinations', {
|
|
206
|
+
title: 'Acme Getaways destinations',
|
|
207
|
+
description: 'Public destination, pricing, cancellation, and support information.',
|
|
208
|
+
documents: [
|
|
209
|
+
file('./knowledge/product.md', {
|
|
210
|
+
title: 'Product guide',
|
|
211
|
+
sourceUrl: 'https://getaways.acme.example/product',
|
|
212
|
+
}),
|
|
213
|
+
file('./knowledge/faq.txt', { title: 'FAQ' }),
|
|
214
|
+
],
|
|
215
|
+
sites: [
|
|
216
|
+
site({
|
|
217
|
+
origin: 'https://getaways.acme.example',
|
|
218
|
+
include: ['/destinations/**', '/pricing', '/support'],
|
|
219
|
+
}),
|
|
220
|
+
],
|
|
221
|
+
});
|
|
222
|
+
|
|
199
223
|
export default server(
|
|
200
224
|
'acme_discovery',
|
|
201
225
|
{
|
|
@@ -217,7 +241,8 @@ export default server(
|
|
|
217
241
|
// The same three tools also serve Acme's own marketing site, with no second tool set and no
|
|
218
242
|
// session backend: a visitor with no account gets the discovery carousel and the booking
|
|
219
243
|
// handoff. `capabilities` is the whole externally reachable surface — short enough to review in
|
|
220
|
-
// one glance, and closed by default when a tool is added to the server later.
|
|
244
|
+
// one glance, and closed by default when a tool is added to the server later. The knowledge
|
|
245
|
+
// component projects its generated search capability the same way a tool does.
|
|
221
246
|
assistant: embeddedAssistant({
|
|
222
247
|
model: openAICompatible({
|
|
223
248
|
baseUrl: variable('ASSISTANT_MODEL_BASE_URL'),
|
|
@@ -226,11 +251,12 @@ export default server(
|
|
|
226
251
|
}),
|
|
227
252
|
access: publicWebsite({
|
|
228
253
|
origins: ['https://getaways.acme.example'],
|
|
229
|
-
capabilities: [discoverGetaways, createHandoff, shortlistGetaway],
|
|
254
|
+
capabilities: [destinations, discoverGetaways, createHandoff, shortlistGetaway],
|
|
230
255
|
}),
|
|
231
256
|
layout: { mode: 'floating', position: 'bottom-right' },
|
|
232
257
|
labels: { welcomeHeading: 'Where would you like to go?' },
|
|
233
258
|
}),
|
|
259
|
+
knowledge: [destinations],
|
|
234
260
|
},
|
|
235
261
|
[discoverGetaways, createHandoff, shortlistGetaway],
|
|
236
262
|
);
|
|
@@ -21,4 +21,14 @@ describe('acme-discovery example', () => {
|
|
|
21
21
|
expect(text).toContain('create_handoff');
|
|
22
22
|
expect(text).toContain('shortlist_getaway');
|
|
23
23
|
});
|
|
24
|
+
|
|
25
|
+
it('declares the grounded knowledge component and its live site scope', async () => {
|
|
26
|
+
const manifest = (await app.toManifest()) as { server: { knowledge?: unknown[] } };
|
|
27
|
+
// One declaration: controlled files plus the live public site, compiled later into the
|
|
28
|
+
// generated `search_destinations` capability with citations.
|
|
29
|
+
expect(manifest.server.knowledge).toHaveLength(1);
|
|
30
|
+
const text = JSON.stringify(manifest);
|
|
31
|
+
expect(text).toContain('knowledge/product.md');
|
|
32
|
+
expect(text).toContain('https://getaways.acme.example');
|
|
33
|
+
});
|
|
24
34
|
});
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
**Owns:** The flagship consumer ordering MCP App example: React view authoring, app-only helper tools,
|
|
4
4
|
caller-scoped cart state handles, invocation context, model-visible widget state/lifecycle, packaged image
|
|
5
5
|
assets, portable structured elicitation, checkout handoff policy, host actions, CSP/permissions metadata,
|
|
6
|
-
and widget preview coverage.
|
|
6
|
+
product-agent guidance, host-neutral distribution metadata, and widget preview coverage.
|
|
7
7
|
|
|
8
8
|
Food Ordering is a generic, synthetic version of a live marketplace ordering app. It lets a user search
|
|
9
9
|
stores, browse menus, customize an item, build a multi-line cart, review the order, and hand off checkout to
|
|
@@ -15,6 +15,7 @@ private customer data.
|
|
|
15
15
|
| Capability | Example |
|
|
16
16
|
| :--- | :--- |
|
|
17
17
|
| Public entry tool | `open_ordering` returns structured fallback content and renders the React widget |
|
|
18
|
+
| Product and distribution projections | `agentGuide` supplies grounded cross-capability guidance; `distribution` supplies listing, publisher, legal, image, and review facts separately from the runtime manifest |
|
|
18
19
|
| App-only helper tools | `search_stores`, `load_menu`, `load_item`, `read_cart`, `sync_cart`, `prepare_checkout`; mutating widget-owned helpers use `confirm: false` (equivalent to omission) and execute directly because action hints alone never gate |
|
|
19
20
|
| Durable cart state | `server(..., { state: { handles: { cart } }, use: { state } })` with caller scope and revision checks |
|
|
20
21
|
| React app runtime kit | `@noodleseed/one/react` supplies app flow, shell/nav/view, async state, form, quantity, choice, and handoff primitives |
|
|
@@ -47,6 +48,11 @@ noodle test
|
|
|
47
48
|
noodle dev
|
|
48
49
|
```
|
|
49
50
|
|
|
51
|
+
The same `server.ts` declares `distribution` metadata for host adapters. It references real packaged images
|
|
52
|
+
and keeps listing copy, support/legal URLs, and positive/negative review scenarios outside the canonical App
|
|
53
|
+
Package and Runtime Artifact. Explicit OpenAI and Claude adapters project those facts with the generated
|
|
54
|
+
product skill; installable plugin archives and directory-submission dossiers remain separate outputs.
|
|
55
|
+
|
|
50
56
|
In another terminal:
|
|
51
57
|
|
|
52
58
|
```sh
|
|
@@ -71,6 +77,65 @@ For Apps metadata conformance, start `noodle dev`, copy the loopback MCP endpoin
|
|
|
71
77
|
npx @mcpjam/cli@latest apps conformance --url http://127.0.0.1:<port>/o/demo/food-ordering/mcp --quiet --format json
|
|
72
78
|
```
|
|
73
79
|
|
|
80
|
+
## Export an OpenAI plugin
|
|
81
|
+
|
|
82
|
+
This flagship includes the guided workflows, listing metadata, review cases, and image assets needed to test
|
|
83
|
+
OpenAI export. See the public [product-agent guide](https://docs.noodleseed.dev/docs/guides/product-agent-guides#export-an-openai-package)
|
|
84
|
+
for the current package workflow and boundaries.
|
|
85
|
+
|
|
86
|
+
Against its deployed MCP URL, generate the Food Ordering submission candidate with:
|
|
87
|
+
|
|
88
|
+
```sh
|
|
89
|
+
noodle export plugin openai \
|
|
90
|
+
--state submission \
|
|
91
|
+
--mcp-url https://food-ordering.noodleseed.app/mcp \
|
|
92
|
+
--category "Food & Drink" \
|
|
93
|
+
--output food-ordering-openai.zip
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Extract `food-ordering-openai.zip` before using the portal. Upload
|
|
97
|
+
`submission/chatgpt-app-submission.json` to the Codex-assisted import field and
|
|
98
|
+
`submission/food-ordering-skill.zip` to **With MCP → Skills**. The outer ZIP is the complete review kit and
|
|
99
|
+
is not itself a valid skill upload; `submission/README.md` repeats the portal steps.
|
|
100
|
+
|
|
101
|
+
After registering that same URL in ChatGPT developer mode, substitute its real technical ID to generate the
|
|
102
|
+
Food Ordering local test package:
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
noodle export plugin openai \
|
|
106
|
+
--state local \
|
|
107
|
+
--mcp-url https://food-ordering.noodleseed.app/mcp \
|
|
108
|
+
--category "Food & Drink" \
|
|
109
|
+
--registered-app-id plugin_asdk_app_0123456789abcdef0123456789abcdef \
|
|
110
|
+
--output food-ordering-openai-local.zip
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Export for Claude
|
|
114
|
+
|
|
115
|
+
Claude Code plugin packaging and Anthropic Connector Directory review are separate outputs. Generate the
|
|
116
|
+
installable plugin repository with:
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
noodle export plugin claude \
|
|
120
|
+
--mcp-url https://food-ordering.noodleseed.app/mcp \
|
|
121
|
+
--output food-ordering-claude.zip
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Generate the credential-free operator dossier for the remote Connector Directory with:
|
|
125
|
+
|
|
126
|
+
```sh
|
|
127
|
+
noodle export connector claude \
|
|
128
|
+
--mcp-url https://food-ordering.noodleseed.app/mcp \
|
|
129
|
+
--auth none \
|
|
130
|
+
--category "Food & Drink" \
|
|
131
|
+
--output food-ordering-anthropic-connector.zip
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The dossier is deliberately marked `portalUploadable: false`: it gathers the listing, tool annotations,
|
|
135
|
+
use cases, allowed-link candidates, test-account guidance, and MCP App screenshot evidence, but a human must
|
|
136
|
+
verify ownership/compliance and enter the final answers in Anthropic's portal. The plugin ZIP does not
|
|
137
|
+
contain this dossier.
|
|
138
|
+
|
|
74
139
|
## Client Setup
|
|
75
140
|
|
|
76
141
|
Use the CLI to print the exact setup flow for your MCP client:
|
|
@@ -95,17 +160,21 @@ connector secrets and does not include tokens, caller-key mechanisms, or `.env.n
|
|
|
95
160
|
|
|
96
161
|
## Demo Assets
|
|
97
162
|
|
|
98
|
-
The packaged demo images live under `assets
|
|
99
|
-
|
|
163
|
+
The packaged demo images live under `assets/`. The current app uses `assets/noodle-bowl.jpg` as the server
|
|
164
|
+
branding image. Its three distribution screenshots are real, response-only MCP App captures from Noodle
|
|
165
|
+
Devtools at 2× device scale; each is 1640×970 PNG and has the producing user prompt next to its `asset(...)`
|
|
166
|
+
reference in `server.ts`.
|
|
100
167
|
|
|
101
168
|
Image sources:
|
|
102
169
|
|
|
103
170
|
- `assets/noodle-bowl.jpg` — Unsplash photo
|
|
104
171
|
[`IRv8V9Hb8gI`](https://unsplash.com/photos/IRv8V9Hb8gI), downloaded from Unsplash.
|
|
105
|
-
- `assets/
|
|
106
|
-
|
|
107
|
-
- `assets/
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
172
|
+
- `assets/food-ordering-stores.png` — store-discovery state produced by “Help me build a noodle order for
|
|
173
|
+
pickup.”
|
|
174
|
+
- `assets/food-ordering-menu.png` — Harbor Noodles menu state produced by “Show me the Harbor Noodles
|
|
175
|
+
menu.”
|
|
176
|
+
- `assets/food-ordering-handoff.png` — checkout-handoff state produced by “Review my spicy miso bowl order
|
|
177
|
+
before checkout.”
|
|
178
|
+
|
|
179
|
+
The Unsplash branding photo is free to use under the [Unsplash License](https://unsplash.com/license);
|
|
180
|
+
attribution is not required, but the source note is kept here for provenance.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { AgentGuideSource } from '@noodleseed/one';
|
|
2
|
+
|
|
3
|
+
/** Product guidance for the model-visible ordering and planning workflows. */
|
|
4
|
+
export const FOOD_ORDERING_AGENT_GUIDE = {
|
|
5
|
+
description:
|
|
6
|
+
'Use Food Ordering to browse synthetic local options, build a reviewable cart, and hand checkout to the user.',
|
|
7
|
+
useWhen: [
|
|
8
|
+
'The user wants to browse nearby food or assemble an order.',
|
|
9
|
+
'The user wants a structured pickup or delivery plan before ordering.',
|
|
10
|
+
],
|
|
11
|
+
workflows: [
|
|
12
|
+
{
|
|
13
|
+
id: 'build_order',
|
|
14
|
+
title: 'Browse and build an order',
|
|
15
|
+
steps: [
|
|
16
|
+
{
|
|
17
|
+
capability: { kind: 'tool', name: 'open_ordering' },
|
|
18
|
+
guidance:
|
|
19
|
+
'Open the ordering app so the user can choose a store, review the cart, and control checkout handoff.',
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: 'summarize_options',
|
|
25
|
+
title: 'Summarize available options',
|
|
26
|
+
steps: [{ capability: { kind: 'tool', name: 'summarize_ordering_options' } }],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: 'plan_fulfilment',
|
|
30
|
+
title: 'Plan pickup or delivery',
|
|
31
|
+
steps: [
|
|
32
|
+
{
|
|
33
|
+
capability: { kind: 'tool', name: 'plan_order' },
|
|
34
|
+
guidance: 'Collect the user’s fulfilment preference without claiming to place an order.',
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
boundaries: [
|
|
40
|
+
'Treat every store, menu item, price, and service area in this example as synthetic.',
|
|
41
|
+
'Never claim checkout or payment completed; the final order happens only after the external handoff.',
|
|
42
|
+
],
|
|
43
|
+
examples: [
|
|
44
|
+
{ prompt: 'Help me put together a noodle order.', workflow: 'build_order' },
|
|
45
|
+
{ prompt: 'What food options are available?', workflow: 'summarize_options' },
|
|
46
|
+
{ prompt: 'Plan a delivery for Friday.', workflow: 'plan_fulfilment' },
|
|
47
|
+
],
|
|
48
|
+
} as const satisfies AgentGuideSource;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { annotations, asset, connector, resource, server, tool, z } from '@noodleseed/one';
|
|
2
|
+
import { FOOD_ORDERING_AGENT_GUIDE } from './agent-guide.js';
|
|
2
3
|
|
|
3
4
|
const heroImage = asset('assets/noodle-bowl.jpg');
|
|
5
|
+
const storesScreenshot = asset('assets/food-ordering-stores.png');
|
|
6
|
+
const menuScreenshot = asset('assets/food-ordering-menu.png');
|
|
7
|
+
const handoffScreenshot = asset('assets/food-ordering-handoff.png');
|
|
4
8
|
|
|
5
9
|
const state = connector('noodle_state')
|
|
6
10
|
.version('1.0.0')
|
|
@@ -202,6 +206,108 @@ export default server(
|
|
|
202
206
|
{
|
|
203
207
|
title: 'Food Ordering',
|
|
204
208
|
version: '1.0.0',
|
|
209
|
+
agentGuide: FOOD_ORDERING_AGENT_GUIDE,
|
|
210
|
+
distribution: {
|
|
211
|
+
listing: {
|
|
212
|
+
summary: 'Build a pickup noodle order.',
|
|
213
|
+
description:
|
|
214
|
+
'Food Ordering is a synthetic MCP App that demonstrates store discovery, menu browsing, a caller-scoped cart, fulfilment planning, and explicit checkout handoff.',
|
|
215
|
+
keywords: ['food', 'ordering', 'delivery'],
|
|
216
|
+
},
|
|
217
|
+
publisher: {
|
|
218
|
+
name: 'Noodle Seed Examples',
|
|
219
|
+
websiteUrl: 'https://noodleseed.com',
|
|
220
|
+
},
|
|
221
|
+
support: {
|
|
222
|
+
documentationUrl: 'https://docs.noodleseed.com/examples/food-ordering',
|
|
223
|
+
supportUrl: 'https://noodleseed.com/support',
|
|
224
|
+
},
|
|
225
|
+
legal: {
|
|
226
|
+
privacyPolicyUrl: 'https://noodleseed.com/privacy',
|
|
227
|
+
termsOfServiceUrl: 'https://noodleseed.com/terms',
|
|
228
|
+
},
|
|
229
|
+
assets: {
|
|
230
|
+
icon: { source: heroImage, alt: 'Food Ordering noodle bowl' },
|
|
231
|
+
screenshots: [
|
|
232
|
+
{
|
|
233
|
+
source: storesScreenshot,
|
|
234
|
+
alt: 'Food Ordering MCP App showing nearby stores',
|
|
235
|
+
prompt: 'Help me build a noodle order for pickup.',
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
source: menuScreenshot,
|
|
239
|
+
alt: 'Food Ordering MCP App showing the Harbor Noodles menu',
|
|
240
|
+
prompt: 'Show me the Harbor Noodles menu.',
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
source: handoffScreenshot,
|
|
244
|
+
alt: 'Food Ordering MCP App reviewing a checkout handoff',
|
|
245
|
+
prompt: 'Review my spicy miso bowl order before checkout.',
|
|
246
|
+
},
|
|
247
|
+
],
|
|
248
|
+
},
|
|
249
|
+
review: {
|
|
250
|
+
instructions:
|
|
251
|
+
'Use the synthetic menu and guest cart. No account or reviewer credential is required.',
|
|
252
|
+
scenarios: [
|
|
253
|
+
{
|
|
254
|
+
id: 'build_order',
|
|
255
|
+
prompt: 'Help me build a noodle order for pickup.',
|
|
256
|
+
expected:
|
|
257
|
+
'The ordering app opens with stores and menu items; checkout remains a handoff.',
|
|
258
|
+
shouldInvoke: true,
|
|
259
|
+
tools: ['open_ordering'],
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
id: 'browse_menu',
|
|
263
|
+
prompt: 'Show me vegetarian menu options nearby.',
|
|
264
|
+
expected: 'The app shows matching stores and bounded menu choices.',
|
|
265
|
+
shouldInvoke: true,
|
|
266
|
+
tools: ['search_stores', 'load_menu'],
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
id: 'compare_options',
|
|
270
|
+
prompt: 'Compare the quickest open food options for me.',
|
|
271
|
+
expected: 'The app grounds its comparison in the synthetic store data.',
|
|
272
|
+
shouldInvoke: true,
|
|
273
|
+
tools: ['search_stores', 'summarize_ordering_options'],
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
id: 'plan_pickup',
|
|
277
|
+
prompt: 'Plan a pickup order for Friday.',
|
|
278
|
+
expected: 'The app collects the missing fulfilment details before planning the order.',
|
|
279
|
+
shouldInvoke: true,
|
|
280
|
+
tools: ['plan_order'],
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
id: 'review_checkout',
|
|
284
|
+
prompt: 'Review my cart before I continue to checkout.',
|
|
285
|
+
expected: 'The app shows the cart and keeps payment on the explicit external handoff.',
|
|
286
|
+
shouldInvoke: true,
|
|
287
|
+
tools: ['read_cart', 'prepare_checkout'],
|
|
288
|
+
},
|
|
289
|
+
// Negative scenarios are non-invocation cases, so they never declare expected tools.
|
|
290
|
+
{
|
|
291
|
+
id: 'unrelated_weather',
|
|
292
|
+
prompt: 'Will it rain tomorrow?',
|
|
293
|
+
expected: 'Food Ordering is not invoked.',
|
|
294
|
+
shouldInvoke: false,
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
id: 'unrelated_email',
|
|
298
|
+
prompt: 'Draft an email to my manager.',
|
|
299
|
+
expected: 'Food Ordering is not invoked.',
|
|
300
|
+
shouldInvoke: false,
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
id: 'unrelated_travel',
|
|
304
|
+
prompt: 'Book me a flight to Lisbon.',
|
|
305
|
+
expected: 'Food Ordering is not invoked.',
|
|
306
|
+
shouldInvoke: false,
|
|
307
|
+
},
|
|
308
|
+
],
|
|
309
|
+
},
|
|
310
|
+
},
|
|
205
311
|
use: { state },
|
|
206
312
|
context: {
|
|
207
313
|
defaults: { locale: 'en-US', timeZone: 'America/New_York' },
|
|
@@ -287,6 +393,7 @@ export default server(
|
|
|
287
393
|
permissions: { clipboardWrite: {} },
|
|
288
394
|
}),
|
|
289
395
|
tool('search_stores', {
|
|
396
|
+
title: 'Search stores',
|
|
290
397
|
visibility: ['app'],
|
|
291
398
|
description: 'Filter synthetic restaurants for the ordering widget.',
|
|
292
399
|
annotations: readOnly,
|
|
@@ -298,6 +405,7 @@ export default server(
|
|
|
298
405
|
fulfil: () => ({ stores }),
|
|
299
406
|
}),
|
|
300
407
|
tool('load_menu', {
|
|
408
|
+
title: 'Load store menu',
|
|
301
409
|
visibility: ['app'],
|
|
302
410
|
description: 'Load synthetic menu categories and items for one store.',
|
|
303
411
|
annotations: readOnly,
|
|
@@ -310,6 +418,7 @@ export default server(
|
|
|
310
418
|
fulfil: ({ input }) => ({ storeId: input.storeId, stores, items: menu }),
|
|
311
419
|
}),
|
|
312
420
|
tool('load_item', {
|
|
421
|
+
title: 'Load menu item',
|
|
313
422
|
visibility: ['app'],
|
|
314
423
|
description: 'Load item details and modifier options for the ordering widget.',
|
|
315
424
|
annotations: readOnly,
|
|
@@ -318,6 +427,7 @@ export default server(
|
|
|
318
427
|
fulfil: ({ input }) => ({ itemId: input.itemId, items: menu }),
|
|
319
428
|
}),
|
|
320
429
|
tool('read_cart', {
|
|
430
|
+
title: 'Read ordering cart',
|
|
321
431
|
visibility: ['app'],
|
|
322
432
|
description: 'Read the caller-scoped ordering cart state.',
|
|
323
433
|
annotations: readOnly,
|
|
@@ -333,6 +443,7 @@ export default server(
|
|
|
333
443
|
},
|
|
334
444
|
}),
|
|
335
445
|
tool('sync_cart', {
|
|
446
|
+
title: 'Update ordering cart',
|
|
336
447
|
visibility: ['app'],
|
|
337
448
|
description: 'Patch the caller-scoped ordering cart with the widget cart mirror.',
|
|
338
449
|
annotations: action,
|
|
@@ -353,6 +464,7 @@ export default server(
|
|
|
353
464
|
},
|
|
354
465
|
}),
|
|
355
466
|
tool('prepare_checkout', {
|
|
467
|
+
title: 'Prepare checkout handoff',
|
|
356
468
|
visibility: ['app'],
|
|
357
469
|
description: 'Prepare the caller-scoped cart for checkout handoff.',
|
|
358
470
|
annotations: action,
|
|
@@ -10,6 +10,7 @@ describe('food-ordering example', () => {
|
|
|
10
10
|
const manifest = (await app.toManifest()) as {
|
|
11
11
|
server: {
|
|
12
12
|
name: string;
|
|
13
|
+
agentGuide?: unknown;
|
|
13
14
|
context?: {
|
|
14
15
|
defaults?: { locale?: string; timeZone?: string };
|
|
15
16
|
ambient?: {
|
|
@@ -23,6 +24,7 @@ describe('food-ordering example', () => {
|
|
|
23
24
|
connectors?: Record<string, { id: string; version: string }>;
|
|
24
25
|
tools: Array<{
|
|
25
26
|
name: string;
|
|
27
|
+
title?: string;
|
|
26
28
|
visibility?: string[];
|
|
27
29
|
annotations?: Record<string, unknown>;
|
|
28
30
|
output?: unknown;
|
|
@@ -36,6 +38,8 @@ describe('food-ordering example', () => {
|
|
|
36
38
|
};
|
|
37
39
|
|
|
38
40
|
expect(manifest.server.name).toBe('food_ordering');
|
|
41
|
+
expect(manifest.server.agentGuide).toBeDefined();
|
|
42
|
+
expect(manifest.server).not.toHaveProperty('distribution');
|
|
39
43
|
expect(manifest.server.context).toMatchObject({
|
|
40
44
|
defaults: { locale: 'en-US', timeZone: 'America/New_York' },
|
|
41
45
|
ambient: {
|
|
@@ -100,5 +104,49 @@ describe('food-ordering example', () => {
|
|
|
100
104
|
},
|
|
101
105
|
});
|
|
102
106
|
expect(manifest.widgets?.map((widget) => widget.name)).toContain('capabilities_card');
|
|
107
|
+
expect(manifest.tools.every((tool) => typeof tool.title === 'string')).toBe(true);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('projects host distribution metadata separately from the runtime manifest', () => {
|
|
111
|
+
const distribution = app.toDistributionMetadata();
|
|
112
|
+
expect(distribution).toMatchObject({
|
|
113
|
+
schemaVersion: 1,
|
|
114
|
+
listing: { summary: expect.stringContaining('Browse local food') },
|
|
115
|
+
assets: {
|
|
116
|
+
icon: { alt: 'Food Ordering noodle bowl' },
|
|
117
|
+
screenshots: [
|
|
118
|
+
expect.objectContaining({
|
|
119
|
+
alt: 'Food Ordering MCP App showing nearby stores',
|
|
120
|
+
prompt: 'Help me build a noodle order for pickup.',
|
|
121
|
+
}),
|
|
122
|
+
expect.objectContaining({
|
|
123
|
+
alt: 'Food Ordering MCP App showing the Harbor Noodles menu',
|
|
124
|
+
prompt: 'Show me the Harbor Noodles menu.',
|
|
125
|
+
}),
|
|
126
|
+
expect.objectContaining({
|
|
127
|
+
alt: 'Food Ordering MCP App reviewing a checkout handoff',
|
|
128
|
+
prompt: 'Review my spicy miso bowl order before checkout.',
|
|
129
|
+
}),
|
|
130
|
+
],
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
const scenarios = distribution?.review.scenarios ?? [];
|
|
134
|
+
expect(scenarios.filter(({ shouldInvoke }) => shouldInvoke).map(({ id }) => id)).toEqual([
|
|
135
|
+
'build_order',
|
|
136
|
+
'browse_menu',
|
|
137
|
+
'compare_options',
|
|
138
|
+
'plan_pickup',
|
|
139
|
+
'review_checkout',
|
|
140
|
+
]);
|
|
141
|
+
expect(scenarios.filter(({ shouldInvoke }) => !shouldInvoke).map(({ id }) => id)).toEqual([
|
|
142
|
+
'unrelated_weather',
|
|
143
|
+
'unrelated_email',
|
|
144
|
+
'unrelated_travel',
|
|
145
|
+
]);
|
|
146
|
+
expect(
|
|
147
|
+
scenarios
|
|
148
|
+
.filter(({ shouldInvoke }) => !shouldInvoke)
|
|
149
|
+
.every((scenario) => !('tools' in scenario)),
|
|
150
|
+
).toBe(true);
|
|
103
151
|
});
|
|
104
152
|
});
|
|
@@ -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.70.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.70.0 hash:efffbf82007f935d -->
|
|
7
7
|
|
|
8
8
|
# publishing-mcp-integrations
|
|
9
9
|
|