@leanmcp/cli 0.2.9 → 0.2.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 +116 -129
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -400,7 +400,7 @@ program.name("leanmcp").description("LeanMCP CLI \u2014 create production-ready
|
|
|
400
400
|
Examples:
|
|
401
401
|
$ leanmcp create my-app --allow-all # Scaffold without interactive prompts
|
|
402
402
|
`);
|
|
403
|
-
program.command("create <projectName>").description("Create a new LeanMCP project with Streamable HTTP transport").option("--allow-all", "Skip interactive confirmations and assume Yes").action(async (projectName, options) => {
|
|
403
|
+
program.command("create <projectName>").description("Create a new LeanMCP project with Streamable HTTP transport").option("--allow-all", "Skip interactive confirmations and assume Yes").option("--no-dashboard", "Disable dashboard UI at / and /mcp GET endpoints").action(async (projectName, options) => {
|
|
404
404
|
const spinner = ora3(`Creating project ${projectName}...`).start();
|
|
405
405
|
const targetDir = path5.join(process.cwd(), projectName);
|
|
406
406
|
if (fs5.existsSync(targetDir)) {
|
|
@@ -465,152 +465,139 @@ program.command("create <projectName>").description("Create a new LeanMCP projec
|
|
|
465
465
|
await fs5.writeJSON(path5.join(targetDir, "tsconfig.json"), tsconfig, {
|
|
466
466
|
spaces: 2
|
|
467
467
|
});
|
|
468
|
+
const dashboardLine = options.dashboard === false ? `
|
|
469
|
+
dashboard: false, // Dashboard disabled via --no-dashboard` : "";
|
|
468
470
|
const mainTs = `import dotenv from "dotenv";
|
|
469
|
-
import { createHTTPServer
|
|
471
|
+
import { createHTTPServer } from "@leanmcp/core";
|
|
470
472
|
|
|
471
473
|
// Load environment variables
|
|
472
474
|
dotenv.config();
|
|
473
475
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
*/
|
|
480
|
-
const serverFactory = async () => {
|
|
481
|
-
const server = new MCPServer({
|
|
482
|
-
name: "${projectName}",
|
|
483
|
-
version: "1.0.0",
|
|
484
|
-
logging: true
|
|
485
|
-
});
|
|
486
|
-
|
|
487
|
-
// Services are automatically discovered and registered from ./mcp
|
|
488
|
-
return server.getServer();
|
|
489
|
-
};
|
|
490
|
-
|
|
491
|
-
// Start the HTTP server
|
|
492
|
-
await createHTTPServer(serverFactory, {
|
|
493
|
-
port: PORT,
|
|
476
|
+
// Services are automatically discovered from ./mcp directory
|
|
477
|
+
await createHTTPServer({
|
|
478
|
+
name: "${projectName}",
|
|
479
|
+
version: "1.0.0",
|
|
480
|
+
port: 3001,
|
|
494
481
|
cors: true,
|
|
495
|
-
logging: true
|
|
482
|
+
logging: true${dashboardLine}
|
|
496
483
|
});
|
|
497
484
|
|
|
498
|
-
console.log(
|
|
485
|
+
console.log("\\n${projectName} MCP Server");
|
|
499
486
|
`;
|
|
500
487
|
await fs5.writeFile(path5.join(targetDir, "main.ts"), mainTs);
|
|
501
488
|
const exampleServiceTs = `import { Tool, Resource, Prompt, SchemaConstraint, Optional } from "@leanmcp/core";
|
|
502
489
|
|
|
503
|
-
/**
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
// Input schema with validation decorators
|
|
510
|
-
class CalculateInput {
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
class EchoInput {
|
|
527
|
-
@SchemaConstraint({
|
|
528
|
-
description: "Message to echo back",
|
|
529
|
-
minLength: 1
|
|
530
|
-
})
|
|
531
|
-
message!: string;
|
|
532
|
-
}
|
|
490
|
+
/**
|
|
491
|
+
* Example service demonstrating LeanMCP SDK decorators
|
|
492
|
+
*
|
|
493
|
+
* This is a simple example to get you started. Add your own tools, resources, and prompts here!
|
|
494
|
+
*/
|
|
495
|
+
|
|
496
|
+
// Input schema with validation decorators
|
|
497
|
+
class CalculateInput {
|
|
498
|
+
@SchemaConstraint({ description: "First number" })
|
|
499
|
+
a!: number;
|
|
500
|
+
|
|
501
|
+
@SchemaConstraint({ description: "Second number" })
|
|
502
|
+
b!: number;
|
|
503
|
+
|
|
504
|
+
@Optional()
|
|
505
|
+
@SchemaConstraint({
|
|
506
|
+
description: "Operation to perform",
|
|
507
|
+
enum: ["add", "subtract", "multiply", "divide"],
|
|
508
|
+
default: "add"
|
|
509
|
+
})
|
|
510
|
+
operation?: string;
|
|
511
|
+
}
|
|
533
512
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
// Ensure numerical operations by explicitly converting to numbers
|
|
541
|
-
const a = Number(input.a);
|
|
542
|
-
const b = Number(input.b);
|
|
543
|
-
let result: number;
|
|
544
|
-
|
|
545
|
-
switch (input.operation || "add") {
|
|
546
|
-
case "add":
|
|
547
|
-
result = a + b;
|
|
548
|
-
break;
|
|
549
|
-
case "subtract":
|
|
550
|
-
result = a - b;
|
|
551
|
-
break;
|
|
552
|
-
case "multiply":
|
|
553
|
-
result = a * b;
|
|
554
|
-
break;
|
|
555
|
-
case "divide":
|
|
556
|
-
if (b === 0) throw new Error("Cannot divide by zero");
|
|
557
|
-
result = a / b;
|
|
558
|
-
break;
|
|
559
|
-
default:
|
|
560
|
-
throw new Error("Invalid operation");
|
|
513
|
+
class EchoInput {
|
|
514
|
+
@SchemaConstraint({
|
|
515
|
+
description: "Message to echo back",
|
|
516
|
+
minLength: 1
|
|
517
|
+
})
|
|
518
|
+
message!: string;
|
|
561
519
|
}
|
|
562
520
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
521
|
+
export class ExampleService {
|
|
522
|
+
@Tool({
|
|
523
|
+
description: "Perform arithmetic operations with automatic schema validation",
|
|
524
|
+
inputClass: CalculateInput
|
|
525
|
+
})
|
|
526
|
+
async calculate(input: CalculateInput) {
|
|
527
|
+
// Ensure numerical operations by explicitly converting to numbers
|
|
528
|
+
const a = Number(input.a);
|
|
529
|
+
const b = Number(input.b);
|
|
530
|
+
let result: number;
|
|
531
|
+
|
|
532
|
+
switch (input.operation || "add") {
|
|
533
|
+
case "add":
|
|
534
|
+
result = a + b;
|
|
535
|
+
break;
|
|
536
|
+
case "subtract":
|
|
537
|
+
result = a - b;
|
|
538
|
+
break;
|
|
539
|
+
case "multiply":
|
|
540
|
+
result = a * b;
|
|
541
|
+
break;
|
|
542
|
+
case "divide":
|
|
543
|
+
if (b === 0) throw new Error("Cannot divide by zero");
|
|
544
|
+
result = a / b;
|
|
545
|
+
break;
|
|
546
|
+
default:
|
|
547
|
+
throw new Error("Invalid operation");
|
|
548
|
+
}
|
|
574
549
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
}, null, 2)
|
|
587
|
-
}]
|
|
588
|
-
};
|
|
589
|
-
}
|
|
550
|
+
return {
|
|
551
|
+
content: [{
|
|
552
|
+
type: "text" as const,
|
|
553
|
+
text: JSON.stringify({
|
|
554
|
+
operation: input.operation || "add",
|
|
555
|
+
operands: { a: input.a, b: input.b },
|
|
556
|
+
result
|
|
557
|
+
}, null, 2)
|
|
558
|
+
}]
|
|
559
|
+
};
|
|
560
|
+
}
|
|
590
561
|
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
562
|
+
@Tool({
|
|
563
|
+
description: "Echo a message back",
|
|
564
|
+
inputClass: EchoInput
|
|
565
|
+
})
|
|
566
|
+
async echo(input: EchoInput) {
|
|
567
|
+
return {
|
|
568
|
+
content: [{
|
|
569
|
+
type: "text" as const,
|
|
570
|
+
text: JSON.stringify({
|
|
571
|
+
echoed: input.message,
|
|
572
|
+
timestamp: new Date().toISOString()
|
|
573
|
+
}, null, 2)
|
|
574
|
+
}]
|
|
575
|
+
};
|
|
576
|
+
}
|
|
605
577
|
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
578
|
+
@Resource({ description: "Get server information" })
|
|
579
|
+
async serverInfo() {
|
|
580
|
+
return {
|
|
581
|
+
contents: [{
|
|
582
|
+
uri: "server://info",
|
|
583
|
+
mimeType: "application/json",
|
|
584
|
+
text: JSON.stringify({
|
|
585
|
+
name: "${projectName}",
|
|
586
|
+
version: "1.0.0",
|
|
587
|
+
uptime: process.uptime()
|
|
588
|
+
}, null, 2)
|
|
589
|
+
}]
|
|
590
|
+
};
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
@Prompt({ description: "Generate a greeting prompt" })
|
|
594
|
+
async greeting(args: { name?: string }) {
|
|
595
|
+
return {
|
|
596
|
+
messages: [{
|
|
597
|
+
role: "user" as const,
|
|
598
|
+
content: {
|
|
599
|
+
type: "text" as const,
|
|
600
|
+
text: \`Hello \${args.name || 'there'}! Welcome to ${projectName}.\`
|
|
614
601
|
}
|
|
615
602
|
}]
|
|
616
603
|
};
|