@noodleseed/one 0.137.0 → 0.139.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 (185) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/cli.js.map +1 -1
  3. package/dist/commands/assistant-ops.d.ts.map +1 -1
  4. package/dist/commands/assistant-ops.js +30 -1
  5. package/dist/commands/assistant-ops.js.map +1 -1
  6. package/dist/commands/deploy-first-flow.d.ts +2 -0
  7. package/dist/commands/deploy-first-flow.d.ts.map +1 -1
  8. package/dist/commands/deploy-first-flow.js +46 -14
  9. package/dist/commands/deploy-first-flow.js.map +1 -1
  10. package/dist/commands/deploy-ops.d.ts.map +1 -1
  11. package/dist/commands/deploy-ops.js +27 -1
  12. package/dist/commands/deploy-ops.js.map +1 -1
  13. package/dist/commands/deploy-preflight.d.ts +1 -0
  14. package/dist/commands/deploy-preflight.d.ts.map +1 -1
  15. package/dist/commands/deploy-preflight.js +1 -0
  16. package/dist/commands/deploy-preflight.js.map +1 -1
  17. package/dist/commands/deploy-status-ops.d.ts +1 -0
  18. package/dist/commands/deploy-status-ops.d.ts.map +1 -1
  19. package/dist/commands/deploy-status-ops.js +59 -4
  20. package/dist/commands/deploy-status-ops.js.map +1 -1
  21. package/dist/commands/deployments-ops.d.ts.map +1 -1
  22. package/dist/commands/deployments-ops.js +2 -0
  23. package/dist/commands/deployments-ops.js.map +1 -1
  24. package/dist/commands/diagnostics-ops.d.ts +1 -0
  25. package/dist/commands/diagnostics-ops.d.ts.map +1 -1
  26. package/dist/commands/diagnostics-ops.js +3 -0
  27. package/dist/commands/diagnostics-ops.js.map +1 -1
  28. package/dist/commands/import.d.ts +4 -0
  29. package/dist/commands/import.d.ts.map +1 -0
  30. package/dist/commands/import.js +198 -0
  31. package/dist/commands/import.js.map +1 -0
  32. package/dist/commands/project-setup.d.ts +1 -1
  33. package/dist/commands/project-setup.d.ts.map +1 -1
  34. package/dist/commands/project-setup.js +2 -48
  35. package/dist/commands/project-setup.js.map +1 -1
  36. package/dist/commands/service-ops.d.ts.map +1 -1
  37. package/dist/commands/service-ops.js +44 -51
  38. package/dist/commands/service-ops.js.map +1 -1
  39. package/dist/deploy.d.ts +3 -0
  40. package/dist/deploy.d.ts.map +1 -1
  41. package/dist/deploy.js +4 -0
  42. package/dist/deploy.js.map +1 -1
  43. package/dist/index.d.ts +1 -1
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +1 -1
  46. package/dist/index.js.map +1 -1
  47. package/dist/mcp-import.d.ts +22 -0
  48. package/dist/mcp-import.d.ts.map +1 -0
  49. package/dist/mcp-import.js +91 -0
  50. package/dist/mcp-import.js.map +1 -0
  51. package/dist/self-host-init.d.ts +23 -0
  52. package/dist/self-host-init.d.ts.map +1 -0
  53. package/dist/self-host-init.js +315 -0
  54. package/dist/self-host-init.js.map +1 -0
  55. package/node_modules/@noodle-borg/admission-limits/dist/envelope.js +1 -1
  56. package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js +6 -6
  57. package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js +1 -0
  58. package/node_modules/@noodle-borg/agent-kit/dist/skill-authoring-refs.js +11 -2
  59. package/node_modules/@noodle-borg/agent-kit/dist/skill-connect-refs.js +31 -1
  60. package/node_modules/@noodle-borg/agent-kit/dist/skill-content.js +3 -2
  61. package/node_modules/@noodle-borg/agent-kit/dist/skill-embedded-assistant-ref.js +6 -7
  62. package/node_modules/@noodle-borg/agent-kit/package.json +1 -1
  63. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-guide.d.ts +1 -0
  64. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-guide.js +35 -1
  65. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-store.d.ts +6 -2
  66. package/node_modules/@noodle-borg/assistant-gateway/dist/assistant-store.js +5 -2
  67. package/node_modules/@noodle-borg/assistant-gateway/dist/model-request.js +37 -0
  68. package/node_modules/@noodle-borg/assistant-gateway/dist/model-runtime.js +4 -0
  69. package/node_modules/@noodle-borg/{service/dist/assistant-model-stream.js → assistant-gateway/dist/model-stream.js} +34 -2
  70. package/node_modules/@noodle-borg/assistant-gateway/dist/public-session.d.ts +3 -0
  71. package/node_modules/@noodle-borg/assistant-gateway/dist/public-session.js +2 -1
  72. package/node_modules/@noodle-borg/assistant-gateway/dist/public-turn.d.ts +4 -1
  73. package/node_modules/@noodle-borg/assistant-gateway/dist/public-turn.js +2 -1
  74. package/node_modules/@noodle-borg/assistant-gateway/dist/surface-budget.d.ts +6 -1
  75. package/node_modules/@noodle-borg/assistant-gateway/dist/surface-budget.js +11 -5
  76. package/node_modules/@noodle-borg/assistant-gateway/package.json +5 -1
  77. package/node_modules/@noodle-borg/authoring/dist/assistant.d.ts +10 -2
  78. package/node_modules/@noodle-borg/authoring/dist/assistant.js +4 -0
  79. package/node_modules/@noodle-borg/authoring/dist/connections.js +1 -0
  80. package/node_modules/@noodle-borg/authoring/dist/connectors.d.ts +25 -3
  81. package/node_modules/@noodle-borg/authoring/dist/connectors.js +82 -7
  82. package/node_modules/@noodle-borg/authoring/dist/index.d.ts +2 -2
  83. package/node_modules/@noodle-borg/authoring/dist/index.js +1 -1
  84. package/node_modules/@noodle-borg/authoring/dist/load-authored.js +1 -1
  85. package/node_modules/@noodle-borg/authoring/dist/model-tool-visibility.js +33 -0
  86. package/node_modules/@noodle-borg/authoring/dist/server.d.ts +5 -0
  87. package/node_modules/@noodle-borg/authoring/dist/server.js +7 -2
  88. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-account.js +13 -1
  89. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-assistant.js +17 -0
  90. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-bootstrap-authoring.js +30 -1
  91. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-hosted-deployment.js +14 -0
  92. package/node_modules/@noodle-borg/compiler/dist/artifact/types.d.ts +1 -7
  93. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts +20 -8
  94. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.js +12 -8
  95. package/node_modules/@noodle-borg/connector-defs/dist/call-graph.js +1 -1
  96. package/node_modules/@noodle-borg/connector-defs/dist/compile-mcp.js +95 -0
  97. package/node_modules/@noodle-borg/connector-defs/dist/compile.js +4 -0
  98. package/node_modules/@noodle-borg/connector-defs/dist/customer-routing.js +1 -1
  99. package/node_modules/@noodle-borg/connector-defs/dist/index.d.ts +1 -1
  100. package/node_modules/@noodle-borg/connector-defs/dist/schema.d.ts +642 -3
  101. package/node_modules/@noodle-borg/connector-defs/dist/schema.js +143 -1
  102. package/node_modules/@noodle-borg/connector-http/dist/index.d.ts +1 -0
  103. package/node_modules/@noodle-borg/connector-http/dist/index.js +1 -0
  104. package/node_modules/@noodle-borg/connector-http/dist/mcp/config.js +76 -0
  105. package/node_modules/@noodle-borg/connector-http/dist/mcp/egress.js +125 -0
  106. package/node_modules/@noodle-borg/connector-http/dist/mcp/failure.js +48 -0
  107. package/node_modules/@noodle-borg/connector-http/dist/mcp/index.d.ts +3 -0
  108. package/node_modules/@noodle-borg/connector-http/dist/mcp/index.js +2 -0
  109. package/node_modules/@noodle-borg/connector-http/dist/mcp/mcp-connector.d.ts +12 -0
  110. package/node_modules/@noodle-borg/connector-http/dist/mcp/mcp-connector.js +125 -0
  111. package/node_modules/@noodle-borg/connector-http/dist/mcp/result.js +55 -0
  112. package/node_modules/@noodle-borg/connector-http/dist/mcp/types.d.ts +52 -0
  113. package/node_modules/@noodle-borg/connector-http/dist/mcp/types.js +10 -0
  114. package/node_modules/@noodle-borg/connector-http/package.json +4 -1
  115. package/node_modules/@noodle-borg/control-plane/dist/portable.d.ts +2 -0
  116. package/node_modules/@noodle-borg/control-plane/dist/portable.js +1 -0
  117. package/node_modules/@noodle-borg/control-plane/dist/rollback-deployment.d.ts +61 -0
  118. package/node_modules/@noodle-borg/{service/dist/operations → control-plane/dist}/rollback-deployment.js +3 -2
  119. package/node_modules/@noodle-borg/control-plane/dist/rollback-result.d.ts +19 -0
  120. package/node_modules/@noodle-borg/control-plane/package.json +3 -1
  121. package/node_modules/@noodle-borg/developer-mcp/dist/contracts.js +4 -0
  122. package/node_modules/@noodle-borg/developer-mcp/dist/widgets/app-overview.js +1 -1
  123. package/node_modules/@noodle-borg/developer-mcp/dist/widgets/deployment-detail.js +1 -1
  124. package/node_modules/@noodle-borg/module/dist/contract.d.ts +1 -0
  125. package/node_modules/@noodle-borg/module/dist/deployment-automation.d.ts +1 -1
  126. package/node_modules/@noodle-borg/module/dist/endpoint-url.d.ts +11 -0
  127. package/node_modules/@noodle-borg/module/dist/endpoint-url.js +20 -0
  128. package/node_modules/@noodle-borg/module/dist/index.d.ts +1 -0
  129. package/node_modules/@noodle-borg/module/dist/index.js +1 -0
  130. package/node_modules/@noodle-borg/observability/dist/assistant-usage.js +217 -0
  131. package/node_modules/@noodle-borg/observability/dist/index.js +2 -0
  132. package/node_modules/@noodle-borg/{service → observability}/dist/request-event-metrics.js +5 -2
  133. package/node_modules/@noodle-borg/observability/dist/request-events-postgres.js +6 -0
  134. package/node_modules/@noodle-borg/observability/dist/request-events.js +2 -0
  135. package/node_modules/@noodle-borg/openapi-import/dist/index.js +1 -0
  136. package/node_modules/@noodle-borg/openapi-import/dist/mcp/index.js +4 -0
  137. package/node_modules/@noodle-borg/openapi-import/dist/mcp/probe.js +165 -0
  138. package/node_modules/@noodle-borg/openapi-import/dist/mcp/render.js +99 -0
  139. package/node_modules/@noodle-borg/openapi-import/dist/mcp/snapshot.js +290 -0
  140. package/node_modules/@noodle-borg/openapi-import/package.json +6 -2
  141. package/node_modules/@noodle-borg/runtime/dist/connector/types.d.ts +2 -0
  142. package/node_modules/@noodle-borg/runtime/dist/operation-execution.js +1 -0
  143. package/node_modules/@noodle-borg/service/dist/assistant-bindings.js +3 -1
  144. package/node_modules/@noodle-borg/service/dist/developer-mcp/control-plane-adapter.js +3 -3
  145. package/node_modules/@noodle-borg/service/dist/developer-mcp/inspection.js +2 -1
  146. package/node_modules/@noodle-borg/service/dist/registry-access.js +73 -24
  147. package/node_modules/@noodle-borg/service/dist/registry-deploy-transaction.js +5 -2
  148. package/node_modules/@noodle-borg/service/dist/registry-helpers.d.ts +5 -9
  149. package/node_modules/@noodle-borg/service/dist/registry-helpers.js +4 -18
  150. package/node_modules/@noodle-borg/service/dist/registry-rollback.js +3 -1
  151. package/node_modules/@noodle-borg/service/dist/registry-status.js +4 -1
  152. package/node_modules/@noodle-borg/service/dist/registry-targets.js +4 -4
  153. package/node_modules/@noodle-borg/service/dist/registry-types.d.ts +11 -16
  154. package/node_modules/@noodle-borg/service/dist/registry.d.ts +8 -5
  155. package/node_modules/@noodle-borg/service/dist/registry.js +8 -5
  156. package/node_modules/@noodle-borg/service/dist/routes/access.js +19 -1
  157. package/node_modules/@noodle-borg/service/dist/routes/analytics-dispatch.js +17 -1
  158. package/node_modules/@noodle-borg/service/dist/routes/analytics.js +1 -1
  159. package/node_modules/@noodle-borg/service/dist/routes/assistant-agent.js +81 -64
  160. package/node_modules/@noodle-borg/service/dist/routes/assistant-doctor.js +1 -1
  161. package/node_modules/@noodle-borg/service/dist/routes/assistant-model-binding.js +28 -0
  162. package/node_modules/@noodle-borg/service/dist/routes/assistant-public-session.js +18 -0
  163. package/node_modules/@noodle-borg/service/dist/routes/assistant-public-turn.js +6 -0
  164. package/node_modules/@noodle-borg/service/dist/routes/assistant-usage.js +42 -0
  165. package/node_modules/@noodle-borg/service/dist/routes/assistant.js +20 -3
  166. package/node_modules/@noodle-borg/service/dist/routes/auth-doctor-live.js +1 -2
  167. package/node_modules/@noodle-borg/service/dist/routes/control-plane.js +49 -4
  168. package/node_modules/@noodle-borg/service/dist/routes/deploy-preflight.js +11 -1
  169. package/node_modules/@noodle-borg/service/dist/routes/endpoint-enrichment.js +2 -1
  170. package/node_modules/@noodle-borg/service/dist/routes/paths.js +4 -0
  171. package/node_modules/@noodle-borg/service/dist/routes/rollback.js +1 -1
  172. package/node_modules/@noodle-borg/service/dist/service.js +6 -0
  173. package/node_modules/@noodle-borg/service/dist/store/in-memory.d.ts +2 -5
  174. package/node_modules/@noodle-borg/service/dist/store/in-memory.js +9 -21
  175. package/node_modules/@noodle-borg/service/dist/store/json-file.d.ts +2 -5
  176. package/node_modules/@noodle-borg/service/dist/store/json-file.js +8 -20
  177. package/node_modules/@noodle-borg/service/dist/store/records.js +39 -0
  178. package/node_modules/@noodle-borg/service/dist/store.d.ts +21 -10
  179. package/node_modules/@noodle-borg/service/package.json +5 -1
  180. package/node_modules/@noodle-borg/wire-contracts/dist/control-plane.d.ts +120 -0
  181. package/node_modules/@noodle-borg/wire-contracts/dist/control-plane.js +123 -1
  182. package/node_modules/@noodle-borg/wire-contracts/dist/index.d.ts +4 -0
  183. package/node_modules/@noodle-borg/wire-contracts/dist/index.js +15 -1
  184. package/node_modules/@noodleseed/assistant/package.json +1 -1
  185. package/package.json +2 -2
