@mcp-use/cli 2.6.1 → 2.7.0-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/deploy.d.ts +3 -0
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deployments.d.ts +6 -0
- package/dist/commands/deployments.d.ts.map +1 -0
- package/dist/index.cjs +2350 -1433
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2348 -1431
- package/dist/index.js.map +1 -1
- package/dist/utils/api.d.ts +40 -0
- package/dist/utils/api.d.ts.map +1 -1
- package/dist/utils/format.d.ts +4 -0
- package/dist/utils/format.d.ts.map +1 -1
- package/dist/utils/project-link.d.ts +12 -0
- package/dist/utils/project-link.d.ts.map +1 -0
- package/package.json +3 -3
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
|
|
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
|
|
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 (
|
|
684
|
-
if (/^[a-z]+:\/\//i.test(
|
|
685
|
-
return
|
|
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",
|
|
688
|
+
const { stdout } = await execFile2("wslpath", ["-aw", path7], { encoding: "utf8" });
|
|
689
689
|
return stdout.trim();
|
|
690
690
|
} catch {
|
|
691
|
-
return
|
|
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
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
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/
|
|
1685
|
-
import {
|
|
1686
|
-
import
|
|
1687
|
-
import
|
|
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/
|
|
1692
|
-
import {
|
|
1693
|
-
import {
|
|
1694
|
-
|
|
1695
|
-
|
|
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
|
-
|
|
1698
|
-
|
|
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
|
|
1704
|
-
|
|
1705
|
-
|
|
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
|
|
1708
|
-
|
|
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
|
|
1711
|
-
const
|
|
1712
|
-
|
|
1713
|
-
|
|
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
|
-
|
|
1719
|
-
|
|
1838
|
+
name: storage.activeSession,
|
|
1839
|
+
config: storage.sessions[storage.activeSession]
|
|
1720
1840
|
};
|
|
1721
1841
|
}
|
|
1722
|
-
async function
|
|
1723
|
-
|
|
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
|
|
1732
|
-
const
|
|
1733
|
-
if (!
|
|
1734
|
-
|
|
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
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
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
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
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/
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
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
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
const
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
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
|
-
|
|
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
|
|
1918
|
+
return JSON.stringify(data);
|
|
1798
1919
|
}
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
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
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
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
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
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
|
-
|
|
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
|
|
1902
|
-
if (
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
const
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
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
|
-
|
|
1918
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1960
|
-
|
|
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
|
-
|
|
1963
|
-
const
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
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
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
`)
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
`)
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
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
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
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
|
-
|
|
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
|
|
2160
|
+
async function connectCommand(urlOrCommand, options) {
|
|
2056
2161
|
try {
|
|
2057
|
-
const
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2066
|
-
const
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
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
|
-
|
|
2083
|
-
if (
|
|
2084
|
-
|
|
2085
|
-
|
|
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
|
-
|
|
2208
|
+
formatKeyValue({
|
|
2209
|
+
Name: serverInfo.name,
|
|
2210
|
+
Version: serverInfo.version || "unknown"
|
|
2211
|
+
})
|
|
2098
2212
|
);
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
const
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
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
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
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
|
-
|
|
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
|
|
2273
|
-
if (
|
|
2274
|
-
|
|
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
|
-
|
|
2277
|
-
|
|
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
|
-
|
|
2294
|
+
console.error(formatError(`Failed to list sessions: ${error.message}`));
|
|
2295
|
+
process.exit(1);
|
|
2280
2296
|
}
|
|
2281
2297
|
}
|
|
2282
|
-
async function
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
}
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
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
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
return
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
}
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
}
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
}
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
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
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
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
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
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
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
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
|
-
|
|
2418
|
-
|
|
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
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
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 (
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
lines.push("");
|
|
2425
|
+
if (resources.length === 0) {
|
|
2426
|
+
console.log(formatInfo("No resources available"));
|
|
2427
|
+
return;
|
|
2450
2428
|
}
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
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
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
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
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
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
|
|
2518
|
-
|
|
2519
|
-
|
|
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
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
const
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
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
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
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
|
|
2574
|
-
if (
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
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.
|
|
2587
|
-
|
|
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
|
|
2595
|
-
|
|
2567
|
+
console.error(formatError(`Failed to get prompt: ${error.message}`));
|
|
2568
|
+
process.exit(1);
|
|
2596
2569
|
}
|
|
2597
2570
|
}
|
|
2598
|
-
async function
|
|
2571
|
+
async function interactiveCommand(options) {
|
|
2599
2572
|
try {
|
|
2600
|
-
const
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
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
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
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
|
-
|
|
3661
|
+
function formatId(id) {
|
|
3662
|
+
return id;
|
|
3663
|
+
}
|
|
3664
|
+
async function listDeploymentsCommand() {
|
|
2702
3665
|
try {
|
|
2703
|
-
|
|
2704
|
-
|
|
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
|
-
|
|
3669
|
+
source_default.gray("Run " + source_default.white("mcp-use login") + " to get started.")
|
|
2708
3670
|
);
|
|
2709
|
-
|
|
3671
|
+
process.exit(1);
|
|
2710
3672
|
}
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
const
|
|
2714
|
-
|
|
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
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
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
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
])
|
|
3688
|
+
source_default.cyan.bold(`
|
|
3689
|
+
\u{1F4E6} Deployments (${sortedDeployments.length})
|
|
3690
|
+
`)
|
|
2770
3691
|
);
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
console.
|
|
2785
|
-
|
|
2786
|
-
|
|
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(
|
|
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
|
|
3718
|
+
async function getDeploymentCommand(deploymentId) {
|
|
2853
3719
|
try {
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
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
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
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
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
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(
|
|
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
|
|
3792
|
+
async function restartDeploymentCommand(deploymentId, options) {
|
|
2887
3793
|
try {
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
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(
|
|
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(
|
|
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
|
|
3852
|
+
async function deleteDeploymentCommand(deploymentId, options) {
|
|
2904
3853
|
try {
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
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
|
-
|
|
2918
|
-
|
|
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
|
-
|
|
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
|
|
3895
|
+
async function logsCommand(deploymentId, options) {
|
|
2928
3896
|
try {
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
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
|
-
|
|
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
|
|
3956
|
+
async function listEnvCommand(deploymentId) {
|
|
2942
3957
|
try {
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
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
|
-
|
|
2957
|
-
|
|
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
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
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(
|
|
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
|
|
3992
|
+
async function setEnvCommand(deploymentId, envPairs) {
|
|
2974
3993
|
try {
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
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
|
-
|
|
2988
|
-
const
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
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(
|
|
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
|
|
4037
|
+
async function unsetEnvCommand(deploymentId, keys) {
|
|
3010
4038
|
try {
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
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.
|
|
4056
|
+
source_default.green.bold(`
|
|
4057
|
+
\u2713 Environment variables removed: ${updated.name}
|
|
4058
|
+
`)
|
|
3037
4059
|
);
|
|
3038
|
-
|
|
3039
|
-
source_default.gray(
|
|
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
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
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
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
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
|
-
|
|
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
|
|
3194
|
-
const
|
|
3195
|
-
"
|
|
4120
|
+
function createDeploymentsCommand() {
|
|
4121
|
+
const deploymentsCommand = new Command2("deployments").description(
|
|
4122
|
+
"Manage cloud deployments"
|
|
3196
4123
|
);
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
);
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
);
|
|
3208
|
-
|
|
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
|
-
|
|
3232
|
-
var program = new Command2();
|
|
4139
|
+
var program = new Command3();
|
|
3233
4140
|
var packageContent = readFileSync(
|
|
3234
|
-
|
|
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(
|
|
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:
|
|
4289
|
+
const { promises: fs10 } = await import("fs");
|
|
3383
4290
|
const { build } = await import("vite");
|
|
3384
|
-
const resourcesDir =
|
|
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
|
|
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:
|
|
4311
|
+
path: path6.join(resourcesDir, dirent.name)
|
|
3405
4312
|
});
|
|
3406
4313
|
} else if (dirent.isDirectory()) {
|
|
3407
|
-
const widgetPath =
|
|
4314
|
+
const widgetPath = path6.join(resourcesDir, dirent.name, "widget.tsx");
|
|
3408
4315
|
try {
|
|
3409
|
-
await
|
|
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 =
|
|
4336
|
+
const packageJsonPath = path6.join(projectPath, "package.json");
|
|
3430
4337
|
let favicon = "";
|
|
3431
4338
|
try {
|
|
3432
|
-
const pkgContent = await
|
|
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 =
|
|
3443
|
-
await
|
|
3444
|
-
const relativeResourcesPath =
|
|
3445
|
-
const mcpUsePath =
|
|
3446
|
-
const relativeMcpUsePath =
|
|
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
|
|
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
|
|
3479
|
-
await
|
|
3480
|
-
const outDir =
|
|
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 =
|
|
4397
|
+
const metadataTempDir = path6.join(
|
|
3491
4398
|
projectPath,
|
|
3492
4399
|
".mcp-use",
|
|
3493
4400
|
`${widgetName}-metadata`
|
|
3494
4401
|
);
|
|
3495
|
-
await
|
|
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:
|
|
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
|
|
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:
|
|
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 =
|
|
3744
|
-
let html = await
|
|
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
|
|
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 =
|
|
3792
|
-
const { promises:
|
|
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 =
|
|
4705
|
+
const publicDir = path6.join(projectPath, "public");
|
|
3799
4706
|
try {
|
|
3800
|
-
await
|
|
4707
|
+
await fs10.access(publicDir);
|
|
3801
4708
|
console.log(source_default.gray("Copying public assets..."));
|
|
3802
|
-
await
|
|
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 =
|
|
4715
|
+
const manifestPath = path6.join(projectPath, "dist", "mcp-use.json");
|
|
3809
4716
|
let existingManifest = {};
|
|
3810
4717
|
try {
|
|
3811
|
-
const existingContent = await
|
|
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
|
|
3832
|
-
await
|
|
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 =
|
|
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,7 +4836,7 @@ 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 =
|
|
4839
|
+
const projectPath = path6.resolve(options.path);
|
|
3933
4840
|
const port = parseInt(options.port, 10);
|
|
3934
4841
|
console.log(
|
|
3935
4842
|
`\x1B[36m\x1B[1mmcp-use\x1B[0m \x1B[90mVersion: ${packageJson.version}\x1B[0m
|
|
@@ -3940,7 +4847,7 @@ program.command("start").description("Start production server").option("-p, --pa
|
|
|
3940
4847
|
let tunnelSubdomain = void 0;
|
|
3941
4848
|
if (options.tunnel) {
|
|
3942
4849
|
try {
|
|
3943
|
-
const manifestPath =
|
|
4850
|
+
const manifestPath = path6.join(projectPath, "dist", "mcp-use.json");
|
|
3944
4851
|
let existingSubdomain;
|
|
3945
4852
|
try {
|
|
3946
4853
|
const manifestContent = await readFile2(manifestPath, "utf-8");
|
|
@@ -3974,7 +4881,7 @@ program.command("start").description("Start production server").option("-p, --pa
|
|
|
3974
4881
|
manifest.tunnel = {};
|
|
3975
4882
|
}
|
|
3976
4883
|
manifest.tunnel.subdomain = subdomain;
|
|
3977
|
-
await mkdir2(
|
|
4884
|
+
await mkdir2(path6.dirname(manifestPath), { recursive: true });
|
|
3978
4885
|
await writeFile2(
|
|
3979
4886
|
manifestPath,
|
|
3980
4887
|
JSON.stringify(manifest, null, 2),
|
|
@@ -3994,7 +4901,7 @@ program.command("start").description("Start production server").option("-p, --pa
|
|
|
3994
4901
|
}
|
|
3995
4902
|
let serverFile = "dist/index.js";
|
|
3996
4903
|
try {
|
|
3997
|
-
await access(
|
|
4904
|
+
await access(path6.join(projectPath, serverFile));
|
|
3998
4905
|
} catch {
|
|
3999
4906
|
serverFile = "dist/server.js";
|
|
4000
4907
|
}
|
|
@@ -4080,15 +4987,25 @@ program.command("whoami").description("Show current user information").action(as
|
|
|
4080
4987
|
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
4988
|
"--from-source",
|
|
4082
4989
|
"Deploy from local source code (even for GitHub repos)"
|
|
4083
|
-
).
|
|
4990
|
+
).option(
|
|
4991
|
+
"--new",
|
|
4992
|
+
"Force creation of new deployment instead of reusing linked deployment"
|
|
4993
|
+
).option(
|
|
4994
|
+
"--env <key=value...>",
|
|
4995
|
+
"Environment variables (can be used multiple times)"
|
|
4996
|
+
).option("--env-file <path>", "Path to .env file with environment variables").action(async (options) => {
|
|
4084
4997
|
await deployCommand({
|
|
4085
4998
|
open: options.open,
|
|
4086
4999
|
name: options.name,
|
|
4087
5000
|
port: options.port ? parseInt(options.port, 10) : void 0,
|
|
4088
5001
|
runtime: options.runtime,
|
|
4089
|
-
fromSource: options.fromSource
|
|
5002
|
+
fromSource: options.fromSource,
|
|
5003
|
+
new: options.new,
|
|
5004
|
+
env: options.env,
|
|
5005
|
+
envFile: options.envFile
|
|
4090
5006
|
});
|
|
4091
5007
|
});
|
|
4092
5008
|
program.addCommand(createClientCommand());
|
|
5009
|
+
program.addCommand(createDeploymentsCommand());
|
|
4093
5010
|
program.parse();
|
|
4094
5011
|
//# sourceMappingURL=index.js.map
|