@sakupa/mcp 0.7.17 → 0.7.18
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/bin.js +10 -88
- package/dist/index.js +10 -88
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -129,7 +129,7 @@ var FORBIDDEN_PATH_SEGMENTS = [
|
|
|
129
129
|
var ALLOWED_HIDDEN_PATHS = [".well-known/"];
|
|
130
130
|
|
|
131
131
|
// ../core/dist/domain/version.js
|
|
132
|
-
var SAKUPA_MCP_VERSION = "0.7.
|
|
132
|
+
var SAKUPA_MCP_VERSION = "0.7.18";
|
|
133
133
|
|
|
134
134
|
// ../core/dist/domain/errors.js
|
|
135
135
|
var HTTP_STATUS = {
|
|
@@ -603,20 +603,6 @@ var HttpApiClient = class {
|
|
|
603
603
|
}
|
|
604
604
|
);
|
|
605
605
|
}
|
|
606
|
-
async unbindDomain(siteId, credential, req) {
|
|
607
|
-
return this.call(
|
|
608
|
-
"POST",
|
|
609
|
-
`/v1/sites/${encodeURIComponent(siteId)}/domain/unbind`,
|
|
610
|
-
{ credential, body: req }
|
|
611
|
-
);
|
|
612
|
-
}
|
|
613
|
-
async previewUnbindDomain(siteId, credential, req) {
|
|
614
|
-
return this.call(
|
|
615
|
-
"POST",
|
|
616
|
-
`/v1/sites/${encodeURIComponent(siteId)}/domain/unbind/preview`,
|
|
617
|
-
{ credential, body: req }
|
|
618
|
-
);
|
|
619
|
-
}
|
|
620
606
|
async recoverDomain(req) {
|
|
621
607
|
return this.call("POST", "/v1/domains/recover", { body: req });
|
|
622
608
|
}
|
|
@@ -2097,9 +2083,12 @@ ${res2.message}
|
|
|
2097
2083
|
const res = await ctx.client.bindDomain(site.credential, req);
|
|
2098
2084
|
const apex = res.apexDomain;
|
|
2099
2085
|
const txtShort = shortHostFor(res.verificationRecord.name, apex);
|
|
2086
|
+
const switchNotice = res.supersedes ? `NOTE FOR THE USER: this site already serves ${res.supersedes}. ${res.supersedes} keeps working the whole time; once www.${apex} is confirmed live, it automatically REPLACES ${res.supersedes} (zero downtime). Tell the user this before they start.
|
|
2087
|
+
|
|
2088
|
+
` : "";
|
|
2100
2089
|
return text(
|
|
2101
2090
|
"domain_verification_started",
|
|
2102
|
-
`Domain binding started for ${apex} (includes: ${res.includedHostnames.join(", ")} \u2014 both will serve this site).
|
|
2091
|
+
switchNotice + `Domain binding started for ${apex} (includes: ${res.includedHostnames.join(", ")} \u2014 both will serve this site).
|
|
2103
2092
|
|
|
2104
2093
|
STEP 1 of 2 \u2014 add ALL THREE records NOW:
|
|
2105
2094
|
|
|
@@ -2120,6 +2109,7 @@ Drive the whole flow with bind "status": it live-checks every record and names t
|
|
|
2120
2109
|
includedHostnames: res.includedHostnames,
|
|
2121
2110
|
verificationRecord: res.verificationRecord,
|
|
2122
2111
|
servingTarget: res.servingTarget,
|
|
2112
|
+
...res.supersedes ? { supersedes: res.supersedes } : {},
|
|
2123
2113
|
requiredRecords: [
|
|
2124
2114
|
{
|
|
2125
2115
|
type: "TXT",
|
|
@@ -2536,15 +2526,6 @@ var deleteConfirmation = z5.object({
|
|
|
2536
2526
|
expectedBoundHostnames: z5.array(z5.string()),
|
|
2537
2527
|
acknowledge: z5.literal("delete_and_cancel_renewal")
|
|
2538
2528
|
});
|
|
2539
|
-
var unbindConfirmation = z5.object({
|
|
2540
|
-
siteId: z5.string().min(1),
|
|
2541
|
-
bindingId: z5.string().min(1),
|
|
2542
|
-
expectedBindingUpdatedAt: z5.string().datetime(),
|
|
2543
|
-
expectedBindingStatus: z5.enum(["provisioning", "active"]),
|
|
2544
|
-
apexDomain: z5.string().min(1),
|
|
2545
|
-
expectedBoundHostnames: z5.array(z5.string()),
|
|
2546
|
-
acknowledge: z5.literal("unbind_and_remove_custom_hostnames")
|
|
2547
|
-
});
|
|
2548
2529
|
function registerLifecycleTools(server, baseCtx) {
|
|
2549
2530
|
server.registerTool(
|
|
2550
2531
|
"delete",
|
|
@@ -2606,66 +2587,6 @@ function registerLifecycleTools(server, baseCtx) {
|
|
|
2606
2587
|
}
|
|
2607
2588
|
}
|
|
2608
2589
|
);
|
|
2609
|
-
server.registerTool(
|
|
2610
|
-
"unbind",
|
|
2611
|
-
{
|
|
2612
|
-
description: "Preview or execute removal of the custom apex/www serving surface while preserving the subscription and permanent Sakupa URL.",
|
|
2613
|
-
inputSchema: {
|
|
2614
|
-
projectDir: projectDirInput,
|
|
2615
|
-
action: z5.enum(["preview", "confirm"]),
|
|
2616
|
-
operationId: z5.string().min(1).optional(),
|
|
2617
|
-
confirmation: unbindConfirmation.optional()
|
|
2618
|
-
},
|
|
2619
|
-
outputSchema: STRUCTURED_TOOL_OUTPUT_SCHEMA,
|
|
2620
|
-
annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true }
|
|
2621
|
-
},
|
|
2622
|
-
async (args) => {
|
|
2623
|
-
try {
|
|
2624
|
-
const ctx = withProjectDir(baseCtx, args.projectDir);
|
|
2625
|
-
const site = requireSiteFile(ctx);
|
|
2626
|
-
const operationId = args.operationId ?? randomUUID2();
|
|
2627
|
-
if (args.action === "preview") {
|
|
2628
|
-
const preview = await ctx.client.previewUnbindDomain(site.siteId, site.credential, {
|
|
2629
|
-
operationId
|
|
2630
|
-
});
|
|
2631
|
-
return structuredToolResult({
|
|
2632
|
-
schemaVersion: 1,
|
|
2633
|
-
outcome: "waiting_user",
|
|
2634
|
-
resultCode: "unbind_confirmation_required",
|
|
2635
|
-
operationId,
|
|
2636
|
-
summary: `Exact binding snapshot returned; unbinding removes ONLY the custom domain \u2014 the subscription, content, and permanent URL stay unchanged. To proceed, call unbind again with action:"confirm", operationId:"${operationId}", and the confirmation object from data.preview.confirmation.`,
|
|
2637
|
-
data: { preview },
|
|
2638
|
-
nextActions: [
|
|
2639
|
-
{ tool: "unbind", allowed: true, reasonCode: "exact_confirmation_required" }
|
|
2640
|
-
]
|
|
2641
|
-
});
|
|
2642
|
-
}
|
|
2643
|
-
if (!args.confirmation) {
|
|
2644
|
-
throw new LocalGuidanceError(
|
|
2645
|
-
"invalid_request",
|
|
2646
|
-
'To CONFIRM unbind, first call unbind with action:"preview" to get the exact confirmation object bound to the current binding, then call again with action:"confirm", the same operationId, and that confirmation object.'
|
|
2647
|
-
);
|
|
2648
|
-
}
|
|
2649
|
-
const result = await ctx.client.unbindDomain(site.siteId, site.credential, {
|
|
2650
|
-
operationId,
|
|
2651
|
-
confirmation: args.confirmation
|
|
2652
|
-
});
|
|
2653
|
-
const { boundDomain: _removed, ...remaining } = site;
|
|
2654
|
-
writeSiteFile(ctx.projectDir, remaining);
|
|
2655
|
-
return structuredToolResult({
|
|
2656
|
-
schemaVersion: 1,
|
|
2657
|
-
outcome: result.servingDeletionPending ? "pending_provider" : "completed",
|
|
2658
|
-
resultCode: "domain_unbound",
|
|
2659
|
-
operationId,
|
|
2660
|
-
summary: `Custom domain unbound; the subscription, deployed content, and permanent Sakupa URL are unchanged. (project: ${ctx.projectDir})`,
|
|
2661
|
-
data: { result },
|
|
2662
|
-
nextActions: [{ tool: "status", allowed: true }]
|
|
2663
|
-
});
|
|
2664
|
-
} catch (error) {
|
|
2665
|
-
return toolError(error);
|
|
2666
|
-
}
|
|
2667
|
-
}
|
|
2668
|
-
);
|
|
2669
2590
|
}
|
|
2670
2591
|
|
|
2671
2592
|
// src/transport.ts
|
|
@@ -2764,8 +2685,9 @@ Workflow:
|
|
|
2764
2685
|
serving surface alongside the permanent URL. Ownership is proven only by DNS control; the
|
|
2765
2686
|
first verified request wins; unverified requests expire after 72 hours. billing,
|
|
2766
2687
|
upgrade, portal and recover manage the paid
|
|
2767
|
-
lifecycle;
|
|
2768
|
-
|
|
2688
|
+
lifecycle; delete tears the whole site down after explicit confirmation. Binding a
|
|
2689
|
+
NEW domain while one is live is a zero-downtime SWITCH: the old domain keeps serving
|
|
2690
|
+
until the new domain's www is confirmed live, then it is replaced automatically.
|
|
2769
2691
|
Plan changes are confirmed only on Stripe and synchronized by Stripe webhook.
|
|
2770
2692
|
A cancellation keeps the site paid through the current period. Sakupa reverts it to a free
|
|
2771
2693
|
24h site and removes paid data after Stripe sends the signed final-cancellation webhook.
|
|
@@ -2779,7 +2701,7 @@ the user opened (for framework projects, where package.json lives \u2014 never t
|
|
|
2779
2701
|
build folder; output is auto-detected). The server NEVER guesses a directory and refuses
|
|
2780
2702
|
calls without one: only you can see which directory the user is actually in. After every deploy, TELL the user which environment it went to (deploy results carry an
|
|
2781
2703
|
Explicit Environment line: TEST vs PRODUCTION). analyze, deploy, status,
|
|
2782
|
-
refresh
|
|
2704
|
+
refresh and delete echo
|
|
2783
2705
|
the directory they acted on \u2014 verify it matches the user's active project.
|
|
2784
2706
|
|
|
2785
2707
|
When the same operation fails twice in a row, or the user is clearly stuck or
|
package/dist/index.js
CHANGED
|
@@ -124,7 +124,7 @@ var FORBIDDEN_PATH_SEGMENTS = [
|
|
|
124
124
|
var ALLOWED_HIDDEN_PATHS = [".well-known/"];
|
|
125
125
|
|
|
126
126
|
// ../core/dist/domain/version.js
|
|
127
|
-
var SAKUPA_MCP_VERSION = "0.7.
|
|
127
|
+
var SAKUPA_MCP_VERSION = "0.7.18";
|
|
128
128
|
|
|
129
129
|
// ../core/dist/domain/errors.js
|
|
130
130
|
var HTTP_STATUS = {
|
|
@@ -673,20 +673,6 @@ var HttpApiClient = class {
|
|
|
673
673
|
}
|
|
674
674
|
);
|
|
675
675
|
}
|
|
676
|
-
async unbindDomain(siteId, credential, req) {
|
|
677
|
-
return this.call(
|
|
678
|
-
"POST",
|
|
679
|
-
`/v1/sites/${encodeURIComponent(siteId)}/domain/unbind`,
|
|
680
|
-
{ credential, body: req }
|
|
681
|
-
);
|
|
682
|
-
}
|
|
683
|
-
async previewUnbindDomain(siteId, credential, req) {
|
|
684
|
-
return this.call(
|
|
685
|
-
"POST",
|
|
686
|
-
`/v1/sites/${encodeURIComponent(siteId)}/domain/unbind/preview`,
|
|
687
|
-
{ credential, body: req }
|
|
688
|
-
);
|
|
689
|
-
}
|
|
690
676
|
async recoverDomain(req) {
|
|
691
677
|
return this.call("POST", "/v1/domains/recover", { body: req });
|
|
692
678
|
}
|
|
@@ -2163,9 +2149,12 @@ ${res2.message}
|
|
|
2163
2149
|
const res = await ctx.client.bindDomain(site.credential, req);
|
|
2164
2150
|
const apex = res.apexDomain;
|
|
2165
2151
|
const txtShort = shortHostFor(res.verificationRecord.name, apex);
|
|
2152
|
+
const switchNotice = res.supersedes ? `NOTE FOR THE USER: this site already serves ${res.supersedes}. ${res.supersedes} keeps working the whole time; once www.${apex} is confirmed live, it automatically REPLACES ${res.supersedes} (zero downtime). Tell the user this before they start.
|
|
2153
|
+
|
|
2154
|
+
` : "";
|
|
2166
2155
|
return text(
|
|
2167
2156
|
"domain_verification_started",
|
|
2168
|
-
`Domain binding started for ${apex} (includes: ${res.includedHostnames.join(", ")} \u2014 both will serve this site).
|
|
2157
|
+
switchNotice + `Domain binding started for ${apex} (includes: ${res.includedHostnames.join(", ")} \u2014 both will serve this site).
|
|
2169
2158
|
|
|
2170
2159
|
STEP 1 of 2 \u2014 add ALL THREE records NOW:
|
|
2171
2160
|
|
|
@@ -2186,6 +2175,7 @@ Drive the whole flow with bind "status": it live-checks every record and names t
|
|
|
2186
2175
|
includedHostnames: res.includedHostnames,
|
|
2187
2176
|
verificationRecord: res.verificationRecord,
|
|
2188
2177
|
servingTarget: res.servingTarget,
|
|
2178
|
+
...res.supersedes ? { supersedes: res.supersedes } : {},
|
|
2189
2179
|
requiredRecords: [
|
|
2190
2180
|
{
|
|
2191
2181
|
type: "TXT",
|
|
@@ -2530,15 +2520,6 @@ var deleteConfirmation = z4.object({
|
|
|
2530
2520
|
expectedBoundHostnames: z4.array(z4.string()),
|
|
2531
2521
|
acknowledge: z4.literal("delete_and_cancel_renewal")
|
|
2532
2522
|
});
|
|
2533
|
-
var unbindConfirmation = z4.object({
|
|
2534
|
-
siteId: z4.string().min(1),
|
|
2535
|
-
bindingId: z4.string().min(1),
|
|
2536
|
-
expectedBindingUpdatedAt: z4.string().datetime(),
|
|
2537
|
-
expectedBindingStatus: z4.enum(["provisioning", "active"]),
|
|
2538
|
-
apexDomain: z4.string().min(1),
|
|
2539
|
-
expectedBoundHostnames: z4.array(z4.string()),
|
|
2540
|
-
acknowledge: z4.literal("unbind_and_remove_custom_hostnames")
|
|
2541
|
-
});
|
|
2542
2523
|
function registerLifecycleTools(server, baseCtx) {
|
|
2543
2524
|
server.registerTool(
|
|
2544
2525
|
"delete",
|
|
@@ -2600,66 +2581,6 @@ function registerLifecycleTools(server, baseCtx) {
|
|
|
2600
2581
|
}
|
|
2601
2582
|
}
|
|
2602
2583
|
);
|
|
2603
|
-
server.registerTool(
|
|
2604
|
-
"unbind",
|
|
2605
|
-
{
|
|
2606
|
-
description: "Preview or execute removal of the custom apex/www serving surface while preserving the subscription and permanent Sakupa URL.",
|
|
2607
|
-
inputSchema: {
|
|
2608
|
-
projectDir: projectDirInput,
|
|
2609
|
-
action: z4.enum(["preview", "confirm"]),
|
|
2610
|
-
operationId: z4.string().min(1).optional(),
|
|
2611
|
-
confirmation: unbindConfirmation.optional()
|
|
2612
|
-
},
|
|
2613
|
-
outputSchema: STRUCTURED_TOOL_OUTPUT_SCHEMA,
|
|
2614
|
-
annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true }
|
|
2615
|
-
},
|
|
2616
|
-
async (args) => {
|
|
2617
|
-
try {
|
|
2618
|
-
const ctx = withProjectDir(baseCtx, args.projectDir);
|
|
2619
|
-
const site = requireSiteFile(ctx);
|
|
2620
|
-
const operationId = args.operationId ?? randomUUID2();
|
|
2621
|
-
if (args.action === "preview") {
|
|
2622
|
-
const preview = await ctx.client.previewUnbindDomain(site.siteId, site.credential, {
|
|
2623
|
-
operationId
|
|
2624
|
-
});
|
|
2625
|
-
return structuredToolResult({
|
|
2626
|
-
schemaVersion: 1,
|
|
2627
|
-
outcome: "waiting_user",
|
|
2628
|
-
resultCode: "unbind_confirmation_required",
|
|
2629
|
-
operationId,
|
|
2630
|
-
summary: `Exact binding snapshot returned; unbinding removes ONLY the custom domain \u2014 the subscription, content, and permanent URL stay unchanged. To proceed, call unbind again with action:"confirm", operationId:"${operationId}", and the confirmation object from data.preview.confirmation.`,
|
|
2631
|
-
data: { preview },
|
|
2632
|
-
nextActions: [
|
|
2633
|
-
{ tool: "unbind", allowed: true, reasonCode: "exact_confirmation_required" }
|
|
2634
|
-
]
|
|
2635
|
-
});
|
|
2636
|
-
}
|
|
2637
|
-
if (!args.confirmation) {
|
|
2638
|
-
throw new LocalGuidanceError(
|
|
2639
|
-
"invalid_request",
|
|
2640
|
-
'To CONFIRM unbind, first call unbind with action:"preview" to get the exact confirmation object bound to the current binding, then call again with action:"confirm", the same operationId, and that confirmation object.'
|
|
2641
|
-
);
|
|
2642
|
-
}
|
|
2643
|
-
const result = await ctx.client.unbindDomain(site.siteId, site.credential, {
|
|
2644
|
-
operationId,
|
|
2645
|
-
confirmation: args.confirmation
|
|
2646
|
-
});
|
|
2647
|
-
const { boundDomain: _removed, ...remaining } = site;
|
|
2648
|
-
writeSiteFile(ctx.projectDir, remaining);
|
|
2649
|
-
return structuredToolResult({
|
|
2650
|
-
schemaVersion: 1,
|
|
2651
|
-
outcome: result.servingDeletionPending ? "pending_provider" : "completed",
|
|
2652
|
-
resultCode: "domain_unbound",
|
|
2653
|
-
operationId,
|
|
2654
|
-
summary: `Custom domain unbound; the subscription, deployed content, and permanent Sakupa URL are unchanged. (project: ${ctx.projectDir})`,
|
|
2655
|
-
data: { result },
|
|
2656
|
-
nextActions: [{ tool: "status", allowed: true }]
|
|
2657
|
-
});
|
|
2658
|
-
} catch (error) {
|
|
2659
|
-
return toolError(error);
|
|
2660
|
-
}
|
|
2661
|
-
}
|
|
2662
|
-
);
|
|
2663
2584
|
}
|
|
2664
2585
|
|
|
2665
2586
|
// src/server.ts
|
|
@@ -2759,8 +2680,9 @@ Workflow:
|
|
|
2759
2680
|
serving surface alongside the permanent URL. Ownership is proven only by DNS control; the
|
|
2760
2681
|
first verified request wins; unverified requests expire after 72 hours. billing,
|
|
2761
2682
|
upgrade, portal and recover manage the paid
|
|
2762
|
-
lifecycle;
|
|
2763
|
-
|
|
2683
|
+
lifecycle; delete tears the whole site down after explicit confirmation. Binding a
|
|
2684
|
+
NEW domain while one is live is a zero-downtime SWITCH: the old domain keeps serving
|
|
2685
|
+
until the new domain's www is confirmed live, then it is replaced automatically.
|
|
2764
2686
|
Plan changes are confirmed only on Stripe and synchronized by Stripe webhook.
|
|
2765
2687
|
A cancellation keeps the site paid through the current period. Sakupa reverts it to a free
|
|
2766
2688
|
24h site and removes paid data after Stripe sends the signed final-cancellation webhook.
|
|
@@ -2774,7 +2696,7 @@ the user opened (for framework projects, where package.json lives \u2014 never t
|
|
|
2774
2696
|
build folder; output is auto-detected). The server NEVER guesses a directory and refuses
|
|
2775
2697
|
calls without one: only you can see which directory the user is actually in. After every deploy, TELL the user which environment it went to (deploy results carry an
|
|
2776
2698
|
Explicit Environment line: TEST vs PRODUCTION). analyze, deploy, status,
|
|
2777
|
-
refresh
|
|
2699
|
+
refresh and delete echo
|
|
2778
2700
|
the directory they acted on \u2014 verify it matches the user's active project.
|
|
2779
2701
|
|
|
2780
2702
|
When the same operation fails twice in a row, or the user is clearly stuck or
|