libmodulor 0.29.0 → 0.31.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 (156) hide show
  1. package/CHANGELOG.md +66 -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 +7 -7
  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/WordingManager.js +12 -4
  16. package/dist/esm/i18n/locales/de.js +2 -0
  17. package/dist/esm/i18n/locales/en.js +2 -0
  18. package/dist/esm/i18n/locales/es.js +2 -0
  19. package/dist/esm/i18n/locales/fr.js +2 -0
  20. package/dist/esm/i18n/types.d.ts +1 -1
  21. package/dist/esm/index.d.ts +3 -0
  22. package/dist/esm/index.instrumentation-otl.d.ts +1 -0
  23. package/dist/esm/index.instrumentation-otl.js +1 -0
  24. package/dist/esm/index.js +3 -0
  25. package/dist/esm/index.node-express.d.ts +2 -0
  26. package/dist/esm/index.node-express.js +1 -0
  27. package/dist/esm/index.node-hono.d.ts +2 -0
  28. package/dist/esm/index.node-hono.js +1 -0
  29. package/dist/esm/index.node-mcp-express.d.ts +3 -0
  30. package/dist/esm/index.node-mcp-express.js +2 -0
  31. package/dist/esm/index.node-mcp-hono.d.ts +3 -0
  32. package/dist/esm/index.node-mcp-hono.js +2 -0
  33. package/dist/esm/index.node-mcp.d.ts +3 -1
  34. package/dist/esm/index.node-mcp.js +3 -1
  35. package/dist/esm/instrumentation/instrumentation-otl.d.ts +12 -0
  36. package/dist/esm/instrumentation/instrumentation-otl.js +119 -0
  37. package/dist/esm/products/Helper/i18n.d.ts +2 -0
  38. package/dist/esm/std/CryptoManager.d.ts +1 -1
  39. package/dist/esm/std/HTTPAPICaller.d.ts +2 -1
  40. package/dist/esm/std/impl/JoseJWTManager.js +9 -4
  41. package/dist/esm/std/impl/SimpleHTTPAPICaller.js +13 -7
  42. package/dist/esm/std/lib/settings.js +4 -5
  43. package/dist/esm/target/edge-worker-hono-server/SyncEdgeWorkerHonoServerManager.d.ts +2 -0
  44. package/dist/esm/target/edge-worker-hono-server/SyncEdgeWorkerHonoServerManager.js +3 -0
  45. package/dist/esm/target/index.d.ts +1 -1
  46. package/dist/esm/target/index.js +1 -1
  47. package/dist/esm/target/lib/client/AuthDataStore.d.ts +5 -0
  48. package/dist/esm/target/lib/client/impl/InMemoryAuthDataStore.d.ts +7 -0
  49. package/dist/esm/target/lib/client/impl/InMemoryAuthDataStore.js +20 -0
  50. package/dist/esm/target/lib/client/impl/MixedServerClientManager.d.ts +15 -0
  51. package/dist/esm/target/lib/client/impl/MixedServerClientManager.js +44 -0
  52. package/dist/esm/target/lib/json-schema/error.d.ts +3 -0
  53. package/dist/esm/target/lib/json-schema/error.js +14 -0
  54. package/dist/esm/target/lib/json-schema/input.d.ts +16 -0
  55. package/dist/esm/target/lib/json-schema/input.js +67 -0
  56. package/dist/esm/target/lib/json-schema/output.d.ts +19 -0
  57. package/dist/esm/target/lib/json-schema/output.js +128 -0
  58. package/dist/esm/target/lib/manifest.d.ts +32 -1
  59. package/dist/esm/target/lib/manifest.js +22 -1
  60. package/dist/esm/target/lib/mcp-server/MCPServerRequestChecker.d.ts +22 -0
  61. package/dist/esm/target/lib/mcp-server/MCPServerRequestChecker.js +71 -0
  62. package/dist/esm/target/lib/mcp-server/MCPServerRequestHandler.d.ts +16 -0
  63. package/dist/esm/target/lib/mcp-server/MCPServerRequestHandler.js +54 -0
  64. package/dist/esm/target/lib/mcp-server/consts.d.ts +1 -0
  65. package/dist/esm/target/lib/mcp-server/consts.js +1 -0
  66. package/dist/esm/target/lib/mcp-server/funcs.d.ts +13 -0
  67. package/dist/esm/target/lib/mcp-server/funcs.js +84 -0
  68. package/dist/esm/target/lib/mcp-server/http/MCPHTTPRequestHandlerBuilder.d.ts +14 -0
  69. package/dist/esm/target/lib/mcp-server/http/MCPHTTPRequestHandlerBuilder.js +1 -0
  70. package/dist/esm/target/lib/mcp-server/http/express/MCPHTTPExpressFakeRequestHandlerBuilder.d.ts +5 -0
  71. package/dist/esm/target/lib/mcp-server/http/express/MCPHTTPExpressFakeRequestHandlerBuilder.js +18 -0
  72. package/dist/esm/target/lib/mcp-server/http/express/MCPHTTPExpressProtocolRequestHandlerBuilder.d.ts +17 -0
  73. package/dist/esm/target/lib/mcp-server/http/express/MCPHTTPExpressProtocolRequestHandlerBuilder.js +100 -0
  74. package/dist/esm/target/lib/mcp-server/http/express/types.d.ts +3 -0
  75. package/dist/esm/target/lib/mcp-server/http/express/types.js +1 -0
  76. package/dist/esm/target/lib/mcp-server/http/funcs.d.ts +6 -0
  77. package/dist/esm/target/lib/mcp-server/http/funcs.js +50 -0
  78. package/dist/esm/target/lib/mcp-server/http/hono/MCPHTTPHonoFakeRequestHandlerBuilder.d.ts +5 -0
  79. package/dist/esm/target/lib/mcp-server/http/hono/MCPHTTPHonoFakeRequestHandlerBuilder.js +18 -0
  80. package/dist/esm/target/lib/mcp-server/http/hono/MCPHTTPHonoProtocolRequestHandlerBuilder.d.ts +17 -0
  81. package/dist/esm/target/lib/mcp-server/http/hono/MCPHTTPHonoProtocolRequestHandlerBuilder.js +100 -0
  82. package/dist/esm/target/lib/mcp-server/http/hono/types.d.ts +3 -0
  83. package/dist/esm/target/lib/mcp-server/http/hono/types.js +1 -0
  84. package/dist/esm/target/lib/mcp-server/stdio/MCPStdioRequestHandler.d.ts +31 -0
  85. package/dist/esm/target/lib/mcp-server/stdio/MCPStdioRequestHandler.js +108 -0
  86. package/dist/esm/target/lib/mcp-server/stdio/MCPStdioUCClientConfirmManager.d.ts +7 -0
  87. package/dist/esm/target/lib/mcp-server/stdio/MCPStdioUCClientConfirmManager.js +36 -0
  88. package/dist/esm/target/lib/mcp-server/stdio/consts.d.ts +2 -0
  89. package/dist/esm/target/lib/mcp-server/stdio/consts.js +3 -0
  90. package/dist/esm/target/lib/mcp-server/stdio/funcs.d.ts +2 -0
  91. package/dist/esm/target/lib/mcp-server/stdio/funcs.js +10 -0
  92. package/dist/esm/target/lib/mcp-server/stdio/input.d.ts +10 -0
  93. package/dist/esm/target/lib/mcp-server/stdio/input.js +15 -0
  94. package/dist/esm/target/lib/mcp-server/types.d.ts +2 -0
  95. package/dist/esm/target/lib/mcp-server/types.js +1 -0
  96. package/dist/esm/target/lib/openapi/OpenAPISpecBuilder.js +8 -4
  97. package/dist/esm/target/lib/openapi/funcs.d.ts +4 -9
  98. package/dist/esm/target/lib/openapi/funcs.js +18 -119
  99. package/dist/esm/target/lib/openapi/types.d.ts +5 -16
  100. package/dist/esm/target/lib/react/useAction.js +0 -1
  101. package/dist/esm/target/lib/react/useUC.js +0 -3
  102. package/dist/esm/target/lib/server/AuthenticationChecker.js +15 -10
  103. package/dist/esm/target/lib/server/JWTAuthenticationChecker.d.ts +1 -0
  104. package/dist/esm/target/lib/server/JWTAuthenticationChecker.js +11 -2
  105. package/dist/esm/target/lib/server/ServerBooter.d.ts +1 -1
  106. package/dist/esm/target/lib/server/ServerBooter.js +10 -0
  107. package/dist/esm/target/lib/server/ServerManager.d.ts +10 -0
  108. package/dist/esm/target/lib/server/ServerRequestHandler.d.ts +10 -5
  109. package/dist/esm/target/lib/server/ServerRequestHandler.js +35 -25
  110. package/dist/esm/target/lib/server/consts.js +4 -0
  111. package/dist/esm/target/lib/server-express/funcs.js +2 -6
  112. package/dist/esm/target/lib/server-hono/funcs.js +4 -2
  113. package/dist/esm/target/lib/shared.d.ts +1 -0
  114. package/dist/esm/target/lib/shared.js +1 -0
  115. package/dist/esm/target/nextjs-server/NextJSServerManager.d.ts +2 -0
  116. package/dist/esm/target/nextjs-server/NextJSServerManager.js +3 -0
  117. package/dist/esm/target/node-express-server/NodeExpressServerManager.d.ts +6 -2
  118. package/dist/esm/target/node-express-server/NodeExpressServerManager.js +15 -6
  119. package/dist/esm/target/node-hono-server/NodeHonoServerManager.d.ts +6 -2
  120. package/dist/esm/target/node-hono-server/NodeHonoServerManager.js +15 -6
  121. package/dist/esm/target/{node-mcp-server/NodeLocalStdioMCPServerManager.d.ts → node-mcp-server-stdio/NodeMCPStdioServerManager.d.ts} +9 -20
  122. package/dist/esm/target/node-mcp-server-stdio/NodeMCPStdioServerManager.js +108 -0
  123. package/dist/esm/target/react-native-pure/UCFormFieldControl.js +0 -1
  124. package/dist/esm/testing/impl/NodeAppTesterConfigurator.js +7 -0
  125. package/dist/esm/testing/impl/newNodeAppTester.js +12 -0
  126. package/dist/esm/uc/cardinality.d.ts +7 -0
  127. package/dist/esm/uc/cardinality.js +14 -0
  128. package/dist/esm/uc/examples.d.ts +2 -0
  129. package/dist/esm/uc/examples.js +12 -0
  130. package/dist/esm/uc/helpers/UCOutputReader.d.ts +2 -2
  131. package/dist/esm/uc/helpers/UCOutputReader.js +2 -2
  132. package/dist/esm/uc/index.d.ts +2 -0
  133. package/dist/esm/uc/index.js +2 -0
  134. package/dist/esm/uc/input-field.d.ts +3 -6
  135. package/dist/esm/uc/input-field.js +5 -21
  136. package/dist/esm/uc/opi.d.ts +3 -1
  137. package/dist/esm/uc/opi.js +4 -1
  138. package/dist/esm/uc/output-field.d.ts +13 -1
  139. package/dist/esm/uc/output-field.js +9 -11
  140. package/dist/esm/utils/bundling/funcs.js +1 -1
  141. package/dist/esm/utils/bundling/vite/plugin.d.ts +1 -1
  142. package/dist/esm/utils/index.d.ts +1 -0
  143. package/dist/esm/utils/index.js +1 -0
  144. package/dist/esm/utils/streams/funcs.d.ts +2 -0
  145. package/dist/esm/utils/streams/funcs.js +10 -0
  146. package/dist/esm/utils/strings/humanize.js +4 -1
  147. package/package.json +47 -20
  148. package/dist/esm/target/lib/openapi/consts.d.ts +0 -2
  149. package/dist/esm/target/lib/openapi/consts.js +0 -1
  150. package/dist/esm/target/lib/openapi/input.d.ts +0 -16
  151. package/dist/esm/target/lib/openapi/input.js +0 -33
  152. package/dist/esm/target/node-mcp-server/NodeLocalStdioMCPServerManager.js +0 -188
  153. package/dist/esm/target/node-mcp-server/funcs.d.ts +0 -7
  154. package/dist/esm/target/node-mcp-server/funcs.js +0 -45
  155. package/dist/esm/target/node-mcp-server/types.d.ts +0 -15
  156. /package/dist/esm/target/{node-mcp-server/types.js → lib/client/AuthDataStore.js} +0 -0
