@mcp-use/cli 3.3.2-canary.6 → 3.4.0-canary.0
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/commands/auth.d.ts +7 -0
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/deploy.d.ts +5 -0
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/index.cjs +284 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +282 -32
- package/dist/index.js.map +1 -1
- package/dist/utils/api.d.ts +28 -0
- package/dist/utils/api.d.ts.map +1 -1
- package/dist/utils/tarball.d.ts +13 -0
- package/dist/utils/tarball.d.ts.map +1 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1369,6 +1369,80 @@ var McpUseAPI = class _McpUseAPI {
|
|
|
1369
1369
|
body: JSON.stringify(body)
|
|
1370
1370
|
});
|
|
1371
1371
|
}
|
|
1372
|
+
/** Multipart helper: POST/PUT a tarball + fields without the JSON Content-Type. */
|
|
1373
|
+
async uploadMultipart(endpoint, form, timeout = 12e4) {
|
|
1374
|
+
const url = `${this.baseUrl}${endpoint}`;
|
|
1375
|
+
const headers = {
|
|
1376
|
+
"x-mcp-creation-location": "cli"
|
|
1377
|
+
};
|
|
1378
|
+
if (this.apiKey) headers["x-api-key"] = this.apiKey;
|
|
1379
|
+
if (this.orgId) headers["x-profile-id"] = this.orgId;
|
|
1380
|
+
const controller = new AbortController();
|
|
1381
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
1382
|
+
try {
|
|
1383
|
+
const response = await fetch(url, {
|
|
1384
|
+
method: "POST",
|
|
1385
|
+
headers,
|
|
1386
|
+
body: form,
|
|
1387
|
+
signal: controller.signal
|
|
1388
|
+
});
|
|
1389
|
+
clearTimeout(timeoutId);
|
|
1390
|
+
if (response.status === 401) throw new ApiUnauthorizedError();
|
|
1391
|
+
if (!response.ok) {
|
|
1392
|
+
const errorText = await response.text();
|
|
1393
|
+
throw new Error(`API request failed: ${response.status} ${errorText}`);
|
|
1394
|
+
}
|
|
1395
|
+
return response.json();
|
|
1396
|
+
} catch (error) {
|
|
1397
|
+
clearTimeout(timeoutId);
|
|
1398
|
+
if (error.name === "AbortError") {
|
|
1399
|
+
throw new Error(`Request timeout after ${timeout / 1e3}s.`);
|
|
1400
|
+
}
|
|
1401
|
+
throw error;
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
/**
|
|
1405
|
+
* Create a server from a source tarball deployed into the platform-managed
|
|
1406
|
+
* GitHub org (no user GitHub connection required).
|
|
1407
|
+
*/
|
|
1408
|
+
async createServerFromManagedUpload(input) {
|
|
1409
|
+
const form = new FormData();
|
|
1410
|
+
form.set(
|
|
1411
|
+
"sourceFile",
|
|
1412
|
+
new Blob([new Uint8Array(input.tarball)], { type: "application/gzip" }),
|
|
1413
|
+
"source.tar.gz"
|
|
1414
|
+
);
|
|
1415
|
+
form.set("organizationId", input.organizationId);
|
|
1416
|
+
form.set("managed", "true");
|
|
1417
|
+
form.set("name", input.name);
|
|
1418
|
+
form.set("repoName", input.repoName);
|
|
1419
|
+
form.set("private", "true");
|
|
1420
|
+
form.set("branch", input.branch ?? "main");
|
|
1421
|
+
form.set("commitMessage", input.commitMessage ?? "Deploy from mcp-use CLI");
|
|
1422
|
+
if (input.port != null) form.set("port", String(input.port));
|
|
1423
|
+
if (input.env && Object.keys(input.env).length > 0) {
|
|
1424
|
+
form.set("env", JSON.stringify(input.env));
|
|
1425
|
+
}
|
|
1426
|
+
return this.uploadMultipart("/servers", form);
|
|
1427
|
+
}
|
|
1428
|
+
/** Push a new source tarball as a commit on an existing server's repo. */
|
|
1429
|
+
async pushSourceToServer(serverId, input) {
|
|
1430
|
+
const form = new FormData();
|
|
1431
|
+
form.set(
|
|
1432
|
+
"sourceFile",
|
|
1433
|
+
new Blob([new Uint8Array(input.tarball)], { type: "application/gzip" }),
|
|
1434
|
+
"source.tar.gz"
|
|
1435
|
+
);
|
|
1436
|
+
form.set("branch", input.branch ?? "main");
|
|
1437
|
+
form.set(
|
|
1438
|
+
"commitMessage",
|
|
1439
|
+
input.commitMessage ?? "Redeploy from mcp-use CLI"
|
|
1440
|
+
);
|
|
1441
|
+
return this.uploadMultipart(
|
|
1442
|
+
`/servers/${encodeURIComponent(serverId)}/source`,
|
|
1443
|
+
form
|
|
1444
|
+
);
|
|
1445
|
+
}
|
|
1372
1446
|
async listServers(params) {
|
|
1373
1447
|
const response = await this.request(`/servers${buildPaginationQuery(params)}`);
|
|
1374
1448
|
return normalizePaginatedResponse(response, params);
|
|
@@ -1687,7 +1761,7 @@ async function loginCommand(options) {
|
|
|
1687
1761
|
}
|
|
1688
1762
|
return;
|
|
1689
1763
|
}
|
|
1690
|
-
if (await isLoggedIn()) {
|
|
1764
|
+
if (!options?.deviceCode && await isLoggedIn()) {
|
|
1691
1765
|
let needsReauth = false;
|
|
1692
1766
|
try {
|
|
1693
1767
|
await (await McpUseAPI.create()).testAuth();
|
|
@@ -1717,29 +1791,33 @@ async function loginCommand(options) {
|
|
|
1717
1791
|
}
|
|
1718
1792
|
console.log(source_default.cyan.bold("Logging in to Manufact cloud...\n"));
|
|
1719
1793
|
const authBaseUrl = await getAuthBaseUrl();
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1794
|
+
let device_code;
|
|
1795
|
+
let interval;
|
|
1796
|
+
if (options?.deviceCode) {
|
|
1797
|
+
device_code = options.deviceCode.trim();
|
|
1798
|
+
interval = 2;
|
|
1799
|
+
console.log(source_default.gray(" Authenticating with provided device code..."));
|
|
1800
|
+
} else {
|
|
1801
|
+
const deviceResp = await requestDeviceCode(authBaseUrl);
|
|
1802
|
+
device_code = deviceResp.device_code;
|
|
1803
|
+
interval = deviceResp.interval || 5;
|
|
1804
|
+
const { user_code, verification_uri, verification_uri_complete } = deviceResp;
|
|
1805
|
+
const displayCode = user_code.length === 8 ? `${user_code.slice(0, 4)}-${user_code.slice(4)}` : user_code;
|
|
1806
|
+
console.log(source_default.white(" Visit: ") + source_default.cyan(verification_uri));
|
|
1807
|
+
console.log(source_default.white(" Code: ") + source_default.bold.white(displayCode));
|
|
1808
|
+
console.log();
|
|
1809
|
+
const urlToOpen = verification_uri_complete || verification_uri;
|
|
1810
|
+
try {
|
|
1811
|
+
await open_default(urlToOpen);
|
|
1812
|
+
console.log(source_default.gray(" Browser opened. Waiting for approval..."));
|
|
1813
|
+
} catch {
|
|
1814
|
+
console.log(source_default.gray(" Open the URL above in your browser."));
|
|
1815
|
+
}
|
|
1738
1816
|
}
|
|
1739
1817
|
const accessToken = await pollForDeviceToken(
|
|
1740
1818
|
authBaseUrl,
|
|
1741
1819
|
device_code,
|
|
1742
|
-
interval
|
|
1820
|
+
interval
|
|
1743
1821
|
);
|
|
1744
1822
|
console.log(source_default.gray("\n Creating persistent API key..."));
|
|
1745
1823
|
const api = await McpUseAPI.create();
|
|
@@ -4699,6 +4777,49 @@ ${MCP_USE_DIR}
|
|
|
4699
4777
|
}
|
|
4700
4778
|
}
|
|
4701
4779
|
|
|
4780
|
+
// src/utils/tarball.ts
|
|
4781
|
+
import { create } from "tar";
|
|
4782
|
+
var EXCLUDE_DIRS = /* @__PURE__ */ new Set([
|
|
4783
|
+
".git",
|
|
4784
|
+
"node_modules",
|
|
4785
|
+
"dist",
|
|
4786
|
+
"build",
|
|
4787
|
+
".next",
|
|
4788
|
+
".turbo",
|
|
4789
|
+
".vercel",
|
|
4790
|
+
".cache",
|
|
4791
|
+
"coverage",
|
|
4792
|
+
".mcp-use"
|
|
4793
|
+
]);
|
|
4794
|
+
async function packProjectTarball(projectDir, prefix = "app") {
|
|
4795
|
+
const stream = create(
|
|
4796
|
+
{
|
|
4797
|
+
gzip: true,
|
|
4798
|
+
cwd: projectDir,
|
|
4799
|
+
prefix,
|
|
4800
|
+
portable: true,
|
|
4801
|
+
filter: (entryPath) => {
|
|
4802
|
+
const segments = entryPath.split(/[/\\]/).filter((s) => s && s !== ".");
|
|
4803
|
+
if (segments.some((seg) => EXCLUDE_DIRS.has(seg))) return false;
|
|
4804
|
+
const base = segments[segments.length - 1] ?? "";
|
|
4805
|
+
if (base === ".DS_Store") return false;
|
|
4806
|
+
if (base === ".env" || base.startsWith(".env.")) return false;
|
|
4807
|
+
return true;
|
|
4808
|
+
}
|
|
4809
|
+
},
|
|
4810
|
+
["."]
|
|
4811
|
+
);
|
|
4812
|
+
const chunks = [];
|
|
4813
|
+
for await (const chunk of stream) {
|
|
4814
|
+
chunks.push(Buffer.from(chunk));
|
|
4815
|
+
}
|
|
4816
|
+
return Buffer.concat(chunks);
|
|
4817
|
+
}
|
|
4818
|
+
function sanitizeRepoName(name) {
|
|
4819
|
+
const cleaned = name.trim().replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^[-.]+|[-.]+$/g, "").slice(0, 80);
|
|
4820
|
+
return cleaned || "mcp-server";
|
|
4821
|
+
}
|
|
4822
|
+
|
|
4702
4823
|
// src/commands/deploy.ts
|
|
4703
4824
|
async function parseEnvFile(filePath) {
|
|
4704
4825
|
try {
|
|
@@ -5200,6 +5321,106 @@ Opening browser...`));
|
|
|
5200
5321
|
return { ok: false, api: client };
|
|
5201
5322
|
}
|
|
5202
5323
|
}
|
|
5324
|
+
async function deployViaManagedUpload(api, options, ctx) {
|
|
5325
|
+
const { cwd, organizationId } = ctx;
|
|
5326
|
+
const projectDir = options.rootDir ? path8.resolve(cwd, options.rootDir) : cwd;
|
|
5327
|
+
try {
|
|
5328
|
+
await fs9.access(projectDir);
|
|
5329
|
+
} catch {
|
|
5330
|
+
console.log(source_default.red(`\u2717 Project directory not found: ${projectDir}`));
|
|
5331
|
+
process.exit(1);
|
|
5332
|
+
}
|
|
5333
|
+
const isMcp = await isMcpProject(projectDir);
|
|
5334
|
+
if (!isMcp && !options.yes) {
|
|
5335
|
+
console.log(
|
|
5336
|
+
source_default.yellow("\u26A0\uFE0F This doesn't look like an MCP server project.")
|
|
5337
|
+
);
|
|
5338
|
+
const shouldContinue = await prompt(
|
|
5339
|
+
source_default.white("Continue anyway? (y/n): ")
|
|
5340
|
+
);
|
|
5341
|
+
if (!shouldContinue) process.exit(0);
|
|
5342
|
+
console.log();
|
|
5343
|
+
}
|
|
5344
|
+
const envVars = await buildEnvVars(options);
|
|
5345
|
+
const branch = "main";
|
|
5346
|
+
const projectName = options.name || await getProjectName(projectDir);
|
|
5347
|
+
console.log(source_default.gray("Packaging project source..."));
|
|
5348
|
+
const tarball = await packProjectTarball(projectDir);
|
|
5349
|
+
console.log(
|
|
5350
|
+
source_default.gray(
|
|
5351
|
+
` Archive size: ${(tarball.length / 1024 / 1024).toFixed(2)} MB`
|
|
5352
|
+
)
|
|
5353
|
+
);
|
|
5354
|
+
if (tarball.length > 80 * 1024 * 1024) {
|
|
5355
|
+
console.log(
|
|
5356
|
+
source_default.red(
|
|
5357
|
+
"\u2717 Project archive exceeds 80 MB. Add large/derived files to .gitignore and retry."
|
|
5358
|
+
)
|
|
5359
|
+
);
|
|
5360
|
+
process.exit(1);
|
|
5361
|
+
}
|
|
5362
|
+
const existingLink = !options.new ? await getProjectLink(cwd) : null;
|
|
5363
|
+
let serverId = existingLink?.serverId;
|
|
5364
|
+
if (serverId) {
|
|
5365
|
+
try {
|
|
5366
|
+
const linked = await api.getServer(serverId);
|
|
5367
|
+
if (linked.organizationId !== organizationId) serverId = void 0;
|
|
5368
|
+
} catch {
|
|
5369
|
+
serverId = void 0;
|
|
5370
|
+
}
|
|
5371
|
+
}
|
|
5372
|
+
let deploymentId;
|
|
5373
|
+
if (serverId) {
|
|
5374
|
+
console.log(source_default.gray("Uploading source and redeploying..."));
|
|
5375
|
+
if (Object.keys(envVars).length > 0) {
|
|
5376
|
+
await syncEnvVarsToServer(api, serverId, envVars);
|
|
5377
|
+
}
|
|
5378
|
+
await api.pushSourceToServer(serverId, {
|
|
5379
|
+
tarball,
|
|
5380
|
+
branch,
|
|
5381
|
+
commitMessage: "Redeploy from mcp-use CLI"
|
|
5382
|
+
});
|
|
5383
|
+
const dep = await api.createDeployment({
|
|
5384
|
+
serverId,
|
|
5385
|
+
branch,
|
|
5386
|
+
trigger: "redeploy"
|
|
5387
|
+
});
|
|
5388
|
+
deploymentId = dep.id;
|
|
5389
|
+
await saveProjectLink(cwd, {
|
|
5390
|
+
deploymentId: dep.id,
|
|
5391
|
+
deploymentName: projectName,
|
|
5392
|
+
serverId,
|
|
5393
|
+
linkedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5394
|
+
});
|
|
5395
|
+
} else {
|
|
5396
|
+
console.log(source_default.gray("Uploading source (no GitHub required)..."));
|
|
5397
|
+
const result = await api.createServerFromManagedUpload({
|
|
5398
|
+
organizationId,
|
|
5399
|
+
name: projectName,
|
|
5400
|
+
repoName: sanitizeRepoName(projectName),
|
|
5401
|
+
tarball,
|
|
5402
|
+
branch,
|
|
5403
|
+
commitMessage: "Deploy from mcp-use CLI",
|
|
5404
|
+
port: options.port,
|
|
5405
|
+
env: Object.keys(envVars).length > 0 ? envVars : void 0
|
|
5406
|
+
});
|
|
5407
|
+
deploymentId = result.deploymentId ?? void 0;
|
|
5408
|
+
if (result.server?.id && deploymentId) {
|
|
5409
|
+
await saveProjectLink(cwd, {
|
|
5410
|
+
deploymentId,
|
|
5411
|
+
deploymentName: projectName,
|
|
5412
|
+
serverId: result.server.id,
|
|
5413
|
+
linkedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5414
|
+
});
|
|
5415
|
+
}
|
|
5416
|
+
}
|
|
5417
|
+
if (!deploymentId) {
|
|
5418
|
+
console.log(source_default.red("\u2717 No deployment was created."));
|
|
5419
|
+
process.exit(1);
|
|
5420
|
+
}
|
|
5421
|
+
console.log(source_default.green("\u2713 Deployment created: ") + source_default.gray(deploymentId));
|
|
5422
|
+
await displayDeploymentProgress(api, deploymentId, { yes: options.yes });
|
|
5423
|
+
}
|
|
5203
5424
|
async function deployCommand(options) {
|
|
5204
5425
|
try {
|
|
5205
5426
|
const cwd = process.cwd();
|
|
@@ -5317,6 +5538,22 @@ async function deployCommand(options) {
|
|
|
5317
5538
|
}
|
|
5318
5539
|
api = await ensureApiSessionForDeploy(api, options, resolvedOrgId);
|
|
5319
5540
|
console.log(source_default.cyan.bold("\n\u{1F680} Deploying to Manufact cloud...\n"));
|
|
5541
|
+
let useNoGithubDeploy = !!options.noGithub;
|
|
5542
|
+
if (!useNoGithubDeploy && !options.new) {
|
|
5543
|
+
const link = await getProjectLink(cwd);
|
|
5544
|
+
if (link?.serverId) {
|
|
5545
|
+
try {
|
|
5546
|
+
const linked = await api.getServer(link.serverId);
|
|
5547
|
+
if (linked.connectedRepository?.isManaged) useNoGithubDeploy = true;
|
|
5548
|
+
} catch {
|
|
5549
|
+
}
|
|
5550
|
+
}
|
|
5551
|
+
}
|
|
5552
|
+
if (useNoGithubDeploy) {
|
|
5553
|
+
const organizationId = resolvedOrgId ?? await api.resolveOrganizationId();
|
|
5554
|
+
await deployViaManagedUpload(api, options, { cwd, organizationId });
|
|
5555
|
+
return;
|
|
5556
|
+
}
|
|
5320
5557
|
const reauth = () => promptReauthenticateOn401(options, resolvedOrgId);
|
|
5321
5558
|
let ghConn = await getGitHubConnectionStatusWith401Retry(
|
|
5322
5559
|
api,
|
|
@@ -9381,18 +9618,27 @@ Looked for:
|
|
|
9381
9618
|
program.command("login").description("Login to Manufact cloud").option(
|
|
9382
9619
|
"--api-key <key>",
|
|
9383
9620
|
"Login with an API key directly (non-interactive, for CI/CD)"
|
|
9384
|
-
).option("--org <slug|id|name>", "Select an organization non-interactively").
|
|
9385
|
-
|
|
9386
|
-
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
-
|
|
9393
|
-
|
|
9621
|
+
).option("--org <slug|id|name>", "Select an organization non-interactively").option(
|
|
9622
|
+
"--device-code <code>",
|
|
9623
|
+
"Authenticate with a pre-approved device code (non-interactive; e.g. from the web onboarding flow)"
|
|
9624
|
+
).action(
|
|
9625
|
+
async (opts) => {
|
|
9626
|
+
try {
|
|
9627
|
+
await loginCommand({
|
|
9628
|
+
apiKey: opts.apiKey,
|
|
9629
|
+
org: opts.org,
|
|
9630
|
+
deviceCode: opts.deviceCode
|
|
9631
|
+
});
|
|
9632
|
+
process.exit(0);
|
|
9633
|
+
} catch (error) {
|
|
9634
|
+
console.error(
|
|
9635
|
+
source_default.red.bold("\n\u2717 Login failed:"),
|
|
9636
|
+
source_default.red(error instanceof Error ? error.message : "Unknown error")
|
|
9637
|
+
);
|
|
9638
|
+
process.exit(1);
|
|
9639
|
+
}
|
|
9394
9640
|
}
|
|
9395
|
-
|
|
9641
|
+
);
|
|
9396
9642
|
program.command("logout").description("Logout from Manufact cloud").action(async () => {
|
|
9397
9643
|
await logoutCommand();
|
|
9398
9644
|
});
|
|
@@ -9427,6 +9673,9 @@ program.command("deploy").description("Deploy MCP server from GitHub to Manufact
|
|
|
9427
9673
|
).option(
|
|
9428
9674
|
"--start-command <cmd>",
|
|
9429
9675
|
"Custom start command (overrides auto-detection)"
|
|
9676
|
+
).option(
|
|
9677
|
+
"--no-github",
|
|
9678
|
+
"Upload local source without connecting GitHub (repo hosted in the platform-managed org)"
|
|
9430
9679
|
).action(async (options) => {
|
|
9431
9680
|
await deployCommand({
|
|
9432
9681
|
open: options.open,
|
|
@@ -9441,7 +9690,8 @@ program.command("deploy").description("Deploy MCP server from GitHub to Manufact
|
|
|
9441
9690
|
yes: options.yes,
|
|
9442
9691
|
region: options.region,
|
|
9443
9692
|
buildCommand: options.buildCommand,
|
|
9444
|
-
startCommand: options.startCommand
|
|
9693
|
+
startCommand: options.startCommand,
|
|
9694
|
+
noGithub: options.github === false
|
|
9445
9695
|
});
|
|
9446
9696
|
});
|
|
9447
9697
|
program.addCommand(createClientCommand());
|