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
@@ -0,0 +1,88 @@
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 { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.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-express/funcs.js';
18
+ import { init, toolConfig } from '../../funcs.js';
19
+ import { MCPServerRequestHandler } from '../../MCPServerRequestHandler.js';
20
+ import { ucStreamExecOpts } from '../funcs.js';
21
+ let MCPHTTPExpressProtocolRequestHandlerBuilder = class MCPHTTPExpressProtocolRequestHandlerBuilder {
22
+ logger;
23
+ productManifest;
24
+ serverRequestHandler;
25
+ wordingManager;
26
+ constructor(logger, productManifest, serverRequestHandler, wordingManager) {
27
+ this.logger = logger;
28
+ this.productManifest = productManifest;
29
+ this.serverRequestHandler = serverRequestHandler;
30
+ this.wordingManager = wordingManager;
31
+ }
32
+ exec({ ucs, ucManager, }) {
33
+ return async (req, res) => {
34
+ const server = init(this.productManifest);
35
+ const transport = new StreamableHTTPServerTransport();
36
+ // In Streamable HTTP, there is usually one request => one transport => one server.
37
+ // So there shouldn't be multiple 'stream' use cases invoked at the same time.
38
+ // But maintaining a Map allows us to handle this case if it occurs.
39
+ // This way, we have all the streams available to close them when the transport is closed.
40
+ const execOptss = new Map();
41
+ for (const uc of ucs) {
42
+ const { def: { ext }, } = uc;
43
+ const mountingPoint = ext?.cmd?.mountAt ?? ucMountingPoint(uc);
44
+ const wording = this.wordingManager.uc(uc.def);
45
+ const config = toolConfig(uc, 'server', wording);
46
+ const transportType = ext?.http?.transportType ?? 'standard';
47
+ server.registerTool(mountingPoint, config, (input, extra) => {
48
+ const execOpts = ucStreamExecOpts(this.logger, transportType, extra);
49
+ if (execOpts) {
50
+ execOptss.set(mountingPoint, execOpts);
51
+ }
52
+ return this.serverRequestHandler.exec({
53
+ appManifest: uc.appManifest,
54
+ envelope: 'json',
55
+ execOpts,
56
+ req: {
57
+ ...toReq(req),
58
+ bodyFromJSON: async () => input,
59
+ },
60
+ res: toRes(res),
61
+ ucd: uc.def,
62
+ ucManager,
63
+ });
64
+ });
65
+ }
66
+ transport.onclose = async () => {
67
+ this.logger.trace('Transport closed => closing streams');
68
+ await Promise.all(execOptss.values().map((eo) => eo.stream?.onClose()));
69
+ };
70
+ res.on('close', async () => {
71
+ this.logger.trace('Connection closed => closing transport');
72
+ await transport.close();
73
+ });
74
+ await server.connect(transport);
75
+ await transport.handleRequest(req, res, req.body);
76
+ };
77
+ }
78
+ };
79
+ MCPHTTPExpressProtocolRequestHandlerBuilder = __decorate([
80
+ injectable(),
81
+ __param(0, inject('Logger')),
82
+ __param(1, inject('ProductManifest')),
83
+ __param(2, inject(MCPServerRequestHandler)),
84
+ __param(3, inject(WordingManager)),
85
+ __metadata("design:paramtypes", [Object, Object, MCPServerRequestHandler,
86
+ WordingManager])
87
+ ], MCPHTTPExpressProtocolRequestHandlerBuilder);
88
+ export { MCPHTTPExpressProtocolRequestHandlerBuilder };
@@ -0,0 +1,3 @@
1
+ import type { RequestHandler } from 'express';
2
+ import type { MCPHTTPRequestHandlerBuilder } from '../MCPHTTPRequestHandlerBuilder.js';
3
+ export type MCPHTTPExpressRequestHandlerBuilder = MCPHTTPRequestHandlerBuilder<RequestHandler>;
@@ -0,0 +1,6 @@
1
+ import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';
2
+ import type { ServerNotification, ServerRequest } from '@modelcontextprotocol/sdk/types.js';
3
+ import type { TransportType } from '../../../../dt/index.js';
4
+ import type { Logger } from '../../../../std/index.js';
5
+ import type { UCManagerExecServerOpts, UCOPIBase } from '../../../../uc/index.js';
6
+ export declare function ucStreamExecOpts<OPI0 extends UCOPIBase | undefined = undefined, OPI1 extends UCOPIBase | undefined = undefined>(logger: Logger, transportType: TransportType, extra: RequestHandlerExtra<ServerRequest, ServerNotification>): UCManagerExecServerOpts<OPI0, OPI1> | undefined;
@@ -0,0 +1,50 @@
1
+ import { defaultStreamOnClose } from '../../../../utils/index.js';
2
+ export function ucStreamExecOpts(logger, transportType, extra) {
3
+ let execOpts;
4
+ switch (transportType) {
5
+ case 'standard':
6
+ // Nothing to do
7
+ break;
8
+ case 'stream': {
9
+ let streamedOnce = false;
10
+ execOpts = {
11
+ stream: {
12
+ onClose: defaultStreamOnClose(streamedOnce),
13
+ onData: async (output) => {
14
+ logger.trace('execOpts.stream.onData', {
15
+ output: JSON.stringify(output),
16
+ });
17
+ streamedOnce = true;
18
+ if (!output) {
19
+ return;
20
+ }
21
+ try {
22
+ await extra.sendNotification({
23
+ method: 'notifications/message',
24
+ params: {
25
+ data: output,
26
+ level: 'info',
27
+ },
28
+ });
29
+ }
30
+ catch (_err) {
31
+ // There are cases where the client (e.g. Claude) has already closed the stream
32
+ // without triggering any lifecycle method (e.g `transport.onclose` or `c.req.raw.signal.addEventListener('abort')` with hono.
33
+ // Sending a notification in this case triggers an error like so : `No connection established for request ID: 1`.
34
+ // So we assume it's closed and force close the stream.
35
+ logger.trace('Connection already closed => force closing stream');
36
+ await execOpts?.stream?.onClose();
37
+ }
38
+ },
39
+ onDone: async () => {
40
+ logger.trace('execOpts.stream.onDone');
41
+ },
42
+ },
43
+ };
44
+ break;
45
+ }
46
+ default:
47
+ transportType;
48
+ }
49
+ return execOpts;
50
+ }
@@ -0,0 +1,5 @@
1
+ import type { MiddlewareHandler } from 'hono';
2
+ import type { MCPHTTPHonoRequestHandlerBuilder } from './types.js';
3
+ export declare class MCPHTTPHonoFakeRequestHandlerBuilder implements MCPHTTPHonoRequestHandlerBuilder {
4
+ exec(): MiddlewareHandler;
5
+ }
@@ -0,0 +1,18 @@
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
+ import { injectable } from 'inversify';
8
+ let MCPHTTPHonoFakeRequestHandlerBuilder = class MCPHTTPHonoFakeRequestHandlerBuilder {
9
+ exec() {
10
+ return async (c) => {
11
+ return c.json({}, 200);
12
+ };
13
+ }
14
+ };
15
+ MCPHTTPHonoFakeRequestHandlerBuilder = __decorate([
16
+ injectable()
17
+ ], MCPHTTPHonoFakeRequestHandlerBuilder);
18
+ export { MCPHTTPHonoFakeRequestHandlerBuilder };
@@ -0,0 +1,15 @@
1
+ import type { MiddlewareHandler } from 'hono';
2
+ import { WordingManager } from '../../../../../i18n/index.js';
3
+ import type { ProductManifest } from '../../../../../product/index.js';
4
+ import type { Logger } from '../../../../../std/index.js';
5
+ import { MCPServerRequestHandler } from '../../MCPServerRequestHandler.js';
6
+ import type { MCPHTTPRequestHandlerBuilderInput } from '../MCPHTTPRequestHandlerBuilder.js';
7
+ import type { MCPHTTPHonoRequestHandlerBuilder } from './types.js';
8
+ export declare class MCPHTTPHonoProtocolRequestHandlerBuilder implements MCPHTTPHonoRequestHandlerBuilder {
9
+ private logger;
10
+ private productManifest;
11
+ private serverRequestHandler;
12
+ private wordingManager;
13
+ constructor(logger: Logger, productManifest: ProductManifest, serverRequestHandler: MCPServerRequestHandler, wordingManager: WordingManager);
14
+ exec({ ucs, ucManager, }: MCPHTTPRequestHandlerBuilderInput): MiddlewareHandler;
15
+ }
@@ -0,0 +1,88 @@
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 { MCPServerRequestHandler } from '../../MCPServerRequestHandler.js';
20
+ import { ucStreamExecOpts } from '../funcs.js';
21
+ let MCPHTTPHonoProtocolRequestHandlerBuilder = class MCPHTTPHonoProtocolRequestHandlerBuilder {
22
+ logger;
23
+ productManifest;
24
+ serverRequestHandler;
25
+ wordingManager;
26
+ constructor(logger, productManifest, serverRequestHandler, wordingManager) {
27
+ this.logger = logger;
28
+ this.productManifest = productManifest;
29
+ this.serverRequestHandler = serverRequestHandler;
30
+ this.wordingManager = wordingManager;
31
+ }
32
+ exec({ ucs, ucManager, }) {
33
+ return async (c) => {
34
+ const server = init(this.productManifest);
35
+ const transport = new WebStandardStreamableHTTPServerTransport();
36
+ // In Streamable HTTP, there is usually one request => one transport => one server.
37
+ // So there shouldn't be multiple 'stream' use cases invoked at the same time.
38
+ // But maintaining a Map allows us to handle this case if it occurs.
39
+ // This way, we have all the streams available to close them when the transport is closed.
40
+ const execOptss = new Map();
41
+ for (const uc of ucs) {
42
+ const { def: { ext }, } = uc;
43
+ const mountingPoint = ext?.cmd?.mountAt ?? ucMountingPoint(uc);
44
+ const wording = this.wordingManager.uc(uc.def);
45
+ const config = toolConfig(uc, 'server', wording);
46
+ const transportType = ext?.http?.transportType ?? 'standard';
47
+ server.registerTool(mountingPoint, config, (input, extra) => {
48
+ const execOpts = ucStreamExecOpts(this.logger, transportType, extra);
49
+ if (execOpts) {
50
+ execOptss.set(mountingPoint, execOpts);
51
+ }
52
+ return this.serverRequestHandler.exec({
53
+ appManifest: uc.appManifest,
54
+ envelope: 'json',
55
+ execOpts,
56
+ req: {
57
+ ...toReq(c),
58
+ bodyFromJSON: async () => input,
59
+ },
60
+ res: toRes(c),
61
+ ucd: uc.def,
62
+ ucManager,
63
+ });
64
+ });
65
+ }
66
+ transport.onclose = async () => {
67
+ this.logger.trace('Transport closed => closing streams');
68
+ await Promise.all(execOptss.values().map((eo) => eo.stream?.onClose()));
69
+ };
70
+ c.req.raw.signal.addEventListener('abort', async () => {
71
+ this.logger.trace('Connection closed => closing transport');
72
+ await transport.close();
73
+ });
74
+ await server.connect(transport);
75
+ return transport.handleRequest(c.req.raw);
76
+ };
77
+ }
78
+ };
79
+ MCPHTTPHonoProtocolRequestHandlerBuilder = __decorate([
80
+ injectable(),
81
+ __param(0, inject('Logger')),
82
+ __param(1, inject('ProductManifest')),
83
+ __param(2, inject(MCPServerRequestHandler)),
84
+ __param(3, inject(WordingManager)),
85
+ __metadata("design:paramtypes", [Object, Object, MCPServerRequestHandler,
86
+ WordingManager])
87
+ ], MCPHTTPHonoProtocolRequestHandlerBuilder);
88
+ 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;