@leanmcp/cli 0.5.2 → 0.5.4

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 LeanMCP Contributors
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2025 LeanMCP Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -27,6 +27,10 @@
27
27
  <a href="https://x.com/LeanMcp">
28
28
  <img src="https://img.shields.io/badge/@LeanMCP-f5f5f5?logo=x&logoColor=000000" />
29
29
  </a>
30
+ <a href="https://leanmcp.com/">
31
+ <img src="https://img.shields.io/badge/Website-leanmcp-0A66C2?" />
32
+ </a>
33
+ <a href="https://deepwiki.com/LeanMCP/leanmcp-sdk"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
30
34
  </p>
31
35
 
32
36
  ## Features
@@ -44,6 +48,7 @@ npm install -g @leanmcp/cli
44
48
  ```
45
49
 
46
50
  Or run without installing:
51
+
47
52
  ```bash
48
53
  npx @leanmcp/cli create my-mcp-server
49
54
  ```
@@ -81,11 +86,13 @@ leanmcp create my-sentiment-tool
81
86
  ```
82
87
 
83
88
  Interactive prompts will guide you through:
89
+
84
90
  1. Creating the project structure
85
91
  2. Installing dependencies (optional)
86
92
  3. Starting the dev server (optional)
87
93
 
88
94
  **Generated structure:**
95
+
89
96
  ```
90
97
  my-mcp-server/
91
98
  ├── main.ts # Entry point with HTTP server
@@ -106,6 +113,7 @@ leanmcp add weather
106
113
  ```
107
114
 
108
115
  This:
116
+
109
117
  - Creates `mcp/weather/index.ts` with example Tool, Prompt, and Resource
110
118
  - Automatically registers the service in `main.ts`
111
119
  - Includes `@SchemaConstraint` validation examples
@@ -119,6 +127,7 @@ leanmcp dev
119
127
  ```
120
128
 
121
129
  This command:
130
+
122
131
  - Scans for `@UIApp` components and builds them
123
132
  - Starts the HTTP server with `tsx watch`
124
133
  - Watches `mcp/` directory for changes
@@ -172,6 +181,7 @@ leanmcp login
172
181
  ```
173
182
 
174
183
  Steps:
