@leanmcp/core 0.3.9 → 0.3.10
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 +58 -18
- package/dist/index.mjs +58 -18
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -889,20 +889,36 @@ async function createHTTPServer(serverInput, options) {
|
|
|
889
889
|
logger.error(`Server error: ${error.message}`);
|
|
890
890
|
reject(error);
|
|
891
891
|
});
|
|
892
|
-
|
|
892
|
+
let isShuttingDown = false;
|
|
893
|
+
const cleanup = /* @__PURE__ */ __name(async () => {
|
|
894
|
+
if (isShuttingDown) return;
|
|
895
|
+
isShuttingDown = true;
|
|
893
896
|
logger.info("\nShutting down server...");
|
|
894
|
-
Object.values(transports)
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
897
|
+
for (const transport of Object.values(transports)) {
|
|
898
|
+
try {
|
|
899
|
+
transport.close?.();
|
|
900
|
+
} catch (e) {
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
if (activeListener) {
|
|
904
|
+
await new Promise((resolveClose) => {
|
|
905
|
+
activeListener.close((err) => {
|
|
906
|
+
if (err) {
|
|
907
|
+
logger.warn(`Error closing server: ${err.message}`);
|
|
908
|
+
} else {
|
|
909
|
+
logger.info("Server closed");
|
|
910
|
+
}
|
|
911
|
+
resolveClose();
|
|
912
|
+
});
|
|
913
|
+
});
|
|
914
|
+
}
|
|
903
915
|
}, "cleanup");
|
|
904
|
-
|
|
905
|
-
|
|
916
|
+
const handleShutdown = /* @__PURE__ */ __name(() => {
|
|
917
|
+
cleanup().finally(() => {
|
|
918
|
+
});
|
|
919
|
+
}, "handleShutdown");
|
|
920
|
+
process.once("SIGINT", handleShutdown);
|
|
921
|
+
process.once("SIGTERM", handleShutdown);
|
|
906
922
|
} catch (error) {
|
|
907
923
|
reject(error);
|
|
908
924
|
}
|
|
@@ -1491,7 +1507,11 @@ var init_index = __esm({
|
|
|
1491
1507
|
}
|
|
1492
1508
|
}
|
|
1493
1509
|
}
|
|
1494
|
-
for (const [uri,
|
|
1510
|
+
for (const [uri, entry] of Object.entries(manifest)) {
|
|
1511
|
+
const isString = typeof entry === "string";
|
|
1512
|
+
const htmlPath = isString ? entry : entry.htmlPath;
|
|
1513
|
+
const isGPTApp = !isString && entry.isGPTApp;
|
|
1514
|
+
const gptMeta = !isString ? entry.gptMeta : void 0;
|
|
1495
1515
|
if (!import_fs.default.existsSync(htmlPath)) {
|
|
1496
1516
|
if (this.logging) {
|
|
1497
1517
|
this.logger.warn(`UI HTML file not found: ${htmlPath}`);
|
|
@@ -1499,17 +1519,25 @@ var init_index = __esm({
|
|
|
1499
1519
|
continue;
|
|
1500
1520
|
}
|
|
1501
1521
|
const wasRegistered = this.resources.has(uri);
|
|
1522
|
+
const mimeType = isGPTApp ? "text/html+skybridge" : "text/html;profile=mcp-app";
|
|
1523
|
+
const _meta = {};
|
|
1524
|
+
if (isGPTApp) {
|
|
1525
|
+
_meta["openai/outputTemplate"] = uri;
|
|
1526
|
+
if (gptMeta) Object.assign(_meta, gptMeta);
|
|
1527
|
+
if (_meta["openai/widgetPrefersBorder"] === void 0) _meta["openai/widgetPrefersBorder"] = true;
|
|
1528
|
+
}
|
|
1502
1529
|
this.resources.set(uri, {
|
|
1503
1530
|
uri,
|
|
1504
1531
|
name: uri.replace("ui://", "").replace(/\//g, "-"),
|
|
1505
1532
|
description: `Auto-generated UI resource from pre-built HTML`,
|
|
1506
|
-
mimeType
|
|
1533
|
+
mimeType,
|
|
1507
1534
|
inputSchema: void 0,
|
|
1508
1535
|
method: /* @__PURE__ */ __name(async () => {
|
|
1509
1536
|
if (import_fs.default.existsSync(htmlPath)) {
|
|
1510
1537
|
const html = import_fs.default.readFileSync(htmlPath, "utf-8");
|
|
1511
1538
|
return {
|
|
1512
|
-
text: html
|
|
1539
|
+
text: html,
|
|
1540
|
+
_meta: Object.keys(_meta).length > 0 ? _meta : void 0
|
|
1513
1541
|
};
|
|
1514
1542
|
}
|
|
1515
1543
|
throw new Error(`UI HTML file not found: ${htmlPath}`);
|
|
@@ -1539,7 +1567,11 @@ var init_index = __esm({
|
|
|
1539
1567
|
return;
|
|
1540
1568
|
}
|
|
1541
1569
|
const manifest = JSON.parse(import_fs.default.readFileSync(manifestPath, "utf-8"));
|
|
1542
|
-
for (const [uri,
|
|
1570
|
+
for (const [uri, entry] of Object.entries(manifest)) {
|
|
1571
|
+
const isString = typeof entry === "string";
|
|
1572
|
+
const htmlPath = isString ? entry : entry.htmlPath;
|
|
1573
|
+
const isGPTApp = !isString && entry.isGPTApp;
|
|
1574
|
+
const gptMeta = !isString ? entry.gptMeta : void 0;
|
|
1543
1575
|
if (this.resources.has(uri)) {
|
|
1544
1576
|
if (this.logging) {
|
|
1545
1577
|
this.logger.debug(`Skipping UI resource ${uri} - already registered`);
|
|
@@ -1553,14 +1585,22 @@ var init_index = __esm({
|
|
|
1553
1585
|
continue;
|
|
1554
1586
|
}
|
|
1555
1587
|
const html = import_fs.default.readFileSync(htmlPath, "utf-8");
|
|
1588
|
+
const mimeType = isGPTApp ? "text/html+skybridge" : "text/html;profile=mcp-app";
|
|
1589
|
+
const _meta = {};
|
|
1590
|
+
if (isGPTApp) {
|
|
1591
|
+
_meta["openai/outputTemplate"] = uri;
|
|
1592
|
+
if (gptMeta) Object.assign(_meta, gptMeta);
|
|
1593
|
+
if (_meta["openai/widgetPrefersBorder"] === void 0) _meta["openai/widgetPrefersBorder"] = true;
|
|
1594
|
+
}
|
|
1556
1595
|
this.resources.set(uri, {
|
|
1557
1596
|
uri,
|
|
1558
1597
|
name: uri.replace("ui://", "").replace(/\//g, "-"),
|
|
1559
1598
|
description: `Auto-generated UI resource from pre-built HTML`,
|
|
1560
|
-
mimeType
|
|
1599
|
+
mimeType,
|
|
1561
1600
|
inputSchema: void 0,
|
|
1562
1601
|
method: /* @__PURE__ */ __name(async () => ({
|
|
1563
|
-
text: html
|
|
1602
|
+
text: html,
|
|
1603
|
+
_meta: Object.keys(_meta).length > 0 ? _meta : void 0
|
|
1564
1604
|
}), "method"),
|
|
1565
1605
|
instance: null,
|
|
1566
1606
|
propertyKey: "getUI"
|
package/dist/index.mjs
CHANGED
|
@@ -851,20 +851,36 @@ async function createHTTPServer(serverInput, options) {
|
|
|
851
851
|
logger.error(`Server error: ${error.message}`);
|
|
852
852
|
reject(error);
|
|
853
853
|
});
|
|
854
|
-
|
|
854
|
+
let isShuttingDown = false;
|
|
855
|
+
const cleanup = /* @__PURE__ */ __name(async () => {
|
|
856
|
+
if (isShuttingDown) return;
|
|
857
|
+
isShuttingDown = true;
|
|
855
858
|
logger.info("\nShutting down server...");
|
|
856
|
-
Object.values(transports)
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
859
|
+
for (const transport of Object.values(transports)) {
|
|
860
|
+
try {
|
|
861
|
+
transport.close?.();
|
|
862
|
+
} catch (e) {
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
if (activeListener) {
|
|
866
|
+
await new Promise((resolveClose) => {
|
|
867
|
+
activeListener.close((err) => {
|
|
868
|
+
if (err) {
|
|
869
|
+
logger.warn(`Error closing server: ${err.message}`);
|
|
870
|
+
} else {
|
|
871
|
+
logger.info("Server closed");
|
|
872
|
+
}
|
|
873
|
+
resolveClose();
|
|
874
|
+
});
|
|
875
|
+
});
|
|
876
|
+
}
|
|
865
877
|
}, "cleanup");
|
|
866
|
-
|
|
867
|
-
|
|
878
|
+
const handleShutdown = /* @__PURE__ */ __name(() => {
|
|
879
|
+
cleanup().finally(() => {
|
|
880
|
+
});
|
|
881
|
+
}, "handleShutdown");
|
|
882
|
+
process.once("SIGINT", handleShutdown);
|
|
883
|
+
process.once("SIGTERM", handleShutdown);
|
|
868
884
|
} catch (error) {
|
|
869
885
|
reject(error);
|
|
870
886
|
}
|
|
@@ -1388,7 +1404,11 @@ var MCPServer = class {
|
|
|
1388
1404
|
}
|
|
1389
1405
|
}
|
|
1390
1406
|
}
|
|
1391
|
-
for (const [uri,
|
|
1407
|
+
for (const [uri, entry] of Object.entries(manifest)) {
|
|
1408
|
+
const isString = typeof entry === "string";
|
|
1409
|
+
const htmlPath = isString ? entry : entry.htmlPath;
|
|
1410
|
+
const isGPTApp = !isString && entry.isGPTApp;
|
|
1411
|
+
const gptMeta = !isString ? entry.gptMeta : void 0;
|
|
1392
1412
|
if (!fs.existsSync(htmlPath)) {
|
|
1393
1413
|
if (this.logging) {
|
|
1394
1414
|
this.logger.warn(`UI HTML file not found: ${htmlPath}`);
|
|
@@ -1396,17 +1416,25 @@ var MCPServer = class {
|
|
|
1396
1416
|
continue;
|
|
1397
1417
|
}
|
|
1398
1418
|
const wasRegistered = this.resources.has(uri);
|
|
1419
|
+
const mimeType = isGPTApp ? "text/html+skybridge" : "text/html;profile=mcp-app";
|
|
1420
|
+
const _meta = {};
|
|
1421
|
+
if (isGPTApp) {
|
|
1422
|
+
_meta["openai/outputTemplate"] = uri;
|
|
1423
|
+
if (gptMeta) Object.assign(_meta, gptMeta);
|
|
1424
|
+
if (_meta["openai/widgetPrefersBorder"] === void 0) _meta["openai/widgetPrefersBorder"] = true;
|
|
1425
|
+
}
|
|
1399
1426
|
this.resources.set(uri, {
|
|
1400
1427
|
uri,
|
|
1401
1428
|
name: uri.replace("ui://", "").replace(/\//g, "-"),
|
|
1402
1429
|
description: `Auto-generated UI resource from pre-built HTML`,
|
|
1403
|
-
mimeType
|
|
1430
|
+
mimeType,
|
|
1404
1431
|
inputSchema: void 0,
|
|
1405
1432
|
method: /* @__PURE__ */ __name(async () => {
|
|
1406
1433
|
if (fs.existsSync(htmlPath)) {
|
|
1407
1434
|
const html = fs.readFileSync(htmlPath, "utf-8");
|
|
1408
1435
|
return {
|
|
1409
|
-
text: html
|
|
1436
|
+
text: html,
|
|
1437
|
+
_meta: Object.keys(_meta).length > 0 ? _meta : void 0
|
|
1410
1438
|
};
|
|
1411
1439
|
}
|
|
1412
1440
|
throw new Error(`UI HTML file not found: ${htmlPath}`);
|
|
@@ -1436,7 +1464,11 @@ var MCPServer = class {
|
|
|
1436
1464
|
return;
|
|
1437
1465
|
}
|
|
1438
1466
|
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
1439
|
-
for (const [uri,
|
|
1467
|
+
for (const [uri, entry] of Object.entries(manifest)) {
|
|
1468
|
+
const isString = typeof entry === "string";
|
|
1469
|
+
const htmlPath = isString ? entry : entry.htmlPath;
|
|
1470
|
+
const isGPTApp = !isString && entry.isGPTApp;
|
|
1471
|
+
const gptMeta = !isString ? entry.gptMeta : void 0;
|
|
1440
1472
|
if (this.resources.has(uri)) {
|
|
1441
1473
|
if (this.logging) {
|
|
1442
1474
|
this.logger.debug(`Skipping UI resource ${uri} - already registered`);
|
|
@@ -1450,14 +1482,22 @@ var MCPServer = class {
|
|
|
1450
1482
|
continue;
|
|
1451
1483
|
}
|
|
1452
1484
|
const html = fs.readFileSync(htmlPath, "utf-8");
|
|
1485
|
+
const mimeType = isGPTApp ? "text/html+skybridge" : "text/html;profile=mcp-app";
|
|
1486
|
+
const _meta = {};
|
|
1487
|
+
if (isGPTApp) {
|
|
1488
|
+
_meta["openai/outputTemplate"] = uri;
|
|
1489
|
+
if (gptMeta) Object.assign(_meta, gptMeta);
|
|
1490
|
+
if (_meta["openai/widgetPrefersBorder"] === void 0) _meta["openai/widgetPrefersBorder"] = true;
|
|
1491
|
+
}
|
|
1453
1492
|
this.resources.set(uri, {
|
|
1454
1493
|
uri,
|
|
1455
1494
|
name: uri.replace("ui://", "").replace(/\//g, "-"),
|
|
1456
1495
|
description: `Auto-generated UI resource from pre-built HTML`,
|
|
1457
|
-
mimeType
|
|
1496
|
+
mimeType,
|
|
1458
1497
|
inputSchema: void 0,
|
|
1459
1498
|
method: /* @__PURE__ */ __name(async () => ({
|
|
1460
|
-
text: html
|
|
1499
|
+
text: html,
|
|
1500
|
+
_meta: Object.keys(_meta).length > 0 ? _meta : void 0
|
|
1461
1501
|
}), "method"),
|
|
1462
1502
|
instance: null,
|
|
1463
1503
|
propertyKey: "getUI"
|