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