@noodleseed/agent-kit 0.102.0 → 0.103.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 (48) hide show
  1. package/manifest.json +359 -359
  2. package/package.json +1 -1
  3. package/skills/claude-code/SKILL.md +1 -1
  4. package/skills/claude-code/authoring-mcp-servers/SKILL.md +1 -1
  5. package/skills/claude-code/authoring-mcp-servers/references/authoring-workflow.md +5 -2
  6. package/skills/claude-code/building-mcp-apps/SKILL.md +1 -1
  7. package/skills/claude-code/connecting-apis-to-mcp/SKILL.md +1 -1
  8. package/skills/claude-code/connecting-apis-to-mcp/references/authoring-workflow.md +5 -2
  9. package/skills/claude-code/creating-product-agent-guides/SKILL.md +1 -1
  10. package/skills/claude-code/debugging-mcp-delivery/SKILL.md +1 -1
  11. package/skills/claude-code/deploying-mcp-services/SKILL.md +1 -1
  12. package/skills/claude-code/designing-mcp-products/SKILL.md +1 -1
  13. package/skills/claude-code/designing-mcp-products/references/authoring-workflow.md +5 -2
  14. package/skills/claude-code/embedding-mcp-assistants/SKILL.md +1 -1
  15. package/skills/claude-code/embedding-mcp-assistants/references/authoring-workflow.md +5 -2
  16. package/skills/claude-code/examples/customer-auth/README.md +29 -41
  17. package/skills/claude-code/examples/customer-auth/src/server.ts +15 -4
  18. package/skills/claude-code/examples/customer-auth/test/server.test.ts +6 -1
  19. package/skills/claude-code/executing-noodle-plans/SKILL.md +1 -1
  20. package/skills/claude-code/publishing-mcp-integrations/SKILL.md +1 -1
  21. package/skills/claude-code/references/authoring-workflow.md +5 -2
  22. package/skills/claude-code/reporting-noodle-feedback/SKILL.md +1 -1
  23. package/skills/claude-code/verifying-mcp-delivery/SKILL.md +1 -1
  24. package/skills/claude-code/wrapping-existing-applications/SKILL.md +1 -1
  25. package/skills/claude-code/wrapping-existing-applications/references/authoring-workflow.md +5 -2
  26. package/skills/codex/SKILL.md +1 -1
  27. package/skills/codex/authoring-mcp-servers/SKILL.md +1 -1
  28. package/skills/codex/authoring-mcp-servers/references/authoring-workflow.md +5 -2
  29. package/skills/codex/building-mcp-apps/SKILL.md +1 -1
  30. package/skills/codex/connecting-apis-to-mcp/SKILL.md +1 -1
  31. package/skills/codex/connecting-apis-to-mcp/references/authoring-workflow.md +5 -2
  32. package/skills/codex/creating-product-agent-guides/SKILL.md +1 -1
  33. package/skills/codex/debugging-mcp-delivery/SKILL.md +1 -1
  34. package/skills/codex/deploying-mcp-services/SKILL.md +1 -1
  35. package/skills/codex/designing-mcp-products/SKILL.md +1 -1
  36. package/skills/codex/designing-mcp-products/references/authoring-workflow.md +5 -2
  37. package/skills/codex/embedding-mcp-assistants/SKILL.md +1 -1
  38. package/skills/codex/embedding-mcp-assistants/references/authoring-workflow.md +5 -2
  39. package/skills/codex/examples/customer-auth/README.md +29 -41
  40. package/skills/codex/examples/customer-auth/src/server.ts +15 -4
  41. package/skills/codex/examples/customer-auth/test/server.test.ts +6 -1
  42. package/skills/codex/executing-noodle-plans/SKILL.md +1 -1
  43. package/skills/codex/publishing-mcp-integrations/SKILL.md +1 -1
  44. package/skills/codex/references/authoring-workflow.md +5 -2
  45. package/skills/codex/reporting-noodle-feedback/SKILL.md +1 -1
  46. package/skills/codex/verifying-mcp-delivery/SKILL.md +1 -1
  47. package/skills/codex/wrapping-existing-applications/SKILL.md +1 -1
  48. package/skills/codex/wrapping-existing-applications/references/authoring-workflow.md +5 -2
@@ -222,7 +222,7 @@ Every federated issuer must repeat every endpoint key used by the app, although
222
222
 
223
223
  Resolved customer URLs are private routing authority: they never enter the manifest/artifact, `${user}`, logs, model output, widgets, public confirmation review, cache keys, or delegated-token-exchange assertions. Routed reads may be used by tools, including declared nested calls. A routed action—including one reached through a connector wrapper—requires exact `annotations.confirm: true`; omitted or `false` fails with `customer_endpoint_action_unsupported`. Routed resources, prompts, and ambient context fail with `customer_endpoint_surface_unsupported`.
224
224
 