@@ -0,0 +1,100 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js';
14
+ import { inject, injectable } from 'inversify';
15
+ import { WordingManager } from '../../../../../i18n/index.js';
16
+ import { ucMountingPoint, } from '../../../../../uc/index.js';
17
+ import { toReq, toRes } from '../../../server-hono/funcs.js';
18
+ import { init, toolConfig } from '../../funcs.js';
19
+ import { MCPServerRequestChecker } from '../../MCPServerRequestChecker.js';
20
+ import { MCPServerRequestHandler } from '../../MCPServerRequestHandler.js';
21
+ import { ucStreamExecOpts } from '../funcs.js';
22
+ let MCPHTTPHonoProtocolRequestHandlerBuilder = class MCPHTTPHonoProtocolRequestHandlerBuilder {
23
+ logger;
24
+ productManifest;
25
+ serverRequestChecker;
26
+ serverRequestHandler;
27
+ wordingManager;
28
+ constructor(logger, productManifest, serverRequestChecker, serverRequestHandler, wordingManager) {
29
+ this.logger = logger;
30
+ this.productManifest = productManifest;
31
+ this.serverRequestChecker = serverRequestChecker;
32
+ this.serverRequestHandler = serverRequestHandler;
33
+ this.wordingManager = wordingManager;
34
+ }
35
+ exec({ ucs, ucManager, }) {
36
+ return async (c) => {
37
+ const { status } = await this.serverRequestChecker.exec({
38
+ req: toReq(c),
39
+ });
40
+ if (status) {
41
+ c.status(status);
42
+ return c.json({});
43
+ }
44
+ const server = init(this.productManifest);
45
+ const transport = new WebStandardStreamableHTTPServerTransport();
46
+ // In Streamable HTTP, there is usually one request => one transport => one server.
47
+ // So there shouldn't be multiple 'stream' use cases invoked at the same time.
48
+ // But maintaining a Map allows us to handle this case if it occurs.
49
+ // This way, we have all the streams available to close them when the transport is closed.
50
+ const execOptss = new Map();
51
+ for (const uc of ucs) {
52
+ const { def: { ext }, } = uc;
53
+ const mountingPoint = ext?.cmd?.mountAt ?? ucMountingPoint(uc);
54
+ const wording = this.wordingManager.uc(uc.def);
55
+ const config = toolConfig(uc, 'server', wording);
56
+ const transportType = ext?.http?.transportType ?? 'standard';
57
+ server.registerTool(mountingPoint, config, (input, extra) => {
58
+ const execOpts = ucStreamExecOpts(this.logger, transportType, extra);
59
+ if (execOpts) {
60
+ execOptss.set(mountingPoint, execOpts);
61
+ }
62
+ return this.serverRequestHandler.exec({
63
+ appManifest: uc.appManifest,
64
+ envelope: 'json',
65
+ execOpts,
66
+ req: {
67
+ ...toReq(c),
68
+ bodyFromJSON: async () => input,
69
+ },
70
+ res: toRes(c),
71
+ ucd: uc.def,
72
+ ucManager,
73
+ });
74
+ });
75
+ }
76
+ transport.onclose = async () => {
77
+ this.logger.trace('Transport closed => closing streams');
78
+ await Promise.all(execOptss.values().map((eo) => eo.stream?.onClose()));
79
+ };
80
+ c.req.raw.signal.addEventListener('abort', async () => {
81
+ this.logger.trace('Connection closed => closing transport');
82
+ await transport.close();
83
+ });
84
+ await server.connect(transport);
85
+ return transport.handleRequest(c.req.raw);
86
+ };
87
+ }
88
+ };
89
+ MCPHTTPHonoProtocolRequestHandlerBuilder = __decorate([
90
+ injectable(),
91
+ __param(0, inject('Logger')),
92
+ __param(1, inject('ProductManifest')),
93
+ __param(2, inject(MCPServerRequestChecker)),
94
+ __param(3, inject(MCPServerRequestHandler)),
95
+ __param(4, inject(WordingManager)),
96
+ __metadata("design:paramtypes", [Object, Object, MCPServerRequestChecker,
97
+ MCPServerRequestHandler,
98
+ WordingManager])
99
+ ], MCPHTTPHonoProtocolRequestHandlerBuilder);
100
+ export { MCPHTTPHonoProtocolRequestHandlerBuilder };
@@ -0,0 +1,3 @@
1
+ import type { MiddlewareHandler } from 'hono';
2
+ import type { MCPHTTPRequestHandlerBuilder } from '../MCPHTTPRequestHandlerBuilder.js';
3
+ export type MCPHTTPHonoRequestHandlerBuilder = MCPHTTPRequestHandlerBuilder<MiddlewareHandler>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,31 @@
1
+ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
2
+ import type { AppManifest } from '../../../../app/index.js';
3
+ import type { JWTManager, Worker } from '../../../../std/index.js';
4
+ import { UCBuilder, type UCDef, type UCInput, type UCManager, type UCOPIBase } from '../../../../uc/index.js';
5
+ import type { AuthDataStore } from '../../client/AuthDataStore.js';
6
+ import type { StdioToolInput } from './input.js';
7
+ interface Input<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined> {
8
+ appManifest: AppManifest;
9
+ toolInput: StdioToolInput<I>;
10
+ ucd: UCDef<I, OPI0, OPI1>;
11
+ /**
12
+ * It is not injected in the handler constructor because it must be the same as the one used in ServerManager.
13
+ *
14
+ * And in some cases, this latter is specific to a context : for instance in automated tests.
15
+ */
16
+ ucManager: UCManager;
17
+ }
18
+ type Output = CallToolResult;
19
+ export declare class MCPStdioRequestHandler implements Worker<Input, Promise<Output>> {
20
+ private authDataStore;
21
+ private jwtManager;
22
+ private ucBuilder;
23
+ constructor(authDataStore: AuthDataStore, jwtManager: JWTManager, ucBuilder: UCBuilder);
24
+ exec<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>({ appManifest, toolInput, ucd, ucManager, }: Input<I, OPI0, OPI1>): Promise<Output>;
25
+ private auth;
26
+ private applySideEffects;
27
+ private applyClearAuthSideEffect;
28
+ private applyRedirectSideEffect;
29
+ private applySetAuthSideEffect;
30
+ }
31
+ export {};
@@ -0,0 +1,108 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { inject, injectable } from 'inversify';
14
+ import { UCBuilder, UCOutputSideEffectType, } from '../../../../uc/index.js';
15
+ import { resAborted, resError, resObj } from '../funcs.js';
16
+ let MCPStdioRequestHandler = class MCPStdioRequestHandler {
17
+ authDataStore;
18
+ jwtManager;
19
+ ucBuilder;
20
+ constructor(authDataStore, jwtManager, ucBuilder) {
21
+ this.authDataStore = authDataStore;
22
+ this.jwtManager = jwtManager;
23
+ this.ucBuilder = ucBuilder;
24
+ }
25
+ async exec({ appManifest, toolInput, ucd, ucManager, }) {
26
+ try {
27
+ const auth = await this.auth();
28
+ const uc = this.ucBuilder.exec({
29
+ appManifest,
30
+ auth,
31
+ def: ucd,
32
+ });
33
+ if (toolInput) {
34
+ const { _reserved, ...rest } = toolInput;
35
+ uc.fill(rest);
36
+ if (_reserved?.confirmed === undefined) {
37
+ await ucManager.confirmClient(uc);
38
+ // ... throws an error
39
+ }
40
+ else if (_reserved.confirmed === false) {
41
+ return resAborted();
42
+ }
43
+ }
44
+ const ucor = await ucManager.execClient(uc);
45
+ await this.applySideEffects(ucor);
46
+ return resObj(ucor.output());
47
+ }
48
+ catch (err) {
49
+ return resError(err);
50
+ }
51
+ }
52
+ async auth() {
53
+ // TODO : Memoize the auth instead of decoding each time
54
+ const jwt = await this.authDataStore.get();
55
+ if (!jwt) {
56
+ return null;
57
+ }
58
+ return this.jwtManager.decodeUnsafe(jwt);
59
+ }
60
+ async applySideEffects(ucor) {
61
+ const { io } = ucor.ucd();
62
+ const sideEffects = io.o?.sideEffects;
63
+ if (!sideEffects) {
64
+ return;
65
+ }
66
+ let item;
67
+ if (ucor.canItem00()) {
68
+ item = ucor.item00().item;
69
+ }
70
+ for (const se of sideEffects) {
71
+ const { type } = se;
72
+ switch (type) {
73
+ case UCOutputSideEffectType.CLEAR_AUTH:
74
+ await this.applyClearAuthSideEffect();
75
+ return;
76
+ case UCOutputSideEffectType.REDIRECT:
77
+ await this.applyRedirectSideEffect(item);
78
+ return;
79
+ case UCOutputSideEffectType.SET_AUTH:
80
+ await this.applySetAuthSideEffect(item);
81
+ return;
82
+ default:
83
+ (type);
84
+ }
85
+ }
86
+ }
87
+ async applyClearAuthSideEffect() {
88
+ await this.authDataStore.set(null);
89
+ }
90
+ async applyRedirectSideEffect(_item) {
91
+ // Nothing to do
92
+ }
93
+ async applySetAuthSideEffect(item) {
94
+ if (!item || !('jwt' in item) || typeof item.jwt !== 'string') {
95
+ return;
96
+ }
97
+ const { jwt } = item;
98
+ await this.authDataStore.set(jwt);
99
+ }
100
+ };
101
+ MCPStdioRequestHandler = __decorate([
102
+ injectable(),
103
+ __param(0, inject('AuthDataStore')),
104
+ __param(1, inject('JWTManager')),
105
+ __param(2, inject(UCBuilder)),
106
+ __metadata("design:paramtypes", [Object, Object, UCBuilder])
107
+ ], MCPStdioRequestHandler);
108
+ export { MCPStdioRequestHandler };
@@ -0,0 +1,7 @@
1
+ import { WordingManager } from '../../../../i18n/index.js';
2
+ import type { UCClientConfirmManager, UCDef, UCInput, UCOPIBase } from '../../../../uc/index.js';
3
+ export declare class MCPStdioUCClientConfirmManager implements UCClientConfirmManager {
4
+ private wordingManager;
5
+ constructor(wordingManager: WordingManager);
6
+ exec<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(ucd: UCDef<I, OPI0, OPI1>): Promise<boolean>;
7
+ }
@@ -0,0 +1,36 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { inject, injectable } from 'inversify';
14
+ import { WordingManager } from '../../../../i18n/index.js';
15
+ import { UC_CONFIRM_HINT } from './consts.js';
16
+ let MCPStdioUCClientConfirmManager = class MCPStdioUCClientConfirmManager {
17
+ wordingManager;
18
+ constructor(wordingManager) {
19
+ this.wordingManager = wordingManager;
20
+ }
21
+ async exec(ucd) {
22
+ const { message, title } = this.wordingManager.ucClientConfirm(ucd);
23
+ let m = title;
24
+ if (message) {
25
+ m = `\n${message}`;
26
+ }
27
+ m = `\n${UC_CONFIRM_HINT}`;
28
+ throw new Error(m);
29
+ }
30
+ };
31
+ MCPStdioUCClientConfirmManager = __decorate([
32
+ injectable(),
33
+ __param(0, inject(WordingManager)),
34
+ __metadata("design:paramtypes", [WordingManager])
35
+ ], MCPStdioUCClientConfirmManager);
36
+ export { MCPStdioUCClientConfirmManager };
@@ -0,0 +1,2 @@
1
+ export declare const ERR_LOGGER_LEVEL = "Set the logging_level to \"error\" as MCP does not want the server to log to stdout (see https://modelcontextprotocol.io/docs/tools/debugging#implementing-logging)";
2
+ export declare const UC_CONFIRM_HINT: string;
@@ -0,0 +1,3 @@
1
+ import { RESERVED_CONFIRMED_KEY, RESERVED_KEY } from './input.js';
2
+ export const ERR_LOGGER_LEVEL = 'Set the logging_level to "error" as MCP does not want the server to log to stdout (see https://modelcontextprotocol.io/docs/tools/debugging#implementing-logging)';
3
+ export const UC_CONFIRM_HINT = `(Hint: ask the user to confirm. If they do, set the property "${RESERVED_CONFIRMED_KEY}" in "${RESERVED_KEY}" to true in the input. Otherwise, set it to false)`;
@@ -0,0 +1,2 @@
1
+ import type { LoggerLevel } from '../../../../std/index.js';
2
+ export declare function assertLoggerLevel(loggerLevel: LoggerLevel): void;
@@ -0,0 +1,10 @@
1
+ import { ERR_LOGGER_LEVEL } from './consts.js';
2
+ export function assertLoggerLevel(loggerLevel) {
3
+ if (loggerLevel === 'error') {
4
+ return;
5
+ }
6
+ // Depending on the `Logger` implementation, this.logger.error() might not write to stderr (e.g. can write to a file).
7
+ // That's why we explicitly write to stdout by calling console.error().
8
+ // biome-ignore lint/suspicious/noConsole: we want it
9
+ console.error(new Error(ERR_LOGGER_LEVEL));
10
+ }
@@ -0,0 +1,10 @@
1
+ import type { JSONSchemaObject } from '../../../../dt/index.js';
2
+ import type { UCInput } from '../../../../uc/index.js';
3
+ export type StdioToolInput<I extends UCInput | undefined = undefined> = I & {
4
+ _reserved?: {
5
+ confirmed?: boolean;
6
+ };
7
+ };
8
+ export declare const RESERVED_KEY: "_reserved";
9
+ export declare const RESERVED_CONFIRMED_KEY: "confirmed";
10
+ export declare function stdioToolInputSchema(): JSONSchemaObject<StdioToolInput>['properties'];
@@ -0,0 +1,15 @@
1
+ export const RESERVED_KEY = '_reserved';
2
+ export const RESERVED_CONFIRMED_KEY = 'confirmed';
3
+ export function stdioToolInputSchema() {
4
+ return {
5
+ [RESERVED_KEY]: {
6
+ additionalProperties: false,
7
+ properties: {
8
+ [RESERVED_CONFIRMED_KEY]: {
9
+ type: 'boolean',
10
+ },
11
+ },
12
+ type: 'object',
13
+ },
14
+ };
15
+ }
@@ -0,0 +1,2 @@
1
+ import type { RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export type RegisterToolConfig = Pick<RegisteredTool, 'description' | 'inputSchema' | 'outputSchema' | 'title' | 'annotations' | '_meta'>;
@@ -0,0 +1 @@
1
+ export {};
@@ -13,8 +13,10 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
13
13
  import { inject, injectable } from 'inversify';
14
14
  import { WordingManager } from '../../../i18n/index.js';
15
15
  import { formatFQUCInputName, formatFQUCName, ucHTTPContract, } from '../../../uc/index.js';
16
+ import { serverErrorJsonSchema } from '../json-schema/error.js';
17
+ import { ucInputJsonSchema } from '../json-schema/input.js';
16
18
  import { DEFAULT_VERSION } from '../shared.js';
17
- import { openAPIErrorSchema, openAPIErrors, openAPIInputSchema, openAPIParameters, openAPIRequestBody, openAPISecurity, openAPISecuritySchemes, openAPISuccess, } from './funcs.js';
19
+ import { openAPIErrors, openAPIParameters, openAPIRequestBody, openAPISecurity, openAPISecuritySchemes, openAPISuccess, } from './funcs.js';
18
20
  let OpenAPISpecBuilder = class OpenAPISpecBuilder {
19
21
  i18nManager;
20
22
  productManifest;
@@ -49,7 +51,7 @@ let OpenAPISpecBuilder = class OpenAPISpecBuilder {
49
51
  const fqUCName = formatFQUCName(uc.appManifest.name, uc.def.metadata.name);
50
52
  const fqUCInputName = formatFQUCInputName(fqUCName);
51
53
  output.spec.components.schemas[fqUCInputName] =
52
- openAPIInputSchema(uc);
54
+ ucInputJsonSchema(uc);
53
55
  for (const p of [path, ...pathAliases]) {
54
56
  output.spec.paths[p] = {
55
57
  ...output.spec.paths[p],
@@ -71,7 +73,7 @@ let OpenAPISpecBuilder = class OpenAPISpecBuilder {
71
73
  spec: {
72
74
  components: {
73
75
  schemas: {
74
- Error: openAPIErrorSchema(),
76
+ Error: serverErrorJsonSchema(),
75
77
  },
76
78
  securitySchemes: openAPISecuritySchemes(this.s().server_cookies_name_auth, this.s().server_public_api_key_header_name),
77
79
  },
@@ -93,9 +95,11 @@ let OpenAPISpecBuilder = class OpenAPISpecBuilder {
93
95
  // biome-ignore lint/suspicious/noExplicitAny: can be anything
94
96
  uc, envelope, fqUCInputName) {
95
97
  const { desc, label } = this.wordingManager.uc(uc.def);
98
+ const res_200 = this.i18nManager.t('res_200');
99
+ const res_204 = this.i18nManager.t('res_204');
96
100
  const path = {
97
101
  responses: {
98
- ...openAPISuccess(uc),
102
+ ...openAPISuccess(uc, { 200: res_200, 204: res_204 }),
99
103
  ...errors,
100
104
  // TODO : Infer errors that can be sent within ServerMain
101
105
  },
@@ -1,16 +1,11 @@
1
- import { type ServerError } from '../../../error/index.js';
2
- import { type FQUCInputName, type UC, type UCInput, type UCInputUnwrapped, type UCOPIBase, type UCOutput, type UCOutputPart, type UCOutputReaderPart, type UCSec } from '../../../uc/index.js';
1
+ import type { HTTPStatusNumber } from '../../../dt/index.js';
2
+ import { type FQUCInputName, type UC, type UCInput, type UCOPIBase, type UCSec } from '../../../uc/index.js';
3
3
  import { type HTTPDataEnvelope } from '../../../utils/index.js';
4
4
  import { type AuthCookieName, type PublicApiKeyHeaderName } from '../shared.js';
5
- import type { OpenAPIParameter, OpenAPIRequestBody, OpenAPIResponses, OpenAPISchema, OpenAPISecurity, OpenAPISecuritySchemes } from './types.js';
6
- export declare function openAPIErrorSchema(): OpenAPISchema<ServerError>;
5
+ import type { OpenAPIParameter, OpenAPIRequestBody, OpenAPIResponses, OpenAPISecurity, OpenAPISecuritySchemes } from './types.js';
7
6
  export declare function openAPIErrors(): OpenAPIResponses;
8
- export declare function openAPIInputSchema<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(uc: UC<I, OPI0, OPI1>): OpenAPISchema<UCInputUnwrapped<I>>;
9
- export declare function openAPIOPISchema<OPI extends UCOPIBase>(part: UCOutputReaderPart<NonNullable<OPI>>): OpenAPISchema<OPI>;
10
- export declare function openAPIOutputPartSchema<OPI extends UCOPIBase>(part: UCOutputReaderPart<NonNullable<OPI>>): OpenAPISchema<UCOutputPart<OPI>>;
11
- export declare function openAPIOutputSchema<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(uc: UC<I, OPI0, OPI1>): OpenAPISchema<UCOutput<OPI0, OPI1>>;
12
7
  export declare function openAPIParameters<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(uc: UC<I, OPI0, OPI1>, envelope: Extract<HTTPDataEnvelope, 'query-params'>): OpenAPIParameter[];
13
8
  export declare function openAPIRequestBody<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(uc: UC<I, OPI0, OPI1>, envelope: Extract<HTTPDataEnvelope, 'form-data' | 'json'>, fqUCInputName: FQUCInputName): OpenAPIRequestBody;
14
9
  export declare function openAPISecuritySchemes(authCookieName: AuthCookieName, publicApiKeyHeaderName: PublicApiKeyHeaderName): OpenAPISecuritySchemes;
15
10
  export declare function openAPISecurity(sec: UCSec | undefined): OpenAPISecurity;
16
- export declare function openAPISuccess<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(uc: UC<I, OPI0, OPI1>): OpenAPIResponses;
11
+ export declare function openAPISuccess<I extends UCInput | undefined = undefined, OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(uc: UC<I, OPI0, OPI1>, descriptions: Record<Extract<HTTPStatusNumber, 200 | 204>, string>): OpenAPIResponses;
@@ -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>>;