@leanmcp/core 0.4.0 → 0.4.2
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/dist/index.js +65 -6
- package/dist/index.mjs +65 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -985,6 +985,63 @@ async function createHTTPServer(serverInput, options) {
|
|
|
985
985
|
if (sessionId && transports[sessionId]) {
|
|
986
986
|
transport = transports[sessionId];
|
|
987
987
|
logger.debug(`Reusing session: ${sessionId}`);
|
|
988
|
+
} else if (sessionId && isInitializeRequest(req.body)) {
|
|
989
|
+
logger.info(`Initialize request with session ${sessionId} - checking for session restoration...`);
|
|
990
|
+
if (httpOptions.sessionStore) {
|
|
991
|
+
const exists = await httpOptions.sessionStore.sessionExists(sessionId);
|
|
992
|
+
if (exists) {
|
|
993
|
+
logger.info(`Restoring session: ${sessionId}`);
|
|
994
|
+
transport = new StreamableHTTPServerTransport2({
|
|
995
|
+
sessionIdGenerator: /* @__PURE__ */ __name(() => sessionId, "sessionIdGenerator"),
|
|
996
|
+
onsessioninitialized: /* @__PURE__ */ __name((sid) => {
|
|
997
|
+
logger.info(`Session restored (onsessioninitialized): ${sid}`);
|
|
998
|
+
}, "onsessioninitialized")
|
|
999
|
+
});
|
|
1000
|
+
transports[sessionId] = transport;
|
|
1001
|
+
logger.info(`Transport stored for restored session: ${sessionId}`);
|
|
1002
|
+
transport.onclose = async () => {
|
|
1003
|
+
if (transport.sessionId) {
|
|
1004
|
+
delete transports[transport.sessionId];
|
|
1005
|
+
logger.debug(`Session cleaned up: ${transport.sessionId}`);
|
|
1006
|
+
if (httpOptions.sessionStore) {
|
|
1007
|
+
await httpOptions.sessionStore.deleteSession(transport.sessionId);
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
};
|
|
1011
|
+
const freshServer = await serverFactory();
|
|
1012
|
+
if (freshServer && typeof freshServer.waitForInit === "function") {
|
|
1013
|
+
await freshServer.waitForInit();
|
|
1014
|
+
}
|
|
1015
|
+
await freshServer.connect(transport);
|
|
1016
|
+
} else {
|
|
1017
|
+
logger.info(`Session ${sessionId} not found in store, creating new session`);
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
if (!transport) {
|
|
1021
|
+
transport = new StreamableHTTPServerTransport2({
|
|
1022
|
+
sessionIdGenerator: /* @__PURE__ */ __name(() => (0, import_node_crypto.randomUUID)(), "sessionIdGenerator"),
|
|
1023
|
+
onsessioninitialized: /* @__PURE__ */ __name(async (newSessionId) => {
|
|
1024
|
+
transports[newSessionId] = transport;
|
|
1025
|
+
logger.info(`Session initialized: ${newSessionId}`);
|
|
1026
|
+
if (httpOptions.sessionStore) {
|
|
1027
|
+
await httpOptions.sessionStore.createSession(newSessionId);
|
|
1028
|
+
}
|
|
1029
|
+
}, "onsessioninitialized")
|
|
1030
|
+
});
|
|
1031
|
+
transport.onclose = async () => {
|
|
1032
|
+
if (transport.sessionId) {
|
|
1033
|
+
delete transports[transport.sessionId];
|
|
1034
|
+
logger.debug(`Session cleaned up: ${transport.sessionId}`);
|
|
1035
|
+
if (httpOptions.sessionStore) {
|
|
1036
|
+
await httpOptions.sessionStore.deleteSession(transport.sessionId);
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
};
|
|
1040
|
+
if (!mcpServer) {
|
|
1041
|
+
throw new Error("MCP server not initialized");
|
|
1042
|
+
}
|
|
1043
|
+
await mcpServer.connect(transport);
|
|
1044
|
+
}
|
|
988
1045
|
} else if (sessionId && !isInitializeRequest(req.body)) {
|
|
989
1046
|
logger.info(`Transport missing for session ${sessionId}, checking session store...`);
|
|
990
1047
|
if (httpOptions.sessionStore) {
|
|
@@ -1000,13 +1057,15 @@ async function createHTTPServer(serverInput, options) {
|
|
|
1000
1057
|
});
|
|
1001
1058
|
return;
|
|
1002
1059
|
}
|
|
1060
|
+
logger.info(`Auto-restoring session: ${sessionId}`);
|
|
1003
1061
|
transport = new StreamableHTTPServerTransport2({
|
|
1004
1062
|
sessionIdGenerator: /* @__PURE__ */ __name(() => sessionId, "sessionIdGenerator"),
|
|
1005
1063
|
onsessioninitialized: /* @__PURE__ */ __name((sid) => {
|
|
1006
|
-
|
|
1007
|
-
logger.info(`Transport recreated for session: ${sid}`);
|
|
1064
|
+
logger.info(`Session auto-restored (onsessioninitialized): ${sid}`);
|
|
1008
1065
|
}, "onsessioninitialized")
|
|
1009
1066
|
});
|
|
1067
|
+
transports[sessionId] = transport;
|
|
1068
|
+
logger.info(`Transport stored for session: ${sessionId}`);
|
|
1010
1069
|
transport.onclose = async () => {
|
|
1011
1070
|
if (transport.sessionId) {
|
|
1012
1071
|
delete transports[transport.sessionId];
|
|
@@ -1822,14 +1881,14 @@ var init_index = __esm({
|
|
|
1822
1881
|
/**
|
|
1823
1882
|
* Auto-register all services from the mcp directory
|
|
1824
1883
|
* Scans the directory recursively and registers all exported classes
|
|
1825
|
-
*
|
|
1884
|
+
*
|
|
1826
1885
|
* @param mcpDir - Path to the mcp directory containing service files
|
|
1827
1886
|
* @param serviceFactories - Optional map of service class names to factory functions for dependency injection
|
|
1828
|
-
*
|
|
1887
|
+
*
|
|
1829
1888
|
* @example
|
|
1830
1889
|
* // Auto-register services with no dependencies
|
|
1831
1890
|
* await server.autoRegisterServices('./mcp');
|
|
1832
|
-
*
|
|
1891
|
+
*
|
|
1833
1892
|
* @example
|
|
1834
1893
|
* // Auto-register with dependency injection
|
|
1835
1894
|
* await server.autoRegisterServices('./mcp', {
|
|
@@ -1982,7 +2041,7 @@ var init_index = __esm({
|
|
|
1982
2041
|
}
|
|
1983
2042
|
/**
|
|
1984
2043
|
* Watch UI manifest for changes and reload resources dynamically
|
|
1985
|
-
*
|
|
2044
|
+
*
|
|
1986
2045
|
* CRITICAL: Only for stateful mode. In stateless mode, each request
|
|
1987
2046
|
* creates a fresh server that reads the manifest directly, making
|
|
1988
2047
|
* watchers both unnecessary and a memory leak source.
|
package/dist/index.mjs
CHANGED
|
@@ -683,6 +683,63 @@ async function createHTTPServer(serverInput, options) {
|
|
|
683
683
|
if (sessionId && transports[sessionId]) {
|
|
684
684
|
transport = transports[sessionId];
|
|
685
685
|
logger.debug(`Reusing session: ${sessionId}`);
|
|
686
|
+
} else if (sessionId && isInitializeRequest(req.body)) {
|
|
687
|
+
logger.info(`Initialize request with session ${sessionId} - checking for session restoration...`);
|
|
688
|
+
if (httpOptions.sessionStore) {
|
|
689
|
+
const exists = await httpOptions.sessionStore.sessionExists(sessionId);
|
|
690
|
+
if (exists) {
|
|
691
|
+
logger.info(`Restoring session: ${sessionId}`);
|
|
692
|
+
transport = new StreamableHTTPServerTransport2({
|
|
693
|
+
sessionIdGenerator: /* @__PURE__ */ __name(() => sessionId, "sessionIdGenerator"),
|
|
694
|
+
onsessioninitialized: /* @__PURE__ */ __name((sid) => {
|
|
695
|
+
logger.info(`Session restored (onsessioninitialized): ${sid}`);
|
|
696
|
+
}, "onsessioninitialized")
|
|
697
|
+
});
|
|
698
|
+
transports[sessionId] = transport;
|
|
699
|
+
logger.info(`Transport stored for restored session: ${sessionId}`);
|
|
700
|
+
transport.onclose = async () => {
|
|
701
|
+
if (transport.sessionId) {
|
|
702
|
+
delete transports[transport.sessionId];
|
|
703
|
+
logger.debug(`Session cleaned up: ${transport.sessionId}`);
|
|
704
|
+
if (httpOptions.sessionStore) {
|
|
705
|
+
await httpOptions.sessionStore.deleteSession(transport.sessionId);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
};
|
|
709
|
+
const freshServer = await serverFactory();
|
|
710
|
+
if (freshServer && typeof freshServer.waitForInit === "function") {
|
|
711
|
+
await freshServer.waitForInit();
|
|
712
|
+
}
|
|
713
|
+
await freshServer.connect(transport);
|
|
714
|
+
} else {
|
|
715
|
+
logger.info(`Session ${sessionId} not found in store, creating new session`);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
if (!transport) {
|
|
719
|
+
transport = new StreamableHTTPServerTransport2({
|
|
720
|
+
sessionIdGenerator: /* @__PURE__ */ __name(() => randomUUID(), "sessionIdGenerator"),
|
|
721
|
+
onsessioninitialized: /* @__PURE__ */ __name(async (newSessionId) => {
|
|
722
|
+
transports[newSessionId] = transport;
|
|
723
|
+
logger.info(`Session initialized: ${newSessionId}`);
|
|
724
|
+
if (httpOptions.sessionStore) {
|
|
725
|
+
await httpOptions.sessionStore.createSession(newSessionId);
|
|
726
|
+
}
|
|
727
|
+
}, "onsessioninitialized")
|
|
728
|
+
});
|
|
729
|
+
transport.onclose = async () => {
|
|
730
|
+
if (transport.sessionId) {
|
|
731
|
+
delete transports[transport.sessionId];
|
|
732
|
+
logger.debug(`Session cleaned up: ${transport.sessionId}`);
|
|
733
|
+
if (httpOptions.sessionStore) {
|
|
734
|
+
await httpOptions.sessionStore.deleteSession(transport.sessionId);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
};
|
|
738
|
+
if (!mcpServer) {
|
|
739
|
+
throw new Error("MCP server not initialized");
|
|
740
|
+
}
|
|
741
|
+
await mcpServer.connect(transport);
|
|
742
|
+
}
|
|
686
743
|
} else if (sessionId && !isInitializeRequest(req.body)) {
|
|
687
744
|
logger.info(`Transport missing for session ${sessionId}, checking session store...`);
|
|
688
745
|
if (httpOptions.sessionStore) {
|
|
@@ -698,13 +755,15 @@ async function createHTTPServer(serverInput, options) {
|
|
|
698
755
|
});
|
|
699
756
|
return;
|
|
700
757
|
}
|
|
758
|
+
logger.info(`Auto-restoring session: ${sessionId}`);
|
|
701
759
|
transport = new StreamableHTTPServerTransport2({
|
|
702
760
|
sessionIdGenerator: /* @__PURE__ */ __name(() => sessionId, "sessionIdGenerator"),
|
|
703
761
|
onsessioninitialized: /* @__PURE__ */ __name((sid) => {
|
|
704
|
-
|
|
705
|
-
logger.info(`Transport recreated for session: ${sid}`);
|
|
762
|
+
logger.info(`Session auto-restored (onsessioninitialized): ${sid}`);
|
|
706
763
|
}, "onsessioninitialized")
|
|
707
764
|
});
|
|
765
|
+
transports[sessionId] = transport;
|
|
766
|
+
logger.info(`Transport stored for session: ${sessionId}`);
|
|
708
767
|
transport.onclose = async () => {
|
|
709
768
|
if (transport.sessionId) {
|
|
710
769
|
delete transports[transport.sessionId];
|
|
@@ -1424,14 +1483,14 @@ var MCPServer = class {
|
|
|
1424
1483
|
/**
|
|
1425
1484
|
* Auto-register all services from the mcp directory
|
|
1426
1485
|
* Scans the directory recursively and registers all exported classes
|
|
1427
|
-
*
|
|
1486
|
+
*
|
|
1428
1487
|
* @param mcpDir - Path to the mcp directory containing service files
|
|
1429
1488
|
* @param serviceFactories - Optional map of service class names to factory functions for dependency injection
|
|
1430
|
-
*
|
|
1489
|
+
*
|
|
1431
1490
|
* @example
|
|
1432
1491
|
* // Auto-register services with no dependencies
|
|
1433
1492
|
* await server.autoRegisterServices('./mcp');
|
|
1434
|
-
*
|
|
1493
|
+
*
|
|
1435
1494
|
* @example
|
|
1436
1495
|
* // Auto-register with dependency injection
|
|
1437
1496
|
* await server.autoRegisterServices('./mcp', {
|
|
@@ -1584,7 +1643,7 @@ var MCPServer = class {
|
|
|
1584
1643
|
}
|
|
1585
1644
|
/**
|
|
1586
1645
|
* Watch UI manifest for changes and reload resources dynamically
|
|
1587
|
-
*
|
|
1646
|
+
*
|
|
1588
1647
|
* CRITICAL: Only for stateful mode. In stateless mode, each request
|
|
1589
1648
|
* creates a fresh server that reads the manifest directly, making
|
|
1590
1649
|
* watchers both unnecessary and a memory leak source.
|