225
- At runtime, an initially missing, malformed, or disallowed claim returns the same safe `connector_route_unavailable` tool error before credential lookup or connector egress. Preparation stores only sorted route `{ key, fingerprint }` bindings in the private server-held continuation. Acceptance re-resolves the current request routes; a missing or changed binding returns `invalid_continuation` before policy, credentials, or egress, then the matching frozen snapshot is reused for the action and nested/later calls. `tools/list` remains based only on roles and scopes, so route availability neither reveals tenant topology nor changes the existing authorization filter.
225
+ At runtime, an initially missing, malformed, or disallowed claim returns the same safe `connector_route_unavailable` tool error before credential lookup or connector egress. Preparation stores only sorted route `{ key, fingerprint }` bindings in the private server-held continuation. Acceptance re-resolves the current request routes; a missing or changed binding returns `invalid_continuation` before policy, credentials, or egress, then the matching frozen snapshot is reused for the action and nested/later calls. `tools/list` follows the scope/role discovery rule and its explicit public-descriptor opt-in, so route availability neither reveals tenant topology nor changes execution authorization.
226
226
 
227
227
  ## Per-tool authorization
228
228
 
@@ -244,7 +244,10 @@ tool('list_org_apps', {
244
244
  })
245
245
  ```
246
246
 
247
- Role values are trusted only from the explicitly configured claim path (or the platform-private bridge role claim). Direct OIDC scopes default to standard `scope`, `scp`, or `scopes` claims unless `claims.scopes` is configured. Embedded-assistant backends pass verified `user.roles` and `user.scopes` separately during `createAssistantSession(...)`; page context never grants either. Claim values must be a string or string array; malformed or oversized values fail closed. Eligible tools remain in authored order in `tools/list`; ineligible tools are omitted and a guessed direct call is still denied before argument validation or connector execution. Scope denials use MCP OAuth step-up metadata without disclosing role names.
247
+ Use `authorization.discovery: 'public'` on a nonempty scope/role rule to expose its MCP descriptor before sign-in. Omission and explicit 'authorized' preserve filtered discovery and compile identically. Visibility grants no execution or product-skill eligibility; scopes remain ALL and roles ANY. Noodle derives securitySchemes; never author them.
248
+ For mixed customer preview, keep server customerAuth and adopt on the same org/app/env, endpoint, issuer and audience; keep the separate public Help endpoint during the pilot, and never create overlapping active issuer/audience ownership. Before any mixed deploy or access change, leave only Help unrestricted, add authorization to every customer tool, and validate plus preview with `noodle dev --access mixed`. For an existing customer-only app, first run `noodle deployments list --org <org> --app <app> --env <env> --json` and inspect an inactive `customers` record for the exact server version. If none exists, record the active ID, redeploy the unchanged secured source to the same version with `--access customers`, then list and inspect again to prove that ID is now inactive; recording it alone preserves nothing. Next deploy the policy-prepared source with `--access customers`, verify the original rollback record remains inactive, and only then run `noodle access set mixed ... --version <version>`. On pilot failure use `noodle rollback <deployment-id> --org <org> --app <app> --env <env> --reason <text>`. This app-history rollback differs from the compatible hosted service-release floor. Invalid supplied credentials fail, with no platform-human fallback. Broker exchange remains required. Local Devtools retries after successful sign-in and leaves Help available after cancellation without executing the protected tool. After deployment, test anonymous discovery, sign-in, cancellation, authenticated retry and expiry in the actual host before customer cutover; local/SDK checks do not prove ChatGPT or another host.
249
+
250
+ Role values are trusted only from the explicitly configured claim path (or the platform-private bridge role claim). Direct OIDC scopes default to standard `scope`, `scp`, or `scopes` claims unless `claims.scopes` is configured. Embedded-assistant backends pass verified `user.roles` and `user.scopes` separately during `createAssistantSession(...)`; page context never grants either. Claim values must be a string or string array; malformed or oversized values fail closed. Tools retain authored order in `tools/list`; protected descriptors are omitted unless explicitly public, and an unauthorized direct call is still denied before argument validation or connector execution. Scope denials use MCP OAuth step-up metadata without disclosing role names.
248
251
 
249
252
  ## Delegated downstream auth (call your API as the signed-in user)
250
253
 
@@ -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.102.0 hash:0e06e11254563b6a -->
6
+ <!-- noodle-skill version:0.103.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.102.0 hash:8d75ad13f4b3120a -->
6
+ <!-- noodle-skill version:0.103.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.102.0 hash:3a1e14ff9b98ddbd -->
6
+ <!-- noodle-skill version:0.103.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.102.0 hash:a21b2ed9997f9454 -->
6
+ <!-- noodle-skill version:0.103.0 hash:a21b2ed9997f9454 -->
7
7
 
8
8
  # designing-mcp-products
9
9
 
@@ -222,7 +222,7 @@ Every federated issuer must repeat every endpoint key used by the app, although
222
222
 
223
223
  Resolved customer URLs are private routing authority: they never enter the manifest/artifact, `${user}`, logs, model output, widgets, public confirmation review, cache keys, or delegated-token-exchange assertions. Routed reads may be used by tools, including declared nested calls. A routed action—including one reached through a connector wrapper—requires exact `annotations.confirm: true`; omitted or `false` fails with `customer_endpoint_action_unsupported`. Routed resources, prompts, and ambient context fail with `customer_endpoint_surface_unsupported`.
224
224
 
225
- At runtime, an initially missing, malformed, or disallowed claim returns the same safe `connector_route_unavailable` tool error before credential lookup or connector egress. Preparation stores only sorted route `{ key, fingerprint }` bindings in the private server-held continuation. Acceptance re-resolves the current request routes; a missing or changed binding returns `invalid_continuation` before policy, credentials, or egress, then the matching frozen snapshot is reused for the action and nested/later calls. `tools/list` remains based only on roles and scopes, so route availability neither reveals tenant topology nor changes the existing authorization filter.
225
+ At runtime, an initially missing, malformed, or disallowed claim returns the same safe `connector_route_unavailable` tool error before credential lookup or connector egress. Preparation stores only sorted route `{ key, fingerprint }` bindings in the private server-held continuation. Acceptance re-resolves the current request routes; a missing or changed binding returns `invalid_continuation` before policy, credentials, or egress, then the matching frozen snapshot is reused for the action and nested/later calls. `tools/list` follows the scope/role discovery rule and its explicit public-descriptor opt-in, so route availability neither reveals tenant topology nor changes execution authorization.
226
226
 
227
227
  ## Per-tool authorization
228
228
 
@@ -244,7 +244,10 @@ tool('list_org_apps', {
244
244
  })
245
245
  ```
