@leanmcp/cli 0.2.8 → 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/bin/leanmcp.js CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
-
3
- // Always prefer ESM build
4
- import('../dist/index.js');
2
+
3
+ // Always prefer ESM build
4
+ import('../dist/index.js');
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, MCPServer } from "@leanmcp/core";
471
+ import { createHTTPServer } from "@leanmcp/core";
470
472
 
471
473
  // Load environment variables
472
474
  dotenv.config();
473
475
 
474
- const PORT = Number(process.env.PORT) || 3001;
475
-
476
- /**
477
- * Create and configure the MCP server
478
- * Services are automatically discovered from ./mcp directory
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 // Log HTTP requests
482
+ logging: true${dashboardLine}
496
483
  });
497
484
 
498
- console.log(\`\\n${projectName} MCP Server\`);
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
- * Example service demonstrating LeanMCP SDK decorators
505
- *
506
- * This is a simple example to get you started. Add your own tools, resources, and prompts here!
507
- */
508
-
509
- // Input schema with validation decorators
510
- class CalculateInput {
511
- @SchemaConstraint({ description: "First number" })
512
- a!: number;
513
-
514
- @SchemaConstraint({ description: "Second number" })
515
- b!: number;
516
-
517
- @Optional()
518
- @SchemaConstraint({
519
- description: "Operation to perform",
520
- enum: ["add", "subtract", "multiply", "divide"],
521
- default: "add"
522
- })
523
- operation?: string;
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
- export class ExampleService {
535
- @Tool({
536
- description: "Perform arithmetic operations with automatic schema validation",
537
- inputClass: CalculateInput
538
- })
539
- async calculate(input: CalculateInput) {
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
- return {
564
- content: [{
565
- type: "text" as const,
566
- text: JSON.stringify({
567
- operation: input.operation || "add",
568
- operands: { a: input.a, b: input.b },
569
- result
570
- }, null, 2)
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
- @Tool({
576
- description: "Echo a message back",
577
- inputClass: EchoInput
578
- })
579
- async echo(input: EchoInput) {
580
- return {
581
- content: [{
582
- type: "text" as const,
583
- text: JSON.stringify({
584
- echoed: input.message,
585
- timestamp: new Date().toISOString()
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
- @Resource({ description: "Get server information" })
592
- async serverInfo() {
593
- return {
594
- contents: [{
595
- uri: "server://info",
596
- mimeType: "application/json",
597
- text: JSON.stringify({
598
- name: "${projectName}",
599
- version: "1.0.0",
600
- uptime: process.uptime()
601
- }, null, 2)
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
- @Prompt({ description: "Generate a greeting prompt" })
607
- async greeting(args: { name?: string }) {
608
- return {
609
- messages: [{
610
- role: "user" as const,
611
- content: {
612
- type: "text" as const,
613
- text: \`Hello \${args.name || 'there'}! Welcome to ${projectName}.\`
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
  };
@@ -618,11 +605,147 @@ export class ExampleService {
618
605
  }
619
606
  `;
620
607
  await fs5.writeFile(path5.join(targetDir, "mcp", "example", "index.ts"), exampleServiceTs);
621
- const gitignore = `node_modules
622
- dist
623
- .env
624
- .env.local
608
+ const gitignore = `# Logs
609
+ logs
625
610
  *.log
611
+ npm-debug.log*
612
+ yarn-debug.log*
613
+ yarn-error.log*
614
+ lerna-debug.log*
615
+
616
+ # Diagnostic reports (https://nodejs.org/api/report.html)
617
+ report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
618
+
619
+ # Runtime data
620
+ pids
621
+ *.pid
622
+ *.seed
623
+ *.pid.lock
624
+
625
+ # Directory for instrumented libs generated by jscoverage/JSCover
626
+ lib-cov
627
+
628
+ # Coverage directory used by tools like istanbul
629
+ coverage
630
+ *.lcov
631
+
632
+ # nyc test coverage
633
+ .nyc_output
634
+
635
+ # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
636
+ .grunt
637
+
638
+ # Bower dependency directory (https://bower.io/)
639
+ bower_components
640
+
641
+ # node-waf configuration
642
+ .lock-wscript
643
+
644
+ # Compiled binary addons (https://nodejs.org/api/addons.html)
645
+ build/Release
646
+
647
+ # Dependency directories
648
+ node_modules/
649
+ jspm_packages/
650
+
651
+ # Snowpack dependency directory (https://snowpack.dev/)
652
+ web_modules/
653
+
654
+ # TypeScript cache
655
+ *.tsbuildinfo
656
+
657
+ # Optional npm cache directory
658
+ .npm
659
+
660
+ # Optional eslint cache
661
+ .eslintcache
662
+
663
+ # Optional stylelint cache
664
+ .stylelintcache
665
+
666
+ # Optional REPL history
667
+ .node_repl_history
668
+
669
+ # Output of 'npm pack'
670
+ *.tgz
671
+
672
+ # Yarn Integrity file
673
+ .yarn-integrity
674
+
675
+ # dotenv environment variable files
676
+ .env
677
+ .env.*
678
+ !.env.example
679
+
680
+ # parcel-bundler cache (https://parceljs.org/)
681
+ .cache
682
+ .parcel-cache
683
+
684
+ # Next.js build output
685
+ .next
686
+ out
687
+
688
+ # Nuxt.js build / generate output
689
+ .nuxt
690
+ dist
691
+ .output
692
+
693
+ # Gatsby files
694
+ .cache/
695
+ # Comment in the public line in if your project uses Gatsby and not Next.js
696
+ # https://nextjs.org/blog/next-9-1#public-directory-support
697
+ # public
698
+
699
+ # vuepress build output
700
+ .vuepress/dist
701
+
702
+ # vuepress v2.x temp and cache directory
703
+ .temp
704
+ .cache
705
+
706
+ # Sveltekit cache directory
707
+ .svelte-kit/
708
+
709
+ # vitepress build output
710
+ **/.vitepress/dist
711
+
712
+ # vitepress cache directory
713
+ **/.vitepress/cache
714
+
715
+ # Docusaurus cache and generated files
716
+ .docusaurus
717
+
718
+ # Serverless directories
719
+ .serverless/
720
+
721
+ # FuseBox cache
722
+ .fusebox/
723
+
724
+ # DynamoDB Local files
725
+ .dynamodb/
726
+
727
+ # Firebase cache directory
728
+ .firebase/
729
+
730
+ # TernJS port file
731
+ .tern-port
732
+
733
+ # Stores VSCode versions used for testing VSCode extensions
734
+ .vscode-test
735
+
736
+ # yarn v3
737
+ .pnp.*
738
+ .yarn/*
739
+ !.yarn/patches
740
+ !.yarn/plugins
741
+ !.yarn/releases
742
+ !.yarn/sdks
743
+ !.yarn/versions
744
+
745
+ # Vite files
746
+ vite.config.js.timestamp-*
747
+ vite.config.ts.timestamp-*
748
+ .vite/
626
749
  `;
627
750
  const env = `# Server Configuration
628
751
  PORT=3001
package/package.json CHANGED
@@ -1,68 +1,68 @@
1
- {
2
- "name": "@leanmcp/cli",
3
- "version": "0.2.8",
4
- "description": "Command-line interface for scaffolding LeanMCP projects",
5
- "bin": {
6
- "leanmcp": "bin/leanmcp.js"
7
- },
8
- "type": "module",
9
- "main": "dist/index.js",
10
- "types": "dist/index.d.ts",
11
- "exports": {
12
- ".": {
13
- "types": "./dist/index.d.ts",
14
- "import": "./dist/index.js"
15
- }
16
- },
17
- "files": [
18
- "bin",
19
- "dist",
20
- "README.md",
21
- "LICENSE"
22
- ],
23
- "scripts": {
24
- "build": "tsup src/index.ts --format esm --dts",
25
- "dev": "tsup src/index.ts --format esm --dts --watch",
26
- "test": "echo \"No tests yet\" && exit 0",
27
- "clean": "rimraf dist"
28
- },
29
- "dependencies": {
30
- "@inquirer/prompts": "^7.0.1",
31
- "@vitejs/plugin-react": "^4.3.0",
32
- "chalk": "^5.3.0",
33
- "chokidar": "^4.0.0",
34
- "commander": "^12.0.0",
35
- "fs-extra": "^11.2.0",
36
- "glob": "^11.0.0",
37
- "ora": "^8.1.0",
38
- "vite": "^5.4.0",
39
- "vite-plugin-singlefile": "^2.3.0"
40
- },
41
- "devDependencies": {
42
- "@types/fs-extra": "^11.0.4",
43
- "@types/node": "^25.0.2",
44
- "rimraf": "^6.1.2"
45
- },
46
- "repository": {
47
- "type": "git",
48
- "url": "git+https://github.com/LeanMCP/leanmcp-sdk.git",
49
- "directory": "packages/cli"
50
- },
51
- "homepage": "https://github.com/LeanMCP/leanmcp-sdk#readme",
52
- "bugs": {
53
- "url": "https://github.com/LeanMCP/leanmcp-sdk/issues"
54
- },
55
- "keywords": [
56
- "mcp",
57
- "model-context-protocol",
58
- "cli",
59
- "scaffolding",
60
- "generator",
61
- "typescript"
62
- ],
63
- "author": "LeanMCP <admin@leanmcp.com>",
64
- "license": "MIT",
65
- "publishConfig": {
66
- "access": "public"
67
- }
68
- }
1
+ {
2
+ "name": "@leanmcp/cli",
3
+ "version": "0.2.10",
4
+ "description": "Command-line interface for scaffolding LeanMCP projects",
5
+ "bin": {
6
+ "leanmcp": "bin/leanmcp.js"
7
+ },
8
+ "type": "module",
9
+ "main": "dist/index.js",
10
+ "types": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "bin",
19
+ "dist",
20
+ "README.md",
21
+ "LICENSE"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsup src/index.ts --format esm --dts",
25
+ "dev": "tsup src/index.ts --format esm --dts --watch",
26
+ "test": "echo \"No tests yet\" && exit 0",
27
+ "clean": "rimraf dist"
28
+ },
29
+ "dependencies": {
30
+ "@inquirer/prompts": "^7.0.1",
31
+ "@vitejs/plugin-react": "^4.3.0",
32
+ "chalk": "^5.3.0",
33
+ "chokidar": "^4.0.0",
34
+ "commander": "^12.0.0",
35
+ "fs-extra": "^11.2.0",
36
+ "glob": "^11.0.0",
37
+ "ora": "^8.1.0",
38
+ "vite": "^5.4.0",
39
+ "vite-plugin-singlefile": "^2.3.0"
40
+ },
41
+ "devDependencies": {
42
+ "@types/fs-extra": "^11.0.4",
43
+ "@types/node": "^25.0.2",
44
+ "rimraf": "^6.1.2"
45
+ },
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "git+https://github.com/LeanMCP/leanmcp-sdk.git",
49
+ "directory": "packages/cli"
50
+ },
51
+ "homepage": "https://github.com/LeanMCP/leanmcp-sdk#readme",
52
+ "bugs": {
53
+ "url": "https://github.com/LeanMCP/leanmcp-sdk/issues"
54
+ },
55
+ "keywords": [
56
+ "mcp",
57
+ "model-context-protocol",
58
+ "cli",
59
+ "scaffolding",
60
+ "generator",
61
+ "typescript"
62
+ ],
63
+ "author": "LeanMCP <admin@leanmcp.com>",
64
+ "license": "MIT",
65
+ "publishConfig": {
66
+ "access": "public"
67
+ }
68
+ }