@mcp-use/cli 3.5.2-canary.1 → 3.5.2-canary.11

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 CHANGED
@@ -464,7 +464,7 @@ For deploying to Manufact cloud, see the environment variables in this section f
464
464
  MCP_WEB_URL=https://mcp-use.com
465
465
 
466
466
  # Backend API URL (where /api/v1 endpoints are)
467
- MCP_API_URL=https://cloud.mcp-use.com
467
+ MCP_API_URL=https://cloud.manufact.com
468
468
 
469
469
  # Example: Local development
470
470
  export MCP_WEB_URL=http://localhost:3000
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/commands/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqDpC;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,aAMtC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,aAQ5B,CAAC;AAqhCH;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAyC7C;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CA2H5D"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/commands/client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqDpC;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,aAMtC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,aAQ5B,CAAC;AA8iCH;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAyC7C;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CA2H5D"}
@@ -30,6 +30,8 @@ interface DeployOptions {
30
30
  region?: "US" | "EU" | "APAC";
31
31
  buildCommand?: string;
32
32
  startCommand?: string;
33
+ /** Path to a non-default Dockerfile (relative to rootDir / repo root). */
34
+ dockerfile?: string;
33
35
  /**
34
36
  * Deploy branch. Defaults to the current git branch (managed flow: "main").
35
37
  * Also scopes env-var sync to that branch's preview env.
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,cAAc,EAGf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAGL,SAAS,EACV,MAAM,iBAAiB,CAAC;AAgGzB;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,SAAS,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,cAAc,EAAE,CAAA;CAAE,GAC1D,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAiC/C;AA0CD,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC5B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA8nBD,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA2xBzE"}
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,cAAc,EAGf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAGL,SAAS,EACV,MAAM,iBAAiB,CAAC;AAgGzB;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,SAAS,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,cAAc,EAAE,CAAA;CAAE,GAC1D,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAiC/C;AA0CD,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC5B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAynBD,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAgyBzE"}
package/dist/index.cjs CHANGED
@@ -1156,7 +1156,7 @@ var import_node_os3 = __toESM(require("os"), 1);
1156
1156
  var import_node_path2 = __toESM(require("path"), 1);
1157
1157
  var CONFIG_DIR = import_node_path2.default.join(import_node_os3.default.homedir(), ".mcp-use");
1158
1158
  var CONFIG_FILE = import_node_path2.default.join(CONFIG_DIR, "config.json");
1159
- var DEFAULT_API_URL = process.env.MCP_API_URL ? process.env.MCP_API_URL.replace(/\/api\/v1$/, "") + "/api/v1" : "https://cloud.mcp-use.com/api/v1";
1159
+ var DEFAULT_API_URL = process.env.MCP_API_URL ? process.env.MCP_API_URL.replace(/\/api\/v1$/, "") + "/api/v1" : "https://cloud.manufact.com/api/v1";
1160
1160
  var DEFAULT_WEB_URL = process.env.MCP_WEB_URL ? process.env.MCP_WEB_URL : "https://manufact.com";
1161
1161
  async function ensureConfigDir() {
1162
1162
  try {
@@ -1570,37 +1570,51 @@ var McpUseAPI = class _McpUseAPI {
1570
1570
  }))
1571
1571
  };
1572
1572
  }
1573
- async getGitHubRepos(_refresh) {
1574
- const orgId = await this.resolveOrganizationId();
1575
- const installResp = await this.request(`/github/installations?organizationId=${orgId}`);
1576
- if (installResp.installations.length === 0) {
1577
- return { user: { login: "", id: 0, avatar_url: "" }, repos: [] };
1573
+ /**
1574
+ * Returns true if the GitHub App can access `${owner}/${repo}` via any of the
1575
+ * organization's installations.
1576
+ *
1577
+ * An organization can have multiple GitHub installations (e.g. a personal
1578
+ * account and one or more GitHub orgs), so we check across all of them.
1579
+ *
1580
+ * Each check is a single authoritative backend call (`repos.get` with the
1581
+ * installation token) rather than listing repos. The old listing approach
1582
+ * only returned the first page — so a repo on a later page was wrongly
1583
+ * reported inaccessible — and fully paginating it hung on very large orgs.
1584
+ * We try the installation whose account matches the repo owner first to
1585
+ * minimize GitHub calls.
1586
+ */
1587
+ async checkGitHubRepoAccess(owner, repo) {
1588
+ const status = await this.getGitHubConnectionStatus();
1589
+ const installations = status.installations ?? [];
1590
+ if (installations.length === 0) return false;
1591
+ const ownerLower = owner.toLowerCase();
1592
+ const ordered = [...installations].sort((a, b) => {
1593
+ const aMatch = a.account_login.toLowerCase() === ownerLower ? 0 : 1;
1594
+ const bMatch = b.account_login.toLowerCase() === ownerLower ? 0 : 1;
1595
+ return aMatch - bMatch;
1596
+ });
1597
+ for (const installation of ordered) {
1598
+ const hasAccess = await this.installationCanAccessRepo(
1599
+ installation.installation_id,
1600
+ owner,
1601
+ repo
1602
+ );
1603
+ if (hasAccess) return true;
1604
+ }
1605
+ return false;
1606
+ }
1607
+ async installationCanAccessRepo(installationId, owner, repo) {
1608
+ try {
1609
+ const resp = await this.request(
1610
+ `/github/installations/${installationId}/repos/${encodeURIComponent(
1611
+ owner
1612
+ )}/${encodeURIComponent(repo)}/access`
1613
+ );
1614
+ return resp.hasAccess;
1615
+ } catch {
1616
+ return false;
1578
1617
  }
1579
- const inst = installResp.installations[0];
1580
- const repoLists = await Promise.all(
1581
- installResp.installations.map(async (installation) => {
1582
- try {
1583
- const reposResp = await this.request(`/github/installations/${installation.installationId}/repos`);
1584
- return reposResp.repos;
1585
- } catch {
1586
- return [];
1587
- }
1588
- })
1589
- );
1590
- return {
1591
- user: {
1592
- login: inst.account?.login ?? "",
1593
- id: 0,
1594
- avatar_url: inst.account?.avatar_url ?? ""
1595
- },
1596
- repos: repoLists.flat().map((r) => ({
1597
- id: r.id,
1598
- name: r.name,
1599
- full_name: r.fullName,
1600
- private: r.private,
1601
- owner: { login: r.fullName.split("/")[0] ?? "" }
1602
- }))
1603
- };
1604
1618
  }
1605
1619
  async getGitHubAppName() {
1606
1620
  if (process.env.MCP_GITHUB_APP_NAME) return process.env.MCP_GITHUB_APP_NAME;
@@ -4032,6 +4046,71 @@ async function describeToolCommand(name, toolName) {
4032
4046
  }
4033
4047
  await cleanupAndExit(0);
4034
4048
  }
4049
+ async function processToolScreenshot(session, toolName, args, callResult, options) {
4050
+ const toolWithMeta = session.tools.find((t) => t.name === toolName);
4051
+ const resourceUri = detectToolResourceUri(toolWithMeta);
4052
+ const wantsScreenshot = options?.screenshot === true || options?.screenshotOutput !== void 0 || options?.screenshotDeviceScaleFactor !== void 0;
4053
+ let screenshot = null;
4054
+ let screenshotError = null;
4055
+ let widgetHintUri = null;
4056
+ if (resourceUri) {
4057
+ if (wantsScreenshot) {
4058
+ console.error(
4059
+ formatInfo(`Capturing widget screenshot (${resourceUri})...`)
4060
+ );
4061
+ try {
4062
+ const screenshotOpts = {};
4063
+ if (options?.screenshotOutput) {
4064
+ screenshotOpts.output = options.screenshotOutput;
4065
+ }
4066
+ if (options?.screenshotDeviceScaleFactor) {
4067
+ screenshotOpts.deviceScaleFactor = parseDeviceScaleFactor(
4068
+ options.screenshotDeviceScaleFactor
4069
+ );
4070
+ }
4071
+ const shot = await captureToolScreenshot(
4072
+ {
4073
+ session,
4074
+ toolName,
4075
+ toolArgs: args,
4076
+ toolOutput: callResult,
4077
+ resourceUri
4078
+ },
4079
+ screenshotOpts
4080
+ );
4081
+ screenshot = {
4082
+ path: shot.outputPath,
4083
+ width: shot.width,
4084
+ height: shot.height,
4085
+ view: shot.view
4086
+ };
4087
+ } catch (err) {
4088
+ screenshotError = err?.message ?? String(err);
4089
+ }
4090
+ } else {
4091
+ widgetHintUri = resourceUri;
4092
+ }
4093
+ }
4094
+ if (screenshot) {
4095
+ console.error(
4096
+ formatSuccess(
4097
+ `Saved widget screenshot: ${screenshot.path} (${screenshot.width}\xD7${screenshot.height})`
4098
+ )
4099
+ );
4100
+ }
4101
+ if (screenshotError) {
4102
+ console.error(
4103
+ formatWarning(`Skipped widget screenshot: ${screenshotError}`)
4104
+ );
4105
+ }
4106
+ if (widgetHintUri) {
4107
+ console.error(
4108
+ formatInfo(
4109
+ `This tool renders a widget (${widgetHintUri}). Re-run with --screenshot to save a PNG of it.`
4110
+ )
4111
+ );
4112
+ }
4113
+ }
4035
4114
  async function callToolCommand(name, toolName, argsList, options) {
4036
4115
  try {
4037
4116
  const result = await getOrRestoreSession(name);
@@ -4081,74 +4160,12 @@ async function callToolCommand(name, toolName, argsList, options) {
4081
4160
  const callResult = await session.callTool(toolName, args, {
4082
4161
  timeout: options?.timeout
4083
4162
  });
4084
- const toolWithMeta = session.tools.find((t) => t.name === toolName);
4085
- const resourceUri = detectToolResourceUri(toolWithMeta);
4086
- const wantsScreenshot = options?.screenshot === true || options?.screenshotOutput !== void 0 || options?.screenshotDeviceScaleFactor !== void 0;
4087
- let screenshot = null;
4088
- let screenshotError = null;
4089
- let widgetHintUri = null;
4090
- if (resourceUri) {
4091
- if (wantsScreenshot) {
4092
- console.error(
4093
- formatInfo(`Capturing widget screenshot (${resourceUri})...`)
4094
- );
4095
- try {
4096
- const screenshotOpts = {};
4097
- if (options?.screenshotOutput) {
4098
- screenshotOpts.output = options.screenshotOutput;
4099
- }
4100
- if (options?.screenshotDeviceScaleFactor) {
4101
- screenshotOpts.deviceScaleFactor = parseDeviceScaleFactor(
4102
- options.screenshotDeviceScaleFactor
4103
- );
4104
- }
4105
- const shot = await captureToolScreenshot(
4106
- {
4107
- session,
4108
- toolName,
4109
- toolArgs: args,
4110
- toolOutput: callResult,
4111
- resourceUri
4112
- },
4113
- screenshotOpts
4114
- );
4115
- screenshot = {
4116
- path: shot.outputPath,
4117
- width: shot.width,
4118
- height: shot.height,
4119
- view: shot.view
4120
- };
4121
- } catch (err) {
4122
- screenshotError = err?.message ?? String(err);
4123
- }
4124
- } else {
4125
- widgetHintUri = resourceUri;
4126
- }
4127
- }
4163
+ await processToolScreenshot(session, toolName, args, callResult, options);
4128
4164
  if (options?.json) {
4129
4165
  console.log(formatJson(callResult));
4130
4166
  } else {
4131
4167
  console.log(formatToolCall(callResult));
4132
4168
  }
4133
- if (screenshot) {
4134
- console.error(
4135
- formatSuccess(
4136
- `Saved widget screenshot: ${screenshot.path} (${screenshot.width}\xD7${screenshot.height})`
4137
- )
4138
- );
4139
- }
4140
- if (screenshotError) {
4141
- console.error(
4142
- formatWarning(`Skipped widget screenshot: ${screenshotError}`)
4143
- );
4144
- }
4145
- if (widgetHintUri) {
4146
- console.error(
4147
- formatInfo(
4148
- `This tool renders a widget (${widgetHintUri}). Re-run with --screenshot to save a PNG of it.`
4149
- )
4150
- );
4151
- }
4152
4169
  if (callResult.isError) {
4153
4170
  await cleanupAndExit(1);
4154
4171
  }
@@ -4240,6 +4257,14 @@ async function subscribeResourceCommand(name, uri) {
4240
4257
  }
4241
4258
  });
4242
4259
  console.log(formatInfo("Listening for updates... (Press Ctrl+C to stop)"));
4260
+ process.once("SIGINT", async () => {
4261
+ console.log(formatInfo("\nUnsubscribing and shutting down..."));
4262
+ try {
4263
+ await session.unsubscribeFromResource(uri);
4264
+ } catch (e) {
4265
+ }
4266
+ await cleanupAndExit(0);
4267
+ });
4243
4268
  await new Promise(() => {
4244
4269
  });
4245
4270
  } catch (error) {
@@ -4370,7 +4395,7 @@ async function interactiveCommand(name) {
4370
4395
  console.log(source_default.gray(" tools list - List available tools"));
4371
4396
  console.log(
4372
4397
  source_default.gray(
4373
- " tools call <name> - Call a tool (will prompt for args)"
4398
+ " tools call <name> [--screenshot] - Call a tool (will prompt for args)"
4374
4399
  )
4375
4400
  );
4376
4401
  console.log(source_default.gray(" tools describe <name> - Show tool details"));
@@ -4417,6 +4442,7 @@ async function interactiveCommand(name) {
4417
4442
  )
4418
4443
  );
4419
4444
  } else if (command === "call" && arg) {
4445
+ const wantsScreenshot = parts.includes("--screenshot");
4420
4446
  rl.question(
4421
4447
  "Arguments (JSON, or press Enter for none): ",
4422
4448
  async (argsInput) => {
@@ -4424,6 +4450,9 @@ async function interactiveCommand(name) {
4424
4450
  const args = argsInput.trim() ? JSON.parse(argsInput) : {};
4425
4451
  const result2 = await session.callTool(arg, args);
4426
4452
  console.log(formatToolCall(result2));
4453
+ await processToolScreenshot(session, arg, args, result2, {
4454
+ screenshot: wantsScreenshot
4455
+ });
4427
4456
  } catch (error) {
4428
4457
  console.error(formatError(error.message));
4429
4458
  }
@@ -5251,12 +5280,7 @@ async function getGitHubConnectionStatusWith401Retry(api, options, orgIdToRestor
5251
5280
  throw new Error("Unreachable");
5252
5281
  }
5253
5282
  async function checkRepoAccess(api, owner, repo) {
5254
- try {
5255
- const resp = await api.getGitHubRepos(true);
5256
- return resp.repos.some((r) => r.full_name === `${owner}/${repo}`);
5257
- } catch {
5258
- return false;
5259
- }
5283
+ return api.checkGitHubRepoAccess(owner, repo);
5260
5284
  }
5261
5285
  async function promptGitHubInstallation(api, reason, repoName, opts) {
5262
5286
  const yes = !!opts?.yes;
@@ -5961,6 +5985,10 @@ async function deployCommand(options) {
5961
5985
  console.log(source_default.gray(` Port: `) + source_default.cyan(port));
5962
5986
  if (options.region)
5963
5987
  console.log(source_default.gray(` Region: `) + source_default.cyan(options.region));
5988
+ if (options.dockerfile)
5989
+ console.log(
5990
+ source_default.gray(` Dockerfile: `) + source_default.cyan(options.dockerfile)
5991
+ );
5964
5992
  if (options.buildCommand)
5965
5993
  console.log(
5966
5994
  source_default.gray(` Build command: `) + source_default.cyan(options.buildCommand)
@@ -6129,7 +6157,8 @@ async function deployCommand(options) {
6129
6157
  env: Object.keys(envVars).length > 0 ? envVars : void 0,
6130
6158
  region: options.region,
6131
6159
  buildCommand: options.buildCommand,
6132
- startCommand: options.startCommand
6160
+ startCommand: options.startCommand,
6161
+ dockerfilePath: options.dockerfile
6133
6162
  });
6134
6163
  deploymentId = serverResult.deploymentId ?? "";
6135
6164
  if (!deploymentId) {
@@ -9873,6 +9902,9 @@ program.command("deploy").description("Deploy MCP server from GitHub to Manufact
9873
9902
  ).option(
9874
9903
  "--start-command <cmd>",
9875
9904
  "Custom start command (overrides auto-detection)"
9905
+ ).option(
9906
+ "--dockerfile <path>",
9907
+ "Path to a non-default Dockerfile (relative to rootDir / repo root)"
9876
9908
  ).option(
9877
9909
  "--no-github",
9878
9910
  "Upload local source without connecting GitHub (repo hosted in the platform-managed org)"
@@ -9892,6 +9924,7 @@ program.command("deploy").description("Deploy MCP server from GitHub to Manufact
9892
9924
  region: options.region,
9893
9925
  buildCommand: options.buildCommand,
9894
9926
  startCommand: options.startCommand,
9927
+ dockerfile: options.dockerfile,
9895
9928
  noGithub: options.github === false
9896
9929
  });
9897
9930
  });