184
+
175
185
  1. Go to [ship.leanmcp.com/api-keys](https://ship.leanmcp.com/api-keys)
176
186
  2. Create an API key with "BUILD_AND_DEPLOY" scope
177
187
  3. Enter the key when prompted
@@ -203,6 +213,7 @@ leanmcp deploy ./my-project
203
213
  ```
204
214
 
205
215
  Deployment process:
216
+
206
217
  1. Creates project (or updates existing)
207
218
  2. Packages and uploads code
208
219
  3. Builds container image
@@ -283,6 +294,7 @@ PORT=4000
283
294
  ### LeanMCP Config
284
295
 
285
296
  Stored in `~/.leanmcp/config.json`:
297
+
286
298
  ```json
287
299
  {
288
300
  "apiKey": "airtrain_...",
@@ -296,6 +308,7 @@ Stored in `~/.leanmcp/config.json`:
296
308
  ### Port Already in Use
297
309
 
298
310
  Change the port in `.env`:
311
+
299
312
  ```bash
300
313
  PORT=3002
301
314
  ```
@@ -303,6 +316,7 @@ PORT=3002
303
316
  ### Module Not Found Errors
304
317
 
305
318
  Ensure dependencies are installed:
319
+
306
320
  ```bash
307
321
  npm install
308
322
  ```
@@ -310,6 +324,7 @@ npm install
310
324
  ### TypeScript Decorator Errors
311
325
 
312
326
  Ensure your `tsconfig.json` has:
327
+
313
328
  ```json
314
329
  {
315
330
  "compilerOptions": {
package/bin/leanmcp.js CHANGED
File without changes
package/dist/index.js CHANGED
@@ -397,7 +397,7 @@ createRoot(document.getElementById('root')!).render(
397
397
  resolve: {
398
398
  alias: {
399
399
  // Resolve React from project or workspace root node_modules
400
- "react": reactPath,
400
+ react: reactPath,
401
401
  "react-dom": reactDomPath,
402
402
  "react/jsx-runtime": path2.join(reactPath, "jsx-runtime"),
403
403
  "react/jsx-dev-runtime": path2.join(reactPath, "jsx-dev-runtime")
@@ -1132,7 +1132,7 @@ async function loginCommand() {
1132
1132
  const response = await fetch(validateUrl, {
1133
1133
  method: "GET",
1134
1134
  headers: {
1135
- "Authorization": `Bearer ${apiKey.trim()}`,
1135
+ Authorization: `Bearer ${apiKey.trim()}`,
1136
1136
  "Content-Type": "application/json"
1137
1137
  }
1138
1138
  });
@@ -1219,7 +1219,7 @@ async function whoamiCommand() {
1219
1219
  const response = await fetch(whoamiUrl, {
1220
1220
  method: "GET",
1221
1221
  headers: {
1222
- "Authorization": `Bearer ${config.apiKey}`,
1222
+ Authorization: `Bearer ${config.apiKey}`,
1223
1223
  "Content-Type": "application/json"
1224
1224
  }
1225
1225
  });
@@ -1665,13 +1665,25 @@ async function createZipArchive(folderPath, outputPath) {
1665
1665
  });
1666
1666
  }
1667
1667
  __name(createZipArchive, "createZipArchive");
1668
+ var BuildError = class BuildError2 extends Error {
1669
+ static {
1670
+ __name(this, "BuildError");
1671
+ }
1672
+ buildId;
1673
+ errorSummary;
1674
+ errorDetails;
1675
+ constructor(message, buildId, errorSummary, errorDetails) {
1676
+ super(message), this.buildId = buildId, this.errorSummary = errorSummary, this.errorDetails = errorDetails;
1677
+ this.name = "BuildError";
1678
+ }
1679
+ };
1668
1680
  async function waitForBuild(apiUrl, apiKey, buildId, spinner) {
1669
1681
  const maxAttempts = 60;
1670
1682
  let attempts = 0;
1671
1683
  while (attempts < maxAttempts) {
1672
1684
  const response = await debugFetch(`${apiUrl}${API_ENDPOINTS.getBuild}/${buildId}`, {
1673
1685
  headers: {
1674
- "Authorization": `Bearer ${apiKey}`
1686
+ Authorization: `Bearer ${apiKey}`
1675
1687
  }
1676
1688
  });
1677
1689
  if (!response.ok) {
@@ -1686,7 +1698,7 @@ async function waitForBuild(apiUrl, apiKey, buildId, spinner) {
1686
1698
  };
1687
1699
  }
1688
1700
  if (build2.status === "failed" || build2.status === "FAILED") {
1689
- throw new Error(`Build failed: ${build2.errorMessage || "Unknown error"}`);
1701
+ throw new BuildError(build2.errorSummary || build2.errorMessage || "Unknown error", buildId, build2.errorSummary, build2.errorDetails);
1690
1702
  }
1691
1703
  await new Promise((r) => setTimeout(r, 5e3));
1692
1704
  attempts++;
@@ -1700,7 +1712,7 @@ async function waitForDeployment(apiUrl, apiKey, deploymentId, spinner) {
1700
1712
  while (attempts < maxAttempts) {
1701
1713
  const response = await debugFetch(`${apiUrl}${API_ENDPOINTS.getDeployment}/${deploymentId}`, {
1702
1714
  headers: {
1703
- "Authorization": `Bearer ${apiKey}`
1715
+ Authorization: `Bearer ${apiKey}`
1704
1716
  }
1705
1717
  });
1706
1718
  if (!response.ok) {
@@ -1806,7 +1818,7 @@ Generated project name: ${chalk.bold(projectName)}
1806
1818
  try {
1807
1819
  const projectsResponse = await debugFetch(`${apiUrl}${API_ENDPOINTS.projects}`, {
1808
1820
  headers: {
1809
- "Authorization": `Bearer ${apiKey}`
1821
+ Authorization: `Bearer ${apiKey}`
1810
1822
  }
1811
1823
  });
1812
1824
  if (projectsResponse.ok) {
@@ -1892,7 +1904,7 @@ Generated project name: ${chalk.bold(projectName)}
1892
1904
  debug3("Checking subdomain:", subdomain);
1893
1905
  const checkResponse = await debugFetch(`${apiUrl}${API_ENDPOINTS.checkSubdomain}/${subdomain}`, {
1894
1906
  headers: {
1895
- "Authorization": `Bearer ${apiKey}`
1907
+ Authorization: `Bearer ${apiKey}`
1896
1908
  }
1897
1909
  });
1898
1910
  if (checkResponse.ok) {
@@ -1947,7 +1959,7 @@ This subdomain is associated with project: ${result.ownedByProject?.substring(0,
1947
1959
  const createResponse = await debugFetch(`${apiUrl}${API_ENDPOINTS.projects}`, {
1948
1960
  method: "POST",
1949
1961
  headers: {
1950
- "Authorization": `Bearer ${apiKey}`,
1962
+ Authorization: `Bearer ${apiKey}`,
1951
1963
  "Content-Type": "application/json"
1952
1964
  },
1953
1965
  body: JSON.stringify({
@@ -1977,7 +1989,7 @@ ${error instanceof Error ? error.message : String(error)}`);
1977
1989
  const uploadUrlResponse = await debugFetch(`${apiUrl}${API_ENDPOINTS.projects}/${projectId}/upload-url`, {
1978
1990
  method: "POST",
1979
1991
  headers: {
1980
- "Authorization": `Bearer ${apiKey}`,
1992
+ Authorization: `Bearer ${apiKey}`,
1981
1993
  "Content-Type": "application/json"
1982
1994
  },
1983
1995
  body: JSON.stringify({
@@ -2013,7 +2025,7 @@ ${error instanceof Error ? error.message : String(error)}`);
2013
2025
  await debugFetch(`${apiUrl}${API_ENDPOINTS.projects}/${projectId}`, {
2014
2026
  method: "PATCH",
2015
2027
  headers: {
2016
- "Authorization": `Bearer ${apiKey}`,
2028
+ Authorization: `Bearer ${apiKey}`,
2017
2029
  "Content-Type": "application/json"
2018
2030
  },
2019
2031
  body: JSON.stringify({
@@ -2037,7 +2049,7 @@ ${error instanceof Error ? error.message : String(error)}`);
2037
2049
  const buildResponse = await debugFetch(`${apiUrl}${API_ENDPOINTS.triggerBuild}/${projectId}`, {
2038
2050
  method: "POST",
2039
2051
  headers: {
2040
- "Authorization": `Bearer ${apiKey}`
2052
+ Authorization: `Bearer ${apiKey}`
2041
2053
  }
2042
2054
  });
2043
2055
  if (!buildResponse.ok) {
@@ -2052,8 +2064,15 @@ ${error instanceof Error ? error.message : String(error)}`);
2052
2064
  buildSpinner.succeed(`Build complete (${buildDuration}s)`);
2053
2065
  } catch (error) {
2054
2066
  buildSpinner.fail("Build failed");
2055
- logger.error(`
2067
+ if (error instanceof BuildError && error.errorDetails?.length) {
2068
+ logger.error(`
2069
+ ${error.errorSummary || "Build failed"}
2070
+ `);
2071
+ error.errorDetails.forEach((err) => logger.gray(` ${err}`));
2072
+ } else {
2073
+ logger.error(`
2056
2074
  ${error instanceof Error ? error.message : String(error)}`);
2075
+ }
2057
2076
  process.exit(1);
2058
2077
  }
2059
2078
  const deploySpinner = ora5("Deploying to LeanMCP...").start();
@@ -2064,7 +2083,7 @@ ${error instanceof Error ? error.message : String(error)}`);
2064
2083
  const deployResponse = await debugFetch(`${apiUrl}${API_ENDPOINTS.createDeployment}`, {
2065
2084
  method: "POST",
2066
2085
  headers: {
2067
- "Authorization": `Bearer ${apiKey}`,
2086
+ Authorization: `Bearer ${apiKey}`,
2068
2087
  "Content-Type": "application/json"
2069
2088
  },
2070
2089
  body: JSON.stringify({
@@ -2092,7 +2111,7 @@ ${error instanceof Error ? error.message : String(error)}`);
2092
2111
  const mappingResponse = await debugFetch(`${apiUrl}${API_ENDPOINTS.createMapping}`, {
2093
2112
  method: "POST",
2094
2113
  headers: {
2095
- "Authorization": `Bearer ${apiKey}`,
2114
+ Authorization: `Bearer ${apiKey}`,
2096
2115
  "Content-Type": "application/json"
2097
2116
  },
2098
2117
  body: JSON.stringify({
@@ -2165,7 +2184,7 @@ async function projectsListCommand() {
2165
2184
  const apiUrl = await getApiUrl();
2166
2185
  const response = await fetch(`${apiUrl}${API_ENDPOINT}`, {
2167
2186
  headers: {
2168
- "Authorization": `Bearer ${apiKey}`
2187
+ Authorization: `Bearer ${apiKey}`
2169
2188
  }
2170
2189
  });
2171
2190
  if (!response.ok) {
@@ -2210,7 +2229,7 @@ async function projectsGetCommand(projectId) {
2210
2229
  const apiUrl = await getApiUrl();
2211
2230
  const response = await fetch(`${apiUrl}${API_ENDPOINT}/${projectId}`, {
2212
2231
  headers: {
2213
- "Authorization": `Bearer ${apiKey}`
2232
+ Authorization: `Bearer ${apiKey}`
2214
2233
  }
2215
2234
  });
2216
2235
  if (!response.ok) {
@@ -2266,7 +2285,7 @@ async function projectsDeleteCommand(projectId, options = {}) {
2266
2285
  const response = await fetch(`${apiUrl}${API_ENDPOINT}/${projectId}`, {
2267
2286
  method: "DELETE",
2268
2287
  headers: {
2269
- "Authorization": `Bearer ${apiKey}`
2288
+ Authorization: `Bearer ${apiKey}`
2270
2289
  }
2271
2290
  });
2272
2291
  if (!response.ok) {
@@ -2375,7 +2394,7 @@ async function envListCommand(folderPath, options = {}) {
2375
2394
  const reveal = options.reveal ? "?reveal=true" : "";
2376
2395
  const response = await debugFetch2(`${apiUrl}/api/lambda-deploy/${config.deploymentId}/env${reveal}`, {
2377
2396
  headers: {
2378
- "Authorization": `Bearer ${apiKey}`
2397
+ Authorization: `Bearer ${apiKey}`
2379
2398
  }
2380
2399
  });
2381
2400
  if (!response.ok) {
@@ -2457,7 +2476,7 @@ ${error instanceof Error ? error.message : String(error)}`);
2457
2476
  const response = await debugFetch2(`${apiUrl}/api/lambda-deploy/${config.deploymentId}/env`, {
2458
2477
  method: "PUT",
2459
2478
  headers: {
2460
- "Authorization": `Bearer ${apiKey}`,
2479
+ Authorization: `Bearer ${apiKey}`,
2461
2480
  "Content-Type": "application/json"
2462
2481
  },
2463
2482
  body: JSON.stringify({
@@ -2491,7 +2510,7 @@ async function envGetCommand(key, folderPath, options = {}) {
2491
2510
  const reveal = options.reveal ? "?reveal=true" : "";
2492
2511
  const response = await debugFetch2(`${apiUrl}/api/lambda-deploy/${config.deploymentId}/env${reveal}`, {
2493
2512
  headers: {
2494
- "Authorization": `Bearer ${apiKey}`
2513
+ Authorization: `Bearer ${apiKey}`
2495
2514
  }
2496
2515
  });
2497
2516
  if (!response.ok) {
@@ -2542,7 +2561,7 @@ async function envRemoveCommand(key, folderPath, options = {}) {
2542
2561
  const response = await debugFetch2(`${apiUrl}/api/lambda-deploy/${config.deploymentId}/env/${key}`, {
2543
2562
  method: "DELETE",
2544
2563
  headers: {
2545
- "Authorization": `Bearer ${apiKey}`
2564
+ Authorization: `Bearer ${apiKey}`
2546
2565
  }
2547
2566
  });
2548
2567
  if (!response.ok) {
@@ -2570,7 +2589,7 @@ async function envPullCommand(folderPath, options = {}) {
2570
2589
  try {
2571
2590
  const response = await debugFetch2(`${apiUrl}/api/lambda-deploy/${config.deploymentId}/env?reveal=true`, {
2572
2591
  headers: {
2573
- "Authorization": `Bearer ${apiKey}`
2592
+ Authorization: `Bearer ${apiKey}`
2574
2593
  }
2575
2594
  });
2576
2595
  if (!response.ok) {
@@ -2637,7 +2656,7 @@ ${error instanceof Error ? error.message : String(error)}`);
2637
2656
  const response = await debugFetch2(`${apiUrl}/api/lambda-deploy/${config.deploymentId}/env`, {
2638
2657
  method: "PUT",
2639
2658
  headers: {
2640
- "Authorization": `Bearer ${apiKey}`,
2659
+ Authorization: `Bearer ${apiKey}`,
2641
2660
  "Content-Type": "application/json"
2642
2661
  },
2643
2662
  body: JSON.stringify({
@@ -3099,6 +3118,7 @@ await createHTTPServer({
3099
3118
  port: 3001,
3100
3119
  cors: true,
3101
3120
  logging: true${dashboardLine}
3121
+ // stateless: false, // Enable stateful mode (uses DynamoDB on Lambda for session persistence)
3102
3122
  });
3103
3123
 
3104
3124
  console.log("\\n${projectName} MCP Server");
@@ -3474,13 +3494,13 @@ PORT=3001
3474
3494
  "@leanmcp/core": "^0.3.14",
3475
3495
  "@leanmcp/ui": "^0.2.1",
3476
3496
  "@leanmcp/auth": "^0.4.0",
3477
- "dotenv": "^16.5.0"
3497
+ dotenv: "^16.5.0"
3478
3498
  },
3479
3499
  devDependencies: {
3480
3500
  "@leanmcp/cli": "^0.4.0",
3481
3501
  "@types/node": "^20.0.0",
3482
- "tsx": "^4.20.3",
3483
- "typescript": "^5.6.3"
3502
+ tsx: "^4.20.3",
3503
+ typescript: "^5.6.3"
3484
3504
  }
3485
3505
  };
3486
3506
  await fs10.writeJSON(path10.join(targetDir, "package.json"), pkg2, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leanmcp/cli",
3
- "version": "0.5.2",
3
+ "version": "0.5.4",
4
4
  "description": "Command-line interface for scaffolding LeanMCP projects",
5
5
  "bin": {
6
6
  "leanmcp": "bin/leanmcp.js"
@@ -70,4 +70,4 @@
70
70
  "publishConfig": {
71
71
  "access": "public"
72
72
  }
73
- }
73
+ }