@ttoss/http-server-mcp 0.39.1 → 0.41.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.
- package/README.md +16 -0
- package/dist/index.cjs +99 -3
- package/dist/index.d.cts +12 -0
- package/dist/index.d.mts +12 -0
- package/dist/index.mjs +100 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -676,6 +676,7 @@ Creates a Koa router configured to handle MCP protocol requests.
|
|
|
676
676
|
- `createMcpServer` (`McpServerFactory`) — Per-request factory serving the `2026-07-28` revision; see [Serving the `2026-07-28` revision](#serving-the-2026-07-28-revision)
|
|
677
677
|
- `bus` (`ServerEventBus`) — Change-event bus `subscriptions/listen` streams subscribe to (default: in-process); see [Change notifications and shutdown](#change-notifications-and-shutdown)
|
|
678
678
|
- `keepAliveMs` (`number`) — SSE keepalive interval for `2026-07-28` streams (default: `15000`)
|
|
679
|
+
- `streaming` (`boolean`) — `false` on a host that buffers the response (AWS Lambda behind API Gateway): no change notifications are advertised, so `subscriptions/listen` completes at once (default: `true`); see [Hosting without streaming](#hosting-without-streaming-aws-lambda)
|
|
679
680
|
- `apiBaseUrl` (`string`) — Base URL prepended to relative paths in `apiCall`
|
|
680
681
|
- `getApiHeaders` (`(ctx: Context) => Record<string, string>`) — Return headers to inject into every `apiCall` for this request
|
|
681
682
|
- `auth` (`McpAuthOptions`) — OAuth/JWT authentication; see [Authentication](#authentication)
|
|
@@ -781,6 +782,8 @@ Registers `Tool`s on an MCP server. See [Tools](#tools).
|
|
|
781
782
|
|
|
782
783
|
By default, a JSON Schema `inputSchema` is **advertised but not enforced**: it round-trips verbatim over `tools/list` so clients know what to send, while arguments reach your handler unchecked. Set `validateArguments: true` to reject mismatched calls before the handler runs.
|
|
783
784
|
|
|
785
|
+
A schema with `additionalProperties: false` refuses every argument it does not declare, and names each one (`prefix: is not an argument of this tool`), so a misspelled argument is an error the caller can fix rather than one dropped unseen.
|
|
786
|
+
|
|
784
787
|
Enable it once you're confident `inputSchema` describes every value the tool genuinely accepts. Schemas derived from an OpenAPI document are a common source of _incomplete_ ones — a field a client may send as `null` to clear it, or one that accepts several shapes, is easily emitted as a bare `{ type: 'string' }`. Validating against a schema like that rejects calls the underlying API would have accepted. To describe those cases accurately, use `{ type: ['string', 'null'] }` for a nullable field and forward `oneOf`/`anyOf` verbatim rather than collapsing to one type.
|
|
785
788
|
|
|
786
789
|
### `defineTool(params)`
|
|
@@ -1050,6 +1053,19 @@ process.on('SIGTERM', async () => {
|
|
|
1050
1053
|
|
|
1051
1054
|
The default bus is in-process, so `notify` reaches the streams this process holds. Behind several replicas, pass a `bus` implementing `ServerEventBus` over a shared pub/sub. Keep `keepAliveMs` below the idle timeout of anything in front of the server, or a quiet stream is cut there. 2025-era traffic is served statelessly, so it holds no stream to notify.
|
|
1052
1055
|
|
|
1056
|
+
### Hosting without streaming (AWS Lambda)
|
|
1057
|
+
|
|
1058
|
+
A host that buffers the whole response — AWS Lambda behind API Gateway, or any runtime without response streaming — never delivers a stream that stays open: the invocation dies at its timeout, and the client reopens the stream at once. Pass `streaming: false` there:
|
|
1059
|
+
|
|
1060
|
+
```typescript
|
|
1061
|
+
const mcpRouter = createMcpRouter(buildServer(), {
|
|
1062
|
+
createMcpServer: buildServer,
|
|
1063
|
+
streaming: false,
|
|
1064
|
+
});
|
|
1065
|
+
```
|
|
1066
|
+
|
|
1067
|
+
The router then stops every server instance it serves from advertising change notifications: `listChanged` for tools, prompts and resources, and `resources.subscribe`. `McpServer` turns them on by default for each kind you register, which is what makes the SDK hold a `subscriptions/listen` open; with nothing advertised, a listen is acknowledged and completed in the same response. A kind you register nothing for stays unadvertised. Nothing is lost on such a host: no process outlives the request to send a notification, so `notify` and `close()` reach no client.
|
|
1068
|
+
|
|
1053
1069
|
**Supported HTTP methods:**
|
|
1054
1070
|
|
|
1055
1071
|
- `POST /mcp` - Send JSON-RPC requests/notifications
|
package/dist/index.cjs
CHANGED
|
@@ -55,6 +55,49 @@ var NO_NOTIFIER = {
|
|
|
55
55
|
resourceUpdated: () => {}
|
|
56
56
|
};
|
|
57
57
|
/**
|
|
58
|
+
* Stops the server advertising change notifications for the tools, prompts
|
|
59
|
+
* and resources it serves, keeping every other capability as registered.
|
|
60
|
+
*
|
|
61
|
+
* `McpServer` advertises `listChanged: true` for each kind the moment one is
|
|
62
|
+
* registered, and the SDK then honours a `2026-07-28` `subscriptions/listen`
|
|
63
|
+
* with an SSE stream it never ends. A host that buffers the response until the
|
|
64
|
+
* handler returns — AWS Lambda behind API Gateway — delivers nothing and kills
|
|
65
|
+
* the invocation at its timeout, and the client reopens the stream at once, so
|
|
66
|
+
* each open session keeps one invocation busy for good (measured on a
|
|
67
|
+
* production Lambda in 2026-10: one 30 s timeout per session every ~30 s).
|
|
68
|
+
* With nothing advertised the SDK acknowledges the
|
|
69
|
+
* listen and completes it in the same response. A kind with nothing
|
|
70
|
+
* registered stays unadvertised, since advertising it would answer its `list`
|
|
71
|
+
* call with "method not found".
|
|
72
|
+
*/
|
|
73
|
+
var withoutChangeNotifications = product => {
|
|
74
|
+
const server = product instanceof _modelcontextprotocol_server.McpServer ? product.server : product;
|
|
75
|
+
const {
|
|
76
|
+
tools,
|
|
77
|
+
prompts,
|
|
78
|
+
resources
|
|
79
|
+
} = server.getCapabilities();
|
|
80
|
+
const off = {};
|
|
81
|
+
if (tools) off.tools = {
|
|
82
|
+
listChanged: false
|
|
83
|
+
};
|
|
84
|
+
if (prompts) off.prompts = {
|
|
85
|
+
listChanged: false
|
|
86
|
+
};
|
|
87
|
+
if (resources) off.resources = {
|
|
88
|
+
listChanged: false,
|
|
89
|
+
subscribe: false
|
|
90
|
+
};
|
|
91
|
+
server.registerCapabilities(off);
|
|
92
|
+
return product;
|
|
93
|
+
};
|
|
94
|
+
/** `factory`, with each instance it builds passed through {@link withoutChangeNotifications}. */
|
|
95
|
+
var servingNoChangeNotifications = factory => {
|
|
96
|
+
return factory && (async ctx => {
|
|
97
|
+
return withoutChangeNotifications(await factory(ctx));
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
58
101
|
* Reads a header as `string | undefined`. Koa's `ctx.get` returns `''` for a
|
|
59
102
|
* missing header, which the classifier would read as "header present but
|
|
60
103
|
* empty" rather than absent.
|
|
@@ -141,10 +184,13 @@ var createMcpRequestServer = ({
|
|
|
141
184
|
server,
|
|
142
185
|
sessionIdGenerator,
|
|
143
186
|
bus,
|
|
144
|
-
keepAliveMs
|
|
187
|
+
keepAliveMs,
|
|
188
|
+
streaming = true
|
|
145
189
|
}) => {
|
|
146
190
|
const isStateful = sessionIdGenerator !== void 0;
|
|
147
|
-
|
|
191
|
+
if (!streaming) withoutChangeNotifications(server);
|
|
192
|
+
const factory = streaming ? createMcpServer : servingNoChangeNotifications(createMcpServer);
|
|
193
|
+
const modern = factory ? (0, _modelcontextprotocol_server.createMcpHandler)(factory, {
|
|
148
194
|
legacy: "reject",
|
|
149
195
|
bus,
|
|
150
196
|
keepAliveMs
|
|
@@ -520,6 +566,50 @@ var isStandardSchema = schema => {
|
|
|
520
566
|
return "~standard" in schema;
|
|
521
567
|
};
|
|
522
568
|
/**
|
|
569
|
+
* Enforces a closed schema while naming each undeclared argument. The SDK's
|
|
570
|
+
* own `additionalProperties: false` issue carries no path, so the argument to
|
|
571
|
+
* drop goes unnamed; the rest of the schema is checked with it left open.
|
|
572
|
+
*/
|
|
573
|
+
var namingUndeclared = ({
|
|
574
|
+
schema,
|
|
575
|
+
standard
|
|
576
|
+
}) => {
|
|
577
|
+
const {
|
|
578
|
+
additionalProperties: _closed,
|
|
579
|
+
...openSchema
|
|
580
|
+
} = schema;
|
|
581
|
+
const open = (0, _modelcontextprotocol_server.fromJsonSchema)(openSchema);
|
|
582
|
+
const declared = new Set(Object.keys(schema.properties ?? {}));
|
|
583
|
+
const withUndeclared = ({
|
|
584
|
+
value,
|
|
585
|
+
result
|
|
586
|
+
}) => {
|
|
587
|
+
const undeclared = Object.keys(Object(value)).filter(key => {
|
|
588
|
+
return !declared.has(key);
|
|
589
|
+
});
|
|
590
|
+
if (undeclared.length === 0) return result;
|
|
591
|
+
return {
|
|
592
|
+
issues: [...undeclared.map(key => {
|
|
593
|
+
return {
|
|
594
|
+
message: "is not an argument of this tool",
|
|
595
|
+
path: [key]
|
|
596
|
+
};
|
|
597
|
+
}), ...(result.issues ?? [])]
|
|
598
|
+
};
|
|
599
|
+
};
|
|
600
|
+
return {
|
|
601
|
+
"~standard": {
|
|
602
|
+
...standard["~standard"],
|
|
603
|
+
validate: async value => {
|
|
604
|
+
return withUndeclared({
|
|
605
|
+
value,
|
|
606
|
+
result: await open["~standard"].validate(value)
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
};
|
|
611
|
+
};
|
|
612
|
+
/**
|
|
523
613
|
* Converts a JSON Schema into the Standard Schema `registerTool` accepts.
|
|
524
614
|
*
|
|
525
615
|
* A Standard Schema keeps advertisement and enforcement in separate fields:
|
|
@@ -532,6 +622,10 @@ var fromJsonObjectSchema = ({
|
|
|
532
622
|
validate
|
|
533
623
|
}) => {
|
|
534
624
|
const standard = (0, _modelcontextprotocol_server.fromJsonSchema)(schema);
|
|
625
|
+
if (validate && schema.additionalProperties === false) return namingUndeclared({
|
|
626
|
+
schema,
|
|
627
|
+
standard
|
|
628
|
+
});
|
|
535
629
|
if (validate) return standard;
|
|
536
630
|
return {
|
|
537
631
|
"~standard": {
|
|
@@ -1596,6 +1690,7 @@ var createMcpRouter = (server, options = {}) => {
|
|
|
1596
1690
|
createMcpServer,
|
|
1597
1691
|
bus,
|
|
1598
1692
|
keepAliveMs,
|
|
1693
|
+
streaming,
|
|
1599
1694
|
apiBaseUrl,
|
|
1600
1695
|
getApiHeaders,
|
|
1601
1696
|
auth
|
|
@@ -1606,7 +1701,8 @@ var createMcpRouter = (server, options = {}) => {
|
|
|
1606
1701
|
sessionIdGenerator,
|
|
1607
1702
|
createMcpServer,
|
|
1608
1703
|
bus,
|
|
1609
|
-
keepAliveMs
|
|
1704
|
+
keepAliveMs,
|
|
1705
|
+
streaming
|
|
1610
1706
|
});
|
|
1611
1707
|
const router = new _ttoss_http_server.Router();
|
|
1612
1708
|
let authCheck;
|
package/dist/index.d.cts
CHANGED
|
@@ -1707,6 +1707,18 @@ export interface McpRouterOptions {
|
|
|
1707
1707
|
* @default 15000
|
|
1708
1708
|
*/
|
|
1709
1709
|
keepAliveMs?: number;
|
|
1710
|
+
/**
|
|
1711
|
+
* Whether the host delivers a response while the handler is still writing
|
|
1712
|
+
* it. Set `false` on a host that buffers the whole response — AWS Lambda
|
|
1713
|
+
* behind API Gateway, or any serverless runtime without response streaming.
|
|
1714
|
+
* The router then stops every instance it serves from advertising change
|
|
1715
|
+
* notifications (`listChanged` for tools, prompts and resources, and
|
|
1716
|
+
* `resources.subscribe`), so a `2026-07-28` `subscriptions/listen` is
|
|
1717
|
+
* acknowledged and completed at once instead of being held until the
|
|
1718
|
+
* platform's timeout. `notify` then reaches no client.
|
|
1719
|
+
* @default true
|
|
1720
|
+
*/
|
|
1721
|
+
streaming?: boolean;
|
|
1710
1722
|
/**
|
|
1711
1723
|
* Base URL prepended to relative paths passed to `apiCall` (paths starting
|
|
1712
1724
|
* with `/`). Tool handlers can then call `apiCall('GET', '/resource')` without
|
package/dist/index.d.mts
CHANGED
|
@@ -1708,6 +1708,18 @@ export interface McpRouterOptions {
|
|
|
1708
1708
|
* @default 15000
|
|
1709
1709
|
*/
|
|
1710
1710
|
keepAliveMs?: number;
|
|
1711
|
+
/**
|
|
1712
|
+
* Whether the host delivers a response while the handler is still writing
|
|
1713
|
+
* it. Set `false` on a host that buffers the whole response — AWS Lambda
|
|
1714
|
+
* behind API Gateway, or any serverless runtime without response streaming.
|
|
1715
|
+
* The router then stops every instance it serves from advertising change
|
|
1716
|
+
* notifications (`listChanged` for tools, prompts and resources, and
|
|
1717
|
+
* `resources.subscribe`), so a `2026-07-28` `subscriptions/listen` is
|
|
1718
|
+
* acknowledged and completed at once instead of being held until the
|
|
1719
|
+
* platform's timeout. `notify` then reaches no client.
|
|
1720
|
+
* @default true
|
|
1721
|
+
*/
|
|
1722
|
+
streaming?: boolean;
|
|
1711
1723
|
/**
|
|
1712
1724
|
* Base URL prepended to relative paths passed to `apiCall` (paths starting
|
|
1713
1725
|
* with `/`). Tool handlers can then call `apiCall('GET', '/resource')` without
|
package/dist/index.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { Router } from "@ttoss/http-server";
|
|
|
5
5
|
import { authMiddleware } from "@ttoss/http-server-auth";
|
|
6
6
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
7
7
|
import { NodeStreamableHTTPServerTransport, toNodeHandler } from "@modelcontextprotocol/node";
|
|
8
|
-
import { InMemoryServerEventBus, McpServer, ProtocolErrorCode, SUPPORTED_PROTOCOL_VERSIONS, classifyInboundRequest, createMcpHandler, fromJsonSchema } from "@modelcontextprotocol/server";
|
|
8
|
+
import { InMemoryServerEventBus, McpServer, McpServer as McpServer$1, ProtocolErrorCode, SUPPORTED_PROTOCOL_VERSIONS, classifyInboundRequest, createMcpHandler, fromJsonSchema } from "@modelcontextprotocol/server";
|
|
9
9
|
import { z } from "zod";
|
|
10
10
|
|
|
11
11
|
//#region src/context.ts
|
|
@@ -52,6 +52,49 @@ var NO_NOTIFIER = {
|
|
|
52
52
|
resourceUpdated: () => {}
|
|
53
53
|
};
|
|
54
54
|
/**
|
|
55
|
+
* Stops the server advertising change notifications for the tools, prompts
|
|
56
|
+
* and resources it serves, keeping every other capability as registered.
|
|
57
|
+
*
|
|
58
|
+
* `McpServer` advertises `listChanged: true` for each kind the moment one is
|
|
59
|
+
* registered, and the SDK then honours a `2026-07-28` `subscriptions/listen`
|
|
60
|
+
* with an SSE stream it never ends. A host that buffers the response until the
|
|
61
|
+
* handler returns — AWS Lambda behind API Gateway — delivers nothing and kills
|
|
62
|
+
* the invocation at its timeout, and the client reopens the stream at once, so
|
|
63
|
+
* each open session keeps one invocation busy for good (measured on a
|
|
64
|
+
* production Lambda in 2026-10: one 30 s timeout per session every ~30 s).
|
|
65
|
+
* With nothing advertised the SDK acknowledges the
|
|
66
|
+
* listen and completes it in the same response. A kind with nothing
|
|
67
|
+
* registered stays unadvertised, since advertising it would answer its `list`
|
|
68
|
+
* call with "method not found".
|
|
69
|
+
*/
|
|
70
|
+
var withoutChangeNotifications = product => {
|
|
71
|
+
const server = product instanceof McpServer$1 ? product.server : product;
|
|
72
|
+
const {
|
|
73
|
+
tools,
|
|
74
|
+
prompts,
|
|
75
|
+
resources
|
|
76
|
+
} = server.getCapabilities();
|
|
77
|
+
const off = {};
|
|
78
|
+
if (tools) off.tools = {
|
|
79
|
+
listChanged: false
|
|
80
|
+
};
|
|
81
|
+
if (prompts) off.prompts = {
|
|
82
|
+
listChanged: false
|
|
83
|
+
};
|
|
84
|
+
if (resources) off.resources = {
|
|
85
|
+
listChanged: false,
|
|
86
|
+
subscribe: false
|
|
87
|
+
};
|
|
88
|
+
server.registerCapabilities(off);
|
|
89
|
+
return product;
|
|
90
|
+
};
|
|
91
|
+
/** `factory`, with each instance it builds passed through {@link withoutChangeNotifications}. */
|
|
92
|
+
var servingNoChangeNotifications = factory => {
|
|
93
|
+
return factory && (async ctx => {
|
|
94
|
+
return withoutChangeNotifications(await factory(ctx));
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
55
98
|
* Reads a header as `string | undefined`. Koa's `ctx.get` returns `''` for a
|
|
56
99
|
* missing header, which the classifier would read as "header present but
|
|
57
100
|
* empty" rather than absent.
|
|
@@ -138,10 +181,13 @@ var createMcpRequestServer = ({
|
|
|
138
181
|
server,
|
|
139
182
|
sessionIdGenerator,
|
|
140
183
|
bus,
|
|
141
|
-
keepAliveMs
|
|
184
|
+
keepAliveMs,
|
|
185
|
+
streaming = true
|
|
142
186
|
}) => {
|
|
143
187
|
const isStateful = sessionIdGenerator !== void 0;
|
|
144
|
-
|
|
188
|
+
if (!streaming) withoutChangeNotifications(server);
|
|
189
|
+
const factory = streaming ? createMcpServer : servingNoChangeNotifications(createMcpServer);
|
|
190
|
+
const modern = factory ? createMcpHandler(factory, {
|
|
145
191
|
legacy: "reject",
|
|
146
192
|
bus,
|
|
147
193
|
keepAliveMs
|
|
@@ -517,6 +563,50 @@ var isStandardSchema = schema => {
|
|
|
517
563
|
return "~standard" in schema;
|
|
518
564
|
};
|
|
519
565
|
/**
|
|
566
|
+
* Enforces a closed schema while naming each undeclared argument. The SDK's
|
|
567
|
+
* own `additionalProperties: false` issue carries no path, so the argument to
|
|
568
|
+
* drop goes unnamed; the rest of the schema is checked with it left open.
|
|
569
|
+
*/
|
|
570
|
+
var namingUndeclared = ({
|
|
571
|
+
schema,
|
|
572
|
+
standard
|
|
573
|
+
}) => {
|
|
574
|
+
const {
|
|
575
|
+
additionalProperties: _closed,
|
|
576
|
+
...openSchema
|
|
577
|
+
} = schema;
|
|
578
|
+
const open = fromJsonSchema(openSchema);
|
|
579
|
+
const declared = new Set(Object.keys(schema.properties ?? {}));
|
|
580
|
+
const withUndeclared = ({
|
|
581
|
+
value,
|
|
582
|
+
result
|
|
583
|
+
}) => {
|
|
584
|
+
const undeclared = Object.keys(Object(value)).filter(key => {
|
|
585
|
+
return !declared.has(key);
|
|
586
|
+
});
|
|
587
|
+
if (undeclared.length === 0) return result;
|
|
588
|
+
return {
|
|
589
|
+
issues: [...undeclared.map(key => {
|
|
590
|
+
return {
|
|
591
|
+
message: "is not an argument of this tool",
|
|
592
|
+
path: [key]
|
|
593
|
+
};
|
|
594
|
+
}), ...(result.issues ?? [])]
|
|
595
|
+
};
|
|
596
|
+
};
|
|
597
|
+
return {
|
|
598
|
+
"~standard": {
|
|
599
|
+
...standard["~standard"],
|
|
600
|
+
validate: async value => {
|
|
601
|
+
return withUndeclared({
|
|
602
|
+
value,
|
|
603
|
+
result: await open["~standard"].validate(value)
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
};
|
|
609
|
+
/**
|
|
520
610
|
* Converts a JSON Schema into the Standard Schema `registerTool` accepts.
|
|
521
611
|
*
|
|
522
612
|
* A Standard Schema keeps advertisement and enforcement in separate fields:
|
|
@@ -529,6 +619,10 @@ var fromJsonObjectSchema = ({
|
|
|
529
619
|
validate
|
|
530
620
|
}) => {
|
|
531
621
|
const standard = fromJsonSchema(schema);
|
|
622
|
+
if (validate && schema.additionalProperties === false) return namingUndeclared({
|
|
623
|
+
schema,
|
|
624
|
+
standard
|
|
625
|
+
});
|
|
532
626
|
if (validate) return standard;
|
|
533
627
|
return {
|
|
534
628
|
"~standard": {
|
|
@@ -1593,6 +1687,7 @@ var createMcpRouter = (server, options = {}) => {
|
|
|
1593
1687
|
createMcpServer,
|
|
1594
1688
|
bus,
|
|
1595
1689
|
keepAliveMs,
|
|
1690
|
+
streaming,
|
|
1596
1691
|
apiBaseUrl,
|
|
1597
1692
|
getApiHeaders,
|
|
1598
1693
|
auth
|
|
@@ -1603,7 +1698,8 @@ var createMcpRouter = (server, options = {}) => {
|
|
|
1603
1698
|
sessionIdGenerator,
|
|
1604
1699
|
createMcpServer,
|
|
1605
1700
|
bus,
|
|
1606
|
-
keepAliveMs
|
|
1701
|
+
keepAliveMs,
|
|
1702
|
+
streaming
|
|
1607
1703
|
});
|
|
1608
1704
|
const router = new Router();
|
|
1609
1705
|
let authCheck;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttoss/http-server-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.41.0",
|
|
4
4
|
"description": "Model Context Protocol (MCP) server integration for @ttoss/http-server",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
"@modelcontextprotocol/node": "^2.1.1",
|
|
38
38
|
"@modelcontextprotocol/server": "^2.3.1",
|
|
39
39
|
"zod": "^4.6.7",
|
|
40
|
+
"@ttoss/http-server": "^0.14.2",
|
|
40
41
|
"@ttoss/http-server-auth": "^0.10.2",
|
|
41
42
|
"@ttoss/auth-core": "^0.20.1",
|
|
42
|
-
"@ttoss/http-server": "^0.14.2",
|
|
43
43
|
"@ttoss/i18n-core": "^0.9.2"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|