@leanmcp/cli 0.5.3 → 0.5.4-alpha.8.f4673cd
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 +11 -0
- package/dist/index.js +47 -27
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -48,6 +48,7 @@ npm install -g @leanmcp/cli
|
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
Or run without installing:
|
|
51
|
+
|
|
51
52
|
```bash
|
|
52
53
|
npx @leanmcp/cli create my-mcp-server
|
|
53
54
|
```
|
|
@@ -85,11 +86,13 @@ leanmcp create my-sentiment-tool
|
|
|
85
86
|
```
|
|
86
87
|
|
|
87
88
|
Interactive prompts will guide you through:
|
|
89
|
+
|
|
88
90
|
1. Creating the project structure
|
|
89
91
|
2. Installing dependencies (optional)
|
|
90
92
|
3. Starting the dev server (optional)
|
|
91
93
|
|
|
92
94
|
**Generated structure:**
|
|
95
|
+
|
|
93
96
|
```
|
|
94
97
|
my-mcp-server/
|
|
95
98
|
├── main.ts # Entry point with HTTP server
|
|
@@ -110,6 +113,7 @@ leanmcp add weather
|
|
|
110
113
|
```
|
|
111
114
|
|
|
112
115
|
This:
|
|
116
|
+
|
|
113
117
|
- Creates `mcp/weather/index.ts` with example Tool, Prompt, and Resource
|
|
114
118
|
- Automatically registers the service in `main.ts`
|
|
115
119
|
- Includes `@SchemaConstraint` validation examples
|
|
@@ -123,6 +127,7 @@ leanmcp dev
|
|
|
123
127
|
```
|
|
124
128
|
|
|
125
129
|
This command:
|
|
130
|
+
|
|
126
131
|
- Scans for `@UIApp` components and builds them
|
|
127
132
|
- Starts the HTTP server with `tsx watch`
|
|
128
133
|
- Watches `mcp/` directory for changes
|
|
@@ -176,6 +181,7 @@ leanmcp login
|
|
|
176
181
|
```
|
|
177
182
|
|
|
178
183
|
Steps:
|
|
184
|
+
|
|
179
185
|
1. Go to [ship.leanmcp.com/api-keys](https://ship.leanmcp.com/api-keys)
|
|
180
186
|
2. Create an API key with "BUILD_AND_DEPLOY" scope
|
|
181
187
|
3. Enter the key when prompted
|
|
@@ -207,6 +213,7 @@ leanmcp deploy ./my-project
|
|
|
207
213
|
```
|
|
208
214
|
|
|
209
215
|
Deployment process:
|
|
216
|
+
|
|
210
217
|
1. Creates project (or updates existing)
|
|
211
218
|
2. Packages and uploads code
|
|
212
219
|
3. Builds container image
|
|
@@ -287,6 +294,7 @@ PORT=4000
|
|
|
287
294
|
### LeanMCP Config
|
|
288
295
|
|
|
289
296
|
Stored in `~/.leanmcp/config.json`:
|
|
297
|
+
|
|
290
298
|
```json
|
|
291
299
|
{
|
|
292
300
|
"apiKey": "airtrain_...",
|
|
@@ -300,6 +308,7 @@ Stored in `~/.leanmcp/config.json`:
|
|
|
300
308
|
### Port Already in Use
|
|
301
309
|
|
|
302
310
|
Change the port in `.env`:
|
|
311
|
+
|
|
303
312
|
```bash
|
|
304
313
|
PORT=3002
|
|
305
314
|
```
|
|
@@ -307,6 +316,7 @@ PORT=3002
|
|
|
307
316
|
### Module Not Found Errors
|
|
308
317
|
|
|
309
318
|
Ensure dependencies are installed:
|
|
319
|
+
|
|
310
320
|
```bash
|
|
311
321
|
npm install
|
|
312
322
|
```
|
|
@@ -314,6 +324,7 @@ npm install
|
|
|
314
324
|
### TypeScript Decorator Errors
|
|
315
325
|
|
|
316
326
|
Ensure your `tsconfig.json` has:
|
|
327
|
+
|
|
317
328
|
```json
|
|
318
329
|
{
|
|
319
330
|
"compilerOptions": {
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3483
|
-
|
|
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, {
|