246
246
 
247
- Role values are trusted only from the explicitly configured claim path (or the platform-private bridge role claim). Direct OIDC scopes default to standard `scope`, `scp`, or `scopes` claims unless `claims.scopes` is configured. Embedded-assistant backends pass verified `user.roles` and `user.scopes` separately during `createAssistantSession(...)`; page context never grants either. Claim values must be a string or string array; malformed or oversized values fail closed. Eligible tools remain in authored order in `tools/list`; ineligible tools are omitted and a guessed direct call is still denied before argument validation or connector execution. Scope denials use MCP OAuth step-up metadata without disclosing role names.
247
+ Use `authorization.discovery: 'public'` on a nonempty scope/role rule to expose its MCP descriptor before sign-in. Omission and explicit 'authorized' preserve filtered discovery and compile identically. Visibility grants no execution or product-skill eligibility; scopes remain ALL and roles ANY. Noodle derives securitySchemes; never author them.
248
+ For mixed customer preview, keep server customerAuth and adopt on the same org/app/env, endpoint, issuer and audience; keep the separate public Help endpoint during the pilot, and never create overlapping active issuer/audience ownership. Before any mixed deploy or access change, leave only Help unrestricted, add authorization to every customer tool, and validate plus preview with `noodle dev --access mixed`. For an existing customer-only app, first run `noodle deployments list --org <org> --app <app> --env <env> --json` and inspect an inactive `customers` record for the exact server version. If none exists, record the active ID, redeploy the unchanged secured source to the same version with `--access customers`, then list and inspect again to prove that ID is now inactive; recording it alone preserves nothing. Next deploy the policy-prepared source with `--access customers`, verify the original rollback record remains inactive, and only then run `noodle access set mixed ... --version <version>`. On pilot failure use `noodle rollback <deployment-id> --org <org> --app <app> --env <env> --reason <text>`. This app-history rollback differs from the compatible hosted service-release floor. Invalid supplied credentials fail, with no platform-human fallback. Broker exchange remains required. Local Devtools retries after successful sign-in and leaves Help available after cancellation without executing the protected tool. After deployment, test anonymous discovery, sign-in, cancellation, authenticated retry and expiry in the actual host before customer cutover; local/SDK checks do not prove ChatGPT or another host.
249
+
250
+ Role values are trusted only from the explicitly configured claim path (or the platform-private bridge role claim). Direct OIDC scopes default to standard `scope`, `scp`, or `scopes` claims unless `claims.scopes` is configured. Embedded-assistant backends pass verified `user.roles` and `user.scopes` separately during `createAssistantSession(...)`; page context never grants either. Claim values must be a string or string array; malformed or oversized values fail closed. Tools retain authored order in `tools/list`; protected descriptors are omitted unless explicitly public, and an unauthorized direct call is still denied before argument validation or connector execution. Scope denials use MCP OAuth step-up metadata without disclosing role names.
248
251
 
249
252
  ## Delegated downstream auth (call your API as the signed-in user)
250
253
 
@@ -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.102.0 hash:d554d661ed7ac7be -->
6
+ <!-- noodle-skill version:0.103.0 hash:d554d661ed7ac7be -->
7
7
 
8
8
  # embedding-mcp-assistants
9
9
 
@@ -222,7 +222,7 @@ Every federated issuer must repeat every endpoint key used by the app, although
222
222
 
223
223
  Resolved customer URLs are private routing authority: they never enter the manifest/artifact, `${user}`, logs, model output, widgets, public confirmation review, cache keys, or delegated-token-exchange assertions. Routed reads may be used by tools, including declared nested calls. A routed action—including one reached through a connector wrapper—requires exact `annotations.confirm: true`; omitted or `false` fails with `customer_endpoint_action_unsupported`. Routed resources, prompts, and ambient context fail with `customer_endpoint_surface_unsupported`.
224
224
 
