@noodleseed/agent-kit 0.58.2 → 0.59.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 (32) hide show
  1. package/manifest.json +243 -243
  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/building-mcp-apps/SKILL.md +1 -1
  6. package/skills/claude-code/connecting-apis-to-mcp/SKILL.md +1 -1
  7. package/skills/claude-code/debugging-mcp-delivery/SKILL.md +1 -1
  8. package/skills/claude-code/deploying-mcp-services/SKILL.md +1 -1
  9. package/skills/claude-code/designing-mcp-products/SKILL.md +1 -1
  10. package/skills/claude-code/embedding-mcp-assistants/SKILL.md +1 -1
  11. package/skills/claude-code/examples/customer-auth/README.md +14 -9
  12. package/skills/claude-code/executing-noodle-plans/SKILL.md +1 -1
  13. package/skills/claude-code/publishing-mcp-integrations/SKILL.md +1 -1
  14. package/skills/claude-code/references/authoring-workflow.md +1 -1
  15. package/skills/claude-code/references/embedded-assistant.md +31 -2
  16. package/skills/claude-code/reporting-noodle-feedback/SKILL.md +1 -1
  17. package/skills/claude-code/verifying-mcp-delivery/SKILL.md +1 -1
  18. package/skills/codex/SKILL.md +1 -1
  19. package/skills/codex/authoring-mcp-servers/SKILL.md +1 -1
  20. package/skills/codex/building-mcp-apps/SKILL.md +1 -1
  21. package/skills/codex/connecting-apis-to-mcp/SKILL.md +1 -1
  22. package/skills/codex/debugging-mcp-delivery/SKILL.md +1 -1
  23. package/skills/codex/deploying-mcp-services/SKILL.md +1 -1
  24. package/skills/codex/designing-mcp-products/SKILL.md +1 -1
  25. package/skills/codex/embedding-mcp-assistants/SKILL.md +1 -1
  26. package/skills/codex/examples/customer-auth/README.md +14 -9
  27. package/skills/codex/executing-noodle-plans/SKILL.md +1 -1
  28. package/skills/codex/publishing-mcp-integrations/SKILL.md +1 -1
  29. package/skills/codex/references/authoring-workflow.md +1 -1
  30. package/skills/codex/references/embedded-assistant.md +31 -2
  31. package/skills/codex/reporting-noodle-feedback/SKILL.md +1 -1
  32. package/skills/codex/verifying-mcp-delivery/SKILL.md +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noodleseed/agent-kit",
3
- "version": "0.58.2",
3
+ "version": "0.59.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.58.2 hash:ec5bfcd0d8165205 -->
6
+ <!-- noodle-skill version:0.59.0 hash:ec5bfcd0d8165205 -->
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.58.2 hash:0b2fd8c7e43fc69f -->
6
+ <!-- noodle-skill version:0.59.0 hash:0b2fd8c7e43fc69f -->
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.58.2 hash:f7fa54992c8d7692 -->
6
+ <!-- noodle-skill version:0.59.0 hash:f7fa54992c8d7692 -->
7
7
 
8
8
  # building-mcp-apps
9
9
 
@@ -3,7 +3,7 @@ name: connecting-apis-to-mcp
3
3
  description: "Use when credentials, an API URL, an OpenAPI document, or an observed response must become real Noodle Seed MCP behavior."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.58.2 hash:1e86b8704f407bd3 -->
6
+ <!-- noodle-skill version:0.59.0 hash:1e86b8704f407bd3 -->
7
7
 
8
8
  # connecting-apis-to-mcp
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.58.2 hash:aa715bae12041d7c -->
6
+ <!-- noodle-skill version:0.59.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.58.2 hash:93e735b7ffb45df1 -->
6
+ <!-- noodle-skill version:0.59.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.58.2 hash:76cce86729cffbee -->
6
+ <!-- noodle-skill version:0.59.0 hash:76cce86729cffbee -->
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.58.2 hash:cc54a67f21c0ecdb -->
6
+ <!-- noodle-skill version:0.59.0 hash:cc54a67f21c0ecdb -->
7
7
 
