libmodulor 0.29.0 → 0.30.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 (137) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +2 -2
  3. package/dist/esm/apps/Helper/src/lib/layers/product.js +1 -1
  4. package/dist/esm/apps/Helper/src/lib/layers/project.js +6 -6
  5. package/dist/esm/apps/Helper/src/lib/layers/target.js +27 -11
  6. package/dist/esm/convention.d.ts +2 -0
  7. package/dist/esm/convention.js +1 -0
  8. package/dist/esm/dt/base/TObject.js +13 -5
  9. package/dist/esm/dt/index.d.ts +1 -1
  10. package/dist/esm/dt/targets/json-schema.d.ts +23 -11
  11. package/dist/esm/error/funcs.d.ts +1 -0
  12. package/dist/esm/error/funcs.js +4 -0
  13. package/dist/esm/error/index.d.ts +1 -1
  14. package/dist/esm/error/index.js +1 -1
  15. package/dist/esm/i18n/locales/de.js +2 -0
  16. package/dist/esm/i18n/locales/en.js +2 -0
  17. package/dist/esm/i18n/locales/es.js +2 -0
  18. package/dist/esm/i18n/locales/fr.js +2 -0
  19. package/dist/esm/i18n/types.d.ts +1 -1
  20. package/dist/esm/index.d.ts +3 -0
  21. package/dist/esm/index.js +3 -0
  22. package/dist/esm/index.node-express.d.ts +2 -0
  23. package/dist/esm/index.node-express.js +1 -0
  24. package/dist/esm/index.node-hono.d.ts +2 -0
  25. package/dist/esm/index.node-hono.js +1 -0
  26. package/dist/esm/index.node-mcp-express.d.ts +3 -0
  27. package/dist/esm/index.node-mcp-express.js +2 -0
  28. package/dist/esm/index.node-mcp-hono.d.ts +3 -0
  29. package/dist/esm/index.node-mcp-hono.js +2 -0
  30. package/dist/esm/index.node-mcp.d.ts +3 -1
  31. package/dist/esm/index.node-mcp.js +3 -1
  32. package/dist/esm/products/Helper/i18n.d.ts +2 -0
  33. package/dist/esm/std/lib/settings.js +4 -5
  34. package/dist/esm/target/edge-worker-hono-server/SyncEdgeWorkerHonoServerManager.d.ts +2 -0
  35. package/dist/esm/target/edge-worker-hono-server/SyncEdgeWorkerHonoServerManager.js +3 -0
  36. package/dist/esm/target/index.d.ts +1 -1
  37. package/dist/esm/target/index.js +1 -1
  38. package/dist/esm/target/lib/client/AuthDataStore.d.ts +5 -0
  39. package/dist/esm/target/lib/client/impl/InMemoryAuthDataStore.d.ts +7 -0
  40. package/dist/esm/target/lib/client/impl/InMemoryAuthDataStore.js +20 -0
  41. package/dist/esm/target/lib/client/impl/MixedServerClientManager.d.ts +15 -0
  42. package/dist/esm/target/lib/client/impl/MixedServerClientManager.js +44 -0
  43. package/dist/esm/target/lib/json-schema/error.d.ts +3 -0
  44. package/dist/esm/target/lib/json-schema/error.js +14 -0
  45. package/dist/esm/target/lib/json-schema/input.d.ts +16 -0
  46. package/dist/esm/target/lib/json-schema/input.js +67 -0
  47. package/dist/esm/target/lib/json-schema/output.d.ts +19 -0
  48. package/dist/esm/target/lib/json-schema/output.js +128 -0
  49. package/dist/esm/target/lib/manifest.d.ts +32 -1
  50. package/dist/esm/target/lib/manifest.js +22 -1
  51. package/dist/esm/target/lib/mcp-server/MCPServerRequestHandler.d.ts +16 -0
  52. package/dist/esm/target/lib/mcp-server/MCPServerRequestHandler.js +54 -0
  53. package/dist/esm/target/lib/mcp-server/consts.d.ts +1 -0
  54. package/dist/esm/target/lib/mcp-server/consts.js +1 -0
  55. package/dist/esm/target/lib/mcp-server/funcs.d.ts +13 -0
  56. package/dist/esm/target/lib/mcp-server/funcs.js +84 -0
  57. package/dist/esm/target/lib/mcp-server/http/MCPHTTPRequestHandlerBuilder.d.ts +14 -0
  58. package/dist/esm/target/lib/mcp-server/http/MCPHTTPRequestHandlerBuilder.js +1 -0
  59. package/dist/esm/target/lib/mcp-server/http/express/MCPHTTPExpressFakeRequestHandlerBuilder.d.ts +5 -0
  60. package/dist/esm/target/lib/mcp-server/http/express/MCPHTTPExpressFakeRequestHandlerBuilder.js +18 -0
  61. package/dist/esm/target/lib/mcp-server/http/express/MCPHTTPExpressProtocolRequestHandlerBuilder.d.ts +15 -0
  62. package/dist/esm/target/lib/mcp-server/http/express/MCPHTTPExpressProtocolRequestHandlerBuilder.js +88 -0
  63. package/dist/esm/target/lib/mcp-server/http/express/types.d.ts +3 -0
  64. package/dist/esm/target/lib/mcp-server/http/express/types.js +1 -0
  65. package/dist/esm/target/lib/mcp-server/http/funcs.d.ts +6 -0
  66. package/dist/esm/target/lib/mcp-server/http/funcs.js +50 -0
  67. package/dist/esm/target/lib/mcp-server/http/hono/MCPHTTPHonoFakeRequestHandlerBuilder.d.ts +5 -0
  68. package/dist/esm/target/lib/mcp-server/http/hono/MCPHTTPHonoFakeRequestHandlerBuilder.js +18 -0
  69. package/dist/esm/target/lib/mcp-server/http/hono/MCPHTTPHonoProtocolRequestHandlerBuilder.d.ts +15 -0
  70. package/dist/esm/target/lib/mcp-server/http/hono/MCPHTTPHonoProtocolRequestHandlerBuilder.js +88 -0
  71. package/dist/esm/target/lib/mcp-server/http/hono/types.d.ts +3 -0
  72. package/dist/esm/target/lib/mcp-server/http/hono/types.js +1 -0
  73. package/dist/esm/target/lib/mcp-server/stdio/MCPStdioRequestHandler.d.ts +31 -0
  74. package/dist/esm/target/lib/mcp-server/stdio/MCPStdioRequestHandler.js +108 -0
  75. package/dist/esm/target/lib/mcp-server/stdio/MCPStdioUCClientConfirmManager.d.ts +7 -0
  76. package/dist/esm/target/lib/mcp-server/stdio/MCPStdioUCClientConfirmManager.js +36 -0
  77. package/dist/esm/target/lib/mcp-server/stdio/consts.d.ts +2 -0
  78. package/dist/esm/target/lib/mcp-server/stdio/consts.js +3 -0
  79. package/dist/esm/target/lib/mcp-server/stdio/funcs.d.ts +2 -0
  80. package/dist/esm/target/lib/mcp-server/stdio/funcs.js +10 -0
  81. package/dist/esm/target/lib/mcp-server/stdio/input.d.ts +10 -0
  82. package/dist/esm/target/lib/mcp-server/stdio/input.js +15 -0
  83. package/dist/esm/target/lib/mcp-server/types.d.ts +2 -0
  84. package/dist/esm/target/lib/mcp-server/types.js +1 -0
  85. package/dist/esm/target/lib/openapi/OpenAPISpecBuilder.js +8 -4
  86. package/dist/esm/target/lib/openapi/funcs.d.ts +4 -9
  87. package/dist/esm/target/lib/openapi/funcs.js +18 -119
  88. package/dist/esm/target/lib/openapi/types.d.ts +5 -16
  89. package/dist/esm/target/lib/server/ServerBooter.d.ts +1 -1
  90. package/dist/esm/target/lib/server/ServerBooter.js +10 -0
  91. package/dist/esm/target/lib/server/ServerManager.d.ts +10 -0
  92. package/dist/esm/target/lib/server/ServerRequestHandler.d.ts +10 -5
  93. package/dist/esm/target/lib/server/ServerRequestHandler.js +35 -25
  94. package/dist/esm/target/lib/server/consts.js +4 -0
  95. package/dist/esm/target/lib/server-express/funcs.js +2 -6
  96. package/dist/esm/target/lib/server-hono/funcs.js +4 -2
  97. package/dist/esm/target/lib/shared.d.ts +1 -0
  98. package/dist/esm/target/lib/shared.js +1 -0
  99. package/dist/esm/target/nextjs-server/NextJSServerManager.d.ts +2 -0
  100. package/dist/esm/target/nextjs-server/NextJSServerManager.js +3 -0
  101. package/dist/esm/target/node-express-server/NodeExpressServerManager.d.ts +6 -2
  102. package/dist/esm/target/node-express-server/NodeExpressServerManager.js +15 -6
  103. package/dist/esm/target/node-hono-server/NodeHonoServerManager.d.ts +6 -2
  104. package/dist/esm/target/node-hono-server/NodeHonoServerManager.js +15 -6
  105. package/dist/esm/target/{node-mcp-server/NodeLocalStdioMCPServerManager.d.ts → node-mcp-server-stdio/NodeMCPStdioServerManager.d.ts} +9 -20
  106. package/dist/esm/target/node-mcp-server-stdio/NodeMCPStdioServerManager.js +108 -0
  107. package/dist/esm/testing/impl/newNodeAppTester.js +5 -0
  108. package/dist/esm/uc/cardinality.d.ts +7 -0
  109. package/dist/esm/uc/cardinality.js +14 -0
  110. package/dist/esm/uc/examples.d.ts +2 -0
  111. package/dist/esm/uc/examples.js +12 -0
  112. package/dist/esm/uc/helpers/UCOutputReader.d.ts +2 -2
  113. package/dist/esm/uc/helpers/UCOutputReader.js +2 -2
  114. package/dist/esm/uc/index.d.ts +2 -0
  115. package/dist/esm/uc/index.js +2 -0
  116. package/dist/esm/uc/input-field.d.ts +3 -6
  117. package/dist/esm/uc/input-field.js +5 -21
  118. package/dist/esm/uc/opi.d.ts +3 -1
  119. package/dist/esm/uc/opi.js +4 -1
  120. package/dist/esm/uc/output-field.d.ts +13 -1
  121. package/dist/esm/uc/output-field.js +9 -11
  122. package/dist/esm/utils/bundling/funcs.js +1 -1
  123. package/dist/esm/utils/bundling/vite/plugin.d.ts +1 -1
  124. package/dist/esm/utils/index.d.ts +1 -0
  125. package/dist/esm/utils/index.js +1 -0
  126. package/dist/esm/utils/streams/funcs.d.ts +2 -0
  127. package/dist/esm/utils/streams/funcs.js +10 -0
  128. package/package.json +20 -9
  129. package/dist/esm/target/lib/openapi/consts.d.ts +0 -2
  130. package/dist/esm/target/lib/openapi/consts.js +0 -1
  131. package/dist/esm/target/lib/openapi/input.d.ts +0 -16
  132. package/dist/esm/target/lib/openapi/input.js +0 -33
  133. package/dist/esm/target/node-mcp-server/NodeLocalStdioMCPServerManager.js +0 -188
  134. package/dist/esm/target/node-mcp-server/funcs.d.ts +0 -7
  135. package/dist/esm/target/node-mcp-server/funcs.js +0 -45
  136. package/dist/esm/target/node-mcp-server/types.d.ts +0 -15
  137. /package/dist/esm/target/{node-mcp-server/types.js → lib/client/AuthDataStore.js} +0 -0
