@leanmcp/cli 0.5.5-alpha.38.4ae4dde → 0.5.5-alpha.42.6df6bbe
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/README.md +124 -15
- package/dist/index.js +46 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# @leanmcp/cli
|
|
2
|
+
|
|
1
3
|
<p align="center">
|
|
2
4
|
<img
|
|
3
5
|
src="https://raw.githubusercontent.com/LeanMCP/leanmcp-sdk/refs/heads/main/assets/logo.png"
|
|
@@ -6,11 +8,6 @@
|
|
|
6
8
|
/>
|
|
7
9
|
</p>
|
|
8
10
|
|
|
9
|
-
<p align="center">
|
|
10
|
-
<strong>@leanmcp/cli</strong><br/>
|
|
11
|
-
Command-line tool for creating, developing, and deploying LeanMCP projects.
|
|
12
|
-
</p>
|
|
13
|
-
|
|
14
11
|
<p align="center">
|
|
15
12
|
<a href="https://www.npmjs.com/package/@leanmcp/cli">
|
|
16
13
|
<img src="https://img.shields.io/npm/v/@leanmcp/cli" alt="npm version" />
|
|
@@ -22,7 +19,7 @@
|
|
|
22
19
|
<img src="https://img.shields.io/badge/Docs-leanmcp-0A66C2?" />
|
|
23
20
|
</a>
|
|
24
21
|
<a href="https://discord.com/invite/DsRcA3GwPy">
|
|
25
|
-
<img src="https://
|
|
22
|
+
<img src="https://dcbadge.limes.pink/api/server/DsRcA3GwPy?style=flat" alt="Discord" />
|
|
26
23
|
</a>
|
|
27
24
|
<a href="https://x.com/LeanMcp">
|
|
28
25
|
<img src="https://img.shields.io/badge/@LeanMCP-f5f5f5?logo=x&logoColor=000000" />
|
|
@@ -33,6 +30,58 @@
|
|
|
33
30
|
<a href="https://deepwiki.com/LeanMCP/leanmcp-sdk"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
|
|
34
31
|
</p>
|
|
35
32
|
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"package": "@leanmcp/cli",
|
|
36
|
+
"purpose": "Command-line interface for scaffolding LeanMCP projects",
|
|
37
|
+
"useCases": [
|
|
38
|
+
"Project scaffolding",
|
|
39
|
+
"Local development with hot-reload",
|
|
40
|
+
"Cloud deployment",
|
|
41
|
+
"Project management"
|
|
42
|
+
],
|
|
43
|
+
"dependencies": ["@inquirer/prompts", "commander", "chalk", "vite", "archiver", "fs-extra"],
|
|
44
|
+
"bin": {
|
|
45
|
+
"leanmcp": "bin/leanmcp.js"
|
|
46
|
+
},
|
|
47
|
+
"main": "dist/index.js",
|
|
48
|
+
"exports": {
|
|
49
|
+
".": {
|
|
50
|
+
"types": "./dist/index.d.ts",
|
|
51
|
+
"import": "./dist/index.js"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Overview
|
|
58
|
+
|
|
59
|
+
- **What it is**: Command-line interface for scaffolding LeanMCP projects with hot-reload development and cloud deployment
|
|
60
|
+
- **Purpose**: Streamlines the entire MCP server development workflow from project creation to production deployment
|
|
61
|
+
- **Key benefits**:
|
|
62
|
+
- Quick project scaffolding with production-ready templates
|
|
63
|
+
- Hot-reload development server with UI component building
|
|
64
|
+
- One-command cloud deployment to LeanMCP platform
|
|
65
|
+
- Interactive setup with guided prompts
|
|
66
|
+
- Project management and monitoring tools
|
|
67
|
+
|
|
68
|
+
## When to Use It
|
|
69
|
+
|
|
70
|
+
**Use `@leanmcp/cli` when:**
|
|
71
|
+
|
|
72
|
+
- Starting any new MCP server project (highly recommended)
|
|
73
|
+
- Need local development with hot-reload and UI building
|
|
74
|
+
- Want to deploy to LeanMCP Cloud with custom subdomains
|
|
75
|
+
- Managing multiple MCP projects
|
|
76
|
+
- Need guided setup for dependencies and configuration
|
|
77
|
+
|
|
78
|
+
**You probably do NOT need this if:**
|
|
79
|
+
|
|
80
|
+
- Using custom build systems or deployment pipelines
|
|
81
|
+
- Only working with existing projects without scaffolding needs
|
|
82
|
+
- Building MCP clients (not servers)
|
|
83
|
+
- Working in environments where global CLI tools aren't allowed
|
|
84
|
+
|
|
36
85
|
## Features
|
|
37
86
|
|
|
38
87
|
- **Quick Scaffolding** — Create production-ready MCP servers in seconds
|
|
@@ -53,7 +102,14 @@ Or run without installing:
|
|
|
53
102
|
npx @leanmcp/cli create my-mcp-server
|
|
54
103
|
```
|
|
55
104
|
|
|
56
|
-
|
|
105
|
+
**Requirements:**
|
|
106
|
+
|
|
107
|
+
- Node.js >= 18.0.0
|
|
108
|
+
- npm >= 9.0.0
|
|
109
|
+
|
|
110
|
+
## Usage / Examples
|
|
111
|
+
|
|
112
|
+
### Commands Overview
|
|
57
113
|
|
|
58
114
|
```bash
|
|
59
115
|
# Local development
|
|
@@ -270,7 +326,60 @@ leanmcp projects delete <project-id> --force # Skip confirmation
|
|
|
270
326
|
|
|
271
327
|
---
|
|
272
328
|
|
|
273
|
-
##
|
|
329
|
+
## API Reference
|
|
330
|
+
|
|
331
|
+
### Command Reference
|
|
332
|
+
|
|
333
|
+
| Command | Description | Usage |
|
|
334
|
+
| ---------------------- | ---------------------------------------- | ------------------------------ |
|
|
335
|
+
| `create <name>` | Create new MCP server project | `leanmcp create my-server` |
|
|
336
|
+
| `add <service>` | Add service to existing project | `leanmcp add weather` |
|
|
337
|
+
| `dev` | Start development server with hot-reload | `leanmcp dev` |
|
|
338
|
+
| `build` | Build for production | `leanmcp build` |
|
|
339
|
+
| `start` | Start production server | `leanmcp start` |
|
|
340
|
+
| `login` | Authenticate with LeanMCP Cloud | `leanmcp login` |
|
|
341
|
+
| `logout` | Remove API key | `leanmcp logout` |
|
|
342
|
+
| `whoami` | Show login status | `leanmcp whoami` |
|
|
343
|
+
| `deploy [folder]` | Deploy to LeanMCP Cloud | `leanmcp deploy .` |
|
|
344
|
+
| `projects list` | List cloud projects | `leanmcp projects list` |
|
|
345
|
+
| `projects get <id>` | Get project details | `leanmcp projects get <id>` |
|
|
346
|
+
| `projects delete <id>` | Delete project | `leanmcp projects delete <id>` |
|
|
347
|
+
| `env list [folder]` | List environment variables | `leanmcp env list` |
|
|
348
|
+
| `env set <keyValue>` | Set environment variable | `leanmcp env set KEY=VALUE` |
|
|
349
|
+
| `env get <key>` | Get environment variable value | `leanmcp env get KEY` |
|
|
350
|
+
| `env remove <key>` | Remove environment variable | `leanmcp env remove KEY` |
|
|
351
|
+
| `env pull [folder]` | Download env vars to local file | `leanmcp env pull` |
|
|
352
|
+
| `env push [folder]` | Upload env vars from local file | `leanmcp env push` |
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## Integration with Other LeanMCP Packages
|
|
357
|
+
|
|
358
|
+
**@leanmcp/cli** works seamlessly with all LeanMCP packages:
|
|
359
|
+
|
|
360
|
+
- **[@leanmcp/core](https://www.npmjs.com/package/@leanmcp/core)** — Generated projects use `@leanmcp/core` as the foundation
|
|
361
|
+
- **[@leanmcp/auth](https://www.npmjs.com/package/@leanmcp/auth)** — CLI can scaffold projects with authentication setup
|
|
362
|
+
- **[@leanmcp/ui](https://www.npmjs.com/package/@leanmcp/ui)** — `leanmcp dev` automatically builds UI components with hot-reload
|
|
363
|
+
- **[@leanmcp/elicitation](https://www.npmjs.com/package/@leanmcp/elicitation)** — Generated services include elicitation examples
|
|
364
|
+
- **[@leanmcp/env-injection](https://www.npmjs.com/package/@leanmcp/env-injection)** — Deploy command handles user secrets configuration
|
|
365
|
+
|
|
366
|
+
**Generated project structure:**
|
|
367
|
+
|
|
368
|
+
```
|
|
369
|
+
my-mcp-server/
|
|
370
|
+
├── main.ts # Entry point with HTTP server
|
|
371
|
+
├── package.json # Dependencies and scripts
|
|
372
|
+
├── tsconfig.json # TypeScript configuration
|
|
373
|
+
└── mcp/ # Services directory (auto-discovered)
|
|
374
|
+
└── example/
|
|
375
|
+
└── index.ts # Example service with @Tool, @Prompt, @Resource
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
## Best Practices / Troubleshooting
|
|
381
|
+
|
|
382
|
+
### NPM Scripts
|
|
274
383
|
|
|
275
384
|
Generated projects include:
|
|
276
385
|
|
|
@@ -357,12 +466,12 @@ Choose a different subdomain when prompted.
|
|
|
357
466
|
- [@leanmcp/auth](https://www.npmjs.com/package/@leanmcp/auth) — Authentication decorators
|
|
358
467
|
- [@leanmcp/ui](https://www.npmjs.com/package/@leanmcp/ui) — MCP App UI components
|
|
359
468
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
- [GitHub Repository](https://github.com/LeanMCP/leanmcp-sdk)
|
|
363
|
-
- [NPM Package](https://www.npmjs.com/package/@leanmcp/cli)
|
|
364
|
-
- [LeanMCP Dashboard](https://ship.leanmcp.com)
|
|
469
|
+
---
|
|
365
470
|
|
|
366
|
-
##
|
|
471
|
+
## Links
|
|
367
472
|
|
|
368
|
-
|
|
473
|
+
- **Documentation**: [https://docs.leanmcp.com/sdk/cli](https://docs.leanmcp.com/sdk/cli)
|
|
474
|
+
- **GitHub**: [https://github.com/LeanMCP/leanmcp-sdk/tree/main/packages/cli](https://github.com/LeanMCP/leanmcp-sdk/tree/main/packages/cli)
|
|
475
|
+
- **npm**: [https://www.npmjs.com/package/@leanmcp/cli](https://www.npmjs.com/package/@leanmcp/cli)
|
|
476
|
+
- **LeanMCP Dashboard**: [https://ship.leanmcp.com](https://ship.leanmcp.com)
|
|
477
|
+
- **License**: MIT
|
package/dist/index.js
CHANGED
|
@@ -1786,6 +1786,42 @@ async function debugFetch(url, options = {}) {
|
|
|
1786
1786
|
return response;
|
|
1787
1787
|
}
|
|
1788
1788
|
__name(debugFetch, "debugFetch");
|
|
1789
|
+
async function fetchWithRetry(fetchFn, options = {}) {
|
|
1790
|
+
const maxRetries = options.maxRetries ?? 15;
|
|
1791
|
+
const initialDelay = options.initialDelay ?? 1e3;
|
|
1792
|
+
const maxDelay = options.maxDelay ?? 1e4;
|
|
1793
|
+
const operation = options.operation ?? "Fetch";
|
|
1794
|
+
const spinner = options.spinner;
|
|
1795
|
+
const retryOnHttpErrors = options.retryOnHttpErrors ?? false;
|
|
1796
|
+
let lastError = null;
|
|
1797
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
1798
|
+
try {
|
|
1799
|
+
const response = await fetchFn();
|
|
1800
|
+
if (retryOnHttpErrors && !response.ok && response.status >= 500) {
|
|
1801
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
1802
|
+
}
|
|
1803
|
+
return response;
|
|
1804
|
+
} catch (error) {
|
|
1805
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
1806
|
+
if (attempt < maxRetries) {
|
|
1807
|
+
const delay = Math.min(initialDelay * Math.pow(2, attempt), maxDelay);
|
|
1808
|
+
const message = `${operation} failed. Retrying... (${attempt + 1}/${maxRetries})`;
|
|
1809
|
+
if (spinner) {
|
|
1810
|
+
spinner.text = message;
|
|
1811
|
+
} else {
|
|
1812
|
+
process.stdout.write("\r" + chalk.yellow(message));
|
|
1813
|
+
}
|
|
1814
|
+
debug3(`Retry ${attempt + 1}/${maxRetries}: ${lastError.message}, waiting ${delay}ms`);
|
|
1815
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
if (!spinner) {
|
|
1820
|
+
process.stdout.write("\x1B[2K\r");
|
|
1821
|
+
}
|
|
1822
|
+
throw new Error(`${operation} failed after ${maxRetries + 1} attempts (1 initial + ${maxRetries} retries): ${lastError?.message || "Unknown error"}`);
|
|
1823
|
+
}
|
|
1824
|
+
__name(fetchWithRetry, "fetchWithRetry");
|
|
1789
1825
|
var API_ENDPOINTS = {
|
|
1790
1826
|
// Projects
|
|
1791
1827
|
projects: "/api/projects",
|
|
@@ -1872,10 +1908,14 @@ async function waitForBuild(apiUrl, apiKey, buildId, spinner) {
|
|
|
1872
1908
|
const maxAttempts = 60;
|
|
1873
1909
|
let attempts = 0;
|
|
1874
1910
|
while (attempts < maxAttempts) {
|
|
1875
|
-
const response = await debugFetch(`${apiUrl}${API_ENDPOINTS.getBuild}/${buildId}`, {
|
|
1911
|
+
const response = await fetchWithRetry(() => debugFetch(`${apiUrl}${API_ENDPOINTS.getBuild}/${buildId}`, {
|
|
1876
1912
|
headers: {
|
|
1877
1913
|
Authorization: `Bearer ${apiKey}`
|
|
1878
1914
|
}
|
|
1915
|
+
}), {
|
|
1916
|
+
operation: "Build status check",
|
|
1917
|
+
spinner,
|
|
1918
|
+
maxRetries: 3
|
|
1879
1919
|
});
|
|
1880
1920
|
if (!response.ok) {
|
|
1881
1921
|
throw new Error(`Failed to get build status: ${response.statusText}`);
|
|
@@ -1901,10 +1941,14 @@ async function waitForDeployment(apiUrl, apiKey, deploymentId, spinner) {
|
|
|
1901
1941
|
const maxAttempts = 60;
|
|
1902
1942
|
let attempts = 0;
|
|
1903
1943
|
while (attempts < maxAttempts) {
|
|
1904
|
-
const response = await debugFetch(`${apiUrl}${API_ENDPOINTS.getDeployment}/${deploymentId}`, {
|
|
1944
|
+
const response = await fetchWithRetry(() => debugFetch(`${apiUrl}${API_ENDPOINTS.getDeployment}/${deploymentId}`, {
|
|
1905
1945
|
headers: {
|
|
1906
1946
|
Authorization: `Bearer ${apiKey}`
|
|
1907
1947
|
}
|
|
1948
|
+
}), {
|
|
1949
|
+
operation: "Deployment status check",
|
|
1950
|
+
spinner,
|
|
1951
|
+
maxRetries: 3
|
|
1908
1952
|
});
|
|
1909
1953
|
if (!response.ok) {
|
|
1910
1954
|
throw new Error(`Failed to get deployment status: ${response.statusText}`);
|