8
8
  # embedding-mcp-assistants
9
9
 
@@ -4,9 +4,9 @@ This curated example owns the customer/end-user authentication capability slot.
4
4
  can protect an MCP endpoint with direct OIDC, retain role/scope-based tool authorization, and route ordinary
5
5
  reads and confirmed actions to the API origin selected by the verified customer's identity provider.
6
6
 
7
- It also owns the customer-branded embedded-assistant presentation showcase. Embedded sessions lack
8
- direct/federated MCP OIDC endpoint claims, so these routed tools fail with `connector_route_unavailable`;
9
- static connectors still support embedded delegated exchange. Exercise routed tools through the MCP endpoint.
7
+ It also owns the customer-branded embedded-assistant presentation showcase. Direct MCP calls obtain the
8
+ route from the verified OIDC claim; embedded sessions obtain it from the authenticated customer backend's
9
+ session exchange. Both paths keep the URL outside tool/model/browser-visible state.
10
10
 
11
11
  The public developer entrypoint is [`src/server.ts`](src/server.ts). It exposes a deliberately small MCP
12
12
  surface for organization discovery and app lifecycle operations:
@@ -171,7 +171,9 @@ and refresh, then maps approved versions of this app/environment to `noodleseed-
171
171
  apps and environments use distinct audiences.
172
172
 
173
173
  Run `noodle auth doctor src/server.ts` before sharing. Its bounded, read-only probes never register a client.
174
- Adding the embedded assistant does not choose or rewrite MCP customer auth.
174
+ Adding the embedded assistant does not choose or rewrite MCP customer auth. Its authenticated backend may
175
+ bind `routing.endpoints.customer_api` during assistant-session exchange from server-owned membership data;
176
+ direct MCP requests continue to resolve the same endpoint from the configured verified OIDC claim.
175
177
 
176
178
  ## Per-tool authorization remains independent
177
179
 
@@ -331,9 +333,11 @@ The embedded assistant uses a customer-supplied OpenAI Chat Completions-compatib
331
333
  managed values at the Noodle deployment environment; none of these values belongs in the customer web
332
334
  application environment, and the API key never reaches the browser:
333
335
 
334
- The assistant session carries a verified user, tenant, deployment, roles, and scopes, but not the IdP's
335
- `tenant.api_base_url` claim. These routed operations are MCP-only; do not copy the route into page context,
336
- session claims, tool input, or model instructions.
336
+ The assistant session carries a verified user, tenant, deployment, roles, and scopes. For this flagship's
337
+ routed tools, the embedding backend resolves the signed-in user's cluster from server-owned membership data
338
+ and passes `routing: { endpoints: { customer_api: cluster.apiBaseUrl } }` to
339
+ `createAssistantSession`. Noodle validates and privately stores that route; it is not returned to the
340
+ browser. Do not copy the route into page context, session claims, tool input, or model instructions.
337
341
 
338
342
  ```bash
339
343
  noodle variables set ASSISTANT_MODEL_BASE_URL https://model.example.com/v1 --scope env
@@ -536,8 +540,9 @@ After deployment, use the assistant doctor to verify the embed client, model, an
536
540
  noodle assistant doctor --user-id <real-test-user> --origin "$PUBLIC_APP_ORIGIN" --org <org> --app <app> --env <env>
