@mcp-use/cli 2.6.1 → 2.7.0-canary.1

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
@@ -523,12 +523,12 @@ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
523
523
  var source_default = chalk;
524
524
 
525
525
  // src/index.ts
526
- var import_commander2 = require("commander");
527
- var import_config4 = require("dotenv/config");
526
+ var import_commander3 = require("commander");
527
+ var import_config5 = require("dotenv/config");
528
528
  var import_node_child_process10 = require("child_process");
529
- var import_node_fs7 = require("fs");
529
+ var import_node_fs8 = require("fs");
530
530
  var import_promises5 = require("fs/promises");
531
- var import_node_path5 = __toESM(require("path"), 1);
531
+ var import_node_path6 = __toESM(require("path"), 1);
532
532
 
533
533
  // ../../node_modules/.pnpm/open@11.0.0/node_modules/open/index.js
534
534
  var import_node_process8 = __toESM(require("process"), 1);
@@ -700,15 +700,15 @@ var wslDefaultBrowser = async () => {
700
700
  const { stdout } = await executePowerShell(command, { powerShellPath: psPath });
701
701
  return stdout.trim();
702
702
  };
703
- var convertWslPathToWindows = async (path5) => {
704
- if (/^[a-z]+:\/\//i.test(path5)) {
705
- return path5;
703
+ var convertWslPathToWindows = async (path6) => {
704
+ if (/^[a-z]+:\/\//i.test(path6)) {
705
+ return path6;
706
706
  }
707
707
  try {
708
- const { stdout } = await execFile2("wslpath", ["-aw", path5], { encoding: "utf8" });
708
+ const { stdout } = await execFile2("wslpath", ["-aw", path6], { encoding: "utf8" });
709
709
  return stdout.trim();
710
710
  } catch {
711
- return path5;
711
+ return path6;
712
712
  }
713
713
  };
714
714
 
@@ -1130,6 +1130,9 @@ defineLazyProperty(apps, "safari", () => detectPlatformBinary({
1130
1130
  }));
1131
1131
  var open_default = open;
1132
1132
 
1133
+ // src/index.ts
1134
+ var import_zod = require("zod");
1135
+
1133
1136
  // src/commands/auth.ts
1134
1137
  var import_node_http = require("http");
1135
1138
 
@@ -1209,15 +1212,30 @@ var McpUseAPI = class _McpUseAPI {
1209
1212
  if (this.apiKey) {
1210
1213
  headers["x-api-key"] = this.apiKey;
1211
1214
  }
1212
- const response = await fetch(url, {
1213
- ...options,
1214
- headers
1215
- });
1216
- if (!response.ok) {
1217
- const error = await response.text();
1218
- throw new Error(`API request failed: ${response.status} ${error}`);
1215
+ const timeout = options.timeout || 3e4;
1216
+ const controller = new AbortController();
1217
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
1218
+ try {
1219
+ const response = await fetch(url, {
1220
+ ...options,
1221
+ headers,
1222
+ signal: controller.signal
1223
+ });
1224
+ clearTimeout(timeoutId);
1225
+ if (!response.ok) {
1226
+ const error = await response.text();
1227
+ throw new Error(`API request failed: ${response.status} ${error}`);
1228
+ }
1229
+ return response.json();
1230
+ } catch (error) {
1231
+ clearTimeout(timeoutId);
1232
+ if (error.name === "AbortError") {
1233
+ throw new Error(
1234
+ `Request timeout after ${timeout / 1e3}s. Try using --follow flag to stream logs instead.`
1235
+ );
1236
+ }
1237
+ throw error;
1219
1238
  }
1220
- return response.json();
1221
1239
  }
1222
1240
  /**
1223
1241
  * Create API key using JWT token
@@ -1360,6 +1378,92 @@ var McpUseAPI = class _McpUseAPI {
1360
1378
  }
1361
1379
  return response.json();
1362
1380
  }
1381
+ /**
1382
+ * List all deployments
1383
+ */
1384
+ async listDeployments() {
1385
+ const response = await this.request("/deployments");
1386
+ return response.deployments;
1387
+ }
1388
+ /**
1389
+ * Delete deployment
1390
+ */
1391
+ async deleteDeployment(deploymentId) {
1392
+ await this.request(`/deployments/${deploymentId}`, {
1393
+ method: "DELETE"
1394
+ });
1395
+ }
1396
+ /**
1397
+ * Update deployment
1398
+ */
1399
+ async updateDeployment(deploymentId, updates) {
1400
+ return this.request(`/deployments/${deploymentId}`, {
1401
+ method: "PATCH",
1402
+ body: JSON.stringify(updates)
1403
+ });
1404
+ }
1405
+ /**
1406
+ * Redeploy deployment
1407
+ */
1408
+ async redeployDeployment(deploymentId, filePath) {
1409
+ if (filePath) {
1410
+ const { readFile: readFile3 } = await import("fs/promises");
1411
+ const { basename } = await import("path");
1412
+ const { stat } = await import("fs/promises");
1413
+ const stats = await stat(filePath);
1414
+ const maxSize = 2 * 1024 * 1024;
1415
+ if (stats.size > maxSize) {
1416
+ throw new Error(
1417
+ `File size (${(stats.size / 1024 / 1024).toFixed(2)}MB) exceeds maximum of 2MB`
1418
+ );
1419
+ }
1420
+ const fileBuffer = await readFile3(filePath);
1421
+ const formData = new FormData();
1422
+ const blob = new Blob([fileBuffer], { type: "application/gzip" });
1423
+ formData.append("source_file", blob, basename(filePath));
1424
+ const headers = {};
1425
+ if (this.apiKey) headers["x-api-key"] = this.apiKey;
1426
+ const response = await fetch(
1427
+ `${this.baseUrl}/deployments/${deploymentId}/redeploy`,
1428
+ {
1429
+ method: "POST",
1430
+ headers,
1431
+ body: formData
1432
+ }
1433
+ );
1434
+ if (!response.ok) {
1435
+ const error = await response.text();
1436
+ throw new Error(`Redeploy failed: ${error}`);
1437
+ }
1438
+ return response.json();
1439
+ } else {
1440
+ return this.request(`/deployments/${deploymentId}/redeploy`, {
1441
+ method: "POST"
1442
+ });
1443
+ }
1444
+ }
1445
+ /**
1446
+ * Get deployment logs
1447
+ */
1448
+ async getDeploymentLogs(deploymentId) {
1449
+ const response = await this.request(
1450
+ `/deployments/${deploymentId}/logs`,
1451
+ { timeout: 6e4 }
1452
+ // 60 second timeout for logs
1453
+ );
1454
+ return response.data.logs;
1455
+ }
1456
+ /**
1457
+ * Get deployment build logs
1458
+ */
1459
+ async getDeploymentBuildLogs(deploymentId) {
1460
+ const response = await this.request(
1461
+ `/deployments/${deploymentId}/logs/build`,
1462
+ { timeout: 6e4 }
1463
+ // 60 second timeout for logs
1464
+ );
1465
+ return response.data.logs;
1466
+ }
1363
1467
  };
1364
1468
 
1365
1469
  // src/commands/auth.ts
@@ -1699,1557 +1803,2360 @@ async function whoamiCommand() {
1699
1803
  }
1700
1804
  }
1701
1805
 
1702
- // src/commands/deploy.ts
1703
- var import_node_fs5 = require("fs");
1704
- var import_node_path3 = __toESM(require("path"), 1);
1705
- var import_node_os4 = __toESM(require("os"), 1);
1706
- var import_node_child_process9 = require("child_process");
1707
- var import_node_util8 = require("util");
1806
+ // src/commands/client.ts
1807
+ var import_commander = require("commander");
1808
+ var import_node_readline = require("readline");
1809
+ var import_client = require("mcp-use/client");
1708
1810
 
1709
- // src/utils/git.ts
1710
- var import_node_child_process8 = require("child_process");
1711
- var import_node_util7 = require("util");
1712
- var execAsync = (0, import_node_util7.promisify)(import_node_child_process8.exec);
1713
- async function gitCommand(command, cwd = process.cwd()) {
1811
+ // src/utils/session-storage.ts
1812
+ var import_node_os4 = require("os");
1813
+ var import_node_path3 = require("path");
1814
+ var import_promises4 = require("fs/promises");
1815
+ var import_node_fs5 = require("fs");
1816
+ var SESSION_FILE_PATH = (0, import_node_path3.join)((0, import_node_os4.homedir)(), ".mcp-use", "cli-sessions.json");
1817
+ async function ensureSessionDir() {
1818
+ const dir = (0, import_node_path3.join)((0, import_node_os4.homedir)(), ".mcp-use");
1819
+ if (!(0, import_node_fs5.existsSync)(dir)) {
1820
+ await (0, import_promises4.mkdir)(dir, { recursive: true });
1821
+ }
1822
+ }
1823
+ async function loadSessions() {
1714
1824
  try {
1715
- const { stdout } = await execAsync(command, { cwd });
1716
- return stdout.trim();
1825
+ await ensureSessionDir();
1826
+ if (!(0, import_node_fs5.existsSync)(SESSION_FILE_PATH)) {
1827
+ return { activeSession: null, sessions: {} };
1828
+ }
1829
+ const content = await (0, import_promises4.readFile)(SESSION_FILE_PATH, "utf-8");
1830
+ return JSON.parse(content);
1717
1831
  } catch (error) {
1718
- return null;
1832
+ return { activeSession: null, sessions: {} };
1719
1833
  }
1720
1834
  }
1721
- async function isGitRepo(cwd = process.cwd()) {
1722
- const result = await gitCommand("git rev-parse --is-inside-work-tree", cwd);
1723
- return result === "true";
1835
+ async function saveSessions(storage) {
1836
+ await ensureSessionDir();
1837
+ await (0, import_promises4.writeFile)(SESSION_FILE_PATH, JSON.stringify(storage, null, 2), "utf-8");
1724
1838
  }
1725
- async function getRemoteUrl(cwd = process.cwd()) {
1726
- return gitCommand("git config --get remote.origin.url", cwd);
1839
+ async function saveSession(name, config) {
1840
+ const storage = await loadSessions();
1841
+ storage.sessions[name] = {
1842
+ ...config,
1843
+ lastUsed: (/* @__PURE__ */ new Date()).toISOString()
1844
+ };
1845
+ if (!storage.activeSession) {
1846
+ storage.activeSession = name;
1847
+ }
1848
+ await saveSessions(storage);
1727
1849
  }
1728
- function parseGitHubUrl(url) {
1729
- const sshMatch = url.match(/git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/);
1730
- const httpsMatch = url.match(
1731
- /https:\/\/github\.com\/([^/]+)\/(.+?)(?:\.git)?$/
1732
- );
1733
- const match = sshMatch || httpsMatch;
1734
- if (!match) return null;
1850
+ async function getActiveSession() {
1851
+ const storage = await loadSessions();
1852
+ if (!storage.activeSession || !storage.sessions[storage.activeSession]) {
1853
+ return null;
1854
+ }
1735
1855
  return {
1736
- owner: match[1],
1737
- repo: match[2]
1856
+ name: storage.activeSession,
1857
+ config: storage.sessions[storage.activeSession]
1738
1858
  };
1739
1859
  }
1740
- async function getCurrentBranch(cwd = process.cwd()) {
1741
- return gitCommand("git rev-parse --abbrev-ref HEAD", cwd);
1742
- }
1743
- async function getCommitSha(cwd = process.cwd()) {
1744
- return gitCommand("git rev-parse HEAD", cwd);
1745
- }
1746
- async function getCommitMessage(cwd = process.cwd()) {
1747
- return gitCommand("git log -1 --pretty=%B", cwd);
1860
+ async function getSession(name) {
1861
+ const storage = await loadSessions();
1862
+ return storage.sessions[name] || null;
1748
1863
  }
1749
- async function getGitInfo(cwd = process.cwd()) {
1750
- const isRepo = await isGitRepo(cwd);
1751
- if (!isRepo) {
1752
- return { isGitRepo: false };
1753
- }
1754
- const remoteUrl = await getRemoteUrl(cwd);
1755
- const branch = await getCurrentBranch(cwd);
1756
- const commitSha = await getCommitSha(cwd);
1757
- const commitMessage = await getCommitMessage(cwd);
1758
- let owner;
1759
- let repo;
1760
- if (remoteUrl) {
1761
- const parsed = parseGitHubUrl(remoteUrl);
1762
- if (parsed) {
1763
- owner = parsed.owner;
1764
- repo = parsed.repo;
1765
- }
1864
+ async function setActiveSession(name) {
1865
+ const storage = await loadSessions();
1866
+ if (!storage.sessions[name]) {
1867
+ throw new Error(`Session '${name}' not found`);
1766
1868
  }
1767
- return {
1768
- isGitRepo: true,
1769
- remoteUrl: remoteUrl || void 0,
1770
- owner,
1771
- repo,
1772
- branch: branch || void 0,
1773
- commitSha: commitSha || void 0,
1774
- commitMessage: commitMessage || void 0
1775
- };
1869
+ storage.activeSession = name;
1870
+ storage.sessions[name].lastUsed = (/* @__PURE__ */ new Date()).toISOString();
1871
+ await saveSessions(storage);
1776
1872
  }
1777
- function isGitHubUrl(url) {
1778
- try {
1779
- const parsedUrl = new URL(url);
1780
- return parsedUrl.hostname === "github.com" || parsedUrl.hostname === "www.github.com";
1781
- } catch {
1782
- const sshMatch = url.match(/^git@([^:/]+)[:/]/);
1783
- if (sshMatch) {
1784
- const host = sshMatch[1];
1785
- return host === "github.com" || host === "www.github.com";
1786
- }
1873
+ async function listAllSessions() {
1874
+ const storage = await loadSessions();
1875
+ return Object.entries(storage.sessions).map(([name, config]) => ({
1876
+ name,
1877
+ config,
1878
+ isActive: name === storage.activeSession
1879
+ }));
1880
+ }
1881
+ async function updateSessionInfo(name, serverInfo, capabilities) {
1882
+ const storage = await loadSessions();
1883
+ if (storage.sessions[name]) {
1884
+ storage.sessions[name].serverInfo = serverInfo;
1885
+ storage.sessions[name].capabilities = capabilities;
1886
+ storage.sessions[name].lastUsed = (/* @__PURE__ */ new Date()).toISOString();
1887
+ await saveSessions(storage);
1787
1888
  }
1788
- return false;
1789
1889
  }
1790
1890
 
1791
- // src/commands/deploy.ts
1792
- var execAsync2 = (0, import_node_util8.promisify)(import_node_child_process9.exec);
1793
- async function isMcpProject(cwd = process.cwd()) {
1794
- try {
1795
- const packageJsonPath = import_node_path3.default.join(cwd, "package.json");
1796
- const content = await import_node_fs5.promises.readFile(packageJsonPath, "utf-8");
1797
- const packageJson2 = JSON.parse(content);
1798
- const hasMcpDeps = packageJson2.dependencies?.["mcp-use"] || packageJson2.dependencies?.["@modelcontextprotocol/sdk"] || packageJson2.devDependencies?.["mcp-use"] || packageJson2.devDependencies?.["@modelcontextprotocol/sdk"];
1799
- const hasMcpScripts = packageJson2.scripts?.mcp || packageJson2.scripts?.["mcp:dev"];
1800
- return !!(hasMcpDeps || hasMcpScripts);
1801
- } catch {
1802
- return false;
1891
+ // src/utils/format.ts
1892
+ function formatTable(data, columns) {
1893
+ if (data.length === 0) {
1894
+ return source_default.gray("No items found");
1803
1895
  }
1804
- }
1805
- async function getProjectName(cwd = process.cwd()) {
1806
- try {
1807
- const packageJsonPath = import_node_path3.default.join(cwd, "package.json");
1808
- const content = await import_node_fs5.promises.readFile(packageJsonPath, "utf-8");
1809
- const packageJson2 = JSON.parse(content);
1810
- if (packageJson2.name) {
1811
- return packageJson2.name;
1896
+ const widths = columns.map((col) => {
1897
+ const maxDataWidth = Math.max(
1898
+ ...data.map((row) => String(row[col.key] || "").length)
1899
+ );
1900
+ const headerWidth = col.header.length;
1901
+ return col.width || Math.max(maxDataWidth, headerWidth, 10);
1902
+ });
1903
+ const createRow = (values, bold = false) => {
1904
+ const cells = values.map((val, i) => {
1905
+ const padded = val.padEnd(widths[i]);
1906
+ return bold ? source_default.bold(padded) : padded;
1907
+ });
1908
+ return `\u2502 ${cells.join(" \u2502 ")} \u2502`;
1909
+ };
1910
+ const separator = (char) => {
1911
+ const parts = widths.map((w) => char.repeat(w + 2));
1912
+ if (char === "\u2500") {
1913
+ return `\u251C${parts.join("\u253C")}\u2524`;
1812
1914
  }
1813
- } catch {
1814
- }
1815
- return import_node_path3.default.basename(cwd);
1915
+ return `\u2514${parts.join("\u2534")}\u2518`;
1916
+ };
1917
+ const lines = [];
1918
+ lines.push(`\u250C${widths.map((w) => "\u2500".repeat(w + 2)).join("\u252C")}\u2510`);
1919
+ lines.push(
1920
+ createRow(
1921
+ columns.map((c) => c.header),
1922
+ true
1923
+ )
1924
+ );
1925
+ lines.push(separator("\u2500"));
1926
+ data.forEach((row) => {
1927
+ lines.push(createRow(columns.map((c) => String(row[c.key] || ""))));
1928
+ });
1929
+ lines.push(separator("\u2500"));
1930
+ return lines.join("\n");
1816
1931
  }
1817
- async function detectBuildCommand(cwd = process.cwd()) {
1818
- try {
1819
- const packageJsonPath = import_node_path3.default.join(cwd, "package.json");
1820
- const content = await import_node_fs5.promises.readFile(packageJsonPath, "utf-8");
1821
- const packageJson2 = JSON.parse(content);
1822
- if (packageJson2.scripts?.build) {
1823
- return "npm run build";
1824
- }
1825
- } catch {
1932
+ function formatJson(data, pretty = true) {
1933
+ if (pretty) {
1934
+ return JSON.stringify(data, null, 2);
1826
1935
  }
1827
- return void 0;
1936
+ return JSON.stringify(data);
1828
1937
  }
1829
- async function detectStartCommand(cwd = process.cwd()) {
1830
- try {
1831
- const packageJsonPath = import_node_path3.default.join(cwd, "package.json");
1832
- const content = await import_node_fs5.promises.readFile(packageJsonPath, "utf-8");
1833
- const packageJson2 = JSON.parse(content);
1834
- if (packageJson2.scripts?.start) {
1835
- return "npm start";
1836
- }
1837
- if (packageJson2.main) {
1838
- return `node ${packageJson2.main}`;
1839
- }
1840
- } catch {
1938
+ function formatToolCall(result) {
1939
+ const lines = [];
1940
+ if (result.isError) {
1941
+ lines.push(source_default.red("\u2717 Tool execution failed"));
1942
+ lines.push("");
1943
+ } else {
1944
+ lines.push(source_default.green("\u2713 Tool executed successfully"));
1945
+ lines.push("");
1841
1946
  }
1842
- return void 0;
1843
- }
1844
- async function detectRuntime(cwd = process.cwd()) {
1845
- try {
1846
- const pythonFiles = ["requirements.txt", "pyproject.toml", "setup.py"];
1847
- for (const file of pythonFiles) {
1848
- try {
1849
- await import_node_fs5.promises.access(import_node_path3.default.join(cwd, file));
1850
- return "python";
1851
- } catch {
1852
- continue;
1947
+ if (result.content && result.content.length > 0) {
1948
+ result.content.forEach((item, index) => {
1949
+ if (result.content.length > 1) {
1950
+ lines.push(source_default.bold(`Content ${index + 1}:`));
1853
1951
  }
1854
- }
1855
- try {
1856
- await import_node_fs5.promises.access(import_node_path3.default.join(cwd, "package.json"));
1857
- return "node";
1858
- } catch {
1859
- }
1860
- } catch {
1861
- }
1862
- return "node";
1863
- }
1864
- async function prompt(question, defaultValue = "n") {
1865
- const readline = await import("readline");
1866
- const rl = readline.createInterface({
1867
- input: process.stdin,
1868
- output: process.stdout
1869
- });
1870
- const defaultIndicator = defaultValue === "y" ? "Y/n" : "y/N";
1871
- const questionWithDefault = question.replace(
1872
- /(\(y\/n\):)/,
1873
- `(${defaultIndicator}):`
1874
- );
1875
- return new Promise((resolve) => {
1876
- rl.question(questionWithDefault, (answer) => {
1877
- rl.close();
1878
- const trimmedAnswer = answer.trim().toLowerCase();
1879
- if (trimmedAnswer === "") {
1880
- resolve(defaultValue === "y");
1952
+ if (item.type === "text") {
1953
+ lines.push(item.text);
1954
+ } else if (item.type === "image") {
1955
+ lines.push(source_default.cyan(`[Image: ${item.mimeType || "unknown type"}]`));
1956
+ if (item.data) {
1957
+ lines.push(source_default.gray(`Data: ${item.data.substring(0, 50)}...`));
1958
+ }
1959
+ } else if (item.type === "resource") {
1960
+ lines.push(source_default.cyan(`[Resource]`));
1961
+ if (item.resource?.uri) {
1962
+ lines.push(source_default.gray(`URI: ${item.resource.uri}`));
1963
+ }
1964
+ if (item.resource && "text" in item.resource && item.resource.text) {
1965
+ lines.push(item.resource.text);
1966
+ }
1881
1967
  } else {
1882
- resolve(trimmedAnswer === "y" || trimmedAnswer === "yes");
1968
+ lines.push(source_default.gray(`[Unknown content type: ${item.type}]`));
1969
+ }
1970
+ if (index < result.content.length - 1) {
1971
+ lines.push("");
1883
1972
  }
1884
1973
  });
1885
- });
1886
- }
1887
- async function createTarball(cwd) {
1888
- const tmpDir = import_node_os4.default.tmpdir();
1889
- const tarballPath = import_node_path3.default.join(tmpDir, `mcp-deploy-${Date.now()}.tar.gz`);
1890
- const excludePatterns = [
1891
- "node_modules",
1892
- ".git",
1893
- "dist",
1894
- "build",
1895
- ".next",
1896
- ".venv",
1897
- "__pycache__",
1898
- "*.pyc",
1899
- ".DS_Store",
1900
- "._*",
1901
- // macOS resource fork files
1902
- ".mcp-use",
1903
- // Build artifacts directory
1904
- ".env",
1905
- ".env.local",
1906
- "*.log"
1907
- ];
1908
- const excludeFlags = excludePatterns.map((pattern) => `--exclude=${pattern}`).join(" ");
1909
- const command = `tar ${excludeFlags} -czf "${tarballPath}" -C "${cwd}" . 2>&1 || true`;
1910
- try {
1911
- await execAsync2(command);
1912
- return tarballPath;
1913
- } catch (error) {
1914
- throw new Error(
1915
- `Failed to create tarball: ${error instanceof Error ? error.message : "Unknown error"}`
1916
- );
1917
1974
  }
1975
+ return lines.join("\n");
1918
1976
  }
1919
- function formatFileSize(bytes) {
1920
- if (bytes === 0) return "0 B";
1921
- const k = 1024;
1922
- const sizes = ["B", "KB", "MB", "GB"];
1923
- const i = Math.floor(Math.log(bytes) / Math.log(k));
1924
- return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
1925
- }
1926
- async function displayDeploymentProgress(api, deployment) {
1927
- const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
1928
- let frameIndex = 0;
1929
- let spinnerInterval = null;
1930
- let lastStep = "";
1931
- const startSpinner = (message) => {
1932
- if (spinnerInterval) {
1933
- clearInterval(spinnerInterval);
1977
+ function formatResourceContent(content) {
1978
+ if (!content || !content.contents) {
1979
+ return source_default.gray("No content");
1980
+ }
1981
+ const lines = [];
1982
+ content.contents.forEach((item, index) => {
1983
+ if (content.contents.length > 1) {
1984
+ lines.push(source_default.bold(`Content ${index + 1}:`));
1934
1985
  }
1935
- process.stdout.write("\r\x1B[K");
1936
- spinnerInterval = setInterval(() => {
1937
- const frame = frames[frameIndex];
1938
- frameIndex = (frameIndex + 1) % frames.length;
1939
- process.stdout.write(
1940
- "\r" + source_default.cyan(frame) + " " + source_default.gray(message)
1941
- );
1942
- }, 80);
1943
- };
1944
- const stopSpinner = () => {
1945
- if (spinnerInterval) {
1946
- clearInterval(spinnerInterval);
1947
- spinnerInterval = null;
1948
- process.stdout.write("\r\x1B[K");
1986
+ if (item.uri) {
1987
+ lines.push(source_default.gray(`URI: ${item.uri}`));
1949
1988
  }
1950
- };
1951
- console.log();
1952
- startSpinner("Deploying...");
1953
- try {
1954
- for await (const log of api.streamDeploymentLogs(deployment.id)) {
1955
- try {
1956
- const logData = JSON.parse(log);
1957
- if (logData.step && logData.step !== lastStep) {
1958
- lastStep = logData.step;
1959
- const stepMessages = {
1960
- clone: "Preparing source code...",
1961
- analyze: "Analyzing project...",
1962
- build: "Building container image...",
1963
- deploy: "Deploying to cloud..."
1964
- };
1965
- const message = stepMessages[logData.step] || "Deploying...";
1966
- startSpinner(message);
1967
- }
1968
- if (logData.line) {
1969
- stopSpinner();
1970
- const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
1971
- const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
1972
- console.log(stepPrefix + levelColor(logData.line));
1973
- }
1974
- } catch {
1975
- }
1989
+ if (item.mimeType) {
1990
+ lines.push(source_default.gray(`Type: ${item.mimeType}`));
1976
1991
  }
1977
- } catch (error) {
1978
- stopSpinner();
1992
+ if ("text" in item && item.text) {
1993
+ lines.push("");
1994
+ lines.push(item.text);
1995
+ } else if ("blob" in item && item.blob) {
1996
+ lines.push("");
1997
+ lines.push(source_default.cyan(`[Binary data: ${item.blob.length} bytes]`));
1998
+ }
1999
+ if (index < content.contents.length - 1) {
2000
+ lines.push("");
2001
+ lines.push(source_default.gray("\u2500".repeat(50)));
2002
+ lines.push("");
2003
+ }
2004
+ });
2005
+ return lines.join("\n");
2006
+ }
2007
+ function formatSchema(schema, indent = 0) {
2008
+ if (!schema) {
2009
+ return source_default.gray("No schema");
1979
2010
  }
1980
- let checkCount = 0;
1981
- const maxChecks = 60;
1982
- let delay = 3e3;
1983
- const maxDelay = 1e4;
1984
- let lastDisplayedLogLength = 0;
1985
- while (checkCount < maxChecks) {
1986
- const currentDelay = delay;
1987
- await new Promise((resolve) => setTimeout(resolve, currentDelay));
1988
- const finalDeployment = await api.getDeployment(deployment.id);
1989
- if (finalDeployment.buildLogs && finalDeployment.buildLogs.length > lastDisplayedLogLength) {
1990
- const newLogs = finalDeployment.buildLogs.substring(
1991
- lastDisplayedLogLength
1992
- );
1993
- const logLines = newLogs.split("\n").filter((l) => l.trim());
1994
- for (const line of logLines) {
1995
- try {
1996
- const logData = JSON.parse(line);
1997
- if (logData.line) {
1998
- stopSpinner();
1999
- const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
2000
- const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
2001
- console.log(stepPrefix + levelColor(logData.line));
2002
- }
2003
- } catch {
2011
+ const lines = [];
2012
+ const pad = " ".repeat(indent);
2013
+ if (schema.type === "object" && schema.properties) {
2014
+ Object.entries(schema.properties).forEach(([key, value]) => {
2015
+ const required = schema.required?.includes(key);
2016
+ const type = value.type || "any";
2017
+ const desc = value.description || "";
2018
+ const keyStr = required ? source_default.bold(key) : key;
2019
+ const typeStr = source_default.cyan(`(${type})`);
2020
+ const requiredStr = required ? source_default.red(" *required") : "";
2021
+ lines.push(`${pad}${keyStr} ${typeStr}${requiredStr}`);
2022
+ if (desc) {
2023
+ lines.push(`${pad} ${source_default.gray(desc)}`);
2024
+ }
2025
+ if (value.type === "object" && value.properties) {
2026
+ lines.push(formatSchema(value, indent + 1));
2027
+ }
2028
+ if (value.type === "array" && value.items) {
2029
+ lines.push(`${pad} ${source_default.gray("Items:")}`);
2030
+ if (value.items.type === "object") {
2031
+ lines.push(formatSchema(value.items, indent + 2));
2032
+ } else {
2033
+ lines.push(
2034
+ `${pad} ${source_default.cyan(`(${value.items.type || "any"})`)}`
2035
+ );
2004
2036
  }
2005
2037
  }
2006
- lastDisplayedLogLength = finalDeployment.buildLogs.length;
2038
+ });
2039
+ } else {
2040
+ lines.push(`${pad}${source_default.cyan(`Type: ${schema.type || "any"}`)}`);
2041
+ if (schema.description) {
2042
+ lines.push(`${pad}${source_default.gray(schema.description)}`);
2007
2043
  }
2008
- if (finalDeployment.status === "running") {
2009
- const mcpUrl = `https://${finalDeployment.domain}/mcp`;
2010
- const inspectorUrl = `https://inspector.mcp-use.com/inspector?autoConnect=${encodeURIComponent(mcpUrl)}`;
2011
- console.log(source_default.green.bold("\u2713 Deployment successful!\n"));
2012
- console.log(source_default.white("\u{1F310} MCP Server URL:"));
2013
- console.log(source_default.cyan.bold(` ${mcpUrl}
2014
- `));
2015
- console.log(source_default.white("\u{1F50D} Inspector URL:"));
2016
- console.log(source_default.cyan.bold(` ${inspectorUrl}
2017
- `));
2018
- if (finalDeployment.customDomain) {
2019
- const customMcpUrl = `https://${finalDeployment.customDomain}/mcp`;
2020
- const customInspectorUrl = `https://inspector.mcp-use.com/inspect?autoConnect=${encodeURIComponent(customMcpUrl)}`;
2021
- console.log(source_default.white("\u{1F517} Custom Domain:"));
2022
- console.log(source_default.cyan.bold(` ${customMcpUrl}
2023
- `));
2024
- console.log(source_default.white("\u{1F50D} Custom Inspector:"));
2025
- console.log(source_default.cyan.bold(` ${customInspectorUrl}
2026
- `));
2027
- }
2028
- console.log(
2029
- source_default.gray("Deployment ID: ") + source_default.white(finalDeployment.id)
2030
- );
2031
- return;
2032
- } else if (finalDeployment.status === "failed") {
2033
- console.log(source_default.red.bold("\u2717 Deployment failed\n"));
2034
- if (finalDeployment.error) {
2035
- console.log(source_default.red("Error: ") + finalDeployment.error);
2036
- }
2037
- if (finalDeployment.buildLogs) {
2038
- console.log(source_default.gray("\nBuild logs:"));
2039
- try {
2040
- const logs = finalDeployment.buildLogs.split("\n").filter((l) => l.trim());
2041
- for (const log of logs) {
2042
- try {
2043
- const logData = JSON.parse(log);
2044
- if (logData.line) {
2045
- console.log(source_default.gray(` ${logData.line}`));
2046
- }
2047
- } catch {
2048
- console.log(source_default.gray(` ${log}`));
2049
- }
2050
- }
2051
- } catch {
2052
- console.log(source_default.gray(finalDeployment.buildLogs));
2044
+ }
2045
+ return lines.join("\n");
2046
+ }
2047
+ function formatError(error) {
2048
+ const message = typeof error === "string" ? error : error.message;
2049
+ return source_default.red(`\u2717 Error: ${message}`);
2050
+ }
2051
+ function formatSuccess(message) {
2052
+ return source_default.green(`\u2713 ${message}`);
2053
+ }
2054
+ function formatInfo(message) {
2055
+ return source_default.cyan(message);
2056
+ }
2057
+ function formatWarning(message) {
2058
+ return source_default.yellow(`\u26A0 ${message}`);
2059
+ }
2060
+ function formatHeader(text) {
2061
+ return source_default.bold.white(text);
2062
+ }
2063
+ function formatKeyValue(pairs) {
2064
+ const maxKeyLength = Math.max(...Object.keys(pairs).map((k) => k.length), 0);
2065
+ return Object.entries(pairs).map(([key, value]) => {
2066
+ const paddedKey = key.padEnd(maxKeyLength);
2067
+ return ` ${source_default.gray(paddedKey)}: ${value}`;
2068
+ }).join("\n");
2069
+ }
2070
+ function formatRelativeTime(dateString) {
2071
+ const date = new Date(dateString);
2072
+ const now = /* @__PURE__ */ new Date();
2073
+ const diffMs = now.getTime() - date.getTime();
2074
+ const diffSecs = Math.floor(diffMs / 1e3);
2075
+ const diffMins = Math.floor(diffSecs / 60);
2076
+ const diffHours = Math.floor(diffMins / 60);
2077
+ const diffDays = Math.floor(diffHours / 24);
2078
+ const diffWeeks = Math.floor(diffDays / 7);
2079
+ const diffMonths = Math.floor(diffDays / 30);
2080
+ const diffYears = Math.floor(diffDays / 365);
2081
+ if (diffYears > 0) {
2082
+ return `${diffYears} year${diffYears > 1 ? "s" : ""} ago`;
2083
+ } else if (diffMonths > 0) {
2084
+ return `${diffMonths} month${diffMonths > 1 ? "s" : ""} ago`;
2085
+ } else if (diffWeeks > 0) {
2086
+ return `${diffWeeks} week${diffWeeks > 1 ? "s" : ""} ago`;
2087
+ } else if (diffDays > 0) {
2088
+ return `${diffDays} day${diffDays > 1 ? "s" : ""} ago`;
2089
+ } else if (diffHours > 0) {
2090
+ return `${diffHours} hour${diffHours > 1 ? "s" : ""} ago`;
2091
+ } else if (diffMins > 0) {
2092
+ return `${diffMins} minute${diffMins > 1 ? "s" : ""} ago`;
2093
+ } else {
2094
+ return "just now";
2095
+ }
2096
+ }
2097
+ function formatPromptMessages(messages) {
2098
+ if (!messages || messages.length === 0) {
2099
+ return source_default.gray("No messages");
2100
+ }
2101
+ const lines = [];
2102
+ messages.forEach((msg, index) => {
2103
+ const role = msg.role || "unknown";
2104
+ const roleStr = role === "user" ? source_default.blue("[User]") : role === "assistant" ? source_default.green("[Assistant]") : source_default.gray(`[${role}]`);
2105
+ lines.push(`${roleStr}`);
2106
+ if (msg.content) {
2107
+ if (typeof msg.content === "string") {
2108
+ lines.push(msg.content);
2109
+ } else if (msg.content.type === "text") {
2110
+ lines.push(msg.content.text);
2111
+ } else if (msg.content.type === "image") {
2112
+ lines.push(source_default.cyan(`[Image: ${msg.content.mimeType}]`));
2113
+ } else if (msg.content.type === "resource") {
2114
+ lines.push(source_default.cyan(`[Resource: ${msg.content.resource?.uri}]`));
2115
+ if (msg.content.resource?.text) {
2116
+ lines.push(msg.content.resource.text);
2053
2117
  }
2054
2118
  }
2055
- process.exit(1);
2056
- } else if (finalDeployment.status === "building") {
2057
- startSpinner("Building and deploying...");
2058
- checkCount++;
2059
- delay = Math.min(delay * 1.2, maxDelay);
2060
- } else {
2061
- console.log(
2062
- source_default.yellow("\u26A0\uFE0F Deployment status: ") + finalDeployment.status
2119
+ }
2120
+ if (index < messages.length - 1) {
2121
+ lines.push("");
2122
+ }
2123
+ });
2124
+ return lines.join("\n");
2125
+ }
2126
+
2127
+ // src/commands/client.ts
2128
+ var activeSessions = /* @__PURE__ */ new Map();
2129
+ async function getOrRestoreSession(sessionName) {
2130
+ if (!sessionName) {
2131
+ const active = await getActiveSession();
2132
+ if (!active) {
2133
+ console.error(
2134
+ formatError("No active session. Connect to a server first.")
2063
2135
  );
2064
- return;
2136
+ console.error(
2137
+ formatInfo("Use: npx mcp-use client connect <url> --name <name>")
2138
+ );
2139
+ return null;
2065
2140
  }
2141
+ sessionName = active.name;
2142
+ }
2143
+ if (activeSessions.has(sessionName)) {
2144
+ const { session } = activeSessions.get(sessionName);
2145
+ return { name: sessionName, session };
2146
+ }
2147
+ const config = await getSession(sessionName);
2148
+ if (!config) {
2149
+ console.error(formatError(`Session '${sessionName}' not found`));
2150
+ return null;
2151
+ }
2152
+ try {
2153
+ const client = new import_client.MCPClient();
2154
+ if (config.type === "http") {
2155
+ client.addServer(sessionName, {
2156
+ url: config.url,
2157
+ headers: config.authToken ? { Authorization: `Bearer ${config.authToken}` } : void 0
2158
+ });
2159
+ } else if (config.type === "stdio") {
2160
+ client.addServer(sessionName, {
2161
+ command: config.command,
2162
+ args: config.args || [],
2163
+ env: config.env
2164
+ });
2165
+ } else {
2166
+ console.error(formatError(`Unknown session type: ${config.type}`));
2167
+ return null;
2168
+ }
2169
+ const session = await client.createSession(sessionName);
2170
+ activeSessions.set(sessionName, { client, session });
2171
+ console.error(formatInfo(`Reconnected to session '${sessionName}'`));
2172
+ return { name: sessionName, session };
2173
+ } catch (error) {
2174
+ console.error(formatError(`Failed to restore session: ${error.message}`));
2175
+ return null;
2066
2176
  }
2067
- stopSpinner();
2068
- console.log(source_default.yellow("\u26A0\uFE0F Deployment is taking longer than expected."));
2069
- console.log(
2070
- source_default.gray("Check status with: ") + source_default.white(`mcp-use status ${deployment.id}`)
2071
- );
2072
2177
  }
2073
- async function deployCommand(options) {
2178
+ async function connectCommand(urlOrCommand, options) {
2074
2179
  try {
2075
- const cwd = process.cwd();
2076
- if (!await isLoggedIn()) {
2077
- console.log(source_default.red("\u2717 You are not logged in."));
2078
- console.log(
2079
- source_default.gray("Run " + source_default.white("mcp-use login") + " to get started.")
2180
+ const sessionName = options.name || `session-${Date.now()}`;
2181
+ const client = new import_client.MCPClient();
2182
+ let session;
2183
+ if (options.stdio) {
2184
+ const parts = urlOrCommand.split(" ");
2185
+ const command = parts[0];
2186
+ const args = parts.slice(1);
2187
+ console.error(
2188
+ formatInfo(`Connecting to stdio server: ${command} ${args.join(" ")}`)
2080
2189
  );
2081
- process.exit(1);
2190
+ client.addServer(sessionName, {
2191
+ command,
2192
+ args
2193
+ });
2194
+ session = await client.createSession(sessionName);
2195
+ await saveSession(sessionName, {
2196
+ type: "stdio",
2197
+ command,
2198
+ args,
2199
+ lastUsed: (/* @__PURE__ */ new Date()).toISOString()
2200
+ });
2201
+ } else {
2202
+ console.error(formatInfo(`Connecting to ${urlOrCommand}...`));
2203
+ client.addServer(sessionName, {
2204
+ url: urlOrCommand,
2205
+ headers: options.auth ? { Authorization: `Bearer ${options.auth}` } : void 0
2206
+ });
2207
+ session = await client.createSession(sessionName);
2208
+ await saveSession(sessionName, {
2209
+ type: "http",
2210
+ url: urlOrCommand,
2211
+ authToken: options.auth,
2212
+ lastUsed: (/* @__PURE__ */ new Date()).toISOString()
2213
+ });
2082
2214
  }
2083
- console.log(source_default.cyan.bold("\u{1F680} Deploying to mcp-use cloud...\n"));
2084
- const isMcp = await isMcpProject(cwd);
2085
- if (!isMcp) {
2215
+ activeSessions.set(sessionName, { client, session });
2216
+ const serverInfo = session.serverInfo;
2217
+ const capabilities = session.serverCapabilities;
2218
+ if (serverInfo) {
2219
+ await updateSessionInfo(sessionName, serverInfo, capabilities);
2220
+ }
2221
+ console.log(formatSuccess(`Connected to ${sessionName}`));
2222
+ if (serverInfo) {
2223
+ console.log("");
2224
+ console.log(formatHeader("Server Information:"));
2086
2225
  console.log(
2087
- source_default.yellow(
2088
- "\u26A0\uFE0F This doesn't appear to be an MCP server project (no mcp-use or @modelcontextprotocol/sdk dependency found)."
2089
- )
2090
- );
2091
- const shouldContinue = await prompt(
2092
- source_default.white("Continue anyway? (y/n): ")
2226
+ formatKeyValue({
2227
+ Name: serverInfo.name,
2228
+ Version: serverInfo.version || "unknown"
2229
+ })
2093
2230
  );
2094
- if (!shouldContinue) {
2095
- console.log(source_default.gray("Deployment cancelled."));
2096
- process.exit(0);
2231
+ }
2232
+ if (capabilities) {
2233
+ console.log("");
2234
+ console.log(formatHeader("Capabilities:"));
2235
+ const caps = Object.keys(capabilities).join(", ");
2236
+ console.log(` ${caps || "none"}`);
2237
+ }
2238
+ const tools = session.tools;
2239
+ console.log("");
2240
+ console.log(
2241
+ formatInfo(
2242
+ `Available: ${tools.length} tool${tools.length !== 1 ? "s" : ""}`
2243
+ )
2244
+ );
2245
+ } catch (error) {
2246
+ console.error(formatError(`Connection failed: ${error.message}`));
2247
+ process.exit(1);
2248
+ }
2249
+ }
2250
+ async function disconnectCommand(sessionName, options) {
2251
+ try {
2252
+ if (options?.all) {
2253
+ for (const [name, { client }] of activeSessions.entries()) {
2254
+ await client.closeAllSessions();
2255
+ activeSessions.delete(name);
2256
+ console.log(formatSuccess(`Disconnected from ${name}`));
2097
2257
  }
2098
- console.log();
2258
+ return;
2099
2259
  }
2100
- const gitInfo = await getGitInfo(cwd);
2101
- if (!options.fromSource && gitInfo.isGitRepo && gitInfo.remoteUrl && isGitHubUrl(gitInfo.remoteUrl)) {
2102
- if (!gitInfo.owner || !gitInfo.repo) {
2103
- console.log(
2104
- source_default.red(
2105
- "\u2717 Could not parse GitHub repository information from remote URL."
2106
- )
2107
- );
2108
- process.exit(1);
2109
- }
2110
- console.log(source_default.white("GitHub repository detected:"));
2111
- console.log(
2112
- source_default.gray(` Repository: `) + source_default.cyan(`${gitInfo.owner}/${gitInfo.repo}`)
2113
- );
2114
- console.log(
2115
- source_default.gray(` Branch: `) + source_default.cyan(gitInfo.branch || "main")
2116
- );
2117
- if (gitInfo.commitSha) {
2118
- console.log(
2119
- source_default.gray(` Commit: `) + source_default.gray(gitInfo.commitSha.substring(0, 7))
2120
- );
2121
- }
2122
- if (gitInfo.commitMessage) {
2123
- console.log(
2124
- source_default.gray(` Message: `) + source_default.gray(gitInfo.commitMessage.split("\n")[0])
2125
- );
2126
- }
2127
- console.log();
2128
- const shouldDeploy = await prompt(
2129
- source_default.white(
2130
- `Deploy from GitHub repository ${gitInfo.owner}/${gitInfo.repo}? (y/n): `
2131
- )
2132
- );
2133
- if (!shouldDeploy) {
2134
- console.log(source_default.gray("Deployment cancelled."));
2135
- process.exit(0);
2136
- }
2137
- const projectName = options.name || await getProjectName(cwd);
2138
- const runtime = options.runtime || await detectRuntime(cwd);
2139
- const port = options.port || 3e3;
2140
- const buildCommand = await detectBuildCommand(cwd);
2141
- const startCommand = await detectStartCommand(cwd);
2142
- console.log();
2143
- console.log(source_default.white("Deployment configuration:"));
2144
- console.log(source_default.gray(` Name: `) + source_default.cyan(projectName));
2145
- console.log(source_default.gray(` Runtime: `) + source_default.cyan(runtime));
2146
- console.log(source_default.gray(` Port: `) + source_default.cyan(port));
2147
- if (buildCommand) {
2148
- console.log(source_default.gray(` Build command: `) + source_default.cyan(buildCommand));
2149
- }
2150
- if (startCommand) {
2151
- console.log(source_default.gray(` Start command: `) + source_default.cyan(startCommand));
2152
- }
2153
- console.log();
2154
- const deploymentRequest = {
2155
- name: projectName,
2156
- source: {
2157
- type: "github",
2158
- repo: `${gitInfo.owner}/${gitInfo.repo}`,
2159
- branch: gitInfo.branch || "main",
2160
- runtime,
2161
- port,
2162
- buildCommand,
2163
- startCommand
2164
- },
2165
- healthCheckPath: "/healthz"
2166
- };
2167
- console.log(source_default.gray("Creating deployment..."));
2168
- const api = await McpUseAPI.create();
2169
- const deployment = await api.createDeployment(deploymentRequest);
2170
- console.log(
2171
- source_default.green("\u2713 Deployment created: ") + source_default.gray(deployment.id)
2172
- );
2173
- await displayDeploymentProgress(api, deployment);
2174
- if (options.open && deployment.domain) {
2175
- console.log();
2176
- console.log(source_default.gray("Opening deployment in browser..."));
2177
- await open_default(`https://${deployment.domain}`);
2260
+ if (!sessionName) {
2261
+ const active = await getActiveSession();
2262
+ if (!active) {
2263
+ console.error(formatError("No active session to disconnect"));
2264
+ return;
2178
2265
  }
2266
+ sessionName = active.name;
2267
+ }
2268
+ const sessionData = activeSessions.get(sessionName);
2269
+ if (sessionData) {
2270
+ await sessionData.client.closeAllSessions();
2271
+ activeSessions.delete(sessionName);
2272
+ console.log(formatSuccess(`Disconnected from ${sessionName}`));
2179
2273
  } else {
2180
- if (options.fromSource) {
2181
- console.log(
2182
- source_default.white("\u{1F4E6} Deploying from local source code (--from-source)...")
2183
- );
2184
- } else {
2185
- console.log(
2186
- source_default.yellow(
2187
- "\u26A0\uFE0F This is not a GitHub repository or no remote is configured."
2188
- )
2189
- );
2190
- console.log(source_default.white("Deploying from local source code instead..."));
2191
- }
2192
- console.log();
2193
- const projectName = options.name || await getProjectName(cwd);
2194
- const runtime = options.runtime || await detectRuntime(cwd);
2195
- const port = options.port || 3e3;
2196
- const buildCommand = await detectBuildCommand(cwd);
2197
- const startCommand = await detectStartCommand(cwd);
2198
- console.log(source_default.white("Deployment configuration:"));
2199
- console.log(source_default.gray(` Name: `) + source_default.cyan(projectName));
2200
- console.log(source_default.gray(` Runtime: `) + source_default.cyan(runtime));
2201
- console.log(source_default.gray(` Port: `) + source_default.cyan(port));
2202
- if (buildCommand) {
2203
- console.log(source_default.gray(` Build command: `) + source_default.cyan(buildCommand));
2204
- }
2205
- if (startCommand) {
2206
- console.log(source_default.gray(` Start command: `) + source_default.cyan(startCommand));
2207
- }
2208
- console.log();
2209
- const shouldDeploy = await prompt(
2210
- source_default.white("Deploy from local source? (y/n): "),
2211
- "y"
2212
- );
2213
- if (!shouldDeploy) {
2214
- console.log(source_default.gray("Deployment cancelled."));
2215
- process.exit(0);
2216
- }
2217
- console.log();
2218
- console.log(source_default.gray("Packaging source code..."));
2219
- const tarballPath = await createTarball(cwd);
2220
- const stats = await import_node_fs5.promises.stat(tarballPath);
2221
- console.log(
2222
- source_default.green("\u2713 Packaged: ") + source_default.gray(formatFileSize(stats.size))
2223
- );
2224
- const maxSize = 2 * 1024 * 1024;
2225
- if (stats.size > maxSize) {
2226
- console.log(
2227
- source_default.red(
2228
- `\u2717 File size (${formatFileSize(stats.size)}) exceeds maximum of 2MB`
2229
- )
2230
- );
2231
- await import_node_fs5.promises.unlink(tarballPath);
2232
- process.exit(1);
2233
- }
2234
- const deploymentRequest = {
2235
- name: projectName,
2236
- source: {
2237
- type: "upload",
2238
- runtime,
2239
- port,
2240
- buildCommand,
2241
- startCommand
2242
- },
2243
- healthCheckPath: "/healthz"
2244
- };
2245
- console.log(source_default.gray("Creating deployment..."));
2246
- const api = await McpUseAPI.create();
2247
- const deployment = await api.createDeploymentWithUpload(
2248
- deploymentRequest,
2249
- tarballPath
2250
- );
2251
- await import_node_fs5.promises.unlink(tarballPath);
2274
+ console.log(formatInfo(`Session '${sessionName}' is not connected`));
2275
+ }
2276
+ } catch (error) {
2277
+ console.error(formatError(`Failed to disconnect: ${error.message}`));
2278
+ process.exit(1);
2279
+ }
2280
+ }
2281
+ async function listSessionsCommand() {
2282
+ try {
2283
+ const sessions = await listAllSessions();
2284
+ if (sessions.length === 0) {
2285
+ console.log(formatInfo("No saved sessions"));
2252
2286
  console.log(
2253
- source_default.green("\u2713 Deployment created: ") + source_default.gray(deployment.id)
2287
+ formatInfo("Connect to a server with: npx mcp-use client connect <url>")
2254
2288
  );
2255
- await displayDeploymentProgress(api, deployment);
2256
- if (options.open && deployment.domain) {
2257
- console.log();
2258
- console.log(source_default.gray("Opening deployment in browser..."));
2259
- await open_default(`https://${deployment.domain}`);
2260
- }
2289
+ return;
2261
2290
  }
2262
- } catch (error) {
2263
- console.error(
2264
- source_default.red.bold("\n\u2717 Deployment failed:"),
2265
- source_default.red(error instanceof Error ? error.message : "Unknown error")
2291
+ console.log(formatHeader("Saved Sessions:"));
2292
+ console.log("");
2293
+ const tableData = sessions.map((s) => ({
2294
+ name: s.isActive ? source_default.green.bold(`${s.name} *`) : s.name,
2295
+ type: s.config.type,
2296
+ target: s.config.type === "http" ? s.config.url || "" : `${s.config.command} ${(s.config.args || []).join(" ")}`,
2297
+ server: s.config.serverInfo?.name || "unknown",
2298
+ status: activeSessions.has(s.name) ? source_default.green("connected") : source_default.gray("disconnected")
2299
+ }));
2300
+ console.log(
2301
+ formatTable(tableData, [
2302
+ { key: "name", header: "Name" },
2303
+ { key: "type", header: "Type" },
2304
+ { key: "target", header: "Target", width: 40 },
2305
+ { key: "server", header: "Server" },
2306
+ { key: "status", header: "Status" }
2307
+ ])
2266
2308
  );
2309
+ console.log("");
2310
+ console.log(source_default.gray("* = active session"));
2311
+ } catch (error) {
2312
+ console.error(formatError(`Failed to list sessions: ${error.message}`));
2267
2313
  process.exit(1);
2268
2314
  }
2269
2315
  }
2270
-
2271
- // src/commands/client.ts
2272
- var import_commander = require("commander");
2273
- var import_node_readline = require("readline");
2274
- var import_client = require("mcp-use/client");
2275
-
2276
- // src/utils/session-storage.ts
2277
- var import_node_os5 = require("os");
2278
- var import_node_path4 = require("path");
2279
- var import_promises4 = require("fs/promises");
2280
- var import_node_fs6 = require("fs");
2281
- var SESSION_FILE_PATH = (0, import_node_path4.join)((0, import_node_os5.homedir)(), ".mcp-use", "cli-sessions.json");
2282
- async function ensureSessionDir() {
2283
- const dir = (0, import_node_path4.join)((0, import_node_os5.homedir)(), ".mcp-use");
2284
- if (!(0, import_node_fs6.existsSync)(dir)) {
2285
- await (0, import_promises4.mkdir)(dir, { recursive: true });
2316
+ async function switchSessionCommand(name) {
2317
+ try {
2318
+ await setActiveSession(name);
2319
+ console.log(formatSuccess(`Switched to session '${name}'`));
2320
+ } catch (error) {
2321
+ console.error(formatError(`Failed to switch session: ${error.message}`));
2322
+ process.exit(1);
2286
2323
  }
2287
2324
  }
2288
- async function loadSessions() {
2325
+ async function listToolsCommand(options) {
2289
2326
  try {
2290
- await ensureSessionDir();
2291
- if (!(0, import_node_fs6.existsSync)(SESSION_FILE_PATH)) {
2292
- return { activeSession: null, sessions: {} };
2327
+ const result = await getOrRestoreSession(options.session || null);
2328
+ if (!result) return;
2329
+ const { session } = result;
2330
+ const tools = await session.listTools();
2331
+ if (options.json) {
2332
+ console.log(formatJson(tools));
2333
+ return;
2293
2334
  }
2294
- const content = await (0, import_promises4.readFile)(SESSION_FILE_PATH, "utf-8");
2295
- return JSON.parse(content);
2335
+ if (tools.length === 0) {
2336
+ console.log(formatInfo("No tools available"));
2337
+ return;
2338
+ }
2339
+ console.log(formatHeader(`Available Tools (${tools.length}):`));
2340
+ console.log("");
2341
+ const tableData = tools.map((tool) => ({
2342
+ name: source_default.bold(tool.name),
2343
+ description: tool.description || source_default.gray("No description")
2344
+ }));
2345
+ console.log(
2346
+ formatTable(tableData, [
2347
+ { key: "name", header: "Tool", width: 25 },
2348
+ { key: "description", header: "Description", width: 50 }
2349
+ ])
2350
+ );
2296
2351
  } catch (error) {
2297
- return { activeSession: null, sessions: {} };
2352
+ console.error(formatError(`Failed to list tools: ${error.message}`));
2353
+ process.exit(1);
2298
2354
  }
2299
2355
  }
2300
- async function saveSessions(storage) {
2301
- await ensureSessionDir();
2302
- await (0, import_promises4.writeFile)(SESSION_FILE_PATH, JSON.stringify(storage, null, 2), "utf-8");
2303
- }
2304
- async function saveSession(name, config) {
2305
- const storage = await loadSessions();
2306
- storage.sessions[name] = {
2307
- ...config,
2308
- lastUsed: (/* @__PURE__ */ new Date()).toISOString()
2309
- };
2310
- if (!storage.activeSession) {
2311
- storage.activeSession = name;
2356
+ async function describeToolCommand(toolName, options) {
2357
+ try {
2358
+ const result = await getOrRestoreSession(options.session || null);
2359
+ if (!result) return;
2360
+ const { session } = result;
2361
+ const tools = session.tools;
2362
+ const tool = tools.find((t) => t.name === toolName);
2363
+ if (!tool) {
2364
+ console.error(formatError(`Tool '${toolName}' not found`));
2365
+ console.log("");
2366
+ console.log(formatInfo("Available tools:"));
2367
+ tools.forEach((t) => console.log(` \u2022 ${t.name}`));
2368
+ return;
2369
+ }
2370
+ console.log(formatHeader(`Tool: ${tool.name}`));
2371
+ console.log("");
2372
+ if (tool.description) {
2373
+ console.log(tool.description);
2374
+ console.log("");
2375
+ }
2376
+ if (tool.inputSchema) {
2377
+ console.log(formatHeader("Input Schema:"));
2378
+ console.log(formatSchema(tool.inputSchema));
2379
+ }
2380
+ } catch (error) {
2381
+ console.error(formatError(`Failed to describe tool: ${error.message}`));
2382
+ process.exit(1);
2312
2383
  }
2313
- await saveSessions(storage);
2314
2384
  }
2315
- async function getActiveSession() {
2316
- const storage = await loadSessions();
2317
- if (!storage.activeSession || !storage.sessions[storage.activeSession]) {
2318
- return null;
2385
+ async function callToolCommand(toolName, argsJson, options) {
2386
+ try {
2387
+ const result = await getOrRestoreSession(options?.session || null);
2388
+ if (!result) return;
2389
+ const { session } = result;
2390
+ let args = {};
2391
+ if (argsJson) {
2392
+ try {
2393
+ args = JSON.parse(argsJson);
2394
+ } catch (error) {
2395
+ console.error(formatError("Invalid JSON arguments"));
2396
+ return;
2397
+ }
2398
+ } else {
2399
+ const tools = session.tools;
2400
+ const tool = tools.find((t) => t.name === toolName);
2401
+ if (tool?.inputSchema?.required && tool.inputSchema.required.length > 0) {
2402
+ console.error(
2403
+ formatError(
2404
+ "This tool requires arguments. Provide them as a JSON string."
2405
+ )
2406
+ );
2407
+ console.log("");
2408
+ console.log(formatInfo("Example:"));
2409
+ console.log(
2410
+ ` npx mcp-use client tools call ${toolName} '{"param": "value"}'`
2411
+ );
2412
+ console.log("");
2413
+ console.log(formatInfo("Tool schema:"));
2414
+ console.log(formatSchema(tool.inputSchema));
2415
+ return;
2416
+ }
2417
+ }
2418
+ console.error(formatInfo(`Calling tool '${toolName}'...`));
2419
+ const callResult = await session.callTool(toolName, args, {
2420
+ timeout: options?.timeout
2421
+ });
2422
+ if (options?.json) {
2423
+ console.log(formatJson(callResult));
2424
+ } else {
2425
+ console.log(formatToolCall(callResult));
2426
+ }
2427
+ } catch (error) {
2428
+ console.error(formatError(`Failed to call tool: ${error.message}`));
2429
+ process.exit(1);
2319
2430
  }
2320
- return {
2321
- name: storage.activeSession,
2322
- config: storage.sessions[storage.activeSession]
2323
- };
2324
- }
2325
- async function getSession(name) {
2326
- const storage = await loadSessions();
2327
- return storage.sessions[name] || null;
2328
2431
  }
2329
- async function setActiveSession(name) {
2330
- const storage = await loadSessions();
2331
- if (!storage.sessions[name]) {
2332
- throw new Error(`Session '${name}' not found`);
2432
+ async function listResourcesCommand(options) {
2433
+ try {
2434
+ const result = await getOrRestoreSession(options.session || null);
2435
+ if (!result) return;
2436
+ const { session } = result;
2437
+ const resourcesResult = await session.listAllResources();
2438
+ const resources = resourcesResult.resources;
2439
+ if (options.json) {
2440
+ console.log(formatJson(resources));
2441
+ return;
2442
+ }
2443
+ if (resources.length === 0) {
2444
+ console.log(formatInfo("No resources available"));
2445
+ return;
2446
+ }
2447
+ console.log(formatHeader(`Available Resources (${resources.length}):`));
2448
+ console.log("");
2449
+ const tableData = resources.map((resource) => ({
2450
+ uri: resource.uri,
2451
+ name: resource.name || source_default.gray("(no name)"),
2452
+ type: resource.mimeType || source_default.gray("unknown")
2453
+ }));
2454
+ console.log(
2455
+ formatTable(tableData, [
2456
+ { key: "uri", header: "URI", width: 40 },
2457
+ { key: "name", header: "Name", width: 20 },
2458
+ { key: "type", header: "Type", width: 15 }
2459
+ ])
2460
+ );
2461
+ } catch (error) {
2462
+ console.error(formatError(`Failed to list resources: ${error.message}`));
2463
+ process.exit(1);
2333
2464
  }
2334
- storage.activeSession = name;
2335
- storage.sessions[name].lastUsed = (/* @__PURE__ */ new Date()).toISOString();
2336
- await saveSessions(storage);
2337
- }
2338
- async function listAllSessions() {
2339
- const storage = await loadSessions();
2340
- return Object.entries(storage.sessions).map(([name, config]) => ({
2341
- name,
2342
- config,
2343
- isActive: name === storage.activeSession
2344
- }));
2345
2465
  }
2346
- async function updateSessionInfo(name, serverInfo, capabilities) {
2347
- const storage = await loadSessions();
2348
- if (storage.sessions[name]) {
2349
- storage.sessions[name].serverInfo = serverInfo;
2350
- storage.sessions[name].capabilities = capabilities;
2351
- storage.sessions[name].lastUsed = (/* @__PURE__ */ new Date()).toISOString();
2352
- await saveSessions(storage);
2466
+ async function readResourceCommand(uri, options) {
2467
+ try {
2468
+ const result = await getOrRestoreSession(options.session || null);
2469
+ if (!result) return;
2470
+ const { session } = result;
2471
+ console.error(formatInfo(`Reading resource: ${uri}`));
2472
+ const resource = await session.readResource(uri);
2473
+ if (options.json) {
2474
+ console.log(formatJson(resource));
2475
+ } else {
2476
+ console.log(formatResourceContent(resource));
2477
+ }
2478
+ } catch (error) {
2479
+ console.error(formatError(`Failed to read resource: ${error.message}`));
2480
+ process.exit(1);
2353
2481
  }
2354
2482
  }
2355
-
2356
- // src/utils/format.ts
2357
- function formatTable(data, columns) {
2358
- if (data.length === 0) {
2359
- return source_default.gray("No items found");
2360
- }
2361
- const widths = columns.map((col) => {
2362
- const maxDataWidth = Math.max(
2363
- ...data.map((row) => String(row[col.key] || "").length)
2364
- );
2365
- const headerWidth = col.header.length;
2366
- return col.width || Math.max(maxDataWidth, headerWidth, 10);
2367
- });
2368
- const createRow = (values, bold = false) => {
2369
- const cells = values.map((val, i) => {
2370
- const padded = val.padEnd(widths[i]);
2371
- return bold ? source_default.bold(padded) : padded;
2483
+ async function subscribeResourceCommand(uri, options) {
2484
+ try {
2485
+ const result = await getOrRestoreSession(options.session || null);
2486
+ if (!result) return;
2487
+ const { session } = result;
2488
+ await session.subscribeToResource(uri);
2489
+ console.log(formatSuccess(`Subscribed to resource: ${uri}`));
2490
+ session.on("notification", async (notification) => {
2491
+ if (notification.method === "notifications/resources/updated") {
2492
+ console.log("");
2493
+ console.log(formatInfo("Resource updated:"));
2494
+ console.log(formatJson(notification.params));
2495
+ }
2372
2496
  });
2373
- return `\u2502 ${cells.join(" \u2502 ")} \u2502`;
2374
- };
2375
- const separator = (char) => {
2376
- const parts = widths.map((w) => char.repeat(w + 2));
2377
- if (char === "\u2500") {
2378
- return `\u251C${parts.join("\u253C")}\u2524`;
2379
- }
2380
- return `\u2514${parts.join("\u2534")}\u2518`;
2381
- };
2382
- const lines = [];
2383
- lines.push(`\u250C${widths.map((w) => "\u2500".repeat(w + 2)).join("\u252C")}\u2510`);
2384
- lines.push(
2385
- createRow(
2386
- columns.map((c) => c.header),
2387
- true
2388
- )
2389
- );
2390
- lines.push(separator("\u2500"));
2391
- data.forEach((row) => {
2392
- lines.push(createRow(columns.map((c) => String(row[c.key] || ""))));
2393
- });
2394
- lines.push(separator("\u2500"));
2395
- return lines.join("\n");
2396
- }
2397
- function formatJson(data, pretty = true) {
2398
- if (pretty) {
2399
- return JSON.stringify(data, null, 2);
2497
+ console.log(formatInfo("Listening for updates... (Press Ctrl+C to stop)"));
2498
+ await new Promise(() => {
2499
+ });
2500
+ } catch (error) {
2501
+ console.error(
2502
+ formatError(`Failed to subscribe to resource: ${error.message}`)
2503
+ );
2504
+ process.exit(1);
2400
2505
  }
2401
- return JSON.stringify(data);
2402
2506
  }
2403
- function formatToolCall(result) {
2404
- const lines = [];
2405
- if (result.isError) {
2406
- lines.push(source_default.red("\u2717 Tool execution failed"));
2407
- lines.push("");
2408
- } else {
2409
- lines.push(source_default.green("\u2713 Tool executed successfully"));
2410
- lines.push("");
2507
+ async function unsubscribeResourceCommand(uri, options) {
2508
+ try {
2509
+ const result = await getOrRestoreSession(options.session || null);
2510
+ if (!result) return;
2511
+ const { session } = result;
2512
+ await session.unsubscribeFromResource(uri);
2513
+ console.log(formatSuccess(`Unsubscribed from resource: ${uri}`));
2514
+ } catch (error) {
2515
+ console.error(
2516
+ formatError(`Failed to unsubscribe from resource: ${error.message}`)
2517
+ );
2518
+ process.exit(1);
2411
2519
  }
2412
- if (result.content && result.content.length > 0) {
2413
- result.content.forEach((item, index) => {
2414
- if (result.content.length > 1) {
2415
- lines.push(source_default.bold(`Content ${index + 1}:`));
2416
- }
2417
- if (item.type === "text") {
2418
- lines.push(item.text);
2419
- } else if (item.type === "image") {
2420
- lines.push(source_default.cyan(`[Image: ${item.mimeType || "unknown type"}]`));
2421
- if (item.data) {
2422
- lines.push(source_default.gray(`Data: ${item.data.substring(0, 50)}...`));
2423
- }
2424
- } else if (item.type === "resource") {
2425
- lines.push(source_default.cyan(`[Resource]`));
2426
- if (item.resource?.uri) {
2427
- lines.push(source_default.gray(`URI: ${item.resource.uri}`));
2428
- }
2429
- if (item.resource && "text" in item.resource && item.resource.text) {
2430
- lines.push(item.resource.text);
2431
- }
2432
- } else {
2433
- lines.push(source_default.gray(`[Unknown content type: ${item.type}]`));
2434
- }
2435
- if (index < result.content.length - 1) {
2436
- lines.push("");
2437
- }
2438
- });
2439
- }
2440
- return lines.join("\n");
2441
2520
  }
2442
- function formatResourceContent(content) {
2443
- if (!content || !content.contents) {
2444
- return source_default.gray("No content");
2445
- }
2446
- const lines = [];
2447
- content.contents.forEach((item, index) => {
2448
- if (content.contents.length > 1) {
2449
- lines.push(source_default.bold(`Content ${index + 1}:`));
2450
- }
2451
- if (item.uri) {
2452
- lines.push(source_default.gray(`URI: ${item.uri}`));
2453
- }
2454
- if (item.mimeType) {
2455
- lines.push(source_default.gray(`Type: ${item.mimeType}`));
2456
- }
2457
- if ("text" in item && item.text) {
2458
- lines.push("");
2459
- lines.push(item.text);
2460
- } else if ("blob" in item && item.blob) {
2461
- lines.push("");
2462
- lines.push(source_default.cyan(`[Binary data: ${item.blob.length} bytes]`));
2463
- }
2464
- if (index < content.contents.length - 1) {
2465
- lines.push("");
2466
- lines.push(source_default.gray("\u2500".repeat(50)));
2467
- lines.push("");
2521
+ async function listPromptsCommand(options) {
2522
+ try {
2523
+ const result = await getOrRestoreSession(options.session || null);
2524
+ if (!result) return;
2525
+ const { session } = result;
2526
+ const promptsResult = await session.listPrompts();
2527
+ const prompts = promptsResult.prompts;
2528
+ if (options.json) {
2529
+ console.log(formatJson(prompts));
2530
+ return;
2468
2531
  }
2469
- });
2470
- return lines.join("\n");
2471
- }
2472
- function formatSchema(schema, indent = 0) {
2473
- if (!schema) {
2474
- return source_default.gray("No schema");
2475
- }
2476
- const lines = [];
2477
- const pad = " ".repeat(indent);
2478
- if (schema.type === "object" && schema.properties) {
2479
- Object.entries(schema.properties).forEach(([key, value]) => {
2480
- const required = schema.required?.includes(key);
2481
- const type = value.type || "any";
2482
- const desc = value.description || "";
2483
- const keyStr = required ? source_default.bold(key) : key;
2484
- const typeStr = source_default.cyan(`(${type})`);
2485
- const requiredStr = required ? source_default.red(" *required") : "";
2486
- lines.push(`${pad}${keyStr} ${typeStr}${requiredStr}`);
2487
- if (desc) {
2488
- lines.push(`${pad} ${source_default.gray(desc)}`);
2489
- }
2490
- if (value.type === "object" && value.properties) {
2491
- lines.push(formatSchema(value, indent + 1));
2492
- }
2493
- if (value.type === "array" && value.items) {
2494
- lines.push(`${pad} ${source_default.gray("Items:")}`);
2495
- if (value.items.type === "object") {
2496
- lines.push(formatSchema(value.items, indent + 2));
2497
- } else {
2498
- lines.push(
2499
- `${pad} ${source_default.cyan(`(${value.items.type || "any"})`)}`
2500
- );
2501
- }
2502
- }
2503
- });
2504
- } else {
2505
- lines.push(`${pad}${source_default.cyan(`Type: ${schema.type || "any"}`)}`);
2506
- if (schema.description) {
2507
- lines.push(`${pad}${source_default.gray(schema.description)}`);
2532
+ if (prompts.length === 0) {
2533
+ console.log(formatInfo("No prompts available"));
2534
+ return;
2508
2535
  }
2536
+ console.log(formatHeader(`Available Prompts (${prompts.length}):`));
2537
+ console.log("");
2538
+ const tableData = prompts.map((prompt3) => ({
2539
+ name: source_default.bold(prompt3.name),
2540
+ description: prompt3.description || source_default.gray("No description")
2541
+ }));
2542
+ console.log(
2543
+ formatTable(tableData, [
2544
+ { key: "name", header: "Prompt", width: 25 },
2545
+ { key: "description", header: "Description", width: 50 }
2546
+ ])
2547
+ );
2548
+ } catch (error) {
2549
+ console.error(formatError(`Failed to list prompts: ${error.message}`));
2550
+ process.exit(1);
2509
2551
  }
2510
- return lines.join("\n");
2511
- }
2512
- function formatError(error) {
2513
- const message = typeof error === "string" ? error : error.message;
2514
- return source_default.red(`\u2717 Error: ${message}`);
2515
- }
2516
- function formatSuccess(message) {
2517
- return source_default.green(`\u2713 ${message}`);
2518
- }
2519
- function formatInfo(message) {
2520
- return source_default.cyan(message);
2521
- }
2522
- function formatWarning(message) {
2523
- return source_default.yellow(`\u26A0 ${message}`);
2524
- }
2525
- function formatHeader(text) {
2526
- return source_default.bold.white(text);
2527
- }
2528
- function formatKeyValue(pairs) {
2529
- const maxKeyLength = Math.max(...Object.keys(pairs).map((k) => k.length), 0);
2530
- return Object.entries(pairs).map(([key, value]) => {
2531
- const paddedKey = key.padEnd(maxKeyLength);
2532
- return ` ${source_default.gray(paddedKey)}: ${value}`;
2533
- }).join("\n");
2534
2552
  }
2535
- function formatPromptMessages(messages) {
2536
- if (!messages || messages.length === 0) {
2537
- return source_default.gray("No messages");
2538
- }
2539
- const lines = [];
2540
- messages.forEach((msg, index) => {
2541
- const role = msg.role || "unknown";
2542
- const roleStr = role === "user" ? source_default.blue("[User]") : role === "assistant" ? source_default.green("[Assistant]") : source_default.gray(`[${role}]`);
2543
- lines.push(`${roleStr}`);
2544
- if (msg.content) {
2545
- if (typeof msg.content === "string") {
2546
- lines.push(msg.content);
2547
- } else if (msg.content.type === "text") {
2548
- lines.push(msg.content.text);
2549
- } else if (msg.content.type === "image") {
2550
- lines.push(source_default.cyan(`[Image: ${msg.content.mimeType}]`));
2551
- } else if (msg.content.type === "resource") {
2552
- lines.push(source_default.cyan(`[Resource: ${msg.content.resource?.uri}]`));
2553
- if (msg.content.resource?.text) {
2554
- lines.push(msg.content.resource.text);
2555
- }
2553
+ async function getPromptCommand(promptName, argsJson, options) {
2554
+ try {
2555
+ const result = await getOrRestoreSession(options?.session || null);
2556
+ if (!result) return;
2557
+ const { session } = result;
2558
+ let args = {};
2559
+ if (argsJson) {
2560
+ try {
2561
+ args = JSON.parse(argsJson);
2562
+ } catch (error) {
2563
+ console.error(formatError("Invalid JSON arguments"));
2564
+ return;
2556
2565
  }
2557
2566
  }
2558
- if (index < messages.length - 1) {
2559
- lines.push("");
2560
- }
2561
- });
2562
- return lines.join("\n");
2563
- }
2564
-
2565
- // src/commands/client.ts
2566
- var activeSessions = /* @__PURE__ */ new Map();
2567
- async function getOrRestoreSession(sessionName) {
2568
- if (!sessionName) {
2569
- const active = await getActiveSession();
2570
- if (!active) {
2571
- console.error(
2572
- formatError("No active session. Connect to a server first.")
2573
- );
2574
- console.error(
2575
- formatInfo("Use: npx mcp-use client connect <url> --name <name>")
2576
- );
2577
- return null;
2578
- }
2579
- sessionName = active.name;
2580
- }
2581
- if (activeSessions.has(sessionName)) {
2582
- const { session } = activeSessions.get(sessionName);
2583
- return { name: sessionName, session };
2584
- }
2585
- const config = await getSession(sessionName);
2586
- if (!config) {
2587
- console.error(formatError(`Session '${sessionName}' not found`));
2588
- return null;
2589
- }
2590
- try {
2591
- const client = new import_client.MCPClient();
2592
- if (config.type === "http") {
2593
- client.addServer(sessionName, {
2594
- url: config.url,
2595
- headers: config.authToken ? { Authorization: `Bearer ${config.authToken}` } : void 0
2596
- });
2597
- } else if (config.type === "stdio") {
2598
- client.addServer(sessionName, {
2599
- command: config.command,
2600
- args: config.args || [],
2601
- env: config.env
2602
- });
2567
+ console.error(formatInfo(`Getting prompt '${promptName}'...`));
2568
+ const prompt3 = await session.getPrompt(promptName, args);
2569
+ if (options?.json) {
2570
+ console.log(formatJson(prompt3));
2603
2571
  } else {
2604
- console.error(formatError(`Unknown session type: ${config.type}`));
2605
- return null;
2572
+ console.log(formatHeader(`Prompt: ${promptName}`));
2573
+ console.log("");
2574
+ if (prompt3.description) {
2575
+ console.log(prompt3.description);
2576
+ console.log("");
2577
+ }
2578
+ if (prompt3.messages) {
2579
+ console.log(formatHeader("Messages:"));
2580
+ console.log("");
2581
+ console.log(formatPromptMessages(prompt3.messages));
2582
+ }
2606
2583
  }
2607
- const session = await client.createSession(sessionName);
2608
- activeSessions.set(sessionName, { client, session });
2609
- console.error(formatInfo(`Reconnected to session '${sessionName}'`));
2610
- return { name: sessionName, session };
2611
2584
  } catch (error) {
2612
- console.error(formatError(`Failed to restore session: ${error.message}`));
2613
- return null;
2585
+ console.error(formatError(`Failed to get prompt: ${error.message}`));
2586
+ process.exit(1);
2614
2587
  }
2615
2588
  }
2616
- async function connectCommand(urlOrCommand, options) {
2589
+ async function interactiveCommand(options) {
2617
2590
  try {
2618
- const sessionName = options.name || `session-${Date.now()}`;
2619
- const client = new import_client.MCPClient();
2620
- let session;
2621
- if (options.stdio) {
2622
- const parts = urlOrCommand.split(" ");
2623
- const command = parts[0];
2624
- const args = parts.slice(1);
2625
- console.error(
2626
- formatInfo(`Connecting to stdio server: ${command} ${args.join(" ")}`)
2591
+ const result = await getOrRestoreSession(options.session || null);
2592
+ if (!result) return;
2593
+ const { name: sessionName, session } = result;
2594
+ console.log(formatHeader("MCP Interactive Mode"));
2595
+ console.log("");
2596
+ console.log(formatInfo(`Connected to: ${sessionName}`));
2597
+ console.log("");
2598
+ console.log(source_default.gray("Commands:"));
2599
+ console.log(source_default.gray(" tools list - List available tools"));
2600
+ console.log(
2601
+ source_default.gray(
2602
+ " tools call <name> - Call a tool (will prompt for args)"
2603
+ )
2604
+ );
2605
+ console.log(source_default.gray(" tools describe <name> - Show tool details"));
2606
+ console.log(
2607
+ source_default.gray(" resources list - List available resources")
2608
+ );
2609
+ console.log(source_default.gray(" resources read <uri> - Read a resource"));
2610
+ console.log(
2611
+ source_default.gray(" prompts list - List available prompts")
2612
+ );
2613
+ console.log(source_default.gray(" prompts get <name> - Get a prompt"));
2614
+ console.log(source_default.gray(" sessions list - List all sessions"));
2615
+ console.log(
2616
+ source_default.gray(" sessions switch <name> - Switch to another session")
2617
+ );
2618
+ console.log(
2619
+ source_default.gray(" exit, quit - Exit interactive mode")
2620
+ );
2621
+ console.log("");
2622
+ const rl = (0, import_node_readline.createInterface)({
2623
+ input: process.stdin,
2624
+ output: process.stdout,
2625
+ prompt: source_default.cyan("mcp> ")
2626
+ });
2627
+ rl.prompt();
2628
+ rl.on("line", async (line) => {
2629
+ const trimmed = line.trim();
2630
+ if (!trimmed) {
2631
+ rl.prompt();
2632
+ return;
2633
+ }
2634
+ if (trimmed === "exit" || trimmed === "quit") {
2635
+ console.log(formatInfo("Goodbye!"));
2636
+ rl.close();
2637
+ process.exit(0);
2638
+ }
2639
+ const parts = trimmed.split(" ");
2640
+ const scope = parts[0];
2641
+ const command = parts[1];
2642
+ const arg = parts[2];
2643
+ try {
2644
+ if (scope === "tools") {
2645
+ if (command === "list") {
2646
+ const tools = await session.listTools();
2647
+ console.log(
2648
+ formatInfo(
2649
+ `Available tools: ${tools.map((t) => t.name).join(", ")}`
2650
+ )
2651
+ );
2652
+ } else if (command === "call" && arg) {
2653
+ rl.question(
2654
+ "Arguments (JSON, or press Enter for none): ",
2655
+ async (argsInput) => {
2656
+ try {
2657
+ const args = argsInput.trim() ? JSON.parse(argsInput) : {};
2658
+ const result2 = await session.callTool(arg, args);
2659
+ console.log(formatToolCall(result2));
2660
+ } catch (error) {
2661
+ console.error(formatError(error.message));
2662
+ }
2663
+ rl.prompt();
2664
+ }
2665
+ );
2666
+ return;
2667
+ } else if (command === "describe" && arg) {
2668
+ const tools = session.tools;
2669
+ const tool = tools.find((t) => t.name === arg);
2670
+ if (tool) {
2671
+ console.log(formatHeader(`Tool: ${tool.name}`));
2672
+ if (tool.description) console.log(tool.description);
2673
+ if (tool.inputSchema) {
2674
+ console.log("");
2675
+ console.log(formatSchema(tool.inputSchema));
2676
+ }
2677
+ } else {
2678
+ console.error(formatError(`Tool '${arg}' not found`));
2679
+ }
2680
+ } else {
2681
+ console.error(
2682
+ formatError(
2683
+ "Invalid command. Try: tools list, tools call <name>, tools describe <name>"
2684
+ )
2685
+ );
2686
+ }
2687
+ } else if (scope === "resources") {
2688
+ if (command === "list") {
2689
+ const result2 = await session.listAllResources();
2690
+ const resources = result2.resources;
2691
+ console.log(
2692
+ formatInfo(
2693
+ `Available resources: ${resources.map((r) => r.uri).join(", ")}`
2694
+ )
2695
+ );
2696
+ } else if (command === "read" && arg) {
2697
+ const resource = await session.readResource(arg);
2698
+ console.log(formatResourceContent(resource));
2699
+ } else {
2700
+ console.error(
2701
+ formatError(
2702
+ "Invalid command. Try: resources list, resources read <uri>"
2703
+ )
2704
+ );
2705
+ }
2706
+ } else if (scope === "prompts") {
2707
+ if (command === "list") {
2708
+ const result2 = await session.listPrompts();
2709
+ const prompts = result2.prompts;
2710
+ console.log(
2711
+ formatInfo(
2712
+ `Available prompts: ${prompts.map((p) => p.name).join(", ")}`
2713
+ )
2714
+ );
2715
+ } else if (command === "get" && arg) {
2716
+ rl.question(
2717
+ "Arguments (JSON, or press Enter for none): ",
2718
+ async (argsInput) => {
2719
+ try {
2720
+ const args = argsInput.trim() ? JSON.parse(argsInput) : {};
2721
+ const prompt3 = await session.getPrompt(arg, args);
2722
+ console.log(formatPromptMessages(prompt3.messages));
2723
+ } catch (error) {
2724
+ console.error(formatError(error.message));
2725
+ }
2726
+ rl.prompt();
2727
+ }
2728
+ );
2729
+ return;
2730
+ } else {
2731
+ console.error(
2732
+ formatError(
2733
+ "Invalid command. Try: prompts list, prompts get <name>"
2734
+ )
2735
+ );
2736
+ }
2737
+ } else if (scope === "sessions") {
2738
+ if (command === "list") {
2739
+ await listSessionsCommand();
2740
+ } else if (command === "switch" && arg) {
2741
+ console.log(
2742
+ formatWarning(
2743
+ "Session switching in interactive mode will be available in a future version"
2744
+ )
2745
+ );
2746
+ } else {
2747
+ console.error(formatError("Invalid command. Try: sessions list"));
2748
+ }
2749
+ } else {
2750
+ console.error(
2751
+ formatError(
2752
+ "Unknown command. Type a valid scope: tools, resources, prompts, sessions"
2753
+ )
2754
+ );
2755
+ }
2756
+ } catch (error) {
2757
+ console.error(formatError(error.message));
2758
+ }
2759
+ rl.prompt();
2760
+ });
2761
+ rl.on("close", () => {
2762
+ console.log("");
2763
+ console.log(formatInfo("Goodbye!"));
2764
+ process.exit(0);
2765
+ });
2766
+ } catch (error) {
2767
+ console.error(
2768
+ formatError(`Failed to start interactive mode: ${error.message}`)
2769
+ );
2770
+ process.exit(1);
2771
+ }
2772
+ }
2773
+ function createClientCommand() {
2774
+ const clientCommand = new import_commander.Command("client").description(
2775
+ "Interactive MCP client for terminal usage"
2776
+ );
2777
+ 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);
2778
+ clientCommand.command("disconnect [session]").description("Disconnect from a session").option("--all", "Disconnect all sessions").action(disconnectCommand);
2779
+ const sessionsCommand = new import_commander.Command("sessions").description(
2780
+ "Manage CLI sessions"
2781
+ );
2782
+ sessionsCommand.command("list").description("List all saved sessions").action(listSessionsCommand);
2783
+ sessionsCommand.command("switch <name>").description("Switch to a different session").action(switchSessionCommand);
2784
+ clientCommand.addCommand(sessionsCommand);
2785
+ const toolsCommand = new import_commander.Command("tools").description(
2786
+ "Interact with MCP tools"
2787
+ );
2788
+ toolsCommand.command("list").description("List available tools").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(listToolsCommand);
2789
+ 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);
2790
+ toolsCommand.command("describe <name>").description("Show tool details and schema").option("--session <name>", "Use specific session").action(describeToolCommand);
2791
+ clientCommand.addCommand(toolsCommand);
2792
+ const resourcesCommand = new import_commander.Command("resources").description(
2793
+ "Interact with MCP resources"
2794
+ );
2795
+ resourcesCommand.command("list").description("List available resources").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(listResourcesCommand);
2796
+ resourcesCommand.command("read <uri>").description("Read a resource by URI").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(readResourceCommand);
2797
+ resourcesCommand.command("subscribe <uri>").description("Subscribe to resource updates").option("--session <name>", "Use specific session").action(subscribeResourceCommand);
2798
+ resourcesCommand.command("unsubscribe <uri>").description("Unsubscribe from resource updates").option("--session <name>", "Use specific session").action(unsubscribeResourceCommand);
2799
+ clientCommand.addCommand(resourcesCommand);
2800
+ const promptsCommand = new import_commander.Command("prompts").description(
2801
+ "Interact with MCP prompts"
2802
+ );
2803
+ promptsCommand.command("list").description("List available prompts").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(listPromptsCommand);
2804
+ 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);
2805
+ clientCommand.addCommand(promptsCommand);
2806
+ clientCommand.command("interactive").description("Start interactive REPL mode").option("--session <name>", "Use specific session").action(interactiveCommand);
2807
+ return clientCommand;
2808
+ }
2809
+
2810
+ // src/commands/deploy.ts
2811
+ var import_node_child_process9 = require("child_process");
2812
+ var import_node_fs7 = require("fs");
2813
+ var import_node_os5 = __toESM(require("os"), 1);
2814
+ var import_node_path5 = __toESM(require("path"), 1);
2815
+ var import_node_util8 = require("util");
2816
+
2817
+ // src/utils/git.ts
2818
+ var import_node_child_process8 = require("child_process");
2819
+ var import_node_util7 = require("util");
2820
+ var execAsync = (0, import_node_util7.promisify)(import_node_child_process8.exec);
2821
+ async function gitCommand(command, cwd = process.cwd()) {
2822
+ try {
2823
+ const { stdout } = await execAsync(command, { cwd });
2824
+ return stdout.trim();
2825
+ } catch (error) {
2826
+ return null;
2827
+ }
2828
+ }
2829
+ async function isGitRepo(cwd = process.cwd()) {
2830
+ const result = await gitCommand("git rev-parse --is-inside-work-tree", cwd);
2831
+ return result === "true";
2832
+ }
2833
+ async function getRemoteUrl(cwd = process.cwd()) {
2834
+ return gitCommand("git config --get remote.origin.url", cwd);
2835
+ }
2836
+ function parseGitHubUrl(url) {
2837
+ const sshMatch = url.match(/git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/);
2838
+ const httpsMatch = url.match(
2839
+ /https:\/\/github\.com\/([^/]+)\/(.+?)(?:\.git)?$/
2840
+ );
2841
+ const match = sshMatch || httpsMatch;
2842
+ if (!match) return null;
2843
+ return {
2844
+ owner: match[1],
2845
+ repo: match[2]
2846
+ };
2847
+ }
2848
+ async function getCurrentBranch(cwd = process.cwd()) {
2849
+ return gitCommand("git rev-parse --abbrev-ref HEAD", cwd);
2850
+ }
2851
+ async function getCommitSha(cwd = process.cwd()) {
2852
+ return gitCommand("git rev-parse HEAD", cwd);
2853
+ }
2854
+ async function getCommitMessage(cwd = process.cwd()) {
2855
+ return gitCommand("git log -1 --pretty=%B", cwd);
2856
+ }
2857
+ async function getGitInfo(cwd = process.cwd()) {
2858
+ const isRepo = await isGitRepo(cwd);
2859
+ if (!isRepo) {
2860
+ return { isGitRepo: false };
2861
+ }
2862
+ const remoteUrl = await getRemoteUrl(cwd);
2863
+ const branch = await getCurrentBranch(cwd);
2864
+ const commitSha = await getCommitSha(cwd);
2865
+ const commitMessage = await getCommitMessage(cwd);
2866
+ let owner;
2867
+ let repo;
2868
+ if (remoteUrl) {
2869
+ const parsed = parseGitHubUrl(remoteUrl);
2870
+ if (parsed) {
2871
+ owner = parsed.owner;
2872
+ repo = parsed.repo;
2873
+ }
2874
+ }
2875
+ return {
2876
+ isGitRepo: true,
2877
+ remoteUrl: remoteUrl || void 0,
2878
+ owner,
2879
+ repo,
2880
+ branch: branch || void 0,
2881
+ commitSha: commitSha || void 0,
2882
+ commitMessage: commitMessage || void 0
2883
+ };
2884
+ }
2885
+ function isGitHubUrl(url) {
2886
+ try {
2887
+ const parsedUrl = new URL(url);
2888
+ return parsedUrl.hostname === "github.com" || parsedUrl.hostname === "www.github.com";
2889
+ } catch {
2890
+ const sshMatch = url.match(/^git@([^:/]+)[:/]/);
2891
+ if (sshMatch) {
2892
+ const host = sshMatch[1];
2893
+ return host === "github.com" || host === "www.github.com";
2894
+ }
2895
+ }
2896
+ return false;
2897
+ }
2898
+
2899
+ // src/utils/project-link.ts
2900
+ var import_node_fs6 = require("fs");
2901
+ var import_node_path4 = __toESM(require("path"), 1);
2902
+ var MCP_USE_DIR = ".mcp-use";
2903
+ var MCP_USE_DIR_PROJECT = "project.json";
2904
+ function getMcpUseDirectory(cwd) {
2905
+ return import_node_path4.default.join(cwd, MCP_USE_DIR);
2906
+ }
2907
+ async function getProjectLink(cwd) {
2908
+ try {
2909
+ const linkPath = import_node_path4.default.join(getMcpUseDirectory(cwd), MCP_USE_DIR_PROJECT);
2910
+ const content = await import_node_fs6.promises.readFile(linkPath, "utf-8");
2911
+ return JSON.parse(content);
2912
+ } catch (err) {
2913
+ if (err.code === "ENOENT") return null;
2914
+ throw err;
2915
+ }
2916
+ }
2917
+ async function saveProjectLink(cwd, link) {
2918
+ const mcpUseDir = getMcpUseDirectory(cwd);
2919
+ await import_node_fs6.promises.mkdir(mcpUseDir, { recursive: true });
2920
+ const linkPath = import_node_path4.default.join(mcpUseDir, MCP_USE_DIR_PROJECT);
2921
+ await import_node_fs6.promises.writeFile(linkPath, JSON.stringify(link, null, 2), "utf-8");
2922
+ await addToGitIgnore(cwd);
2923
+ }
2924
+ async function addToGitIgnore(cwd) {
2925
+ const gitignorePath = import_node_path4.default.join(cwd, ".gitignore");
2926
+ try {
2927
+ let content = "";
2928
+ try {
2929
+ content = await import_node_fs6.promises.readFile(gitignorePath, "utf-8");
2930
+ } catch (err) {
2931
+ if (err.code !== "ENOENT") throw err;
2932
+ }
2933
+ if (!content.includes(MCP_USE_DIR)) {
2934
+ const newContent = content + (content.endsWith("\n") ? "" : "\n") + `
2935
+ # mcp-use deployment
2936
+ ${MCP_USE_DIR}
2937
+ `;
2938
+ await import_node_fs6.promises.writeFile(gitignorePath, newContent, "utf-8");
2939
+ }
2940
+ } catch (err) {
2941
+ }
2942
+ }
2943
+
2944
+ // src/commands/deploy.ts
2945
+ var execAsync2 = (0, import_node_util8.promisify)(import_node_child_process9.exec);
2946
+ async function parseEnvFile(filePath) {
2947
+ try {
2948
+ const content = await import_node_fs7.promises.readFile(filePath, "utf-8");
2949
+ const envVars = {};
2950
+ const lines = content.split("\n");
2951
+ let currentKey = null;
2952
+ let currentValue = "";
2953
+ for (let line of lines) {
2954
+ line = line.trim();
2955
+ if (!line || line.startsWith("#")) {
2956
+ continue;
2957
+ }
2958
+ if (currentKey && !line.includes("=")) {
2959
+ currentValue += "\n" + line;
2960
+ continue;
2961
+ }
2962
+ if (currentKey) {
2963
+ envVars[currentKey] = currentValue.replace(/^["']|["']$/g, "");
2964
+ currentKey = null;
2965
+ currentValue = "";
2966
+ }
2967
+ const equalIndex = line.indexOf("=");
2968
+ if (equalIndex === -1) {
2969
+ continue;
2970
+ }
2971
+ const key = line.substring(0, equalIndex).trim();
2972
+ let value = line.substring(equalIndex + 1).trim();
2973
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
2974
+ console.log(
2975
+ source_default.yellow(`\u26A0\uFE0F Skipping invalid environment variable key: ${key}`)
2976
+ );
2977
+ continue;
2978
+ }
2979
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
2980
+ value = value.slice(1, -1);
2981
+ envVars[key] = value;
2982
+ } else if (value.startsWith('"') || value.startsWith("'")) {
2983
+ currentKey = key;
2984
+ currentValue = value.slice(1);
2985
+ } else {
2986
+ envVars[key] = value;
2987
+ }
2988
+ }
2989
+ if (currentKey) {
2990
+ envVars[currentKey] = currentValue.replace(/^["']|["']$/g, "");
2991
+ }
2992
+ return envVars;
2993
+ } catch (error) {
2994
+ if (error.code === "ENOENT") {
2995
+ throw new Error(`Environment file not found: ${filePath}`);
2996
+ }
2997
+ throw new Error(
2998
+ `Failed to parse environment file: ${error instanceof Error ? error.message : "Unknown error"}`
2999
+ );
3000
+ }
3001
+ }
3002
+ function parseEnvVar(envStr) {
3003
+ const equalIndex = envStr.indexOf("=");
3004
+ if (equalIndex === -1) {
3005
+ throw new Error(
3006
+ `Invalid environment variable format: "${envStr}". Expected KEY=VALUE`
3007
+ );
3008
+ }
3009
+ const key = envStr.substring(0, equalIndex).trim();
3010
+ const value = envStr.substring(equalIndex + 1);
3011
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key)) {
3012
+ throw new Error(
3013
+ `Invalid environment variable key: "${key}". Keys must start with a letter or underscore and contain only letters, numbers, and underscores.`
3014
+ );
3015
+ }
3016
+ return { key, value };
3017
+ }
3018
+ async function buildEnvVars(options) {
3019
+ const envVars = {};
3020
+ if (options.envFile) {
3021
+ try {
3022
+ const fileEnv = await parseEnvFile(options.envFile);
3023
+ Object.assign(envVars, fileEnv);
3024
+ console.log(
3025
+ source_default.gray(
3026
+ `Loaded ${Object.keys(fileEnv).length} variable(s) from ${options.envFile}`
3027
+ )
3028
+ );
3029
+ } catch (error) {
3030
+ console.log(
3031
+ source_default.red(
3032
+ `\u2717 ${error instanceof Error ? error.message : "Failed to load env file"}`
3033
+ )
3034
+ );
3035
+ process.exit(1);
3036
+ }
3037
+ }
3038
+ if (options.env && options.env.length > 0) {
3039
+ for (const envStr of options.env) {
3040
+ try {
3041
+ const { key, value } = parseEnvVar(envStr);
3042
+ envVars[key] = value;
3043
+ } catch (error) {
3044
+ console.log(
3045
+ source_default.red(
3046
+ `\u2717 ${error instanceof Error ? error.message : "Invalid env variable"}`
3047
+ )
3048
+ );
3049
+ process.exit(1);
3050
+ }
3051
+ }
3052
+ }
3053
+ return envVars;
3054
+ }
3055
+ async function isMcpProject(cwd = process.cwd()) {
3056
+ try {
3057
+ const packageJsonPath = import_node_path5.default.join(cwd, "package.json");
3058
+ const content = await import_node_fs7.promises.readFile(packageJsonPath, "utf-8");
3059
+ const packageJson2 = JSON.parse(content);
3060
+ const hasMcpDeps = packageJson2.dependencies?.["mcp-use"] || packageJson2.dependencies?.["@modelcontextprotocol/sdk"] || packageJson2.devDependencies?.["mcp-use"] || packageJson2.devDependencies?.["@modelcontextprotocol/sdk"];
3061
+ const hasMcpScripts = packageJson2.scripts?.mcp || packageJson2.scripts?.["mcp:dev"];
3062
+ return !!(hasMcpDeps || hasMcpScripts);
3063
+ } catch {
3064
+ return false;
3065
+ }
3066
+ }
3067
+ async function getProjectName(cwd = process.cwd()) {
3068
+ try {
3069
+ const packageJsonPath = import_node_path5.default.join(cwd, "package.json");
3070
+ const content = await import_node_fs7.promises.readFile(packageJsonPath, "utf-8");
3071
+ const packageJson2 = JSON.parse(content);
3072
+ if (packageJson2.name) {
3073
+ return packageJson2.name;
3074
+ }
3075
+ } catch {
3076
+ }
3077
+ return import_node_path5.default.basename(cwd);
3078
+ }
3079
+ async function detectBuildCommand(cwd = process.cwd()) {
3080
+ try {
3081
+ const packageJsonPath = import_node_path5.default.join(cwd, "package.json");
3082
+ const content = await import_node_fs7.promises.readFile(packageJsonPath, "utf-8");
3083
+ const packageJson2 = JSON.parse(content);
3084
+ if (packageJson2.scripts?.build) {
3085
+ return "npm run build";
3086
+ }
3087
+ } catch {
3088
+ }
3089
+ return void 0;
3090
+ }
3091
+ async function detectStartCommand(cwd = process.cwd()) {
3092
+ try {
3093
+ const packageJsonPath = import_node_path5.default.join(cwd, "package.json");
3094
+ const content = await import_node_fs7.promises.readFile(packageJsonPath, "utf-8");
3095
+ const packageJson2 = JSON.parse(content);
3096
+ if (packageJson2.scripts?.start) {
3097
+ return "npm start";
3098
+ }
3099
+ if (packageJson2.main) {
3100
+ return `node ${packageJson2.main}`;
3101
+ }
3102
+ } catch {
3103
+ }
3104
+ return void 0;
3105
+ }
3106
+ async function detectRuntime(cwd = process.cwd()) {
3107
+ try {
3108
+ const pythonFiles = ["requirements.txt", "pyproject.toml", "setup.py"];
3109
+ for (const file of pythonFiles) {
3110
+ try {
3111
+ await import_node_fs7.promises.access(import_node_path5.default.join(cwd, file));
3112
+ return "python";
3113
+ } catch {
3114
+ continue;
3115
+ }
3116
+ }
3117
+ try {
3118
+ await import_node_fs7.promises.access(import_node_path5.default.join(cwd, "package.json"));
3119
+ return "node";
3120
+ } catch {
3121
+ }
3122
+ } catch {
3123
+ }
3124
+ return "node";
3125
+ }
3126
+ async function prompt(question, defaultValue = "n") {
3127
+ const readline = await import("readline");
3128
+ const rl = readline.createInterface({
3129
+ input: process.stdin,
3130
+ output: process.stdout
3131
+ });
3132
+ const defaultIndicator = defaultValue === "y" ? "Y/n" : "y/N";
3133
+ const questionWithDefault = question.replace(
3134
+ /(\(y\/n\):)/,
3135
+ `(${defaultIndicator}):`
3136
+ );
3137
+ return new Promise((resolve) => {
3138
+ rl.question(questionWithDefault, (answer) => {
3139
+ rl.close();
3140
+ const trimmedAnswer = answer.trim().toLowerCase();
3141
+ if (trimmedAnswer === "") {
3142
+ resolve(defaultValue === "y");
3143
+ } else {
3144
+ resolve(trimmedAnswer === "y" || trimmedAnswer === "yes");
3145
+ }
3146
+ });
3147
+ });
3148
+ }
3149
+ async function createTarball(cwd) {
3150
+ const tmpDir = import_node_os5.default.tmpdir();
3151
+ const tarballPath = import_node_path5.default.join(tmpDir, `mcp-deploy-${Date.now()}.tar.gz`);
3152
+ const excludePatterns = [
3153
+ "node_modules",
3154
+ ".git",
3155
+ "dist",
3156
+ "build",
3157
+ ".next",
3158
+ ".venv",
3159
+ "__pycache__",
3160
+ "*.pyc",
3161
+ ".DS_Store",
3162
+ "._*",
3163
+ // macOS resource fork files
3164
+ ".mcp-use",
3165
+ // Build artifacts directory
3166
+ ".env",
3167
+ ".env.local",
3168
+ "*.log"
3169
+ ];
3170
+ const excludeFlags = excludePatterns.map((pattern) => `--exclude=${pattern}`).join(" ");
3171
+ const command = `tar ${excludeFlags} -czf "${tarballPath}" -C "${cwd}" . 2>&1 || true`;
3172
+ try {
3173
+ await execAsync2(command);
3174
+ return tarballPath;
3175
+ } catch (error) {
3176
+ throw new Error(
3177
+ `Failed to create tarball: ${error instanceof Error ? error.message : "Unknown error"}`
3178
+ );
3179
+ }
3180
+ }
3181
+ function formatFileSize(bytes) {
3182
+ if (bytes === 0) return "0 B";
3183
+ const k = 1024;
3184
+ const sizes = ["B", "KB", "MB", "GB"];
3185
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
3186
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
3187
+ }
3188
+ async function displayDeploymentProgress(api, deployment) {
3189
+ const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
3190
+ let frameIndex = 0;
3191
+ let spinnerInterval = null;
3192
+ let lastStep = "";
3193
+ const startSpinner = (message) => {
3194
+ if (spinnerInterval) {
3195
+ clearInterval(spinnerInterval);
3196
+ }
3197
+ process.stdout.write("\r\x1B[K");
3198
+ spinnerInterval = setInterval(() => {
3199
+ const frame = frames[frameIndex];
3200
+ frameIndex = (frameIndex + 1) % frames.length;
3201
+ process.stdout.write(
3202
+ "\r" + source_default.cyan(frame) + " " + source_default.gray(message)
3203
+ );
3204
+ }, 80);
3205
+ };
3206
+ const stopSpinner = () => {
3207
+ if (spinnerInterval) {
3208
+ clearInterval(spinnerInterval);
3209
+ spinnerInterval = null;
3210
+ process.stdout.write("\r\x1B[K");
3211
+ }
3212
+ };
3213
+ console.log();
3214
+ startSpinner("Deploying...");
3215
+ try {
3216
+ for await (const log of api.streamDeploymentLogs(deployment.id)) {
3217
+ try {
3218
+ const logData = JSON.parse(log);
3219
+ if (logData.step && logData.step !== lastStep) {
3220
+ lastStep = logData.step;
3221
+ const stepMessages = {
3222
+ clone: "Preparing source code...",
3223
+ analyze: "Analyzing project...",
3224
+ build: "Building container image...",
3225
+ deploy: "Deploying to cloud..."
3226
+ };
3227
+ const message = stepMessages[logData.step] || "Deploying...";
3228
+ startSpinner(message);
3229
+ }
3230
+ if (logData.line) {
3231
+ stopSpinner();
3232
+ const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
3233
+ const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
3234
+ console.log(stepPrefix + levelColor(logData.line));
3235
+ }
3236
+ } catch {
3237
+ }
3238
+ }
3239
+ } catch (error) {
3240
+ stopSpinner();
3241
+ }
3242
+ let checkCount = 0;
3243
+ const maxChecks = 60;
3244
+ let delay = 3e3;
3245
+ const maxDelay = 1e4;
3246
+ let lastDisplayedLogLength = 0;
3247
+ while (checkCount < maxChecks) {
3248
+ const currentDelay = delay;
3249
+ await new Promise((resolve) => setTimeout(resolve, currentDelay));
3250
+ const finalDeployment = await api.getDeployment(deployment.id);
3251
+ if (finalDeployment.buildLogs && finalDeployment.buildLogs.length > lastDisplayedLogLength) {
3252
+ const newLogs = finalDeployment.buildLogs.substring(
3253
+ lastDisplayedLogLength
3254
+ );
3255
+ const logLines = newLogs.split("\n").filter((l) => l.trim());
3256
+ for (const line of logLines) {
3257
+ try {
3258
+ const logData = JSON.parse(line);
3259
+ if (logData.line) {
3260
+ stopSpinner();
3261
+ const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
3262
+ const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
3263
+ console.log(stepPrefix + levelColor(logData.line));
3264
+ }
3265
+ } catch {
3266
+ }
3267
+ }
3268
+ lastDisplayedLogLength = finalDeployment.buildLogs.length;
3269
+ }
3270
+ if (finalDeployment.status === "running") {
3271
+ const mcpUrl = `https://${finalDeployment.domain}/mcp`;
3272
+ const inspectorUrl = `https://inspector.mcp-use.com/inspector?autoConnect=${encodeURIComponent(mcpUrl)}`;
3273
+ console.log(source_default.green.bold("\u2713 Deployment successful!\n"));
3274
+ console.log(source_default.white("\u{1F310} MCP Server URL:"));
3275
+ console.log(source_default.cyan.bold(` ${mcpUrl}
3276
+ `));
3277
+ console.log(source_default.white("\u{1F50D} Inspector URL:"));
3278
+ console.log(source_default.cyan.bold(` ${inspectorUrl}
3279
+ `));
3280
+ if (finalDeployment.customDomain) {
3281
+ const customMcpUrl = `https://${finalDeployment.customDomain}/mcp`;
3282
+ const customInspectorUrl = `https://inspector.mcp-use.com/inspect?autoConnect=${encodeURIComponent(customMcpUrl)}`;
3283
+ console.log(source_default.white("\u{1F517} Custom Domain:"));
3284
+ console.log(source_default.cyan.bold(` ${customMcpUrl}
3285
+ `));
3286
+ console.log(source_default.white("\u{1F50D} Custom Inspector:"));
3287
+ console.log(source_default.cyan.bold(` ${customInspectorUrl}
3288
+ `));
3289
+ }
3290
+ console.log(
3291
+ source_default.gray("Deployment ID: ") + source_default.white(finalDeployment.id)
3292
+ );
3293
+ return;
3294
+ } else if (finalDeployment.status === "failed") {
3295
+ console.log(source_default.red.bold("\u2717 Deployment failed\n"));
3296
+ if (finalDeployment.error) {
3297
+ console.log(source_default.red("Error: ") + finalDeployment.error);
3298
+ }
3299
+ if (finalDeployment.buildLogs) {
3300
+ console.log(source_default.gray("\nBuild logs:"));
3301
+ try {
3302
+ const logs = finalDeployment.buildLogs.split("\n").filter((l) => l.trim());
3303
+ for (const log of logs) {
3304
+ try {
3305
+ const logData = JSON.parse(log);
3306
+ if (logData.line) {
3307
+ console.log(source_default.gray(` ${logData.line}`));
3308
+ }
3309
+ } catch {
3310
+ console.log(source_default.gray(` ${log}`));
3311
+ }
3312
+ }
3313
+ } catch {
3314
+ console.log(source_default.gray(finalDeployment.buildLogs));
3315
+ }
3316
+ }
3317
+ process.exit(1);
3318
+ } else if (finalDeployment.status === "building") {
3319
+ startSpinner("Building and deploying...");
3320
+ checkCount++;
3321
+ delay = Math.min(delay * 1.2, maxDelay);
3322
+ } else {
3323
+ console.log(
3324
+ source_default.yellow("\u26A0\uFE0F Deployment status: ") + finalDeployment.status
3325
+ );
3326
+ return;
3327
+ }
3328
+ }
3329
+ stopSpinner();
3330
+ console.log(source_default.yellow("\u26A0\uFE0F Deployment is taking longer than expected."));
3331
+ console.log(
3332
+ source_default.gray("Check status with: ") + source_default.white(`mcp-use status ${deployment.id}`)
3333
+ );
3334
+ }
3335
+ async function deployCommand(options) {
3336
+ try {
3337
+ const cwd = process.cwd();
3338
+ if (!await isLoggedIn()) {
3339
+ console.log(source_default.red("\u2717 You are not logged in."));
3340
+ console.log(
3341
+ source_default.gray("Run " + source_default.white("mcp-use login") + " to get started.")
3342
+ );
3343
+ process.exit(1);
3344
+ }
3345
+ console.log(source_default.cyan.bold("\u{1F680} Deploying to mcp-use cloud...\n"));
3346
+ const isMcp = await isMcpProject(cwd);
3347
+ if (!isMcp) {
3348
+ console.log(
3349
+ source_default.yellow(
3350
+ "\u26A0\uFE0F This doesn't appear to be an MCP server project (no mcp-use or @modelcontextprotocol/sdk dependency found)."
3351
+ )
3352
+ );
3353
+ const shouldContinue = await prompt(
3354
+ source_default.white("Continue anyway? (y/n): ")
3355
+ );
3356
+ if (!shouldContinue) {
3357
+ console.log(source_default.gray("Deployment cancelled."));
3358
+ process.exit(0);
3359
+ }
3360
+ console.log();
3361
+ }
3362
+ const gitInfo = await getGitInfo(cwd);
3363
+ if (!options.fromSource && gitInfo.isGitRepo && gitInfo.remoteUrl && isGitHubUrl(gitInfo.remoteUrl)) {
3364
+ if (!gitInfo.owner || !gitInfo.repo) {
3365
+ console.log(
3366
+ source_default.red(
3367
+ "\u2717 Could not parse GitHub repository information from remote URL."
3368
+ )
3369
+ );
3370
+ process.exit(1);
3371
+ }
3372
+ console.log(source_default.white("GitHub repository detected:"));
3373
+ console.log(
3374
+ source_default.gray(` Repository: `) + source_default.cyan(`${gitInfo.owner}/${gitInfo.repo}`)
3375
+ );
3376
+ console.log(
3377
+ source_default.gray(` Branch: `) + source_default.cyan(gitInfo.branch || "main")
3378
+ );
3379
+ if (gitInfo.commitSha) {
3380
+ console.log(
3381
+ source_default.gray(` Commit: `) + source_default.gray(gitInfo.commitSha.substring(0, 7))
3382
+ );
3383
+ }
3384
+ if (gitInfo.commitMessage) {
3385
+ console.log(
3386
+ source_default.gray(` Message: `) + source_default.gray(gitInfo.commitMessage.split("\n")[0])
3387
+ );
3388
+ }
3389
+ console.log();
3390
+ const shouldDeploy = await prompt(
3391
+ source_default.white(
3392
+ `Deploy from GitHub repository ${gitInfo.owner}/${gitInfo.repo}? (y/n): `
3393
+ )
3394
+ );
3395
+ if (!shouldDeploy) {
3396
+ console.log(source_default.gray("Deployment cancelled."));
3397
+ process.exit(0);
3398
+ }
3399
+ const projectName = options.name || await getProjectName(cwd);
3400
+ const runtime = options.runtime || await detectRuntime(cwd);
3401
+ const port = options.port || 3e3;
3402
+ const buildCommand = await detectBuildCommand(cwd);
3403
+ const startCommand = await detectStartCommand(cwd);
3404
+ const envVars = await buildEnvVars(options);
3405
+ console.log();
3406
+ console.log(source_default.white("Deployment configuration:"));
3407
+ console.log(source_default.gray(` Name: `) + source_default.cyan(projectName));
3408
+ console.log(source_default.gray(` Runtime: `) + source_default.cyan(runtime));
3409
+ console.log(source_default.gray(` Port: `) + source_default.cyan(port));
3410
+ if (buildCommand) {
3411
+ console.log(source_default.gray(` Build command: `) + source_default.cyan(buildCommand));
3412
+ }
3413
+ if (startCommand) {
3414
+ console.log(source_default.gray(` Start command: `) + source_default.cyan(startCommand));
3415
+ }
3416
+ if (envVars && Object.keys(envVars).length > 0) {
3417
+ console.log(
3418
+ source_default.gray(` Environment: `) + source_default.cyan(`${Object.keys(envVars).length} variable(s)`)
3419
+ );
3420
+ console.log(
3421
+ source_default.gray(` `) + source_default.gray(Object.keys(envVars).join(", "))
3422
+ );
3423
+ }
3424
+ console.log();
3425
+ const api = await McpUseAPI.create();
3426
+ const existingLink = !options.new ? await getProjectLink(cwd) : null;
3427
+ if (existingLink) {
3428
+ try {
3429
+ const existingDeployment = await api.getDeployment(
3430
+ existingLink.deploymentId
3431
+ );
3432
+ if (existingDeployment && existingDeployment.status !== "failed") {
3433
+ console.log(source_default.green(`\u2713 Found linked deployment`));
3434
+ console.log(
3435
+ source_default.gray(` Redeploying to maintain the same URL...`)
3436
+ );
3437
+ console.log(
3438
+ source_default.cyan(` URL: https://${existingDeployment.domain}/mcp
3439
+ `)
3440
+ );
3441
+ const deployment2 = await api.redeployDeployment(
3442
+ existingLink.deploymentId
3443
+ );
3444
+ await saveProjectLink(cwd, {
3445
+ ...existingLink,
3446
+ linkedAt: (/* @__PURE__ */ new Date()).toISOString()
3447
+ });
3448
+ await displayDeploymentProgress(api, deployment2);
3449
+ if (options.open && deployment2.domain) {
3450
+ console.log();
3451
+ console.log(source_default.gray("Opening deployment in browser..."));
3452
+ await open_default(`https://${deployment2.domain}`);
3453
+ }
3454
+ return;
3455
+ }
3456
+ } catch (error) {
3457
+ console.log(
3458
+ source_default.yellow(`\u26A0\uFE0F Linked deployment not found, creating new one...`)
3459
+ );
3460
+ }
3461
+ }
3462
+ const deploymentRequest = {
3463
+ name: projectName,
3464
+ source: {
3465
+ type: "github",
3466
+ repo: `${gitInfo.owner}/${gitInfo.repo}`,
3467
+ branch: gitInfo.branch || "main",
3468
+ runtime,
3469
+ port,
3470
+ buildCommand,
3471
+ startCommand,
3472
+ env: Object.keys(envVars).length > 0 ? envVars : void 0
3473
+ },
3474
+ healthCheckPath: "/healthz"
3475
+ };
3476
+ console.log(source_default.gray("Creating deployment..."));
3477
+ const deployment = await api.createDeployment(deploymentRequest);
3478
+ console.log(
3479
+ source_default.green("\u2713 Deployment created: ") + source_default.gray(deployment.id)
3480
+ );
3481
+ await saveProjectLink(cwd, {
3482
+ deploymentId: deployment.id,
3483
+ deploymentName: projectName,
3484
+ deploymentUrl: deployment.domain,
3485
+ linkedAt: (/* @__PURE__ */ new Date()).toISOString()
3486
+ });
3487
+ console.log(
3488
+ source_default.gray(` Linked to this project (stored in .mcp-use/project.json)`)
3489
+ );
3490
+ console.log(source_default.gray(` Future deploys will reuse the same URL
3491
+ `));
3492
+ await displayDeploymentProgress(api, deployment);
3493
+ if (options.open && deployment.domain) {
3494
+ console.log();
3495
+ console.log(source_default.gray("Opening deployment in browser..."));
3496
+ await open_default(`https://${deployment.domain}`);
3497
+ }
3498
+ } else {
3499
+ if (options.fromSource) {
3500
+ console.log(
3501
+ source_default.white("\u{1F4E6} Deploying from local source code (--from-source)...")
3502
+ );
3503
+ } else {
3504
+ console.log(
3505
+ source_default.yellow(
3506
+ "\u26A0\uFE0F This is not a GitHub repository or no remote is configured."
3507
+ )
3508
+ );
3509
+ console.log(source_default.white("Deploying from local source code instead..."));
3510
+ }
3511
+ console.log();
3512
+ const projectName = options.name || await getProjectName(cwd);
3513
+ const runtime = options.runtime || await detectRuntime(cwd);
3514
+ const port = options.port || 3e3;
3515
+ const buildCommand = await detectBuildCommand(cwd);
3516
+ const startCommand = await detectStartCommand(cwd);
3517
+ const envVars = await buildEnvVars(options);
3518
+ console.log(source_default.white("Deployment configuration:"));
3519
+ console.log(source_default.gray(` Name: `) + source_default.cyan(projectName));
3520
+ console.log(source_default.gray(` Runtime: `) + source_default.cyan(runtime));
3521
+ console.log(source_default.gray(` Port: `) + source_default.cyan(port));
3522
+ if (buildCommand) {
3523
+ console.log(source_default.gray(` Build command: `) + source_default.cyan(buildCommand));
3524
+ }
3525
+ if (startCommand) {
3526
+ console.log(source_default.gray(` Start command: `) + source_default.cyan(startCommand));
3527
+ }
3528
+ if (envVars && Object.keys(envVars).length > 0) {
3529
+ console.log(
3530
+ source_default.gray(` Environment: `) + source_default.cyan(`${Object.keys(envVars).length} variable(s)`)
3531
+ );
3532
+ console.log(
3533
+ source_default.gray(` `) + source_default.gray(Object.keys(envVars).join(", "))
3534
+ );
3535
+ }
3536
+ console.log();
3537
+ const shouldDeploy = await prompt(
3538
+ source_default.white("Deploy from local source? (y/n): "),
3539
+ "y"
3540
+ );
3541
+ if (!shouldDeploy) {
3542
+ console.log(source_default.gray("Deployment cancelled."));
3543
+ process.exit(0);
3544
+ }
3545
+ console.log();
3546
+ console.log(source_default.gray("Packaging source code..."));
3547
+ const tarballPath = await createTarball(cwd);
3548
+ const stats = await import_node_fs7.promises.stat(tarballPath);
3549
+ console.log(
3550
+ source_default.green("\u2713 Packaged: ") + source_default.gray(formatFileSize(stats.size))
3551
+ );
3552
+ const maxSize = 2 * 1024 * 1024;
3553
+ if (stats.size > maxSize) {
3554
+ console.log(
3555
+ source_default.red(
3556
+ `\u2717 File size (${formatFileSize(stats.size)}) exceeds maximum of 2MB`
3557
+ )
3558
+ );
3559
+ await import_node_fs7.promises.unlink(tarballPath);
3560
+ process.exit(1);
3561
+ }
3562
+ const api = await McpUseAPI.create();
3563
+ const existingLink = !options.new ? await getProjectLink(cwd) : null;
3564
+ if (existingLink) {
3565
+ try {
3566
+ const existingDeployment = await api.getDeployment(
3567
+ existingLink.deploymentId
3568
+ );
3569
+ if (existingDeployment && existingDeployment.status !== "failed") {
3570
+ console.log(source_default.green(`\u2713 Found linked deployment`));
3571
+ console.log(
3572
+ source_default.gray(` Redeploying to maintain the same URL...`)
3573
+ );
3574
+ console.log(
3575
+ source_default.cyan(` URL: https://${existingDeployment.domain}/mcp
3576
+ `)
3577
+ );
3578
+ const deployment2 = await api.redeployDeployment(
3579
+ existingLink.deploymentId,
3580
+ tarballPath
3581
+ );
3582
+ await import_node_fs7.promises.unlink(tarballPath);
3583
+ await saveProjectLink(cwd, {
3584
+ ...existingLink,
3585
+ linkedAt: (/* @__PURE__ */ new Date()).toISOString()
3586
+ });
3587
+ await displayDeploymentProgress(api, deployment2);
3588
+ if (options.open && deployment2.domain) {
3589
+ console.log();
3590
+ console.log(source_default.gray("Opening deployment in browser..."));
3591
+ await open_default(`https://${deployment2.domain}`);
3592
+ }
3593
+ return;
3594
+ }
3595
+ } catch (error) {
3596
+ console.log(
3597
+ source_default.yellow(`\u26A0\uFE0F Linked deployment not found, creating new one...`)
3598
+ );
3599
+ }
3600
+ }
3601
+ const deploymentRequest = {
3602
+ name: projectName,
3603
+ source: {
3604
+ type: "upload",
3605
+ runtime,
3606
+ port,
3607
+ buildCommand,
3608
+ startCommand,
3609
+ env: Object.keys(envVars).length > 0 ? envVars : void 0
3610
+ },
3611
+ healthCheckPath: "/healthz"
3612
+ };
3613
+ console.log(source_default.gray("Creating deployment..."));
3614
+ const deployment = await api.createDeploymentWithUpload(
3615
+ deploymentRequest,
3616
+ tarballPath
2627
3617
  );
2628
- client.addServer(sessionName, {
2629
- command,
2630
- args
2631
- });
2632
- session = await client.createSession(sessionName);
2633
- await saveSession(sessionName, {
2634
- type: "stdio",
2635
- command,
2636
- args,
2637
- lastUsed: (/* @__PURE__ */ new Date()).toISOString()
2638
- });
2639
- } else {
2640
- console.error(formatInfo(`Connecting to ${urlOrCommand}...`));
2641
- client.addServer(sessionName, {
2642
- url: urlOrCommand,
2643
- headers: options.auth ? { Authorization: `Bearer ${options.auth}` } : void 0
2644
- });
2645
- session = await client.createSession(sessionName);
2646
- await saveSession(sessionName, {
2647
- type: "http",
2648
- url: urlOrCommand,
2649
- authToken: options.auth,
2650
- lastUsed: (/* @__PURE__ */ new Date()).toISOString()
3618
+ await import_node_fs7.promises.unlink(tarballPath);
3619
+ console.log(
3620
+ source_default.green("\u2713 Deployment created: ") + source_default.gray(deployment.id)
3621
+ );
3622
+ await saveProjectLink(cwd, {
3623
+ deploymentId: deployment.id,
3624
+ deploymentName: projectName,
3625
+ deploymentUrl: deployment.domain,
3626
+ linkedAt: (/* @__PURE__ */ new Date()).toISOString()
2651
3627
  });
2652
- }
2653
- activeSessions.set(sessionName, { client, session });
2654
- const serverInfo = session.serverInfo;
2655
- const capabilities = session.serverCapabilities;
2656
- if (serverInfo) {
2657
- await updateSessionInfo(sessionName, serverInfo, capabilities);
2658
- }
2659
- console.log(formatSuccess(`Connected to ${sessionName}`));
2660
- if (serverInfo) {
2661
- console.log("");
2662
- console.log(formatHeader("Server Information:"));
2663
3628
  console.log(
2664
- formatKeyValue({
2665
- Name: serverInfo.name,
2666
- Version: serverInfo.version || "unknown"
2667
- })
3629
+ source_default.gray(` Linked to this project (stored in .mcp-use/project.json)`)
2668
3630
  );
3631
+ console.log(source_default.gray(` Future deploys will reuse the same URL
3632
+ `));
3633
+ await displayDeploymentProgress(api, deployment);
3634
+ if (options.open && deployment.domain) {
3635
+ console.log();
3636
+ console.log(source_default.gray("Opening deployment in browser..."));
3637
+ await open_default(`https://${deployment.domain}`);
3638
+ }
2669
3639
  }
2670
- if (capabilities) {
2671
- console.log("");
2672
- console.log(formatHeader("Capabilities:"));
2673
- const caps = Object.keys(capabilities).join(", ");
2674
- console.log(` ${caps || "none"}`);
2675
- }
2676
- const tools = session.tools;
2677
- console.log("");
2678
- console.log(
2679
- formatInfo(
2680
- `Available: ${tools.length} tool${tools.length !== 1 ? "s" : ""}`
2681
- )
2682
- );
2683
3640
  } catch (error) {
2684
- console.error(formatError(`Connection failed: ${error.message}`));
3641
+ console.error(
3642
+ source_default.red.bold("\n\u2717 Deployment failed:"),
3643
+ source_default.red(error instanceof Error ? error.message : "Unknown error")
3644
+ );
2685
3645
  process.exit(1);
2686
3646
  }
2687
3647
  }
2688
- async function disconnectCommand(sessionName, options) {
2689
- try {
2690
- if (options?.all) {
2691
- for (const [name, { client }] of activeSessions.entries()) {
2692
- await client.closeAllSessions();
2693
- activeSessions.delete(name);
2694
- console.log(formatSuccess(`Disconnected from ${name}`));
2695
- }
2696
- return;
2697
- }
2698
- if (!sessionName) {
2699
- const active = await getActiveSession();
2700
- if (!active) {
2701
- console.error(formatError("No active session to disconnect"));
2702
- return;
2703
- }
2704
- sessionName = active.name;
2705
- }
2706
- const sessionData = activeSessions.get(sessionName);
2707
- if (sessionData) {
2708
- await sessionData.client.closeAllSessions();
2709
- activeSessions.delete(sessionName);
2710
- console.log(formatSuccess(`Disconnected from ${sessionName}`));
2711
- } else {
2712
- console.log(formatInfo(`Session '${sessionName}' is not connected`));
2713
- }
2714
- } catch (error) {
2715
- console.error(formatError(`Failed to disconnect: ${error.message}`));
2716
- process.exit(1);
3648
+
3649
+ // src/commands/deployments.ts
3650
+ var import_commander2 = require("commander");
3651
+ async function prompt2(question) {
3652
+ const readline = await import("readline");
3653
+ const rl = readline.createInterface({
3654
+ input: process.stdin,
3655
+ output: process.stdout
3656
+ });
3657
+ return new Promise((resolve) => {
3658
+ rl.question(question, (answer) => {
3659
+ rl.close();
3660
+ const trimmedAnswer = answer.trim().toLowerCase();
3661
+ resolve(trimmedAnswer === "y" || trimmedAnswer === "yes");
3662
+ });
3663
+ });
3664
+ }
3665
+ function getStatusColor(status) {
3666
+ switch (status) {
3667
+ case "running":
3668
+ return source_default.green;
3669
+ case "building":
3670
+ case "pending":
3671
+ return source_default.yellow;
3672
+ case "failed":
3673
+ case "stopped":
3674
+ return source_default.red;
3675
+ default:
3676
+ return source_default.gray;
2717
3677
  }
2718
3678
  }
2719
- async function listSessionsCommand() {
3679
+ function formatId(id) {
3680
+ return id;
3681
+ }
3682
+ async function listDeploymentsCommand() {
2720
3683
  try {
2721
- const sessions = await listAllSessions();
2722
- if (sessions.length === 0) {
2723
- console.log(formatInfo("No saved sessions"));
3684
+ if (!await isLoggedIn()) {
3685
+ console.log(source_default.red("\u2717 You are not logged in."));
2724
3686
  console.log(
2725
- formatInfo("Connect to a server with: npx mcp-use client connect <url>")
3687
+ source_default.gray("Run " + source_default.white("mcp-use login") + " to get started.")
2726
3688
  );
2727
- return;
3689
+ process.exit(1);
2728
3690
  }
2729
- console.log(formatHeader("Saved Sessions:"));
2730
- console.log("");
2731
- const tableData = sessions.map((s) => ({
2732
- name: s.isActive ? source_default.green.bold(`${s.name} *`) : s.name,
2733
- type: s.config.type,
2734
- target: s.config.type === "http" ? s.config.url || "" : `${s.config.command} ${(s.config.args || []).join(" ")}`,
2735
- server: s.config.serverInfo?.name || "unknown",
2736
- status: activeSessions.has(s.name) ? source_default.green("connected") : source_default.gray("disconnected")
2737
- }));
2738
- console.log(
2739
- formatTable(tableData, [
2740
- { key: "name", header: "Name" },
2741
- { key: "type", header: "Type" },
2742
- { key: "target", header: "Target", width: 40 },
2743
- { key: "server", header: "Server" },
2744
- { key: "status", header: "Status" }
2745
- ])
3691
+ const api = await McpUseAPI.create();
3692
+ const deployments = await api.listDeployments();
3693
+ const sortedDeployments = [...deployments].sort(
3694
+ (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
2746
3695
  );
2747
- console.log("");
2748
- console.log(source_default.gray("* = active session"));
2749
- } catch (error) {
2750
- console.error(formatError(`Failed to list sessions: ${error.message}`));
2751
- process.exit(1);
2752
- }
2753
- }
2754
- async function switchSessionCommand(name) {
2755
- try {
2756
- await setActiveSession(name);
2757
- console.log(formatSuccess(`Switched to session '${name}'`));
2758
- } catch (error) {
2759
- console.error(formatError(`Failed to switch session: ${error.message}`));
2760
- process.exit(1);
2761
- }
2762
- }
2763
- async function listToolsCommand(options) {
2764
- try {
2765
- const result = await getOrRestoreSession(options.session || null);
2766
- if (!result) return;
2767
- const { session } = result;
2768
- const tools = await session.listTools();
2769
- if (options.json) {
2770
- console.log(formatJson(tools));
2771
- return;
2772
- }
2773
- if (tools.length === 0) {
2774
- console.log(formatInfo("No tools available"));
3696
+ if (sortedDeployments.length === 0) {
3697
+ console.log(source_default.yellow("No deployments found."));
3698
+ console.log(
3699
+ source_default.gray(
3700
+ "\nDeploy your first MCP server with " + source_default.white("mcp-use deploy")
3701
+ )
3702
+ );
2775
3703
  return;
2776
3704
  }
2777
- console.log(formatHeader(`Available Tools (${tools.length}):`));
2778
- console.log("");
2779
- const tableData = tools.map((tool) => ({
2780
- name: source_default.bold(tool.name),
2781
- description: tool.description || source_default.gray("No description")
2782
- }));
2783
3705
  console.log(
2784
- formatTable(tableData, [
2785
- { key: "name", header: "Tool", width: 25 },
2786
- { key: "description", header: "Description", width: 50 }
2787
- ])
3706
+ source_default.cyan.bold(`
3707
+ \u{1F4E6} Deployments (${sortedDeployments.length})
3708
+ `)
2788
3709
  );
2789
- } catch (error) {
2790
- console.error(formatError(`Failed to list tools: ${error.message}`));
2791
- process.exit(1);
2792
- }
2793
- }
2794
- async function describeToolCommand(toolName, options) {
2795
- try {
2796
- const result = await getOrRestoreSession(options.session || null);
2797
- if (!result) return;
2798
- const { session } = result;
2799
- const tools = session.tools;
2800
- const tool = tools.find((t) => t.name === toolName);
2801
- if (!tool) {
2802
- console.error(formatError(`Tool '${toolName}' not found`));
2803
- console.log("");
2804
- console.log(formatInfo("Available tools:"));
2805
- tools.forEach((t) => console.log(` \u2022 ${t.name}`));
2806
- return;
2807
- }
2808
- console.log(formatHeader(`Tool: ${tool.name}`));
2809
- console.log("");
2810
- if (tool.description) {
2811
- console.log(tool.description);
2812
- console.log("");
2813
- }
2814
- if (tool.inputSchema) {
2815
- console.log(formatHeader("Input Schema:"));
2816
- console.log(formatSchema(tool.inputSchema));
2817
- }
2818
- } catch (error) {
2819
- console.error(formatError(`Failed to describe tool: ${error.message}`));
2820
- process.exit(1);
2821
- }
2822
- }
2823
- async function callToolCommand(toolName, argsJson, options) {
2824
- try {
2825
- const result = await getOrRestoreSession(options?.session || null);
2826
- if (!result) return;
2827
- const { session } = result;
2828
- let args = {};
2829
- if (argsJson) {
2830
- try {
2831
- args = JSON.parse(argsJson);
2832
- } catch (error) {
2833
- console.error(formatError("Invalid JSON arguments"));
2834
- return;
2835
- }
2836
- } else {
2837
- const tools = session.tools;
2838
- const tool = tools.find((t) => t.name === toolName);
2839
- if (tool?.inputSchema?.required && tool.inputSchema.required.length > 0) {
2840
- console.error(
2841
- formatError(
2842
- "This tool requires arguments. Provide them as a JSON string."
2843
- )
2844
- );
2845
- console.log("");
2846
- console.log(formatInfo("Example:"));
2847
- console.log(
2848
- ` npx mcp-use client tools call ${toolName} '{"param": "value"}'`
2849
- );
2850
- console.log("");
2851
- console.log(formatInfo("Tool schema:"));
2852
- console.log(formatSchema(tool.inputSchema));
2853
- return;
2854
- }
2855
- }
2856
- console.error(formatInfo(`Calling tool '${toolName}'...`));
2857
- const callResult = await session.callTool(toolName, args, {
2858
- timeout: options?.timeout
2859
- });
2860
- if (options?.json) {
2861
- console.log(formatJson(callResult));
2862
- } else {
2863
- console.log(formatToolCall(callResult));
3710
+ console.log(
3711
+ source_default.white.bold(
3712
+ `${"ID".padEnd(40)} ${"NAME".padEnd(25)} ${"STATUS".padEnd(12)} ${"DOMAIN".padEnd(35)} ${"CREATED"}`
3713
+ )
3714
+ );
3715
+ console.log(source_default.gray("\u2500".repeat(130)));
3716
+ for (const deployment of sortedDeployments) {
3717
+ const id = formatId(deployment.id).padEnd(40);
3718
+ const name = deployment.name.substring(0, 24).padEnd(25);
3719
+ const statusColor = getStatusColor(deployment.status);
3720
+ const status = statusColor(deployment.status.padEnd(12));
3721
+ const domain = (deployment.domain || "-").substring(0, 34).padEnd(35);
3722
+ const created = formatRelativeTime(deployment.createdAt);
3723
+ console.log(
3724
+ `${source_default.gray(id)} ${name} ${status} ${source_default.cyan(domain)} ${source_default.gray(created)}`
3725
+ );
2864
3726
  }
3727
+ console.log();
2865
3728
  } catch (error) {
2866
- console.error(formatError(`Failed to call tool: ${error.message}`));
3729
+ console.error(
3730
+ source_default.red.bold("\n\u2717 Failed to list deployments:"),
3731
+ source_default.red(error instanceof Error ? error.message : "Unknown error")
3732
+ );
2867
3733
  process.exit(1);
2868
3734
  }
2869
3735
  }
2870
- async function listResourcesCommand(options) {
3736
+ async function getDeploymentCommand(deploymentId) {
2871
3737
  try {
2872
- const result = await getOrRestoreSession(options.session || null);
2873
- if (!result) return;
2874
- const { session } = result;
2875
- const resourcesResult = await session.listAllResources();
2876
- const resources = resourcesResult.resources;
2877
- if (options.json) {
2878
- console.log(formatJson(resources));
2879
- return;
3738
+ if (!await isLoggedIn()) {
3739
+ console.log(source_default.red("\u2717 You are not logged in."));
3740
+ console.log(
3741
+ source_default.gray("Run " + source_default.white("mcp-use login") + " to get started.")
3742
+ );
3743
+ process.exit(1);
2880
3744
  }
2881
- if (resources.length === 0) {
2882
- console.log(formatInfo("No resources available"));
2883
- return;
3745
+ const api = await McpUseAPI.create();
3746
+ const deployment = await api.getDeployment(deploymentId);
3747
+ console.log(source_default.cyan.bold("\n\u{1F4E6} Deployment Details\n"));
3748
+ console.log(source_default.white("ID: ") + source_default.gray(deployment.id));
3749
+ console.log(source_default.white("Name: ") + source_default.cyan(deployment.name));
3750
+ const statusColor = getStatusColor(deployment.status);
3751
+ console.log(
3752
+ source_default.white("Status: ") + statusColor(deployment.status)
3753
+ );
3754
+ if (deployment.domain) {
3755
+ console.log(
3756
+ source_default.white("Domain: ") + source_default.cyan(`https://${deployment.domain}`)
3757
+ );
3758
+ }
3759
+ if (deployment.customDomain) {
3760
+ console.log(
3761
+ source_default.white("Custom Domain: ") + source_default.cyan(`https://${deployment.customDomain}`)
3762
+ );
2884
3763
  }
2885
- console.log(formatHeader(`Available Resources (${resources.length}):`));
2886
- console.log("");
2887
- const tableData = resources.map((resource) => ({
2888
- uri: resource.uri,
2889
- name: resource.name || source_default.gray("(no name)"),
2890
- type: resource.mimeType || source_default.gray("unknown")
2891
- }));
2892
3764
  console.log(
2893
- formatTable(tableData, [
2894
- { key: "uri", header: "URI", width: 40 },
2895
- { key: "name", header: "Name", width: 20 },
2896
- { key: "type", header: "Type", width: 15 }
2897
- ])
3765
+ source_default.white("Source: ") + source_default.gray(deployment.source.type)
3766
+ );
3767
+ if (deployment.source.type === "github") {
3768
+ console.log(
3769
+ source_default.white("Repository: ") + source_default.gray(deployment.source.repo)
3770
+ );
3771
+ console.log(
3772
+ source_default.white("Branch: ") + source_default.gray(deployment.source.branch || "main")
3773
+ );
3774
+ }
3775
+ console.log(source_default.white("Port: ") + source_default.gray(deployment.port));
3776
+ console.log(
3777
+ source_default.white("Runtime: ") + source_default.gray(deployment.source.runtime || "node")
3778
+ );
3779
+ if (deployment.provider) {
3780
+ console.log(
3781
+ source_default.white("Provider: ") + source_default.gray(deployment.provider)
3782
+ );
3783
+ }
3784
+ console.log(
3785
+ source_default.white("Created: ") + source_default.gray(formatRelativeTime(deployment.createdAt))
3786
+ );
3787
+ console.log(
3788
+ source_default.white("Updated: ") + source_default.gray(formatRelativeTime(deployment.updatedAt))
2898
3789
  );
3790
+ if (deployment.source.env && Object.keys(deployment.source.env).length > 0) {
3791
+ console.log(source_default.white("\nEnvironment Variables:"));
3792
+ for (const [key, value] of Object.entries(deployment.source.env)) {
3793
+ const displayValue = key.toLowerCase().includes("key") || key.toLowerCase().includes("secret") || key.toLowerCase().includes("password") || key.toLowerCase().includes("token") ? "***" : value;
3794
+ console.log(source_default.gray(` ${key}=`) + source_default.white(displayValue));
3795
+ }
3796
+ }
3797
+ if (deployment.status === "failed" && deployment.error) {
3798
+ console.log(source_default.red("\nError:"));
3799
+ console.log(source_default.red(` ${deployment.error}`));
3800
+ }
3801
+ console.log();
2899
3802
  } catch (error) {
2900
- console.error(formatError(`Failed to list resources: ${error.message}`));
3803
+ console.error(
3804
+ source_default.red.bold("\n\u2717 Failed to get deployment:"),
3805
+ source_default.red(error instanceof Error ? error.message : "Unknown error")
3806
+ );
2901
3807
  process.exit(1);
2902
3808
  }
2903
3809
  }
2904
- async function readResourceCommand(uri, options) {
3810
+ async function restartDeploymentCommand(deploymentId, options) {
2905
3811
  try {
2906
- const result = await getOrRestoreSession(options.session || null);
2907
- if (!result) return;
2908
- const { session } = result;
2909
- console.error(formatInfo(`Reading resource: ${uri}`));
2910
- const resource = await session.readResource(uri);
2911
- if (options.json) {
2912
- console.log(formatJson(resource));
3812
+ if (!await isLoggedIn()) {
3813
+ console.log(source_default.red("\u2717 You are not logged in."));
3814
+ console.log(
3815
+ source_default.gray("Run " + source_default.white("mcp-use login") + " to get started.")
3816
+ );
3817
+ process.exit(1);
3818
+ }
3819
+ const api = await McpUseAPI.create();
3820
+ const deployment = await api.getDeployment(deploymentId);
3821
+ console.log(
3822
+ source_default.cyan.bold(`
3823
+ \u{1F504} Restarting deployment: ${deployment.name}
3824
+ `)
3825
+ );
3826
+ const redeployedDeployment = await api.redeployDeployment(deploymentId);
3827
+ console.log(
3828
+ source_default.green("\u2713 Restart initiated: ") + source_default.gray(redeployedDeployment.id)
3829
+ );
3830
+ if (options.follow) {
3831
+ console.log(source_default.gray("\nFollowing deployment logs...\n"));
3832
+ try {
3833
+ for await (const log of api.streamDeploymentLogs(
3834
+ redeployedDeployment.id
3835
+ )) {
3836
+ try {
3837
+ const logData = JSON.parse(log);
3838
+ if (logData.line) {
3839
+ const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
3840
+ const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
3841
+ console.log(stepPrefix + levelColor(logData.line));
3842
+ }
3843
+ } catch {
3844
+ console.log(source_default.gray(log));
3845
+ }
3846
+ }
3847
+ } catch (error) {
3848
+ console.log(
3849
+ source_default.gray(
3850
+ "\nLog stream ended. Use " + source_default.white(`mcp-use deployments get ${deploymentId}`) + " to check status."
3851
+ )
3852
+ );
3853
+ }
2913
3854
  } else {
2914
- console.log(formatResourceContent(resource));
3855
+ console.log(
3856
+ source_default.gray(
3857
+ "\nCheck status with: " + source_default.white(`mcp-use deployments get ${deploymentId}`)
3858
+ )
3859
+ );
2915
3860
  }
3861
+ console.log();
2916
3862
  } catch (error) {
2917
- console.error(formatError(`Failed to read resource: ${error.message}`));
3863
+ console.error(
3864
+ source_default.red.bold("\n\u2717 Failed to restart deployment:"),
3865
+ source_default.red(error instanceof Error ? error.message : "Unknown error")
3866
+ );
2918
3867
  process.exit(1);
2919
3868
  }
2920
3869
  }
2921
- async function subscribeResourceCommand(uri, options) {
3870
+ async function deleteDeploymentCommand(deploymentId, options) {
2922
3871
  try {
2923
- const result = await getOrRestoreSession(options.session || null);
2924
- if (!result) return;
2925
- const { session } = result;
2926
- await session.subscribeToResource(uri);
2927
- console.log(formatSuccess(`Subscribed to resource: ${uri}`));
2928
- session.on("notification", async (notification) => {
2929
- if (notification.method === "notifications/resources/updated") {
2930
- console.log("");
2931
- console.log(formatInfo("Resource updated:"));
2932
- console.log(formatJson(notification.params));
3872
+ if (!await isLoggedIn()) {
3873
+ console.log(source_default.red("\u2717 You are not logged in."));
3874
+ console.log(
3875
+ source_default.gray("Run " + source_default.white("mcp-use login") + " to get started.")
3876
+ );
3877
+ process.exit(1);
3878
+ }
3879
+ const api = await McpUseAPI.create();
3880
+ const deployment = await api.getDeployment(deploymentId);
3881
+ if (!options.yes) {
3882
+ console.log(
3883
+ source_default.yellow(
3884
+ `
3885
+ \u26A0\uFE0F You are about to delete deployment: ${source_default.white(deployment.name)}`
3886
+ )
3887
+ );
3888
+ console.log(source_default.gray(` ID: ${deployment.id}`));
3889
+ console.log(source_default.gray(` Domain: ${deployment.domain || "none"}
3890
+ `));
3891
+ const confirmed = await prompt2(
3892
+ source_default.white("Are you sure you want to delete this deployment? (y/N): ")
3893
+ );
3894
+ if (!confirmed) {
3895
+ console.log(source_default.gray("Deletion cancelled."));
3896
+ return;
2933
3897
  }
2934
- });
2935
- console.log(formatInfo("Listening for updates... (Press Ctrl+C to stop)"));
2936
- await new Promise(() => {
2937
- });
3898
+ }
3899
+ await api.deleteDeployment(deploymentId);
3900
+ console.log(
3901
+ source_default.green.bold(`
3902
+ \u2713 Deployment deleted: ${deployment.name}
3903
+ `)
3904
+ );
2938
3905
  } catch (error) {
2939
3906
  console.error(
2940
- formatError(`Failed to subscribe to resource: ${error.message}`)
3907
+ source_default.red.bold("\n\u2717 Failed to delete deployment:"),
3908
+ source_default.red(error instanceof Error ? error.message : "Unknown error")
2941
3909
  );
2942
3910
  process.exit(1);
2943
3911
  }
2944
3912
  }
2945
- async function unsubscribeResourceCommand(uri, options) {
3913
+ async function logsCommand(deploymentId, options) {
2946
3914
  try {
2947
- const result = await getOrRestoreSession(options.session || null);
2948
- if (!result) return;
2949
- const { session } = result;
2950
- await session.unsubscribeFromResource(uri);
2951
- console.log(formatSuccess(`Unsubscribed from resource: ${uri}`));
3915
+ if (!await isLoggedIn()) {
3916
+ console.log(source_default.red("\u2717 You are not logged in."));
3917
+ console.log(
3918
+ source_default.gray("Run " + source_default.white("mcp-use login") + " to get started.")
3919
+ );
3920
+ process.exit(1);
3921
+ }
3922
+ const api = await McpUseAPI.create();
3923
+ if (options.follow) {
3924
+ console.log(source_default.gray("Streaming logs...\n"));
3925
+ try {
3926
+ for await (const log of api.streamDeploymentLogs(deploymentId)) {
3927
+ try {
3928
+ const logData = JSON.parse(log);
3929
+ if (logData.line) {
3930
+ const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
3931
+ const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
3932
+ console.log(stepPrefix + levelColor(logData.line));
3933
+ }
3934
+ } catch {
3935
+ console.log(source_default.gray(log));
3936
+ }
3937
+ }
3938
+ } catch (error) {
3939
+ console.log(source_default.gray("\nLog stream ended."));
3940
+ }
3941
+ } else {
3942
+ const logs = options.build ? await api.getDeploymentBuildLogs(deploymentId) : await api.getDeploymentLogs(deploymentId);
3943
+ if (!logs || logs.trim() === "") {
3944
+ console.log(
3945
+ source_default.yellow(
3946
+ `No ${options.build ? "build " : ""}logs available for this deployment.`
3947
+ )
3948
+ );
3949
+ return;
3950
+ }
3951
+ const logLines = logs.split("\n").filter((l) => l.trim());
3952
+ for (const line of logLines) {
3953
+ try {
3954
+ const logData = JSON.parse(line);
3955
+ if (logData.line) {
3956
+ const levelColor = logData.level === "error" ? source_default.red : logData.level === "warn" ? source_default.yellow : source_default.gray;
3957
+ const stepPrefix = logData.step ? source_default.cyan(`[${logData.step}]`) + " " : "";
3958
+ console.log(stepPrefix + levelColor(logData.line));
3959
+ }
3960
+ } catch {
3961
+ console.log(source_default.gray(line));
3962
+ }
3963
+ }
3964
+ }
3965
+ console.log();
2952
3966
  } catch (error) {
2953
3967
  console.error(
2954
- formatError(`Failed to unsubscribe from resource: ${error.message}`)
3968
+ source_default.red.bold("\n\u2717 Failed to get logs:"),
3969
+ source_default.red(error instanceof Error ? error.message : "Unknown error")
2955
3970
  );
2956
3971
  process.exit(1);
2957
3972
  }
2958
3973
  }
2959
- async function listPromptsCommand(options) {
3974
+ async function listEnvCommand(deploymentId) {
2960
3975
  try {
2961
- const result = await getOrRestoreSession(options.session || null);
2962
- if (!result) return;
2963
- const { session } = result;
2964
- const promptsResult = await session.listPrompts();
2965
- const prompts = promptsResult.prompts;
2966
- if (options.json) {
2967
- console.log(formatJson(prompts));
2968
- return;
2969
- }
2970
- if (prompts.length === 0) {
2971
- console.log(formatInfo("No prompts available"));
2972
- return;
3976
+ if (!await isLoggedIn()) {
3977
+ console.log(source_default.red("\u2717 You are not logged in."));
3978
+ console.log(
3979
+ source_default.gray("Run " + source_default.white("mcp-use login") + " to get started.")
3980
+ );
3981
+ process.exit(1);
2973
3982
  }
2974
- console.log(formatHeader(`Available Prompts (${prompts.length}):`));
2975
- console.log("");
2976
- const tableData = prompts.map((prompt2) => ({
2977
- name: source_default.bold(prompt2.name),
2978
- description: prompt2.description || source_default.gray("No description")
2979
- }));
3983
+ const api = await McpUseAPI.create();
3984
+ const deployment = await api.getDeployment(deploymentId);
2980
3985
  console.log(
2981
- formatTable(tableData, [
2982
- { key: "name", header: "Prompt", width: 25 },
2983
- { key: "description", header: "Description", width: 50 }
2984
- ])
3986
+ source_default.cyan.bold(`
3987
+ \u{1F510} Environment Variables: ${deployment.name}
3988
+ `)
2985
3989
  );
3990
+ if (!deployment.source.env || Object.keys(deployment.source.env).length === 0) {
3991
+ console.log(source_default.yellow("No environment variables set."));
3992
+ console.log();
3993
+ return;
3994
+ }
3995
+ for (const [key, value] of Object.entries(deployment.source.env)) {
3996
+ const displayValue = key.toLowerCase().includes("key") || key.toLowerCase().includes("secret") || key.toLowerCase().includes("password") || key.toLowerCase().includes("token") ? "***" : value;
3997
+ console.log(
3998
+ source_default.white(key) + source_default.gray("=") + source_default.cyan(displayValue)
3999
+ );
4000
+ }
4001
+ console.log();
2986
4002
  } catch (error) {
2987
- console.error(formatError(`Failed to list prompts: ${error.message}`));
4003
+ console.error(
4004
+ source_default.red.bold("\n\u2717 Failed to list environment variables:"),
4005
+ source_default.red(error instanceof Error ? error.message : "Unknown error")
4006
+ );
2988
4007
  process.exit(1);
2989
4008
  }
2990
4009
  }
2991
- async function getPromptCommand(promptName, argsJson, options) {
4010
+ async function setEnvCommand(deploymentId, envPairs) {
2992
4011
  try {
2993
- const result = await getOrRestoreSession(options?.session || null);
2994
- if (!result) return;
2995
- const { session } = result;
2996
- let args = {};
2997
- if (argsJson) {
2998
- try {
2999
- args = JSON.parse(argsJson);
3000
- } catch (error) {
3001
- console.error(formatError("Invalid JSON arguments"));
3002
- return;
3003
- }
4012
+ if (!await isLoggedIn()) {
4013
+ console.log(source_default.red("\u2717 You are not logged in."));
4014
+ console.log(
4015
+ source_default.gray("Run " + source_default.white("mcp-use login") + " to get started.")
4016
+ );
4017
+ process.exit(1);
3004
4018
  }
3005
- console.error(formatInfo(`Getting prompt '${promptName}'...`));
3006
- const prompt2 = await session.getPrompt(promptName, args);
3007
- if (options?.json) {
3008
- console.log(formatJson(prompt2));
3009
- } else {
3010
- console.log(formatHeader(`Prompt: ${promptName}`));
3011
- console.log("");
3012
- if (prompt2.description) {
3013
- console.log(prompt2.description);
3014
- console.log("");
3015
- }
3016
- if (prompt2.messages) {
3017
- console.log(formatHeader("Messages:"));
3018
- console.log("");
3019
- console.log(formatPromptMessages(prompt2.messages));
4019
+ const env2 = {};
4020
+ for (const pair of envPairs) {
4021
+ const [key, ...valueParts] = pair.split("=");
4022
+ if (!key || valueParts.length === 0) {
4023
+ console.log(source_default.red(`\u2717 Invalid format: ${pair}. Expected KEY=VALUE`));
4024
+ process.exit(1);
3020
4025
  }
4026
+ env2[key.trim()] = valueParts.join("=").trim();
4027
+ }
4028
+ const api = await McpUseAPI.create();
4029
+ const deployment = await api.getDeployment(deploymentId);
4030
+ const currentEnv = deployment.source.env || {};
4031
+ const mergedEnv = { ...currentEnv, ...env2 };
4032
+ const updated = await api.updateDeployment(deploymentId, {
4033
+ env: mergedEnv
4034
+ });
4035
+ console.log(
4036
+ source_default.green.bold(`
4037
+ \u2713 Environment variables updated: ${updated.name}
4038
+ `)
4039
+ );
4040
+ for (const key of Object.keys(env2)) {
4041
+ const displayValue = key.toLowerCase().includes("key") || key.toLowerCase().includes("secret") || key.toLowerCase().includes("password") || key.toLowerCase().includes("token") ? "***" : env2[key];
4042
+ console.log(
4043
+ source_default.white(key) + source_default.gray("=") + source_default.cyan(displayValue)
4044
+ );
3021
4045
  }
4046
+ console.log();
3022
4047
  } catch (error) {
3023
- console.error(formatError(`Failed to get prompt: ${error.message}`));
4048
+ console.error(
4049
+ source_default.red.bold("\n\u2717 Failed to set environment variables:"),
4050
+ source_default.red(error instanceof Error ? error.message : "Unknown error")
4051
+ );
3024
4052
  process.exit(1);
3025
4053
  }
3026
4054
  }
3027
- async function interactiveCommand(options) {
4055
+ async function unsetEnvCommand(deploymentId, keys) {
3028
4056
  try {
3029
- const result = await getOrRestoreSession(options.session || null);
3030
- if (!result) return;
3031
- const { name: sessionName, session } = result;
3032
- console.log(formatHeader("MCP Interactive Mode"));
3033
- console.log("");
3034
- console.log(formatInfo(`Connected to: ${sessionName}`));
3035
- console.log("");
3036
- console.log(source_default.gray("Commands:"));
3037
- console.log(source_default.gray(" tools list - List available tools"));
3038
- console.log(
3039
- source_default.gray(
3040
- " tools call <name> - Call a tool (will prompt for args)"
3041
- )
3042
- );
3043
- console.log(source_default.gray(" tools describe <name> - Show tool details"));
3044
- console.log(
3045
- source_default.gray(" resources list - List available resources")
3046
- );
3047
- console.log(source_default.gray(" resources read <uri> - Read a resource"));
3048
- console.log(
3049
- source_default.gray(" prompts list - List available prompts")
3050
- );
3051
- console.log(source_default.gray(" prompts get <name> - Get a prompt"));
3052
- console.log(source_default.gray(" sessions list - List all sessions"));
4057
+ if (!await isLoggedIn()) {
4058
+ console.log(source_default.red("\u2717 You are not logged in."));
4059
+ console.log(
4060
+ source_default.gray("Run " + source_default.white("mcp-use login") + " to get started.")
4061
+ );
4062
+ process.exit(1);
4063
+ }
4064
+ const api = await McpUseAPI.create();
4065
+ const deployment = await api.getDeployment(deploymentId);
4066
+ const currentEnv = { ...deployment.source.env || {} };
4067
+ for (const key of keys) {
4068
+ delete currentEnv[key];
4069
+ }
4070
+ const updated = await api.updateDeployment(deploymentId, {
4071
+ env: currentEnv
4072
+ });
3053
4073
  console.log(
3054
- source_default.gray(" sessions switch <name> - Switch to another session")
4074
+ source_default.green.bold(`
4075
+ \u2713 Environment variables removed: ${updated.name}
4076
+ `)
3055
4077
  );
3056
- console.log(
3057
- source_default.gray(" exit, quit - Exit interactive mode")
4078
+ for (const key of keys) {
4079
+ console.log(source_default.gray(` ${key}`));
4080
+ }
4081
+ console.log();
4082
+ } catch (error) {
4083
+ console.error(
4084
+ source_default.red.bold("\n\u2717 Failed to unset environment variables:"),
4085
+ source_default.red(error instanceof Error ? error.message : "Unknown error")
3058
4086
  );
3059
- console.log("");
3060
- const rl = (0, import_node_readline.createInterface)({
3061
- input: process.stdin,
3062
- output: process.stdout,
3063
- prompt: source_default.cyan("mcp> ")
3064
- });
3065
- rl.prompt();
3066
- rl.on("line", async (line) => {
3067
- const trimmed = line.trim();
3068
- if (!trimmed) {
3069
- rl.prompt();
3070
- return;
3071
- }
3072
- if (trimmed === "exit" || trimmed === "quit") {
3073
- console.log(formatInfo("Goodbye!"));
3074
- rl.close();
3075
- process.exit(0);
3076
- }
3077
- const parts = trimmed.split(" ");
3078
- const scope = parts[0];
3079
- const command = parts[1];
3080
- const arg = parts[2];
3081
- try {
3082
- if (scope === "tools") {
3083
- if (command === "list") {
3084
- const tools = await session.listTools();
3085
- console.log(
3086
- formatInfo(
3087
- `Available tools: ${tools.map((t) => t.name).join(", ")}`
3088
- )
3089
- );
3090
- } else if (command === "call" && arg) {
3091
- rl.question(
3092
- "Arguments (JSON, or press Enter for none): ",
3093
- async (argsInput) => {
3094
- try {
3095
- const args = argsInput.trim() ? JSON.parse(argsInput) : {};
3096
- const result2 = await session.callTool(arg, args);
3097
- console.log(formatToolCall(result2));
3098
- } catch (error) {
3099
- console.error(formatError(error.message));
3100
- }
3101
- rl.prompt();
3102
- }
3103
- );
3104
- return;
3105
- } else if (command === "describe" && arg) {
3106
- const tools = session.tools;
3107
- const tool = tools.find((t) => t.name === arg);
3108
- if (tool) {
3109
- console.log(formatHeader(`Tool: ${tool.name}`));
3110
- if (tool.description) console.log(tool.description);
3111
- if (tool.inputSchema) {
3112
- console.log("");
3113
- console.log(formatSchema(tool.inputSchema));
3114
- }
3115
- } else {
3116
- console.error(formatError(`Tool '${arg}' not found`));
3117
- }
3118
- } else {
3119
- console.error(
3120
- formatError(
3121
- "Invalid command. Try: tools list, tools call <name>, tools describe <name>"
3122
- )
3123
- );
3124
- }
3125
- } else if (scope === "resources") {
3126
- if (command === "list") {
3127
- const result2 = await session.listAllResources();
3128
- const resources = result2.resources;
3129
- console.log(
3130
- formatInfo(
3131
- `Available resources: ${resources.map((r) => r.uri).join(", ")}`
3132
- )
3133
- );
3134
- } else if (command === "read" && arg) {
3135
- const resource = await session.readResource(arg);
3136
- console.log(formatResourceContent(resource));
3137
- } else {
3138
- console.error(
3139
- formatError(
3140
- "Invalid command. Try: resources list, resources read <uri>"
3141
- )
3142
- );
3143
- }
3144
- } else if (scope === "prompts") {
3145
- if (command === "list") {
3146
- const result2 = await session.listPrompts();
3147
- const prompts = result2.prompts;
3148
- console.log(
3149
- formatInfo(
3150
- `Available prompts: ${prompts.map((p) => p.name).join(", ")}`
3151
- )
3152
- );
3153
- } else if (command === "get" && arg) {
3154
- rl.question(
3155
- "Arguments (JSON, or press Enter for none): ",
3156
- async (argsInput) => {
3157
- try {
3158
- const args = argsInput.trim() ? JSON.parse(argsInput) : {};
3159
- const prompt2 = await session.getPrompt(arg, args);
3160
- console.log(formatPromptMessages(prompt2.messages));
3161
- } catch (error) {
3162
- console.error(formatError(error.message));
3163
- }
3164
- rl.prompt();
3165
- }
3166
- );
3167
- return;
3168
- } else {
3169
- console.error(
3170
- formatError(
3171
- "Invalid command. Try: prompts list, prompts get <name>"
3172
- )
3173
- );
3174
- }
3175
- } else if (scope === "sessions") {
3176
- if (command === "list") {
3177
- await listSessionsCommand();
3178
- } else if (command === "switch" && arg) {
3179
- console.log(
3180
- formatWarning(
3181
- "Session switching in interactive mode will be available in a future version"
3182
- )
3183
- );
3184
- } else {
3185
- console.error(formatError("Invalid command. Try: sessions list"));
3186
- }
3187
- } else {
3188
- console.error(
3189
- formatError(
3190
- "Unknown command. Type a valid scope: tools, resources, prompts, sessions"
3191
- )
3192
- );
3193
- }
3194
- } catch (error) {
3195
- console.error(formatError(error.message));
3196
- }
3197
- rl.prompt();
4087
+ process.exit(1);
4088
+ }
4089
+ }
4090
+ async function stopDeploymentCommand(deploymentId) {
4091
+ try {
4092
+ if (!await isLoggedIn()) {
4093
+ console.log(source_default.red("\u2717 You are not logged in."));
4094
+ console.log(
4095
+ source_default.gray("Run " + source_default.white("mcp-use login") + " to get started.")
4096
+ );
4097
+ process.exit(1);
4098
+ }
4099
+ const api = await McpUseAPI.create();
4100
+ const updated = await api.updateDeployment(deploymentId, {
4101
+ status: "stopped"
3198
4102
  });
3199
- rl.on("close", () => {
3200
- console.log("");
3201
- console.log(formatInfo("Goodbye!"));
3202
- process.exit(0);
4103
+ console.log(source_default.green.bold(`
4104
+ \u2713 Deployment stopped: ${updated.name}
4105
+ `));
4106
+ } catch (error) {
4107
+ console.error(
4108
+ source_default.red.bold("\n\u2717 Failed to stop deployment:"),
4109
+ source_default.red(error instanceof Error ? error.message : "Unknown error")
4110
+ );
4111
+ process.exit(1);
4112
+ }
4113
+ }
4114
+ async function startDeploymentCommand(deploymentId) {
4115
+ try {
4116
+ if (!await isLoggedIn()) {
4117
+ console.log(source_default.red("\u2717 You are not logged in."));
4118
+ console.log(
4119
+ source_default.gray("Run " + source_default.white("mcp-use login") + " to get started.")
4120
+ );
4121
+ process.exit(1);
4122
+ }
4123
+ const api = await McpUseAPI.create();
4124
+ const updated = await api.updateDeployment(deploymentId, {
4125
+ status: "running"
3203
4126
  });
4127
+ console.log(source_default.green.bold(`
4128
+ \u2713 Deployment started: ${updated.name}
4129
+ `));
3204
4130
  } catch (error) {
3205
4131
  console.error(
3206
- formatError(`Failed to start interactive mode: ${error.message}`)
4132
+ source_default.red.bold("\n\u2717 Failed to start deployment:"),
4133
+ source_default.red(error instanceof Error ? error.message : "Unknown error")
3207
4134
  );
3208
4135
  process.exit(1);
3209
4136
  }
3210
4137
  }
3211
- function createClientCommand() {
3212
- const clientCommand = new import_commander.Command("client").description(
3213
- "Interactive MCP client for terminal usage"
4138
+ function createDeploymentsCommand() {
4139
+ const deploymentsCommand = new import_commander2.Command("deployments").description(
4140
+ "Manage cloud deployments"
3214
4141
  );
3215
- 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);
3216
- clientCommand.command("disconnect [session]").description("Disconnect from a session").option("--all", "Disconnect all sessions").action(disconnectCommand);
3217
- const sessionsCommand = new import_commander.Command("sessions").description(
3218
- "Manage CLI sessions"
3219
- );
3220
- sessionsCommand.command("list").description("List all saved sessions").action(listSessionsCommand);
3221
- sessionsCommand.command("switch <name>").description("Switch to a different session").action(switchSessionCommand);
3222
- clientCommand.addCommand(sessionsCommand);
3223
- const toolsCommand = new import_commander.Command("tools").description(
3224
- "Interact with MCP tools"
3225
- );
3226
- toolsCommand.command("list").description("List available tools").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(listToolsCommand);
3227
- 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);
3228
- toolsCommand.command("describe <name>").description("Show tool details and schema").option("--session <name>", "Use specific session").action(describeToolCommand);
3229
- clientCommand.addCommand(toolsCommand);
3230
- const resourcesCommand = new import_commander.Command("resources").description(
3231
- "Interact with MCP resources"
3232
- );
3233
- resourcesCommand.command("list").description("List available resources").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(listResourcesCommand);
3234
- resourcesCommand.command("read <uri>").description("Read a resource by URI").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(readResourceCommand);
3235
- resourcesCommand.command("subscribe <uri>").description("Subscribe to resource updates").option("--session <name>", "Use specific session").action(subscribeResourceCommand);
3236
- resourcesCommand.command("unsubscribe <uri>").description("Unsubscribe from resource updates").option("--session <name>", "Use specific session").action(unsubscribeResourceCommand);
3237
- clientCommand.addCommand(resourcesCommand);
3238
- const promptsCommand = new import_commander.Command("prompts").description(
3239
- "Interact with MCP prompts"
3240
- );
3241
- promptsCommand.command("list").description("List available prompts").option("--session <name>", "Use specific session").option("--json", "Output as JSON").action(listPromptsCommand);
3242
- 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);
3243
- clientCommand.addCommand(promptsCommand);
3244
- clientCommand.command("interactive").description("Start interactive REPL mode").option("--session <name>", "Use specific session").action(interactiveCommand);
3245
- return clientCommand;
4142
+ deploymentsCommand.command("list").alias("ls").description("List all deployments").action(listDeploymentsCommand);
4143
+ deploymentsCommand.command("get").argument("<deployment-id>", "Deployment ID").description("Get deployment details").action(getDeploymentCommand);
4144
+ deploymentsCommand.command("restart").argument("<deployment-id>", "Deployment ID").option("-f, --follow", "Follow deployment logs").description("Restart a deployment").action(restartDeploymentCommand);
4145
+ deploymentsCommand.command("delete").alias("rm").argument("<deployment-id>", "Deployment ID").option("-y, --yes", "Skip confirmation prompt").description("Delete a deployment").action(deleteDeploymentCommand);
4146
+ deploymentsCommand.command("logs").argument("<deployment-id>", "Deployment ID").option("-b, --build", "Show build logs instead of runtime logs").option("-f, --follow", "Stream logs in real-time").description("View deployment logs").action(logsCommand);
4147
+ const envCommand = deploymentsCommand.command("env").description("Manage environment variables");
4148
+ envCommand.command("list").argument("<deployment-id>", "Deployment ID").description("List environment variables").action(listEnvCommand);
4149
+ envCommand.command("set").argument("<deployment-id>", "Deployment ID").argument("<pairs...>", "Environment variables in KEY=VALUE format").description("Set environment variables").action(setEnvCommand);
4150
+ envCommand.command("unset").argument("<deployment-id>", "Deployment ID").argument("<keys...>", "Environment variable keys to remove").description("Unset environment variables").action(unsetEnvCommand);
4151
+ deploymentsCommand.command("stop").argument("<deployment-id>", "Deployment ID").description("Stop a deployment").action(stopDeploymentCommand);
4152
+ deploymentsCommand.command("start").argument("<deployment-id>", "Deployment ID").description("Start a stopped deployment").action(startDeploymentCommand);
4153
+ return deploymentsCommand;
3246
4154
  }
3247
4155
 
3248
4156
  // src/index.ts
3249
- var import_zod = require("zod");
3250
- var program = new import_commander2.Command();
3251
- var packageContent = (0, import_node_fs7.readFileSync)(
3252
- import_node_path5.default.join(__dirname, "../package.json"),
4157
+ var program = new import_commander3.Command();
4158
+ var packageContent = (0, import_node_fs8.readFileSync)(
4159
+ import_node_path6.default.join(__dirname, "../package.json"),
3253
4160
  "utf-8"
3254
4161
  );
3255
4162
  var packageJson = JSON.parse(packageContent);
@@ -3388,7 +4295,7 @@ async function findServerFile(projectPath) {
3388
4295
  const candidates = ["index.ts", "src/index.ts", "server.ts", "src/server.ts"];
3389
4296
  for (const candidate of candidates) {
3390
4297
  try {
3391
- await (0, import_promises5.access)(import_node_path5.default.join(projectPath, candidate));
4298
+ await (0, import_promises5.access)(import_node_path6.default.join(projectPath, candidate));
3392
4299
  return candidate;
3393
4300
  } catch {
3394
4301
  continue;
@@ -3397,9 +4304,9 @@ async function findServerFile(projectPath) {
3397
4304
  throw new Error("No server file found");
3398
4305
  }
3399
4306
  async function buildWidgets(projectPath) {
3400
- const { promises: fs9 } = await import("fs");
4307
+ const { promises: fs10 } = await import("fs");
3401
4308
  const { build } = await import("vite");
3402
- const resourcesDir = import_node_path5.default.join(projectPath, "resources");
4309
+ const resourcesDir = import_node_path6.default.join(projectPath, "resources");
3403
4310
  const mcpUrl = process.env.MCP_URL;
3404
4311
  try {
3405
4312
  await (0, import_promises5.access)(resourcesDir);
@@ -3411,7 +4318,7 @@ async function buildWidgets(projectPath) {
3411
4318
  }
3412
4319
  const entries = [];
3413
4320
  try {
3414
- const files = await fs9.readdir(resourcesDir, { withFileTypes: true });
4321
+ const files = await fs10.readdir(resourcesDir, { withFileTypes: true });
3415
4322
  for (const dirent of files) {
3416
4323
  if (dirent.name.startsWith("._") || dirent.name.startsWith(".DS_Store")) {
3417
4324
  continue;
@@ -3419,12 +4326,12 @@ async function buildWidgets(projectPath) {
3419
4326
  if (dirent.isFile() && (dirent.name.endsWith(".tsx") || dirent.name.endsWith(".ts"))) {
3420
4327
  entries.push({
3421
4328
  name: dirent.name.replace(/\.tsx?$/, ""),
3422
- path: import_node_path5.default.join(resourcesDir, dirent.name)
4329
+ path: import_node_path6.default.join(resourcesDir, dirent.name)
3423
4330
  });
3424
4331
  } else if (dirent.isDirectory()) {
3425
- const widgetPath = import_node_path5.default.join(resourcesDir, dirent.name, "widget.tsx");
4332
+ const widgetPath = import_node_path6.default.join(resourcesDir, dirent.name, "widget.tsx");
3426
4333
  try {
3427
- await fs9.access(widgetPath);
4334
+ await fs10.access(widgetPath);
3428
4335
  entries.push({
3429
4336
  name: dirent.name,
3430
4337
  path: widgetPath
@@ -3444,10 +4351,10 @@ async function buildWidgets(projectPath) {
3444
4351
  console.log(source_default.gray(`Building ${entries.length} widget(s)...`));
3445
4352
  const react = (await import("@vitejs/plugin-react")).default;
3446
4353
  const tailwindcss = (await import("@tailwindcss/vite")).default;
3447
- const packageJsonPath = import_node_path5.default.join(projectPath, "package.json");
4354
+ const packageJsonPath = import_node_path6.default.join(projectPath, "package.json");
3448
4355
  let favicon = "";
3449
4356
  try {
3450
- const pkgContent = await fs9.readFile(packageJsonPath, "utf-8");
4357
+ const pkgContent = await fs10.readFile(packageJsonPath, "utf-8");
3451
4358
  const pkg = JSON.parse(pkgContent);
3452
4359
  favicon = pkg.mcpUse?.favicon || "";
3453
4360
  } catch {
@@ -3457,18 +4364,18 @@ async function buildWidgets(projectPath) {
3457
4364
  const widgetName = entry.name;
3458
4365
  const entryPath = entry.path;
3459
4366
  console.log(source_default.gray(` - Building ${widgetName}...`));
3460
- const tempDir = import_node_path5.default.join(projectPath, ".mcp-use", widgetName);
3461
- await fs9.mkdir(tempDir, { recursive: true });
3462
- const relativeResourcesPath = import_node_path5.default.relative(tempDir, resourcesDir).replace(/\\/g, "/");
3463
- const mcpUsePath = import_node_path5.default.join(projectPath, "node_modules", "mcp-use");
3464
- const relativeMcpUsePath = import_node_path5.default.relative(tempDir, mcpUsePath).replace(/\\/g, "/");
4367
+ const tempDir = import_node_path6.default.join(projectPath, ".mcp-use", widgetName);
4368
+ await fs10.mkdir(tempDir, { recursive: true });
4369
+ const relativeResourcesPath = import_node_path6.default.relative(tempDir, resourcesDir).replace(/\\/g, "/");
4370
+ const mcpUsePath = import_node_path6.default.join(projectPath, "node_modules", "mcp-use");
4371
+ const relativeMcpUsePath = import_node_path6.default.relative(tempDir, mcpUsePath).replace(/\\/g, "/");
3465
4372
  const cssContent = `@import "tailwindcss";
3466
4373
 
3467
4374
  /* Configure Tailwind to scan the resources directory and mcp-use package */
3468
4375
  @source "${relativeResourcesPath}";
3469
4376
  @source "${relativeMcpUsePath}/**/*.{ts,tsx,js,jsx}";
3470
4377
  `;
3471
- await fs9.writeFile(import_node_path5.default.join(tempDir, "styles.css"), cssContent, "utf8");
4378
+ await fs10.writeFile(import_node_path6.default.join(tempDir, "styles.css"), cssContent, "utf8");
3472
4379
  const entryContent = `import React from 'react'
3473
4380
  import { createRoot } from 'react-dom/client'
3474
4381
  import './styles.css'
@@ -3493,9 +4400,9 @@ if (container && Component) {
3493
4400
  <script type="module" src="/entry.tsx"></script>
3494
4401
  </body>
3495
4402
  </html>`;
3496
- await fs9.writeFile(import_node_path5.default.join(tempDir, "entry.tsx"), entryContent, "utf8");
3497
- await fs9.writeFile(import_node_path5.default.join(tempDir, "index.html"), htmlContent, "utf8");
3498
- const outDir = import_node_path5.default.join(
4403
+ await fs10.writeFile(import_node_path6.default.join(tempDir, "entry.tsx"), entryContent, "utf8");
4404
+ await fs10.writeFile(import_node_path6.default.join(tempDir, "index.html"), htmlContent, "utf8");
4405
+ const outDir = import_node_path6.default.join(
3499
4406
  projectPath,
3500
4407
  "dist",
3501
4408
  "resources",
@@ -3505,12 +4412,12 @@ if (container && Component) {
3505
4412
  const baseUrl = mcpUrl ? `${mcpUrl}/${widgetName}/` : `/mcp-use/widgets/${widgetName}/`;
3506
4413
  let widgetMetadata = {};
3507
4414
  try {
3508
- const metadataTempDir = import_node_path5.default.join(
4415
+ const metadataTempDir = import_node_path6.default.join(
3509
4416
  projectPath,
3510
4417
  ".mcp-use",
3511
4418
  `${widgetName}-metadata`
3512
4419
  );
3513
- await fs9.mkdir(metadataTempDir, { recursive: true });
4420
+ await fs10.mkdir(metadataTempDir, { recursive: true });
3514
4421
  const { createServer: createServer2 } = await import("vite");
3515
4422
  const nodeStubsPlugin = {
3516
4423
  name: "node-stubs",
@@ -3540,7 +4447,7 @@ export default PostHog;
3540
4447
  };
3541
4448
  const metadataServer = await createServer2({
3542
4449
  root: metadataTempDir,
3543
- cacheDir: import_node_path5.default.join(metadataTempDir, ".vite-cache"),
4450
+ cacheDir: import_node_path6.default.join(metadataTempDir, ".vite-cache"),
3544
4451
  plugins: [nodeStubsPlugin, tailwindcss(), react()],
3545
4452
  resolve: {
3546
4453
  alias: {
@@ -3625,7 +4532,7 @@ export default PostHog;
3625
4532
  } finally {
3626
4533
  await metadataServer.close();
3627
4534
  try {
3628
- await fs9.rm(metadataTempDir, { recursive: true, force: true });
4535
+ await fs10.rm(metadataTempDir, { recursive: true, force: true });
3629
4536
  } catch {
3630
4537
  }
3631
4538
  }
@@ -3748,7 +4655,7 @@ export default {
3748
4655
  outDir,
3749
4656
  emptyOutDir: true,
3750
4657
  rollupOptions: {
3751
- input: import_node_path5.default.join(tempDir, "index.html"),
4658
+ input: import_node_path6.default.join(tempDir, "index.html"),
3752
4659
  external: (id) => {
3753
4660
  return false;
3754
4661
  }
@@ -3758,8 +4665,8 @@ export default {
3758
4665
  const mcpServerUrl = process.env.MCP_SERVER_URL;
3759
4666
  if (mcpServerUrl) {
3760
4667
  try {
3761
- const htmlPath = import_node_path5.default.join(outDir, "index.html");
3762
- let html = await fs9.readFile(htmlPath, "utf8");
4668
+ const htmlPath = import_node_path6.default.join(outDir, "index.html");
4669
+ let html = await fs10.readFile(htmlPath, "utf8");
3763
4670
  const injectionScript = `<script>window.__getFile = (filename) => { return "${mcpUrl}/${widgetName}/"+filename }; window.__mcpPublicUrl = "${mcpServerUrl}/mcp-use/public"; window.__mcpPublicAssetsUrl = "${mcpUrl}/public";</script>`;
3764
4671
  if (!html.includes("window.__mcpPublicUrl")) {
3765
4672
  html = html.replace(
@@ -3780,7 +4687,7 @@ export default {
3780
4687
  <base href="${mcpServerUrl}">`
3781
4688
  );
3782
4689
  }
3783
- await fs9.writeFile(htmlPath, html, "utf8");
4690
+ await fs10.writeFile(htmlPath, html, "utf8");
3784
4691
  console.log(
3785
4692
  source_default.gray(` \u2192 Injected MCP_SERVER_URL into ${widgetName}`)
3786
4693
  );
@@ -3806,27 +4713,27 @@ export default {
3806
4713
  }
3807
4714
  program.command("build").description("Build TypeScript and MCP UI widgets").option("-p, --path <path>", "Path to project directory", process.cwd()).option("--with-inspector", "Include inspector in production build").action(async (options) => {
3808
4715
  try {
3809
- const projectPath = import_node_path5.default.resolve(options.path);
3810
- const { promises: fs9 } = await import("fs");
4716
+ const projectPath = import_node_path6.default.resolve(options.path);
4717
+ const { promises: fs10 } = await import("fs");
3811
4718
  console.log(source_default.cyan.bold(`mcp-use v${packageJson.version}`));
3812
4719
  const builtWidgets = await buildWidgets(projectPath);
3813
4720
  console.log(source_default.gray("Building TypeScript..."));
3814
4721
  await runCommand("npx", ["tsc"], projectPath);
3815
4722
  console.log(source_default.green("\u2713 TypeScript build complete!"));
3816
- const publicDir = import_node_path5.default.join(projectPath, "public");
4723
+ const publicDir = import_node_path6.default.join(projectPath, "public");
3817
4724
  try {
3818
- await fs9.access(publicDir);
4725
+ await fs10.access(publicDir);
3819
4726
  console.log(source_default.gray("Copying public assets..."));
3820
- await fs9.cp(publicDir, import_node_path5.default.join(projectPath, "dist", "public"), {
4727
+ await fs10.cp(publicDir, import_node_path6.default.join(projectPath, "dist", "public"), {
3821
4728
  recursive: true
3822
4729
  });
3823
4730
  console.log(source_default.green("\u2713 Public assets copied"));
3824
4731
  } catch {
3825
4732
  }
3826
- const manifestPath = import_node_path5.default.join(projectPath, "dist", "mcp-use.json");
4733
+ const manifestPath = import_node_path6.default.join(projectPath, "dist", "mcp-use.json");
3827
4734
  let existingManifest = {};
3828
4735
  try {
3829
- const existingContent = await fs9.readFile(manifestPath, "utf-8");
4736
+ const existingContent = await fs10.readFile(manifestPath, "utf-8");
3830
4737
  existingManifest = JSON.parse(existingContent);
3831
4738
  } catch {
3832
4739
  }
@@ -3846,8 +4753,8 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
3846
4753
  buildId,
3847
4754
  widgets: widgetsData
3848
4755
  };
3849
- await fs9.mkdir(import_node_path5.default.dirname(manifestPath), { recursive: true });
3850
- await fs9.writeFile(
4756
+ await fs10.mkdir(import_node_path6.default.dirname(manifestPath), { recursive: true });
4757
+ await fs10.writeFile(
3851
4758
  manifestPath,
3852
4759
  JSON.stringify(manifest, null, 2),
3853
4760
  "utf8"
@@ -3868,7 +4775,7 @@ program.command("build").description("Build TypeScript and MCP UI widgets").opti
3868
4775
  });
3869
4776
  program.command("dev").description("Run development server with auto-reload and inspector").option("-p, --path <path>", "Path to project directory", process.cwd()).option("--port <port>", "Server port", "3000").option("--host <host>", "Server host", "localhost").option("--no-open", "Do not auto-open inspector").action(async (options) => {
3870
4777
  try {
3871
- const projectPath = import_node_path5.default.resolve(options.path);
4778
+ const projectPath = import_node_path6.default.resolve(options.path);
3872
4779
  let port = parseInt(options.port, 10);
3873
4780
  const host = options.host;
3874
4781
  console.log(source_default.cyan.bold(`mcp-use v${packageJson.version}`));
@@ -3947,8 +4854,9 @@ program.command("dev").description("Run development server with auto-reload and
3947
4854
  });
3948
4855
  program.command("start").description("Start production server").option("-p, --path <path>", "Path to project directory", process.cwd()).option("--port <port>", "Server port", "3000").option("--tunnel", "Expose server through a tunnel").action(async (options) => {
3949
4856
  try {
3950
- const projectPath = import_node_path5.default.resolve(options.path);
3951
- const port = parseInt(options.port, 10);
4857
+ const projectPath = import_node_path6.default.resolve(options.path);
4858
+ const portFlagProvided = process.argv.includes("--port") || process.argv.includes("-p") || process.argv.some((arg) => arg.startsWith("--port=")) || process.argv.some((arg) => arg.startsWith("-p="));
4859
+ const port = portFlagProvided ? parseInt(options.port, 10) : parseInt(process.env.PORT || options.port || "3000", 10);
3952
4860
  console.log(
3953
4861
  `\x1B[36m\x1B[1mmcp-use\x1B[0m \x1B[90mVersion: ${packageJson.version}\x1B[0m
3954
4862
  `
@@ -3958,7 +4866,7 @@ program.command("start").description("Start production server").option("-p, --pa
3958
4866
  let tunnelSubdomain = void 0;
3959
4867
  if (options.tunnel) {
3960
4868
  try {
3961
- const manifestPath = import_node_path5.default.join(projectPath, "dist", "mcp-use.json");
4869
+ const manifestPath = import_node_path6.default.join(projectPath, "dist", "mcp-use.json");
3962
4870
  let existingSubdomain;
3963
4871
  try {
3964
4872
  const manifestContent = await (0, import_promises5.readFile)(manifestPath, "utf-8");
@@ -3992,7 +4900,7 @@ program.command("start").description("Start production server").option("-p, --pa
3992
4900
  manifest.tunnel = {};
3993
4901
  }
3994
4902
  manifest.tunnel.subdomain = subdomain;
3995
- await (0, import_promises5.mkdir)(import_node_path5.default.dirname(manifestPath), { recursive: true });
4903
+ await (0, import_promises5.mkdir)(import_node_path6.default.dirname(manifestPath), { recursive: true });
3996
4904
  await (0, import_promises5.writeFile)(
3997
4905
  manifestPath,
3998
4906
  JSON.stringify(manifest, null, 2),
@@ -4012,7 +4920,7 @@ program.command("start").description("Start production server").option("-p, --pa
4012
4920
  }
4013
4921
  let serverFile = "dist/index.js";
4014
4922
  try {
4015
- await (0, import_promises5.access)(import_node_path5.default.join(projectPath, serverFile));
4923
+ await (0, import_promises5.access)(import_node_path6.default.join(projectPath, serverFile));
4016
4924
  } catch {
4017
4925
  serverFile = "dist/server.js";
4018
4926
  }
@@ -4098,15 +5006,25 @@ program.command("whoami").description("Show current user information").action(as
4098
5006
  program.command("deploy").description("Deploy MCP server to mcp-use cloud").option("--open", "Open deployment in browser after successful deploy").option("--name <name>", "Custom deployment name").option("--port <port>", "Server port", "3000").option("--runtime <runtime>", "Runtime (node or python)").option(
4099
5007
  "--from-source",
4100
5008
  "Deploy from local source code (even for GitHub repos)"
4101
- ).action(async (options) => {
5009
+ ).option(
5010
+ "--new",
5011
+ "Force creation of new deployment instead of reusing linked deployment"
5012
+ ).option(
5013
+ "--env <key=value...>",
5014
+ "Environment variables (can be used multiple times)"
5015
+ ).option("--env-file <path>", "Path to .env file with environment variables").action(async (options) => {
4102
5016
  await deployCommand({
4103
5017
  open: options.open,
4104
5018
  name: options.name,
4105
5019
  port: options.port ? parseInt(options.port, 10) : void 0,
4106
5020
  runtime: options.runtime,
4107
- fromSource: options.fromSource
5021
+ fromSource: options.fromSource,
5022
+ new: options.new,
5023
+ env: options.env,
5024
+ envFile: options.envFile
4108
5025
  });
4109
5026
  });
4110
5027
  program.addCommand(createClientCommand());
5028
+ program.addCommand(createDeploymentsCommand());
4111
5029
  program.parse();
4112
5030
  //# sourceMappingURL=index.cjs.map