@mcp-use/cli 3.5.2-canary.1 → 3.5.2-canary.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/commands/client.d.ts.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/index.cjs +125 -101
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +125 -101
- package/dist/index.js.map +1 -1
- package/dist/utils/api.d.ts +16 -18
- package/dist/utils/api.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1136,7 +1136,7 @@ import os3 from "os";
|
|
|
1136
1136
|
import path3 from "path";
|
|
1137
1137
|
var CONFIG_DIR = path3.join(os3.homedir(), ".mcp-use");
|
|
1138
1138
|
var CONFIG_FILE = path3.join(CONFIG_DIR, "config.json");
|
|
1139
|
-
var DEFAULT_API_URL = process.env.MCP_API_URL ? process.env.MCP_API_URL.replace(/\/api\/v1$/, "") + "/api/v1" : "https://cloud.
|
|
1139
|
+
var DEFAULT_API_URL = process.env.MCP_API_URL ? process.env.MCP_API_URL.replace(/\/api\/v1$/, "") + "/api/v1" : "https://cloud.manufact.com/api/v1";
|
|
1140
1140
|
var DEFAULT_WEB_URL = process.env.MCP_WEB_URL ? process.env.MCP_WEB_URL : "https://manufact.com";
|
|
1141
1141
|
async function ensureConfigDir() {
|
|
1142
1142
|
try {
|
|
@@ -1550,37 +1550,51 @@ var McpUseAPI = class _McpUseAPI {
|
|
|
1550
1550
|
}))
|
|
1551
1551
|
};
|
|
1552
1552
|
}
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1553
|
+
/**
|
|
1554
|
+
* Returns true if the GitHub App can access `${owner}/${repo}` via any of the
|
|
1555
|
+
* organization's installations.
|
|
1556
|
+
*
|
|
1557
|
+
* An organization can have multiple GitHub installations (e.g. a personal
|
|
1558
|
+
* account and one or more GitHub orgs), so we check across all of them.
|
|
1559
|
+
*
|
|
1560
|
+
* Each check is a single authoritative backend call (`repos.get` with the
|
|
1561
|
+
* installation token) rather than listing repos. The old listing approach
|
|
1562
|
+
* only returned the first page — so a repo on a later page was wrongly
|
|
1563
|
+
* reported inaccessible — and fully paginating it hung on very large orgs.
|
|
1564
|
+
* We try the installation whose account matches the repo owner first to
|
|
1565
|
+
* minimize GitHub calls.
|
|
1566
|
+
*/
|
|
1567
|
+
async checkGitHubRepoAccess(owner, repo) {
|
|
1568
|
+
const status = await this.getGitHubConnectionStatus();
|
|
1569
|
+
const installations = status.installations ?? [];
|
|
1570
|
+
if (installations.length === 0) return false;
|
|
1571
|
+
const ownerLower = owner.toLowerCase();
|
|
1572
|
+
const ordered = [...installations].sort((a, b) => {
|
|
1573
|
+
const aMatch = a.account_login.toLowerCase() === ownerLower ? 0 : 1;
|
|
1574
|
+
const bMatch = b.account_login.toLowerCase() === ownerLower ? 0 : 1;
|
|
1575
|
+
return aMatch - bMatch;
|
|
1576
|
+
});
|
|
1577
|
+
for (const installation of ordered) {
|
|
1578
|
+
const hasAccess = await this.installationCanAccessRepo(
|
|
1579
|
+
installation.installation_id,
|
|
1580
|
+
owner,
|
|
1581
|
+
repo
|
|
1582
|
+
);
|
|
1583
|
+
if (hasAccess) return true;
|
|
1584
|
+
}
|
|
1585
|
+
return false;
|
|
1586
|
+
}
|
|
1587
|
+
async installationCanAccessRepo(installationId, owner, repo) {
|
|
1588
|
+
try {
|
|
1589
|
+
const resp = await this.request(
|
|
1590
|
+
`/github/installations/${installationId}/repos/${encodeURIComponent(
|
|
1591
|
+
owner
|
|
1592
|
+
)}/${encodeURIComponent(repo)}/access`
|
|
1593
|
+
);
|
|
1594
|
+
return resp.hasAccess;
|
|
1595
|
+
} catch {
|
|
1596
|
+
return false;
|
|
1558
1597
|
}
|
|
1559
|
-
const inst = installResp.installations[0];
|
|
1560
|
-
const repoLists = await Promise.all(
|
|
1561
|
-
installResp.installations.map(async (installation) => {
|
|
1562
|
-
try {
|
|
1563
|
-
const reposResp = await this.request(`/github/installations/${installation.installationId}/repos`);
|
|
1564
|
-
return reposResp.repos;
|
|
1565
|
-
} catch {
|
|
1566
|
-
return [];
|
|
1567
|
-
}
|
|
1568
|
-
})
|
|
1569
|
-
);
|
|
1570
|
-
return {
|
|
1571
|
-
user: {
|
|
1572
|
-
login: inst.account?.login ?? "",
|
|
1573
|
-
id: 0,
|
|
1574
|
-
avatar_url: inst.account?.avatar_url ?? ""
|
|
1575
|
-
},
|
|
1576
|
-
repos: repoLists.flat().map((r) => ({
|
|
1577
|
-
id: r.id,
|
|
1578
|
-
name: r.name,
|
|
1579
|
-
full_name: r.fullName,
|
|
1580
|
-
private: r.private,
|
|
1581
|
-
owner: { login: r.fullName.split("/")[0] ?? "" }
|
|
1582
|
-
}))
|
|
1583
|
-
};
|
|
1584
1598
|
}
|
|
1585
1599
|
async getGitHubAppName() {
|
|
1586
1600
|
if (process.env.MCP_GITHUB_APP_NAME) return process.env.MCP_GITHUB_APP_NAME;
|
|
@@ -4017,6 +4031,71 @@ async function describeToolCommand(name, toolName) {
|
|
|
4017
4031
|
}
|
|
4018
4032
|
await cleanupAndExit(0);
|
|
4019
4033
|
}
|
|
4034
|
+
async function processToolScreenshot(session, toolName, args, callResult, options) {
|
|
4035
|
+
const toolWithMeta = session.tools.find((t) => t.name === toolName);
|
|
4036
|
+
const resourceUri = detectToolResourceUri(toolWithMeta);
|
|
4037
|
+
const wantsScreenshot = options?.screenshot === true || options?.screenshotOutput !== void 0 || options?.screenshotDeviceScaleFactor !== void 0;
|
|
4038
|
+
let screenshot = null;
|
|
4039
|
+
let screenshotError = null;
|
|
4040
|
+
let widgetHintUri = null;
|
|
4041
|
+
if (resourceUri) {
|
|
4042
|
+
if (wantsScreenshot) {
|
|
4043
|
+
console.error(
|
|
4044
|
+
formatInfo(`Capturing widget screenshot (${resourceUri})...`)
|
|
4045
|
+
);
|
|
4046
|
+
try {
|
|
4047
|
+
const screenshotOpts = {};
|
|
4048
|
+
if (options?.screenshotOutput) {
|
|
4049
|
+
screenshotOpts.output = options.screenshotOutput;
|
|
4050
|
+
}
|
|
4051
|
+
if (options?.screenshotDeviceScaleFactor) {
|
|
4052
|
+
screenshotOpts.deviceScaleFactor = parseDeviceScaleFactor(
|
|
4053
|
+
options.screenshotDeviceScaleFactor
|
|
4054
|
+
);
|
|
4055
|
+
}
|
|
4056
|
+
const shot = await captureToolScreenshot(
|
|
4057
|
+
{
|
|
4058
|
+
session,
|
|
4059
|
+
toolName,
|
|
4060
|
+
toolArgs: args,
|
|
4061
|
+
toolOutput: callResult,
|
|
4062
|
+
resourceUri
|
|
4063
|
+
},
|
|
4064
|
+
screenshotOpts
|
|
4065
|
+
);
|
|
4066
|
+
screenshot = {
|
|
4067
|
+
path: shot.outputPath,
|
|
4068
|
+
width: shot.width,
|
|
4069
|
+
height: shot.height,
|
|
4070
|
+
view: shot.view
|
|
4071
|
+
};
|
|
4072
|
+
} catch (err) {
|
|
4073
|
+
screenshotError = err?.message ?? String(err);
|
|
4074
|
+
}
|
|
4075
|
+
} else {
|
|
4076
|
+
widgetHintUri = resourceUri;
|
|
4077
|
+
}
|
|
4078
|
+
}
|
|
4079
|
+
if (screenshot) {
|
|
4080
|
+
console.error(
|
|
4081
|
+
formatSuccess(
|
|
4082
|
+
`Saved widget screenshot: ${screenshot.path} (${screenshot.width}\xD7${screenshot.height})`
|
|
4083
|
+
)
|
|
4084
|
+
);
|
|
4085
|
+
}
|
|
4086
|
+
if (screenshotError) {
|
|
4087
|
+
console.error(
|
|
4088
|
+
formatWarning(`Skipped widget screenshot: ${screenshotError}`)
|
|
4089
|
+
);
|
|
4090
|
+
}
|
|
4091
|
+
if (widgetHintUri) {
|
|
4092
|
+
console.error(
|
|
4093
|
+
formatInfo(
|
|
4094
|
+
`This tool renders a widget (${widgetHintUri}). Re-run with --screenshot to save a PNG of it.`
|
|
4095
|
+
)
|
|
4096
|
+
);
|
|
4097
|
+
}
|
|
4098
|
+
}
|
|
4020
4099
|
async function callToolCommand(name, toolName, argsList, options) {
|
|
4021
4100
|
try {
|
|
4022
4101
|
const result = await getOrRestoreSession(name);
|
|
@@ -4066,74 +4145,12 @@ async function callToolCommand(name, toolName, argsList, options) {
|
|
|
4066
4145
|
const callResult = await session.callTool(toolName, args, {
|
|
4067
4146
|
timeout: options?.timeout
|
|
4068
4147
|
});
|
|
4069
|
-
|
|
4070
|
-
const resourceUri = detectToolResourceUri(toolWithMeta);
|
|
4071
|
-
const wantsScreenshot = options?.screenshot === true || options?.screenshotOutput !== void 0 || options?.screenshotDeviceScaleFactor !== void 0;
|
|
4072
|
-
let screenshot = null;
|
|
4073
|
-
let screenshotError = null;
|
|
4074
|
-
let widgetHintUri = null;
|
|
4075
|
-
if (resourceUri) {
|
|
4076
|
-
if (wantsScreenshot) {
|
|
4077
|
-
console.error(
|
|
4078
|
-
formatInfo(`Capturing widget screenshot (${resourceUri})...`)
|
|
4079
|
-
);
|
|
4080
|
-
try {
|
|
4081
|
-
const screenshotOpts = {};
|
|
4082
|
-
if (options?.screenshotOutput) {
|
|
4083
|
-
screenshotOpts.output = options.screenshotOutput;
|
|
4084
|
-
}
|
|
4085
|
-
if (options?.screenshotDeviceScaleFactor) {
|
|
4086
|
-
screenshotOpts.deviceScaleFactor = parseDeviceScaleFactor(
|
|
4087
|
-
options.screenshotDeviceScaleFactor
|
|
4088
|
-
);
|
|
4089
|
-
}
|
|
4090
|
-
const shot = await captureToolScreenshot(
|
|
4091
|
-
{
|
|
4092
|
-
session,
|
|
4093
|
-
toolName,
|
|
4094
|
-
toolArgs: args,
|
|
4095
|
-
toolOutput: callResult,
|
|
4096
|
-
resourceUri
|
|
4097
|
-
},
|
|
4098
|
-
screenshotOpts
|
|
4099
|
-
);
|
|
4100
|
-
screenshot = {
|
|
4101
|
-
path: shot.outputPath,
|
|
4102
|
-
width: shot.width,
|
|
4103
|
-
height: shot.height,
|
|
4104
|
-
view: shot.view
|
|
4105
|
-
};
|
|
4106
|
-
} catch (err) {
|
|
4107
|
-
screenshotError = err?.message ?? String(err);
|
|
4108
|
-
}
|
|
4109
|
-
} else {
|
|
4110
|
-
widgetHintUri = resourceUri;
|
|
4111
|
-
}
|
|
4112
|
-
}
|
|
4148
|
+
await processToolScreenshot(session, toolName, args, callResult, options);
|
|
4113
4149
|
if (options?.json) {
|
|
4114
4150
|
console.log(formatJson(callResult));
|
|
4115
4151
|
} else {
|
|
4116
4152
|
console.log(formatToolCall(callResult));
|
|
4117
4153
|
}
|
|
4118
|
-
if (screenshot) {
|
|
4119
|
-
console.error(
|
|
4120
|
-
formatSuccess(
|
|
4121
|
-
`Saved widget screenshot: ${screenshot.path} (${screenshot.width}\xD7${screenshot.height})`
|
|
4122
|
-
)
|
|
4123
|
-
);
|
|
4124
|
-
}
|
|
4125
|
-
if (screenshotError) {
|
|
4126
|
-
console.error(
|
|
4127
|
-
formatWarning(`Skipped widget screenshot: ${screenshotError}`)
|
|
4128
|
-
);
|
|
4129
|
-
}
|
|
4130
|
-
if (widgetHintUri) {
|
|
4131
|
-
console.error(
|
|
4132
|
-
formatInfo(
|
|
4133
|
-
`This tool renders a widget (${widgetHintUri}). Re-run with --screenshot to save a PNG of it.`
|
|
4134
|
-
)
|
|
4135
|
-
);
|
|
4136
|
-
}
|
|
4137
4154
|
if (callResult.isError) {
|
|
4138
4155
|
await cleanupAndExit(1);
|
|
4139
4156
|
}
|
|
@@ -4225,6 +4242,14 @@ async function subscribeResourceCommand(name, uri) {
|
|
|
4225
4242
|
}
|
|
4226
4243
|
});
|
|
4227
4244
|
console.log(formatInfo("Listening for updates... (Press Ctrl+C to stop)"));
|
|
4245
|
+
process.once("SIGINT", async () => {
|
|
4246
|
+
console.log(formatInfo("\nUnsubscribing and shutting down..."));
|
|
4247
|
+
try {
|
|
4248
|
+
await session.unsubscribeFromResource(uri);
|
|
4249
|
+
} catch (e) {
|
|
4250
|
+
}
|
|
4251
|
+
await cleanupAndExit(0);
|
|
4252
|
+
});
|
|
4228
4253
|
await new Promise(() => {
|
|
4229
4254
|
});
|
|
4230
4255
|
} catch (error) {
|
|
@@ -4355,7 +4380,7 @@ async function interactiveCommand(name) {
|
|
|
4355
4380
|
console.log(source_default.gray(" tools list - List available tools"));
|
|
4356
4381
|
console.log(
|
|
4357
4382
|
source_default.gray(
|
|
4358
|
-
" tools call <name>
|
|
4383
|
+
" tools call <name> [--screenshot] - Call a tool (will prompt for args)"
|
|
4359
4384
|
)
|
|
4360
4385
|
);
|
|
4361
4386
|
console.log(source_default.gray(" tools describe <name> - Show tool details"));
|
|
@@ -4402,6 +4427,7 @@ async function interactiveCommand(name) {
|
|
|
4402
4427
|
)
|
|
4403
4428
|
);
|
|
4404
4429
|
} else if (command === "call" && arg) {
|
|
4430
|
+
const wantsScreenshot = parts.includes("--screenshot");
|
|
4405
4431
|
rl.question(
|
|
4406
4432
|
"Arguments (JSON, or press Enter for none): ",
|
|
4407
4433
|
async (argsInput) => {
|
|
@@ -4409,6 +4435,9 @@ async function interactiveCommand(name) {
|
|
|
4409
4435
|
const args = argsInput.trim() ? JSON.parse(argsInput) : {};
|
|
4410
4436
|
const result2 = await session.callTool(arg, args);
|
|
4411
4437
|
console.log(formatToolCall(result2));
|
|
4438
|
+
await processToolScreenshot(session, arg, args, result2, {
|
|
4439
|
+
screenshot: wantsScreenshot
|
|
4440
|
+
});
|
|
4412
4441
|
} catch (error) {
|
|
4413
4442
|
console.error(formatError(error.message));
|
|
4414
4443
|
}
|
|
@@ -5236,12 +5265,7 @@ async function getGitHubConnectionStatusWith401Retry(api, options, orgIdToRestor
|
|
|
5236
5265
|
throw new Error("Unreachable");
|
|
5237
5266
|
}
|
|
5238
5267
|
async function checkRepoAccess(api, owner, repo) {
|
|
5239
|
-
|
|
5240
|
-
const resp = await api.getGitHubRepos(true);
|
|
5241
|
-
return resp.repos.some((r) => r.full_name === `${owner}/${repo}`);
|
|
5242
|
-
} catch {
|
|
5243
|
-
return false;
|
|
5244
|
-
}
|
|
5268
|
+
return api.checkGitHubRepoAccess(owner, repo);
|
|
5245
5269
|
}
|
|
5246
5270
|
async function promptGitHubInstallation(api, reason, repoName, opts) {
|
|
5247
5271
|
const yes = !!opts?.yes;
|