537
541
  ```
538
542
 
539
- This does not add an OIDC customer route. Routed operations succeed only through a direct/federated
540
- customer-authenticated MCP request with an allowed endpoint claim.
543
+ The doctor does not invent or test an application-specific customer route. Prove routed assistant tools by
544
+ having the authenticated embedding backend pass the user's server-verified endpoint during session
545
+ exchange, then invoke one representative safe read.
541
546
 
542
547
  If the application deliberately sends a first turn on mount, do not combine a persistent "sent" ref with a
543
548
  mount effect. React Strict Mode can abort that provisional request and then suppress the stable remount.
@@ -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.58.2 hash:6a9f132ddb79352e -->
6
+ <!-- noodle-skill version:0.59.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.58.2 hash:efffbf82007f935d -->
6
+ <!-- noodle-skill version:0.59.0 hash:efffbf82007f935d -->
7
7
 
8
8
  # publishing-mcp-integrations
9
9
 
@@ -230,7 +230,7 @@ Role values are trusted only from the explicitly configured claim path (or the p
230
230
 
231
231
  Use delegated connector auth when the downstream API must enforce its own per-user authorization — a shared service credential plus a forwarded user id would bypass it. Three shapes exist; pick by who owns the downstream:
232
232
 
233
- - **`delegatedTokenExchange`** — your own API. The platform signs a short-lived, verifiable assertion of the signed-in user and exchanges it at a token endpoint you implement (RFC 8693). It works with verified customer OIDC identities and the built-in Firebase/Microsoft adapters; no per-user OAuth enrollment. Embedded-assistant sessions support this exchange for static connectors. Customer-routed connectors require a direct or federated MCP OIDC request and fail closed in embedded-assistant sessions because those sessions carry no IdP endpoint claim.
233
+ - **`delegatedTokenExchange`** — your own API. The platform signs a short-lived, verifiable assertion of the signed-in user and exchanges it at a token endpoint you implement (RFC 8693). It works with verified customer OIDC identities and the built-in Firebase/Microsoft adapters; no per-user OAuth enrollment. Embedded-assistant sessions can bind customer-routed connectors when the authenticated embedding backend resolves each route from server-owned tenancy data and passes it during session exchange. Browser input, page context, session claims, and tool arguments cannot supply or override that private route authority.
234
234
  - **`delegatedOAuth` with `provider: "firebase" | "microsoft"`** — Noodle-managed bridge providers using stored per-user refresh tokens. Requires the matching `customerAuth` bridge; any other provider string is the compile error `unsupported_delegated_provider`.
235
235
  - **`delegatedSessionCookie`** — Firebase-managed session-cookie apps only; not a generic mechanism.
236
236
 
@@ -128,13 +128,13 @@ noodle assistant clients create --name web --org <org> --app <app> --env <env>
128
128
 
129
129
  The CLI writes `{ clientId, clientSecret }` to a mode-`0600` file and prints only its path. Move the values into the SaaS backend secret manager without printing or committing them. Rotation invalidates the previous secret.
130
130
 
131
- Validate the active deployment, backend credential, exact origin, and delegated credential exchanges without invoking a business tool:
131
+ Validate the active deployment, backend credential, exact origin, and delegated credential exchanges that do not require an application-specific customer route:
132
132
 
133
133
  ```sh
134
134
  noodle assistant doctor --origin "$PUBLIC_APP_ORIGIN" --org <org> --app <app> --env <env>
