@sakupa/mcp 0.7.1 → 0.7.3

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.
Files changed (3) hide show
  1. package/dist/bin.js +23 -13
  2. package/dist/index.js +23 -13
  3. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -128,7 +128,7 @@ var FORBIDDEN_PATH_SEGMENTS = [
128
128
  var ALLOWED_HIDDEN_PATHS = [".well-known/"];
129
129
 
130
130
  // ../core/dist/domain/version.js
131
- var SAKUPA_MCP_VERSION = "0.7.1";
131
+ var SAKUPA_MCP_VERSION = "0.7.3";
132
132
 
133
133
  // ../core/dist/domain/errors.js
134
134
  var HTTP_STATUS = {
@@ -467,6 +467,9 @@ var WEBHOOK_PROCESSING_LEASE_MS = 5 * 60 * 1e3;
467
467
 
468
468
  // src/config.ts
469
469
  var TEST_API_BASE_URL = "https://api-test.sakupa.com";
470
+ function previewHostPatternFor(apiBaseUrl) {
471
+ return apiBaseUrl === TEST_API_BASE_URL ? "{shortId}-test.sakupa.com" : "{shortId}.sakupa.com";
472
+ }
470
473
  function loadMcpRuntimeConfig(env = process.env, cwd = process.cwd()) {
471
474
  const apiBaseUrl = (env["SAKUPA_API_URL"] ?? DEFAULT_API_BASE_URL).replace(/\/+$/, "");
472
475
  const projectDir = env["SAKUPA_PROJECT_DIR"] ?? cwd;
@@ -1394,6 +1397,7 @@ async function uploadAll(ctx, targets, files, outputAbs) {
1394
1397
  return targets.length;
1395
1398
  }
1396
1399
  function registerTools(server, ctx) {
1400
+ const previewHostPattern = previewHostPatternFor(ctx.apiBaseUrl);
1397
1401
  server.registerTool(
1398
1402
  "analyze_site",
1399
1403
  {
@@ -1427,7 +1431,7 @@ Next action: ${analysis.suggestedNextAction}`,
1427
1431
  server.registerTool(
1428
1432
  "deploy_site",
1429
1433
  {
1430
- description: `Deploy the local static output to Sakupa. First deploy creates a free temporary site (valid ${FREE_SITE_TTL_HOURS}h, public URL like https://{shortId}.sakupa.com) and stores the management credential in .sakupa/site.json. Later runs update the existing site (free sites also refresh their validity; subscribed sites are permanent). Runs analyze_site first and refuses to upload source projects, secrets, .env files, archives, media or server code. Never uploads anything when the analysis says the project is not deployable.`,
1434
+ description: `Deploy the local static output to Sakupa. First deploy creates a free temporary site (valid ${FREE_SITE_TTL_HOURS}h, public URL like https://${previewHostPattern}) and stores the management credential in .sakupa/site.json. Later runs update the existing site (free sites also refresh their validity; subscribed sites are permanent). Runs analyze_site first and refuses to upload source projects, secrets, .env files, archives, media or server code. Never uploads anything when the analysis says the project is not deployable.`,
1431
1435
  outputSchema: STRUCTURED_TOOL_OUTPUT_SCHEMA,
1432
1436
  annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },
1433
1437
  inputSchema: {
@@ -1610,7 +1614,7 @@ Free sites stay live for ${FREE_SITE_TTL_HOURS} hours after each deploy or refre
1610
1614
  server.registerTool(
1611
1615
  "subscribe_site",
1612
1616
  {
1613
- description: `Create a Stripe Checkout link that subscribes THIS site to a Sakupa Hosting monthly plan (${planCatalog()}). Paying makes the site PERMANENT on its {shortId}.sakupa.com URL \u2014 no more 24h expiry; that is the core value of paying. Binding a custom domain afterwards (bind_domain) is an optional included extra and requires DNS control of that domain. Owner-only: requires this project's site credential (.sakupa/site.json) \u2014 deploy_site first. If the site outgrows its plan, Sakupa shows an over-limit notice and never changes billing automatically. The owner can explicitly choose another plan through Stripe Customer Portal. Card details are entered only on the Stripe-hosted page \u2014 never through the AI tool. Opening and completing Stripe Checkout is the final subscription confirmation.`,
1617
+ description: `Create a Stripe Checkout link that subscribes THIS site to a Sakupa Hosting monthly plan (${planCatalog()}). Paying makes the site PERMANENT on its ${previewHostPattern} URL \u2014 no more 24h expiry; that is the core value of paying. Binding a custom domain afterwards (bind_domain) is an optional included extra and requires DNS control of that domain. Owner-only: requires this project's site credential (.sakupa/site.json) \u2014 deploy_site first. If the site outgrows its plan, Sakupa shows an over-limit notice and never changes billing automatically. The owner can explicitly choose another plan through Stripe Customer Portal. Card details are entered only on the Stripe-hosted page \u2014 never through the AI tool. Opening and completing Stripe Checkout is the final subscription confirmation.`,
1614
1618
  outputSchema: STRUCTURED_TOOL_OUTPUT_SCHEMA,
1615
1619
  annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },
1616
1620
  inputSchema: {
@@ -1655,7 +1659,7 @@ Once payment confirms, the site becomes permanent on its current URL. Binding a
1655
1659
  server.registerTool(
1656
1660
  "bind_domain",
1657
1661
  {
1658
- description: "Bind a custom domain to this subscribed site \u2014 an OPTIONAL extra serving surface; the permanent {shortId}.sakupa.com URL keeps working alongside it. The binding unit is the APEX domain: binding example.com automatically includes www.example.com (both serve the same content, one apex TXT verification covers both), and one site binds at most ONE apex domain \u2014 a second domain needs a second subscribed site. Requires an ACTIVE subscription (subscribe_site). Ownership is proven ONLY by DNS control of the apex \u2014 payment never grants ownership. A binding request never reserves the domain: whoever proves DNS control first gets it, and unverified requests expire after 72 hours. Call again with verificationId to check progress.",
1662
+ description: `Bind a custom domain to this subscribed site \u2014 an OPTIONAL extra serving surface; the permanent ${previewHostPattern} URL keeps working alongside it. The binding unit is the APEX domain: binding example.com automatically includes www.example.com (both serve the same content, one apex TXT verification covers both), and one site binds at most ONE apex domain \u2014 a second domain needs a second subscribed site. Requires an ACTIVE subscription (subscribe_site). Ownership is proven ONLY by DNS control of the apex \u2014 payment never grants ownership. A binding request never reserves the domain: whoever proves DNS control first gets it, and unverified requests expire after 72 hours. Call again with verificationId to check progress.`,
1659
1663
  outputSchema: STRUCTURED_TOOL_OUTPUT_SCHEMA,
1660
1664
  annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },
1661
1665
  inputSchema: {
@@ -2288,28 +2292,34 @@ var FetchTransport = class {
2288
2292
  };
2289
2293
 
2290
2294
  // src/server.ts
2291
- var INSTRUCTIONS = `Sakupa publishes AI-made static websites. AI-made pages, live in seconds.
2295
+ var instructionsFor = (hostPattern) => `Sakupa publishes AI-made static websites. AI-made pages, live in seconds.
2292
2296
 
2293
2297
  Workflow:
2294
2298
  1. analyze_site \u2014 check whether this project has deployable static output. If a build is needed
2295
2299
  (Vite/Vue/React/Svelte/Astro/Next static export/Nuxt generate), run the build LOCALLY first,
2296
2300
  then re-run analyze_site.
2297
2301
  2. deploy_site \u2014 uploads ONLY the built static output. The first deploy creates a free temporary
2298
- site (public URL {shortId}.sakupa.com, valid 24 hours, free banner shown) and stores the
2302
+ site (public URL ${hostPattern}, valid 24 hours, free banner shown) and stores the
2299
2303
  management credential in .sakupa/site.json. Deploying again updates the site and refreshes
2300
- its validity; refresh_site extends validity without uploading.
2301
- 3. To make the site PERMANENT, subscribe it to a monthly hosting plan (subscribe_site ->
2302
- Stripe-hosted checkout; water/personal/share/business). Paying makes the
2303
- {shortId}.sakupa.com URL permanent \u2014 that is what payment buys. Usage over the chosen plan
2304
+ its validity; refresh_site extends validity without uploading; site_status shows the
2305
+ current deployment and serving state at any time.
2306
+ 3. To make the site PERMANENT, subscribe it to a monthly hosting plan (list_billing_plans
2307
+ shows the catalog; subscribe_site -> Stripe-hosted checkout;
2308
+ water/personal/share/business). Paying makes the
2309
+ ${hostPattern} URL permanent \u2014 that is what payment buys. Usage over the chosen plan
2304
2310
  shows an over-limit notice by default. An external AI may periodically query usage and
2305
2311
  recommend a plan, but Sakupa never changes a subscription automatically.
2306
2312
  4. Optionally bind a custom domain to the subscribed site (bind_domain): an included extra
2307
2313
  serving surface alongside the permanent URL. Ownership is proven only by DNS control; the
2308
2314
  first verified request wins; unverified requests expire after 72 hours. billing_status,
2309
- billing_status, change_subscription_plan, manage_billing and recover_domain_site manage the paid
2310
- lifecycle. Plan changes are confirmed only on Stripe and synchronized by Stripe webhook.
2315
+ change_subscription_plan, manage_billing and recover_domain_site manage the paid
2316
+ lifecycle; unbind_domain removes the custom domain (the permanent URL keeps serving) and
2317
+ delete_site tears the whole site down after explicit confirmation.
2318
+ Plan changes are confirmed only on Stripe and synchronized by Stripe webhook.
2311
2319
  A cancellation keeps the site paid through the current period. Sakupa reverts it to a free
2312
2320
  24h site and removes paid data after Stripe sends the signed final-cancellation webhook.
2321
+ 5. create_support_ticket (subscribed sites) opens a support ticket; report_bug sends a
2322
+ sanitized diagnostic report after the user explicitly confirms it.
2313
2323
 
2314
2324
  Safety boundaries:
2315
2325
  - Static output only: no SSR, API routes, middleware, server actions, databases or online builds.
@@ -2326,7 +2336,7 @@ function createSakupaMcpServer(opts) {
2326
2336
  );
2327
2337
  const server = new McpServer(
2328
2338
  { name: "sakupa", version: MCP_VERSION },
2329
- { instructions: INSTRUCTIONS }
2339
+ { instructions: instructionsFor(previewHostPatternFor(opts.apiBaseUrl)) }
2330
2340
  );
2331
2341
  registerTools(server, {
2332
2342
  client,
package/dist/index.js CHANGED
@@ -123,7 +123,7 @@ var FORBIDDEN_PATH_SEGMENTS = [
123
123
  var ALLOWED_HIDDEN_PATHS = [".well-known/"];
124
124
 
125
125
  // ../core/dist/domain/version.js
126
- var SAKUPA_MCP_VERSION = "0.7.1";
126
+ var SAKUPA_MCP_VERSION = "0.7.3";
127
127
 
128
128
  // ../core/dist/domain/errors.js
129
129
  var HTTP_STATUS = {
@@ -466,6 +466,9 @@ var CLIENT_TYPE = "sakupa-mcp";
466
466
 
467
467
  // src/config.ts
468
468
  var TEST_API_BASE_URL = "https://api-test.sakupa.com";
469
+ function previewHostPatternFor(apiBaseUrl) {
470
+ return apiBaseUrl === TEST_API_BASE_URL ? "{shortId}-test.sakupa.com" : "{shortId}.sakupa.com";
471
+ }
469
472
  function loadMcpRuntimeConfig(env = process.env, cwd = process.cwd()) {
470
473
  const apiBaseUrl = (env["SAKUPA_API_URL"] ?? DEFAULT_API_BASE_URL).replace(/\/+$/, "");
471
474
  const projectDir = env["SAKUPA_PROJECT_DIR"] ?? cwd;
@@ -1456,6 +1459,7 @@ async function uploadAll(ctx, targets, files, outputAbs) {
1456
1459
  return targets.length;
1457
1460
  }
1458
1461
  function registerTools(server, ctx) {
1462
+ const previewHostPattern = previewHostPatternFor(ctx.apiBaseUrl);
1459
1463
  server.registerTool(
1460
1464
  "analyze_site",
1461
1465
  {
@@ -1489,7 +1493,7 @@ Next action: ${analysis.suggestedNextAction}`,
1489
1493
  server.registerTool(
1490
1494
  "deploy_site",
1491
1495
  {
1492
- description: `Deploy the local static output to Sakupa. First deploy creates a free temporary site (valid ${FREE_SITE_TTL_HOURS}h, public URL like https://{shortId}.sakupa.com) and stores the management credential in .sakupa/site.json. Later runs update the existing site (free sites also refresh their validity; subscribed sites are permanent). Runs analyze_site first and refuses to upload source projects, secrets, .env files, archives, media or server code. Never uploads anything when the analysis says the project is not deployable.`,
1496
+ description: `Deploy the local static output to Sakupa. First deploy creates a free temporary site (valid ${FREE_SITE_TTL_HOURS}h, public URL like https://${previewHostPattern}) and stores the management credential in .sakupa/site.json. Later runs update the existing site (free sites also refresh their validity; subscribed sites are permanent). Runs analyze_site first and refuses to upload source projects, secrets, .env files, archives, media or server code. Never uploads anything when the analysis says the project is not deployable.`,
1493
1497
  outputSchema: STRUCTURED_TOOL_OUTPUT_SCHEMA,
1494
1498
  annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },
1495
1499
  inputSchema: {
@@ -1672,7 +1676,7 @@ Free sites stay live for ${FREE_SITE_TTL_HOURS} hours after each deploy or refre
1672
1676
  server.registerTool(
1673
1677
  "subscribe_site",
1674
1678
  {
1675
- description: `Create a Stripe Checkout link that subscribes THIS site to a Sakupa Hosting monthly plan (${planCatalog()}). Paying makes the site PERMANENT on its {shortId}.sakupa.com URL \u2014 no more 24h expiry; that is the core value of paying. Binding a custom domain afterwards (bind_domain) is an optional included extra and requires DNS control of that domain. Owner-only: requires this project's site credential (.sakupa/site.json) \u2014 deploy_site first. If the site outgrows its plan, Sakupa shows an over-limit notice and never changes billing automatically. The owner can explicitly choose another plan through Stripe Customer Portal. Card details are entered only on the Stripe-hosted page \u2014 never through the AI tool. Opening and completing Stripe Checkout is the final subscription confirmation.`,
1679
+ description: `Create a Stripe Checkout link that subscribes THIS site to a Sakupa Hosting monthly plan (${planCatalog()}). Paying makes the site PERMANENT on its ${previewHostPattern} URL \u2014 no more 24h expiry; that is the core value of paying. Binding a custom domain afterwards (bind_domain) is an optional included extra and requires DNS control of that domain. Owner-only: requires this project's site credential (.sakupa/site.json) \u2014 deploy_site first. If the site outgrows its plan, Sakupa shows an over-limit notice and never changes billing automatically. The owner can explicitly choose another plan through Stripe Customer Portal. Card details are entered only on the Stripe-hosted page \u2014 never through the AI tool. Opening and completing Stripe Checkout is the final subscription confirmation.`,
1676
1680
  outputSchema: STRUCTURED_TOOL_OUTPUT_SCHEMA,
1677
1681
  annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },
1678
1682
  inputSchema: {
@@ -1717,7 +1721,7 @@ Once payment confirms, the site becomes permanent on its current URL. Binding a
1717
1721
  server.registerTool(
1718
1722
  "bind_domain",
1719
1723
  {
1720
- description: "Bind a custom domain to this subscribed site \u2014 an OPTIONAL extra serving surface; the permanent {shortId}.sakupa.com URL keeps working alongside it. The binding unit is the APEX domain: binding example.com automatically includes www.example.com (both serve the same content, one apex TXT verification covers both), and one site binds at most ONE apex domain \u2014 a second domain needs a second subscribed site. Requires an ACTIVE subscription (subscribe_site). Ownership is proven ONLY by DNS control of the apex \u2014 payment never grants ownership. A binding request never reserves the domain: whoever proves DNS control first gets it, and unverified requests expire after 72 hours. Call again with verificationId to check progress.",
1724
+ description: `Bind a custom domain to this subscribed site \u2014 an OPTIONAL extra serving surface; the permanent ${previewHostPattern} URL keeps working alongside it. The binding unit is the APEX domain: binding example.com automatically includes www.example.com (both serve the same content, one apex TXT verification covers both), and one site binds at most ONE apex domain \u2014 a second domain needs a second subscribed site. Requires an ACTIVE subscription (subscribe_site). Ownership is proven ONLY by DNS control of the apex \u2014 payment never grants ownership. A binding request never reserves the domain: whoever proves DNS control first gets it, and unverified requests expire after 72 hours. Call again with verificationId to check progress.`,
1721
1725
  outputSchema: STRUCTURED_TOOL_OUTPUT_SCHEMA,
1722
1726
  annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },
1723
1727
  inputSchema: {
@@ -2281,28 +2285,34 @@ function registerBillingTools(server, ctx) {
2281
2285
  }
2282
2286
 
2283
2287
  // src/server.ts
2284
- var INSTRUCTIONS = `Sakupa publishes AI-made static websites. AI-made pages, live in seconds.
2288
+ var instructionsFor = (hostPattern) => `Sakupa publishes AI-made static websites. AI-made pages, live in seconds.
2285
2289
 
2286
2290
  Workflow:
2287
2291
  1. analyze_site \u2014 check whether this project has deployable static output. If a build is needed
2288
2292
  (Vite/Vue/React/Svelte/Astro/Next static export/Nuxt generate), run the build LOCALLY first,
2289
2293
  then re-run analyze_site.
2290
2294
  2. deploy_site \u2014 uploads ONLY the built static output. The first deploy creates a free temporary
2291
- site (public URL {shortId}.sakupa.com, valid 24 hours, free banner shown) and stores the
2295
+ site (public URL ${hostPattern}, valid 24 hours, free banner shown) and stores the
2292
2296
  management credential in .sakupa/site.json. Deploying again updates the site and refreshes
2293
- its validity; refresh_site extends validity without uploading.
2294
- 3. To make the site PERMANENT, subscribe it to a monthly hosting plan (subscribe_site ->
2295
- Stripe-hosted checkout; water/personal/share/business). Paying makes the
2296
- {shortId}.sakupa.com URL permanent \u2014 that is what payment buys. Usage over the chosen plan
2297
+ its validity; refresh_site extends validity without uploading; site_status shows the
2298
+ current deployment and serving state at any time.
2299
+ 3. To make the site PERMANENT, subscribe it to a monthly hosting plan (list_billing_plans
2300
+ shows the catalog; subscribe_site -> Stripe-hosted checkout;
2301
+ water/personal/share/business). Paying makes the
2302
+ ${hostPattern} URL permanent \u2014 that is what payment buys. Usage over the chosen plan
2297
2303
  shows an over-limit notice by default. An external AI may periodically query usage and
2298
2304
  recommend a plan, but Sakupa never changes a subscription automatically.
2299
2305
  4. Optionally bind a custom domain to the subscribed site (bind_domain): an included extra
2300
2306
  serving surface alongside the permanent URL. Ownership is proven only by DNS control; the
2301
2307
  first verified request wins; unverified requests expire after 72 hours. billing_status,
2302
- billing_status, change_subscription_plan, manage_billing and recover_domain_site manage the paid
2303
- lifecycle. Plan changes are confirmed only on Stripe and synchronized by Stripe webhook.
2308
+ change_subscription_plan, manage_billing and recover_domain_site manage the paid
2309
+ lifecycle; unbind_domain removes the custom domain (the permanent URL keeps serving) and
2310
+ delete_site tears the whole site down after explicit confirmation.
2311
+ Plan changes are confirmed only on Stripe and synchronized by Stripe webhook.
2304
2312
  A cancellation keeps the site paid through the current period. Sakupa reverts it to a free
2305
2313
  24h site and removes paid data after Stripe sends the signed final-cancellation webhook.
2314
+ 5. create_support_ticket (subscribed sites) opens a support ticket; report_bug sends a
2315
+ sanitized diagnostic report after the user explicitly confirms it.
2306
2316
 
2307
2317
  Safety boundaries:
2308
2318
  - Static output only: no SSR, API routes, middleware, server actions, databases or online builds.
@@ -2319,7 +2329,7 @@ function createSakupaMcpServer(opts) {
2319
2329
  );
2320
2330
  const server = new McpServer(
2321
2331
  { name: "sakupa", version: MCP_VERSION },
2322
- { instructions: INSTRUCTIONS }
2332
+ { instructions: instructionsFor(previewHostPatternFor(opts.apiBaseUrl)) }
2323
2333
  );
2324
2334
  registerTools(server, {
2325
2335
  client,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sakupa/mcp",
3
- "version": "0.7.1",
3
+ "version": "0.7.3",
4
4
  "description": "Sakupa MCP server: publish AI-made static sites from your AI tool. AI-made pages, live in seconds.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",