@mcp-use/cli 3.1.5-canary.3 → 3.2.0-canary.10

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/index.cjs CHANGED
@@ -23,7 +23,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
23
  mod
24
24
  ));
25
25
 
26
- // ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.14_tsx@4.21.0_typescript@5.9.3_yaml@2.8.3/node_modules/tsup/assets/cjs_shims.js
26
+ // ../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.9_tsx@4.21.0_typescript@5.9.3_yaml@2.8.3/node_modules/tsup/assets/cjs_shims.js
27
27
  var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
28
28
  var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
29
29
 
@@ -217,10 +217,10 @@ var ansi_styles_default = ansiStyles;
217
217
  var import_node_process = __toESM(require("process"), 1);
218
218
  var import_node_os = __toESM(require("os"), 1);
219
219
  var import_node_tty = __toESM(require("tty"), 1);
220
- function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : import_node_process.default.argv) {
220
+ function hasFlag(flag, argv2 = globalThis.Deno ? globalThis.Deno.args : import_node_process.default.argv) {
221
221
  const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
222
- const position = argv.indexOf(prefix + flag);
223
- const terminatorPosition = argv.indexOf("--");
222
+ const position = argv2.indexOf(prefix + flag);
223
+ const terminatorPosition = argv2.indexOf("--");
224
224
  return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
225
225
  }
226
226
  var { env } = import_node_process.default;
@@ -523,13 +523,13 @@ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
523
523
  var source_default = chalk;
524
524
 
525
525
  // src/index.ts
526
- var import_commander6 = require("commander");
526
+ var import_commander7 = require("commander");
527
527
  var import_config8 = require("dotenv/config");
528
- var import_node_child_process9 = require("child_process");
529
- var import_node_fs11 = require("fs");
530
- var import_promises7 = require("fs/promises");
528
+ var import_node_child_process11 = require("child_process");
529
+ var import_node_fs14 = require("fs");
530
+ var import_promises8 = require("fs/promises");
531
531
  var import_node_module2 = require("module");
532
- var import_node_path9 = __toESM(require("path"), 1);
532
+ var import_node_path12 = __toESM(require("path"), 1);
533
533
  var import_node_url3 = require("url");
534
534
 
535
535
  // ../../node_modules/.pnpm/open@11.0.0/node_modules/open/index.js
@@ -716,15 +716,15 @@ var wslDefaultBrowser = async () => {
716
716
  const { stdout } = await executePowerShell(command, { powerShellPath: psPath });
717
717
  return stdout.trim();
718
718
  };
719
- var convertWslPathToWindows = async (path8) => {
720
- if (/^[a-z]+:\/\//i.test(path8)) {
721
- return path8;
719
+ var convertWslPathToWindows = async (path11) => {
720
+ if (/^[a-z]+:\/\//i.test(path11)) {
721
+ return path11;
722
722
  }
723
723
  try {
724
- const { stdout } = await execFile2("wslpath", ["-aw", path8], { encoding: "utf8" });
724
+ const { stdout } = await execFile2("wslpath", ["-aw", path11], { encoding: "utf8" });
725
725
  return stdout.trim();
726
726
  } catch {
727
- return path8;
727
+ return path11;
728
728
  }
729
729
  };
730
730
 
@@ -1340,8 +1340,8 @@ var McpUseAPI = class _McpUseAPI {
1340
1340
  // ── Organization ID resolution ──────────────────────────────────
1341
1341
  async resolveOrganizationId() {
1342
1342
  if (this.orgId) return this.orgId;
1343
- const auth = await this.testAuth();
1344
- const id = auth.default_org_id;
1343
+ const auth2 = await this.testAuth();
1344
+ const id = auth2.default_org_id;
1345
1345
  if (!id) {
1346
1346
  throw new Error(
1347
1347
  "No organization set. Run `mcp-use org switch` or use --org to specify one."
@@ -1374,8 +1374,8 @@ var McpUseAPI = class _McpUseAPI {
1374
1374
  return this.request(`/servers${q ? `?${q}` : ""}`);
1375
1375
  }
1376
1376
  async getServer(idOrSlug) {
1377
- const path8 = encodeURIComponent(idOrSlug);
1378
- return this.request(`/servers/${path8}`);
1377
+ const path11 = encodeURIComponent(idOrSlug);
1378
+ return this.request(`/servers/${path11}`);
1379
1379
  }
1380
1380
  async deleteServer(id) {
1381
1381
  await this.request(
@@ -1875,52 +1875,110 @@ async function whoamiCommand() {
1875
1875
  }
1876
1876
 
1877
1877
  // src/commands/client.ts
1878
- var import_commander = require("commander");
1879
- var import_client = require("mcp-use/client");
1880
- var import_server = require("mcp-use/server");
1881
- var import_node_readline = require("readline");
1878
+ var import_commander2 = require("commander");
1879
+ var import_client3 = require("mcp-use/client");
1880
+ var import_node_readline2 = require("readline");
1882
1881
 
1883
1882
  // src/utils/format.ts
1884
- function formatTable(data, columns) {
1883
+ var ANSI_RE = /\x1b\[[0-9;]*m/g;
1884
+ var GUTTER = " ";
1885
+ var MIN_TRUNCATABLE_WIDTH = 8;
1886
+ var DEFAULT_MAX_WIDTH = 100;
1887
+ function stripAnsi(s) {
1888
+ return s.replace(ANSI_RE, "");
1889
+ }
1890
+ function visibleWidth(s) {
1891
+ return stripAnsi(s).length;
1892
+ }
1893
+ function padCell(s, width) {
1894
+ const w = visibleWidth(s);
1895
+ if (w >= width) return s;
1896
+ return s + " ".repeat(width - w);
1897
+ }
1898
+ function truncateCell(s, width) {
1899
+ if (width <= 0) return "";
1900
+ const plain = stripAnsi(s);
1901
+ if (plain.length <= width) return s;
1902
+ if (width === 1) return "\u2026";
1903
+ return plain.slice(0, width - 1) + "\u2026";
1904
+ }
1905
+ function formatTable(data, columns, options = {}) {
1906
+ const tsv = options.tsv ?? !process.stdout.isTTY;
1907
+ if (tsv) {
1908
+ return data.map(
1909
+ (row) => columns.map(
1910
+ (c) => stripAnsi(String(row[c.key] ?? "")).replace(/[\t\r\n]+/g, " ")
1911
+ ).join(" ")
1912
+ ).join("\n");
1913
+ }
1885
1914
  if (data.length === 0) {
1886
1915
  return source_default.gray("No items found");
1887
1916
  }
1888
- const widths = columns.map((col) => {
1889
- const maxDataWidth = Math.max(
1890
- ...data.map((row) => String(row[col.key] || "").length)
1891
- );
1892
- const headerWidth = col.header.length;
1893
- return col.width || Math.max(maxDataWidth, headerWidth, 10);
1917
+ const maxWidth = options.maxWidth ?? process.stdout.columns ?? DEFAULT_MAX_WIDTH;
1918
+ const natural = columns.map((col) => {
1919
+ const headerW = col.header.length;
1920
+ const dataW = data.reduce((m, row) => {
1921
+ return Math.max(m, visibleWidth(String(row[col.key] ?? "")));
1922
+ }, 0);
1923
+ return Math.max(headerW, dataW);
1894
1924
  });
1895
- const createRow = (values, bold = false) => {
1896
- const cells = values.map((val, i) => {
1897
- const padded = val.padEnd(widths[i]);
1898
- return bold ? source_default.bold(padded) : padded;
1899
- });
1900
- return `\u2502 ${cells.join(" \u2502 ")} \u2502`;
1901
- };
1902
- const separator = (char) => {
1903
- const parts = widths.map((w) => char.repeat(w + 2));
1904
- if (char === "\u2500") {
1905
- return `\u251C${parts.join("\u253C")}\u2524`;
1925
+ const widths = columns.map((c, i) => c.width ?? natural[i]);
1926
+ const overhead = GUTTER.length * (columns.length - 1);
1927
+ const totalWidth = () => widths.reduce((s, w) => s + w, 0) + overhead;
1928
+ if (totalWidth() > maxWidth) {
1929
+ const truncIdxs = columns.map((c, i) => c.truncate ? i : -1).filter((i) => i >= 0);
1930
+ if (truncIdxs.length > 0) {
1931
+ const fixedSum = columns.reduce(
1932
+ (s, c, i) => s + (c.truncate ? 0 : widths[i]),
1933
+ 0
1934
+ );
1935
+ const remaining = Math.max(
1936
+ truncIdxs.length * MIN_TRUNCATABLE_WIDTH,
1937
+ maxWidth - fixedSum - overhead
1938
+ );
1939
+ const truncSum = truncIdxs.reduce((s, i) => s + widths[i], 0) || 1;
1940
+ let used = 0;
1941
+ truncIdxs.forEach((i, idx) => {
1942
+ if (idx === truncIdxs.length - 1) {
1943
+ widths[i] = Math.max(MIN_TRUNCATABLE_WIDTH, remaining - used);
1944
+ } else {
1945
+ const share = Math.max(
1946
+ MIN_TRUNCATABLE_WIDTH,
1947
+ Math.floor(widths[i] / truncSum * remaining)
1948
+ );
1949
+ widths[i] = share;
1950
+ used += share;
1951
+ }
1952
+ });
1906
1953
  }
1907
- return `\u2514${parts.join("\u2534")}\u2518`;
1908
- };
1954
+ }
1909
1955
  const lines = [];
1910
- lines.push(`\u250C${widths.map((w) => "\u2500".repeat(w + 2)).join("\u252C")}\u2510`);
1911
- lines.push(
1912
- createRow(
1913
- columns.map((c) => c.header),
1914
- true
1915
- )
1916
- );
1917
- lines.push(separator("\u2500"));
1918
- data.forEach((row) => {
1919
- lines.push(createRow(columns.map((c) => String(row[c.key] || ""))));
1956
+ const headerCells = columns.map((c, i) => {
1957
+ const text = c.header.toUpperCase();
1958
+ const cell = i === columns.length - 1 ? text : padCell(text, widths[i]);
1959
+ return source_default.bold(cell);
1920
1960
  });
1921
- lines.push(separator("\u2500"));
1961
+ lines.push(headerCells.join(GUTTER).trimEnd());
1962
+ for (const row of data) {
1963
+ const cells = columns.map((c, i) => {
1964
+ let v = String(row[c.key] ?? "");
1965
+ if (visibleWidth(v) > widths[i]) {
1966
+ v = truncateCell(v, widths[i]);
1967
+ }
1968
+ return i === columns.length - 1 ? v : padCell(v, widths[i]);
1969
+ });
1970
+ lines.push(cells.join(GUTTER).trimEnd());
1971
+ }
1922
1972
  return lines.join("\n");
1923
1973
  }
1974
+ function isStdoutTty() {
1975
+ return Boolean(process.stdout.isTTY);
1976
+ }
1977
+ function formatToolMode(annotations) {
1978
+ if (annotations?.readOnlyHint === true) return source_default.green("read-only");
1979
+ if (annotations?.destructiveHint === true) return source_default.red("destructive");
1980
+ return source_default.yellow("write");
1981
+ }
1924
1982
  function formatJson(data, pretty = true) {
1925
1983
  if (pretty) {
1926
1984
  return JSON.stringify(data, null, 2);
@@ -1929,20 +1987,29 @@ function formatJson(data, pretty = true) {
1929
1987
  }
1930
1988
  function formatToolCall(result) {
1931
1989
  const lines = [];
1932
- if (result.isError) {
1990
+ const { isError, structuredContent } = result;
1991
+ const hasStructured = structuredContent !== void 0 && structuredContent !== null;
1992
+ const visibleContent = (result.content ?? []).filter(
1993
+ (item) => !hasStructured || item.type !== "text"
1994
+ );
1995
+ const hasVisibleContent = visibleContent.length > 0;
1996
+ if (isError) {
1933
1997
  lines.push(source_default.red("\u2717 Tool execution failed"));
1934
1998
  lines.push("");
1935
1999
  } else {
1936
2000
  lines.push(source_default.green("\u2713 Tool executed successfully"));
1937
2001
  lines.push("");
1938
2002
  }
1939
- if (result.content && result.content.length > 0) {
1940
- result.content.forEach((item, index) => {
1941
- if (result.content.length > 1) {
2003
+ if (hasVisibleContent) {
2004
+ if (isError) {
2005
+ lines.push(source_default.red.bold("Error details:"));
2006
+ }
2007
+ visibleContent.forEach((item, index) => {
2008
+ if (visibleContent.length > 1) {
1942
2009
  lines.push(source_default.bold(`Content ${index + 1}:`));
1943
2010
  }
1944
2011
  if (item.type === "text") {
1945
- lines.push(item.text);
2012
+ lines.push(isError ? source_default.red(item.text) : item.text);
1946
2013
  } else if (item.type === "image") {
1947
2014
  lines.push(source_default.cyan(`[Image: ${item.mimeType || "unknown type"}]`));
1948
2015
  if (item.data) {
@@ -1959,11 +2026,20 @@ function formatToolCall(result) {
1959
2026
  } else {
1960
2027
  lines.push(source_default.gray(`[Unknown content type: ${item.type}]`));
1961
2028
  }
1962
- if (index < result.content.length - 1) {
2029
+ if (index < visibleContent.length - 1) {
1963
2030
  lines.push("");
1964
2031
  }
1965
2032
  });
1966
2033
  }
2034
+ if (hasStructured) {
2035
+ if (isError) {
2036
+ lines.push(source_default.bold("Structured error data:"));
2037
+ }
2038
+ lines.push(formatJson(structuredContent));
2039
+ }
2040
+ if (isError && !hasVisibleContent && !hasStructured) {
2041
+ lines.push(source_default.gray("(no error details provided by server)"));
2042
+ }
1967
2043
  return lines.join("\n");
1968
2044
  }
1969
2045
  function formatResourceContent(content) {
@@ -2116,28 +2192,218 @@ function formatPromptMessages(messages) {
2116
2192
  return lines.join("\n");
2117
2193
  }
2118
2194
 
2195
+ // src/utils/parse-args.ts
2196
+ function parseToolArgs(rawArgs, inputSchema) {
2197
+ if (!rawArgs || rawArgs.length === 0) return {};
2198
+ if (rawArgs.length === 1) {
2199
+ const trimmed = rawArgs[0].trim();
2200
+ if (trimmed.startsWith("{")) {
2201
+ try {
2202
+ const parsed = JSON.parse(trimmed);
2203
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
2204
+ throw new Error("expected a JSON object");
2205
+ }
2206
+ return parsed;
2207
+ } catch (err) {
2208
+ throw new Error(`Invalid JSON arguments: ${err.message}`);
2209
+ }
2210
+ }
2211
+ }
2212
+ const props = inputSchema?.properties ?? {};
2213
+ const result = {};
2214
+ for (const raw of rawArgs) {
2215
+ const token = raw.startsWith("--") ? raw.slice(2) : raw;
2216
+ const jsonIdx = token.indexOf(":=");
2217
+ const eqIdx = token.indexOf("=");
2218
+ let key;
2219
+ let rawValue;
2220
+ let forceJson = false;
2221
+ if (jsonIdx !== -1 && (eqIdx === -1 || jsonIdx < eqIdx)) {
2222
+ key = token.slice(0, jsonIdx);
2223
+ rawValue = token.slice(jsonIdx + 2);
2224
+ forceJson = true;
2225
+ } else if (eqIdx !== -1) {
2226
+ key = token.slice(0, eqIdx);
2227
+ rawValue = token.slice(eqIdx + 1);
2228
+ } else {
2229
+ throw new Error(
2230
+ `Invalid argument '${raw}'. Use key=value or key:=jsonvalue.`
2231
+ );
2232
+ }
2233
+ if (!key) {
2234
+ throw new Error(`Empty key in argument '${raw}'`);
2235
+ }
2236
+ result[key] = coerceArgValue(rawValue, props[key], forceJson, key);
2237
+ }
2238
+ return result;
2239
+ }
2240
+ function coerceArgValue(value, propSchema, forceJson, key) {
2241
+ if (forceJson) {
2242
+ try {
2243
+ return JSON.parse(value);
2244
+ } catch (err) {
2245
+ throw new Error(
2246
+ `Invalid JSON value for '${key}': ${err.message}`
2247
+ );
2248
+ }
2249
+ }
2250
+ const types = Array.isArray(propSchema?.type) ? propSchema.type : propSchema?.type ? [propSchema.type] : [];
2251
+ if (types.includes("null") && (value === "null" || value === "")) {
2252
+ return null;
2253
+ }
2254
+ if (types.includes("integer")) {
2255
+ const n = Number(value);
2256
+ if (!Number.isFinite(n) || !Number.isInteger(n)) {
2257
+ throw new Error(`Expected integer for '${key}', got '${value}'`);
2258
+ }
2259
+ return n;
2260
+ }
2261
+ if (types.includes("number")) {
2262
+ const n = Number(value);
2263
+ if (!Number.isFinite(n)) {
2264
+ throw new Error(`Expected number for '${key}', got '${value}'`);
2265
+ }
2266
+ return n;
2267
+ }
2268
+ if (types.includes("boolean")) {
2269
+ if (value === "true" || value === "1") return true;
2270
+ if (value === "false" || value === "0") return false;
2271
+ throw new Error(
2272
+ `Expected boolean (true/false) for '${key}', got '${value}'`
2273
+ );
2274
+ }
2275
+ if (types.includes("array") || types.includes("object")) {
2276
+ try {
2277
+ return JSON.parse(value);
2278
+ } catch (err) {
2279
+ const wanted = types.includes("array") ? "array" : "object";
2280
+ throw new Error(
2281
+ `Expected JSON ${wanted} for '${key}'. Tip: use ${key}:=<json>. ${err.message}`
2282
+ );
2283
+ }
2284
+ }
2285
+ return value;
2286
+ }
2287
+ function parsePromptArgs(rawArgs) {
2288
+ if (!rawArgs || rawArgs.length === 0) return {};
2289
+ if (rawArgs.length === 1) {
2290
+ const trimmed = rawArgs[0].trim();
2291
+ if (trimmed.startsWith("{")) {
2292
+ try {
2293
+ const parsed = JSON.parse(trimmed);
2294
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
2295
+ throw new Error("expected a JSON object");
2296
+ }
2297
+ const out = {};
2298
+ for (const [k, v] of Object.entries(parsed)) {
2299
+ out[k] = typeof v === "string" ? v : JSON.stringify(v);
2300
+ }
2301
+ return out;
2302
+ } catch (err) {
2303
+ throw new Error(`Invalid JSON arguments: ${err.message}`);
2304
+ }
2305
+ }
2306
+ }
2307
+ const result = {};
2308
+ for (const raw of rawArgs) {
2309
+ const token = raw.startsWith("--") ? raw.slice(2) : raw;
2310
+ const eqIdx = token.indexOf("=");
2311
+ if (eqIdx === -1) {
2312
+ throw new Error(`Invalid argument '${raw}'. Use key=value.`);
2313
+ }
2314
+ const key = token.slice(0, eqIdx);
2315
+ const value = token.slice(eqIdx + 1);
2316
+ if (!key) {
2317
+ throw new Error(`Empty key in argument '${raw}'`);
2318
+ }
2319
+ result[key] = value;
2320
+ }
2321
+ return result;
2322
+ }
2323
+
2324
+ // src/utils/oauth.ts
2325
+ var import_node = require("mcp-use/auth/node");
2326
+ var import_node_readline = require("readline");
2327
+ async function buildOAuthProvider(serverUrl, options = {}) {
2328
+ return import_node.NodeOAuthClientProvider.create(serverUrl, {
2329
+ clientName: "mcp-use CLI",
2330
+ clientUri: "https://mcp-use.com",
2331
+ storageKeyPrefix: "mcp:auth",
2332
+ ...options,
2333
+ openBrowser: async (url) => {
2334
+ console.error(`
2335
+ Open this URL in a browser to authenticate:`);
2336
+ console.error(` ${url}
2337
+ `);
2338
+ }
2339
+ });
2340
+ }
2341
+ async function runOAuthFlow(provider, serverUrl, print = console.error.bind(console)) {
2342
+ print(`\u2192 OAuth authentication required.`);
2343
+ print(
2344
+ ` Listening on http://127.0.0.1:${provider.callbackPort}/callback (waiting up to 5m)`
2345
+ );
2346
+ if (!provider.hasPendingFlow) {
2347
+ const result = await (0, import_node.auth)(provider, { serverUrl });
2348
+ if (result === "AUTHORIZED") {
2349
+ return;
2350
+ }
2351
+ if (result !== "REDIRECT") {
2352
+ throw new import_node.OAuthFlowError(
2353
+ "unexpected_auth_result",
2354
+ `auth() returned ${result}`
2355
+ );
2356
+ }
2357
+ }
2358
+ const code = await provider.getAuthorizationCode();
2359
+ await (0, import_node.auth)(provider, { serverUrl, authorizationCode: code });
2360
+ }
2361
+ function isUnauthorized(err) {
2362
+ if (err instanceof import_node.UnauthorizedError) return true;
2363
+ if (err instanceof Error && err.name === "UnauthorizedError") return true;
2364
+ if (err instanceof Error && err.code === 401) {
2365
+ return true;
2366
+ }
2367
+ return false;
2368
+ }
2369
+ async function promptYesNo(question, defaultYes = true) {
2370
+ if (!process.stdin.isTTY) return false;
2371
+ const rl = (0, import_node_readline.createInterface)({ input: process.stdin, output: process.stderr });
2372
+ try {
2373
+ const answer = await new Promise((resolve2) => {
2374
+ rl.question(`${question} ${defaultYes ? "[Y/n] " : "[y/N] "}`, resolve2);
2375
+ });
2376
+ const trimmed = answer.trim().toLowerCase();
2377
+ if (!trimmed) return defaultYes;
2378
+ return trimmed === "y" || trimmed === "yes";
2379
+ } finally {
2380
+ rl.close();
2381
+ }
2382
+ }
2383
+
2119
2384
  // src/utils/session-storage.ts
2120
2385
  var import_node_os4 = require("os");
2121
2386
  var import_node_path3 = require("path");
2122
2387
  var import_promises4 = require("fs/promises");
2123
2388
  var import_node_fs5 = require("fs");
2124
2389
  var SESSION_FILE_PATH = (0, import_node_path3.join)((0, import_node_os4.homedir)(), ".mcp-use", "cli-sessions.json");
2390
+ var _dirEnsured = false;
2125
2391
  async function ensureSessionDir() {
2126
- const dir = (0, import_node_path3.join)((0, import_node_os4.homedir)(), ".mcp-use");
2127
- if (!(0, import_node_fs5.existsSync)(dir)) {
2128
- await (0, import_promises4.mkdir)(dir, { recursive: true });
2129
- }
2392
+ if (_dirEnsured) return;
2393
+ await (0, import_promises4.mkdir)((0, import_node_path3.join)((0, import_node_os4.homedir)(), ".mcp-use"), { recursive: true });
2394
+ _dirEnsured = true;
2130
2395
  }
2131
2396
  async function loadSessions() {
2132
2397
  try {
2133
2398
  await ensureSessionDir();
2134
2399
  if (!(0, import_node_fs5.existsSync)(SESSION_FILE_PATH)) {
2135
- return { activeSession: null, sessions: {} };
2400
+ return { sessions: {} };
2136
2401
  }
2137
2402
  const content = await (0, import_promises4.readFile)(SESSION_FILE_PATH, "utf-8");
2138
- return JSON.parse(content);
2139
- } catch (error) {
2140
- return { activeSession: null, sessions: {} };
2403
+ const parsed = JSON.parse(content);
2404
+ return { sessions: parsed?.sessions ?? {} };
2405
+ } catch {
2406
+ return { sessions: {} };
2141
2407
  }
2142
2408
  }
2143
2409
  async function saveSessions(storage) {
@@ -2150,40 +2416,22 @@ async function saveSession(name, config) {
2150
2416
  ...config,
2151
2417
  lastUsed: (/* @__PURE__ */ new Date()).toISOString()
2152
2418
  };
2153
- if (!storage.activeSession) {
2154
- storage.activeSession = name;
2155
- }
2156
2419
  await saveSessions(storage);
2157
2420
  }
2158
- async function getActiveSession() {
2421
+ async function removeSession(name) {
2159
2422
  const storage = await loadSessions();
2160
- if (!storage.activeSession || !storage.sessions[storage.activeSession]) {
2161
- return null;
2162
- }
2163
- return {
2164
- name: storage.activeSession,
2165
- config: storage.sessions[storage.activeSession]
2166
- };
2423
+ delete storage.sessions[name];
2424
+ await saveSessions(storage);
2167
2425
  }
2168
2426
  async function getSession(name) {
2169
2427
  const storage = await loadSessions();
2170
2428
  return storage.sessions[name] || null;
2171
2429
  }
2172
- async function setActiveSession(name) {
2173
- const storage = await loadSessions();
2174
- if (!storage.sessions[name]) {
2175
- throw new Error(`Session '${name}' not found`);
2176
- }
2177
- storage.activeSession = name;
2178
- storage.sessions[name].lastUsed = (/* @__PURE__ */ new Date()).toISOString();
2179
- await saveSessions(storage);
2180
- }
2181
2430
  async function listAllSessions() {
2182
2431
  const storage = await loadSessions();
2183
2432
  return Object.entries(storage.sessions).map(([name, config]) => ({
2184
2433
  name,
2185
- config,
2186
- isActive: name === storage.activeSession
2434
+ config
2187
2435
  }));
2188
2436
  }
2189
2437
  async function updateSessionInfo(name, serverInfo, capabilities) {
@@ -2196,40 +2444,68 @@ async function updateSessionInfo(name, serverInfo, capabilities) {
2196
2444
  }
2197
2445
  }
2198
2446
 
2199
- // src/commands/client.ts
2447
+ // src/utils/session.ts
2448
+ var import_client = require("mcp-use/client");
2449
+ var import_server = require("mcp-use/server");
2200
2450
  var activeSessions = /* @__PURE__ */ new Map();
2201
- async function getOrRestoreSession(sessionName) {
2202
- if (!sessionName) {
2203
- const active = await getActiveSession();
2204
- if (!active) {
2205
- console.error(
2206
- formatError("No active session. Connect to a server first.")
2207
- );
2208
- console.error(
2209
- formatInfo("Use: npx mcp-use client connect <url> --name <name>")
2210
- );
2211
- return null;
2451
+ function getCliClientInfo() {
2452
+ return {
2453
+ name: "mcp-use CLI",
2454
+ title: "mcp-use CLI",
2455
+ version: (0, import_server.getPackageVersion)(),
2456
+ description: "mcp-use CLI - Command-line interface for MCP servers",
2457
+ icons: [
2458
+ {
2459
+ src: "https://manufact.com/logo.png"
2460
+ }
2461
+ ],
2462
+ websiteUrl: "https://manufact.com"
2463
+ };
2464
+ }
2465
+ async function cleanupAndExit(code) {
2466
+ for (const [name, { client }] of activeSessions) {
2467
+ try {
2468
+ await client.closeAllSessions();
2469
+ } catch {
2212
2470
  }
2213
- sessionName = active.name;
2471
+ activeSessions.delete(name);
2214
2472
  }
2473
+ process.exit(code);
2474
+ }
2475
+ async function getOrRestoreSession(sessionName) {
2215
2476
  if (activeSessions.has(sessionName)) {
2216
2477
  const { session } = activeSessions.get(sessionName);
2217
2478
  return { name: sessionName, session };
2218
2479
  }
2219
2480
  const config = await getSession(sessionName);
2220
2481
  if (!config) {
2221
- console.error(formatError(`Session '${sessionName}' not found`));
2482
+ console.error(formatError(`Server '${sessionName}' not found`));
2483
+ console.error(
2484
+ formatInfo(
2485
+ `Connect with: npx mcp-use client connect ${sessionName} <url>`
2486
+ )
2487
+ );
2222
2488
  return null;
2223
2489
  }
2224
2490
  try {
2225
2491
  const client = new import_client.MCPClient();
2226
2492
  const cliClientInfo = getCliClientInfo();
2493
+ let authProvider;
2227
2494
  if (config.type === "http") {
2228
- client.addServer(sessionName, {
2229
- url: config.url,
2230
- headers: config.authToken ? { Authorization: `Bearer ${config.authToken}` } : void 0,
2231
- clientInfo: cliClientInfo
2232
- });
2495
+ if (config.authMode === "oauth") {
2496
+ authProvider = await buildOAuthProvider(config.url);
2497
+ client.addServer(sessionName, {
2498
+ url: config.url,
2499
+ authProvider,
2500
+ clientInfo: cliClientInfo
2501
+ });
2502
+ } else {
2503
+ client.addServer(sessionName, {
2504
+ url: config.url,
2505
+ headers: config.authToken ? { Authorization: `Bearer ${config.authToken}` } : void 0,
2506
+ clientInfo: cliClientInfo
2507
+ });
2508
+ }
2233
2509
  } else if (config.type === "stdio") {
2234
2510
  client.addServer(sessionName, {
2235
2511
  command: config.command,
@@ -2241,37 +2517,1028 @@ async function getOrRestoreSession(sessionName) {
2241
2517
  console.error(formatError(`Unknown session type: ${config.type}`));
2242
2518
  return null;
2243
2519
  }
2244
- const session = await client.createSession(sessionName);
2520
+ let session;
2521
+ try {
2522
+ session = await client.createSession(sessionName);
2523
+ } catch (err) {
2524
+ if (config.type === "http" && config.authMode === "oauth" && authProvider && isUnauthorized(err)) {
2525
+ const reAuth = await promptYesNo(
2526
+ `! Tokens for server '${sessionName}' expired and could not refresh. Re-authenticate now?`,
2527
+ true
2528
+ );
2529
+ if (!reAuth) {
2530
+ console.error(formatError(`Tokens expired and could not refresh.`));
2531
+ console.error(
2532
+ formatInfo(
2533
+ `Run: mcp-use client connect ${sessionName} ${config.url}`
2534
+ )
2535
+ );
2536
+ return null;
2537
+ }
2538
+ await runOAuthFlow(authProvider, config.url);
2539
+ session = await client.createSession(sessionName);
2540
+ } else {
2541
+ throw err;
2542
+ }
2543
+ }
2245
2544
  activeSessions.set(sessionName, { client, session });
2246
- console.error(formatInfo(`Reconnected to session '${sessionName}'`));
2247
2545
  return { name: sessionName, session };
2248
2546
  } catch (error) {
2249
- console.error(formatError(`Failed to restore session: ${error.message}`));
2547
+ console.error(formatError(`Failed to restore server: ${error.message}`));
2548
+ return null;
2549
+ }
2550
+ }
2551
+
2552
+ // src/commands/client-auth.ts
2553
+ async function resolveSession(name) {
2554
+ const config = await getSession(name);
2555
+ if (!config) {
2556
+ console.error(formatError(`Server '${name}' not found`));
2557
+ return null;
2558
+ }
2559
+ if (config.type !== "http") {
2560
+ console.error(formatError("Auth commands only apply to HTTP servers"));
2561
+ return null;
2562
+ }
2563
+ if (config.authMode !== "oauth") {
2564
+ console.error(
2565
+ formatError(
2566
+ `Server '${name}' was not authenticated via OAuth (authMode=${config.authMode ?? "bearer"})`
2567
+ )
2568
+ );
2569
+ return null;
2570
+ }
2571
+ return { name, url: config.url };
2572
+ }
2573
+ function formatExpiresIn(expSec) {
2574
+ const ms = expSec * 1e3 - Date.now();
2575
+ if (ms <= 0) return "expired";
2576
+ const mins = Math.round(ms / 6e4);
2577
+ if (mins < 60) return `${mins}m`;
2578
+ const hours = Math.floor(mins / 60);
2579
+ const rem = mins % 60;
2580
+ return rem ? `${hours}h${rem}m` : `${hours}h`;
2581
+ }
2582
+ function decodeJwtExp(token) {
2583
+ try {
2584
+ const parts = token.split(".");
2585
+ if (parts.length < 2) return null;
2586
+ const payload = JSON.parse(
2587
+ Buffer.from(parts[1], "base64url").toString("utf-8")
2588
+ );
2589
+ return typeof payload.exp === "number" ? payload.exp : null;
2590
+ } catch {
2591
+ return null;
2592
+ }
2593
+ }
2594
+ async function authStatusCommand(name) {
2595
+ const target = await resolveSession(name);
2596
+ if (!target) {
2597
+ process.exit(1);
2598
+ }
2599
+ const { name: serverName, url } = target;
2600
+ const provider = await buildOAuthProvider(url);
2601
+ const tokens = await provider.tokens();
2602
+ const fields = {
2603
+ server: serverName,
2604
+ url,
2605
+ tokens: tokens?.access_token ? "present" : "missing"
2606
+ };
2607
+ if (tokens?.scope) fields.scope = tokens.scope;
2608
+ if (tokens?.access_token) {
2609
+ const exp = decodeJwtExp(tokens.access_token);
2610
+ fields.expires_in = exp ? formatExpiresIn(exp) : "unknown (opaque token)";
2611
+ }
2612
+ fields.refresh = tokens?.refresh_token ? "available" : "missing";
2613
+ console.log(formatKeyValue(fields));
2614
+ if (!tokens?.access_token) process.exit(1);
2615
+ }
2616
+ async function authRefreshCommand(name) {
2617
+ const target = await resolveSession(name);
2618
+ if (!target) {
2619
+ process.exit(1);
2620
+ }
2621
+ const { name: serverName, url } = target;
2622
+ const provider = await buildOAuthProvider(url);
2623
+ const refreshed = await provider.forceRefresh();
2624
+ if (!refreshed) {
2625
+ console.error(
2626
+ formatError(
2627
+ "Refresh failed (no refresh_token, or server rejected). Re-connect to re-authenticate."
2628
+ )
2629
+ );
2630
+ console.error(
2631
+ formatInfo(`Run: mcp-use client connect ${serverName} ${url}`)
2632
+ );
2633
+ process.exit(1);
2634
+ }
2635
+ const exp = refreshed.access_token ? decodeJwtExp(refreshed.access_token) : null;
2636
+ console.log(
2637
+ formatSuccess(
2638
+ `Refreshed access token${exp ? ` (expires in ${formatExpiresIn(exp)})` : ""}`
2639
+ )
2640
+ );
2641
+ }
2642
+ async function authLogoutCommand(name) {
2643
+ const target = await resolveSession(name);
2644
+ if (!target) {
2645
+ process.exit(1);
2646
+ }
2647
+ const { name: serverName, url } = target;
2648
+ const provider = await buildOAuthProvider(url);
2649
+ await provider.invalidateCredentials("all");
2650
+ console.log(formatSuccess(`Removed tokens for ${url}`));
2651
+ console.log(
2652
+ formatInfo(
2653
+ `Server '${serverName}' kept; reconnect with \`mcp-use client connect\`.`
2654
+ )
2655
+ );
2656
+ }
2657
+
2658
+ // src/commands/screenshot.ts
2659
+ var import_commander = require("commander");
2660
+ var import_client2 = require("mcp-use/client");
2661
+ var import_node_child_process9 = require("child_process");
2662
+ var import_node_fs8 = require("fs");
2663
+ var import_promises5 = require("fs/promises");
2664
+ var import_node_net = require("net");
2665
+ var import_node_path6 = __toESM(require("path"), 1);
2666
+
2667
+ // src/utils/cdp-screenshot.ts
2668
+ var import_node_child_process8 = require("child_process");
2669
+ var import_node_fs6 = require("fs");
2670
+ var import_node_os5 = __toESM(require("os"), 1);
2671
+ var import_node_path4 = __toESM(require("path"), 1);
2672
+ var import_ws = __toESM(require("ws"), 1);
2673
+ var CdpClient = class {
2674
+ constructor(ws) {
2675
+ this.ws = ws;
2676
+ ws.on("message", (data) => {
2677
+ let msg;
2678
+ try {
2679
+ msg = JSON.parse(data.toString());
2680
+ } catch {
2681
+ return;
2682
+ }
2683
+ if (typeof msg.id !== "number") return;
2684
+ const cb = this.pending.get(msg.id);
2685
+ if (!cb) return;
2686
+ this.pending.delete(msg.id);
2687
+ if (msg.error) {
2688
+ cb.reject(new Error(msg.error.message ?? "CDP error"));
2689
+ } else {
2690
+ cb.resolve(msg.result ?? {});
2691
+ }
2692
+ });
2693
+ ws.on("close", () => {
2694
+ for (const cb of this.pending.values()) {
2695
+ cb.reject(new Error("CDP WebSocket closed"));
2696
+ }
2697
+ this.pending.clear();
2698
+ });
2699
+ ws.on("error", (err) => {
2700
+ for (const cb of this.pending.values()) {
2701
+ cb.reject(err);
2702
+ }
2703
+ this.pending.clear();
2704
+ });
2705
+ }
2706
+ nextId = 0;
2707
+ pending = /* @__PURE__ */ new Map();
2708
+ send(method, params = {}, sessionId) {
2709
+ const id = ++this.nextId;
2710
+ const payload = { id, method, params };
2711
+ if (sessionId) payload.sessionId = sessionId;
2712
+ return new Promise((resolve2, reject) => {
2713
+ this.pending.set(id, {
2714
+ resolve: (r) => resolve2(r),
2715
+ reject
2716
+ });
2717
+ this.ws.send(JSON.stringify(payload));
2718
+ });
2719
+ }
2720
+ close() {
2721
+ try {
2722
+ this.ws.close();
2723
+ } catch {
2724
+ }
2725
+ }
2726
+ };
2727
+ function waitForDevToolsUrl(child, timeoutMs = 5e3) {
2728
+ return new Promise((resolve2, reject) => {
2729
+ let buf = "";
2730
+ const onData = (d) => {
2731
+ buf += d.toString();
2732
+ const m = buf.match(/DevTools listening on (ws:\/\/\S+)/);
2733
+ if (m) {
2734
+ cleanup();
2735
+ resolve2(m[1]);
2736
+ }
2737
+ };
2738
+ const onExit = (code) => {
2739
+ cleanup();
2740
+ reject(
2741
+ new Error(
2742
+ `Chrome exited (code ${code}) before exposing a DevTools port. Last stderr: ${buf.slice(-500)}`
2743
+ )
2744
+ );
2745
+ };
2746
+ const cleanup = () => {
2747
+ child.stderr?.off("data", onData);
2748
+ child.off("exit", onExit);
2749
+ clearTimeout(timer);
2750
+ };
2751
+ const timer = setTimeout(() => {
2752
+ cleanup();
2753
+ reject(
2754
+ new Error(`Chrome did not expose a DevTools port within ${timeoutMs}ms`)
2755
+ );
2756
+ }, timeoutMs);
2757
+ child.stderr?.on("data", onData);
2758
+ child.on("exit", onExit);
2759
+ });
2760
+ }
2761
+ async function captureScreenshot(opts) {
2762
+ let userDataDir;
2763
+ let child;
2764
+ let cdp;
2765
+ let cleanedUp = false;
2766
+ const cleanup = () => {
2767
+ if (cleanedUp) return;
2768
+ cleanedUp = true;
2769
+ cdp?.close();
2770
+ if (child && !child.killed) {
2771
+ try {
2772
+ child.kill("SIGTERM");
2773
+ } catch {
2774
+ }
2775
+ const localChild = child;
2776
+ const killTimer = setTimeout(() => {
2777
+ if (!localChild.killed) {
2778
+ try {
2779
+ localChild.kill("SIGKILL");
2780
+ } catch {
2781
+ }
2782
+ }
2783
+ }, 2e3);
2784
+ killTimer.unref();
2785
+ }
2786
+ if (userDataDir) {
2787
+ try {
2788
+ (0, import_node_fs6.rmSync)(userDataDir, { recursive: true, force: true });
2789
+ } catch {
2790
+ }
2791
+ }
2792
+ };
2793
+ try {
2794
+ let wsUrl;
2795
+ if (opts.cdpUrl) {
2796
+ wsUrl = opts.cdpUrl;
2797
+ } else {
2798
+ if (!opts.chromePath) {
2799
+ throw new Error(
2800
+ "captureScreenshot requires either `cdpUrl` or `chromePath`"
2801
+ );
2802
+ }
2803
+ userDataDir = (0, import_node_fs6.mkdtempSync)(import_node_path4.default.join(import_node_os5.default.tmpdir(), "mcp-use-chrome-"));
2804
+ const chromeArgs = [
2805
+ "--headless=new",
2806
+ "--remote-debugging-port=0",
2807
+ `--user-data-dir=${userDataDir}`,
2808
+ "--no-first-run",
2809
+ "--no-default-browser-check",
2810
+ "--disable-extensions",
2811
+ "--disable-gpu",
2812
+ "--hide-scrollbars",
2813
+ "--mute-audio",
2814
+ `--window-size=${opts.width},${opts.height}`,
2815
+ "about:blank"
2816
+ ];
2817
+ child = (0, import_node_child_process8.spawn)(opts.chromePath, chromeArgs, {
2818
+ stdio: ["ignore", "pipe", "pipe"]
2819
+ });
2820
+ child.stdout?.resume();
2821
+ wsUrl = await waitForDevToolsUrl(child);
2822
+ }
2823
+ const ws = new import_ws.default(wsUrl);
2824
+ await new Promise((resolve2, reject) => {
2825
+ const onOpen = () => {
2826
+ ws.off("error", onError);
2827
+ resolve2();
2828
+ };
2829
+ const onError = (err) => {
2830
+ ws.off("open", onOpen);
2831
+ reject(err);
2832
+ };
2833
+ ws.once("open", onOpen);
2834
+ ws.once("error", onError);
2835
+ });
2836
+ cdp = new CdpClient(ws);
2837
+ let sessionId;
2838
+ if (opts.cdpUrl) {
2839
+ const attachPromise = new Promise((resolve2, reject) => {
2840
+ const timer = setTimeout(
2841
+ () => reject(
2842
+ new Error(
2843
+ "Timed out waiting for Target.attachedToTarget event from remote CDP"
2844
+ )
2845
+ ),
2846
+ 1e4
2847
+ );
2848
+ const onMessage = (data) => {
2849
+ try {
2850
+ const msg = JSON.parse(data.toString());
2851
+ if (msg.method === "Target.attachedToTarget" && msg.params?.targetInfo?.type === "page" && typeof msg.params.sessionId === "string") {
2852
+ clearTimeout(timer);
2853
+ ws.off("message", onMessage);
2854
+ resolve2(msg.params.sessionId);
2855
+ }
2856
+ } catch {
2857
+ }
2858
+ };
2859
+ ws.on("message", onMessage);
2860
+ });
2861
+ await cdp.send("Target.setAutoAttach", {
2862
+ autoAttach: true,
2863
+ waitForDebuggerOnStart: false,
2864
+ flatten: true
2865
+ });
2866
+ sessionId = await attachPromise;
2867
+ } else {
2868
+ const { targetId } = await cdp.send(
2869
+ "Target.createTarget",
2870
+ { url: "about:blank" }
2871
+ );
2872
+ const attach = await cdp.send(
2873
+ "Target.attachToTarget",
2874
+ { targetId, flatten: true }
2875
+ );
2876
+ sessionId = attach.sessionId;
2877
+ }
2878
+ await cdp.send("Page.enable", {}, sessionId);
2879
+ await cdp.send(
2880
+ "Emulation.setDeviceMetricsOverride",
2881
+ {
2882
+ width: opts.width,
2883
+ height: opts.height,
2884
+ deviceScaleFactor: 1,
2885
+ mobile: false
2886
+ },
2887
+ sessionId
2888
+ );
2889
+ await cdp.send(
2890
+ "Emulation.setEmulatedMedia",
2891
+ {
2892
+ features: [
2893
+ { name: "prefers-color-scheme", value: opts.theme },
2894
+ { name: "prefers-reduced-motion", value: "reduce" }
2895
+ ]
2896
+ },
2897
+ sessionId
2898
+ );
2899
+ if (opts.bundle !== void 0) {
2900
+ const payload = JSON.stringify(JSON.stringify(opts.bundle));
2901
+ await cdp.send(
2902
+ "Page.addScriptToEvaluateOnNewDocument",
2903
+ {
2904
+ source: `globalThis.__mcpUsePreviewBundle = JSON.parse(${payload});`,
2905
+ runImmediately: true
2906
+ },
2907
+ sessionId
2908
+ );
2909
+ }
2910
+ await cdp.send("Page.navigate", { url: opts.url }, sessionId);
2911
+ const start = Date.now();
2912
+ const exprSelector = JSON.stringify(opts.waitForSelector);
2913
+ while (true) {
2914
+ const r = await cdp.send(
2915
+ "Runtime.evaluate",
2916
+ {
2917
+ expression: `!!document.querySelector(${exprSelector})`,
2918
+ returnByValue: true
2919
+ },
2920
+ sessionId
2921
+ );
2922
+ if (r.result?.value === true) break;
2923
+ if (Date.now() - start > opts.timeoutMs) {
2924
+ throw new Error(
2925
+ `Timed out after ${opts.timeoutMs}ms waiting for selector "${opts.waitForSelector}"`
2926
+ );
2927
+ }
2928
+ await new Promise((res) => setTimeout(res, 100));
2929
+ }
2930
+ if (opts.delayMs && opts.delayMs > 0) {
2931
+ await new Promise((res) => setTimeout(res, opts.delayMs));
2932
+ }
2933
+ const shot = await cdp.send(
2934
+ "Page.captureScreenshot",
2935
+ {
2936
+ format: "png",
2937
+ clip: {
2938
+ x: 0,
2939
+ y: 0,
2940
+ width: opts.width,
2941
+ height: opts.height,
2942
+ scale: 1
2943
+ }
2944
+ },
2945
+ sessionId
2946
+ );
2947
+ (0, import_node_fs6.writeFileSync)(opts.outputPath, Buffer.from(shot.data, "base64"));
2948
+ } finally {
2949
+ cleanup();
2950
+ }
2951
+ }
2952
+
2953
+ // src/utils/chrome-path.ts
2954
+ var import_node_fs7 = require("fs");
2955
+ var import_node_path5 = __toESM(require("path"), 1);
2956
+ var ENV_VAR_NAMES = [
2957
+ "MCP_USE_CHROME_PATH",
2958
+ "PUPPETEER_EXECUTABLE_PATH",
2959
+ "CHROME_PATH"
2960
+ ];
2961
+ var DARWIN_PATHS = [
2962
+ "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
2963
+ "/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary",
2964
+ "/Applications/Chromium.app/Contents/MacOS/Chromium",
2965
+ "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge",
2966
+ "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"
2967
+ ];
2968
+ var LINUX_BINARIES = [
2969
+ "google-chrome-stable",
2970
+ "google-chrome",
2971
+ "chromium",
2972
+ "chromium-browser",
2973
+ "microsoft-edge",
2974
+ "microsoft-edge-stable",
2975
+ "brave-browser"
2976
+ ];
2977
+ var WIN_SUBPATHS = [
2978
+ "Google\\Chrome\\Application\\chrome.exe",
2979
+ "Microsoft\\Edge\\Application\\msedge.exe",
2980
+ "BraveSoftware\\Brave-Browser\\Application\\brave.exe",
2981
+ "Chromium\\Application\\chrome.exe"
2982
+ ];
2983
+ function isAccessible(p) {
2984
+ try {
2985
+ (0, import_node_fs7.accessSync)(p, import_node_fs7.constants.F_OK);
2986
+ return true;
2987
+ } catch {
2988
+ return false;
2989
+ }
2990
+ }
2991
+ function findOnPath(binary) {
2992
+ const PATH = process.env.PATH ?? "";
2993
+ for (const dir of PATH.split(":")) {
2994
+ if (!dir) continue;
2995
+ const candidate = import_node_path5.default.posix.join(dir, binary);
2996
+ if (isAccessible(candidate)) return candidate;
2997
+ }
2998
+ return null;
2999
+ }
3000
+ function findChrome() {
3001
+ for (const name of ENV_VAR_NAMES) {
3002
+ const v = process.env[name];
3003
+ if (v && isAccessible(v)) return v;
3004
+ }
3005
+ if (process.platform === "darwin") {
3006
+ for (const p of DARWIN_PATHS) {
3007
+ if (isAccessible(p)) return p;
3008
+ }
3009
+ return null;
3010
+ }
3011
+ if (process.platform === "linux") {
3012
+ for (const bin of LINUX_BINARIES) {
3013
+ const p = findOnPath(bin);
3014
+ if (p) return p;
3015
+ }
2250
3016
  return null;
2251
3017
  }
2252
- }
2253
- function getCliClientInfo() {
2254
- return {
2255
- name: "mcp-use CLI",
2256
- title: "mcp-use CLI",
2257
- version: (0, import_server.getPackageVersion)(),
2258
- description: "mcp-use CLI - Command-line interface for MCP servers",
2259
- icons: [
2260
- {
2261
- src: "https://manufact.com/logo.png"
2262
- }
2263
- ],
2264
- websiteUrl: "https://manufact.com"
2265
- };
2266
- }
2267
- async function connectCommand(urlOrCommand, options) {
3018
+ if (process.platform === "win32") {
3019
+ const dirs = [
3020
+ process.env["ProgramFiles"],
3021
+ process.env["ProgramFiles(x86)"],
3022
+ process.env["LocalAppData"]
3023
+ ].filter((d) => Boolean(d));
3024
+ for (const dir of dirs) {
3025
+ for (const sub of WIN_SUBPATHS) {
3026
+ const candidate = import_node_path5.default.join(dir, sub);
3027
+ if (isAccessible(candidate)) return candidate;
3028
+ }
3029
+ }
3030
+ return null;
3031
+ }
3032
+ return null;
3033
+ }
3034
+ function resolveChromePath() {
3035
+ const found = findChrome();
3036
+ if (found) return found;
3037
+ throw new Error(
3038
+ "Could not find Chrome, Chromium, Edge, or Brave on this system. Install Chrome from https://google.com/chrome, or set MCP_USE_CHROME_PATH (or PUPPETEER_EXECUTABLE_PATH / CHROME_PATH) to a browser executable."
3039
+ );
3040
+ }
3041
+
3042
+ // src/commands/screenshot.ts
3043
+ function parseHeaderArg(raw) {
3044
+ const idx = raw.indexOf(":");
3045
+ if (idx === -1) {
3046
+ throw new Error(
3047
+ `Invalid --header value "${raw}". Expected "Key: Value" (e.g. "Authorization: Bearer xyz").`
3048
+ );
3049
+ }
3050
+ const key = raw.slice(0, idx).trim();
3051
+ const value = raw.slice(idx + 1).trim();
3052
+ if (!key) {
3053
+ throw new Error(`Invalid --header value "${raw}". Header name is empty.`);
3054
+ }
3055
+ return [key, value];
3056
+ }
3057
+ function parseHeaderArgs(args) {
3058
+ const headers = {};
3059
+ for (const raw of args) {
3060
+ const [key, value] = parseHeaderArg(raw);
3061
+ headers[key] = value;
3062
+ }
3063
+ return headers;
3064
+ }
3065
+ function collectHeader(value, previous = []) {
3066
+ return previous.concat([value]);
3067
+ }
3068
+ function detectToolResourceUri(tool) {
3069
+ if (!tool) return null;
3070
+ const meta = tool._meta;
3071
+ if (!meta) return null;
3072
+ const uiMeta = meta.ui ?? void 0;
3073
+ return uiMeta?.resourceUri ?? meta["openai/outputTemplate"] ?? null;
3074
+ }
3075
+ async function captureToolScreenshot(inputs, options = {}) {
3076
+ const width = options.width ?? 800;
3077
+ const height = options.height ?? 600;
3078
+ const theme = options.theme ?? "light";
3079
+ const timeoutMs = options.timeoutMs ?? 3e4;
3080
+ const delayMs = options.delayMs ?? 0;
3081
+ const chromePath = options.cdpUrl ? void 0 : resolveChromePath();
3082
+ const view = extractViewName(inputs.resourceUri);
3083
+ const devOptions = {
3084
+ width: String(width),
3085
+ height: String(height),
3086
+ theme,
3087
+ timeout: String(timeoutMs),
3088
+ inspector: options.inspector,
3089
+ quiet: options.quiet
3090
+ };
3091
+ let devHandle;
3092
+ try {
3093
+ devHandle = await ensureDevServer(devOptions);
3094
+ const resourceContents = await inputs.session.readResource(
3095
+ inputs.resourceUri
3096
+ );
3097
+ const bundle = {
3098
+ resourceUri: inputs.resourceUri,
3099
+ resourceContents,
3100
+ toolInput: inputs.toolArgs,
3101
+ toolOutput: inputs.toolOutput
3102
+ };
3103
+ const previewUrl = new URL(`/inspector/preview/${view}`, devHandle.url);
3104
+ previewUrl.searchParams.set("theme", theme);
3105
+ const ts = timestampSuffix();
3106
+ const outputPath = import_node_path6.default.resolve(options.output ?? `./${view}-${ts}.png`);
3107
+ await (0, import_promises5.mkdir)(import_node_path6.default.dirname(outputPath), { recursive: true });
3108
+ await captureScreenshot({
3109
+ url: previewUrl.toString(),
3110
+ width,
3111
+ height,
3112
+ theme,
3113
+ waitForSelector: options.waitFor ?? 'body[data-view-ready="true"]',
3114
+ timeoutMs,
3115
+ outputPath,
3116
+ chromePath,
3117
+ cdpUrl: options.cdpUrl,
3118
+ delayMs: Number.isFinite(delayMs) && delayMs > 0 ? delayMs : 0,
3119
+ bundle
3120
+ });
3121
+ return { outputPath, width, height, view };
3122
+ } finally {
3123
+ killChild(devHandle?.child);
3124
+ }
3125
+ }
3126
+ function getFreePort() {
3127
+ return new Promise((resolve2, reject) => {
3128
+ const srv = (0, import_node_net.createServer)();
3129
+ srv.unref();
3130
+ srv.on("error", reject);
3131
+ srv.listen(0, () => {
3132
+ const addr = srv.address();
3133
+ if (typeof addr === "object" && addr) {
3134
+ const port = addr.port;
3135
+ srv.close(() => resolve2(port));
3136
+ } else {
3137
+ srv.close(() => reject(new Error("Failed to allocate free port")));
3138
+ }
3139
+ });
3140
+ });
3141
+ }
3142
+ async function probeServer(url, timeoutMs = 1500) {
3143
+ const controller = new AbortController();
3144
+ const t = setTimeout(() => controller.abort(), timeoutMs);
3145
+ try {
3146
+ const u = new URL("/inspector/health", url);
3147
+ const res = await fetch(u, { signal: controller.signal });
3148
+ if (!res.ok) return false;
3149
+ const ct = res.headers.get("content-type") ?? "";
3150
+ if (!ct.includes("application/json")) return false;
3151
+ const body = await res.json();
3152
+ return body?.status === "ok";
3153
+ } catch {
3154
+ return false;
3155
+ } finally {
3156
+ clearTimeout(t);
3157
+ }
3158
+ }
3159
+ async function waitForHealth(url, timeoutMs = 15e3) {
3160
+ const deadline = Date.now() + timeoutMs;
3161
+ while (Date.now() < deadline) {
3162
+ if (await probeServer(url)) return true;
3163
+ await new Promise((r) => setTimeout(r, 200));
3164
+ }
3165
+ return false;
3166
+ }
3167
+ function resolveInspectorCli() {
3168
+ const candidateRoots = /* @__PURE__ */ new Set();
3169
+ const moduleDir = typeof __dirname !== "undefined" ? __dirname : import_node_path6.default.dirname(new URL(importMetaUrl).pathname);
3170
+ candidateRoots.add(moduleDir);
3171
+ candidateRoots.add(process.cwd());
3172
+ for (const start of candidateRoots) {
3173
+ let dir = start;
3174
+ while (true) {
3175
+ const candidate = import_node_path6.default.join(
3176
+ dir,
3177
+ "node_modules",
3178
+ "@mcp-use",
3179
+ "inspector",
3180
+ "dist",
3181
+ "cli.js"
3182
+ );
3183
+ if ((0, import_node_fs8.existsSync)(candidate)) return candidate;
3184
+ const parent = import_node_path6.default.dirname(dir);
3185
+ if (parent === dir) break;
3186
+ dir = parent;
3187
+ }
3188
+ }
3189
+ throw new Error(
3190
+ "Could not locate `@mcp-use/inspector` in node_modules. Install the inspector package or pass --inspector <url> to use an existing instance."
3191
+ );
3192
+ }
3193
+ async function ensureDevServer(options) {
3194
+ if (options.inspector) {
3195
+ const ok = await probeServer(options.inspector);
3196
+ if (!ok) {
3197
+ throw new Error(
3198
+ `Inspector at ${options.inspector} did not respond on /inspector/health with status:"ok"`
3199
+ );
3200
+ }
3201
+ return { url: options.inspector };
3202
+ }
3203
+ const port = await getFreePort();
3204
+ const url = `http://localhost:${port}`;
3205
+ if (!options.quiet) {
3206
+ console.error(formatInfo(`Starting inspector on port ${port}\u2026`));
3207
+ }
3208
+ const inspectorCli = resolveInspectorCli();
3209
+ const child = (0, import_node_child_process9.spawn)(
3210
+ process.execPath,
3211
+ [inspectorCli, "--port", String(port), "--no-open"],
3212
+ {
3213
+ cwd: process.cwd(),
3214
+ stdio: ["ignore", "pipe", "pipe"],
3215
+ env: { ...process.env, MCP_INSPECTOR_MODE: "standalone" }
3216
+ }
3217
+ );
3218
+ const prefix = source_default.gray("[inspector]");
3219
+ if (!options.quiet) {
3220
+ child.stdout?.on("data", (d) => {
3221
+ process.stderr.write(`${prefix} ${d}`);
3222
+ });
3223
+ child.stderr?.on("data", (d) => {
3224
+ process.stderr.write(`${prefix} ${d}`);
3225
+ });
3226
+ } else {
3227
+ child.stdout?.resume();
3228
+ child.stderr?.resume();
3229
+ }
3230
+ const ready = await waitForHealth(url);
3231
+ if (!ready) {
3232
+ child.kill("SIGTERM");
3233
+ throw new Error(`Inspector failed to come up on ${url} within 15s.`);
3234
+ }
3235
+ return { url, child };
3236
+ }
3237
+ function killChild(child) {
3238
+ if (!child || child.killed) return;
3239
+ try {
3240
+ child.kill("SIGTERM");
3241
+ } catch {
3242
+ }
3243
+ }
3244
+ function timestampSuffix(date = /* @__PURE__ */ new Date()) {
3245
+ const pad = (n) => String(n).padStart(2, "0");
3246
+ const datePart = `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
3247
+ const timePart = `${pad(date.getHours())}-${pad(date.getMinutes())}-${pad(date.getSeconds())}`;
3248
+ return `${datePart}_${timePart}`;
3249
+ }
3250
+ function extractViewName(resourceUri) {
3251
+ const m = resourceUri.match(/^ui:\/\/widget\/(.+)$/);
3252
+ if (!m) return resourceUri;
3253
+ return m[1].replace(/\.html$/, "").replace(/\.[0-9a-f]+$/i, "");
3254
+ }
3255
+ function parseDimension(raw, name) {
3256
+ const n = parseInt(raw, 10);
3257
+ if (!Number.isFinite(n) || n <= 0) {
3258
+ throw new Error(`--${name} must be a positive integer (got "${raw}")`);
3259
+ }
3260
+ return n;
3261
+ }
3262
+ var AD_HOC_SESSION_NAME = "__screenshot_ad_hoc__";
3263
+ async function resolveSessionForScreenshot(options, headers) {
3264
+ if (options.session) {
3265
+ const result = await getOrRestoreSession(options.session);
3266
+ return result?.session ?? null;
3267
+ }
3268
+ if (options.mcp) {
3269
+ const client = new import_client2.MCPClient();
3270
+ client.addServer(AD_HOC_SESSION_NAME, {
3271
+ url: options.mcp,
3272
+ ...headers ? { headers } : {},
3273
+ clientInfo: getCliClientInfo()
3274
+ });
3275
+ try {
3276
+ const session = await client.createSession(AD_HOC_SESSION_NAME);
3277
+ activeSessions.set(AD_HOC_SESSION_NAME, { client, session });
3278
+ return session;
3279
+ } catch (err) {
3280
+ const msg = err instanceof Error ? err.message : String(err);
3281
+ console.error(formatError(`Failed to connect to ${options.mcp}: ${msg}`));
3282
+ return null;
3283
+ }
3284
+ }
3285
+ console.error(
3286
+ formatError(
3287
+ "No MCP target. Pass --session <name> (a saved server) or --mcp <url> (ad-hoc)."
3288
+ )
3289
+ );
3290
+ return null;
3291
+ }
3292
+ async function screenshotCommand(options, argsList) {
3293
+ let exitCode = 0;
3294
+ try {
3295
+ if (!options.tool) {
3296
+ console.error(
3297
+ formatError(
3298
+ "--tool <name> is required (optionally with key=value args)."
3299
+ )
3300
+ );
3301
+ exitCode = 1;
3302
+ return;
3303
+ }
3304
+ let headers;
3305
+ if (options.header && options.header.length > 0) {
3306
+ if (!options.mcp) {
3307
+ console.error(
3308
+ formatError(
3309
+ "--header is only supported with --mcp <url>. Saved sessions (use --session) carry their own auth from `mcp-use client connect`."
3310
+ )
3311
+ );
3312
+ exitCode = 1;
3313
+ return;
3314
+ }
3315
+ try {
3316
+ headers = parseHeaderArgs(options.header);
3317
+ } catch (err) {
3318
+ console.error(
3319
+ formatError(err instanceof Error ? err.message : String(err))
3320
+ );
3321
+ exitCode = 1;
3322
+ return;
3323
+ }
3324
+ }
3325
+ try {
3326
+ resolveChromePath();
3327
+ } catch (err) {
3328
+ console.error(
3329
+ formatError(err instanceof Error ? err.message : String(err))
3330
+ );
3331
+ exitCode = 1;
3332
+ return;
3333
+ }
3334
+ const width = parseDimension(options.width, "width");
3335
+ const height = parseDimension(options.height, "height");
3336
+ const navTimeout = parseInt(options.timeout, 10) || 3e4;
3337
+ const delayMs = options.delay ? parseInt(options.delay, 10) : 0;
3338
+ const session = await resolveSessionForScreenshot(options, headers);
3339
+ if (!session) {
3340
+ exitCode = 1;
3341
+ return;
3342
+ }
3343
+ const tool = session.tools.find((t) => t.name === options.tool);
3344
+ if (!tool) {
3345
+ throw new Error(
3346
+ `Tool "${options.tool}" not found. Available: ${session.tools.map((t) => t.name).join(", ")}`
3347
+ );
3348
+ }
3349
+ const resourceUri = detectToolResourceUri(tool);
3350
+ if (!resourceUri) {
3351
+ throw new Error(
3352
+ `Tool "${options.tool}" does not declare a UI resource (expected _meta.ui.resourceUri or openai/outputTemplate).`
3353
+ );
3354
+ }
3355
+ let toolArgs = {};
3356
+ if (argsList && argsList.length > 0) {
3357
+ try {
3358
+ toolArgs = parseToolArgs(
3359
+ argsList,
3360
+ tool.inputSchema
3361
+ );
3362
+ } catch (err) {
3363
+ console.error(
3364
+ formatError(err instanceof Error ? err.message : String(err))
3365
+ );
3366
+ console.log("");
3367
+ console.log(formatInfo("Usage:"));
3368
+ console.log(
3369
+ ` npx mcp-use screenshot --tool ${options.tool} key=value [key2=value2 ...]`
3370
+ );
3371
+ console.log(
3372
+ ` npx mcp-use screenshot --tool ${options.tool} nested:='{"a":1}' # JSON value`
3373
+ );
3374
+ console.log(
3375
+ ` npx mcp-use screenshot --tool ${options.tool} '{"key":"value"}' # full JSON object`
3376
+ );
3377
+ if (tool.inputSchema) {
3378
+ console.log("");
3379
+ console.log(formatInfo("Tool schema:"));
3380
+ console.log(formatSchema(tool.inputSchema));
3381
+ }
3382
+ exitCode = 1;
3383
+ return;
3384
+ }
3385
+ }
3386
+ const toolOutput = await session.callTool(options.tool, toolArgs);
3387
+ const result = await captureToolScreenshot(
3388
+ {
3389
+ session,
3390
+ toolName: options.tool,
3391
+ toolArgs,
3392
+ toolOutput,
3393
+ resourceUri
3394
+ },
3395
+ {
3396
+ width,
3397
+ height,
3398
+ theme: options.theme,
3399
+ output: options.output,
3400
+ waitFor: options.waitFor,
3401
+ delayMs,
3402
+ timeoutMs: navTimeout,
3403
+ inspector: options.inspector,
3404
+ quiet: options.quiet,
3405
+ cdpUrl: options.cdpUrl
3406
+ }
3407
+ );
3408
+ console.log(
3409
+ `Saved screenshot: ${result.outputPath} (${result.width}\xD7${result.height})`
3410
+ );
3411
+ } catch (err) {
3412
+ const msg = err instanceof Error ? err.message : String(err);
3413
+ console.error(formatError(`Screenshot failed: ${msg}`));
3414
+ exitCode = 1;
3415
+ } finally {
3416
+ await cleanupAndExit(exitCode);
3417
+ }
3418
+ }
3419
+ function createScreenshotCommand() {
3420
+ return new import_commander.Command("screenshot").description(
3421
+ "Render an MCP Apps view headlessly and save a PNG by calling a tool and rendering its UI resource with the result."
3422
+ ).argument(
3423
+ "[args...]",
3424
+ "Tool args as key=value pairs (use key:=<json> for nested values, or pass a single JSON object)."
3425
+ ).option(
3426
+ "--tool <name>",
3427
+ "Tool to call. Its UI resource is rendered with the result."
3428
+ ).option("--width <px>", "Browser viewport width in pixels.", "800").option("--height <px>", "Browser viewport height in pixels.", "600").option(
3429
+ "--inspector <url>",
3430
+ "Inspector host that serves /inspector/preview/:view. When omitted, probes localhost:3000 then auto-spawns `mcp-use dev`."
3431
+ ).option(
3432
+ "--session <name>",
3433
+ "Saved server name (from `mcp-use client connect <name> <url>`)."
3434
+ ).option(
3435
+ "--mcp <url>",
3436
+ "Ad-hoc MCP server URL (escape hatch). Use when you don't have a saved server. No authentication unless --header is supplied."
3437
+ ).option(
3438
+ "-H, --header <header>",
3439
+ 'HTTP header to send to the --mcp <url> server, formatted "Key: Value". Repeatable. Use to pass an Authorization bearer token or other auth headers when screenshotting an authenticated MCP server.',
3440
+ collectHeader,
3441
+ []
3442
+ ).option(
3443
+ "--theme <light|dark>",
3444
+ "Color scheme to render the view in.",
3445
+ "light"
3446
+ ).option(
3447
+ "--output <path>",
3448
+ "Output PNG path. Defaults to ./<view>-<timestamp>.png in cwd."
3449
+ ).option(
3450
+ "--wait-for <selector>",
3451
+ 'Override readiness selector (default: body[data-view-ready="true"]).'
3452
+ ).option(
3453
+ "--delay <ms>",
3454
+ "Extra wait after readiness, to let chart animations / async layouts settle.",
3455
+ "0"
3456
+ ).option("--timeout <ms>", "Navigation + readiness timeout in ms.", "30000").option(
3457
+ "--cdp-url <url>",
3458
+ "Connect to an existing CDP WebSocket (ws:// or wss://) instead of spawning local Chrome. Useful for hosted browsers like Notte."
3459
+ ).option("--quiet", "Suppress dev-server output.").action(async (args, opts) => {
3460
+ await screenshotCommand(opts, args);
3461
+ });
3462
+ }
3463
+
3464
+ // src/commands/client.ts
3465
+ var RESERVED_CLIENT_SUBCOMMANDS = /* @__PURE__ */ new Set([
3466
+ "connect",
3467
+ "list",
3468
+ "remove",
3469
+ "help"
3470
+ ]);
3471
+ var PER_CLIENT_SCOPES = /* @__PURE__ */ new Set([
3472
+ "tools",
3473
+ "resources",
3474
+ "prompts",
3475
+ "auth",
3476
+ "disconnect",
3477
+ "interactive"
3478
+ ]);
3479
+ async function connectCommand(name, urlOrCommand, options) {
3480
+ if (!name || !urlOrCommand) {
3481
+ const looksLikeUrl = !!name && /^https?:\/\//i.test(name);
3482
+ if (looksLikeUrl && !urlOrCommand && !options.stdio) {
3483
+ console.error(formatError("Missing server name."));
3484
+ console.error("");
3485
+ console.error(
3486
+ formatInfo(
3487
+ "Each saved server needs a short name you'll use to address it later."
3488
+ )
3489
+ );
3490
+ console.error("");
3491
+ console.error("Try:");
3492
+ console.error(` mcp-use client connect <name> ${name}`);
3493
+ console.error("");
3494
+ console.error("Example:");
3495
+ console.error(` mcp-use client connect my-server ${name}`);
3496
+ console.error(" mcp-use client my-server tools list");
3497
+ } else if (name && !urlOrCommand) {
3498
+ console.error(
3499
+ formatError(options.stdio ? "Missing <command>." : "Missing <url>.")
3500
+ );
3501
+ console.error("");
3502
+ console.error(formatInfo("Usage:"));
3503
+ console.error(
3504
+ options.stdio ? ` mcp-use client connect ${name} "<command>" --stdio` : ` mcp-use client connect ${name} <url>`
3505
+ );
3506
+ } else {
3507
+ console.error(formatError("Missing required arguments: <name> <url>."));
3508
+ console.error("");
3509
+ console.error(formatInfo("Usage:"));
3510
+ console.error(" mcp-use client connect <name> <url>");
3511
+ console.error("");
3512
+ console.error("Example:");
3513
+ console.error(
3514
+ " mcp-use client connect manufact https://mcp.manufact.com/mcp"
3515
+ );
3516
+ }
3517
+ await cleanupAndExit(1);
3518
+ }
3519
+ const sessionName = name;
3520
+ const target = urlOrCommand;
3521
+ if (PER_CLIENT_SCOPES.has(sessionName)) {
3522
+ console.error(
3523
+ formatError(
3524
+ `'${sessionName}' is a reserved name and can't be used for a saved server.`
3525
+ )
3526
+ );
3527
+ console.error("");
3528
+ console.error(
3529
+ `Reserved names: ${Array.from(PER_CLIENT_SCOPES).sort().join(", ")}`
3530
+ );
3531
+ console.error("");
3532
+ console.error("Pick a different name, e.g.:");
3533
+ console.error(` mcp-use client connect my-${sessionName} ${target}`);
3534
+ await cleanupAndExit(1);
3535
+ }
2268
3536
  try {
2269
- const sessionName = options.name || `session-${Date.now()}`;
2270
- const client = new import_client.MCPClient();
3537
+ const client = new import_client3.MCPClient();
2271
3538
  let session;
2272
3539
  const cliClientInfo = getCliClientInfo();
2273
3540
  if (options.stdio) {
2274
- const parts = urlOrCommand.split(" ");
3541
+ const parts = target.split(" ");
2275
3542
  const command = parts[0];
2276
3543
  const args = parts.slice(1);
2277
3544
  console.error(
@@ -2290,17 +3557,41 @@ async function connectCommand(urlOrCommand, options) {
2290
3557
  lastUsed: (/* @__PURE__ */ new Date()).toISOString()
2291
3558
  });
2292
3559
  } else {
2293
- console.error(formatInfo(`Connecting to ${urlOrCommand}...`));
3560
+ console.error(formatInfo(`Connecting to ${target}...`));
3561
+ const wantOAuth = !options.auth && options.oauth !== false;
3562
+ let authProvider;
3563
+ if (wantOAuth) {
3564
+ const authTimeoutMs = options.authTimeout ? Number.parseInt(options.authTimeout, 10) : void 0;
3565
+ authProvider = await buildOAuthProvider(target, {
3566
+ ...authTimeoutMs ? { authTimeoutMs } : {}
3567
+ });
3568
+ }
2294
3569
  client.addServer(sessionName, {
2295
- url: urlOrCommand,
2296
- headers: options.auth ? { Authorization: `Bearer ${options.auth}` } : void 0,
3570
+ url: target,
3571
+ ...authProvider ? { authProvider } : options.auth ? { headers: { Authorization: `Bearer ${options.auth}` } } : {},
2297
3572
  clientInfo: cliClientInfo
2298
3573
  });
2299
- session = await client.createSession(sessionName);
3574
+ try {
3575
+ session = await client.createSession(sessionName);
3576
+ } catch (err) {
3577
+ if (authProvider && isUnauthorized(err)) {
3578
+ console.error(
3579
+ formatWarning(
3580
+ "Server requires authentication. Starting OAuth flow."
3581
+ )
3582
+ );
3583
+ await runOAuthFlow(authProvider, target);
3584
+ console.error(formatSuccess("Authentication successful"));
3585
+ session = await client.createSession(sessionName);
3586
+ } else {
3587
+ throw err;
3588
+ }
3589
+ }
2300
3590
  await saveSession(sessionName, {
2301
3591
  type: "http",
2302
- url: urlOrCommand,
2303
- authToken: options.auth,
3592
+ url: target,
3593
+ authMode: authProvider ? "oauth" : options.auth ? "bearer" : void 0,
3594
+ authToken: authProvider ? void 0 : options.auth,
2304
3595
  lastUsed: (/* @__PURE__ */ new Date()).toISOString()
2305
3596
  });
2306
3597
  }
@@ -2310,7 +3601,7 @@ async function connectCommand(urlOrCommand, options) {
2310
3601
  if (serverInfo) {
2311
3602
  await updateSessionInfo(sessionName, serverInfo, capabilities);
2312
3603
  }
2313
- console.log(formatSuccess(`Connected to ${sessionName}`));
3604
+ console.log(formatSuccess(`Connected as '${sessionName}'`));
2314
3605
  if (serverInfo) {
2315
3606
  console.log("");
2316
3607
  console.log(formatHeader("Server Information:"));
@@ -2336,119 +3627,173 @@ async function connectCommand(urlOrCommand, options) {
2336
3627
  );
2337
3628
  } catch (error) {
2338
3629
  console.error(formatError(`Connection failed: ${error.message}`));
2339
- process.exit(1);
3630
+ await cleanupAndExit(1);
2340
3631
  }
3632
+ await cleanupAndExit(0);
2341
3633
  }
2342
- async function disconnectCommand(sessionName, options) {
3634
+ async function disconnectCommand(name) {
2343
3635
  try {
2344
- if (options?.all) {
2345
- for (const [name, { client }] of activeSessions.entries()) {
2346
- await client.closeAllSessions();
2347
- activeSessions.delete(name);
2348
- console.log(formatSuccess(`Disconnected from ${name}`));
2349
- }
2350
- return;
2351
- }
2352
- if (!sessionName) {
2353
- const active = await getActiveSession();
2354
- if (!active) {
2355
- console.error(formatError("No active session to disconnect"));
2356
- return;
2357
- }
2358
- sessionName = active.name;
2359
- }
2360
- const sessionData = activeSessions.get(sessionName);
3636
+ const sessionData = activeSessions.get(name);
2361
3637
  if (sessionData) {
2362
3638
  await sessionData.client.closeAllSessions();
2363
- activeSessions.delete(sessionName);
2364
- console.log(formatSuccess(`Disconnected from ${sessionName}`));
3639
+ activeSessions.delete(name);
3640
+ console.log(formatSuccess(`Disconnected from ${name}`));
2365
3641
  } else {
2366
- console.log(formatInfo(`Session '${sessionName}' is not connected`));
3642
+ console.log(formatInfo(`Server '${name}' is not connected`));
2367
3643
  }
2368
3644
  } catch (error) {
2369
3645
  console.error(formatError(`Failed to disconnect: ${error.message}`));
2370
- process.exit(1);
3646
+ await cleanupAndExit(1);
3647
+ }
3648
+ await cleanupAndExit(0);
3649
+ }
3650
+ async function removeClientCommand(name) {
3651
+ try {
3652
+ const config = await getSession(name);
3653
+ if (!config) {
3654
+ console.error(formatError(`Server '${name}' not found`));
3655
+ console.error("");
3656
+ console.error("See your saved servers with:");
3657
+ console.error(" mcp-use client list");
3658
+ await cleanupAndExit(1);
3659
+ }
3660
+ const sessionData = activeSessions.get(name);
3661
+ if (sessionData) {
3662
+ await sessionData.client.closeAllSessions();
3663
+ activeSessions.delete(name);
3664
+ }
3665
+ const isOAuthHttp = config.type === "http" && config.authMode === "oauth" && typeof config.url === "string";
3666
+ const sharedUrlSibling = isOAuthHttp ? (await listAllSessions()).find(
3667
+ (s) => s.name !== name && s.config.type === "http" && s.config.url === config.url
3668
+ ) : void 0;
3669
+ await removeSession(name);
3670
+ console.log(formatSuccess(`Removed saved server '${name}'`));
3671
+ if (isOAuthHttp) {
3672
+ if (sharedUrlSibling) {
3673
+ console.log(
3674
+ formatInfo(
3675
+ `OAuth tokens for ${config.url} were kept because saved server '${sharedUrlSibling.name}' still uses that URL.`
3676
+ )
3677
+ );
3678
+ } else {
3679
+ try {
3680
+ const provider = await buildOAuthProvider(config.url);
3681
+ await provider.invalidateCredentials("all");
3682
+ console.log(formatInfo(`Removed OAuth tokens for ${config.url}`));
3683
+ } catch (error) {
3684
+ console.error(
3685
+ formatWarning(
3686
+ `Saved entry removed, but failed to clear OAuth tokens for ${config.url}: ${error.message}`
3687
+ )
3688
+ );
3689
+ }
3690
+ }
3691
+ }
3692
+ } catch (error) {
3693
+ console.error(formatError(`Failed to remove server: ${error.message}`));
3694
+ await cleanupAndExit(1);
2371
3695
  }
3696
+ await cleanupAndExit(0);
2372
3697
  }
2373
- async function listSessionsCommand() {
3698
+ async function listClientsCommand() {
2374
3699
  try {
2375
3700
  const sessions = await listAllSessions();
2376
3701
  if (sessions.length === 0) {
2377
- console.log(formatInfo("No saved sessions"));
2378
- console.log(
2379
- formatInfo("Connect to a server with: npx mcp-use client connect <url>")
2380
- );
3702
+ if (isStdoutTty()) {
3703
+ console.log(formatInfo("No saved servers"));
3704
+ console.log(
3705
+ formatInfo(
3706
+ "Connect to a server with: npx mcp-use client connect <name> <url>"
3707
+ )
3708
+ );
3709
+ }
2381
3710
  return;
2382
3711
  }
2383
- console.log(formatHeader("Saved Sessions:"));
2384
- console.log("");
3712
+ const tty2 = isStdoutTty();
3713
+ if (tty2) {
3714
+ console.log(formatHeader("Saved Servers:"));
3715
+ console.log("");
3716
+ }
2385
3717
  const tableData = sessions.map((s) => ({
2386
- name: s.isActive ? source_default.green.bold(`${s.name} *`) : s.name,
3718
+ name: s.name,
2387
3719
  type: s.config.type,
2388
3720
  target: s.config.type === "http" ? s.config.url || "" : `${s.config.command} ${(s.config.args || []).join(" ")}`,
2389
- server: s.config.serverInfo?.name || "unknown",
2390
- status: activeSessions.has(s.name) ? source_default.green("connected") : source_default.gray("disconnected")
3721
+ server: s.config.serverInfo?.name || "unknown"
2391
3722
  }));
2392
3723
  console.log(
2393
3724
  formatTable(tableData, [
2394
3725
  { key: "name", header: "Name" },
2395
3726
  { key: "type", header: "Type" },
2396
- { key: "target", header: "Target", width: 40 },
2397
- { key: "server", header: "Server" },
2398
- { key: "status", header: "Status" }
3727
+ { key: "target", header: "Target", truncate: true },
3728
+ { key: "server", header: "Server" }
2399
3729
  ])
2400
3730
  );
2401
- console.log("");
2402
- console.log(source_default.gray("* = active session"));
2403
- } catch (error) {
2404
- console.error(formatError(`Failed to list sessions: ${error.message}`));
2405
- process.exit(1);
2406
- }
2407
- }
2408
- async function switchSessionCommand(name) {
2409
- try {
2410
- await setActiveSession(name);
2411
- console.log(formatSuccess(`Switched to session '${name}'`));
2412
3731
  } catch (error) {
2413
- console.error(formatError(`Failed to switch session: ${error.message}`));
2414
- process.exit(1);
3732
+ console.error(formatError(`Failed to list servers: ${error.message}`));
3733
+ await cleanupAndExit(1);
2415
3734
  }
3735
+ await cleanupAndExit(0);
2416
3736
  }
2417
- async function listToolsCommand(options) {
3737
+ async function listToolsCommand(name, options) {
2418
3738
  try {
2419
- const result = await getOrRestoreSession(options.session || null);
2420
- if (!result) return;
3739
+ const result = await getOrRestoreSession(name);
3740
+ if (!result) {
3741
+ await cleanupAndExit(1);
3742
+ }
2421
3743
  const { session } = result;
2422
3744
  const tools = await session.listTools();
2423
3745
  if (options.json) {
2424
3746
  console.log(formatJson(tools));
2425
- return;
2426
- }
2427
- if (tools.length === 0) {
2428
- console.log(formatInfo("No tools available"));
2429
- return;
3747
+ } else if (tools.length === 0) {
3748
+ if (isStdoutTty()) console.log(formatInfo("No tools available"));
3749
+ } else {
3750
+ const tty2 = isStdoutTty();
3751
+ if (tty2) {
3752
+ console.log(formatHeader(`Available Tools (${tools.length}):`));
3753
+ console.log("");
3754
+ }
3755
+ const tableData = tools.map((tool) => {
3756
+ const props = tool.inputSchema?.properties ?? {};
3757
+ const required = tool.inputSchema?.required ?? [];
3758
+ const total = Object.keys(props).length;
3759
+ const reqCount = Array.isArray(required) ? required.length : 0;
3760
+ const argsCell = total === 0 ? source_default.gray("\u2014") : `${reqCount}/${total}`;
3761
+ return {
3762
+ name: source_default.bold(tool.name),
3763
+ mode: formatToolMode(tool.annotations),
3764
+ args: argsCell,
3765
+ description: tool.description || source_default.gray("(no description)")
3766
+ };
3767
+ });
3768
+ console.log(
3769
+ formatTable(tableData, [
3770
+ { key: "name", header: "Tool" },
3771
+ { key: "mode", header: "Mode" },
3772
+ { key: "args", header: "Args" },
3773
+ { key: "description", header: "Description", truncate: true }
3774
+ ])
3775
+ );
3776
+ if (tty2) {
3777
+ console.log("");
3778
+ console.log(
3779
+ source_default.gray(
3780
+ "ARGS shows required/total. Modes: read-only \xB7 write \xB7 destructive."
3781
+ )
3782
+ );
3783
+ }
2430
3784
  }
2431
- console.log(formatHeader(`Available Tools (${tools.length}):`));
2432
- console.log("");
2433
- const tableData = tools.map((tool) => ({
2434
- name: source_default.bold(tool.name),
2435
- description: tool.description || source_default.gray("No description")
2436
- }));
2437
- console.log(
2438
- formatTable(tableData, [
2439
- { key: "name", header: "Tool", width: 25 },
2440
- { key: "description", header: "Description", width: 50 }
2441
- ])
2442
- );
2443
3785
  } catch (error) {
2444
3786
  console.error(formatError(`Failed to list tools: ${error.message}`));
2445
- process.exit(1);
3787
+ await cleanupAndExit(1);
2446
3788
  }
3789
+ await cleanupAndExit(0);
2447
3790
  }
2448
- async function describeToolCommand(toolName, options) {
3791
+ async function describeToolCommand(name, toolName) {
2449
3792
  try {
2450
- const result = await getOrRestoreSession(options.session || null);
2451
- if (!result) return;
3793
+ const result = await getOrRestoreSession(name);
3794
+ if (!result) {
3795
+ await cleanupAndExit(1);
3796
+ }
2452
3797
  const { session } = result;
2453
3798
  const tools = session.tools;
2454
3799
  const tool = tools.find((t) => t.name === toolName);
@@ -2457,7 +3802,7 @@ async function describeToolCommand(toolName, options) {
2457
3802
  console.log("");
2458
3803
  console.log(formatInfo("Available tools:"));
2459
3804
  tools.forEach((t) => console.log(` \u2022 ${t.name}`));
2460
- return;
3805
+ await cleanupAndExit(1);
2461
3806
  }
2462
3807
  console.log(formatHeader(`Tool: ${tool.name}`));
2463
3808
  console.log("");
@@ -2471,94 +3816,167 @@ async function describeToolCommand(toolName, options) {
2471
3816
  }
2472
3817
  } catch (error) {
2473
3818
  console.error(formatError(`Failed to describe tool: ${error.message}`));
2474
- process.exit(1);
3819
+ await cleanupAndExit(1);
2475
3820
  }
3821
+ await cleanupAndExit(0);
2476
3822
  }
2477
- async function callToolCommand(toolName, argsJson, options) {
3823
+ async function callToolCommand(name, toolName, argsList, options) {
2478
3824
  try {
2479
- const result = await getOrRestoreSession(options?.session || null);
2480
- if (!result) return;
3825
+ const result = await getOrRestoreSession(name);
3826
+ if (!result) {
3827
+ await cleanupAndExit(1);
3828
+ }
2481
3829
  const { session } = result;
3830
+ const tools = session.tools;
3831
+ const tool = tools.find((t) => t.name === toolName);
2482
3832
  let args = {};
2483
- if (argsJson) {
3833
+ if (argsList && argsList.length > 0) {
2484
3834
  try {
2485
- args = JSON.parse(argsJson);
3835
+ args = parseToolArgs(argsList, tool?.inputSchema);
2486
3836
  } catch (error) {
2487
- console.error(formatError("Invalid JSON arguments"));
2488
- return;
2489
- }
2490
- } else {
2491
- const tools = session.tools;
2492
- const tool = tools.find((t) => t.name === toolName);
2493
- if (tool?.inputSchema?.required && tool.inputSchema.required.length > 0) {
2494
- console.error(
2495
- formatError(
2496
- "This tool requires arguments. Provide them as a JSON string."
2497
- )
2498
- );
3837
+ console.error(formatError(error.message));
2499
3838
  console.log("");
2500
- console.log(formatInfo("Example:"));
3839
+ console.log(formatInfo("Usage:"));
2501
3840
  console.log(
2502
- ` npx mcp-use client tools call ${toolName} '{"param": "value"}'`
3841
+ ` npx mcp-use client ${name} tools call ${toolName} key=value [key2=value2 ...]`
2503
3842
  );
2504
- console.log("");
2505
- console.log(formatInfo("Tool schema:"));
2506
- console.log(formatSchema(tool.inputSchema));
2507
- return;
3843
+ console.log(
3844
+ ` npx mcp-use client ${name} tools call ${toolName} nested:='{"a":1}' # JSON value`
3845
+ );
3846
+ console.log(
3847
+ ` npx mcp-use client ${name} tools call ${toolName} '{"key":"value"}' # full JSON object`
3848
+ );
3849
+ if (tool?.inputSchema) {
3850
+ console.log("");
3851
+ console.log(formatInfo("Tool schema:"));
3852
+ console.log(formatSchema(tool.inputSchema));
3853
+ }
3854
+ await cleanupAndExit(1);
2508
3855
  }
3856
+ } else if (tool?.inputSchema?.required && tool.inputSchema.required.length > 0) {
3857
+ console.error(formatError("This tool requires arguments."));
3858
+ console.log("");
3859
+ console.log(formatInfo("Provide arguments as key=value pairs:"));
3860
+ console.log(
3861
+ ` npx mcp-use client ${name} tools call ${toolName} key=value [key2=value2 ...]`
3862
+ );
3863
+ console.log("");
3864
+ console.log(formatInfo("Tool schema:"));
3865
+ console.log(formatSchema(tool.inputSchema));
3866
+ await cleanupAndExit(1);
2509
3867
  }
2510
3868
  console.error(formatInfo(`Calling tool '${toolName}'...`));
2511
3869
  const callResult = await session.callTool(toolName, args, {
2512
3870
  timeout: options?.timeout
2513
3871
  });
3872
+ let screenshot = null;
3873
+ let screenshotError = null;
3874
+ if (options?.screenshot !== false) {
3875
+ const tool2 = session.tools.find((t) => t.name === toolName);
3876
+ const resourceUri = detectToolResourceUri(tool2);
3877
+ if (resourceUri) {
3878
+ console.error(
3879
+ formatInfo(`Capturing widget screenshot (${resourceUri})...`)
3880
+ );
3881
+ try {
3882
+ const shot = await captureToolScreenshot(
3883
+ {
3884
+ session,
3885
+ toolName,
3886
+ toolArgs: args,
3887
+ toolOutput: callResult,
3888
+ resourceUri
3889
+ },
3890
+ options?.screenshotOutput ? { output: options.screenshotOutput } : {}
3891
+ );
3892
+ screenshot = {
3893
+ path: shot.outputPath,
3894
+ width: shot.width,
3895
+ height: shot.height,
3896
+ view: shot.view
3897
+ };
3898
+ } catch (err) {
3899
+ screenshotError = err?.message ?? String(err);
3900
+ }
3901
+ }
3902
+ }
2514
3903
  if (options?.json) {
2515
3904
  console.log(formatJson(callResult));
2516
3905
  } else {
2517
3906
  console.log(formatToolCall(callResult));
2518
3907
  }
3908
+ if (screenshot) {
3909
+ console.error(
3910
+ formatSuccess(
3911
+ `Saved widget screenshot: ${screenshot.path} (${screenshot.width}\xD7${screenshot.height})`
3912
+ )
3913
+ );
3914
+ }
3915
+ if (screenshotError) {
3916
+ console.error(
3917
+ formatWarning(`Skipped widget screenshot: ${screenshotError}`)
3918
+ );
3919
+ }
3920
+ if (callResult.isError) {
3921
+ await cleanupAndExit(1);
3922
+ }
2519
3923
  } catch (error) {
2520
3924
  console.error(formatError(`Failed to call tool: ${error.message}`));
2521
- process.exit(1);
3925
+ if (error?.data !== void 0) {
3926
+ console.error(
3927
+ source_default.gray(
3928
+ typeof error.data === "string" ? error.data : formatJson(error.data)
3929
+ )
3930
+ );
3931
+ }
3932
+ await cleanupAndExit(1);
2522
3933
  }
3934
+ await cleanupAndExit(0);
2523
3935
  }
2524
- async function listResourcesCommand(options) {
3936
+ async function listResourcesCommand(name, options) {
2525
3937
  try {
2526
- const result = await getOrRestoreSession(options.session || null);
2527
- if (!result) return;
3938
+ const result = await getOrRestoreSession(name);
3939
+ if (!result) {
3940
+ await cleanupAndExit(1);
3941
+ }
2528
3942
  const { session } = result;
2529
3943
  const resourcesResult = await session.listAllResources();
2530
3944
  const resources = resourcesResult.resources;
2531
3945
  if (options.json) {
2532
3946
  console.log(formatJson(resources));
2533
- return;
2534
- }
2535
- if (resources.length === 0) {
2536
- console.log(formatInfo("No resources available"));
2537
- return;
3947
+ } else if (resources.length === 0) {
3948
+ if (isStdoutTty()) console.log(formatInfo("No resources available"));
3949
+ } else {
3950
+ const tty2 = isStdoutTty();
3951
+ if (tty2) {
3952
+ console.log(formatHeader(`Available Resources (${resources.length}):`));
3953
+ console.log("");
3954
+ }
3955
+ const tableData = resources.map((resource) => ({
3956
+ name: source_default.bold(resource.name || "(no name)"),
3957
+ type: resource.mimeType || source_default.gray("unknown"),
3958
+ uri: resource.uri
3959
+ }));
3960
+ console.log(
3961
+ formatTable(tableData, [
3962
+ { key: "name", header: "Name" },
3963
+ { key: "type", header: "Type" },
3964
+ { key: "uri", header: "URI", truncate: true }
3965
+ ])
3966
+ );
2538
3967
  }
2539
- console.log(formatHeader(`Available Resources (${resources.length}):`));
2540
- console.log("");
2541
- const tableData = resources.map((resource) => ({
2542
- uri: resource.uri,
2543
- name: resource.name || source_default.gray("(no name)"),
2544
- type: resource.mimeType || source_default.gray("unknown")
2545
- }));
2546
- console.log(
2547
- formatTable(tableData, [
2548
- { key: "uri", header: "URI", width: 40 },
2549
- { key: "name", header: "Name", width: 20 },
2550
- { key: "type", header: "Type", width: 15 }
2551
- ])
2552
- );
2553
3968
  } catch (error) {
2554
3969
  console.error(formatError(`Failed to list resources: ${error.message}`));
2555
- process.exit(1);
3970
+ await cleanupAndExit(1);
2556
3971
  }
3972
+ await cleanupAndExit(0);
2557
3973
  }
2558
- async function readResourceCommand(uri, options) {
3974
+ async function readResourceCommand(name, uri, options) {
2559
3975
  try {
2560
- const result = await getOrRestoreSession(options.session || null);
2561
- if (!result) return;
3976
+ const result = await getOrRestoreSession(name);
3977
+ if (!result) {
3978
+ await cleanupAndExit(1);
3979
+ }
2562
3980
  const { session } = result;
2563
3981
  console.error(formatInfo(`Reading resource: ${uri}`));
2564
3982
  const resource = await session.readResource(uri);
@@ -2569,13 +3987,16 @@ async function readResourceCommand(uri, options) {
2569
3987
  }
2570
3988
  } catch (error) {
2571
3989
  console.error(formatError(`Failed to read resource: ${error.message}`));
2572
- process.exit(1);
3990
+ await cleanupAndExit(1);
2573
3991
  }
3992
+ await cleanupAndExit(0);
2574
3993
  }
2575
- async function subscribeResourceCommand(uri, options) {
3994
+ async function subscribeResourceCommand(name, uri) {
2576
3995
  try {
2577
- const result = await getOrRestoreSession(options.session || null);
2578
- if (!result) return;
3996
+ const result = await getOrRestoreSession(name);
3997
+ if (!result) {
3998
+ await cleanupAndExit(1);
3999
+ }
2579
4000
  const { session } = result;
2580
4001
  await session.subscribeToResource(uri);
2581
4002
  console.log(formatSuccess(`Subscribed to resource: ${uri}`));
@@ -2593,13 +4014,15 @@ async function subscribeResourceCommand(uri, options) {
2593
4014
  console.error(
2594
4015
  formatError(`Failed to subscribe to resource: ${error.message}`)
2595
4016
  );
2596
- process.exit(1);
4017
+ await cleanupAndExit(1);
2597
4018
  }
2598
4019
  }
2599
- async function unsubscribeResourceCommand(uri, options) {
4020
+ async function unsubscribeResourceCommand(name, uri) {
2600
4021
  try {
2601
- const result = await getOrRestoreSession(options.session || null);
2602
- if (!result) return;
4022
+ const result = await getOrRestoreSession(name);
4023
+ if (!result) {
4024
+ await cleanupAndExit(1);
4025
+ }
2603
4026
  const { session } = result;
2604
4027
  await session.unsubscribeFromResource(uri);
2605
4028
  console.log(formatSuccess(`Unsubscribed from resource: ${uri}`));
@@ -2607,53 +4030,76 @@ async function unsubscribeResourceCommand(uri, options) {
2607
4030
  console.error(
2608
4031
  formatError(`Failed to unsubscribe from resource: ${error.message}`)
2609
4032
  );
2610
- process.exit(1);
4033
+ await cleanupAndExit(1);
2611
4034
  }
4035
+ await cleanupAndExit(0);
2612
4036
  }
2613
- async function listPromptsCommand(options) {
4037
+ async function listPromptsCommand(name, options) {
2614
4038
  try {
2615
- const result = await getOrRestoreSession(options.session || null);
2616
- if (!result) return;
4039
+ const result = await getOrRestoreSession(name);
4040
+ if (!result) {
4041
+ await cleanupAndExit(1);
4042
+ }
2617
4043
  const { session } = result;
2618
4044
  const promptsResult = await session.listPrompts();
2619
4045
  const prompts = promptsResult.prompts;
2620
4046
  if (options.json) {
2621
4047
  console.log(formatJson(prompts));
2622
- return;
2623
- }
2624
- if (prompts.length === 0) {
2625
- console.log(formatInfo("No prompts available"));
2626
- return;
4048
+ } else if (prompts.length === 0) {
4049
+ if (isStdoutTty()) console.log(formatInfo("No prompts available"));
4050
+ } else {
4051
+ const tty2 = isStdoutTty();
4052
+ if (tty2) {
4053
+ console.log(formatHeader(`Available Prompts (${prompts.length}):`));
4054
+ console.log("");
4055
+ }
4056
+ const tableData = prompts.map((prompt4) => {
4057
+ const args = prompt4.arguments ?? [];
4058
+ const reqCount = Array.isArray(args) ? args.filter((a) => a?.required).length : 0;
4059
+ const total = Array.isArray(args) ? args.length : 0;
4060
+ const argsCell = total === 0 ? source_default.gray("\u2014") : `${reqCount}/${total}`;
4061
+ return {
4062
+ name: source_default.bold(prompt4.name),
4063
+ args: argsCell,
4064
+ description: prompt4.description || source_default.gray("(no description)")
4065
+ };
4066
+ });
4067
+ console.log(
4068
+ formatTable(tableData, [
4069
+ { key: "name", header: "Prompt" },
4070
+ { key: "args", header: "Args" },
4071
+ { key: "description", header: "Description", truncate: true }
4072
+ ])
4073
+ );
2627
4074
  }
2628
- console.log(formatHeader(`Available Prompts (${prompts.length}):`));
2629
- console.log("");
2630
- const tableData = prompts.map((prompt4) => ({
2631
- name: source_default.bold(prompt4.name),
2632
- description: prompt4.description || source_default.gray("No description")
2633
- }));
2634
- console.log(
2635
- formatTable(tableData, [
2636
- { key: "name", header: "Prompt", width: 25 },
2637
- { key: "description", header: "Description", width: 50 }
2638
- ])
2639
- );
2640
4075
  } catch (error) {
2641
4076
  console.error(formatError(`Failed to list prompts: ${error.message}`));
2642
- process.exit(1);
4077
+ await cleanupAndExit(1);
2643
4078
  }
4079
+ await cleanupAndExit(0);
2644
4080
  }
2645
- async function getPromptCommand(promptName, argsJson, options) {
4081
+ async function getPromptCommand(name, promptName, argsList, options) {
2646
4082
  try {
2647
- const result = await getOrRestoreSession(options?.session || null);
2648
- if (!result) return;
4083
+ const result = await getOrRestoreSession(name);
4084
+ if (!result) {
4085
+ await cleanupAndExit(1);
4086
+ }
2649
4087
  const { session } = result;
2650
4088
  let args = {};
2651
- if (argsJson) {
4089
+ if (argsList && argsList.length > 0) {
2652
4090
  try {
2653
- args = JSON.parse(argsJson);
4091
+ args = parsePromptArgs(argsList);
2654
4092
  } catch (error) {
2655
- console.error(formatError("Invalid JSON arguments"));
2656
- return;
4093
+ console.error(formatError(error.message));
4094
+ console.log("");
4095
+ console.log(formatInfo("Usage:"));
4096
+ console.log(
4097
+ ` npx mcp-use client ${name} prompts get ${promptName} key=value [key2=value2 ...]`
4098
+ );
4099
+ console.log(
4100
+ ` npx mcp-use client ${name} prompts get ${promptName} '{"key":"value"}' # full JSON object`
4101
+ );
4102
+ await cleanupAndExit(1);
2657
4103
  }
2658
4104
  }
2659
4105
  console.error(formatInfo(`Getting prompt '${promptName}'...`));
@@ -2675,12 +4121,13 @@ async function getPromptCommand(promptName, argsJson, options) {
2675
4121
  }
2676
4122
  } catch (error) {
2677
4123
  console.error(formatError(`Failed to get prompt: ${error.message}`));
2678
- process.exit(1);
4124
+ await cleanupAndExit(1);
2679
4125
  }
4126
+ await cleanupAndExit(0);
2680
4127
  }
2681
- async function interactiveCommand(options) {
4128
+ async function interactiveCommand(name) {
2682
4129
  try {
2683
- const result = await getOrRestoreSession(options.session || null);
4130
+ const result = await getOrRestoreSession(name);
2684
4131
  if (!result) return;
2685
4132
  const { name: sessionName, session } = result;
2686
4133
  console.log(formatHeader("MCP Interactive Mode"));
@@ -2703,15 +4150,11 @@ async function interactiveCommand(options) {
2703
4150
  source_default.gray(" prompts list - List available prompts")
2704
4151
  );
2705
4152
  console.log(source_default.gray(" prompts get <name> - Get a prompt"));
2706
- console.log(source_default.gray(" sessions list - List all sessions"));
2707
- console.log(
2708
- source_default.gray(" sessions switch <name> - Switch to another session")
2709
- );
2710
4153
  console.log(
2711
4154
  source_default.gray(" exit, quit - Exit interactive mode")
2712
4155
  );
2713
4156
  console.log("");
2714
- const rl = (0, import_node_readline.createInterface)({
4157
+ const rl = (0, import_node_readline2.createInterface)({
2715
4158
  input: process.stdin,
2716
4159
  output: process.stdout,
2717
4160
  prompt: source_default.cyan("mcp> ")
@@ -2726,7 +4169,7 @@ async function interactiveCommand(options) {
2726
4169
  if (trimmed === "exit" || trimmed === "quit") {
2727
4170
  console.log(formatInfo("Goodbye!"));
2728
4171
  rl.close();
2729
- process.exit(0);
4172
+ await cleanupAndExit(0);
2730
4173
  }
2731
4174
  const parts = trimmed.split(" ");
2732
4175
  const scope = parts[0];
@@ -2826,22 +4269,10 @@ async function interactiveCommand(options) {
2826
4269
  )
2827
4270
  );
2828
4271
  }
2829
- } else if (scope === "sessions") {
2830
- if (command === "list") {
2831
- await listSessionsCommand();
2832
- } else if (command === "switch" && arg) {
2833
- console.log(
2834
- formatWarning(
2835
- "Session switching in interactive mode will be available in a future version"
2836
- )
2837
- );
2838
- } else {
2839
- console.error(formatError("Invalid command. Try: sessions list"));
2840
- }
2841
4272
  } else {
2842
4273
  console.error(
2843
4274
  formatError(
2844
- "Unknown command. Type a valid scope: tools, resources, prompts, sessions"
4275
+ "Unknown command. Type a valid scope: tools, resources, prompts"
2845
4276
  )
2846
4277
  );
2847
4278
  }
@@ -2850,63 +4281,98 @@ async function interactiveCommand(options) {
2850
4281
  }
2851
4282
  rl.prompt();
2852
4283
  });
2853
- rl.on("close", () => {
4284
+ rl.on("close", async () => {
2854
4285
  console.log("");
2855
4286
  console.log(formatInfo("Goodbye!"));
2856
- process.exit(0);
4287
+ await cleanupAndExit(0);
2857
4288
  });
2858
4289
  } catch (error) {
2859
4290
  console.error(
2860
4291
  formatError(`Failed to start interactive mode: ${error.message}`)
2861
4292
  );
2862
- process.exit(1);
4293
+ await cleanupAndExit(1);
2863
4294
  }
2864
4295
  }
2865
4296
  function createClientCommand() {
2866
- const clientCommand = new import_commander.Command("client").description(
2867
- "Interactive MCP client for terminal usage"
4297
+ const clientCommand = new import_commander2.Command("client").description(
4298
+ "Interactive MCP client for terminal usage. Use `mcp-use client <name> ...` to run commands against a saved server."
4299
+ ).showHelpAfterError(
4300
+ "(Run `mcp-use client --help` to see available commands)"
4301
+ );
4302
+ clientCommand.command("connect [name] [url]").description(
4303
+ "Connect to an MCP server and save it under a short name. Use the name to address it in later commands (e.g. `mcp-use client <name> tools list`)."
4304
+ ).option("--stdio", "Use stdio connector instead of HTTP").option("--auth <token>", "Static Bearer token (skips OAuth)").option(
4305
+ "--no-oauth",
4306
+ "Don't auto-trigger OAuth on 401; fail with the 401 instead"
4307
+ ).option(
4308
+ "--auth-timeout <ms>",
4309
+ "OAuth loopback wait timeout in ms (default 300000)"
4310
+ ).action(connectCommand);
4311
+ clientCommand.command("list").description("List saved servers").action(listClientsCommand);
4312
+ clientCommand.command("remove <name>").description(
4313
+ "Remove a saved server. Also clears any OAuth tokens for that URL, unless another saved server still uses it."
4314
+ ).action(removeClientCommand);
4315
+ return clientCommand;
4316
+ }
4317
+ function createPerClientCommand(name) {
4318
+ const cmd = new import_commander2.Command(`mcp-use client ${name}`).description(`Commands for server '${name}'`).showHelpAfterError(
4319
+ `(Run \`mcp-use client ${name} --help\` to see available commands)`
2868
4320
  );
2869
- clientCommand.command("connect <url>").description("Connect to an MCP server").option("--name <name>", "Session name").option("--stdio", "Use stdio connector instead of HTTP").option("--auth <token>", "Authentication token").action(connectCommand);
2870
- clientCommand.command("disconnect [session]").description("Disconnect from a session").option("--all", "Disconnect all sessions").action(disconnectCommand);
2871
- const sessionsCommand = new import_commander.Command("sessions").description(
2872
- "Manage CLI sessions"
4321
+ cmd.command("disconnect").description("Disconnect from this server").action(() => disconnectCommand(name));
4322
+ cmd.command("interactive").description("Start interactive REPL mode for this server").action(() => interactiveCommand(name));
4323
+ const toolsCommand = new import_commander2.Command("tools").description("Interact with MCP tools").showHelpAfterError(
4324
+ `(Run \`mcp-use client ${name} tools --help\` to see available actions)`
2873
4325
  );
2874
- sessionsCommand.command("list").description("List all saved sessions").action(listSessionsCommand);
2875
- sessionsCommand.command("switch <name>").description("Switch to a different session").action(switchSessionCommand);
2876
- clientCommand.addCommand(sessionsCommand);
2877
- const toolsCommand = new import_commander.Command("tools").description(
2878
- "Interact with MCP tools"
4326
+ toolsCommand.command("list").description("List available tools").option("--json", "Output as JSON").action((options) => listToolsCommand(name, options));
4327
+ toolsCommand.command("call <tool> [args...]").description(
4328
+ "Call a tool. Args as key=value pairs (use key:=<json> for nested values, or pass a JSON object)"
4329
+ ).option("--timeout <ms>", "Request timeout in milliseconds", parseInt).option("--json", "Output as JSON").option(
4330
+ "--no-screenshot",
4331
+ "Skip the auto-screenshot for tools that render a widget"
4332
+ ).option(
4333
+ "--screenshot-output <path>",
4334
+ "Output PNG path for the widget screenshot (defaults to ./<view>-<timestamp>.png)"
4335
+ ).action(
4336
+ (tool, args, options) => callToolCommand(name, tool, args, options)
2879
4337
  );
2880
- toolsCommand.command("list").description("List available tools").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(listToolsCommand);
2881
- toolsCommand.command("call <name> [args]").description("Call a tool with arguments (JSON string)").option("--session <name>", "Use specific session").option("--timeout <ms>", "Request timeout in milliseconds", parseInt).option("--json", "Output as JSON").action(callToolCommand);
2882
- toolsCommand.command("describe <name>").description("Show tool details and schema").option("--session <name>", "Use specific session").action(describeToolCommand);
2883
- clientCommand.addCommand(toolsCommand);
2884
- const resourcesCommand = new import_commander.Command("resources").description(
2885
- "Interact with MCP resources"
4338
+ toolsCommand.command("describe <tool>").description("Show tool details and schema").action((tool) => describeToolCommand(name, tool));
4339
+ cmd.addCommand(toolsCommand);
4340
+ const resourcesCommand = new import_commander2.Command("resources").description("Interact with MCP resources").showHelpAfterError(
4341
+ `(Run \`mcp-use client ${name} resources --help\` to see available actions)`
2886
4342
  );
2887
- resourcesCommand.command("list").description("List available resources").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(listResourcesCommand);
2888
- resourcesCommand.command("read <uri>").description("Read a resource by URI").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(readResourceCommand);
2889
- resourcesCommand.command("subscribe <uri>").description("Subscribe to resource updates").option("--session <name>", "Use specific session").action(subscribeResourceCommand);
2890
- resourcesCommand.command("unsubscribe <uri>").description("Unsubscribe from resource updates").option("--session <name>", "Use specific session").action(unsubscribeResourceCommand);
2891
- clientCommand.addCommand(resourcesCommand);
2892
- const promptsCommand = new import_commander.Command("prompts").description(
2893
- "Interact with MCP prompts"
4343
+ resourcesCommand.command("list").description("List available resources").option("--json", "Output as JSON").action((options) => listResourcesCommand(name, options));
4344
+ resourcesCommand.command("read <uri>").description("Read a resource by URI").option("--json", "Output as JSON").action((uri, options) => readResourceCommand(name, uri, options));
4345
+ resourcesCommand.command("subscribe <uri>").description("Subscribe to resource updates").action((uri) => subscribeResourceCommand(name, uri));
4346
+ resourcesCommand.command("unsubscribe <uri>").description("Unsubscribe from resource updates").action((uri) => unsubscribeResourceCommand(name, uri));
4347
+ cmd.addCommand(resourcesCommand);
4348
+ const promptsCommand = new import_commander2.Command("prompts").description("Interact with MCP prompts").showHelpAfterError(
4349
+ `(Run \`mcp-use client ${name} prompts --help\` to see available actions)`
2894
4350
  );
2895
- promptsCommand.command("list").description("List available prompts").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(listPromptsCommand);
2896
- promptsCommand.command("get <name> [args]").description("Get a prompt with arguments (JSON string)").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(getPromptCommand);
2897
- clientCommand.addCommand(promptsCommand);
2898
- clientCommand.command("interactive").description("Start interactive REPL mode").option("--session <name>", "Use specific session").action(interactiveCommand);
2899
- return clientCommand;
4351
+ promptsCommand.command("list").description("List available prompts").option("--json", "Output as JSON").action((options) => listPromptsCommand(name, options));
4352
+ promptsCommand.command("get <prompt> [args...]").description(
4353
+ "Get a prompt. Args as key=value pairs (or pass a JSON object)"
4354
+ ).option("--json", "Output as JSON").action(
4355
+ (prompt4, args, options) => getPromptCommand(name, prompt4, args, options)
4356
+ );
4357
+ cmd.addCommand(promptsCommand);
4358
+ const authCommand = new import_commander2.Command("auth").description("Manage OAuth tokens for HTTP servers").showHelpAfterError(
4359
+ `(Run \`mcp-use client ${name} auth --help\` to see available actions)`
4360
+ );
4361
+ authCommand.command("status").description("Show OAuth token status for this server").action(() => authStatusCommand(name));
4362
+ authCommand.command("refresh").description("Force-refresh the OAuth access token").action(() => authRefreshCommand(name));
4363
+ authCommand.command("logout").description("Remove stored OAuth tokens for this server's URL").action(() => authLogoutCommand(name));
4364
+ cmd.addCommand(authCommand);
4365
+ return cmd;
2900
4366
  }
2901
4367
 
2902
4368
  // src/commands/deploy.ts
2903
- var import_node_fs7 = require("fs");
2904
- var import_node_path5 = __toESM(require("path"), 1);
4369
+ var import_node_fs10 = require("fs");
4370
+ var import_node_path8 = __toESM(require("path"), 1);
2905
4371
 
2906
4372
  // src/utils/git.ts
2907
- var import_node_child_process8 = require("child_process");
4373
+ var import_node_child_process10 = require("child_process");
2908
4374
  var import_node_util7 = require("util");
2909
- var execFileAsync5 = (0, import_node_util7.promisify)(import_node_child_process8.execFile);
4375
+ var execFileAsync5 = (0, import_node_util7.promisify)(import_node_child_process10.execFile);
2910
4376
  async function gitCommand(args, cwd = process.cwd()) {
2911
4377
  try {
2912
4378
  const { stdout } = await execFileAsync5("git", args, { cwd });
@@ -3055,17 +4521,17 @@ function getMcpServerUrlForCloudServer(server) {
3055
4521
  }
3056
4522
 
3057
4523
  // src/utils/project-link.ts
3058
- var import_node_fs6 = require("fs");
3059
- var import_node_path4 = __toESM(require("path"), 1);
4524
+ var import_node_fs9 = require("fs");
4525
+ var import_node_path7 = __toESM(require("path"), 1);
3060
4526
  var MCP_USE_DIR = ".mcp-use";
3061
4527
  var MCP_USE_DIR_PROJECT = "project.json";
3062
4528
  function getMcpUseDirectory(cwd) {
3063
- return import_node_path4.default.join(cwd, MCP_USE_DIR);
4529
+ return import_node_path7.default.join(cwd, MCP_USE_DIR);
3064
4530
  }
3065
4531
  async function getProjectLink(cwd) {
3066
4532
  try {
3067
- const linkPath = import_node_path4.default.join(getMcpUseDirectory(cwd), MCP_USE_DIR_PROJECT);
3068
- const content = await import_node_fs6.promises.readFile(linkPath, "utf-8");
4533
+ const linkPath = import_node_path7.default.join(getMcpUseDirectory(cwd), MCP_USE_DIR_PROJECT);
4534
+ const content = await import_node_fs9.promises.readFile(linkPath, "utf-8");
3069
4535
  return JSON.parse(content);
3070
4536
  } catch (err) {
3071
4537
  if (err.code === "ENOENT") return null;
@@ -3074,17 +4540,17 @@ async function getProjectLink(cwd) {
3074
4540
  }
3075
4541
  async function saveProjectLink(cwd, link) {
3076
4542
  const mcpUseDir = getMcpUseDirectory(cwd);
3077
- await import_node_fs6.promises.mkdir(mcpUseDir, { recursive: true });
3078
- const linkPath = import_node_path4.default.join(mcpUseDir, MCP_USE_DIR_PROJECT);
3079
- await import_node_fs6.promises.writeFile(linkPath, JSON.stringify(link, null, 2), "utf-8");
4543
+ await import_node_fs9.promises.mkdir(mcpUseDir, { recursive: true });
4544
+ const linkPath = import_node_path7.default.join(mcpUseDir, MCP_USE_DIR_PROJECT);
4545
+ await import_node_fs9.promises.writeFile(linkPath, JSON.stringify(link, null, 2), "utf-8");
3080
4546
  await addToGitIgnore(cwd);
3081
4547
  }
3082
4548
  async function addToGitIgnore(cwd) {
3083
- const gitignorePath = import_node_path4.default.join(cwd, ".gitignore");
4549
+ const gitignorePath = import_node_path7.default.join(cwd, ".gitignore");
3084
4550
  try {
3085
4551
  let content = "";
3086
4552
  try {
3087
- content = await import_node_fs6.promises.readFile(gitignorePath, "utf-8");
4553
+ content = await import_node_fs9.promises.readFile(gitignorePath, "utf-8");
3088
4554
  } catch (err) {
3089
4555
  if (err.code !== "ENOENT") throw err;
3090
4556
  }
@@ -3093,7 +4559,7 @@ async function addToGitIgnore(cwd) {
3093
4559
  # mcp-use deployment
3094
4560
  ${MCP_USE_DIR}
3095
4561
  `;
3096
- await import_node_fs6.promises.writeFile(gitignorePath, newContent, "utf-8");
4562
+ await import_node_fs9.promises.writeFile(gitignorePath, newContent, "utf-8");
3097
4563
  }
3098
4564
  } catch (err) {
3099
4565
  }
@@ -3102,7 +4568,7 @@ ${MCP_USE_DIR}
3102
4568
  // src/commands/deploy.ts
3103
4569
  async function parseEnvFile(filePath) {
3104
4570
  try {
3105
- const content = await import_node_fs7.promises.readFile(filePath, "utf-8");
4571
+ const content = await import_node_fs10.promises.readFile(filePath, "utf-8");
3106
4572
  const envVars = {};
3107
4573
  const lines = content.split("\n");
3108
4574
  let currentKey = null;
@@ -3221,7 +4687,7 @@ async function buildEnvVars(options) {
3221
4687
  }
3222
4688
  async function isMcpProject(cwd = process.cwd()) {
3223
4689
  try {
3224
- const content = await import_node_fs7.promises.readFile(import_node_path5.default.join(cwd, "package.json"), "utf-8");
4690
+ const content = await import_node_fs10.promises.readFile(import_node_path8.default.join(cwd, "package.json"), "utf-8");
3225
4691
  const pkg = JSON.parse(content);
3226
4692
  return !!(pkg.dependencies?.["mcp-use"] || pkg.dependencies?.["@modelcontextprotocol/sdk"] || pkg.devDependencies?.["mcp-use"] || pkg.devDependencies?.["@modelcontextprotocol/sdk"]);
3227
4693
  } catch {
@@ -3230,16 +4696,16 @@ async function isMcpProject(cwd = process.cwd()) {
3230
4696
  }
3231
4697
  async function getProjectName(cwd = process.cwd()) {
3232
4698
  try {
3233
- const content = await import_node_fs7.promises.readFile(import_node_path5.default.join(cwd, "package.json"), "utf-8");
4699
+ const content = await import_node_fs10.promises.readFile(import_node_path8.default.join(cwd, "package.json"), "utf-8");
3234
4700
  const pkg = JSON.parse(content);
3235
4701
  if (pkg.name) return pkg.name;
3236
4702
  } catch {
3237
4703
  }
3238
- return import_node_path5.default.basename(cwd);
4704
+ return import_node_path8.default.basename(cwd);
3239
4705
  }
3240
4706
  async function detectBuildCommand(cwd) {
3241
4707
  try {
3242
- const content = await import_node_fs7.promises.readFile(import_node_path5.default.join(cwd, "package.json"), "utf-8");
4708
+ const content = await import_node_fs10.promises.readFile(import_node_path8.default.join(cwd, "package.json"), "utf-8");
3243
4709
  if (JSON.parse(content).scripts?.build) return "npm run build";
3244
4710
  } catch {
3245
4711
  }
@@ -3247,7 +4713,7 @@ async function detectBuildCommand(cwd) {
3247
4713
  }
3248
4714
  async function detectStartCommand(cwd) {
3249
4715
  try {
3250
- const content = await import_node_fs7.promises.readFile(import_node_path5.default.join(cwd, "package.json"), "utf-8");
4716
+ const content = await import_node_fs10.promises.readFile(import_node_path8.default.join(cwd, "package.json"), "utf-8");
3251
4717
  const pkg = JSON.parse(content);
3252
4718
  if (pkg.scripts?.start) return "npm start";
3253
4719
  if (pkg.main) return `node ${pkg.main}`;
@@ -3258,7 +4724,7 @@ async function detectStartCommand(cwd) {
3258
4724
  async function detectRuntime(cwd) {
3259
4725
  for (const f of ["requirements.txt", "pyproject.toml", "setup.py"]) {
3260
4726
  try {
3261
- await import_node_fs7.promises.access(import_node_path5.default.join(cwd, f));
4727
+ await import_node_fs10.promises.access(import_node_path8.default.join(cwd, f));
3262
4728
  return "python";
3263
4729
  } catch {
3264
4730
  continue;
@@ -3305,17 +4771,17 @@ var REQUIRED_IGNORES = [
3305
4771
  ".mcp-use"
3306
4772
  ];
3307
4773
  async function ensureGitignore(cwd) {
3308
- const gitignorePath = import_node_path5.default.join(cwd, ".gitignore");
4774
+ const gitignorePath = import_node_path8.default.join(cwd, ".gitignore");
3309
4775
  let content = "";
3310
4776
  try {
3311
- content = await import_node_fs7.promises.readFile(gitignorePath, "utf-8");
4777
+ content = await import_node_fs10.promises.readFile(gitignorePath, "utf-8");
3312
4778
  } catch {
3313
4779
  }
3314
4780
  const missing = REQUIRED_IGNORES.filter((entry) => !content.includes(entry));
3315
4781
  if (missing.length > 0) {
3316
4782
  const additions = missing.join("\n");
3317
4783
  const newContent = content + (content.endsWith("\n") ? "" : "\n") + additions + "\n";
3318
- await import_node_fs7.promises.writeFile(gitignorePath, newContent, "utf-8");
4784
+ await import_node_fs10.promises.writeFile(gitignorePath, newContent, "utf-8");
3319
4785
  }
3320
4786
  }
3321
4787
  async function displayDeploymentProgress(api, deploymentId, progressOptions) {
@@ -3765,10 +5231,10 @@ async function deployCommand(options) {
3765
5231
  console.log(source_default.green("\u2713 GitHub connected\n"));
3766
5232
  let installationDbId;
3767
5233
  let githubInstallationId;
3768
- const projectDir = options.rootDir ? import_node_path5.default.resolve(cwd, options.rootDir) : cwd;
5234
+ const projectDir = options.rootDir ? import_node_path8.default.resolve(cwd, options.rootDir) : cwd;
3769
5235
  if (options.rootDir) {
3770
5236
  try {
3771
- await import_node_fs7.promises.access(projectDir);
5237
+ await import_node_fs10.promises.access(projectDir);
3772
5238
  } catch {
3773
5239
  console.log(
3774
5240
  source_default.red(`\u2717 Root directory not found: ${options.rootDir}`)
@@ -4277,7 +5743,7 @@ async function deployCommand(options) {
4277
5743
  }
4278
5744
 
4279
5745
  // src/commands/deployments.ts
4280
- var import_commander2 = require("commander");
5746
+ var import_commander3 = require("commander");
4281
5747
  async function prompt2(question) {
4282
5748
  const readline = await import("readline");
4283
5749
  const rl = readline.createInterface({
@@ -4689,8 +6155,8 @@ async function startDeploymentCommand(deploymentId) {
4689
6155
  }
4690
6156
  }
4691
6157
  function createDeploymentsCommand() {
4692
- const deploymentsCommand = new import_commander2.Command("deployments").description(
4693
- "Manage cloud deployments"
6158
+ const deploymentsCommand = new import_commander3.Command("deployments").description("Manage cloud deployments").showHelpAfterError(
6159
+ "(Run `mcp-use deployments --help` to see available commands)"
4694
6160
  );
4695
6161
  deploymentsCommand.command("list").alias("ls").description("List all deployments").action(listDeploymentsCommand);
4696
6162
  deploymentsCommand.command("get").argument("<deployment-id>", "Deployment ID").description("Get deployment details").action(getDeploymentCommand);
@@ -4705,10 +6171,10 @@ function createDeploymentsCommand() {
4705
6171
  }
4706
6172
 
4707
6173
  // src/commands/servers.ts
4708
- var import_commander4 = require("commander");
6174
+ var import_commander5 = require("commander");
4709
6175
 
4710
6176
  // src/commands/env.ts
4711
- var import_commander3 = require("commander");
6177
+ var import_commander4 = require("commander");
4712
6178
  var ALL_ENVS = ["production", "preview", "development"];
4713
6179
  function parseEnvironments(raw) {
4714
6180
  const parts = raw.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean);
@@ -4853,9 +6319,7 @@ async function removeEnvCommand(varId, options) {
4853
6319
  }
4854
6320
  }
4855
6321
  function createEnvCommand() {
4856
- const envCommand = new import_commander3.Command("env").description(
4857
- "Manage environment variables for a server"
4858
- );
6322
+ const envCommand = new import_commander4.Command("env").description("Manage environment variables for a server").showHelpAfterError("(Run `mcp-use env --help` to see available commands)");
4859
6323
  envCommand.command("list").alias("ls").description("List environment variables for a server").requiredOption("--server <id>", "Server UUID").option("--show-values", "Reveal non-sensitive values in output").action(listEnvCommand);
4860
6324
  envCommand.command("add").argument("<KEY=VALUE>", "Variable assignment, e.g. API_KEY=abc123").description("Add an environment variable to a server").requiredOption("--server <id>", "Server UUID").option(
4861
6325
  "--env <environments>",
@@ -5137,8 +6601,8 @@ async function deleteServerCommand(serverId, options) {
5137
6601
  }
5138
6602
  }
5139
6603
  function createServersCommand() {
5140
- const serversCommand = new import_commander4.Command("servers").description(
5141
- "Manage cloud servers (Git-backed deploy targets)"
6604
+ const serversCommand = new import_commander5.Command("servers").description("Manage cloud servers (Git-backed deploy targets)").showHelpAfterError(
6605
+ "(Run `mcp-use servers --help` to see available commands)"
5142
6606
  );
5143
6607
  serversCommand.command("list").alias("ls").description("List servers for the current organization").option("--org <slug-or-id>", "Target organization (slug, id, or name)").option("--limit <n>", "Page size (1\u2013100, default 50)").option("--skip <n>", "Offset for pagination").option("--sort <field:asc|desc>", "Sort (e.g. updatedAt:desc)").action(listServersCommand);
5144
6608
  serversCommand.command("get").argument("<id-or-slug>", "Server UUID or slug").option("--org <slug-or-id>", "Resolve org context before fetch").description("Show server details and recent deployments").action(getServerCommand);
@@ -5255,12 +6719,12 @@ async function orgCurrentCommand() {
5255
6719
  }
5256
6720
 
5257
6721
  // src/commands/skills.ts
5258
- var import_commander5 = require("commander");
5259
- var import_node_fs8 = require("fs");
5260
- var import_node_os5 = require("os");
5261
- var import_node_path6 = require("path");
6722
+ var import_commander6 = require("commander");
6723
+ var import_node_fs11 = require("fs");
6724
+ var import_node_os6 = require("os");
6725
+ var import_node_path9 = require("path");
5262
6726
  var import_node_stream = require("stream");
5263
- var import_promises5 = require("stream/promises");
6727
+ var import_promises6 = require("stream/promises");
5264
6728
  var import_tar = require("tar");
5265
6729
  var REPO_OWNER = "mcp-use";
5266
6730
  var REPO_NAME = "mcp-use";
@@ -5295,42 +6759,42 @@ function sendInstallTelemetryEvent(agents, skills) {
5295
6759
  }
5296
6760
  async function addSkillsToProject(projectPath) {
5297
6761
  const tarballUrl = `https://codeload.github.com/${REPO_OWNER}/${REPO_NAME}/tar.gz/${REPO_BRANCH}`;
5298
- const tempDir = (0, import_node_fs8.mkdtempSync)((0, import_node_path6.join)((0, import_node_os5.tmpdir)(), "mcp-use-skills-"));
6762
+ const tempDir = (0, import_node_fs11.mkdtempSync)((0, import_node_path9.join)((0, import_node_os6.tmpdir)(), "mcp-use-skills-"));
5299
6763
  try {
5300
6764
  const response = await fetch(tarballUrl);
5301
6765
  if (!response.ok) {
5302
6766
  throw new Error(`Failed to download tarball: ${response.statusText}`);
5303
6767
  }
5304
- await (0, import_promises5.pipeline)(
6768
+ await (0, import_promises6.pipeline)(
5305
6769
  import_node_stream.Readable.fromWeb(response.body),
5306
6770
  (0, import_tar.extract)({
5307
6771
  cwd: tempDir,
5308
- filter: (path8) => path8.includes("/skills/"),
6772
+ filter: (path11) => path11.includes("/skills/"),
5309
6773
  strip: 1
5310
6774
  })
5311
6775
  );
5312
- const skillsPath = (0, import_node_path6.join)(tempDir, "skills");
5313
- if (!(0, import_node_fs8.existsSync)(skillsPath)) {
6776
+ const skillsPath = (0, import_node_path9.join)(tempDir, "skills");
6777
+ if (!(0, import_node_fs11.existsSync)(skillsPath)) {
5314
6778
  throw new Error("Skills folder not found in repository");
5315
6779
  }
5316
6780
  for (const preset of ALL_PRESETS) {
5317
6781
  const folderName = AGENT_PRESET_FOLDERS[preset];
5318
- const outputPath = (0, import_node_path6.join)(projectPath, folderName, "skills");
5319
- (0, import_node_fs8.cpSync)(skillsPath, outputPath, { recursive: true });
6782
+ const outputPath = (0, import_node_path9.join)(projectPath, folderName, "skills");
6783
+ (0, import_node_fs11.cpSync)(skillsPath, outputPath, { recursive: true });
5320
6784
  }
5321
- const skillNames = (0, import_node_fs8.readdirSync)(skillsPath, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
6785
+ const skillNames = (0, import_node_fs11.readdirSync)(skillsPath, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
5322
6786
  sendInstallTelemetryEvent(ALL_PRESETS.join(","), skillNames.join(","));
5323
6787
  } finally {
5324
- (0, import_node_fs8.rmSync)(tempDir, { recursive: true, force: true });
6788
+ (0, import_node_fs11.rmSync)(tempDir, { recursive: true, force: true });
5325
6789
  }
5326
6790
  }
5327
6791
  function createSkillsCommand() {
5328
- const skills = new import_commander5.Command("skills").description(
5329
- "Manage mcp-use AI agent skills"
6792
+ const skills = new import_commander6.Command("skills").description("Manage mcp-use AI agent skills").showHelpAfterError(
6793
+ "(Run `mcp-use skills --help` to see available commands)"
5330
6794
  );
5331
6795
  const installAction = async (options) => {
5332
- const projectPath = (0, import_node_path6.resolve)(options.path);
5333
- if (!(0, import_node_fs8.existsSync)(projectPath)) {
6796
+ const projectPath = (0, import_node_path9.resolve)(options.path);
6797
+ if (!(0, import_node_fs11.existsSync)(projectPath)) {
5334
6798
  console.error(source_default.red(`Directory not found: ${projectPath}`));
5335
6799
  process.exit(1);
5336
6800
  }
@@ -5371,13 +6835,13 @@ function createSkillsCommand() {
5371
6835
  }
5372
6836
 
5373
6837
  // src/utils/next-shims.ts
5374
- var import_node_fs9 = require("fs");
5375
- var import_node_path7 = __toESM(require("path"), 1);
6838
+ var import_node_fs12 = require("fs");
6839
+ var import_node_path10 = __toESM(require("path"), 1);
5376
6840
  var import_node_url2 = require("url");
5377
6841
  async function detectNextJsProject(projectPath) {
5378
6842
  try {
5379
- const pkgPath = import_node_path7.default.join(projectPath, "package.json");
5380
- const content = await import_node_fs9.promises.readFile(pkgPath, "utf-8");
6843
+ const pkgPath = import_node_path10.default.join(projectPath, "package.json");
6844
+ const content = await import_node_fs12.promises.readFile(pkgPath, "utf-8");
5381
6845
  const pkg = JSON.parse(content);
5382
6846
  const deps = pkg.dependencies ?? {};
5383
6847
  const devDeps = pkg.devDependencies ?? {};
@@ -5395,9 +6859,9 @@ async function loadNextJsEnvFiles(projectPath) {
5395
6859
  ];
5396
6860
  const dotenv = await import("dotenv");
5397
6861
  for (const file of files) {
5398
- const abs = import_node_path7.default.join(projectPath, file);
6862
+ const abs = import_node_path10.default.join(projectPath, file);
5399
6863
  try {
5400
- await import_node_fs9.promises.access(abs);
6864
+ await import_node_fs12.promises.access(abs);
5401
6865
  } catch {
5402
6866
  continue;
5403
6867
  }
@@ -5407,20 +6871,20 @@ async function loadNextJsEnvFiles(projectPath) {
5407
6871
  function getThisDir() {
5408
6872
  if (typeof __dirname === "string") return __dirname;
5409
6873
  const url = importMetaUrl;
5410
- return import_node_path7.default.dirname((0, import_node_url2.fileURLToPath)(url));
6874
+ return import_node_path10.default.dirname((0, import_node_url2.fileURLToPath)(url));
5411
6875
  }
5412
6876
  function resolveShimPath(filename) {
5413
6877
  const thisDir = getThisDir();
5414
6878
  const candidates = [
5415
6879
  // Production: `dist/` next to this module
5416
- import_node_path7.default.join(thisDir, "shims", filename),
6880
+ import_node_path10.default.join(thisDir, "shims", filename),
5417
6881
  // Test / dev: one level up (e.g., from `dist/utils/` back to `src/shims/`)
5418
- import_node_path7.default.join(thisDir, "..", "shims", filename),
5419
- import_node_path7.default.join(thisDir, "..", "..", "src", "shims", filename),
5420
- import_node_path7.default.join(thisDir, "..", "src", "shims", filename)
6882
+ import_node_path10.default.join(thisDir, "..", "shims", filename),
6883
+ import_node_path10.default.join(thisDir, "..", "..", "src", "shims", filename),
6884
+ import_node_path10.default.join(thisDir, "..", "src", "shims", filename)
5421
6885
  ];
5422
6886
  for (const candidate of candidates) {
5423
- if ((0, import_node_fs9.existsSync)(candidate)) return candidate;
6887
+ if ((0, import_node_fs12.existsSync)(candidate)) return candidate;
5424
6888
  }
5425
6889
  return void 0;
5426
6890
  }
@@ -5438,7 +6902,7 @@ async function registerNextShimsInProcess() {
5438
6902
  const cjsPath = getShimCjsPreloadPath();
5439
6903
  if (cjsPath) {
5440
6904
  const { createRequire: createRequire3 } = await import("module");
5441
- const req = createRequire3((0, import_node_url2.pathToFileURL)(getThisDir() + import_node_path7.default.sep).href);
6905
+ const req = createRequire3((0, import_node_url2.pathToFileURL)(getThisDir() + import_node_path10.default.sep).href);
5442
6906
  req(cjsPath);
5443
6907
  anyRegistered = true;
5444
6908
  }
@@ -5446,7 +6910,7 @@ async function registerNextShimsInProcess() {
5446
6910
  if (loaderPath) {
5447
6911
  const { register } = await import("module");
5448
6912
  const loaderUrl = (0, import_node_url2.pathToFileURL)(loaderPath).href;
5449
- register(loaderUrl, (0, import_node_url2.pathToFileURL)(getThisDir() + import_node_path7.default.sep).href);
6913
+ register(loaderUrl, (0, import_node_url2.pathToFileURL)(getThisDir() + import_node_path10.default.sep).href);
5450
6914
  anyRegistered = true;
5451
6915
  }
5452
6916
  return anyRegistered;
@@ -5471,13 +6935,13 @@ function quoteNodeOption(value) {
5471
6935
  }
5472
6936
 
5473
6937
  // src/utils/update-check.ts
5474
- var import_node_fs10 = require("fs");
5475
- var import_promises6 = require("fs/promises");
6938
+ var import_node_fs13 = require("fs");
6939
+ var import_promises7 = require("fs/promises");
5476
6940
  var import_node_module = require("module");
5477
- var import_node_os6 = __toESM(require("os"), 1);
5478
- var import_node_path8 = __toESM(require("path"), 1);
5479
- var CACHE_DIR = import_node_path8.default.join(import_node_os6.default.homedir(), ".mcp-use");
5480
- var CACHE_FILE = import_node_path8.default.join(CACHE_DIR, "update-check.json");
6941
+ var import_node_os7 = __toESM(require("os"), 1);
6942
+ var import_node_path11 = __toESM(require("path"), 1);
6943
+ var CACHE_DIR = import_node_path11.default.join(import_node_os7.default.homedir(), ".mcp-use");
6944
+ var CACHE_FILE = import_node_path11.default.join(CACHE_DIR, "update-check.json");
5481
6945
  var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
5482
6946
  var FETCH_TIMEOUT_MS = 3e3;
5483
6947
  var PACKAGE_NAME = "mcp-use";
@@ -5502,7 +6966,7 @@ function isNewer(current, candidate) {
5502
6966
  }
5503
6967
  async function readCache() {
5504
6968
  try {
5505
- const content = await (0, import_promises6.readFile)(CACHE_FILE, "utf-8");
6969
+ const content = await (0, import_promises7.readFile)(CACHE_FILE, "utf-8");
5506
6970
  return JSON.parse(content);
5507
6971
  } catch {
5508
6972
  return null;
@@ -5510,12 +6974,12 @@ async function readCache() {
5510
6974
  }
5511
6975
  async function writeCache(latestVersion) {
5512
6976
  try {
5513
- await (0, import_promises6.mkdir)(CACHE_DIR, { recursive: true });
6977
+ await (0, import_promises7.mkdir)(CACHE_DIR, { recursive: true });
5514
6978
  const cache = {
5515
6979
  lastChecked: (/* @__PURE__ */ new Date()).toISOString(),
5516
6980
  latestVersion
5517
6981
  };
5518
- await (0, import_promises6.writeFile)(CACHE_FILE, JSON.stringify(cache, null, 2), "utf-8");
6982
+ await (0, import_promises7.writeFile)(CACHE_FILE, JSON.stringify(cache, null, 2), "utf-8");
5519
6983
  } catch {
5520
6984
  }
5521
6985
  }
@@ -5560,16 +7024,16 @@ function resolveInstalledVersion(projectPath) {
5560
7024
  if (projectPath) {
5561
7025
  attempts.push(() => {
5562
7026
  const projectRequire = (0, import_node_module.createRequire)(
5563
- import_node_path8.default.join(projectPath, "package.json")
7027
+ import_node_path11.default.join(projectPath, "package.json")
5564
7028
  );
5565
7029
  return projectRequire.resolve(`${PACKAGE_NAME}/package.json`);
5566
7030
  });
5567
7031
  }
5568
- attempts.push(() => import_node_path8.default.join(__dirname, "../../mcp-use/package.json"));
7032
+ attempts.push(() => import_node_path11.default.join(__dirname, "../../mcp-use/package.json"));
5569
7033
  for (const attempt of attempts) {
5570
7034
  try {
5571
7035
  const pkgPath = attempt();
5572
- const json = JSON.parse((0, import_node_fs10.readFileSync)(pkgPath, "utf-8"));
7036
+ const json = JSON.parse((0, import_node_fs13.readFileSync)(pkgPath, "utf-8"));
5573
7037
  if (typeof json.version === "string") return json.version;
5574
7038
  } catch {
5575
7039
  }
@@ -5601,14 +7065,14 @@ A new release of ${source_default.bold(PACKAGE_NAME)} is available: ${source_def
5601
7065
  }
5602
7066
 
5603
7067
  // src/index.ts
5604
- var program = new import_commander6.Command();
5605
- var packageContent = (0, import_node_fs11.readFileSync)(
5606
- import_node_path9.default.join(__dirname, "../package.json"),
7068
+ var program = new import_commander7.Command();
7069
+ var packageContent = (0, import_node_fs14.readFileSync)(
7070
+ import_node_path12.default.join(__dirname, "../package.json"),
5607
7071
  "utf-8"
5608
7072
  );
5609
7073
  var packageJson = JSON.parse(packageContent);
5610
7074
  var packageVersion = packageJson.version || "unknown";
5611
- program.name("mcp-use").description("Create and run MCP servers with ui resources widgets").version(packageVersion);
7075
+ program.name("mcp-use").description("Create and run MCP servers with ui resources widgets").version(packageVersion).showHelpAfterError("(Run `mcp-use --help` to see available commands)");
5612
7076
  function displayPackageVersions(projectPath) {
5613
7077
  const packages = [
5614
7078
  { name: "@mcp-use/cli", relativePath: "../package.json" },
@@ -5634,16 +7098,16 @@ function displayPackageVersions(projectPath) {
5634
7098
  if (projectPath) {
5635
7099
  try {
5636
7100
  const projectRequire = (0, import_node_module2.createRequire)(
5637
- import_node_path9.default.join(projectPath, "package.json")
7101
+ import_node_path12.default.join(projectPath, "package.json")
5638
7102
  );
5639
7103
  pkgPath = projectRequire.resolve(`${pkg.name}/package.json`);
5640
7104
  } catch (resolveError) {
5641
- pkgPath = import_node_path9.default.join(__dirname, pkg.relativePath);
7105
+ pkgPath = import_node_path12.default.join(__dirname, pkg.relativePath);
5642
7106
  }
5643
7107
  } else {
5644
- pkgPath = import_node_path9.default.join(__dirname, pkg.relativePath);
7108
+ pkgPath = import_node_path12.default.join(__dirname, pkg.relativePath);
5645
7109
  }
5646
- const pkgContent = (0, import_node_fs11.readFileSync)(pkgPath, "utf-8");
7110
+ const pkgContent = (0, import_node_fs14.readFileSync)(pkgPath, "utf-8");
5647
7111
  const pkgJson = JSON.parse(pkgContent);
5648
7112
  const version = pkgJson.version || "unknown";
5649
7113
  if (pkg.highlight) {
@@ -5698,7 +7162,7 @@ function normalizeBrowserHost(host) {
5698
7162
  return host === "0.0.0.0" ? "localhost" : host;
5699
7163
  }
5700
7164
  function runCommand(command, args, cwd, env2, filterStderr = false) {
5701
- const proc = (0, import_node_child_process9.spawn)(command, args, {
7165
+ const proc = (0, import_node_child_process11.spawn)(command, args, {
5702
7166
  cwd,
5703
7167
  stdio: filterStderr ? ["inherit", "inherit", "pipe"] : "inherit",
5704
7168
  shell: process.platform === "win32",
@@ -5731,7 +7195,7 @@ async function startTunnel(port, subdomain) {
5731
7195
  if (subdomain) {
5732
7196
  tunnelArgs.push("--subdomain", subdomain);
5733
7197
  }
5734
- const proc = (0, import_node_child_process9.spawn)("npx", tunnelArgs, {
7198
+ const proc = (0, import_node_child_process11.spawn)("npx", tunnelArgs, {
5735
7199
  stdio: ["ignore", "pipe", "pipe"],
5736
7200
  shell: process.platform === "win32"
5737
7201
  });
@@ -5795,21 +7259,21 @@ async function startTunnel(port, subdomain) {
5795
7259
  }
5796
7260
  async function resolveEntryFile(projectPath, cliEntry, mcpDir) {
5797
7261
  if (cliEntry) {
5798
- await (0, import_promises7.access)(import_node_path9.default.join(projectPath, cliEntry)).catch(() => {
7262
+ await (0, import_promises8.access)(import_node_path12.default.join(projectPath, cliEntry)).catch(() => {
5799
7263
  throw new Error(`File not found: ${cliEntry}`);
5800
7264
  });
5801
7265
  return cliEntry;
5802
7266
  }
5803
7267
  if (mcpDir) {
5804
7268
  const mcpCandidates = [
5805
- import_node_path9.default.join(mcpDir, "index.ts"),
5806
- import_node_path9.default.join(mcpDir, "index.tsx"),
5807
- import_node_path9.default.join(mcpDir, "server.ts"),
5808
- import_node_path9.default.join(mcpDir, "server.tsx")
7269
+ import_node_path12.default.join(mcpDir, "index.ts"),
7270
+ import_node_path12.default.join(mcpDir, "index.tsx"),
7271
+ import_node_path12.default.join(mcpDir, "server.ts"),
7272
+ import_node_path12.default.join(mcpDir, "server.tsx")
5809
7273
  ];
5810
7274
  for (const candidate of mcpCandidates) {
5811
7275
  try {
5812
- await (0, import_promises7.access)(import_node_path9.default.join(projectPath, candidate));
7276
+ await (0, import_promises8.access)(import_node_path12.default.join(projectPath, candidate));
5813
7277
  return candidate;
5814
7278
  } catch {
5815
7279
  continue;
@@ -5818,17 +7282,17 @@ async function resolveEntryFile(projectPath, cliEntry, mcpDir) {
5818
7282
  throw new Error(
5819
7283
  `No entry file found inside ${mcpDir}.
5820
7284
 
5821
- Expected one of: ${mcpCandidates.map((c) => import_node_path9.default.relative(projectPath, import_node_path9.default.join(projectPath, c))).join(", ")}
7285
+ Expected one of: ${mcpCandidates.map((c) => import_node_path12.default.relative(projectPath, import_node_path12.default.join(projectPath, c))).join(", ")}
5822
7286
 
5823
7287
  Fix this by either:
5824
- 1. Creating ${import_node_path9.default.join(mcpDir, "index.ts")}, or
7288
+ 1. Creating ${import_node_path12.default.join(mcpDir, "index.ts")}, or
5825
7289
  2. Passing --entry <file> on the command line`
5826
7290
  );
5827
7291
  }
5828
7292
  const candidates = ["index.ts", "src/index.ts", "server.ts", "src/server.ts"];
5829
7293
  for (const candidate of candidates) {
5830
7294
  try {
5831
- await (0, import_promises7.access)(import_node_path9.default.join(projectPath, candidate));
7295
+ await (0, import_promises8.access)(import_node_path12.default.join(projectPath, candidate));
5832
7296
  return candidate;
5833
7297
  } catch {
5834
7298
  continue;
@@ -5846,7 +7310,7 @@ Fix this by either:
5846
7310
  }
5847
7311
  function resolveWidgetsDir(cliWidgetsDir, mcpDir) {
5848
7312
  if (cliWidgetsDir) return cliWidgetsDir;
5849
- if (mcpDir) return import_node_path9.default.join(mcpDir, "resources");
7313
+ if (mcpDir) return import_node_path12.default.join(mcpDir, "resources");
5850
7314
  return "resources";
5851
7315
  }
5852
7316
  function makeWidgetServerOnlyGuard(widgetName) {
@@ -5881,8 +7345,8 @@ function isBunRuntime() {
5881
7345
  return typeof globalThis.Bun !== "undefined" || typeof process.versions.bun === "string";
5882
7346
  }
5883
7347
  async function generateToolRegistryTypesForServer(projectPath, serverFileRelative) {
5884
- const serverFile = import_node_path9.default.join(projectPath, serverFileRelative);
5885
- const serverFileExists = await (0, import_promises7.access)(serverFile).then(() => true).catch(() => false);
7348
+ const serverFile = import_node_path12.default.join(projectPath, serverFileRelative);
7349
+ const serverFileExists = await (0, import_promises8.access)(serverFile).then(() => true).catch(() => false);
5886
7350
  if (!serverFileExists) {
5887
7351
  throw new Error(`Server file not found: ${serverFile}`);
5888
7352
  }
@@ -5907,8 +7371,8 @@ async function generateToolRegistryTypesForServer(projectPath, serverFileRelativ
5907
7371
  await loadNextJsEnvFiles(projectPath);
5908
7372
  await registerNextShimsInProcess();
5909
7373
  }
5910
- const projectTsconfigPath = import_node_path9.default.join(projectPath, "tsconfig.json");
5911
- const hasTsconfig = await (0, import_promises7.access)(projectTsconfigPath).then(() => true).catch(() => false);
7374
+ const projectTsconfigPath = import_node_path12.default.join(projectPath, "tsconfig.json");
7375
+ const hasTsconfig = await (0, import_promises8.access)(projectTsconfigPath).then(() => true).catch(() => false);
5912
7376
  if (hasTsconfig) {
5913
7377
  process.env.TSX_TSCONFIG_PATH = projectTsconfigPath;
5914
7378
  }
@@ -5916,7 +7380,7 @@ async function generateToolRegistryTypesForServer(projectPath, serverFileRelativ
5916
7380
  if (previousCwd !== projectPath) process.chdir(projectPath);
5917
7381
  try {
5918
7382
  const projectRequire = (0, import_node_module2.createRequire)(
5919
- import_node_path9.default.join(projectPath, "package.json")
7383
+ import_node_path12.default.join(projectPath, "package.json")
5920
7384
  );
5921
7385
  const tsxEsmApiPath = projectRequire.resolve("tsx/esm/api");
5922
7386
  const tsxEsmApi = await import((0, import_node_url3.pathToFileURL)(tsxEsmApiPath).href);
@@ -5943,8 +7407,8 @@ async function generateToolRegistryTypesForServer(projectPath, serverFileRelativ
5943
7407
  "No MCPServer instance found. Make sure your server file creates an MCPServer instance."
5944
7408
  );
5945
7409
  }
5946
- const mcpUsePath = import_node_path9.default.join(projectPath, "node_modules", "mcp-use");
5947
- const { generateToolRegistryTypes } = await import((0, import_node_url3.pathToFileURL)(import_node_path9.default.join(mcpUsePath, "dist", "src", "server", "index.js")).href).then((mod) => mod);
7410
+ const mcpUsePath = import_node_path12.default.join(projectPath, "node_modules", "mcp-use");
7411
+ const { generateToolRegistryTypes } = await import((0, import_node_url3.pathToFileURL)(import_node_path12.default.join(mcpUsePath, "dist", "src", "server", "index.js")).href).then((mod) => mod);
5948
7412
  if (!generateToolRegistryTypes) {
5949
7413
  throw new Error("generateToolRegistryTypes not found in mcp-use package");
5950
7414
  }
@@ -5962,10 +7426,10 @@ async function buildWidgets(projectPath, options = {}) {
5962
7426
  const { promises: fs11 } = await import("fs");
5963
7427
  const { build } = await import("vite");
5964
7428
  const widgetsDirRelative = options.widgetsDir ?? "resources";
5965
- const resourcesDir = import_node_path9.default.resolve(projectPath, widgetsDirRelative);
7429
+ const resourcesDir = import_node_path12.default.resolve(projectPath, widgetsDirRelative);
5966
7430
  const mcpUrl = process.env.MCP_URL;
5967
7431
  try {
5968
- await (0, import_promises7.access)(resourcesDir);
7432
+ await (0, import_promises8.access)(resourcesDir);
5969
7433
  } catch {
5970
7434
  console.log(
5971
7435
  source_default.gray(
@@ -5984,10 +7448,10 @@ async function buildWidgets(projectPath, options = {}) {
5984
7448
  if (dirent.isFile() && (dirent.name.endsWith(".tsx") || dirent.name.endsWith(".ts"))) {
5985
7449
  entries.push({
5986
7450
  name: dirent.name.replace(/\.tsx?$/, ""),
5987
- path: import_node_path9.default.join(resourcesDir, dirent.name)
7451
+ path: import_node_path12.default.join(resourcesDir, dirent.name)
5988
7452
  });
5989
7453
  } else if (dirent.isDirectory()) {
5990
- const widgetPath = import_node_path9.default.join(resourcesDir, dirent.name, "widget.tsx");
7454
+ const widgetPath = import_node_path12.default.join(resourcesDir, dirent.name, "widget.tsx");
5991
7455
  try {
5992
7456
  await fs11.access(widgetPath);
5993
7457
  entries.push({
@@ -6017,14 +7481,14 @@ async function buildWidgets(projectPath, options = {}) {
6017
7481
  );
6018
7482
  const react = (await import("@vitejs/plugin-react")).default;
6019
7483
  const tailwindcss = (await import("@tailwindcss/vite")).default;
6020
- const projectTsconfigPath = import_node_path9.default.join(projectPath, "tsconfig.json");
7484
+ const projectTsconfigPath = import_node_path12.default.join(projectPath, "tsconfig.json");
6021
7485
  let hasProjectTsconfig = false;
6022
7486
  try {
6023
- await (0, import_promises7.access)(projectTsconfigPath);
7487
+ await (0, import_promises8.access)(projectTsconfigPath);
6024
7488
  hasProjectTsconfig = true;
6025
7489
  } catch {
6026
7490
  }
6027
- const packageJsonPath = import_node_path9.default.join(projectPath, "package.json");
7491
+ const packageJsonPath = import_node_path12.default.join(projectPath, "package.json");
6028
7492
  let favicon = "";
6029
7493
  try {
6030
7494
  const pkgContent = await fs11.readFile(packageJsonPath, "utf-8");
@@ -6036,16 +7500,16 @@ async function buildWidgets(projectPath, options = {}) {
6036
7500
  const widgetName = entry.name;
6037
7501
  const entryPath = entry.path.replace(/\\/g, "/");
6038
7502
  console.log(source_default.gray(` - Building ${widgetName}...`));
6039
- const tempDir = import_node_path9.default.join(projectPath, ".mcp-use", widgetName);
7503
+ const tempDir = import_node_path12.default.join(projectPath, ".mcp-use", widgetName);
6040
7504
  await fs11.mkdir(tempDir, { recursive: true });
6041
- const relativeResourcesPath = import_node_path9.default.relative(tempDir, resourcesDir).replace(/\\/g, "/");
6042
- const mcpUsePath = import_node_path9.default.join(projectPath, "node_modules", "mcp-use");
6043
- const relativeMcpUsePath = import_node_path9.default.relative(tempDir, mcpUsePath).replace(/\\/g, "/");
6044
- const projectSrcDir = import_node_path9.default.join(projectPath, "src");
7505
+ const relativeResourcesPath = import_node_path12.default.relative(tempDir, resourcesDir).replace(/\\/g, "/");
7506
+ const mcpUsePath = import_node_path12.default.join(projectPath, "node_modules", "mcp-use");
7507
+ const relativeMcpUsePath = import_node_path12.default.relative(tempDir, mcpUsePath).replace(/\\/g, "/");
7508
+ const projectSrcDir = import_node_path12.default.join(projectPath, "src");
6045
7509
  let projectSrcSourceLine = "";
6046
7510
  try {
6047
- await (0, import_promises7.access)(projectSrcDir);
6048
- const relativeProjectSrcPath = import_node_path9.default.relative(tempDir, projectSrcDir).replace(/\\/g, "/");
7511
+ await (0, import_promises8.access)(projectSrcDir);
7512
+ const relativeProjectSrcPath = import_node_path12.default.relative(tempDir, projectSrcDir).replace(/\\/g, "/");
6049
7513
  projectSrcSourceLine = `@source "${relativeProjectSrcPath}";
6050
7514
  `;
6051
7515
  } catch {
@@ -6056,7 +7520,7 @@ async function buildWidgets(projectPath, options = {}) {
6056
7520
  @source "${relativeResourcesPath}";
6057
7521
  @source "${relativeMcpUsePath}/**/*.{ts,tsx,js,jsx}";
6058
7522
  ${projectSrcSourceLine}`;
6059
- await fs11.writeFile(import_node_path9.default.join(tempDir, "styles.css"), cssContent, "utf8");
7523
+ await fs11.writeFile(import_node_path12.default.join(tempDir, "styles.css"), cssContent, "utf8");
6060
7524
  const entryContent = `import React from 'react'
6061
7525
  import { createRoot } from 'react-dom/client'
6062
7526
  import './styles.css'
@@ -6081,9 +7545,9 @@ if (container && Component) {
6081
7545
  <script type="module" src="/entry.tsx"></script>
6082
7546
  </body>
6083
7547
  </html>`;
6084
- await fs11.writeFile(import_node_path9.default.join(tempDir, "entry.tsx"), entryContent, "utf8");
6085
- await fs11.writeFile(import_node_path9.default.join(tempDir, "index.html"), htmlContent, "utf8");
6086
- const outDir = import_node_path9.default.join(
7548
+ await fs11.writeFile(import_node_path12.default.join(tempDir, "entry.tsx"), entryContent, "utf8");
7549
+ await fs11.writeFile(import_node_path12.default.join(tempDir, "index.html"), htmlContent, "utf8");
7550
+ const outDir = import_node_path12.default.join(
6087
7551
  projectPath,
6088
7552
  "dist",
6089
7553
  "resources",
@@ -6093,13 +7557,13 @@ if (container && Component) {
6093
7557
  const baseUrl = mcpUrl ? `${mcpUrl}/${widgetName}/` : `/mcp-use/widgets/${widgetName}/`;
6094
7558
  let widgetMetadata = {};
6095
7559
  try {
6096
- const metadataTempDir = import_node_path9.default.join(
7560
+ const metadataTempDir = import_node_path12.default.join(
6097
7561
  projectPath,
6098
7562
  ".mcp-use",
6099
7563
  `${widgetName}-metadata`
6100
7564
  );
6101
7565
  await fs11.mkdir(metadataTempDir, { recursive: true });
6102
- const { createServer } = await import("vite");
7566
+ const { createServer: createServer2 } = await import("vite");
6103
7567
  const nodeStubsPlugin = {
6104
7568
  name: "node-stubs",
6105
7569
  enforce: "pre",
@@ -6127,9 +7591,9 @@ export default PostHog;
6127
7591
  }
6128
7592
  };
6129
7593
  const serverOnlyGuard = makeWidgetServerOnlyGuard(widgetName);
6130
- const metadataServer = await createServer({
7594
+ const metadataServer = await createServer2({
6131
7595
  root: metadataTempDir,
6132
- cacheDir: import_node_path9.default.join(metadataTempDir, ".vite-cache"),
7596
+ cacheDir: import_node_path12.default.join(metadataTempDir, ".vite-cache"),
6133
7597
  plugins: [serverOnlyGuard, nodeStubsPlugin, tailwindcss(), react()],
6134
7598
  // When the project has a tsconfig, enable Vite's native tsconfig-paths
6135
7599
  // resolver so `@/*` (or any custom alias) resolves through the
@@ -6360,7 +7824,7 @@ export default {
6360
7824
  // Inline all assets under 100MB (effectively all)
6361
7825
  } : {},
6362
7826
  rolldownOptions: {
6363
- input: import_node_path9.default.join(tempDir, "index.html"),
7827
+ input: import_node_path12.default.join(tempDir, "index.html"),
6364
7828
  external: (id) => {
6365
7829
  return false;
6366
7830
  }
@@ -6368,11 +7832,11 @@ export default {
6368
7832
  }
6369
7833
  });
6370
7834
  try {
6371
- const assetsDir = import_node_path9.default.join(outDir, "assets");
7835
+ const assetsDir = import_node_path12.default.join(outDir, "assets");
6372
7836
  const assetFiles = await fs11.readdir(assetsDir);
6373
7837
  const jsFiles = assetFiles.filter((f) => f.endsWith(".js"));
6374
7838
  for (const jsFile of jsFiles) {
6375
- const jsPath = import_node_path9.default.join(assetsDir, jsFile);
7839
+ const jsPath = import_node_path12.default.join(assetsDir, jsFile);
6376
7840
  let content = await fs11.readFile(jsPath, "utf8");
6377
7841
  const zodConfigPatterns = [
6378
7842
  // Non-minified: export const globalConfig = {}
@@ -6404,7 +7868,7 @@ export default {
6404
7868
  const mcpServerUrl = process.env.MCP_SERVER_URL;
6405
7869
  if (mcpServerUrl) {
6406
7870
  try {
6407
- const htmlPath = import_node_path9.default.join(outDir, "index.html");
7871
+ const htmlPath = import_node_path12.default.join(outDir, "index.html");
6408
7872
  let html = await fs11.readFile(htmlPath, "utf8");
6409
7873
  const injectionScript = `<script>window.__getFile = (filename) => { return "${mcpUrl}/${widgetName}/"+filename }; window.__mcpPublicUrl = "${mcpServerUrl}/mcp-use/public"; window.__mcpPublicAssetsUrl = "${mcpUrl}/public";</script>`;
6410
7874
  if (!html.includes("window.__mcpPublicUrl")) {
@@ -6480,7 +7944,7 @@ async function collectTsFiles(projectPath, includePatterns, excludePatterns) {
6480
7944
  for (const file of literalFiles) {
6481
7945
  if (/\.tsx?$/.test(file) && !file.endsWith(".d.ts")) {
6482
7946
  try {
6483
- await (0, import_promises7.access)(import_node_path9.default.join(projectPath, file));
7947
+ await (0, import_promises8.access)(import_node_path12.default.join(projectPath, file));
6484
7948
  files.push(file);
6485
7949
  } catch {
6486
7950
  }
@@ -6488,13 +7952,13 @@ async function collectTsFiles(projectPath, includePatterns, excludePatterns) {
6488
7952
  }
6489
7953
  const excludeSet = new Set(excludePatterns.map((e) => e.replace(/\*+/g, "")));
6490
7954
  for (const prefix of dirPrefixes) {
6491
- const dirPath = import_node_path9.default.join(projectPath, prefix);
7955
+ const dirPath = import_node_path12.default.join(projectPath, prefix);
6492
7956
  try {
6493
7957
  const entries = await fs11.readdir(dirPath, { recursive: true });
6494
7958
  for (const entry of entries) {
6495
7959
  const entryStr = String(entry);
6496
- const rel = import_node_path9.default.join(prefix, entryStr);
6497
- if (/\.tsx?$/.test(entryStr) && !entryStr.endsWith(".d.ts") && !excludeSet.has(rel.split(import_node_path9.default.sep)[0])) {
7960
+ const rel = import_node_path12.default.join(prefix, entryStr);
7961
+ if (/\.tsx?$/.test(entryStr) && !entryStr.endsWith(".d.ts") && !excludeSet.has(rel.split(import_node_path12.default.sep)[0])) {
6498
7962
  files.push(rel);
6499
7963
  }
6500
7964
  }
@@ -6506,7 +7970,7 @@ async function collectTsFiles(projectPath, includePatterns, excludePatterns) {
6506
7970
  async function transpileWithEsbuild(projectPath) {
6507
7971
  const esbuild = await import("esbuild");
6508
7972
  const { promises: fs11 } = await import("fs");
6509
- const tsconfigPath = import_node_path9.default.join(projectPath, "tsconfig.json");
7973
+ const tsconfigPath = import_node_path12.default.join(projectPath, "tsconfig.json");
6510
7974
  let tsconfig = {};
6511
7975
  try {
6512
7976
  const raw = await fs11.readFile(tsconfigPath, "utf-8");
@@ -6536,10 +8000,10 @@ async function transpileWithEsbuild(projectPath) {
6536
8000
  const target = (compilerOptions.target || "ES2022").toLowerCase();
6537
8001
  const moduleStr = (compilerOptions.module || "ESNext").toLowerCase();
6538
8002
  const format = moduleStr.includes("commonjs") ? "cjs" : "esm";
6539
- const outbase = compilerOptions.rootDir ? import_node_path9.default.resolve(projectPath, compilerOptions.rootDir) : projectPath;
8003
+ const outbase = compilerOptions.rootDir ? import_node_path12.default.resolve(projectPath, compilerOptions.rootDir) : projectPath;
6540
8004
  await esbuild.build({
6541
- entryPoints: files.map((f) => import_node_path9.default.join(projectPath, f)),
6542
- outdir: import_node_path9.default.join(projectPath, outDir),
8005
+ entryPoints: files.map((f) => import_node_path12.default.join(projectPath, f)),
8006
+ outdir: import_node_path12.default.join(projectPath, outDir),
6543
8007
  outbase,
6544
8008
  bundle: true,
6545
8009
  packages: "external",
@@ -6566,7 +8030,7 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
6566
8030
  "Inline all JS/CSS into HTML (required for VS Code MCP Apps)"
6567
8031
  ).option("--no-inline", "Keep JS/CSS as separate files (default)").option("--no-typecheck", "Skip TypeScript type checking (faster builds)").action(async (options) => {
6568
8032
  try {
6569
- const projectPath = import_node_path9.default.resolve(options.path);
8033
+ const projectPath = import_node_path12.default.resolve(options.path);
6570
8034
  const { promises: fs11 } = await import("fs");
6571
8035
  displayPackageVersions(projectPath);
6572
8036
  const mcpDir = options.mcpDir;
@@ -6626,7 +8090,7 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
6626
8090
  }
6627
8091
  if (options.typecheck !== false && !mcpDir) {
6628
8092
  console.log(source_default.gray("Type checking..."));
6629
- const tscBin = import_node_path9.default.join(
8093
+ const tscBin = import_node_path12.default.join(
6630
8094
  projectPath,
6631
8095
  "node_modules",
6632
8096
  "typescript",
@@ -6649,7 +8113,7 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
6649
8113
  if (mcpDir) {
6650
8114
  entryPoint = sourceServerFile;
6651
8115
  } else {
6652
- const baseName = import_node_path9.default.basename(sourceServerFile, ".ts") + ".js";
8116
+ const baseName = import_node_path12.default.basename(sourceServerFile, ".ts") + ".js";
6653
8117
  const possibleOutputs = [
6654
8118
  `dist/${baseName}`,
6655
8119
  // rootDir set to project root or src
@@ -6660,7 +8124,7 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
6660
8124
  ];
6661
8125
  for (const candidate of possibleOutputs) {
6662
8126
  try {
6663
- await (0, import_promises7.access)(import_node_path9.default.join(projectPath, candidate));
8127
+ await (0, import_promises8.access)(import_node_path12.default.join(projectPath, candidate));
6664
8128
  entryPoint = candidate;
6665
8129
  break;
6666
8130
  } catch {
@@ -6669,17 +8133,17 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
6669
8133
  }
6670
8134
  }
6671
8135
  }
6672
- const publicDir = import_node_path9.default.join(projectPath, "public");
8136
+ const publicDir = import_node_path12.default.join(projectPath, "public");
6673
8137
  try {
6674
8138
  await fs11.access(publicDir);
6675
8139
  console.log(source_default.gray("Copying public assets..."));
6676
- await fs11.cp(publicDir, import_node_path9.default.join(projectPath, "dist", "public"), {
8140
+ await fs11.cp(publicDir, import_node_path12.default.join(projectPath, "dist", "public"), {
6677
8141
  recursive: true
6678
8142
  });
6679
8143
  console.log(source_default.green("\u2713 Public assets copied"));
6680
8144
  } catch {
6681
8145
  }
6682
- const manifestPath = import_node_path9.default.join(projectPath, "dist", "mcp-use.json");
8146
+ const manifestPath = import_node_path12.default.join(projectPath, "dist", "mcp-use.json");
6683
8147
  let existingManifest = {};
6684
8148
  try {
6685
8149
  const existingContent = await fs11.readFile(manifestPath, "utf-8");
@@ -6704,7 +8168,7 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
6704
8168
  // Server entry point for `mcp-use start`
6705
8169
  widgets: widgetsData
6706
8170
  };
6707
- await fs11.mkdir(import_node_path9.default.dirname(manifestPath), { recursive: true });
8171
+ await fs11.mkdir(import_node_path12.default.dirname(manifestPath), { recursive: true });
6708
8172
  await fs11.writeFile(
6709
8173
  manifestPath,
6710
8174
  JSON.stringify(manifest, null, 2),
@@ -6741,7 +8205,7 @@ program.command("dev").description("Run development server with auto-reload and
6741
8205
  ).option("--no-open", "Do not auto-open inspector").option("--no-hmr", "Disable hot module reloading (use tsx watch instead)").option("--tunnel", "Expose server through a tunnel").action(async (options) => {
6742
8206
  try {
6743
8207
  process.env.MCP_USE_CLI_DEV = "1";
6744
- const projectPath = import_node_path9.default.resolve(options.path);
8208
+ const projectPath = import_node_path12.default.resolve(options.path);
6745
8209
  let port = parseInt(options.port, 10);
6746
8210
  const host = options.host;
6747
8211
  const useHmr = options.hmr !== false;
@@ -6769,10 +8233,10 @@ program.command("dev").description("Run development server with auto-reload and
6769
8233
  let tunnelUrl = void 0;
6770
8234
  if (options.tunnel) {
6771
8235
  try {
6772
- const manifestPath = import_node_path9.default.join(projectPath, "dist", "mcp-use.json");
8236
+ const manifestPath = import_node_path12.default.join(projectPath, "dist", "mcp-use.json");
6773
8237
  let existingSubdomain;
6774
8238
  try {
6775
- const manifestContent = await (0, import_promises7.readFile)(manifestPath, "utf-8");
8239
+ const manifestContent = await (0, import_promises8.readFile)(manifestPath, "utf-8");
6776
8240
  const manifest = JSON.parse(manifestContent);
6777
8241
  existingSubdomain = manifest.tunnel?.subdomain;
6778
8242
  if (existingSubdomain) {
@@ -6810,7 +8274,7 @@ program.command("dev").description("Run development server with auto-reload and
6810
8274
  try {
6811
8275
  let manifest = {};
6812
8276
  try {
6813
- const manifestContent = await (0, import_promises7.readFile)(manifestPath, "utf-8");
8277
+ const manifestContent = await (0, import_promises8.readFile)(manifestPath, "utf-8");
6814
8278
  manifest = JSON.parse(manifestContent);
6815
8279
  } catch {
6816
8280
  }
@@ -6818,8 +8282,8 @@ program.command("dev").description("Run development server with auto-reload and
6818
8282
  manifest.tunnel = {};
6819
8283
  }
6820
8284
  manifest.tunnel.subdomain = tunnelSubdomain;
6821
- await (0, import_promises7.mkdir)(import_node_path9.default.dirname(manifestPath), { recursive: true });
6822
- await (0, import_promises7.writeFile)(
8285
+ await (0, import_promises8.mkdir)(import_node_path12.default.dirname(manifestPath), { recursive: true });
8286
+ await (0, import_promises8.writeFile)(
6823
8287
  manifestPath,
6824
8288
  JSON.stringify(manifest, null, 2),
6825
8289
  "utf-8"
@@ -6873,10 +8337,10 @@ program.command("dev").description("Run development server with auto-reload and
6873
8337
  let args;
6874
8338
  try {
6875
8339
  const projectRequire = createRequire4(
6876
- import_node_path9.default.join(projectPath, "package.json")
8340
+ import_node_path12.default.join(projectPath, "package.json")
6877
8341
  );
6878
8342
  const tsxPkgPath = projectRequire.resolve("tsx/package.json");
6879
- const tsxPkg = JSON.parse(await (0, import_promises7.readFile)(tsxPkgPath, "utf-8"));
8343
+ const tsxPkg = JSON.parse(await (0, import_promises8.readFile)(tsxPkgPath, "utf-8"));
6880
8344
  let binPath;
6881
8345
  if (typeof tsxPkg.bin === "string") {
6882
8346
  binPath = tsxPkg.bin;
@@ -6885,7 +8349,7 @@ program.command("dev").description("Run development server with auto-reload and
6885
8349
  } else {
6886
8350
  throw new Error("No bin field found in tsx package.json");
6887
8351
  }
6888
- const tsxBin = import_node_path9.default.resolve(import_node_path9.default.dirname(tsxPkgPath), binPath);
8352
+ const tsxBin = import_node_path12.default.resolve(import_node_path12.default.dirname(tsxPkgPath), binPath);
6889
8353
  cmd = "node";
6890
8354
  args = [tsxBin, "watch", serverFile];
6891
8355
  } catch (error) {
@@ -6974,10 +8438,10 @@ program.command("dev").description("Run development server with auto-reload and
6974
8438
  const chokidar = chokidarModule.default || chokidarModule;
6975
8439
  const { fileURLToPath: fileURLToPath3 } = await import("url");
6976
8440
  const { createRequire: createRequire3 } = await import("module");
6977
- const projectTsconfigPath = import_node_path9.default.join(projectPath, "tsconfig.json");
8441
+ const projectTsconfigPath = import_node_path12.default.join(projectPath, "tsconfig.json");
6978
8442
  let tsconfigAvailable = false;
6979
8443
  try {
6980
- await (0, import_promises7.access)(projectTsconfigPath);
8444
+ await (0, import_promises8.access)(projectTsconfigPath);
6981
8445
  tsconfigAvailable = true;
6982
8446
  process.env.TSX_TSCONFIG_PATH = projectTsconfigPath;
6983
8447
  if (process.cwd() !== projectPath) process.chdir(projectPath);
@@ -6986,7 +8450,7 @@ program.command("dev").description("Run development server with auto-reload and
6986
8450
  let tsxLoaderActive = false;
6987
8451
  try {
6988
8452
  const projectRequire = createRequire3(
6989
- import_node_path9.default.join(projectPath, "package.json")
8453
+ import_node_path12.default.join(projectPath, "package.json")
6990
8454
  );
6991
8455
  const tsxEsmApiPath = projectRequire.resolve("tsx/esm/api");
6992
8456
  const tsxEsmApi = await import((0, import_node_url3.pathToFileURL)(tsxEsmApiPath).href);
@@ -7017,7 +8481,7 @@ program.command("dev").description("Run development server with auto-reload and
7017
8481
  )
7018
8482
  );
7019
8483
  }
7020
- const serverFilePath = import_node_path9.default.join(projectPath, serverFile);
8484
+ const serverFilePath = import_node_path12.default.join(projectPath, serverFile);
7021
8485
  const serverFileUrl = (0, import_node_url3.pathToFileURL)(serverFilePath).href;
7022
8486
  globalThis.__mcpUseHmrMode = true;
7023
8487
  const importServerModule = async () => {
@@ -7114,8 +8578,8 @@ program.command("dev").description("Run development server with auto-reload and
7114
8578
  }
7115
8579
  let watcher = chokidar.watch(".", {
7116
8580
  cwd: projectPath,
7117
- ignored: (path8, stats) => {
7118
- const normalizedPath = path8.replace(/\\/g, "/");
8581
+ ignored: (path11, stats) => {
8582
+ const normalizedPath = path11.replace(/\\/g, "/");
7119
8583
  if (/(^|\/)\.[^/]/.test(normalizedPath)) {
7120
8584
  return true;
7121
8585
  }
@@ -7289,10 +8753,10 @@ program.command("dev").description("Run development server with auto-reload and
7289
8753
  }
7290
8754
  tunnelUrl = void 0;
7291
8755
  if (withTunnel) {
7292
- const manifestPath = import_node_path9.default.join(projectPath, "dist", "mcp-use.json");
8756
+ const manifestPath = import_node_path12.default.join(projectPath, "dist", "mcp-use.json");
7293
8757
  let existingSubdomain;
7294
8758
  try {
7295
- const manifestContent = await (0, import_promises7.readFile)(manifestPath, "utf-8");
8759
+ const manifestContent = await (0, import_promises8.readFile)(manifestPath, "utf-8");
7296
8760
  const manifest = JSON.parse(manifestContent);
7297
8761
  existingSubdomain = manifest.tunnel?.subdomain;
7298
8762
  if (existingSubdomain) {
@@ -7326,16 +8790,16 @@ program.command("dev").description("Run development server with auto-reload and
7326
8790
  tunnelSubdomain = tunnelInfo.subdomain;
7327
8791
  process.env.MCP_URL = tunnelUrl;
7328
8792
  try {
7329
- const mPath = import_node_path9.default.join(projectPath, "dist", "mcp-use.json");
8793
+ const mPath = import_node_path12.default.join(projectPath, "dist", "mcp-use.json");
7330
8794
  let manifest = {};
7331
8795
  try {
7332
- manifest = JSON.parse(await (0, import_promises7.readFile)(mPath, "utf-8"));
8796
+ manifest = JSON.parse(await (0, import_promises8.readFile)(mPath, "utf-8"));
7333
8797
  } catch {
7334
8798
  }
7335
8799
  if (!manifest.tunnel) manifest.tunnel = {};
7336
8800
  manifest.tunnel.subdomain = tunnelSubdomain;
7337
- await (0, import_promises7.mkdir)(import_node_path9.default.dirname(mPath), { recursive: true });
7338
- await (0, import_promises7.writeFile)(mPath, JSON.stringify(manifest, null, 2), "utf-8");
8801
+ await (0, import_promises8.mkdir)(import_node_path12.default.dirname(mPath), { recursive: true });
8802
+ await (0, import_promises8.writeFile)(mPath, JSON.stringify(manifest, null, 2), "utf-8");
7339
8803
  } catch {
7340
8804
  }
7341
8805
  } else {
@@ -7438,7 +8902,7 @@ program.command("start").description("Start production server").option("-p, --pa
7438
8902
  "Folder holding the MCP entry + resources (e.g. 'src/mcp' for Next.js apps)"
7439
8903
  ).option("--port <port>", "Server port", "3000").option("--tunnel", "Expose server through a tunnel").action(async (options) => {
7440
8904
  try {
7441
- const projectPath = import_node_path9.default.resolve(options.path);
8905
+ const projectPath = import_node_path12.default.resolve(options.path);
7442
8906
  const portFlagProvided = process.argv.includes("--port") || process.argv.includes("-p") || process.argv.some((arg) => arg.startsWith("--port=")) || process.argv.some((arg) => arg.startsWith("-p="));
7443
8907
  let port = portFlagProvided ? parseInt(options.port, 10) : parseInt(process.env.PORT || options.port || "3000", 10);
7444
8908
  if (!await isPortAvailable(port)) {
@@ -7456,10 +8920,10 @@ program.command("start").description("Start production server").option("-p, --pa
7456
8920
  let tunnelSubdomain = void 0;
7457
8921
  if (options.tunnel) {
7458
8922
  try {
7459
- const manifestPath2 = import_node_path9.default.join(projectPath, "dist", "mcp-use.json");
8923
+ const manifestPath2 = import_node_path12.default.join(projectPath, "dist", "mcp-use.json");
7460
8924
  let existingSubdomain;
7461
8925
  try {
7462
- const manifestContent = await (0, import_promises7.readFile)(manifestPath2, "utf-8");
8926
+ const manifestContent = await (0, import_promises8.readFile)(manifestPath2, "utf-8");
7463
8927
  const manifest = JSON.parse(manifestContent);
7464
8928
  existingSubdomain = manifest.tunnel?.subdomain;
7465
8929
  if (existingSubdomain) {
@@ -7503,7 +8967,7 @@ program.command("start").description("Start production server").option("-p, --pa
7503
8967
  try {
7504
8968
  let manifest = {};
7505
8969
  try {
7506
- const manifestContent = await (0, import_promises7.readFile)(manifestPath2, "utf-8");
8970
+ const manifestContent = await (0, import_promises8.readFile)(manifestPath2, "utf-8");
7507
8971
  manifest = JSON.parse(manifestContent);
7508
8972
  } catch {
7509
8973
  }
@@ -7511,8 +8975,8 @@ program.command("start").description("Start production server").option("-p, --pa
7511
8975
  manifest.tunnel = {};
7512
8976
  }
7513
8977
  manifest.tunnel.subdomain = subdomain;
7514
- await (0, import_promises7.mkdir)(import_node_path9.default.dirname(manifestPath2), { recursive: true });
7515
- await (0, import_promises7.writeFile)(
8978
+ await (0, import_promises8.mkdir)(import_node_path12.default.dirname(manifestPath2), { recursive: true });
8979
+ await (0, import_promises8.writeFile)(
7516
8980
  manifestPath2,
7517
8981
  JSON.stringify(manifest, null, 2),
7518
8982
  "utf-8"
@@ -7530,12 +8994,12 @@ program.command("start").description("Start production server").option("-p, --pa
7530
8994
  }
7531
8995
  }
7532
8996
  let serverFile;
7533
- const manifestPath = import_node_path9.default.join(projectPath, "dist", "mcp-use.json");
8997
+ const manifestPath = import_node_path12.default.join(projectPath, "dist", "mcp-use.json");
7534
8998
  try {
7535
- const manifestContent = await (0, import_promises7.readFile)(manifestPath, "utf-8");
8999
+ const manifestContent = await (0, import_promises8.readFile)(manifestPath, "utf-8");
7536
9000
  const manifest = JSON.parse(manifestContent);
7537
9001
  if (manifest.entryPoint) {
7538
- await (0, import_promises7.access)(import_node_path9.default.join(projectPath, manifest.entryPoint));
9002
+ await (0, import_promises8.access)(import_node_path12.default.join(projectPath, manifest.entryPoint));
7539
9003
  serverFile = manifest.entryPoint;
7540
9004
  }
7541
9005
  } catch {
@@ -7556,7 +9020,7 @@ program.command("start").description("Start production server").option("-p, --pa
7556
9020
  ];
7557
9021
  for (const candidate of serverCandidates) {
7558
9022
  try {
7559
- await (0, import_promises7.access)(import_node_path9.default.join(projectPath, candidate));
9023
+ await (0, import_promises8.access)(import_node_path12.default.join(projectPath, candidate));
7560
9024
  serverFile = candidate;
7561
9025
  break;
7562
9026
  } catch {
@@ -7607,13 +9071,13 @@ Looked for:
7607
9071
  if (isTsEntry) {
7608
9072
  try {
7609
9073
  const projectRequire = (0, import_node_module2.createRequire)(
7610
- import_node_path9.default.join(projectPath, "package.json")
9074
+ import_node_path12.default.join(projectPath, "package.json")
7611
9075
  );
7612
9076
  const tsxPkgPath = projectRequire.resolve("tsx/package.json");
7613
- const tsxPkg = JSON.parse(await (0, import_promises7.readFile)(tsxPkgPath, "utf-8"));
9077
+ const tsxPkg = JSON.parse(await (0, import_promises8.readFile)(tsxPkgPath, "utf-8"));
7614
9078
  const binField = typeof tsxPkg.bin === "string" ? tsxPkg.bin : tsxPkg.bin?.tsx ?? Object.values(tsxPkg.bin ?? {})[0];
7615
9079
  if (!binField) throw new Error("tsx bin entry not found");
7616
- const tsxBin = import_node_path9.default.resolve(import_node_path9.default.dirname(tsxPkgPath), binField);
9080
+ const tsxBin = import_node_path12.default.resolve(import_node_path12.default.dirname(tsxPkgPath), binField);
7617
9081
  spawnCmd = "node";
7618
9082
  spawnArgs = [tsxBin, serverFile];
7619
9083
  } catch (error) {
@@ -7626,7 +9090,7 @@ Looked for:
7626
9090
  spawnArgs = ["tsx", serverFile];
7627
9091
  }
7628
9092
  }
7629
- const serverProc = (0, import_node_child_process9.spawn)(spawnCmd, spawnArgs, {
9093
+ const serverProc = (0, import_node_child_process11.spawn)(spawnCmd, spawnArgs, {
7630
9094
  cwd: projectPath,
7631
9095
  stdio: "inherit",
7632
9096
  env: env2
@@ -7759,10 +9223,11 @@ program.addCommand(createClientCommand());
7759
9223
  program.addCommand(createDeploymentsCommand());
7760
9224
  program.addCommand(createServersCommand());
7761
9225
  program.addCommand(createSkillsCommand());
9226
+ program.addCommand(createScreenshotCommand());
7762
9227
  program.command("generate-types").description(
7763
9228
  "Generate TypeScript type definitions for tools (writes .mcp-use/tool-registry.d.ts)"
7764
9229
  ).option("-p, --path <path>", "Path to project directory", process.cwd()).option("--server <file>", "Server entry file", "index.ts").action(async (options) => {
7765
- const projectPath = import_node_path9.default.resolve(options.path);
9230
+ const projectPath = import_node_path12.default.resolve(options.path);
7766
9231
  try {
7767
9232
  console.log(source_default.blue("Generating tool registry types..."));
7768
9233
  const result = await generateToolRegistryTypesForServer(
@@ -7792,5 +9257,49 @@ program.hook("preAction", async (_thisCommand, actionCommand) => {
7792
9257
  const projectPath = actionCommand.opts().path;
7793
9258
  await notifyIfUpdateAvailable(projectPath);
7794
9259
  });
7795
- program.parse();
9260
+ var argv = process.argv;
9261
+ var clientIdx = argv[2] === "client" ? 2 : -1;
9262
+ var perClientName = clientIdx !== -1 && argv.length > clientIdx + 1 && !argv[clientIdx + 1].startsWith("-") && !RESERVED_CLIENT_SUBCOMMANDS.has(argv[clientIdx + 1]) ? argv[clientIdx + 1] : null;
9263
+ if (perClientName) {
9264
+ if (PER_CLIENT_SCOPES.has(perClientName)) {
9265
+ const rest2 = argv.slice(clientIdx + 1).join(" ");
9266
+ console.error(formatError("Missing server name."));
9267
+ console.error("");
9268
+ console.error(
9269
+ `'${perClientName}' is a per-server subcommand, not a server name. Address it through a saved server:`
9270
+ );
9271
+ console.error("");
9272
+ console.error(` mcp-use client <name> ${rest2}`);
9273
+ console.error("");
9274
+ console.error("See your saved servers with:");
9275
+ console.error(" mcp-use client list");
9276
+ process.exit(1);
9277
+ }
9278
+ const rest = argv.slice(clientIdx + 2);
9279
+ const isHelpOnly = rest.length === 0 || rest.length === 1 && (rest[0] === "--help" || rest[0] === "-h");
9280
+ (async () => {
9281
+ if (isHelpOnly) {
9282
+ const config = await getSession(perClientName);
9283
+ if (!config) {
9284
+ console.error(formatError(`Server '${perClientName}' not found.`));
9285
+ console.error("");
9286
+ console.error("Connect to an MCP server and save it under this name:");
9287
+ console.error(` mcp-use client connect ${perClientName} <url>`);
9288
+ console.error("");
9289
+ console.error("See your saved servers with:");
9290
+ console.error(" mcp-use client list");
9291
+ process.exit(1);
9292
+ }
9293
+ }
9294
+ await createPerClientCommand(perClientName).parseAsync(rest, {
9295
+ from: "user"
9296
+ });
9297
+ })().catch((err) => {
9298
+ const message = err instanceof Error ? err.message : String(err);
9299
+ console.error(formatError(message));
9300
+ process.exit(1);
9301
+ });
9302
+ } else {
9303
+ program.parse();
9304
+ }
7796
9305
  //# sourceMappingURL=index.cjs.map