135
135
  ```
136
136
 
137
- The doctor reads `NOODLE_ASSISTANT_CLIENT_ID` / `NOODLE_ASSISTANT_CLIENT_SECRET` or the saved mode-0600 client file and never prints the secret. Pass `--user-id <real-test-user>` only when the downstream exchange requires an existing application user.
137
+ The doctor reads `NOODLE_ASSISTANT_CLIENT_ID` / `NOODLE_ASSISTANT_CLIENT_SECRET` or the saved mode-0600 client file and never prints the secret. Pass `--user-id <real-test-user>` only when the downstream exchange requires an existing application user. The assistant doctor does not supply application-specific routes; after the backend mints a routed session, invoke one representative safe read to verify its route-bound exchange and connector together.
138
138
 
139
139
  ## Integrate the customer backend
140
140
 
@@ -171,6 +171,32 @@ Authenticate before exchange. Pass backend-verified `user.roles` and OAuth-style
171
171
 
172
172
  `serviceUrl` is the Noodle Seed control-plane base URL: the value `noodle assistant clients create` prints, also stored as `serviceUrl` in `deployment.json`. It is NOT the deployment MCP endpoint (`url`, which ends in `/v1/mcp` and rejects session exchange). Never probe or guess endpoints with real credentials.
173
173
 
174
+ ### Route customer endpoints from the backend
175
+
176
+ When a connector uses `customerEndpoint("customer_api", ...)`, resolve the signed-in user's API base URL from authenticated, server-owned tenancy data and bind it during session exchange:
177
+
178
+ ```ts
179
+ const user = await requireCurrentUser(request);
180
+ const account = await requireAccountMembership(user.id);
181
+
182
+ const session = await createAssistantSession({
183
+ serviceUrl,
184
+ clientId,
185
+ clientSecret,
186
+ origin,
187
+ user: { id: user.id, email: user.email },
188
+ routing: {
189
+ endpoints: {
190
+ customer_api: account.clusterApiBaseUrl,
191
+ },
192
+ },
193
+ });
194
+ ```
195
+
196
+ The browser does not send `routing`. Authenticate the user and validate account/cluster membership before selecting the URL. Never read it from page context, request headers, session claims, tool arguments, or model output. The endpoint key must match the authored `customerEndpoint` name. Noodle validates the canonical HTTPS URL against the active artifact policy, stores it only in the private short-lived session, and omits it from the session response and caller identity.
197
+
198
+ Routing is optional: static tools continue to work, while a tool whose endpoint was omitted fails closed with `connector_route_unavailable` before credential or connector egress. A confirmed routed action binds a URL-blind fingerprint at proposal time and rejects a missing or changed route on acceptance.
199
+
174
200
  ## Ground time and ambient facts
175
201
 
176
202
  Every assistant turn receives a server-authoritative instant and user-local date/time. Locale and IANA time zone resolve in this order: backend-verified `preferences` from session exchange, fresh per-turn browser `clientContext` hints, `server.context.defaults`, then platform defaults (`en-US`/`UTC`). Browser hints affect presentation and relative-date interpretation only; they are untrusted and never authorize a tool.
@@ -515,6 +541,7 @@ Devtools privacy gate: default model and connector exercises to synthetic or moc
515
541
  - An expired turn re-exchanges once; interaction decisions never auto-retry. An explicit same-decision repeat returns the stored outcome without executing again.
516
542
  - Accept, decline, and cancel are single-use. Only accept executes; the server ignores replacement tool arguments.
517
543
  - Wrong-origin and malformed-origin requests fail closed.
544
+ - Browser-controlled fields cannot select or override `routing.endpoints`; a customer-routed connector uses only the backend-verified session route.
518
545
  - Run the production-equivalent host build after regenerating environment bindings.
519
546
  - In a real browser, submit with the keyboard, inspect console and network failures, complete session exchange and one tool turn, and render one linked App before claiming the host works.
520
547
 
@@ -530,6 +557,8 @@ Devtools privacy gate: default model and connector exercises to synthetic or moc
530
557
  | Validate rejects an origin | Non-loopback HTTP origin in `allowedOrigins` | Use the exact HTTPS production origin; HTTP is only for `localhost`/`127.0.0.1` |
531
558
  | Session exchange returns 404 | `serviceUrl` points at the deployment MCP endpoint | Use the control-plane service URL printed by `noodle assistant clients create` |
532
559
  | Session exchange returns 403 `origin is not allowed` | Request origin differs from `allowedOrigins` character-for-character | Align the exact scheme/host/port on both sides and redeploy |
560
+ | Session exchange returns `400` with `invalid assistant routing` | The authenticated backend supplied an unknown endpoint name or a malformed/policy-disallowed URL | Resolve the route from server-owned membership, use the exact authored endpoint name, and ensure the canonical HTTPS URL satisfies its active `customerEndpoint` policy; the error never reflects the URL |
561
+ | A routed assistant tool returns `connector_route_unavailable` | The authenticated backend omitted that endpoint during session exchange | Pass the server-verified route as `routing.endpoints.<name>` when minting a new session; keep it out of browser input |
533
562
  | Host session 503 | A required backend environment name is absent or mapped into the wrong deployment environment | Run `noodle assistant embed --check --json`, repair the host CI mapping, then probe the session route again |
534
563
  | `HEAD` on a widget or session path looks broken | The route contract is `GET` for the hosted sandbox/widget document or `POST` for session exchange; `HEAD` is not the product flow | Exercise the documented method and inspect its response instead of inferring readiness from `HEAD` |
535
564
  | Local server reports `listen EPERM` | The coding sandbox blocked loopback binding before application behavior ran | Rerun the same local/browser test with approved loopback permissions; do not change product code |
@@ -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.58.2 hash:0f404109f4845683 -->
6
+ <!-- noodle-skill version:0.59.0 hash:0f404109f4845683 -->
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.58.2 hash:6ef6ef551e26b78e -->
6
+ <!-- noodle-skill version:0.59.0 hash:6ef6ef551e26b78e -->
7
7
 
8
8
  # verifying-mcp-delivery
9
9
 
@@ -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.58.2 hash:ec5bfcd0d8165205 -->
6
+ <!-- noodle-skill version:0.59.0 hash:ec5bfcd0d8165205 -->
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.58.2 hash:0b2fd8c7e43fc69f -->
6
+ <!-- noodle-skill version:0.59.0 hash:0b2fd8c7e43fc69f -->
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.58.2 hash:f7fa54992c8d7692 -->
6
+ <!-- noodle-skill version:0.59.0 hash:f7fa54992c8d7692 -->
7
7
 
8
8
  # building-mcp-apps
9
9
 
@@ -3,7 +3,7 @@ name: connecting-apis-to-mcp
3
3
  description: "Use when credentials, an API URL, an OpenAPI document, or an observed response must become real Noodle Seed MCP behavior."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.58.2 hash:1e86b8704f407bd3 -->
6
+ <!-- noodle-skill version:0.59.0 hash:1e86b8704f407bd3 -->
7
7
 
8
8
  # connecting-apis-to-mcp
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.58.2 hash:aa715bae12041d7c -->
6
+ <!-- noodle-skill version:0.59.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.58.2 hash:93e735b7ffb45df1 -->
6
+ <!-- noodle-skill version:0.59.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.58.2 hash:76cce86729cffbee -->
6
+ <!-- noodle-skill version:0.59.0 hash:76cce86729cffbee -->
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.58.2 hash:cc54a67f21c0ecdb -->
6
+ <!-- noodle-skill version:0.59.0 hash:cc54a67f21c0ecdb -->
7
7
 
8
8
  # embedding-mcp-assistants
9
9
 
@@ -4,9 +4,9 @@ This curated example owns the customer/end-user authentication capability slot.
4
4
  can protect an MCP endpoint with direct OIDC, retain role/scope-based tool authorization, and route ordinary
5
5
  reads and confirmed actions to the API origin selected by the verified customer's identity provider.
6
6
 
7
- It also owns the customer-branded embedded-assistant presentation showcase. Embedded sessions lack
8
- direct/federated MCP OIDC endpoint claims, so these routed tools fail with `connector_route_unavailable`;
9
- static connectors still support embedded delegated exchange. Exercise routed tools through the MCP endpoint.
7
+ It also owns the customer-branded embedded-assistant presentation showcase. Direct MCP calls obtain the
8
+ route from the verified OIDC claim; embedded sessions obtain it from the authenticated customer backend's
9
+ session exchange. Both paths keep the URL outside tool/model/browser-visible state.
10
10
 
11
11
  The public developer entrypoint is [`src/server.ts`](src/server.ts). It exposes a deliberately small MCP
12
12
  surface for organization discovery and app lifecycle operations:
@@ -171,7 +171,9 @@ and refresh, then maps approved versions of this app/environment to `noodleseed-
171
171
  apps and environments use distinct audiences.
