@amerged/ohmyhost-mcp 0.1.25 → 0.1.27

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 CHANGED
@@ -2,7 +2,7 @@ import { createRequire as __ohmyhostCreateRequire } from "node:module"; const re
2
2
  import {
3
3
  createOhmyhostMcpServer,
4
4
  ohmyhostMcpHandler
5
- } from "./chunk-L5A5FEGY.js";
5
+ } from "./chunk-QF7MOXLY.js";
6
6
  export {
7
7
  createOhmyhostMcpServer,
8
8
  ohmyhostMcpHandler
@@ -27,7 +27,7 @@ import {
27
27
  serverIdentityOf,
28
28
  setNegotiatedProtocolVersion,
29
29
  validateEnvelopeMeta
30
- } from "./chunk-L5A5FEGY.js";
30
+ } from "./chunk-QF7MOXLY.js";
31
31
 
32
32
  // node_modules/.pnpm/@modelcontextprotocol+server@2.0.0/node_modules/@modelcontextprotocol/server/dist/stdio.mjs
33
33
  var StdioServerTransport = class {
@@ -812,7 +812,7 @@ function exact2(v, keys) {
812
812
  // apps/product-cli/package.json
813
813
  var package_default2 = {
814
814
  name: "@ohmyhost/product-cli",
815
- version: "0.1.25",
815
+ version: "0.1.27",
816
816
  private: true,
817
817
  ohmyhost: {
818
818
  deployment: "production",
@@ -1906,7 +1906,7 @@ var ALL_LOCKFILES = Object.freeze(Object.values(PACKAGE_MANAGER_CONTRACTS).flatM
1906
1906
  var VERIFIED_VERSIONS = Object.freeze({
1907
1907
  vite: /* @__PURE__ */ new Set(["5.4.21", "8.0.16", "8.2.2"]),
1908
1908
  "tanstack-start": /* @__PURE__ */ new Set(["1.168.26", "1.168.49"]),
1909
- nextjs: /* @__PURE__ */ new Set(["15.5.23", "16.3.2"])
1909
+ nextjs: /* @__PURE__ */ new Set(["15.5.26", "16.3.7"])
1910
1910
  });
1911
1911
  var PUSH_AND_PLAN = "Commit and push the change, then plan the new commit.";
1912
1912
  var FRAMEWORK_CONVERSION_DETAILS = Object.freeze({
@@ -2512,6 +2512,7 @@ var parsePaidDomain = (value) => {
2512
2512
  const records2 = input["validation_records"];
2513
2513
  if (![
2514
2514
  "not_configured",
2515
+ "awaiting_deployment",
2515
2516
  "pending",
2516
2517
  "active",
2517
2518
  "reconciliation_required",
@@ -2522,7 +2523,7 @@ var parsePaidDomain = (value) => {
2522
2523
  "paid_plan_required",
2523
2524
  "insufficient_organization_credits",
2524
2525
  "project_budget_exceeded"
2525
- ].includes(input["suspension_reason"]) || status === "suspended" !== (input["suspension_reason"] !== null) || status === "suspended" && input["url"] !== null || input["environment"] !== "prod" || !isSaasCnameTarget(input["cname_target"]) || hostname !== null && !isPaidHostname(hostname) || input["custom_hostname_status"] !== null && typeof input["custom_hostname_status"] !== "string" || input["ssl_status"] !== null && typeof input["ssl_status"] !== "string" || !Array.isArray(records2) || records2.length > 16 || !records2.every(isPaidValidationRecord) || input["url"] !== null && input["url"] !== `https://${String(hostname)}`) {
2526
+ ].includes(input["suspension_reason"]) || status === "suspended" !== (input["suspension_reason"] !== null) || status === "suspended" && input["url"] !== null || input["environment"] !== "prod" || !isSaasCnameTarget(input["cname_target"]) || hostname !== null && !isPaidHostname(hostname) || input["custom_hostname_status"] !== null && typeof input["custom_hostname_status"] !== "string" || input["ssl_status"] !== null && typeof input["ssl_status"] !== "string" || !Array.isArray(records2) || records2.length > 16 || !records2.every(isPaidValidationRecord) || input["url"] !== null && input["url"] !== `https://${String(hostname)}` || status === "awaiting_deployment" && (hostname === null || input["custom_hostname_status"] !== null || input["ssl_status"] !== null || input["url"] !== null || records2.length !== 0)) {
2526
2527
  throw new ResponseContractError();
2527
2528
  }
2528
2529
  return input;
@@ -7282,8 +7283,8 @@ function createLocalOhmyhostMcpServer(dependencies) {
7282
7283
  idempotencyKey: input.idempotency_key
7283
7284
  }), mutationAnnotations());
7284
7285
  registerProductTool(server, dependencies, "domain_cloudflare_status", "Read the project's customer DNS authorization state, zone, scopes and expiry without credentials. authorized is not DNS/TLS readiness. For a Paid hostname, use domain_paid_apply with the original hostname/key after consent, then domain_paid_status. If DNS/TLS is pending, tell the customer to ask their agent again after 60 minutes; do not repeat correct records or create another deployment.", external_exports.object({ project_id: identifier2 }), (client2, input) => client2.getCloudflareDnsStatus(input.project_id));
7285
- registerProductTool(server, dependencies, "domain_paid_plan", "Plan a customer-owned production hostname and return the manual CNAME/validation instructions. This does not activate or change DNS. Without Paid, only a project that shows the powered-by flag (powered_by_flag_get) can activate its own hostname; for any other Free project domain_paid_apply answers paid_plan_required. production_deployment_required means Prod has no active deployment: deploy to Prod or promote the current Dev deployment, then plan again.", external_exports.object({ project_id: identifier2, hostname: domainName }), (client2, input) => client2.planPaidDomain({ projectId: input.project_id, hostname: input.hostname }));
7286
- registerProductTool(server, dependencies, "domain_paid_apply", "Activate the explicitly requested customer hostname. Requires Paid access, or a Free workspace whose project shows the powered-by flag (powered_by_flag_set, only with the owner's consent); otherwise it answers paid_plan_required. The backend may reuse only its scoped customer OAuth grant. After domain_cloudflare_status is authorized, replay the original hostname/key to reconcile its exact DNS records. Otherwise return the manual DNS records to the human. Preserve the original hostname/key after uncertainty; no arbitrary DNS or provider credentials are accepted. production_deployment_required changed nothing: deploy to Prod or promote Dev first, then repeat the same hostname/key.", external_exports.object({
7286
+ registerProductTool(server, dependencies, "domain_paid_plan", "Plan a customer-owned production hostname before or after the first Prod deployment. This reads the project and describes declaration and activation without changing DNS. domain_paid_apply can declare a hostname as awaiting_deployment for early Cloudflare consent. Without Paid, only a project that shows the powered-by flag (powered_by_flag_get) can connect its own hostname; for any other Free project domain_paid_apply answers paid_plan_required.", external_exports.object({ project_id: identifier2, hostname: domainName }), (client2, input) => client2.planPaidDomain({ projectId: input.project_id, hostname: input.hostname }));
7287
+ registerProductTool(server, dependencies, "domain_paid_apply", "Declare or activate the explicitly requested customer hostname. Requires Paid access, or a Free workspace whose project shows the powered-by flag (powered_by_flag_set, only with the owner's consent). Without an active Prod deployment, returns awaiting_deployment and reserves the hostname without provider resources, DNS changes or domain charges; request Cloudflare consent now, then deploy to Prod. After Prod succeeds and domain_cloudflare_status is authorized, replay the original hostname/key to activate and reconcile its exact DNS records. Otherwise return the manual records to the human. Preserve the original hostname/key after uncertainty; no arbitrary DNS or provider credentials are accepted.", external_exports.object({
7287
7288
  project_id: identifier2,
7288
7289
  hostname: domainName,
7289
7290
  idempotency_key: idempotencyKey,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amerged/ohmyhost-mcp",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=22"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ohmyhost/mcp",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
4
4
  "private": true,
5
5
  "ohmyhost": {
6
6
  "deployment": "production",
@@ -576,7 +576,7 @@ export function createLocalOhmyhostMcpServer(dependencies: LocalOhmyhostMcpDepen
576
576
  server,
577
577
  dependencies,
578
578
  "domain_paid_plan",
579
- "Plan a customer-owned production hostname and return the manual CNAME/validation instructions. This does not activate or change DNS. Without Paid, only a project that shows the powered-by flag (powered_by_flag_get) can activate its own hostname; for any other Free project domain_paid_apply answers paid_plan_required. production_deployment_required means Prod has no active deployment: deploy to Prod or promote the current Dev deployment, then plan again.",
579
+ "Plan a customer-owned production hostname before or after the first Prod deployment. This reads the project and describes declaration and activation without changing DNS. domain_paid_apply can declare a hostname as awaiting_deployment for early Cloudflare consent. Without Paid, only a project that shows the powered-by flag (powered_by_flag_get) can connect its own hostname; for any other Free project domain_paid_apply answers paid_plan_required.",
580
580
  z.object({ project_id: identifier, hostname: domainName }),
581
581
  (client, input) =>
582
582
  client.planPaidDomain({ projectId: input.project_id, hostname: input.hostname }),
@@ -585,7 +585,7 @@ export function createLocalOhmyhostMcpServer(dependencies: LocalOhmyhostMcpDepen
585
585
  server,
586
586
  dependencies,
587
587
  "domain_paid_apply",
588
- "Activate the explicitly requested customer hostname. Requires Paid access, or a Free workspace whose project shows the powered-by flag (powered_by_flag_set, only with the owner's consent); otherwise it answers paid_plan_required. The backend may reuse only its scoped customer OAuth grant. After domain_cloudflare_status is authorized, replay the original hostname/key to reconcile its exact DNS records. Otherwise return the manual DNS records to the human. Preserve the original hostname/key after uncertainty; no arbitrary DNS or provider credentials are accepted. production_deployment_required changed nothing: deploy to Prod or promote Dev first, then repeat the same hostname/key.",
588
+ "Declare or activate the explicitly requested customer hostname. Requires Paid access, or a Free workspace whose project shows the powered-by flag (powered_by_flag_set, only with the owner's consent). Without an active Prod deployment, returns awaiting_deployment and reserves the hostname without provider resources, DNS changes or domain charges; request Cloudflare consent now, then deploy to Prod. After Prod succeeds and domain_cloudflare_status is authorized, replay the original hostname/key to activate and reconcile its exact DNS records. Otherwise return the manual records to the human. Preserve the original hostname/key after uncertainty; no arbitrary DNS or provider credentials are accepted.",
589
589
  z.object({
590
590
  project_id: identifier,
591
591
  hostname: domainName,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ohmyhost/product-cli",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
4
4
  "private": true,
5
5
  "ohmyhost": {
6
6
  "deployment": "production",
@@ -292,8 +292,10 @@ export async function initializeRepository(
292
292
  const supabaseMigrationCount = applicationFiles.filter((path) =>
293
293
  /^supabase\/migrations\/[^/]+\.sql$/u.test(path),
294
294
  ).length;
295
- const postgresMigrationCount = applicationFiles.filter((path) =>
296
- /^postgres\/migrations\/[^/]+\.sql$/u.test(path),
295
+ const postgresMigrationRoot =
296
+ existingConfiguration?.database?.migrations ?? "postgres/migrations";
297
+ const postgresMigrationCount = applicationFiles.filter(
298
+ (path) => path.startsWith(`${postgresMigrationRoot}/`) && path.endsWith(".sql"),
297
299
  ).length;
298
300
  const edgeFunctionNames = new Set(
299
301
  applicationFiles.flatMap((path) => {
@@ -1228,7 +1230,7 @@ function repositoryBlockers(
1228
1230
  .join(", ");
1229
1231
  blockers.push({
1230
1232
  code: "framework_version_unsupported",
1231
- message: `${unsupported} is outside the versions ohmyho.st builds: next 15.5.x or 16.0.0–16.3.4, vite 5.4.0–8.2.2, @tanstack/react-start 1.168.26–1.168.49, as an exact version or a ^ or ~ range whose base version is inside. Pin a version in that range in package.json, update the lockfile, commit and push.`,
1233
+ message: `${unsupported} is outside the versions ohmyho.st builds: next 15.5.26+ (15.5.x) or 16.3.6–16.3.7, vite 5.4.0–8.2.2, @tanstack/react-start 1.168.26–1.168.49, as an exact version or a ^ or ~ range whose base version is inside. Pin a version in that range in package.json, update the lockfile, commit and push.`,
1232
1234
  });
1233
1235
  }
1234
1236
  const scripts = packageJson["scripts"];
@@ -1283,7 +1285,7 @@ function repositoryBlockers(
1283
1285
  blockers.push({
1284
1286
  code: "next_adapter_unconfigured",
1285
1287
  message:
1286
- 'Next.js needs scripts.build exactly "next build" or "next build --webpack", react and react-dom at exact versions such as "19.1.0" (no ^ or ~), next within 15.5.x or 16.0.0–16.3.4, and exactly one next.config.js, .mjs or .ts, with at most one open-next.config file. ohmyho.st adds the OpenNext build itself; do not make it the build script.',
1288
+ 'Next.js needs scripts.build exactly "next build" or "next build --webpack", react and react-dom at exact versions such as "19.1.0" (no ^ or ~), next within 15.5.26+ (15.5.x) or 16.3.6–16.3.7, and exactly one next.config.js, .mjs or .ts, with at most one open-next.config file. ohmyho.st adds the OpenNext build itself; do not make it the build script.',
1287
1289
  });
1288
1290
  }
1289
1291
  }
@@ -94,6 +94,7 @@ export interface PublicPaidDomainPlan {
94
94
  export interface PublicPaidDomain {
95
95
  readonly status:
96
96
  | "not_configured"
97
+ | "awaiting_deployment"
97
98
  | "pending"
98
99
  | "active"
99
100
  | "reconciliation_required"
@@ -153,6 +154,7 @@ export const parsePaidDomain = (value: unknown): PublicPaidDomain => {
153
154
  if (
154
155
  ![
155
156
  "not_configured",
157
+ "awaiting_deployment",
156
158
  "pending",
157
159
  "active",
158
160
  "reconciliation_required",
@@ -176,7 +178,13 @@ export const parsePaidDomain = (value: unknown): PublicPaidDomain => {
176
178
  !Array.isArray(records) ||
177
179
  records.length > 16 ||
178
180
  !records.every(isPaidValidationRecord) ||
179
- (input["url"] !== null && input["url"] !== `https://${String(hostname)}`)
181
+ (input["url"] !== null && input["url"] !== `https://${String(hostname)}`) ||
182
+ (status === "awaiting_deployment" &&
183
+ (hostname === null ||
184
+ input["custom_hostname_status"] !== null ||
185
+ input["ssl_status"] !== null ||
186
+ input["url"] !== null ||
187
+ records.length !== 0))
180
188
  ) {
181
189
  throw new ResponseContractError();
182
190
  }