@@ -1,5 +1,5 @@
1
1
  import { type CustomerEndpointRef, type JsonSchema, type OperationSignature } from '@noodle-borg/compiler';
2
- import { type ConnectorFile, type CredentialProfileDef, type HttpConnectorDef } from '@noodle-borg/connector-defs';
2
+ import { type ConnectorFile, type CredentialProfileDef, type HttpConnectorDef, type McpConnectorDef } from '@noodle-borg/connector-defs';
3
3
  import { z } from 'zod';
4
4
  import { type ConfigRef } from './config.js';
5
5
  import type { ConnectionBinding } from './connection-types.js';
@@ -86,7 +86,24 @@ export type HttpConnectorOptions = Omit<HttpConnectorDef['http'], 'baseUrl' | 'a
86
86
  readonly credentialProfiles?: HttpConnectorDef['credentialProfiles'];
87
87
  readonly operations: Readonly<Record<string, HttpOperationOptionsWithRefs>>;
88
88
  };
89
- type DeclaredCredentialProfileKeys<Options extends HttpConnectorOptions> = Options extends {
89
+ export type McpAuthOptions = Extract<HttpAuthOptions, {
90
+ readonly kind: 'bearer' | 'apiKey' | 'clientCredentials';
91
+ }>;
92
+ type McpOperationOptionsWithRefs = Omit<McpConnectorDef['operations'][string], 'auth' | 'input' | 'output'> & {
93
+ readonly auth?: McpAuthOptions;
94
+ readonly input?: OperationIoOptions;
95
+ readonly output?: OperationIoOptions;
96
+ };
97
+ export type McpConnectorOptions = Omit<McpConnectorDef['mcp'], 'endpoint' | 'allowedOrigins' | 'auth'> & {
98
+ readonly endpoint: string | ConfigRef;
99
+ readonly allowedOrigins?: readonly (string | ConfigRef)[];
100
+ readonly auth?: McpAuthOptions;
101
+ readonly credentialProfiles?: McpConnectorDef['credentialProfiles'];
102
+ readonly operations: Readonly<Record<string, McpOperationOptionsWithRefs>>;
103
+ };
104
+ type DeclaredCredentialProfileKeys<Options extends {
105
+ readonly credentialProfiles?: unknown;
106
+ }> = Options extends {
90
107
  readonly credentialProfiles: infer Profiles;
91
108
  } ? Extract<keyof Profiles, string> : never;
92
109
  export interface ConnectorOperationOptions {
@@ -142,6 +159,8 @@ export interface ConnectorRef<CredentialProfileKey extends string = string> {
142
159
  readonly definitions?: Readonly<Record<string, ConnectorOpDefinition>>;
143
160
  /** HTTP fulfilment (present for connectors declared with `.http()`), emitted to the catalog verbatim. */
144
161
  readonly httpDef?: HttpConnectorDef;
162
+ /** MCP fulfilment (present for connectors declared with `.mcp()`), emitted to the catalog verbatim. */
163
+ readonly mcpDef?: McpConnectorDef;
145
164
  }
146
165
  /**
147
166
  * The connector-catalog document the SDK emits for the compiler. It is the canonical `ConnectorFile` from
@@ -160,8 +179,9 @@ export declare class ConnectorBuilder<CredentialProfileKey extends string = neve
160
179
  readonly operations: Readonly<Record<string, OperationSignature>>;
161
180
  readonly definitions: Readonly<Record<string, ConnectorOpDefinition>>;
162
181
  readonly httpDef?: HttpConnectorDef;
182
+ readonly mcpDef?: McpConnectorDef;
163
183
  readonly credentialProfiles?: Readonly<Record<CredentialProfileKey, CredentialProfileDef>>;
164
- constructor(id: string, version: string, operations?: Readonly<Record<string, OperationSignature>>, definitions?: Readonly<Record<string, ConnectorOpDefinition>>, httpDef?: HttpConnectorDef, credentialProfiles?: Readonly<Record<CredentialProfileKey, CredentialProfileDef>>);
184
+ constructor(id: string, version: string, operations?: Readonly<Record<string, OperationSignature>>, definitions?: Readonly<Record<string, ConnectorOpDefinition>>, httpDef?: HttpConnectorDef, credentialProfiles?: Readonly<Record<CredentialProfileKey, CredentialProfileDef>>, mcpDef?: McpConnectorDef);
165
185
  /** Declare the credential profiles supported by a curated signature ref or compute connector. */
166
186
  credentials<const Profiles extends Readonly<Record<string, CredentialProfileDef>>>(profiles: Profiles): ConnectorBuilder<Extract<keyof Profiles, string>>;
167
187
  /** Declare an operation by signature only (fulfilment supplied elsewhere, e.g. a catalog by `id@version`). */
@@ -173,6 +193,8 @@ export declare class ConnectorBuilder<CredentialProfileKey extends string = neve
173
193
  * `.provides()`-d. The typed options are validated against the canonical schema at author time.
174
194
  */
175
195
  http<const Options extends HttpConnectorOptions>(options: Options): ConnectorBuilder<DeclaredCredentialProfileKeys<Options>>;
196
+ /** Declare a governed remote MCP connector from an imported, frozen upstream tool snapshot. */
197
+ mcp<const Options extends McpConnectorOptions>(options: Options): ConnectorBuilder<DeclaredCredentialProfileKeys<Options>>;
176
198
  /** Declare a sandboxed-compute operation: `run` is your function, shipped as the connector's `code`. */
177
199
  compute(name: string, options: ComputeOperationOptions): ConnectorBuilder<CredentialProfileKey>;
178
200
  }
@@ -48,8 +48,9 @@ export class ConnectorBuilder {
48
48
  operations;
49
49
  definitions;
50
50
  httpDef;
51
+ mcpDef;
51
52
  credentialProfiles;
52
- constructor(id, version, operations = {}, definitions = {}, httpDef, credentialProfiles) {
53
+ constructor(id, version, operations = {}, definitions = {}, httpDef, credentialProfiles, mcpDef) {
53
54
  this.id = id;
54
55
  this.version = version;
55
56
  this.operations = operations;
@@ -57,20 +58,22 @@ export class ConnectorBuilder {
57
58
  // Assign conditionally (not `= undefined`) to satisfy exactOptionalPropertyTypes.
58
59
  if (httpDef !== undefined)
59
60
  this.httpDef = httpDef;
60
- const declaredProfiles = credentialProfiles ?? httpDef?.credentialProfiles;
61
+ if (mcpDef !== undefined)
62
+ this.mcpDef = mcpDef;
63
+ const declaredProfiles = credentialProfiles ?? httpDef?.credentialProfiles ?? mcpDef?.credentialProfiles;
61
64
  if (declaredProfiles !== undefined) {
62
65
  this.credentialProfiles = declaredProfiles;
63
66
  }
64
67
  }
65
68
  /** Declare the credential profiles supported by a curated signature ref or compute connector. */
66
69
  credentials(profiles) {
67
- if (this.httpDef !== undefined) {
68
- throw new Error(`connector "${this.id}" is HTTP — declare credentialProfiles inside .http(...)`);
70
+ if (this.httpDef !== undefined || this.mcpDef !== undefined) {
71
+ throw new Error(`connector "${this.id}" owns its transport — declare credentialProfiles inside the transport options`);
69
72
  }
70
73
  if (this.credentialProfiles !== undefined) {
71
74
  throw new Error(`connector "${this.id}" already declares credential profiles`);
72
75
  }
73
- return new ConnectorBuilder(this.id, this.version, this.operations, this.definitions, undefined, { ...profiles });
76
+ return new ConnectorBuilder(this.id, this.version, this.operations, this.definitions, undefined, { ...profiles }, undefined);
74
77
  }
75
78
  /** Declare an operation by signature only (fulfilment supplied elsewhere, e.g. a catalog by `id@version`). */
76
79
  operation(name, options) {
@@ -81,7 +84,7 @@ export class ConnectorBuilder {
81
84
  input: toOperationIoSchema(options.input, 'input', `${this.id}.${name}`),
82
85
  output: toOperationIoSchema(options.output, 'output', `${this.id}.${name}`),
83
86
  },
84
- }, this.definitions, this.httpDef, this.credentialProfiles);
87
+ }, this.definitions, this.httpDef, this.credentialProfiles, this.mcpDef);
85
88
  }
86
89
  /**
87
90
  * Declare this as an **HTTP connector**: transport (`baseUrl`/`allowedOrigins`), `bearer`/`apiKey` auth
@@ -93,6 +96,9 @@ export class ConnectorBuilder {
93
96
  if (this.credentialProfiles !== undefined) {
94
97
  throw new Error(`connector "${this.id}" already uses .credentials(...) — HTTP connectors declare credentialProfiles inside .http(...)`);
95
98
  }
99
+ if (this.mcpDef !== undefined) {
100
+ throw new Error(`connector "${this.id}" is already an .mcp() connector — a connector has one engine`);
101
+ }
96
102
  if (Object.keys(this.definitions).length > 0) {
97
103
  throw new Error(`connector "${this.id}" already has .compute() operations — a connector is HTTP or compute, not both`);
98
104
  }
@@ -120,11 +126,80 @@ export class ConnectorBuilder {
120
126
  }
121
127
  return new ConnectorBuilder(this.id, this.version, signatures, this.definitions, def);
122
128
  }
129
+ /** Declare a governed remote MCP connector from an imported, frozen upstream tool snapshot. */
130
+ mcp(options) {
131
+ if (this.credentialProfiles !== undefined) {
132
+ throw new Error(`connector "${this.id}" already uses .credentials(...) — MCP connectors declare credentialProfiles inside .mcp(...)`);
133
+ }
134
+ if (this.httpDef !== undefined) {
135
+ throw new Error(`connector "${this.id}" is already an .http() connector — a connector has one engine`);
136
+ }
137
+ if (Object.keys(this.definitions).length > 0) {
138
+ throw new Error(`connector "${this.id}" already has .compute() operations — a connector is MCP or compute, not both`);
139
+ }
140
+ const operations = {};
141
+ for (const [name, operation] of Object.entries(options.operations)) {
142
+ const output = operation.result === 'text' && operation.output === undefined
143
+ ? {
144
+ type: 'object',
145
+ properties: { text: { type: 'string' } },
146
+ required: ['text'],
147
+ additionalProperties: false,
148
+ }
149
+ : toOperationIoSchema(operation.output, 'output', `${this.id}.${name}`);
150
+ operations[name] = {
151
+ ...operation,
152
+ result: operation.result ?? 'structured',
153
+ input: toOperationIoSchema(operation.input, 'input', `${this.id}.${name}`),
154
+ output,
155
+ ...(operation.auth === undefined
156
+ ? {}
157
+ : {
158
+ auth: normalizeAuth(operation.auth, `connectors.${this.id}.operations.${name}.auth`),
159
+ }),
160
+ };
161
+ }
162
+ const { credentialProfiles, operations: _operations, ...mcpOptions } = options;
163
+ const def = {
164
+ id: this.id,
165
+ version: this.version,
166
+ kind: 'custom',
167
+ ...(credentialProfiles === undefined ? {} : { credentialProfiles }),
168
+ mcp: {
169
+ ...mcpOptions,
170
+ endpoint: normalizeVariableOrString(options.endpoint, `connectors.${this.id}.mcp.endpoint`),
171
+ ...(options.allowedOrigins === undefined
172
+ ? {}
173
+ : {
174
+ allowedOrigins: options.allowedOrigins.map((origin, index) => normalizeVariableOrString(origin, `connectors.${this.id}.mcp.allowedOrigins.${index}`)),
175
+ }),
176
+ ...(options.auth === undefined
177
+ ? {}
178
+ : {
179
+ auth: normalizeAuth(options.auth, `connectors.${this.id}.mcp.auth`),
180
+ }),
181
+ },
182
+ operations,
183
+ };
184
+ validateCatalog({ connectors: [def] });
185
+ const signatures = {};
186
+ for (const [name, operation] of Object.entries(operations)) {
187
+ signatures[name] = {
188
+ type: operation.type,
189
+ input: normalizeOperationIoSchema(operation.input),
190
+ output: normalizeOperationIoSchema(operation.output),
191
+ };
192
+ }
193
+ return new ConnectorBuilder(this.id, this.version, signatures, this.definitions, undefined, undefined, def);
194
+ }
123
195
  /** Declare a sandboxed-compute operation: `run` is your function, shipped as the connector's `code`. */
124
196
  compute(name, options) {
125
197
  if (this.httpDef) {
126
198
  throw new Error(`connector "${this.id}" is already an .http() connector — a connector is HTTP or compute, not both`);
127
199
  }
200
+ if (this.mcpDef) {
201
+ throw new Error(`connector "${this.id}" is already an .mcp() connector — a connector is MCP or compute, not both`);
202
+ }
128
203
  const type = options.type ?? 'read';
129
204
  const input = toOperationIoSchema(options.input, 'input', `${this.id}.${name}`);
130
205
  const output = toOperationIoSchema(options.output, 'output', `${this.id}.${name}`);
@@ -139,7 +214,7 @@ export class ConnectorBuilder {
139
214
  ...(options.limits ? { limits: options.limits } : {}),
140
215
  ...(options.calls ? { calls: options.calls } : {}),
141
216
  },
142
- }, undefined, this.credentialProfiles);
217
+ }, undefined, this.credentialProfiles, undefined);
143
218
  }