172
172
 
173
173
  Run `noodle auth doctor src/server.ts` before sharing. Its bounded, read-only probes never register a client.
174
- Adding the embedded assistant does not choose or rewrite MCP customer auth.
174
+ Adding the embedded assistant does not choose or rewrite MCP customer auth. Its authenticated backend may
175
+ bind `routing.endpoints.customer_api` during assistant-session exchange from server-owned membership data;
176
+ direct MCP requests continue to resolve the same endpoint from the configured verified OIDC claim.
175
177
 
176
178
  ## Per-tool authorization remains independent
177
179
 
@@ -331,9 +333,11 @@ The embedded assistant uses a customer-supplied OpenAI Chat Completions-compatib
331
333
  managed values at the Noodle deployment environment; none of these values belongs in the customer web
332
334
  application environment, and the API key never reaches the browser:
333
335
 
334
- The assistant session carries a verified user, tenant, deployment, roles, and scopes, but not the IdP's
335
- `tenant.api_base_url` claim. These routed operations are MCP-only; do not copy the route into page context,
336
- session claims, tool input, or model instructions.
336
+ The assistant session carries a verified user, tenant, deployment, roles, and scopes. For this flagship's
337
+ routed tools, the embedding backend resolves the signed-in user's cluster from server-owned membership data
338
+ and passes `routing: { endpoints: { customer_api: cluster.apiBaseUrl } }` to
339
+ `createAssistantSession`. Noodle validates and privately stores that route; it is not returned to the
340
+ browser. Do not copy the route into page context, session claims, tool input, or model instructions.
337
341
 
