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