@drop2run/mcp 1.0.0 → 1.1.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/index.js +44 -10
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -87,6 +87,14 @@ function missingCredentialsMessage(surface = "cli") {
|
|
|
87
87
|
"The token is shown once when it is created and cannot be recovered afterwards."
|
|
88
88
|
].join("\n");
|
|
89
89
|
}
|
|
90
|
+
function problemCode(type, status) {
|
|
91
|
+
return typeof type === "string" && type !== "" && !/^[a-z][a-z0-9+.-]*:/i.test(type) ? type : `http_${status}`;
|
|
92
|
+
}
|
|
93
|
+
function problemTraceId(body) {
|
|
94
|
+
if (typeof body !== "object" || body === null) return null;
|
|
95
|
+
const value = body.traceId;
|
|
96
|
+
return typeof value === "string" && value !== "" ? value : null;
|
|
97
|
+
}
|
|
90
98
|
function sizeOf(content) {
|
|
91
99
|
if (ArrayBuffer.isView(content)) return content.byteLength;
|
|
92
100
|
if (isArrayBuffer(content)) return content.byteLength;
|
|
@@ -270,7 +278,7 @@ async function problemToError(response) {
|
|
|
270
278
|
`The server responded with ${response.status}.`
|
|
271
279
|
);
|
|
272
280
|
}
|
|
273
|
-
const code =
|
|
281
|
+
const code = problemCode(problem.type, response.status);
|
|
274
282
|
const message = typeof problem.detail === "string" ? problem.detail : typeof problem.title === "string" ? problem.title : `The server responded with ${response.status}.`;
|
|
275
283
|
return new DeployError(code, message, problem);
|
|
276
284
|
}
|
|
@@ -1542,6 +1550,7 @@ function asDeployError(error) {
|
|
|
1542
1550
|
);
|
|
1543
1551
|
}
|
|
1544
1552
|
async function deploy(source, siteId, onProgress, signal, options = {}) {
|
|
1553
|
+
let deployId;
|
|
1545
1554
|
try {
|
|
1546
1555
|
onProgress({ type: "reading", bytes: 0, total: 0 });
|
|
1547
1556
|
const collected = await source(
|
|
@@ -1563,6 +1572,7 @@ async function deploy(source, siteId, onProgress, signal, options = {}) {
|
|
|
1563
1572
|
onProgress({ type: "unchanged", url: prepared.url ?? "" });
|
|
1564
1573
|
return;
|
|
1565
1574
|
}
|
|
1575
|
+
deployId = prepared.deployId;
|
|
1566
1576
|
const sizes = new Map(hashed.map((file) => [file.path, sizeOf(file.bytes)]));
|
|
1567
1577
|
const batches = prepared.batches ?? [];
|
|
1568
1578
|
const targets = [...prepared.upload, ...batches];
|
|
@@ -1623,7 +1633,8 @@ async function deploy(source, siteId, onProgress, signal, options = {}) {
|
|
|
1623
1633
|
type: "error",
|
|
1624
1634
|
code: failure.code,
|
|
1625
1635
|
message: failure.message,
|
|
1626
|
-
...failure.detail === void 0 ? {} : { detail: failure.detail }
|
|
1636
|
+
...failure.detail === void 0 ? {} : { detail: failure.detail },
|
|
1637
|
+
...deployId === void 0 ? {} : { deployId }
|
|
1627
1638
|
});
|
|
1628
1639
|
throw failure;
|
|
1629
1640
|
}
|
|
@@ -1644,7 +1655,9 @@ async function call(credentials, path, init = {}) {
|
|
|
1644
1655
|
async function failureOf(response) {
|
|
1645
1656
|
const problem = await response.json().catch(() => null);
|
|
1646
1657
|
return Object.assign(new Error(problem?.detail ?? `The API answered ${response.status}.`), {
|
|
1647
|
-
status: response.status
|
|
1658
|
+
status: response.status,
|
|
1659
|
+
code: problemCode(problem?.type, response.status),
|
|
1660
|
+
traceId: problemTraceId(problem)
|
|
1648
1661
|
});
|
|
1649
1662
|
}
|
|
1650
1663
|
function isTokenRefused(error) {
|
|
@@ -2305,6 +2318,22 @@ function describeSite(site, folderPath) {
|
|
|
2305
2318
|
...more > 0 ? [` … and ${more} older`] : []
|
|
2306
2319
|
].join("\n");
|
|
2307
2320
|
}
|
|
2321
|
+
function failureContext(error) {
|
|
2322
|
+
if (typeof error !== "object" || error === null) return { code: null, traceId: null };
|
|
2323
|
+
const { code, traceId, detail } = error;
|
|
2324
|
+
return {
|
|
2325
|
+
code: typeof code === "string" && code !== "" ? code : null,
|
|
2326
|
+
traceId: typeof traceId === "string" && traceId !== "" ? traceId : problemTraceId(detail)
|
|
2327
|
+
};
|
|
2328
|
+
}
|
|
2329
|
+
function reportLink(dashboardOrigin, context, source) {
|
|
2330
|
+
if (context.traceId === null) return null;
|
|
2331
|
+
const url = new URL("/report", dashboardOrigin);
|
|
2332
|
+
if (context.code !== null) url.searchParams.set("code", context.code);
|
|
2333
|
+
url.searchParams.set("trace", context.traceId);
|
|
2334
|
+
url.searchParams.set("source", source);
|
|
2335
|
+
return url.toString();
|
|
2336
|
+
}
|
|
2308
2337
|
const DEFAULT_WAIT_SECONDS = 120;
|
|
2309
2338
|
const MAX_WAIT_SECONDS = 240;
|
|
2310
2339
|
const ATTEMPT_LIFETIME_MS = 15 * 60 * 1e3;
|
|
@@ -2481,7 +2510,7 @@ async function signInWithCode(waitSeconds, replace = false) {
|
|
|
2481
2510
|
"Call this tool again to keep waiting. Nothing has been changed yet."
|
|
2482
2511
|
].join("\n");
|
|
2483
2512
|
}
|
|
2484
|
-
const SERVER_VERSION = "1.
|
|
2513
|
+
const SERVER_VERSION = "1.1.0";
|
|
2485
2514
|
const REPLACES_A_SITE = {
|
|
2486
2515
|
readOnlyHint: false,
|
|
2487
2516
|
destructiveHint: true,
|
|
@@ -2706,16 +2735,21 @@ async function withCredentials(context, work) {
|
|
|
2706
2735
|
() => work(credentials),
|
|
2707
2736
|
(error) => {
|
|
2708
2737
|
if (isTokenRefused(error)) context.tokenRefused?.();
|
|
2709
|
-
}
|
|
2738
|
+
},
|
|
2739
|
+
dashboardUrlFor(credentials.apiBaseUrl)
|
|
2710
2740
|
);
|
|
2711
2741
|
}
|
|
2712
|
-
async function attempt(work, observe) {
|
|
2742
|
+
async function attempt(work, observe, dashboardOrigin) {
|
|
2713
2743
|
try {
|
|
2714
2744
|
const answer = await work();
|
|
2715
2745
|
return typeof answer === "string" ? say(answer) : answer;
|
|
2716
2746
|
} catch (error) {
|
|
2717
2747
|
observe?.(error);
|
|
2718
|
-
|
|
2748
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2749
|
+
const report2 = dashboardOrigin === void 0 ? null : reportLink(dashboardOrigin, failureContext(error), "mcp");
|
|
2750
|
+
return say(report2 === null ? message : `${message}
|
|
2751
|
+
|
|
2752
|
+
Report it: ${report2}`, true);
|
|
2719
2753
|
}
|
|
2720
2754
|
}
|
|
2721
2755
|
function describe(result) {
|
|
@@ -2834,7 +2868,7 @@ function registerSiteTools(server, context) {
|
|
|
2834
2868
|
"delete_site",
|
|
2835
2869
|
{
|
|
2836
2870
|
...titled("Delete a site", REMOVES_A_SITE),
|
|
2837
|
-
description: "Takes a site down permanently — its files, its history and its subdomain. Nothing here undoes it, and the subdomain stays reserved — nobody can use it again. Requires `confirm` to repeat the site's own subdomain exactly; ask the person for it rather than filling it in from what you already know, because that is the step this asks for.",
|
|
2871
|
+
description: "Takes a site down permanently — its files, its history and its subdomain. Nothing here undoes it, and the subdomain stays reserved — nobody can use it again. Requires `confirm` to repeat the site's own subdomain exactly; ask the person for it rather than filling it in from what you already know, because that is the step this asks for. To take a site off the air and keep it, use pause_site instead; resume_site brings it back.",
|
|
2838
2872
|
inputSchema: {
|
|
2839
2873
|
site: z.string().min(1).describe("Subdomain or site id to delete."),
|
|
2840
2874
|
confirm: z.string().min(1).describe(
|
|
@@ -2899,7 +2933,7 @@ function registerSiteTools(server, context) {
|
|
|
2899
2933
|
"list_sites",
|
|
2900
2934
|
{
|
|
2901
2935
|
...titled("List sites", READS_ONLY),
|
|
2902
|
-
description: "Lists the sites on this account, so a publish can go to one of them.",
|
|
2936
|
+
description: "Lists the sites on this account, newest first, so a publish can go to one of them. Returns up to 100 with the account's total; there are no pages to fetch beyond that. Use get_site for one site's settings and versions.",
|
|
2903
2937
|
inputSchema: {},
|
|
2904
2938
|
outputSchema: {
|
|
2905
2939
|
sites: z.array(SITE_OUTPUT).describe("The account's sites, newest first — every one unless `total` is larger."),
|
|
@@ -3330,7 +3364,7 @@ function createServer() {
|
|
|
3330
3364
|
"login",
|
|
3331
3365
|
{
|
|
3332
3366
|
...titled("Sign in to Drop2Run", CREDENTIAL_WRITE),
|
|
3333
|
-
description: "Signs in through a browser on this machine and stores an access token, which every other tool then uses. Opens the browser here and waits for the person to approve. If it answers that nothing has been approved yet, call it again to keep waiting — that is not a failure. Needs no command line and no token pasted by hand.",
|
|
3367
|
+
description: "Signs in through a browser on this machine and stores an access token, which every other tool then uses. Opens the browser here and waits for the person to approve. If it answers that nothing has been approved yet, call it again to keep waiting — that is not a failure. Needs no command line and no token pasted by hand. Where no browser can open on this machine — a container, a remote host — use login_code instead.",
|
|
3334
3368
|
inputSchema: {
|
|
3335
3369
|
waitSeconds: z.number().int().min(5).max(MAX_WAIT_SECONDS).optional().describe("How long this call waits for the approval before answering. Default 120."),
|
|
3336
3370
|
replace: z.boolean().optional().describe(
|
package/package.json
CHANGED