338
342
  ```bash
339
343
  noodle variables set ASSISTANT_MODEL_BASE_URL https://model.example.com/v1 --scope env
@@ -536,8 +540,9 @@ After deployment, use the assistant doctor to verify the embed client, model, an
536
540
  noodle assistant doctor --user-id <real-test-user> --origin "$PUBLIC_APP_ORIGIN" --org <org> --app <app> --env <env>
537
541
  ```
538
542
 
539
- This does not add an OIDC customer route. Routed operations succeed only through a direct/federated
540
- customer-authenticated MCP request with an allowed endpoint claim.
543
+ The doctor does not invent or test an application-specific customer route. Prove routed assistant tools by
544
+ having the authenticated embedding backend pass the user's server-verified endpoint during session
545
+ exchange, then invoke one representative safe read.
541
546
 
542
547
  If the application deliberately sends a first turn on mount, do not combine a persistent "sent" ref with a
543
548
  mount effect. React Strict Mode can abort that provisional request and then suppress the stable remount.
@@ -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.58.2 hash:6a9f132ddb79352e -->
6
+ <!-- noodle-skill version:0.59.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.58.2 hash:efffbf82007f935d -->
6
+ <!-- noodle-skill version:0.59.0 hash:efffbf82007f935d -->
7
7
 
8
8
  # publishing-mcp-integrations
9
9
 