144
219
  }
145
220
  function rejectUnsafeActionRetry(id, options) {
@@ -2,10 +2,10 @@ import type { ConnectorFile, HttpConnectorDef } from '@noodle-borg/connector-def
2
2
  import { z } from 'zod';
3
3
  export type { PackagedAssetReference } from '@noodle-borg/compiler';
4
4
  export type { AgentCapabilityKind, AgentCapabilityRef, AgentExampleSource, AgentGuideSource, AgentWorkflowSource, AgentWorkflowStepSource, } from './agent-guide.js';
5
- export { type AssistantAccess, type AssistantCapability, type AssistantLabels, type AssistantLayoutMode, type AssistantPosition, type AssistantPresentationOptions, type AssistantPresentationTone, type AssistantSurfaceConfig, type AssistantSurfaceMode, type AssistantThemeMode, type AssistantUiOptions, type AuthenticatedWebsiteAccess, type AuthenticatedWebsiteInput, authenticatedWebsite, type CapabilityRef, type EmbeddedAssistantConfig, type EmbeddedAssistantOptions, embeddedAssistant, type OpenAICompatibleModel, type OpenAICompatibleModelInput, openAICompatible, type PublicWebsiteAccess, type PublicWebsiteInput, publicWebsite, } from './assistant.js';
5
+ export { type AssistantAccess, type AssistantCapability, type AssistantLabels, type AssistantLayoutMode, type AssistantModel, type AssistantPosition, type AssistantPresentationOptions, type AssistantPresentationTone, type AssistantSurfaceConfig, type AssistantSurfaceMode, type AssistantThemeMode, type AssistantUiOptions, type AuthenticatedWebsiteAccess, type AuthenticatedWebsiteInput, authenticatedWebsite, type CapabilityRef, type EmbeddedAssistantConfig, type EmbeddedAssistantOptions, embeddedAssistant, type NoodleManagedModel, noodleManaged, type OpenAICompatibleModel, type OpenAICompatibleModelInput, openAICompatible, type PublicWebsiteAccess, type PublicWebsiteInput, publicWebsite, } from './assistant.js';
6
6
  export { type ConfigRef, type ConfigRefKind, secret, variable, } from './config.js';
7
7
  export { type BoundConnectorRef, bind, type ConnectionBinding, type ConnectionRef, type ConnectionSource, clientCredentials, connection, externalExchange, type GoogleWorkloadIdentityAccess, googleWorkloadIdentity, managedSecret, } from './connections.js';
8
- export { type ComputeHost, type ComputeLimits, type ComputeOperationOptions, ConnectorBuilder, type ConnectorCatalogDoc, type ConnectorOpDefinition, type ConnectorOperationOptions, type ConnectorRef, connector, type HttpConnectorOptions, } from './connectors.js';
8
+ export { type ComputeHost, type ComputeLimits, type ComputeOperationOptions, ConnectorBuilder, type ConnectorCatalogDoc, type ConnectorOpDefinition, type ConnectorOperationOptions, type ConnectorRef, connector, type HttpConnectorOptions, type McpAuthOptions, type McpConnectorOptions, } from './connectors.js';
9
9
  export type { AmbientContextOptions, AmbientProviderContext, ServerContextOptions, } from './context.js';
10
10
  export { type CustomerAuth, type CustomerAuthClaimMap, type CustomerAuthRouting, type CustomerEndpointClaimMapping, customerAuth, type FederatedOidcIssuer, } from './customer-auth.js';
11
11
  export { type CustomerEndpointPolicy, type CustomerEndpointRef, customerEndpoint, } from './customer-endpoint.js';
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- export { authenticatedWebsite, embeddedAssistant, openAICompatible, publicWebsite, } from './assistant.js';
2
+ export { authenticatedWebsite, embeddedAssistant, noodleManaged, openAICompatible, publicWebsite, } from './assistant.js';
3
3
  export { secret, variable, } from './config.js';
4
4
  export { bind, clientCredentials, connection, externalExchange, googleWorkloadIdentity, managedSecret, } from './connections.js';
5
5
  export { ConnectorBuilder, connector, } from './connectors.js';
@@ -33,7 +33,7 @@ export function prepareAuthoringRuntimeDir(dir, options) {
33
33
  './react': './react.mjs',
34
34
  },
35
35
  }));