225
- At runtime, an initially missing, malformed, or disallowed claim returns the same safe `connector_route_unavailable` tool error before credential lookup or connector egress. Preparation stores only sorted route `{ key, fingerprint }` bindings in the private server-held continuation. Acceptance re-resolves the current request routes; a missing or changed binding returns `invalid_continuation` before policy, credentials, or egress, then the matching frozen snapshot is reused for the action and nested/later calls. `tools/list` remains based only on roles and scopes, so route availability neither reveals tenant topology nor changes the existing authorization filter.
225
+ At runtime, an initially missing, malformed, or disallowed claim returns the same safe `connector_route_unavailable` tool error before credential lookup or connector egress. Preparation stores only sorted route `{ key, fingerprint }` bindings in the private server-held continuation. Acceptance re-resolves the current request routes; a missing or changed binding returns `invalid_continuation` before policy, credentials, or egress, then the matching frozen snapshot is reused for the action and nested/later calls. `tools/list` follows the scope/role discovery rule and its explicit public-descriptor opt-in, so route availability neither reveals tenant topology nor changes execution authorization.
226
226
 
227
227
  ## Per-tool authorization
228
228
 
@@ -244,7 +244,10 @@ tool('list_org_apps', {
244
244
  })
245
245
  ```
246
246
 
247
- Role values are trusted only from the explicitly configured claim path (or the platform-private bridge role claim). Direct OIDC scopes default to standard `scope`, `scp`, or `scopes` claims unless `claims.scopes` is configured. Embedded-assistant backends pass verified `user.roles` and `user.scopes` separately during `createAssistantSession(...)`; page context never grants either. Claim values must be a string or string array; malformed or oversized values fail closed. Eligible tools remain in authored order in `tools/list`; ineligible tools are omitted and a guessed direct call is still denied before argument validation or connector execution. Scope denials use MCP OAuth step-up metadata without disclosing role names.
247
+ Use `authorization.discovery: 'public'` on a nonempty scope/role rule to expose its MCP descriptor before sign-in. Omission and explicit 'authorized' preserve filtered discovery and compile identically. Visibility grants no execution or product-skill eligibility; scopes remain ALL and roles ANY. Noodle derives securitySchemes; never author them.
248
+ For mixed customer preview, keep server customerAuth and adopt on the same org/app/env, endpoint, issuer and audience; keep the separate public Help endpoint during the pilot, and never create overlapping active issuer/audience ownership. Before any mixed deploy or access change, leave only Help unrestricted, add authorization to every customer tool, and validate plus preview with `noodle dev --access mixed`. For an existing customer-only app, first run `noodle deployments list --org <org> --app <app> --env <env> --json` and inspect an inactive `customers` record for the exact server version. If none exists, record the active ID, redeploy the unchanged secured source to the same version with `--access customers`, then list and inspect again to prove that ID is now inactive; recording it alone preserves nothing. Next deploy the policy-prepared source with `--access customers`, verify the original rollback record remains inactive, and only then run `noodle access set mixed ... --version <version>`. On pilot failure use `noodle rollback <deployment-id> --org <org> --app <app> --env <env> --reason <text>`. This app-history rollback differs from the compatible hosted service-release floor. Invalid supplied credentials fail, with no platform-human fallback. Broker exchange remains required. Local Devtools retries after successful sign-in and leaves Help available after cancellation without executing the protected tool. After deployment, test anonymous discovery, sign-in, cancellation, authenticated retry and expiry in the actual host before customer cutover; local/SDK checks do not prove ChatGPT or another host.
249
+
250
+ Role values are trusted only from the explicitly configured claim path (or the platform-private bridge role claim). Direct OIDC scopes default to standard `scope`, `scp`, or `scopes` claims unless `claims.scopes` is configured. Embedded-assistant backends pass verified `user.roles` and `user.scopes` separately during `createAssistantSession(...)`; page context never grants either. Claim values must be a string or string array; malformed or oversized values fail closed. Tools retain authored order in `tools/list`; protected descriptors are omitted unless explicitly public, and an unauthorized direct call is still denied before argument validation or connector execution. Scope denials use MCP OAuth step-up metadata without disclosing role names.
248
251
 
249
252
  ## Delegated downstream auth (call your API as the signed-in user)
250
253
 
@@ -7,20 +7,16 @@ This curated example owns the customer/end-user authentication capability slot.
7
7
  can protect an MCP endpoint with direct OIDC, retain role/scope-based tool authorization, and route ordinary
8
8
  reads and confirmed actions to the API origin selected by the verified customer's identity provider.
9
9
 
10
- It also owns the customer-branded embedded-assistant presentation showcase. Direct MCP calls obtain the
11
- route from the verified OIDC claim; embedded sessions obtain it from the authenticated customer backend's
12
- session exchange. Both paths keep the URL outside tool/model/browser-visible state. The built-in card hides
13
- its optional technical Additional details disclosure while retaining the business review and confirmation
14
- controls; this presentation setting does not weaken the exact runtime confirmation boundary.
10
+ Direct MCP calls obtain the private route from verified OIDC claims; embedded sessions obtain it from the authenticated backend. Both keep routes out of model and browser state.
15
11
 
16
12
  The public developer entrypoint is [`src/server.ts`](src/server.ts). It exposes a deliberately small MCP
17
13
  surface for organization discovery and app lifecycle operations:
18
14
 
19
- - `list_my_organizations` lists the NoodleSeed.com organizations the signed-in customer belongs to (no
20
- arguments the org set comes from the verified customer session).
21
- - `list_org_apps` lists apps for one of those organizations through that tenant's API. It is visible and
22
- callable only when the verified customer has the `org_apps:read` scope and either the `org_admin` or
23
- `org_member` role.
15
+ - `help` explains the product without customer identity.
16
+ - `list_my_organizations` publicly advertises its descriptor but requires `organizations:read` to list the signed-in customer’s organizations.
17
+ - `list_org_apps` uses `authorization.discovery: 'public'` to expose its descriptor on an anonymously
18
+ accessible endpoint. Execution still requires `org_apps:read` and `org_admin` or `org_member`. Visibility
19
+ grants no permissions, records, role disclosure, or product-guide eligibility. ChatGPT sign-in is unproven.
24
20
  - `archive_org_app` archives one app only after exact runtime confirmation. It requires the
25
21
  `org_apps:write` scope and `org_admin` role.
26
22
 
@@ -28,22 +24,7 @@ The tools chain: `list_my_organizations` surfaces the `org_id`s the customer can
28
24
  `list_org_apps` takes one of those ids, and `archive_org_app` accepts the selected app id. Tool code remains
29
25
  independent of the selected origin.
30
26
 
31
- The server also declares one typed `agentGuide` for those product workflows. The deployed embedded assistant
32
- uses it automatically: each turn keeps only complete workflows supported by the verified session's roles,
33
- scopes, and model-visible tools. An organization member can receive organization/app review guidance, while
34
- only an administrator with `org_apps:write` receives the complete archive workflow and its confirmation
35
- boundary. The guide stays server-side, so the Web Component, React renderer, headless hook, and public client
36
- need no new option and receive no raw skill content. See
37
- [using a product guide at runtime](https://docs.noodleseed.dev/docs/guides/product-agent-guides#use-the-guide-at-runtime)
38
- for the public behavior guide.
39
-
40
- A skill-aware external agent connected directly to the same tenant MCP URL receives the same
41
- complete-workflow filtering through the modern draft MCP Skills extension. Members and administrators may
42
- therefore receive different `SKILL.md` and MCP-surface bytes, each with matching caller-specific digests.
43
- This reuses the configured customer OAuth boundary; it does not require a second skill installation or auth
44
- system, and it is not a claim that every external host currently implements the draft extension. The
45
- same [runtime guide](https://docs.noodleseed.dev/docs/guides/product-agent-guides#use-the-guide-at-runtime)
46
- explains this preview boundary.
27
+ The typed `agentGuide` retains only complete workflows the verified caller can execute. Public descriptor discovery does not grant workflow access. See the [runtime guide](https://docs.noodleseed.dev/docs/guides/product-agent-guides#use-the-guide-at-runtime) for embedded behavior and the draft MCP Skills preview.
47
28
 
48
29
  ## Declare the customer endpoint
49
30
 
@@ -212,6 +193,7 @@ rule beside the rest of its public contract:
212
193
  ```ts