@@ -230,7 +230,7 @@ Role values are trusted only from the explicitly configured claim path (or the p
230
230
 
231
231
  Use delegated connector auth when the downstream API must enforce its own per-user authorization — a shared service credential plus a forwarded user id would bypass it. Three shapes exist; pick by who owns the downstream:
232
232
 
233
- - **`delegatedTokenExchange`** — your own API. The platform signs a short-lived, verifiable assertion of the signed-in user and exchanges it at a token endpoint you implement (RFC 8693). It works with verified customer OIDC identities and the built-in Firebase/Microsoft adapters; no per-user OAuth enrollment. Embedded-assistant sessions support this exchange for static connectors. Customer-routed connectors require a direct or federated MCP OIDC request and fail closed in embedded-assistant sessions because those sessions carry no IdP endpoint claim.
233
+ - **`delegatedTokenExchange`** — your own API. The platform signs a short-lived, verifiable assertion of the signed-in user and exchanges it at a token endpoint you implement (RFC 8693). It works with verified customer OIDC identities and the built-in Firebase/Microsoft adapters; no per-user OAuth enrollment. Embedded-assistant sessions can bind customer-routed connectors when the authenticated embedding backend resolves each route from server-owned tenancy data and passes it during session exchange. Browser input, page context, session claims, and tool arguments cannot supply or override that private route authority.
234
234
  - **`delegatedOAuth` with `provider: "firebase" | "microsoft"`** — Noodle-managed bridge providers using stored per-user refresh tokens. Requires the matching `customerAuth` bridge; any other provider string is the compile error `unsupported_delegated_provider`.
235
235
  - **`delegatedSessionCookie`** — Firebase-managed session-cookie apps only; not a generic mechanism.
236
236
 
@@ -128,13 +128,13 @@ noodle assistant clients create --name web --org <org> --app <app> --env <env>
128
128
 
129
129
  The CLI writes `{ clientId, clientSecret }` to a mode-`0600` file and prints only its path. Move the values into the SaaS backend secret manager without printing or committing them. Rotation invalidates the previous secret.
130
130
 
131
- Validate the active deployment, backend credential, exact origin, and delegated credential exchanges without invoking a business tool:
131
+ Validate the active deployment, backend credential, exact origin, and delegated credential exchanges that do not require an application-specific customer route:
132
132
 
133
133
  ```sh
134
134
  noodle assistant doctor --origin "$PUBLIC_APP_ORIGIN" --org <org> --app <app> --env <env>
135
135
  ```
136
136
 
137
- The doctor reads `NOODLE_ASSISTANT_CLIENT_ID` / `NOODLE_ASSISTANT_CLIENT_SECRET` or the saved mode-0600 client file and never prints the secret. Pass `--user-id <real-test-user>` only when the downstream exchange requires an existing application user.
137
+ The doctor reads `NOODLE_ASSISTANT_CLIENT_ID` / `NOODLE_ASSISTANT_CLIENT_SECRET` or the saved mode-0600 client file and never prints the secret. Pass `--user-id <real-test-user>` only when the downstream exchange requires an existing application user. The assistant doctor does not supply application-specific routes; after the backend mints a routed session, invoke one representative safe read to verify its route-bound exchange and connector together.
138
138
 
139
139
  ## Integrate the customer backend
140
140
 
@@ -171,6 +171,32 @@ Authenticate before exchange. Pass backend-verified `user.roles` and OAuth-style
171
171
 
172
172
  `serviceUrl` is the Noodle Seed control-plane base URL: the value `noodle assistant clients create` prints, also stored as `serviceUrl` in `deployment.json`. It is NOT the deployment MCP endpoint (`url`, which ends in `/v1/mcp` and rejects session exchange). Never probe or guess endpoints with real credentials.
173
173
 
174
+ ### Route customer endpoints from the backend
175
+
176
+ When a connector uses `customerEndpoint("customer_api", ...)`, resolve the signed-in user's API base URL from authenticated, server-owned tenancy data and bind it during session exchange:
177
+
178
+ ```ts
179
+ const user = await requireCurrentUser(request);
180
+ const account = await requireAccountMembership(user.id);
181
+
182
+ const session = await createAssistantSession({
183
+ serviceUrl,
184
+ clientId,
185
+ clientSecret,
186
+ origin,
187
+ user: { id: user.id, email: user.email },
188
+ routing: {
189
+ endpoints: {
190
+ customer_api: account.clusterApiBaseUrl,
191
+ },
192
+ },
193
+ });
194
+ ```
195
+
196
+ The browser does not send `routing`. Authenticate the user and validate account/cluster membership before selecting the URL. Never read it from page context, request headers, session claims, tool arguments, or model output. The endpoint key must match the authored `customerEndpoint` name. Noodle validates the canonical HTTPS URL against the active artifact policy, stores it only in the private short-lived session, and omits it from the session response and caller identity.
197
+
198
+ Routing is optional: static tools continue to work, while a tool whose endpoint was omitted fails closed with `connector_route_unavailable` before credential or connector egress. A confirmed routed action binds a URL-blind fingerprint at proposal time and rejects a missing or changed route on acceptance.
199
+
174
200
  ## Ground time and ambient facts
175
201
 
176
202
  Every assistant turn receives a server-authoritative instant and user-local date/time. Locale and IANA time zone resolve in this order: backend-verified `preferences` from session exchange, fresh per-turn browser `clientContext` hints, `server.context.defaults`, then platform defaults (`en-US`/`UTC`). Browser hints affect presentation and relative-date interpretation only; they are untrusted and never authorize a tool.
@@ -515,6 +541,7 @@ Devtools privacy gate: default model and connector exercises to synthetic or moc
515
541
  - An expired turn re-exchanges once; interaction decisions never auto-retry. An explicit same-decision repeat returns the stored outcome without executing again.
516
542
  - Accept, decline, and cancel are single-use. Only accept executes; the server ignores replacement tool arguments.
517
543
  - Wrong-origin and malformed-origin requests fail closed.
544
+ - Browser-controlled fields cannot select or override `routing.endpoints`; a customer-routed connector uses only the backend-verified session route.
518
545
  - Run the production-equivalent host build after regenerating environment bindings.
519
546
  - In a real browser, submit with the keyboard, inspect console and network failures, complete session exchange and one tool turn, and render one linked App before claiming the host works.
520
547
 
@@ -530,6 +557,8 @@ Devtools privacy gate: default model and connector exercises to synthetic or moc
530
557
  | Validate rejects an origin | Non-loopback HTTP origin in `allowedOrigins` | Use the exact HTTPS production origin; HTTP is only for `localhost`/`127.0.0.1` |
531
558
  | Session exchange returns 404 | `serviceUrl` points at the deployment MCP endpoint | Use the control-plane service URL printed by `noodle assistant clients create` |
532
559
  | Session exchange returns 403 `origin is not allowed` | Request origin differs from `allowedOrigins` character-for-character | Align the exact scheme/host/port on both sides and redeploy |
560
+ | Session exchange returns `400` with `invalid assistant routing` | The authenticated backend supplied an unknown endpoint name or a malformed/policy-disallowed URL | Resolve the route from server-owned membership, use the exact authored endpoint name, and ensure the canonical HTTPS URL satisfies its active `customerEndpoint` policy; the error never reflects the URL |
561
+ | A routed assistant tool returns `connector_route_unavailable` | The authenticated backend omitted that endpoint during session exchange | Pass the server-verified route as `routing.endpoints.<name>` when minting a new session; keep it out of browser input |
533
562
  | Host session 503 | A required backend environment name is absent or mapped into the wrong deployment environment | Run `noodle assistant embed --check --json`, repair the host CI mapping, then probe the session route again |
534
563
  | `HEAD` on a widget or session path looks broken | The route contract is `GET` for the hosted sandbox/widget document or `POST` for session exchange; `HEAD` is not the product flow | Exercise the documented method and inspect its response instead of inferring readiness from `HEAD` |
535
564
  | Local server reports `listen EPERM` | The coding sandbox blocked loopback binding before application behavior ran | Rerun the same local/browser test with approved loopback permissions; do not change product code |
@@ -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.58.2 hash:0f404109f4845683 -->
6
+ <!-- noodle-skill version:0.59.0 hash:0f404109f4845683 -->
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.58.2 hash:6ef6ef551e26b78e -->
6
+ <!-- noodle-skill version:0.59.0 hash:6ef6ef551e26b78e -->
7
7
 
8
8
  # verifying-mcp-delivery
9
9