36
- writeFileSync(join(self, 'index.mjs'), "export { annotations, asset, authenticatedWebsite, bind, clientCredentials, connector, connection, customerAuth, customerEndpoint, embeddedAssistant, externalExchange, file, gmailConnector, googleWorkloadIdentity, handoffSession, knowledge, managedSecret, openAICompatible, prompt, publicWebsite, resource, secret, server, site, tool, variable, when, z } from '@noodle-borg/authoring';\n");
36
+ writeFileSync(join(self, 'index.mjs'), "export { annotations, asset, authenticatedWebsite, bind, clientCredentials, connector, connection, customerAuth, customerEndpoint, embeddedAssistant, externalExchange, file, gmailConnector, googleWorkloadIdentity, handoffSession, knowledge, managedSecret, noodleManaged, openAICompatible, prompt, publicWebsite, resource, secret, server, site, tool, variable, when, z } from '@noodle-borg/authoring';\n");
37
37
  writeFileSync(join(self, 'platform.mjs'), "export { noodlePlatform, noodlePlatformCatalog } from '@noodle-borg/authoring';\n");
38
38
  writeFileSync(join(self, 'react.mjs'), "export { generateHelpers } from '@noodle-borg/authoring/react';\n");
39
39
  }
@@ -0,0 +1,33 @@
1
+ const ANNOTATION = 'x-noodleseed-model-latest-message-includes-any';
2
+ const MAX_PHRASES = 32;
3
+ const MAX_PHRASE_CHARS = 128;
4
+ export function manifestToolAnnotations(options) {
5
+ if (options.modelVisibility === undefined) {
6
+ return options.annotations ? { annotations: { ...options.annotations } } : {};
7
+ }
8
+ if (Object.hasOwn(options.annotations ?? {}, ANNOTATION)) {
9
+ throw new Error(`Use modelVisibility.latestMessageIncludesAny instead of the reserved ${ANNOTATION} annotation.`);
10
+ }
11
+ const phrases = options.modelVisibility.latestMessageIncludesAny;
12
+ if (phrases.length < 1 || phrases.length > MAX_PHRASES) {
13
+ throw new Error(`modelVisibility.latestMessageIncludesAny must contain 1-${MAX_PHRASES} literal phrases.`);
14
+ }
15
+ const trimmed = phrases.map((phrase) => phrase.trim());
16
+ const normalized = trimmed.map(normalize);
17
+ if (trimmed.some((phrase, index) => phrase.length > MAX_PHRASE_CHARS || normalized[index]?.length === 0)) {
18
+ throw new Error(`modelVisibility.latestMessageIncludesAny phrases must contain text and be at most ${MAX_PHRASE_CHARS} characters.`);
19
+ }
20
+ if (new Set(normalized).size !== normalized.length) {
21
+ throw new Error('modelVisibility.latestMessageIncludesAny phrases must be unique.');
22
+ }
23
+ return { annotations: { ...options.annotations, [ANNOTATION]: trimmed } };
24
+ }
25
+ function normalize(value) {
26
+ return value
27
+ .normalize('NFKC')
28
+ .toLocaleLowerCase('en-US')
29
+ .replace(/[^\p{L}\p{N}]+/gu, ' ')
30
+ .trim()
31
+ .replace(/\s+/gu, ' ');
32
+ }
33
+ //# sourceMappingURL=model-tool-visibility.js.map
@@ -132,6 +132,11 @@ export interface ToolOptions {
132
132
  readonly input: JsonSchema | z.ZodType;
133
133
  readonly output?: JsonSchema | z.ZodType;
134
134
  readonly annotations?: Readonly<Record<string, unknown>>;
135
+ /** Deterministic model-discovery constraints. These do not grant invocation authority. */
136
+ readonly modelVisibility?: {
137
+ /** Show this tool to the model only when the latest user message contains one of these literals. */
138
+ readonly latestMessageIncludesAny: readonly string[];
139
+ };
135
140
  /**
136
141
  * Tool-surface visibility (SEP-1865 `_meta.ui.visibility`). Default `['model', 'app']`. Set `['app']`
137
142
  * for a **UI-only helper** — discoverable with app-only metadata so hosts can hide it from the model
@@ -10,6 +10,7 @@ import { manifestContext } from './context.js';
10
10
  import { manifestCustomerAuth } from './customer-auth.js';
11
11
  import { toJsonSchema } from './json-schema.js';
12
12
  import { manifestKnowledge } from './knowledge.js';
13
+ import { manifestToolAnnotations } from './model-tool-visibility.js';
13
14
  import { recordFulfilment, recordTool, } from './recording.js';
14
15
  const WIDGET_RESULT_META_KEY = '__noodleResultMeta';
15
16
  export function server(name, options, definitions = []) {
@@ -142,7 +143,7 @@ class ServerBuilder {
142
143
  ...(tool.options.contextProvider ? { contextProvider: true } : {}),
143
144
  inputSchema: toJsonSchema(tool.options.input, 'input'),
144
145
  ...(tool.options.output ? { outputSchema: toJsonSchema(tool.options.output) } : {}),
145
- ...(tool.options.annotations ? { annotations: { ...tool.options.annotations } } : {}),
146
+ ...manifestToolAnnotations(tool.options),
146
147
  ...(tool.options.visibility?.length ? { visibility: [...tool.options.visibility] } : {}),
147
148
  fulfilment: {
148
149
  steps: recorded.steps,
@@ -251,7 +252,7 @@ class ServerBuilder {
251
252
  }
252
253
  toConnectorCatalog() {
253
254
  // `use ∪ provides` is the authoritative emit set: each connector carries its own fulfilment — an
254
- // HTTP def (`.http()`) or compute definitions (`.compute()`). Signature-only connectors are skipped.
255
+ // HTTP/MCP transport def or compute definitions. Signature-only connectors are skipped.
255
256
  const connectors = [];
256
257
  const seen = new Set();
257
258
  for (const c of [...Object.values(this.connectors), ...Object.values(this.provided)]) {
@@ -262,6 +263,10 @@ class ServerBuilder {
262
263
  connectors.push(c.httpDef);
263
264
  continue;
264
265
  }
266
+ if (c.mcpDef) {
267
+ connectors.push(c.mcpDef);
268
+ continue;
269
+ }
265
270
  const definitions = c.definitions;
266
271
  if (definitions && Object.keys(definitions).length > 0) {
267
272
  const credentialProfiles = c.credentialProfiles;
@@ -110,7 +110,7 @@ export const CATALOG_ACCOUNT = [
110
110
  },
111
111
  {
112
112
  name: 'init',
113
- summary: 'Write a noodle.service.yaml from a named profile.',
113
+ summary: 'Initialize a service profile or the local open-core Compose stack.',
114
114
  arguments: [],
115
115
  flags: [
116
116
  {
@@ -128,6 +128,18 @@ export const CATALOG_ACCOUNT = [
128
128
  type: 'boolean',
129
129
  summary: 'Overwrite a changed existing config.',
130
130
  },
131
+ {
132
+ ...OPTIONAL_FLAG,
133
+ name: 'compose',
134
+ type: 'boolean',
135
+ summary: 'Generate the local Docker Compose state for the open-core profile.',
136
+ },
137
+ {
138
+ ...OPTIONAL_FLAG,
139
+ name: 'replace-secrets',
140
+ type: 'boolean',
141
+ summary: 'Rotate all generated secrets; requires --compose.',
142
+ },
131
143
  ],
132
144
  },
133
145
  {
@@ -203,6 +203,23 @@ export const ASSISTANT_COMMAND = {
203
203
  CLIENTS_SUBCOMMAND,
204
204
  EMBEDS_SUBCOMMAND,
205
205
  BUDGET_SUBCOMMAND,
206
+ subcommand({
207
+ ...SUBCOMMAND_FIELDS,
208
+ name: 'usage',
209
+ summary: 'Show assistant sessions, conversation depth, engagement, latency, and model tokens.',
210
+ flags: [
211
+ flag({
212
+ ...FLAG_FIELDS,
213
+ name: 'window',
214
+ type: 'string',
215
+ value: '<window>',
216
+ summary: 'Aggregation window.',
217
+ constraints: { choices: ['24h', '7d', '30d'], default: '7d' },
218
+ }),
219
+ ...TENANT_FLAGS,
220
+ ],
221
+ jsonOutput: { mode: 'single' },
222
+ }),
206
223
  subcommand({
207
224
  ...SUBCOMMAND_FIELDS,
208
225
  name: 'embed',
@@ -129,7 +129,7 @@ export const CATALOG_BOOTSTRAP_AUTHORING = [
129
129
  name: 'import',
130
130
  section: 'build',
131
131
  helpRank: 8,
132
- summary: 'Scaffold starter code from an OpenAPI spec.',
132
+ summary: 'Scaffold starter code from OpenAPI or a frozen upstream MCP tool snapshot.',
133
133
  arguments: [],
134
134
  flags: [],
135
135
  subcommands: [
@@ -158,6 +158,35 @@ export const CATALOG_BOOTSTRAP_AUTHORING = [
158
158
  FORCE_FLAG,
159
159
  ],
160
160
  },
161
+ {
162
+ name: 'mcp',
163
+ summary: 'Import a remote MCP tool snapshot into a governed TypeScript project.',
164
+ arguments: [
165
+ {
166
+ name: 'url',
167
+ type: 'string',
168
+ summary: 'Remote Streamable HTTP MCP endpoint.',
169
+ required: true,
170
+ variadic: false,
171
+ sensitive: false,
172
+ constraints: {},
173
+ },
174
+ ],
175
+ flags: [
176
+ stringFlag('output', '<dir>', 'Generated project directory.', {
177
+ constraints: { default: 'noodle-mcp-app' },
178
+ }),
179
+ stringFlag('name', '<slug>', 'Generated server and connector name.', {
180
+ constraints: { default: 'mcp-app' },
181
+ }),
182
+ stringFlag('prefix', '<name>', 'Prefix imported operation and outward tool names.'),
183
+ stringFlag('header-env', '<header>=<ENV_NAME>', 'Read one import credential from the named environment variable; never persist its value.'),
184
+ booleanFlag('check', 'Compare the live tool surface with the saved snapshot without writing.'),
185
+ FORCE_FLAG,
186
+ JSON_FLAG,
187
+ ],
188
+ jsonOutput: { mode: 'single' },
189
+ },
161
190
  ],
162
191
  local: true,
163
192
  },
@@ -132,6 +132,13 @@ export const CATALOG_HOSTED_DEPLOYMENT = [
132
132
  summary: 'Identity access mode for the deployment.',
133
133
  constraints: { choices: ACCESS_MODES },
134
134
  }),
135
+ flag({
136
+ ...FLAG_FIELDS,
137
+ name: 'owner-subject',
138
+ type: 'string',
139
+ value: '<subject>',
140
+ summary: 'Exact OAuth subject bound when access is owner-only.',
141
+ }),
135
142
  flag({
136
143
  ...FLAG_FIELDS,
137
144
  name: 'connectors',
@@ -318,6 +325,13 @@ export const CATALOG_HOSTED_DEPLOYMENT = [
318
325
  value: '<version>',
319
326
  summary: 'Server version whose access mode is changed.',
320
327
  }),
328
+ flag({
329
+ ...FLAG_FIELDS,
330
+ name: 'owner-subject',
331
+ type: 'string',
332
+ value: '<subject>',
333
+ summary: 'Exact OAuth subject to bind or transfer for owner-only access.',
334
+ }),
321
335
  ...TENANT_TARGET_FLAGS,
322
336
  ],
323
337
  jsonOutput: { mode: 'single' },
@@ -227,13 +227,7 @@ export interface ArtifactServer {
227
227
  /** Compiled knowledge components (ADR 0202, Core v2): descriptors + generated tool metadata, never bytes. */
228
228
  readonly knowledge?: readonly CompiledKnowledgeComponent[];
229
229
  readonly assistant?: {
230
- readonly model: {
231
- readonly kind: 'openai-compatible';
232
- readonly baseUrl: string;
233
- readonly model: string;
234
- /** Managed secret name, never the secret value. */
235
- readonly apiKey: string;
236
- };
230
+ readonly model: NonNullable<Manifest['server']['assistant']>['model'];
237
231
  readonly allowedOrigins: readonly string[];
238
232
  } & Omit<NonNullable<Manifest['server']['assistant']>, 'model' | 'allowedOrigins'>;
239
233
  readonly branding?: {
@@ -231,6 +231,7 @@ export declare const manifestV1Schema: z.ZodObject<{
231
231
  copy: z.ZodOptional<z.ZodString>;
232
232
  newMessages: z.ZodOptional<z.ZodString>;
233
233
  reconnect: z.ZodOptional<z.ZodString>;
234
+ newConversation: z.ZodOptional<z.ZodString>;
234
235
  retry: z.ZodOptional<z.ZodString>;
235
236
  unavailable: z.ZodOptional<z.ZodString>;
236
237
  sessionExpired: z.ZodOptional<z.ZodString>;
@@ -325,12 +326,14 @@ export declare const manifestV1Schema: z.ZodObject<{
325
326
  ltr: "ltr";
326
327
  rtl: "rtl";
327
328
  }>>;
328
- model: z.ZodObject<{
329
+ model: z.ZodUnion<readonly [z.ZodObject<{
329
330
  kind: z.ZodLiteral<"openai-compatible">;
330
331
  baseUrl: z.ZodString;
331
332
  model: z.ZodString;
332
333
  apiKey: z.ZodString;
333
- }, z.core.$strict>;
334
+ }, z.core.$strict>, z.ZodObject<{
335
+ kind: z.ZodLiteral<"noodle-managed">;
336
+ }, z.core.$strict>]>;
334
337
  allowedOrigins: z.ZodArray<z.ZodString>;
335
338
  surfaces: z.ZodOptional<z.ZodArray<z.ZodObject<{
336
339
  mode: z.ZodEnum<{
@@ -682,6 +685,7 @@ export declare const manifestV2Schema: z.ZodObject<{
682
685
  copy: z.ZodOptional<z.ZodString>;
683
686
  newMessages: z.ZodOptional<z.ZodString>;
684
687
  reconnect: z.ZodOptional<z.ZodString>;
688
+ newConversation: z.ZodOptional<z.ZodString>;
685
689
  retry: z.ZodOptional<z.ZodString>;
686
690
  unavailable: z.ZodOptional<z.ZodString>;
687
691
  sessionExpired: z.ZodOptional<z.ZodString>;
@@ -776,12 +780,14 @@ export declare const manifestV2Schema: z.ZodObject<{
776
780
  ltr: "ltr";
777
781
  rtl: "rtl";
778
782
  }>>;
779
- model: z.ZodObject<{
783
+ model: z.ZodUnion<readonly [z.ZodObject<{
780
784
  kind: z.ZodLiteral<"openai-compatible">;
781
785
  baseUrl: z.ZodString;
782
786
  model: z.ZodString;
783
787
  apiKey: z.ZodString;
784
- }, z.core.$strict>;
788
+ }, z.core.$strict>, z.ZodObject<{
789
+ kind: z.ZodLiteral<"noodle-managed">;
790
+ }, z.core.$strict>]>;
785
791
  allowedOrigins: z.ZodArray<z.ZodString>;
786
792
  surfaces: z.ZodOptional<z.ZodArray<z.ZodObject<{
787
793
  mode: z.ZodEnum<{
@@ -1343,6 +1349,7 @@ export declare const manifestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1343
1349
  copy: z.ZodOptional<z.ZodString>;
1344
1350
  newMessages: z.ZodOptional<z.ZodString>;
1345
1351
  reconnect: z.ZodOptional<z.ZodString>;
1352
+ newConversation: z.ZodOptional<z.ZodString>;
1346
1353
  retry: z.ZodOptional<z.ZodString>;
1347
1354
  unavailable: z.ZodOptional<z.ZodString>;
1348
1355
  sessionExpired: z.ZodOptional<z.ZodString>;
@@ -1437,12 +1444,14 @@ export declare const manifestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1437
1444
  ltr: "ltr";
1438
1445
  rtl: "rtl";
1439
1446
  }>>;
1440
- model: z.ZodObject<{
1447
+ model: z.ZodUnion<readonly [z.ZodObject<{
1441
1448
  kind: z.ZodLiteral<"openai-compatible">;
1442
1449
  baseUrl: z.ZodString;
1443
1450
  model: z.ZodString;
1444
1451
  apiKey: z.ZodString;
1445
- }, z.core.$strict>;
1452
+ }, z.core.$strict>, z.ZodObject<{
1453
+ kind: z.ZodLiteral<"noodle-managed">;
1454
+ }, z.core.$strict>]>;
1446
1455
  allowedOrigins: z.ZodArray<z.ZodString>;
1447
1456
  surfaces: z.ZodOptional<z.ZodArray<z.ZodObject<{
1448
1457
  mode: z.ZodEnum<{
@@ -1793,6 +1802,7 @@ export declare const manifestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1793
1802
  copy: z.ZodOptional<z.ZodString>;
1794
1803
  newMessages: z.ZodOptional<z.ZodString>;
1795
1804
  reconnect: z.ZodOptional<z.ZodString>;
1805
+ newConversation: z.ZodOptional<z.ZodString>;
1796
1806
  retry: z.ZodOptional<z.ZodString>;
1797
1807
  unavailable: z.ZodOptional<z.ZodString>;
1798
1808
  sessionExpired: z.ZodOptional<z.ZodString>;
@@ -1887,12 +1897,14 @@ export declare const manifestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1887
1897
  ltr: "ltr";
1888
1898
  rtl: "rtl";
1889
1899
  }>>;
1890
- model: z.ZodObject<{
1900
+ model: z.ZodUnion<readonly [z.ZodObject<{
1891
1901
  kind: z.ZodLiteral<"openai-compatible">;
1892
1902
  baseUrl: z.ZodString;
1893
1903
  model: z.ZodString;
1894
1904
  apiKey: z.ZodString;
1895
- }, z.core.$strict>;
1905
+ }, z.core.$strict>, z.ZodObject<{
1906
+ kind: z.ZodLiteral<"noodle-managed">;
1907
+ }, z.core.$strict>]>;
1896
1908
  allowedOrigins: z.ZodArray<z.ZodString>;
1897
1909
  surfaces: z.ZodOptional<z.ZodArray<z.ZodObject<{
1898
1910
  mode: z.ZodEnum<{
@@ -310,6 +310,7 @@ const assistantUiSchema = z
310
310
  copy: z.string().trim().min(1).max(80).optional(),
311
311
  newMessages: z.string().trim().min(1).max(80).optional(),
312
312
  reconnect: z.string().trim().min(1).max(80).optional(),
313
+ newConversation: z.string().trim().min(1).max(80).optional(),
313
314
  retry: z.string().trim().min(1).max(80).optional(),
314
315
  unavailable: z.string().trim().min(1).max(240).optional(),
315
316
  sessionExpired: z.string().trim().min(1).max(240).optional(),
@@ -343,14 +344,17 @@ const MAX_SERVER_INSTRUCTIONS = 4000;
343
344
  const sessionClaimsSchema = z.record(z.string().regex(/^[A-Za-z][A-Za-z0-9_]{0,63}$/, 'claim keys are identifier-style'), z.object({ exposeToModel: z.boolean().optional() }).strict());
344
345
  const embeddedAssistantSchema = z
345
346
  .object({
346
- model: z
347
- .object({
348
- kind: z.literal('openai-compatible'),
349
- baseUrl: z.string().trim().min(1),
350
- model: z.string().trim().min(1),
351
- apiKey: z.string().regex(/^[A-Za-z0-9_]+$/),
352
- })
353
- .strict(),
347
+ model: z.union([
348
+ z
349
+ .object({
350
+ kind: z.literal('openai-compatible'),
351
+ baseUrl: z.string().trim().min(1),
352
+ model: z.string().trim().min(1),
353
+ apiKey: z.string().regex(/^[A-Za-z0-9_]+$/),
354
+ })
355
+ .strict(),
356
+ z.object({ kind: z.literal('noodle-managed') }).strict(),
357
+ ]),
354
358
  allowedOrigins: z.array(assistantOriginOrVariableSchema).min(1),
355
359
  // The front doors this assistant serves (ADR 0201, amended 2026-08-12). Absent means the pre-0201
356
360
  // authenticated shape, so released artifacts keep their meaning; `allowedOrigins` stays the union
@@ -8,7 +8,7 @@ export function validateComputeCallGraph(defs, targets, errors) {
8
8
  graph.set(key, graph.get(key) ?? new Set());
9
9
  paths.set(key, `connectors.${def.id}.operations.${opName}.calls`);
10
10
  }
11
- if ('http' in def)
11
+ if ('http' in def || 'mcp' in def)
12
12
  continue;
13
13
  for (const [opName, op] of Object.entries(def.operations)) {
14
14
  const from = operationIdentityKey(def.id, def.version, opName);