213
194
  tool('list_org_apps', {
214
195
  authorization: {
196
+ discovery: 'public',
215
197
  requiredScopes: ['org_apps:read'],
216
198
  allowedRoles: ['org_admin', 'org_member'],
217
199
  },
@@ -220,9 +202,9 @@ tool('list_org_apps', {
220
202
  ```
221
203
 
222
204
  Every required scope must be present and at least one allowed role must match. When both lists are declared,
223
- both conditions apply. Route availability never changes `tools/list`: discovery remains based only on
224
- roles/scopes. A restricted tool is omitted for an ineligible customer and a guessed direct call still fails
225
- closed.
205
+ both conditions apply. In mixed customer mode, `discovery: 'public'` exposes this descriptor before sign-in;
206
+ execution still requires those scopes and roles. Other restricted tools remain filtered by authorization.
207
+ Route availability never changes discovery, and unauthorized direct calls fail closed.
226
208
 
227
209
  Tool code calls the connector normally:
228
210
 
@@ -811,11 +793,7 @@ subject assertion and mints a short-lived token scoped to the signed-in user and
811
793
 
812
794
  ## Launch and qualified-usage proof
813
795
 
814
- Use the [embedded assistant guide](https://docs.noodleseed.dev/docs/guides/embedded-assistant) for the complete
815
- pre-launch, browser-proof, qualified-usage, recovery, measurement, and operator procedure; do not copy those
816
- commands into this example. Keep deployed capability, production-browser proof, qualified usage, and measured
817
- outcome separate; raw turn volume is utilization rather than outcome. Platform-owned completion events still
818
- require a separate human-approved analytics and customer-data contract.
796
+ For launch, browser verification, and qualified usage, follow the [embedded assistant guide](https://docs.noodleseed.dev/docs/guides/embedded-assistant).
819
797
 
820
798
  ## Deploy customer-protected to Noodle Seed Cloud
821
799
 
@@ -833,13 +811,23 @@ Endpoint:
833
811
  https://cloud.noodleseed.dev/o/noodleseed/customer-auth/mcp
834
812
  ```
835
813
 
836
- ## MCP Primitives
837
-
838
- - Tool `list_my_organizations`: calls `GET /api/organizations` and returns the organizations the signed-in
839
- customer is a member of. Takes no arguments; the org set is scoped by the verified customer session.
840
- - Tool `list_org_apps`: calls `GET /api/organizations/{org_id}/apps` for one organization `org_id`.
841
- - Tool `archive_org_app`: after confirmation, calls
842
- `POST /api/organizations/{org_id}/apps/{app_id}/archive`.
814
+ ## Preview anonymous Help with customer sign-in
815
+
816
+ Use `noodle dev examples/customer-auth/src/server.ts --access mixed`. Help remains available before sign-in;
817
+ protected reads advertise descriptors and require their verified scopes/roles to execute. Customer mode
818
+ remains the default. Local Devtools retries a protected call after successful sign-in; cancellation executes
819
+ nothing and leaves Help available. With a hosted service, a new target may use
820
+ `--access mixed` only after every customer tool has an authorization rule. For an existing customer-only
821
+ target, preserve its org/app/env, endpoint, issuer, and audience. Follow the public guide: verify an inactive
822
+ `customers` record for the exact version, creating it by unchanged secured redeploy if absent; add and
823
+ validate every tool rule; deploy the prepared source as `customers`; recheck the rollback; then adopt mixed
824
+ access. On pilot failure, use
825
+ `noodle rollback <deployment-id>` with the same org/app/env. This app-history rollback is separate from the
826
+ compatible hosted service-release floor. Keep the public Help endpoint through the post-deployment ChatGPT
827
+ and customer API pilot. Local behavior and wire checks do not prove that host
828
+ journey. See the
829
+ [customer auth rollback and adoption procedure](https://docs.noodleseed.dev/docs/guides/customer-auth#preserve-an-app-rollback-target-and-adopt)
830
+ for the exact commands and checks.
843
831
 
844
832
  ## Auth boundary
845
833
 
@@ -202,10 +202,23 @@ export default server(
202
202
  }),
203
203
  },
204
204
  [
205
+ tool('help', {
206
+ title: 'Help with organizations and apps',
207
+ description: 'Explain what customers can do before they sign in.',
208
+ input: z.object({}),
209
+ output: z.object({ help: z.string() }),
210
+ annotations: annotations.readOnly(),
211
+ fulfil() {
212
+ return {
213
+ help: 'Sign in to browse your organizations and apps. Archiving an app requires an administrator and confirmation.',
214
+ };
215
+ },
216
+ }),
205
217
  tool('list_org_apps', {
206
218
  title: 'List organization apps',
207
219
  description: 'List NoodleSeed.com apps for an organization from its customer API.',
208
220
  authorization: {
221
+ discovery: 'public',
209
222
  requiredScopes: ['org_apps:read'],
210
223
  allowedRoles: ['org_admin', 'org_member'],
211
224
  },
@@ -232,12 +245,10 @@ export default server(
232
245
  tool('list_my_organizations', {
233
246
  title: 'List my organizations',
234
247
  description: 'List the NoodleSeed.com organizations the signed-in customer belongs to.',
248
+ authorization: { discovery: 'public', requiredScopes: ['organizations:read'] },
235
249
  contextProvider: true,
236
250
  input: z.object({}),
237
- // The customer API returns every organization for the signed-in customer in one response, with no
238
- // page parameter to pass through, so the bound is declared on the shape. A customer belongs to a
239
- // handful of organizations; `noodle check` reports an unbounded list as
240
- // `tool_design_output_bounds`.
251
+ // The API returns all of the caller's organizations without pagination; bound the output shape.
241
252
  output: z.object({
242
253
  organizations: z.array(z.unknown()).max(100),
243
254
  }),
@@ -85,12 +85,17 @@ describe('customer-auth example', () => {
85
85
  expect(catalog?.connectors[0]?.http).not.toHaveProperty('allowedOrigins');
86
86
  expect(JSON.stringify({ manifest, catalog })).not.toContain('tenant-a.api.noodleseed.dev');
87
87
  expect(manifest.tools.find((tool) => tool.name === 'list_org_apps')?.authorization).toEqual({
88
+ discovery: 'public',
88
89
  requiredScopes: ['org_apps:read'],
89
90
  allowedRoles: ['org_admin', 'org_member'],
90
91
  });
91
92
  expect(
92
93
  manifest.tools.find((tool) => tool.name === 'list_my_organizations')?.authorization,
93
- ).toBeUndefined();
94
+ ).toEqual({ discovery: 'public', requiredScopes: ['organizations:read'] });
95
+ const help = manifest.tools.find((tool) => tool.name === 'help');
96
+ expect(help).toBeDefined();
97
+ expect(help?.authorization).toBeUndefined();
98
+ expect(help?.annotations?.readOnlyHint).toBe(true);
94
99
  expect(manifest.tools.find((tool) => tool.name === 'archive_org_app')).toMatchObject({
95
100
  authorization: {
96
101
  requiredScopes: ['org_apps:write'],
@@ -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.102.0 hash:6a9f132ddb79352e -->
6
+ <!-- noodle-skill version:0.103.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.102.0 hash:0ccafb222038f553 -->
6
+ <!-- noodle-skill version:0.103.0 hash:0ccafb222038f553 -->
7
7
 
8
8
  # publishing-mcp-integrations
9
9
 
@@ -222,7 +222,7 @@ Every federated issuer must repeat every endpoint key used by the app, although
222
222
 
223
223
  Resolved customer URLs are private routing authority: they never enter the manifest/artifact, `${user}`, logs, model output, widgets, public confirmation review, cache keys, or delegated-token-exchange assertions. Routed reads may be used by tools, including declared nested calls. A routed action—including one reached through a connector wrapper—requires exact `annotations.confirm: true`; omitted or `false` fails with `customer_endpoint_action_unsupported`. Routed resources, prompts, and ambient context fail with `customer_endpoint_surface_unsupported`.
224
224
 
225
- At runtime, an initially missing, malformed, or disallowed claim returns the same safe `connector_route_unavailable` tool error before credential lookup or connector egress. Preparation stores only sorted route `{ key, fingerprint }` bindings in the private server-held continuation. Acceptance re-resolves the current request routes; a missing or changed binding returns `invalid_continuation` before policy, credentials, or egress, then the matching frozen snapshot is reused for the action and nested/later calls. `tools/list` remains based only on roles and scopes, so route availability neither reveals tenant topology nor changes the existing authorization filter.
225
+ At runtime, an initially missing, malformed, or disallowed claim returns the same safe `connector_route_unavailable` tool error before credential lookup or connector egress. Preparation stores only sorted route `{ key, fingerprint }` bindings in the private server-held continuation. Acceptance re-resolves the current request routes; a missing or changed binding returns `invalid_continuation` before policy, credentials, or egress, then the matching frozen snapshot is reused for the action and nested/later calls. `tools/list` follows the scope/role discovery rule and its explicit public-descriptor opt-in, so route availability neither reveals tenant topology nor changes execution authorization.
226
226
 
227
227
  ## Per-tool authorization
228
228
 
@@ -244,7 +244,10 @@ tool('list_org_apps', {
244
244
  })
245
245
  ```
246
246
 
247
- Role values are trusted only from the explicitly configured claim path (or the platform-private bridge role claim). Direct OIDC scopes default to standard `scope`, `scp`, or `scopes` claims unless `claims.scopes` is configured. Embedded-assistant backends pass verified `user.roles` and `user.scopes` separately during `createAssistantSession(...)`; page context never grants either. Claim values must be a string or string array; malformed or oversized values fail closed. Eligible tools remain in authored order in `tools/list`; ineligible tools are omitted and a guessed direct call is still denied before argument validation or connector execution. Scope denials use MCP OAuth step-up metadata without disclosing role names.
247
+ Use `authorization.discovery: 'public'` on a nonempty scope/role rule to expose its MCP descriptor before sign-in. Omission and explicit 'authorized' preserve filtered discovery and compile identically. Visibility grants no execution or product-skill eligibility; scopes remain ALL and roles ANY. Noodle derives securitySchemes; never author them.
248
+ For mixed customer preview, keep server customerAuth and adopt on the same org/app/env, endpoint, issuer and audience; keep the separate public Help endpoint during the pilot, and never create overlapping active issuer/audience ownership. Before any mixed deploy or access change, leave only Help unrestricted, add authorization to every customer tool, and validate plus preview with `noodle dev --access mixed`. For an existing customer-only app, first run `noodle deployments list --org <org> --app <app> --env <env> --json` and inspect an inactive `customers` record for the exact server version. If none exists, record the active ID, redeploy the unchanged secured source to the same version with `--access customers`, then list and inspect again to prove that ID is now inactive; recording it alone preserves nothing. Next deploy the policy-prepared source with `--access customers`, verify the original rollback record remains inactive, and only then run `noodle access set mixed ... --version <version>`. On pilot failure use `noodle rollback <deployment-id> --org <org> --app <app> --env <env> --reason <text>`. This app-history rollback differs from the compatible hosted service-release floor. Invalid supplied credentials fail, with no platform-human fallback. Broker exchange remains required. Local Devtools retries after successful sign-in and leaves Help available after cancellation without executing the protected tool. After deployment, test anonymous discovery, sign-in, cancellation, authenticated retry and expiry in the actual host before customer cutover; local/SDK checks do not prove ChatGPT or another host.
249
+
250
+ Role values are trusted only from the explicitly configured claim path (or the platform-private bridge role claim). Direct OIDC scopes default to standard `scope`, `scp`, or `scopes` claims unless `claims.scopes` is configured. Embedded-assistant backends pass verified `user.roles` and `user.scopes` separately during `createAssistantSession(...)`; page context never grants either. Claim values must be a string or string array; malformed or oversized values fail closed. Tools retain authored order in `tools/list`; protected descriptors are omitted unless explicitly public, and an unauthorized direct call is still denied before argument validation or connector execution. Scope denials use MCP OAuth step-up metadata without disclosing role names.
248
251
 
249
252
  ## Delegated downstream auth (call your API as the signed-in user)
250
253
 
@@ -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.102.0 hash:660cc6ad9469d90f -->
6
+ <!-- noodle-skill version:0.103.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.102.0 hash:292253cbaed9a3c5 -->
6
+ <!-- noodle-skill version:0.103.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.102.0 hash:379ab9f64878f1fe -->
6
+ <!-- noodle-skill version:0.103.0 hash:379ab9f64878f1fe -->
7
7
 
8
8
  # wrapping-existing-applications
9
9
 
@@ -222,7 +222,7 @@ Every federated issuer must repeat every endpoint key used by the app, although
222
222
 
223
223
  Resolved customer URLs are private routing authority: they never enter the manifest/artifact, `${user}`, logs, model output, widgets, public confirmation review, cache keys, or delegated-token-exchange assertions. Routed reads may be used by tools, including declared nested calls. A routed action—including one reached through a connector wrapper—requires exact `annotations.confirm: true`; omitted or `false` fails with `customer_endpoint_action_unsupported`. Routed resources, prompts, and ambient context fail with `customer_endpoint_surface_unsupported`.
224
224
 
225
- At runtime, an initially missing, malformed, or disallowed claim returns the same safe `connector_route_unavailable` tool error before credential lookup or connector egress. Preparation stores only sorted route `{ key, fingerprint }` bindings in the private server-held continuation. Acceptance re-resolves the current request routes; a missing or changed binding returns `invalid_continuation` before policy, credentials, or egress, then the matching frozen snapshot is reused for the action and nested/later calls. `tools/list` remains based only on roles and scopes, so route availability neither reveals tenant topology nor changes the existing authorization filter.
225
+ At runtime, an initially missing, malformed, or disallowed claim returns the same safe `connector_route_unavailable` tool error before credential lookup or connector egress. Preparation stores only sorted route `{ key, fingerprint }` bindings in the private server-held continuation. Acceptance re-resolves the current request routes; a missing or changed binding returns `invalid_continuation` before policy, credentials, or egress, then the matching frozen snapshot is reused for the action and nested/later calls. `tools/list` follows the scope/role discovery rule and its explicit public-descriptor opt-in, so route availability neither reveals tenant topology nor changes execution authorization.
226
226
 
227
227
  ## Per-tool authorization
228
228
 
@@ -244,7 +244,10 @@ tool('list_org_apps', {
244
244
  })
245
245
  ```
246
246
 
247
- Role values are trusted only from the explicitly configured claim path (or the platform-private bridge role claim). Direct OIDC scopes default to standard `scope`, `scp`, or `scopes` claims unless `claims.scopes` is configured. Embedded-assistant backends pass verified `user.roles` and `user.scopes` separately during `createAssistantSession(...)`; page context never grants either. Claim values must be a string or string array; malformed or oversized values fail closed. Eligible tools remain in authored order in `tools/list`; ineligible tools are omitted and a guessed direct call is still denied before argument validation or connector execution. Scope denials use MCP OAuth step-up metadata without disclosing role names.
247
+ Use `authorization.discovery: 'public'` on a nonempty scope/role rule to expose its MCP descriptor before sign-in. Omission and explicit 'authorized' preserve filtered discovery and compile identically. Visibility grants no execution or product-skill eligibility; scopes remain ALL and roles ANY. Noodle derives securitySchemes; never author them.
248
+ For mixed customer preview, keep server customerAuth and adopt on the same org/app/env, endpoint, issuer and audience; keep the separate public Help endpoint during the pilot, and never create overlapping active issuer/audience ownership. Before any mixed deploy or access change, leave only Help unrestricted, add authorization to every customer tool, and validate plus preview with `noodle dev --access mixed`. For an existing customer-only app, first run `noodle deployments list --org <org> --app <app> --env <env> --json` and inspect an inactive `customers` record for the exact server version. If none exists, record the active ID, redeploy the unchanged secured source to the same version with `--access customers`, then list and inspect again to prove that ID is now inactive; recording it alone preserves nothing. Next deploy the policy-prepared source with `--access customers`, verify the original rollback record remains inactive, and only then run `noodle access set mixed ... --version <version>`. On pilot failure use `noodle rollback <deployment-id> --org <org> --app <app> --env <env> --reason <text>`. This app-history rollback differs from the compatible hosted service-release floor. Invalid supplied credentials fail, with no platform-human fallback. Broker exchange remains required. Local Devtools retries after successful sign-in and leaves Help available after cancellation without executing the protected tool. After deployment, test anonymous discovery, sign-in, cancellation, authenticated retry and expiry in the actual host before customer cutover; local/SDK checks do not prove ChatGPT or another host.
249
+
250
+ Role values are trusted only from the explicitly configured claim path (or the platform-private bridge role claim). Direct OIDC scopes default to standard `scope`, `scp`, or `scopes` claims unless `claims.scopes` is configured. Embedded-assistant backends pass verified `user.roles` and `user.scopes` separately during `createAssistantSession(...)`; page context never grants either. Claim values must be a string or string array; malformed or oversized values fail closed. Tools retain authored order in `tools/list`; protected descriptors are omitted unless explicitly public, and an unauthorized direct call is still denied before argument validation or connector execution. Scope denials use MCP OAuth step-up metadata without disclosing role names.
248
251
 
249
252
  ## Delegated downstream auth (call your API as the signed-in user)
250
253