@@ -1,21 +1,10 @@
1
- import { ERROR_HTTP_STATUS_MAP, IllegalArgumentError, } from '../../../error/index.js';
2
- import { DEFAULT_UC_SEC_AT, DEFAULT_UC_SEC_PAKCT, UCOutputReader, ucofExamples, } from '../../../uc/index.js';
1
+ import { ERROR_HTTP_STATUS_MAP } from '../../../error/index.js';
2
+ import { DEFAULT_UC_SEC_AT, DEFAULT_UC_SEC_PAKCT, } from '../../../uc/index.js';
3
3
  import { isBlank } from '../../../utils/index.js';
4
+ import { serverErrorJsonSchema } from '../json-schema/error.js';
5
+ import { ucifJsonSchemaDef } from '../json-schema/input.js';
6
+ import { ucOutputJsonSchema } from '../json-schema/output.js';
4
7
  import { AUTHORIZATION_HEADER_NAME, } from '../shared.js';
5
- import { SUCCESS_DESCRIPTION } from './consts.js';
6
- import { openAPIInputDef } from './input.js';
7
- export function openAPIErrorSchema() {
8
- return {
9
- additionalProperties: false,
10
- properties: {
11
- message: {
12
- examples: [new IllegalArgumentError().message],
13
- type: 'string',
14
- },
15
- },
16
- type: 'object',
17
- };
18
- }
19
8
  export function openAPIErrors() {
20
9
  return ERROR_HTTP_STATUS_MAP.entries().reduce((acc, cur) => {
21
10
  const [status, clazz] = cur;
@@ -23,16 +12,7 @@ export function openAPIErrors() {
23
12
  acc[status] = {
24
13
  content: {
25
14
  'application/json': {
26
- schema: {
27
- additionalProperties: false,
28
- properties: {
29
- message: {
30
- examples: [message],
31
- type: 'string',
32
- },
33
- },
34
- type: 'object',
35
- },
15
+ schema: serverErrorJsonSchema(message),
36
16
  },
37
17
  },
38
18
  description: message,
@@ -40,95 +20,6 @@ export function openAPIErrors() {
40
20
  return acc;
41
21
  }, {});
42
22
  }
43
- export function openAPIInputSchema(uc) {
44
- const res = {
45
- additionalProperties: false,
46
- properties: {},
47
- type: 'object',
48
- };
49
- for (const f of uc.inputFields) {
50
- const { key } = f;
51
- const { internal, spec } = openAPIInputDef(f);
52
- if (!spec) {
53
- continue;
54
- }
55
- const k = key;
56
- res.properties[k] = spec;
57
- if (!internal?.required) {
58
- continue;
59
- }
60
- if (!res.required) {
61
- res.required = [];
62
- }
63
- res.required.push(k);
64
- }
65
- return res;
66
- }
67
- export function openAPIOPISchema(part) {
68
- const res = {
69
- additionalProperties: false,
70
- properties: {},
71
- type: 'object',
72
- };
73
- for (const f of part.fields) {
74
- const { def, key } = f;
75
- const { type } = def;
76
- const k = key;
77
- res.properties[k] = type.jsonSchemaType();
78
- const examples = ucofExamples(def);
79
- if (examples) {
80
- res.properties[k].examples = examples;
81
- }
82
- }
83
- return res;
84
- }
85
- export function openAPIOutputPartSchema(part) {
86
- return {
87
- additionalProperties: false,
88
- properties: {
89
- items: {
90
- items: openAPIOPISchema(part),
91
- type: 'array',
92
- },
93
- pagination: {
94
- properties: {
95
- id: { format: 'uuid', type: 'string' },
96
- limit: { type: 'integer' },
97
- offset: { type: 'integer' },
98
- q: { type: 'string' },
99
- },
100
- type: 'object',
101
- },
102
- total: { examples: [1], type: 'integer' },
103
- },
104
- required: ['items', 'total'],
105
- type: 'object',
106
- };
107
- }
108
- export function openAPIOutputSchema(uc) {
109
- const res = {
110
- additionalProperties: false,
111
- properties: {},
112
- type: 'object',
113
- };
114
- if (!uc.hasOutputParts()) {
115
- return res;
116
- }
117
- const ucor = new UCOutputReader(uc.def, undefined);
118
- const [part0, part1] = ucor.parts();
119
- res.properties.parts = {
120
- properties: {
121
- _0: openAPIOutputPartSchema(part0),
122
- },
123
- type: 'object',
124
- };
125
- if (part1) {
126
- res.properties.parts.properties = {
127
- _1: openAPIOutputPartSchema(part1),
128
- };
129
- }
130
- return res;
131
- }
132
23
  export function openAPIParameters(uc, envelope) {
133
24
  const res = [];
134
25
  switch (envelope) {
@@ -136,7 +27,7 @@ export function openAPIParameters(uc, envelope) {
136
27
  {
137
28
  for (const f of uc.inputFields) {
138
29
  const { key } = f;
139
- const { internal, spec } = openAPIInputDef(f);
30
+ const { internal, spec } = ucifJsonSchemaDef(f);
140
31
  if (!spec) {
141
32
  continue;
142
33
  }
@@ -235,15 +126,23 @@ export function openAPISecurity(sec) {
235
126
  item[authType] = [];
236
127
  return res;
237
128
  }
238
- export function openAPISuccess(uc) {
129
+ export function openAPISuccess(uc, descriptions) {
130
+ const schema = ucOutputJsonSchema(uc);
131
+ if (!schema) {
132
+ return {
133
+ '204': {
134
+ description: descriptions[204],
135
+ },
136
+ };
137
+ }
239
138
  return {
240
139
  '200': {
241
140
  content: {
242
141
  'application/json': {
243
- schema: openAPIOutputSchema(uc),
142
+ schema,
244
143
  },
245
144
  },
246
- description: SUCCESS_DESCRIPTION,
145
+ description: descriptions[200],
247
146
  },
248
147
  };
249
148
  }
@@ -1,23 +1,12 @@
1
- import type { DataType, FreeTextLong, FreeTextShort, HTTPMethod, HTTPStatusNumber, JSONSchemaType, SemVerVersion, URL } from '../../../dt/index.js';
1
+ import type { FreeTextLong, FreeTextShort, HTTPMethod, HTTPStatusNumber, JSONSchemaObject, JSONSchemaProperty, SemVerVersion, URL } from '../../../dt/index.js';
2
2
  import type { ProductName } from '../../../product/index.js';
3
3
  import type { FQUCInputName, FQUCOPI0Name, FQUCOPI1Name, UCFieldKey } from '../../../uc/index.js';
4
- import type { StringKeys } from '../../../utils/index.js';
5
4
  import type { AUTHORIZATION_HEADER_NAME, AuthCookieName, PublicApiKeyHeaderName } from '../shared.js';
6
5
  export type OpenAPIPathName = string;
7
6
  export type OpenAPIDescription = FreeTextLong;
8
7
  export type OpenAPISchemaName = FQUCInputName | FQUCOPI0Name | FQUCOPI1Name | `Error`;
9
8
  export type OpenAPISchemaRef = `#/components/schemas/${OpenAPISchemaName}`;
10
9
  export type OpenAPISummary = FreeTextShort;
11
- export type OpenAPIProperty<T extends DataType> = JSONSchemaType & {
12
- enum?: T[];
13
- examples?: T[];
14
- };
15
- export interface OpenAPISchema<T extends object> {
16
- additionalProperties: false;
17
- properties: Record<StringKeys<T>, OpenAPIProperty<any>>;
18
- required?: StringKeys<T>[];
19
- type: 'object';
20
- }
21
10
  export type OpenAPISecurityItem = Partial<Record<keyof OpenAPISecuritySchemes, []>>;
22
11
  export type OpenAPISecurity = OpenAPISecurityItem[];
23
12
  export interface OpenAPISecurityScheme {
@@ -47,14 +36,14 @@ export interface OpenAPISecuritySchemes {
47
36
  }
48
37
  export interface OpenAPIComponents {
49
38
  securitySchemes: OpenAPISecuritySchemes;
50
- schemas: Record<OpenAPISchemaName, OpenAPISchema<any>>;
39
+ schemas: Record<OpenAPISchemaName, JSONSchemaObject<any>>;
51
40
  }
52
41
  export interface OpenAPIParameter {
53
42
  description?: OpenAPIDescription;
54
43
  in: 'path' | 'query';
55
44
  name: UCFieldKey;
56
45
  required: boolean;
57
- schema: OpenAPIProperty<any>;
46
+ schema: JSONSchemaProperty<any>;
58
47
  }
59
48
  export interface OpenAPIPath {
60
49
  description?: OpenAPIDescription;
@@ -68,7 +57,7 @@ export interface OpenAPIPath {
68
57
  export interface OpenAPIInnerContent {
69
58
  schema: {
70
59
  $ref: OpenAPISchemaRef;
71
- } | OpenAPISchema<any>;
60
+ } | JSONSchemaObject<any>;
72
61
  }
73
62
  export type OpenAPIContent = {
74
63
  'application/json': OpenAPIInnerContent;
@@ -87,7 +76,7 @@ export interface OpenAPIRequestBody {
87
76
  }
88
77
  export type OpenAPIPaths = Record<OpenAPIPathName, Partial<Record<Lowercase<HTTPMethod>, OpenAPIPath>>>;
89
78
  export interface OpenAPIResponse {
90
- content: OpenAPIContent;
79
+ content?: OpenAPIContent;
91
80
  description: OpenAPIDescription;
92
81
  }
93
82
  export type OpenAPIResponses = Partial<Record<HTTPStatusNumber, OpenAPIResponse>>;
@@ -5,7 +5,7 @@ import type { TargetEntrypointInput } from '../entrypoint.js';
5
5
  import { OpenAPISpecBuilder } from '../openapi/OpenAPISpecBuilder.js';
6
6
  import { ServerInstaller } from './ServerInstaller.js';
7
7
  import type { ServerManager, ServerManagerSettings } from './ServerManager.js';
8
- type S = Pick<ServerManagerSettings, 'server_expose_openapi_spec' | 'server_expose_openapi_spec_at' | 'server_static_dir_path' | 'server_tmp_path'>;
8
+ type S = Pick<ServerManagerSettings, 'server_expose_mcp' | 'server_expose_mcp_at' | 'server_expose_openapi_spec' | 'server_expose_openapi_spec_at' | 'server_static_dir_path' | 'server_tmp_path'>;
9
9
  type Input = TargetEntrypointInput & {
10
10
  autoMountUCs?: boolean;
11
11
  };
@@ -43,6 +43,8 @@ let ServerBooter = class ServerBooter {
43
43
  }
44
44
  s() {
45
45
  return {
46
+ server_expose_mcp: this.settingsManager.get()('server_expose_mcp'),
47
+ server_expose_mcp_at: this.settingsManager.get()('server_expose_mcp_at'),
46
48
  server_expose_openapi_spec: this.settingsManager.get()('server_expose_openapi_spec'),
47
49
  server_expose_openapi_spec_at: this.settingsManager.get()('server_expose_openapi_spec_at'),
48
50
  server_static_dir_path: this.settingsManager.get()('server_static_dir_path'),
@@ -97,6 +99,14 @@ let ServerBooter = class ServerBooter {
97
99
  });
98
100
  await this.serverManager.mountOpenAPISpec(spec, at);
99
101
  }
102
+ if (this.s().server_expose_mcp) {
103
+ const at = this.s().server_expose_mcp_at;
104
+ this.logger.info('Mounting MCP', {
105
+ at,
106
+ mountedUCs: mountedUCs.length,
107
+ });
108
+ await this.serverManager.mountMCP(mountedUCs, at);
109
+ }
100
110
  await this.serverManager.warmUp();
101
111
  await this.serverManager.start();
102
112
  }
@@ -1,5 +1,6 @@
1
1
  import type { AppManifest } from '../../../app/index.js';
2
2
  import type { ApiKey, DirPath, FilePath, HostPort, HTTPMethod, Password, URL, URLPath, Username } from '../../../dt/index.js';
3
+ import type { ProductUCsLoaderOutput } from '../../../product/index.js';
3
4
  import type { Settings } from '../../../std/index.js';
4
5
  import type { UCDef, UCHTTPContract, UCInput, UCManager, UCOPIBase } from '../../../uc/index.js';
5
6
  import type { HTTPCSPValue } from '../../../utils/http/types.js';
@@ -25,8 +26,12 @@ export interface ServerManagerSettings extends ServerManagerAuthSettings, Settin
25
26
  server_cors_headers: HTTPHeaderName[];
26
27
  server_cors_methods: HTTPMethod[];
27
28
  server_cors_origins: URL[];
29
+ server_expose_mcp: boolean;
30
+ server_expose_mcp_at: URLPath;
28
31
  server_expose_openapi_spec: boolean;
29
32
  server_expose_openapi_spec_at: URLPath;
33
+ server_mcp_dangerously_skip_pub_api_key_check: boolean;
34
+ server_mcp_dangerously_skip_auth_check: boolean;
30
35
  server_public_api_key_header_name: PublicApiKeyHeaderName;
31
36
  server_public_url: URL;
32
37
  server_ssl_fullchain_path: FilePath | null;
@@ -51,6 +56,11 @@ export interface ServerManager extends Initializable {
51
56
  * @param contract
52
57
  */
53
58
  mountSync<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(appManifest: AppManifest, ucd: UCDef<I, OPI0, OPI1>, contract: UCHTTPContract): void;
59
+ /**
60
+ * Mount the MCP endpoint
61
+ * @param spec
62
+ */
63
+ mountMCP(ucs: ProductUCsLoaderOutput, at: URLPath): Promise<void>;
54
64
  /**
55
65
  * Mount the OpenAPI spec
56
66
  * @param spec
@@ -26,12 +26,15 @@ export interface ServerRequestHandlerRes {
26
26
  redirect: (location: URL | URLPath) => Promise<void>;
27
27
  setCookie: (info: AuthCookieCreatorOutput) => Promise<void>;
28
28
  }
29
- interface Input<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined> {
29
+ export interface ServerRequestHandlerInput<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined> {
30
30
  appManifest: AppManifest;
31
+ dangerouslySkipAuthCheck?: boolean | undefined;
32
+ dangerouslySkipPubApiKeyCheck?: boolean | undefined;
31
33
  envelope: HTTPDataEnvelope;
32
34
  execOpts?: UCManagerExecServerOpts<OPI0, OPI1> | undefined;
33
35
  req: ServerRequestHandlerReq;
34
36
  res: ServerRequestHandlerRes;
37
+ skipSideEffects?: boolean | undefined;
35
38
  ucd: UCDef<I, OPI0, OPI1>;
36
39
  /**
37
40
  * It is not injected in the handler constructor because it must be the same as the one used in ServerManager.
@@ -41,15 +44,18 @@ interface Input<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBas
41
44
  ucManager: UCManager;
42
45
  }
43
46
  type BodylessStatus = 204 | 302;
44
- type Output<OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined> = {
47
+ type Output<OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined> = ({
45
48
  body: undefined;
46
49
  status: BodylessStatus;
47
50
  } | {
48
51
  body: UCOutput<OPI0, OPI1> | object;
52
+ rawErr?: Error;
49
53
  status: Exclude<HTTPStatusNumber, BodylessStatus>;
54
+ }) & {
55
+ rawErr?: Error;
50
56
  };
51
57
  type S = Pick<ServerManagerSettings, 'server_cookies_name_auth' | 'server_public_api_key_header_name'>;
52
- export declare class ServerRequestHandler implements Worker<Input, Promise<Output>> {
58
+ export declare class ServerRequestHandler implements Worker<ServerRequestHandlerInput, Promise<Output>> {
53
59
  private authCookieCreator;
54
60
  private authenticationChecker;
55
61
  private customerFacingErrorBuilder;
@@ -58,10 +64,9 @@ export declare class ServerRequestHandler implements Worker<Input, Promise<Outpu
58
64
  private requestLogger;
59
65
  private settingsManager;
60
66
  private ucBuilder;
61
- private static X_FORWARDED_PROTO_HEADER_NAME;
62
67
  constructor(authCookieCreator: AuthCookieCreator, authenticationChecker: AuthenticationChecker, customerFacingErrorBuilder: CustomerFacingErrorBuilder, publicApiKeyChecker: PublicApiKeyChecker, requestChecker: RequestChecker, requestLogger: RequestLogger, settingsManager: SettingsManager<S>, ucBuilder: UCBuilder);
63
68
  s(): S;
64
- exec<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>({ appManifest, envelope, execOpts, req, res, ucd, ucManager, }: Input<I, OPI0, OPI1>): Promise<Output<OPI0, OPI1>>;
69
+ exec<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>({ appManifest, dangerouslySkipAuthCheck, dangerouslySkipPubApiKeyCheck, envelope, execOpts, req, res, skipSideEffects, ucd, ucManager, }: ServerRequestHandlerInput<I, OPI0, OPI1>): Promise<Output<OPI0, OPI1>>;
65
70
  private fill;
66
71
  private applySideEffects;
67
72
  private applyClearAuthSideEffect;
@@ -10,11 +10,10 @@ var __metadata = (this && this.__metadata) || function (k, v) {
10
10
  var __param = (this && this.__param) || function (paramIndex, decorator) {
11
11
  return function (target, key) { decorator(target, key, paramIndex); }
12
12
  };
13
- var ServerRequestHandler_1;
14
13
  import { inject, injectable } from 'inversify';
15
- import { IllegalArgumentError, isEmptyJSON } from '../../../error/index.js';
14
+ import { IllegalArgumentError, isEmptyJSON, logDevWarning, } from '../../../error/index.js';
16
15
  import { UCBuilder, UCOutputReader, UCOutputSideEffectType, } from '../../../uc/index.js';
17
- import { AUTHORIZATION_HEADER_NAME } from '../shared.js';
16
+ import { AUTHORIZATION_HEADER_NAME, X_FORWARDED_PROTO_HEADER_NAME, } from '../shared.js';
18
17
  import { AuthCookieCreator, } from './AuthCookieCreator.js';
19
18
  import { AuthenticationChecker } from './AuthenticationChecker.js';
20
19
  import { CustomerFacingErrorBuilder } from './CustomerFacingErrorBuilder.js';
@@ -22,7 +21,6 @@ import { PublicApiKeyChecker } from './PublicApiKeyChecker.js';
22
21
  import { RequestChecker } from './RequestChecker.js';
23
22
  import { RequestLogger } from './RequestLogger.js';
24
23
  let ServerRequestHandler = class ServerRequestHandler {
25
- static { ServerRequestHandler_1 = this; }
26
24
  authCookieCreator;
27
25
  authenticationChecker;
28
26
  customerFacingErrorBuilder;
@@ -31,7 +29,6 @@ let ServerRequestHandler = class ServerRequestHandler {
31
29
  requestLogger;
32
30
  settingsManager;
33
31
  ucBuilder;
34
- static X_FORWARDED_PROTO_HEADER_NAME = 'X-Forwarded-Proto';
35
32
  constructor(authCookieCreator, authenticationChecker, customerFacingErrorBuilder, publicApiKeyChecker, requestChecker, requestLogger, settingsManager, ucBuilder) {
36
33
  this.authCookieCreator = authCookieCreator;
37
34
  this.authenticationChecker = authenticationChecker;
@@ -48,7 +45,7 @@ let ServerRequestHandler = class ServerRequestHandler {
48
45
  server_public_api_key_header_name: this.settingsManager.get()('server_public_api_key_header_name'),
49
46
  };
50
47
  }
51
- async exec({ appManifest, envelope, execOpts, req, res, ucd, ucManager, }) {
48
+ async exec({ appManifest, dangerouslySkipAuthCheck = false, dangerouslySkipPubApiKeyCheck = false, envelope, execOpts, req, res, skipSideEffects = false, ucd, ucManager, }) {
52
49
  try {
53
50
  const { bodyRaw, cookie, header, method, secure, url } = req;
54
51
  this.requestLogger.exec({
@@ -59,34 +56,46 @@ let ServerRequestHandler = class ServerRequestHandler {
59
56
  this.requestChecker.exec({
60
57
  secure,
61
58
  url,
62
- xForwardedProtoHeader: await header(ServerRequestHandler_1.X_FORWARDED_PROTO_HEADER_NAME),
59
+ xForwardedProtoHeader: await header(X_FORWARDED_PROTO_HEADER_NAME),
63
60
  });
64
61
  const { ext, sec } = ucd;
65
- await this.publicApiKeyChecker.exec({
66
- checkType: sec?.publicApiKeyCheckType,
67
- value: await header(this.s().server_public_api_key_header_name),
68
- });
62
+ if (dangerouslySkipPubApiKeyCheck) {
63
+ logDevWarning('Skipping pub api key check');
64
+ }
65
+ else {
66
+ await this.publicApiKeyChecker.exec({
67
+ checkType: sec?.publicApiKeyCheckType,
68
+ value: await header(this.s().server_public_api_key_header_name),
69
+ });
70
+ }
69
71
  const uc = this.ucBuilder.exec({
70
72
  appManifest,
71
73
  auth: null,
72
74
  def: ucd,
73
75
  });
74
- const { auth } = await this.authenticationChecker.exec({
75
- authCookie: await cookie(this.s().server_cookies_name_auth),
76
- authorizationHeader: await header(AUTHORIZATION_HEADER_NAME),
77
- uc,
78
- });
79
- if (auth) {
80
- uc.auth = auth;
76
+ if (dangerouslySkipAuthCheck) {
77
+ logDevWarning('Skipping auth check');
78
+ }
79
+ else {
80
+ const { auth } = await this.authenticationChecker.exec({
81
+ authCookie: await cookie(this.s().server_cookies_name_auth),
82
+ authorizationHeader: await header(AUTHORIZATION_HEADER_NAME),
83
+ uc,
84
+ });
85
+ if (auth) {
86
+ uc.auth = auth;
87
+ }
81
88
  }
82
89
  await this.fill(req, envelope, uc);
83
90
  const output = await ucManager.execServer(uc, execOpts);
84
- const { status } = await this.applySideEffects(res, ucd, output);
85
- if (status !== undefined) {
86
- return {
87
- body: undefined,
88
- status,
89
- };
91
+ if (!skipSideEffects) {
92
+ const { status } = await this.applySideEffects(res, ucd, output);
93
+ if (status !== undefined) {
94
+ return {
95
+ body: undefined,
96
+ status,
97
+ };
98
+ }
90
99
  }
91
100
  if (!output) {
92
101
  return {
@@ -106,6 +115,7 @@ let ServerRequestHandler = class ServerRequestHandler {
106
115
  });
107
116
  return {
108
117
  body: error.toObj(),
118
+ rawErr: err,
109
119
  status: error.httpStatus,
110
120
  };
111
121
  }
@@ -186,7 +196,7 @@ let ServerRequestHandler = class ServerRequestHandler {
186
196
  res.setCookie(output);
187
197
  }
188
198
  };
189
- ServerRequestHandler = ServerRequestHandler_1 = __decorate([
199
+ ServerRequestHandler = __decorate([
190
200
  injectable(),
191
201
  __param(0, inject(AuthCookieCreator)),
192
202
  __param(1, inject(AuthenticationChecker)),
@@ -17,8 +17,12 @@ export const TARGET_DEFAULT_SERVER_MANAGER_SETTINGS = {
17
17
  server_csp_default_src: [],
18
18
  server_csp_img_src: [],
19
19
  server_csp_script_src: [],
20
+ server_expose_mcp: false,
21
+ server_expose_mcp_at: '/mcp',
20
22
  server_expose_openapi_spec: false,
21
23
  server_expose_openapi_spec_at: '/api/openapi.json',
24
+ server_mcp_dangerously_skip_auth_check: false,
25
+ server_mcp_dangerously_skip_pub_api_key_check: false,
22
26
  server_private_api_key_entries: [],
23
27
  server_public_api_key_entries: [unsafeDefaultSetting()],
24
28
  server_public_api_key_header_name: 'X-API-Key',
@@ -1,7 +1,7 @@
1
1
  import cookieParser from 'cookie-parser';
2
2
  import express, {} from 'express';
3
3
  import fileUpload from 'express-fileupload';
4
- import { fmtSingleDataMsg, fmtSSEError, isError, SSE_HEADERS, } from '../../../utils/index.js';
4
+ import { defaultStreamOnClose, fmtSingleDataMsg, fmtSSEError, isError, SSE_HEADERS, } from '../../../utils/index.js';
5
5
  export function buildHandler(appManifest, ucd, contract, serverRequestHandler, ucManager) {
6
6
  const { envelope } = contract;
7
7
  const handler = async (req, res) => {
@@ -15,11 +15,7 @@ export function buildHandler(appManifest, ucd, contract, serverRequestHandler, u
15
15
  let streamedOnce = false;
16
16
  execOpts = {
17
17
  stream: {
18
- onClose: async () => {
19
- if (streamedOnce) {
20
- throw new Error('execOpts.stream.onClose needs to be set in the UC ServerMain');
21
- }
22
- },
18
+ onClose: defaultStreamOnClose(streamedOnce),
23
19
  onData: async (output) => {
24
20
  streamedOnce = true;
25
21
  if (!output) {
@@ -3,7 +3,7 @@ import { deleteCookie, getCookie, setCookie } from 'hono/cookie';
3
3
  import { logger } from 'hono/logger';
4
4
  import { secureHeaders } from 'hono/secure-headers';
5
5
  import { NotFoundError } from '../../../error/index.js';
6
- import { fmtSingleDataMsg, fmtSSEError, fromFormData, isError, SSE_HEADERS, } from '../../../utils/index.js';
6
+ import { defaultStreamOnClose, fmtSingleDataMsg, fmtSSEError, fromFormData, isError, SSE_HEADERS, } from '../../../utils/index.js';
7
7
  export function buildHandler(appManifest, ucd, contract, serverRequestHandler, ucManager, beforeExec) {
8
8
  const { envelope } = contract;
9
9
  const handler = async (c) => {
@@ -28,10 +28,12 @@ export function buildHandler(appManifest, ucd, contract, serverRequestHandler, u
28
28
  ctrl.close();
29
29
  closed = true;
30
30
  };
31
+ let streamedOnce = false;
31
32
  execOpts = {
32
33
  stream: {
33
- onClose: async () => { },
34
+ onClose: defaultStreamOnClose(streamedOnce),
34
35
  onData: async (output) => {
36
+ streamedOnce = true;
35
37
  if (!output || closed) {
36
38
  return;
37
39
  }
@@ -3,4 +3,5 @@ import type { HTTPHeaderName } from '../../utils/index.js';
3
3
  export type AuthCookieName = 'auth';
4
4
  export type PublicApiKeyHeaderName = 'X-API-Key' | (string & {});
5
5
  export declare const AUTHORIZATION_HEADER_NAME: HTTPHeaderName;
6
+ export declare const X_FORWARDED_PROTO_HEADER_NAME: HTTPHeaderName;
6
7
  export declare const DEFAULT_VERSION: SemVerVersion;
@@ -1,2 +1,3 @@
1
1
  export const AUTHORIZATION_HEADER_NAME = 'Authorization';
2
+ export const X_FORWARDED_PROTO_HEADER_NAME = 'X-Forwarded-Proto';
2
3
  export const DEFAULT_VERSION = '0.1.0';
@@ -1,5 +1,6 @@
1
1
  import type { AppManifest } from '../../app/index.js';
2
2
  import type { DirPath, URLPath } from '../../dt/index.js';
3
+ import type { ProductUCsLoaderOutput } from '../../product/index.js';
3
4
  import type { UCDef, UCHTTPContract, UCInput, UCManager, UCOPIBase } from '../../uc/index.js';
4
5
  import type { OpenAPISpec } from '../lib/openapi/types.js';
5
6
  import type { ServerManager } from '../lib/server/ServerManager.js';
@@ -9,6 +10,7 @@ export declare class NextJSServerManager implements ServerManager {
9
10
  initSync(): void;
10
11
  mount<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(_appManifest: AppManifest, _ucd: UCDef<I, OPI0, OPI1>, _contract: UCHTTPContract): Promise<void>;
11
12
  mountSync<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(_appManifest: AppManifest, _ucd: UCDef<I, OPI0, OPI1>, _contract: UCHTTPContract): void;
13
+ mountMCP(_ucs: ProductUCsLoaderOutput, _at: URLPath): Promise<void>;
12
14
  mountOpenAPISpec(_spec: OpenAPISpec, _at: URLPath): Promise<void>;
13
15
  mountStaticDir(_dirPath: DirPath): Promise<void>;
14
16
  start(): Promise<void>;
@@ -21,6 +21,9 @@ let NextJSServerManager = class NextJSServerManager {
21
21
  mountSync(_appManifest, _ucd, _contract) {
22
22
  // Nothing to do
23
23
  }
24
+ async mountMCP(_ucs, _at) {
25
+ // Nothing to do
26
+ }
24
27
  async mountOpenAPISpec(_spec, _at) {
25
28
  // Nothing to do
26
29
  }
@@ -1,8 +1,10 @@
1
- import { type Express } from 'express';
1
+ import { type Express, type RequestHandler } from 'express';
2
2
  import type { AppManifest } from '../../app/index.js';
3
3
  import type { DirPath, URLPath } from '../../dt/index.js';
4
+ import type { ProductUCsLoaderOutput } from '../../product/index.js';
4
5
  import type { Configurable, EnvironmentManager, Logger, LoggerSettings, SettingsManager } from '../../std/index.js';
5
6
  import type { UCDef, UCHTTPContract, UCInput, UCManager, UCOPIBase } from '../../uc/index.js';
7
+ import type { MCPHTTPRequestHandlerBuilder } from '../lib/mcp-server/http/MCPHTTPRequestHandlerBuilder.js';
6
8
  import type { OpenAPISpec } from '../lib/openapi/types.js';
7
9
  import { CustomerFacingErrorBuilder } from '../lib/server/CustomerFacingErrorBuilder.js';
8
10
  import { EntrypointsBuilder } from '../lib/server/EntrypointsBuilder.js';
@@ -20,13 +22,14 @@ export declare class NodeExpressServerManager implements Configurable<S>, Server
20
22
  protected environmentManager: EnvironmentManager;
21
23
  private helmetMiddlewareBuilder;
22
24
  protected logger: Logger;
25
+ private mcpHTTPRequestHandlerBuilder;
23
26
  private serverRequestHandler;
24
27
  private serverSSLCertLoader;
25
28
  private settingsManager;
26
29
  private ucManager;
27
30
  protected runtime: Express;
28
31
  private server;
29
- constructor(corsMiddlewareBuilder: CORSMiddlewareBuilder, customerFacingErrorBuilder: CustomerFacingErrorBuilder, entrypointsBuilder: EntrypointsBuilder, environmentManager: EnvironmentManager, helmetMiddlewareBuilder: HelmetMiddlewareBuilder, logger: Logger, serverRequestHandler: ServerRequestHandler, serverSSLCertLoader: ServerSSLCertLoader, settingsManager: SettingsManager<S>, ucManager: UCManager);
32
+ constructor(corsMiddlewareBuilder: CORSMiddlewareBuilder, customerFacingErrorBuilder: CustomerFacingErrorBuilder, entrypointsBuilder: EntrypointsBuilder, environmentManager: EnvironmentManager, helmetMiddlewareBuilder: HelmetMiddlewareBuilder, logger: Logger, mcpHTTPRequestHandlerBuilder: MCPHTTPRequestHandlerBuilder<RequestHandler>, serverRequestHandler: ServerRequestHandler, serverSSLCertLoader: ServerSSLCertLoader, settingsManager: SettingsManager<S>, ucManager: UCManager);
30
33
  s(): S;
31
34
  getRuntime(): Express;
32
35
  overrideUCManager(ucManager: UCManager): void;
@@ -34,6 +37,7 @@ export declare class NodeExpressServerManager implements Configurable<S>, Server
34
37
  initSync(): void;
35
38
  mount<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(appManifest: AppManifest, ucd: UCDef<I, OPI0, OPI1>, contract: UCHTTPContract): Promise<void>;
36
39
  mountSync<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(appManifest: AppManifest, ucd: UCDef<I, OPI0, OPI1>, contract: UCHTTPContract): void;
40
+ mountMCP(ucs: ProductUCsLoaderOutput, at: URLPath): Promise<void>;
37
41
  mountOpenAPISpec(spec: OpenAPISpec, at: URLPath): Promise<void>;
38
42
  mountStaticDir(dirPath: DirPath): Promise<void>;
39
43
  start(): Promise<void>;