@leanmcp/core 0.3.1 → 0.3.3
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.d.mts +34 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +80 -22
- package/dist/index.mjs +80 -22
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -434,9 +434,18 @@ declare class MCPServer {
|
|
|
434
434
|
method: string;
|
|
435
435
|
params?: {
|
|
436
436
|
[x: string]: unknown;
|
|
437
|
+
task?: {
|
|
438
|
+
[x: string]: unknown;
|
|
439
|
+
ttl?: number | null | undefined;
|
|
440
|
+
pollInterval?: number | undefined;
|
|
441
|
+
} | undefined;
|
|
437
442
|
_meta?: {
|
|
438
443
|
[x: string]: unknown;
|
|
439
444
|
progressToken?: string | number | undefined;
|
|
445
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
446
|
+
[x: string]: unknown;
|
|
447
|
+
taskId: string;
|
|
448
|
+
} | undefined;
|
|
440
449
|
} | undefined;
|
|
441
450
|
} | undefined;
|
|
442
451
|
}, {
|
|
@@ -445,12 +454,20 @@ declare class MCPServer {
|
|
|
445
454
|
[x: string]: unknown;
|
|
446
455
|
_meta?: {
|
|
447
456
|
[x: string]: unknown;
|
|
457
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
458
|
+
[x: string]: unknown;
|
|
459
|
+
taskId: string;
|
|
460
|
+
} | undefined;
|
|
448
461
|
} | undefined;
|
|
449
462
|
} | undefined;
|
|
450
463
|
}, {
|
|
451
464
|
[x: string]: unknown;
|
|
452
465
|
_meta?: {
|
|
453
466
|
[x: string]: unknown;
|
|
467
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
468
|
+
[x: string]: unknown;
|
|
469
|
+
taskId: string;
|
|
470
|
+
} | undefined;
|
|
454
471
|
} | undefined;
|
|
455
472
|
}>;
|
|
456
473
|
}
|
|
@@ -469,9 +486,18 @@ declare class MCPServerRuntime {
|
|
|
469
486
|
method: string;
|
|
470
487
|
params?: {
|
|
471
488
|
[x: string]: unknown;
|
|
489
|
+
task?: {
|
|
490
|
+
[x: string]: unknown;
|
|
491
|
+
ttl?: number | null | undefined;
|
|
492
|
+
pollInterval?: number | undefined;
|
|
493
|
+
} | undefined;
|
|
472
494
|
_meta?: {
|
|
473
495
|
[x: string]: unknown;
|
|
474
496
|
progressToken?: string | number | undefined;
|
|
497
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
498
|
+
[x: string]: unknown;
|
|
499
|
+
taskId: string;
|
|
500
|
+
} | undefined;
|
|
475
501
|
} | undefined;
|
|
476
502
|
} | undefined;
|
|
477
503
|
}, {
|
|
@@ -480,12 +506,20 @@ declare class MCPServerRuntime {
|
|
|
480
506
|
[x: string]: unknown;
|
|
481
507
|
_meta?: {
|
|
482
508
|
[x: string]: unknown;
|
|
509
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
510
|
+
[x: string]: unknown;
|
|
511
|
+
taskId: string;
|
|
512
|
+
} | undefined;
|
|
483
513
|
} | undefined;
|
|
484
514
|
} | undefined;
|
|
485
515
|
}, {
|
|
486
516
|
[x: string]: unknown;
|
|
487
517
|
_meta?: {
|
|
488
518
|
[x: string]: unknown;
|
|
519
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
520
|
+
[x: string]: unknown;
|
|
521
|
+
taskId: string;
|
|
522
|
+
} | undefined;
|
|
489
523
|
} | undefined;
|
|
490
524
|
}>;
|
|
491
525
|
getTools(): RegisteredTool[];
|
package/dist/index.d.ts
CHANGED
|
@@ -434,9 +434,18 @@ declare class MCPServer {
|
|
|
434
434
|
method: string;
|
|
435
435
|
params?: {
|
|
436
436
|
[x: string]: unknown;
|
|
437
|
+
task?: {
|
|
438
|
+
[x: string]: unknown;
|
|
439
|
+
ttl?: number | null | undefined;
|
|
440
|
+
pollInterval?: number | undefined;
|
|
441
|
+
} | undefined;
|
|
437
442
|
_meta?: {
|
|
438
443
|
[x: string]: unknown;
|
|
439
444
|
progressToken?: string | number | undefined;
|
|
445
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
446
|
+
[x: string]: unknown;
|
|
447
|
+
taskId: string;
|
|
448
|
+
} | undefined;
|
|
440
449
|
} | undefined;
|
|
441
450
|
} | undefined;
|
|
442
451
|
}, {
|
|
@@ -445,12 +454,20 @@ declare class MCPServer {
|
|
|
445
454
|
[x: string]: unknown;
|
|
446
455
|
_meta?: {
|
|
447
456
|
[x: string]: unknown;
|
|
457
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
458
|
+
[x: string]: unknown;
|
|
459
|
+
taskId: string;
|
|
460
|
+
} | undefined;
|
|
448
461
|
} | undefined;
|
|
449
462
|
} | undefined;
|
|
450
463
|
}, {
|
|
451
464
|
[x: string]: unknown;
|
|
452
465
|
_meta?: {
|
|
453
466
|
[x: string]: unknown;
|
|
467
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
468
|
+
[x: string]: unknown;
|
|
469
|
+
taskId: string;
|
|
470
|
+
} | undefined;
|
|
454
471
|
} | undefined;
|
|
455
472
|
}>;
|
|
456
473
|
}
|
|
@@ -469,9 +486,18 @@ declare class MCPServerRuntime {
|
|
|
469
486
|
method: string;
|
|
470
487
|
params?: {
|
|
471
488
|
[x: string]: unknown;
|
|
489
|
+
task?: {
|
|
490
|
+
[x: string]: unknown;
|
|
491
|
+
ttl?: number | null | undefined;
|
|
492
|
+
pollInterval?: number | undefined;
|
|
493
|
+
} | undefined;
|
|
472
494
|
_meta?: {
|
|
473
495
|
[x: string]: unknown;
|
|
474
496
|
progressToken?: string | number | undefined;
|
|
497
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
498
|
+
[x: string]: unknown;
|
|
499
|
+
taskId: string;
|
|
500
|
+
} | undefined;
|
|
475
501
|
} | undefined;
|
|
476
502
|
} | undefined;
|
|
477
503
|
}, {
|
|
@@ -480,12 +506,20 @@ declare class MCPServerRuntime {
|
|
|
480
506
|
[x: string]: unknown;
|
|
481
507
|
_meta?: {
|
|
482
508
|
[x: string]: unknown;
|
|
509
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
510
|
+
[x: string]: unknown;
|
|
511
|
+
taskId: string;
|
|
512
|
+
} | undefined;
|
|
483
513
|
} | undefined;
|
|
484
514
|
} | undefined;
|
|
485
515
|
}, {
|
|
486
516
|
[x: string]: unknown;
|
|
487
517
|
_meta?: {
|
|
488
518
|
[x: string]: unknown;
|
|
519
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
520
|
+
[x: string]: unknown;
|
|
521
|
+
taskId: string;
|
|
522
|
+
} | undefined;
|
|
489
523
|
} | undefined;
|
|
490
524
|
}>;
|
|
491
525
|
getTools(): RegisteredTool[];
|
package/dist/index.js
CHANGED
|
@@ -464,14 +464,61 @@ async function createHTTPServer(serverInput, options) {
|
|
|
464
464
|
httpOptions.cors ? import("cors").catch(() => null) : Promise.resolve(null)
|
|
465
465
|
]);
|
|
466
466
|
const app = express.default();
|
|
467
|
-
const
|
|
468
|
-
validatePort(
|
|
467
|
+
const basePort = httpOptions.port || 3001;
|
|
468
|
+
validatePort(basePort);
|
|
469
469
|
const transports = {};
|
|
470
470
|
let mcpServer = null;
|
|
471
471
|
const logger = httpOptions.logger || new Logger({
|
|
472
472
|
level: httpOptions.logging ? LogLevel.INFO : LogLevel.NONE,
|
|
473
473
|
prefix: "HTTP"
|
|
474
474
|
});
|
|
475
|
+
const logPrimary = /* @__PURE__ */ __name((message) => {
|
|
476
|
+
if (httpOptions.logging) {
|
|
477
|
+
logger.info?.(message);
|
|
478
|
+
} else {
|
|
479
|
+
console.log(message);
|
|
480
|
+
}
|
|
481
|
+
}, "logPrimary");
|
|
482
|
+
const warnPrimary = /* @__PURE__ */ __name((message) => {
|
|
483
|
+
if (httpOptions.logging) {
|
|
484
|
+
logger.warn?.(message);
|
|
485
|
+
} else {
|
|
486
|
+
console.warn(message);
|
|
487
|
+
}
|
|
488
|
+
}, "warnPrimary");
|
|
489
|
+
const startServerWithPortRetry = /* @__PURE__ */ __name(async () => {
|
|
490
|
+
const maxAttempts = 20;
|
|
491
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
492
|
+
const portToTry = basePort + attempt;
|
|
493
|
+
const listener = await new Promise((resolve, reject) => {
|
|
494
|
+
const server = app.listen(portToTry);
|
|
495
|
+
const onListening = /* @__PURE__ */ __name(() => {
|
|
496
|
+
server.off("error", onError);
|
|
497
|
+
resolve(server);
|
|
498
|
+
}, "onListening");
|
|
499
|
+
const onError = /* @__PURE__ */ __name((error) => {
|
|
500
|
+
server.off("listening", onListening);
|
|
501
|
+
server.close();
|
|
502
|
+
reject(error);
|
|
503
|
+
}, "onError");
|
|
504
|
+
server.once("listening", onListening);
|
|
505
|
+
server.once("error", onError);
|
|
506
|
+
}).catch((error) => {
|
|
507
|
+
if (error?.code === "EADDRINUSE" && attempt < maxAttempts - 1) {
|
|
508
|
+
warnPrimary(`Port ${portToTry} in use, trying ${portToTry + 1}...`);
|
|
509
|
+
return null;
|
|
510
|
+
}
|
|
511
|
+
throw error;
|
|
512
|
+
});
|
|
513
|
+
if (listener) {
|
|
514
|
+
return {
|
|
515
|
+
listener,
|
|
516
|
+
port: portToTry
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
throw new Error(`No available port found in range ${basePort}-${basePort + maxAttempts - 1}`);
|
|
521
|
+
}, "startServerWithPortRetry");
|
|
475
522
|
if (cors && httpOptions.cors) {
|
|
476
523
|
const corsOptions = typeof httpOptions.cors === "object" ? {
|
|
477
524
|
origin: httpOptions.cors.origin || false,
|
|
@@ -498,7 +545,7 @@ async function createHTTPServer(serverInput, options) {
|
|
|
498
545
|
}
|
|
499
546
|
}
|
|
500
547
|
app.use(express.json());
|
|
501
|
-
|
|
548
|
+
console.log("Starting LeanMCP HTTP Server...");
|
|
502
549
|
app.get("/health", (req, res) => {
|
|
503
550
|
res.json({
|
|
504
551
|
status: "ok",
|
|
@@ -573,16 +620,22 @@ async function createHTTPServer(serverInput, options) {
|
|
|
573
620
|
app.post("/mcp", handleMCPRequest);
|
|
574
621
|
app.delete("/mcp", handleMCPRequest);
|
|
575
622
|
return new Promise(async (resolve, reject) => {
|
|
623
|
+
let activeListener;
|
|
576
624
|
try {
|
|
577
625
|
mcpServer = await serverFactory();
|
|
578
626
|
if (mcpServer && typeof mcpServer.waitForInit === "function") {
|
|
579
627
|
await mcpServer.waitForInit();
|
|
580
628
|
}
|
|
581
|
-
const listener =
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
629
|
+
const { listener, port } = await startServerWithPortRetry();
|
|
630
|
+
activeListener = listener;
|
|
631
|
+
process.env.PORT = String(port);
|
|
632
|
+
listener.port = port;
|
|
633
|
+
console.log(`Server running on http://localhost:${port}`);
|
|
634
|
+
console.log(`MCP endpoint: http://localhost:${port}/mcp`);
|
|
635
|
+
console.log(`Health check: http://localhost:${port}/health`);
|
|
636
|
+
resolve({
|
|
637
|
+
listener,
|
|
638
|
+
port
|
|
586
639
|
});
|
|
587
640
|
listener.on("error", (error) => {
|
|
588
641
|
logger.error(`Server error: ${error.message}`);
|
|
@@ -591,7 +644,7 @@ async function createHTTPServer(serverInput, options) {
|
|
|
591
644
|
const cleanup = /* @__PURE__ */ __name(() => {
|
|
592
645
|
logger.info("\nShutting down server...");
|
|
593
646
|
Object.values(transports).forEach((t) => t.close?.());
|
|
594
|
-
|
|
647
|
+
activeListener?.close(() => {
|
|
595
648
|
logger.info("Server closed");
|
|
596
649
|
process.exit(0);
|
|
597
650
|
});
|
|
@@ -769,24 +822,29 @@ var init_index = __esm({
|
|
|
769
822
|
const stack = err.stack;
|
|
770
823
|
for (let i = 0; i < stack.length; i++) {
|
|
771
824
|
let fileName = stack[i].getFileName();
|
|
772
|
-
if (
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
}
|
|
825
|
+
if (!fileName) continue;
|
|
826
|
+
if (fileName.startsWith("file://")) {
|
|
827
|
+
try {
|
|
828
|
+
const url = new URL(fileName);
|
|
829
|
+
fileName = decodeURIComponent(url.pathname);
|
|
830
|
+
if (process.platform === "win32" && fileName.startsWith("/")) {
|
|
831
|
+
fileName = fileName.substring(1);
|
|
832
|
+
}
|
|
833
|
+
} catch (e) {
|
|
834
|
+
fileName = fileName.replace("file://", "");
|
|
835
|
+
if (process.platform === "win32" && fileName.startsWith("/")) {
|
|
836
|
+
fileName = fileName.substring(1);
|
|
785
837
|
}
|
|
786
838
|
}
|
|
839
|
+
}
|
|
840
|
+
const normalizedPath = fileName.replace(/\\/g, "/");
|
|
841
|
+
const isLeanMCPCore = normalizedPath.includes("@leanmcp/core") || normalizedPath.includes("leanmcp-sdk/packages/core");
|
|
842
|
+
const isValidExtension = fileName.endsWith(".ts") || fileName.endsWith(".js") || fileName.endsWith(".mjs");
|
|
843
|
+
if (!isLeanMCPCore && isValidExtension) {
|
|
787
844
|
return fileName;
|
|
788
845
|
}
|
|
789
846
|
}
|
|
847
|
+
this.logger.debug("No suitable caller file found in stack trace");
|
|
790
848
|
return null;
|
|
791
849
|
} finally {
|
|
792
850
|
Error.prepareStackTrace = originalPrepareStackTrace;
|
package/dist/index.mjs
CHANGED
|
@@ -425,14 +425,61 @@ async function createHTTPServer(serverInput, options) {
|
|
|
425
425
|
httpOptions.cors ? import("cors").catch(() => null) : Promise.resolve(null)
|
|
426
426
|
]);
|
|
427
427
|
const app = express.default();
|
|
428
|
-
const
|
|
429
|
-
validatePort(
|
|
428
|
+
const basePort = httpOptions.port || 3001;
|
|
429
|
+
validatePort(basePort);
|
|
430
430
|
const transports = {};
|
|
431
431
|
let mcpServer = null;
|
|
432
432
|
const logger = httpOptions.logger || new Logger({
|
|
433
433
|
level: httpOptions.logging ? LogLevel.INFO : LogLevel.NONE,
|
|
434
434
|
prefix: "HTTP"
|
|
435
435
|
});
|
|
436
|
+
const logPrimary = /* @__PURE__ */ __name((message) => {
|
|
437
|
+
if (httpOptions.logging) {
|
|
438
|
+
logger.info?.(message);
|
|
439
|
+
} else {
|
|
440
|
+
console.log(message);
|
|
441
|
+
}
|
|
442
|
+
}, "logPrimary");
|
|
443
|
+
const warnPrimary = /* @__PURE__ */ __name((message) => {
|
|
444
|
+
if (httpOptions.logging) {
|
|
445
|
+
logger.warn?.(message);
|
|
446
|
+
} else {
|
|
447
|
+
console.warn(message);
|
|
448
|
+
}
|
|
449
|
+
}, "warnPrimary");
|
|
450
|
+
const startServerWithPortRetry = /* @__PURE__ */ __name(async () => {
|
|
451
|
+
const maxAttempts = 20;
|
|
452
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
453
|
+
const portToTry = basePort + attempt;
|
|
454
|
+
const listener = await new Promise((resolve, reject) => {
|
|
455
|
+
const server = app.listen(portToTry);
|
|
456
|
+
const onListening = /* @__PURE__ */ __name(() => {
|
|
457
|
+
server.off("error", onError);
|
|
458
|
+
resolve(server);
|
|
459
|
+
}, "onListening");
|
|
460
|
+
const onError = /* @__PURE__ */ __name((error) => {
|
|
461
|
+
server.off("listening", onListening);
|
|
462
|
+
server.close();
|
|
463
|
+
reject(error);
|
|
464
|
+
}, "onError");
|
|
465
|
+
server.once("listening", onListening);
|
|
466
|
+
server.once("error", onError);
|
|
467
|
+
}).catch((error) => {
|
|
468
|
+
if (error?.code === "EADDRINUSE" && attempt < maxAttempts - 1) {
|
|
469
|
+
warnPrimary(`Port ${portToTry} in use, trying ${portToTry + 1}...`);
|
|
470
|
+
return null;
|
|
471
|
+
}
|
|
472
|
+
throw error;
|
|
473
|
+
});
|
|
474
|
+
if (listener) {
|
|
475
|
+
return {
|
|
476
|
+
listener,
|
|
477
|
+
port: portToTry
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
throw new Error(`No available port found in range ${basePort}-${basePort + maxAttempts - 1}`);
|
|
482
|
+
}, "startServerWithPortRetry");
|
|
436
483
|
if (cors && httpOptions.cors) {
|
|
437
484
|
const corsOptions = typeof httpOptions.cors === "object" ? {
|
|
438
485
|
origin: httpOptions.cors.origin || false,
|
|
@@ -459,7 +506,7 @@ async function createHTTPServer(serverInput, options) {
|
|
|
459
506
|
}
|
|
460
507
|
}
|
|
461
508
|
app.use(express.json());
|
|
462
|
-
|
|
509
|
+
console.log("Starting LeanMCP HTTP Server...");
|
|
463
510
|
app.get("/health", (req, res) => {
|
|
464
511
|
res.json({
|
|
465
512
|
status: "ok",
|
|
@@ -534,16 +581,22 @@ async function createHTTPServer(serverInput, options) {
|
|
|
534
581
|
app.post("/mcp", handleMCPRequest);
|
|
535
582
|
app.delete("/mcp", handleMCPRequest);
|
|
536
583
|
return new Promise(async (resolve, reject) => {
|
|
584
|
+
let activeListener;
|
|
537
585
|
try {
|
|
538
586
|
mcpServer = await serverFactory();
|
|
539
587
|
if (mcpServer && typeof mcpServer.waitForInit === "function") {
|
|
540
588
|
await mcpServer.waitForInit();
|
|
541
589
|
}
|
|
542
|
-
const listener =
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
590
|
+
const { listener, port } = await startServerWithPortRetry();
|
|
591
|
+
activeListener = listener;
|
|
592
|
+
process.env.PORT = String(port);
|
|
593
|
+
listener.port = port;
|
|
594
|
+
console.log(`Server running on http://localhost:${port}`);
|
|
595
|
+
console.log(`MCP endpoint: http://localhost:${port}/mcp`);
|
|
596
|
+
console.log(`Health check: http://localhost:${port}/health`);
|
|
597
|
+
resolve({
|
|
598
|
+
listener,
|
|
599
|
+
port
|
|
547
600
|
});
|
|
548
601
|
listener.on("error", (error) => {
|
|
549
602
|
logger.error(`Server error: ${error.message}`);
|
|
@@ -552,7 +605,7 @@ async function createHTTPServer(serverInput, options) {
|
|
|
552
605
|
const cleanup = /* @__PURE__ */ __name(() => {
|
|
553
606
|
logger.info("\nShutting down server...");
|
|
554
607
|
Object.values(transports).forEach((t) => t.close?.());
|
|
555
|
-
|
|
608
|
+
activeListener?.close(() => {
|
|
556
609
|
logger.info("Server closed");
|
|
557
610
|
process.exit(0);
|
|
558
611
|
});
|
|
@@ -666,24 +719,29 @@ var MCPServer = class {
|
|
|
666
719
|
const stack = err.stack;
|
|
667
720
|
for (let i = 0; i < stack.length; i++) {
|
|
668
721
|
let fileName = stack[i].getFileName();
|
|
669
|
-
if (
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
}
|
|
722
|
+
if (!fileName) continue;
|
|
723
|
+
if (fileName.startsWith("file://")) {
|
|
724
|
+
try {
|
|
725
|
+
const url = new URL(fileName);
|
|
726
|
+
fileName = decodeURIComponent(url.pathname);
|
|
727
|
+
if (process.platform === "win32" && fileName.startsWith("/")) {
|
|
728
|
+
fileName = fileName.substring(1);
|
|
729
|
+
}
|
|
730
|
+
} catch (e) {
|
|
731
|
+
fileName = fileName.replace("file://", "");
|
|
732
|
+
if (process.platform === "win32" && fileName.startsWith("/")) {
|
|
733
|
+
fileName = fileName.substring(1);
|
|
682
734
|
}
|
|
683
735
|
}
|
|
736
|
+
}
|
|
737
|
+
const normalizedPath = fileName.replace(/\\/g, "/");
|
|
738
|
+
const isLeanMCPCore = normalizedPath.includes("@leanmcp/core") || normalizedPath.includes("leanmcp-sdk/packages/core");
|
|
739
|
+
const isValidExtension = fileName.endsWith(".ts") || fileName.endsWith(".js") || fileName.endsWith(".mjs");
|
|
740
|
+
if (!isLeanMCPCore && isValidExtension) {
|
|
684
741
|
return fileName;
|
|
685
742
|
}
|
|
686
743
|
}
|
|
744
|
+
this.logger.debug("No suitable caller file found in stack trace");
|
|
687
745
|
return null;
|
|
688
746
|
} finally {
|
|
689
747
|
Error.prepareStackTrace = originalPrepareStackTrace;
|