@cloudbase/cloudbase-mcp 2.25.3 → 2.25.5

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.cjs CHANGED
@@ -29512,6 +29512,22 @@ function buildLoginConfigNextStep(loginMethods) {
29512
29512
  },
29513
29513
  };
29514
29514
  }
29515
+ /**
29516
+ * 短信验证码默认通道提示:开启 phone 登录后即可用云开发默认短信通道收发验证码,
29517
+ * 不需要配置短信签名/模板/自定义 Provider。仅当需要自定义模板、签名或更换短信服务商时,
29518
+ * 才需要配置 SmsVerificationConfig / 自定义短信通道。
29519
+ */
29520
+ function buildSmsHint(loginMethods) {
29521
+ if (!loginMethods.phone) {
29522
+ return undefined;
29523
+ }
29524
+ return {
29525
+ defaultChannelReady: true,
29526
+ message: "短信验证码登录已开启,可直接使用云开发默认短信通道收发验证码,无需配置短信签名/模板/自定义 Provider。" +
29527
+ "前端调用 auth.getVerification({ phone_number }) 发送验证码、auth.signInWithSms({ verificationInfo, verificationCode, phoneNum }) 登录。" +
29528
+ "仅当需要自定义短信模板/签名或更换短信服务商时,才需要配置 SmsVerificationConfig 或接入自定义短信通道。",
29529
+ };
29530
+ }
29515
29531
  function extractProviders(value) {
29516
29532
  const payload = normalizePlainObject(value, "providersResult");
29517
29533
  const providers = payload?.Providers ?? payload?.ProviderList ?? payload?.Data ?? [];
@@ -29692,12 +29708,14 @@ function registerAppAuthTools(server) {
29692
29708
  const loginMethods = buildLoginMethods(result);
29693
29709
  const nextStep = buildLoginConfigNextStep(loginMethods);
29694
29710
  const webSdkHint = buildWebSdkHint(loginMethods);
29711
+ const smsHint = buildSmsHint(loginMethods);
29695
29712
  return buildSupabaseLikeAuthResponse({
29696
29713
  success: true,
29697
29714
  envId,
29698
29715
  loginMethods,
29699
29716
  ...(nextStep ? { next_step: nextStep } : {}),
29700
29717
  ...(webSdkHint ? { webSdkHint } : {}),
29718
+ ...(smsHint ? { smsHint } : {}),
29701
29719
  });
29702
29720
  }
29703
29721
  case "listProviders": {
@@ -29773,7 +29791,7 @@ function registerAppAuthTools(server) {
29773
29791
  }));
29774
29792
  server.registerTool?.("manageAppAuth", {
29775
29793
  title: "管理 CloudBase 应用认证配置",
29776
- description: "CloudBase 应用侧认证配置写入口。用于修改登录方式、provider、client 配置,确保 publishable key,以及创建或删除 API key、自定义登录密钥。⚠️ 本工具为管理端配置工具,不执行用户登录。当任务要求编写客户端登录代码时(例如「用 JS SDK 登录」),应先通过本工具完成配置(如启用 usernamePassword、获取 publishable key),再在项目代码中编写 @cloudbase/js-sdk 客户端登录代码(如 auth.signInWithPassword()),而非使用本工具完成登录。若前端要接受普通用户名样式标识符,应先执行 action=patchLoginStrategy 并传入 patch={ usernamePassword: true },再实现对应前端登录逻辑。⚠️ action=createApiKey 返回体中的 created 字段表示是否真正新建:created=false 说明复用了环境中已存在的 key,此时 keyName/expireIn 入参不会生效,返回的 keyName/expireAt 均为服务端真实值,并会附带 warnings,切勿把它当作临时凭证分发。",
29794
+ description: "CloudBase 应用侧认证配置写入口。用于修改登录方式、provider、client 配置,确保 publishable key,以及创建或删除 API key、自定义登录密钥。⚠️ 本工具为管理端配置工具,不执行用户登录。当任务要求编写客户端登录代码时(例如「用 JS SDK 登录」),应先通过本工具完成配置(如启用 usernamePassword、获取 publishable key),再在项目代码中编写 @cloudbase/js-sdk 客户端登录代码(如 auth.signInWithPassword()),而非使用本工具完成登录。若前端要接受普通用户名样式标识符,应先执行 action=patchLoginStrategy 并传入 patch={ usernamePassword: true },再实现对应前端登录逻辑。⚠️ 短信验证码登录(patch={ phone: true })使用云开发默认短信通道,开启后即可收发验证码,不需要配置短信签名/模板/自定义 Provider;仅当需要自定义模板/签名或更换短信服务商时才需配置 SmsVerificationConfig 或自定义短信通道。⚠️ action=createApiKey 返回体中的 created 字段表示是否真正新建:created=false 说明复用了环境中已存在的 key,此时 keyName/expireIn 入参不会生效,返回的 keyName/expireAt 均为服务端真实值,并会附带 warnings,切勿把它当作临时凭证分发。",
29777
29795
  inputSchema: {
29778
29796
  action: zod_1.z.enum(MANAGE_APP_AUTH_ACTIONS),
29779
29797
  patch: zod_1.z
@@ -29839,12 +29857,14 @@ function registerAppAuthTools(server) {
29839
29857
  const loginMethods = buildLoginMethods(confirmed);
29840
29858
  const nextStep = buildLoginConfigNextStep(loginMethods);
29841
29859
  const webSdkHint = buildWebSdkHint(loginMethods);
29860
+ const smsHint = buildSmsHint(loginMethods);
29842
29861
  return buildSupabaseLikeAuthResponse({
29843
29862
  success: true,
29844
29863
  envId,
29845
29864
  loginMethods,
29846
29865
  ...(nextStep ? { next_step: nextStep } : {}),
29847
29866
  ...(webSdkHint ? { webSdkHint } : {}),
29867
+ ...(smsHint ? { smsHint } : {}),
29848
29868
  });
29849
29869
  }
29850
29870
  case "addProvider": {
@@ -91031,7 +91051,7 @@ const TRIGGER_SCHEMA = zod_1.z.object({
91031
91051
  const CREATE_FUNCTION_SCHEMA = zod_1.z.object({
91032
91052
  name: zod_1.z.string().describe("函数名称"),
91033
91053
  type: zod_1.z.enum(["Event", "HTTP"]).optional().describe("函数类型"),
91034
- protocolType: zod_1.z.enum(["HTTP", "WS"]).optional().describe("HTTP 云函数协议类型"),
91054
+ protocolType: zod_1.z.enum(["WS"]).optional().describe("HTTP 函数访问协议,当前仅支持 WebSockets,取值为 WS(配合 protocolParams.wsParams 使用)。普通 HTTP 函数不要传此字段;传其他值(如 HTTP)会报 InvalidParameterValue.ProtocolType。"),
91035
91055
  protocolParams: zod_1.z
91036
91056
  .object({
91037
91057
  wsParams: zod_1.z
@@ -138335,7 +138355,7 @@ class TelemetryReporter {
138335
138355
  const nodeVersion = process.version; // Node.js版本
138336
138356
  const arch = os_1.default.arch(); // 系统架构
138337
138357
  // 从构建时注入的版本号获取MCP版本信息
138338
- const mcpVersion = process.env.npm_package_version || "2.25.3" || 0;
138358
+ const mcpVersion = process.env.npm_package_version || "2.25.5" || 0;
138339
138359
  return {
138340
138360
  userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
138341
138361
  deviceId: this.deviceId,
@@ -162248,6 +162268,14 @@ function collectMigrationVersions(value, found = new Set()) {
162248
162268
  /** Brief retries before concluding a pushed migration never landed (Push can be async). */
162249
162269
  const MIGRATION_VERIFY_ATTEMPTS = 4;
162250
162270
  const MIGRATION_VERIFY_DELAY_MS = 1500;
162271
+ /** Page size when hydrating remote migration history into a Push/Preview payload. */
162272
+ const MIGRATION_LIST_PAGE_SIZE = 100;
162273
+ /**
162274
+ * PushPGUserMigrations is async: poll DescribeTaskResult until Succeed/Failed.
162275
+ * Aligns with CLI `tcb db pg migration up` and Manager SDK docs.
162276
+ */
162277
+ const MIGRATION_TASK_POLL_INTERVAL_MS = 1500;
162278
+ const MIGRATION_TASK_MAX_WAIT_MS = 90_000;
162251
162279
  /**
162252
162280
  * Confirm a pushed migration version is present in the remote migration history.
162253
162281
  *
@@ -162281,6 +162309,99 @@ async function verifyMigrationApplied(context, version, cloudBaseOptions) {
162281
162309
  }
162282
162310
  return { applied: null, error: lastError };
162283
162311
  }
162312
+ function extractMigrationSummaries(history) {
162313
+ const raw = history.Migrations;
162314
+ if (!Array.isArray(raw)) {
162315
+ return [];
162316
+ }
162317
+ const summaries = [];
162318
+ for (const item of raw) {
162319
+ if (!item || typeof item !== "object") {
162320
+ continue;
162321
+ }
162322
+ const row = item;
162323
+ const version = typeof row.Version === "string" ? row.Version.trim() : "";
162324
+ const name = typeof row.Name === "string" ? row.Name.trim() : "";
162325
+ if (version) {
162326
+ summaries.push({ Version: version, Name: name || version });
162327
+ }
162328
+ }
162329
+ return summaries;
162330
+ }
162331
+ /**
162332
+ * List every remote migration summary (paginated). Required before Push/Preview:
162333
+ * submitting only the pending migration while remote history exists yields
162334
+ * Executable=false with Conflicts reason remote_history_not_found_locally, and the
162335
+ * async task fails with "migration plan is not executable".
162336
+ */
162337
+ async function listAllRemoteMigrationSummaries(context, cloudBaseOptions) {
162338
+ const summaries = [];
162339
+ let offset = 0;
162340
+ let latestVersion = "";
162341
+ let total = 0;
162342
+ while (true) {
162343
+ const page = await callPgMigrationApi(context, "ListPGUserMigrations", { Limit: MIGRATION_LIST_PAGE_SIZE, Offset: offset }, cloudBaseOptions);
162344
+ const pageItems = extractMigrationSummaries(page);
162345
+ summaries.push(...pageItems);
162346
+ if (typeof page.LatestVersion === "string" && page.LatestVersion.trim()) {
162347
+ latestVersion = page.LatestVersion.trim();
162348
+ }
162349
+ if (typeof page.Total === "number" && Number.isFinite(page.Total)) {
162350
+ total = page.Total;
162351
+ }
162352
+ else {
162353
+ total = summaries.length;
162354
+ }
162355
+ if (pageItems.length < MIGRATION_LIST_PAGE_SIZE) {
162356
+ break;
162357
+ }
162358
+ offset += MIGRATION_LIST_PAGE_SIZE;
162359
+ }
162360
+ return { summaries, latestVersion, total };
162361
+ }
162362
+ /**
162363
+ * Build Push/Preview Migrations = remote history Queries + the pending migration.
162364
+ * Matches CLI behavior (submit full set; server skips already-applied versions).
162365
+ */
162366
+ async function buildMigrationsPayloadWithRemoteHistory(context, pending, cloudBaseOptions) {
162367
+ const { summaries, latestVersion } = await listAllRemoteMigrationSummaries(context, cloudBaseOptions);
162368
+ const migrations = [];
162369
+ for (const summary of summaries) {
162370
+ if (summary.Version === pending.Version) {
162371
+ // Caller supplies the authoritative SQL for this version.
162372
+ continue;
162373
+ }
162374
+ const detail = await callPgMigrationApi(context, "DescribePGUserMigration", { MigrationVersion: summary.Version }, cloudBaseOptions);
162375
+ const query = typeof detail.Query === "string" ? detail.Query : "";
162376
+ if (!query.trim()) {
162377
+ throw new Error(`DescribePGUserMigration returned empty Query for version=${summary.Version} (${summary.Name}). ` +
162378
+ "Cannot hydrate remote history for PushPGUserMigrations.");
162379
+ }
162380
+ migrations.push({
162381
+ Version: typeof detail.Version === "string" && detail.Version.trim() ? detail.Version.trim() : summary.Version,
162382
+ Name: typeof detail.Name === "string" && detail.Name.trim() ? detail.Name.trim() : summary.Name,
162383
+ Query: query,
162384
+ });
162385
+ }
162386
+ migrations.push(pending);
162387
+ return { migrations, remoteCount: summaries.length, latestVersion };
162388
+ }
162389
+ async function waitPgMigrationTask(context, taskId, cloudBaseOptions) {
162390
+ const deadline = Date.now() + MIGRATION_TASK_MAX_WAIT_MS;
162391
+ let last = { TaskId: taskId };
162392
+ while (Date.now() <= deadline) {
162393
+ last = (await callPgMigrationApi(context, "DescribeTaskResult", { TaskId: taskId }, cloudBaseOptions));
162394
+ const status = String(last.Status || "").toLowerCase();
162395
+ if (status === "succeed" || status === "failed") {
162396
+ return last;
162397
+ }
162398
+ await sleep(MIGRATION_TASK_POLL_INTERVAL_MS);
162399
+ }
162400
+ const error = new Error(`DescribeTaskResult timed out after ${Math.floor(MIGRATION_TASK_MAX_WAIT_MS / 1000)}s ` +
162401
+ `for TaskId=${taskId} (last Status=${last.Status || "-"}, Phase=${last.Phase || "-"}).`);
162402
+ error.lastTask = last;
162403
+ throw error;
162404
+ }
162284
162405
  const MIGRATION_VERSION_REQUIRED_MESSAGE = "migrationVersion is required (14-digit UTC timestamp YYYYMMDDHHMMSS). " +
162285
162406
  "Decide the version first, write local file migrations/<version>_<migrationName>.sql, " +
162286
162407
  "then call planMigration/applyMigration with the same migrationVersion and migrationName.";
@@ -163067,29 +163188,38 @@ async function handlePlanMigration(args, context, deps, cloudBaseOptions) {
163067
163188
  }
163068
163189
  const version = versionOrError;
163069
163190
  const localFileHint = buildLocalMigrationFileHint(version, args.migrationName);
163070
- const migration = {
163191
+ const pending = {
163071
163192
  Version: version,
163072
163193
  Name: args.migrationName,
163073
163194
  Query: args.sql,
163074
163195
  };
163075
163196
  if (args.rollbackSql?.trim()) {
163076
- migration.Rollback = args.rollbackSql;
163197
+ pending.Rollback = args.rollbackSql;
163077
163198
  }
163078
163199
  try {
163200
+ const hydrated = await buildMigrationsPayloadWithRemoteHistory(context, pending, cloudBaseOptions);
163079
163201
  const result = await callPgMigrationApi(context, "PreviewPGUserMigrations", {
163080
- Migrations: [migration],
163202
+ Migrations: hydrated.migrations,
163081
163203
  }, cloudBaseOptions);
163204
+ const executable = result.Executable === true;
163082
163205
  return buildPgToolResult({
163083
163206
  success: true,
163084
163207
  data: {
163085
163208
  migrationVersion: version,
163086
163209
  migrationName: args.migrationName,
163087
163210
  localFileHint,
163211
+ hydratedRemoteCount: hydrated.remoteCount,
163212
+ latestRemoteVersion: hydrated.latestVersion || null,
163213
+ executable,
163088
163214
  apiResult: result,
163089
163215
  },
163090
- message: `Migration plan generated via PreviewPGUserMigrations. Reuse migrationVersion=${version} on applyMigration. Ensure local file ${localFileHint} exists and matches.`,
163216
+ message: executable
163217
+ ? `Migration plan generated via PreviewPGUserMigrations (hydrated ${hydrated.remoteCount} remote migration(s)). Reuse migrationVersion=${version} on applyMigration. Ensure local file ${localFileHint} exists and matches.`
163218
+ : `Migration plan is NOT executable (PreviewPGUserMigrations.Executable=false after hydrating ${hydrated.remoteCount} remote migration(s)). Inspect apiResult.Conflicts before applyMigration. Common causes: version older than latest remote (${hydrated.latestVersion || "unknown"}), or checksum mismatch.`,
163091
163219
  nextActions: [
163092
- buildNextAction(MANAGE_PG_DATABASE, "applyMigration", "Review the plan above. If it looks correct, call applyMigration with the same migrationVersion.", {
163220
+ buildNextAction(MANAGE_PG_DATABASE, "applyMigration", executable
163221
+ ? "Review the plan above. If it looks correct, call applyMigration with the same migrationVersion."
163222
+ : "Resolve Conflicts (often pick a migrationVersion newer than LatestVersion), then retry planMigration/applyMigration.", {
163093
163223
  action: "applyMigration",
163094
163224
  migrationName: args.migrationName,
163095
163225
  migrationVersion: version,
@@ -163136,26 +163266,118 @@ async function handleApplyMigration(args, context, deps, cloudBaseOptions) {
163136
163266
  }
163137
163267
  const version = versionOrError;
163138
163268
  const localFileHint = buildLocalMigrationFileHint(version, args.migrationName);
163139
- const migration = {
163269
+ const pending = {
163140
163270
  Version: version,
163141
163271
  Name: args.migrationName,
163142
163272
  Query: args.sql,
163143
163273
  };
163144
163274
  if (args.rollbackSql?.trim()) {
163145
- migration.Rollback = args.rollbackSql;
163146
- }
163147
- const params = { Migrations: [migration] };
163148
- if (args.lockTimeoutMs !== undefined) {
163149
- params.LockTimeoutMs = args.lockTimeoutMs;
163150
- }
163151
- if (args.statementTimeoutMs !== undefined) {
163152
- params.StatementTimeoutMs = args.statementTimeoutMs;
163275
+ pending.Rollback = args.rollbackSql;
163153
163276
  }
163154
163277
  try {
163278
+ // Pushing only the pending migration while remote history exists makes the plan
163279
+ // non-executable (remote_history_not_found_locally). Hydrate remote Queries first,
163280
+ // matching CLI `tcb db pg migration up` (full list; server skips applied).
163281
+ const hydrated = await buildMigrationsPayloadWithRemoteHistory(context, pending, cloudBaseOptions);
163282
+ const preview = await callPgMigrationApi(context, "PreviewPGUserMigrations", { Migrations: hydrated.migrations }, cloudBaseOptions);
163283
+ if (preview.Executable !== true) {
163284
+ return buildPgToolResult({
163285
+ success: false,
163286
+ errorCode: "MIGRATION_NOT_EXECUTABLE",
163287
+ data: {
163288
+ migrationVersion: version,
163289
+ migrationName: args.migrationName,
163290
+ localFileHint,
163291
+ hydratedRemoteCount: hydrated.remoteCount,
163292
+ latestRemoteVersion: hydrated.latestVersion || null,
163293
+ previewResult: preview,
163294
+ verified: false,
163295
+ },
163296
+ message: `PreviewPGUserMigrations reported Executable=false for migrationVersion=${version} ` +
163297
+ `(latest remote=${hydrated.latestVersion || "unknown"}, hydratedRemoteCount=${hydrated.remoteCount}). ` +
163298
+ "Push was NOT submitted. Inspect previewResult.Conflicts — common reasons: " +
163299
+ "local_migration_before_latest_remote (pick a newer 14-digit version) or checksum_mismatch. " +
163300
+ "If the schema change is urgent you may fall back to action=execute with allowDdlViaExecute=true, but that bypasses migration history.",
163301
+ nextActions: [
163302
+ buildNextAction(MANAGE_PG_DATABASE, "listMigrations", "Check LatestVersion and pick a migrationVersion strictly newer than it.", { action: "listMigrations", limit: 20 }),
163303
+ buildNextAction(MANAGE_PG_DATABASE, "planMigration", "Re-run planMigration after adjusting migrationVersion/SQL.", {
163304
+ action: "planMigration",
163305
+ migrationName: args.migrationName,
163306
+ migrationVersion: version,
163307
+ sql: args.sql,
163308
+ ...(args.rollbackSql ? { rollbackSql: args.rollbackSql } : {}),
163309
+ }),
163310
+ ],
163311
+ });
163312
+ }
163313
+ const params = { Migrations: hydrated.migrations };
163314
+ if (args.lockTimeoutMs !== undefined) {
163315
+ params.LockTimeoutMs = args.lockTimeoutMs;
163316
+ }
163317
+ if (args.statementTimeoutMs !== undefined) {
163318
+ params.StatementTimeoutMs = args.statementTimeoutMs;
163319
+ }
163155
163320
  const result = await callPgMigrationApi(context, "PushPGUserMigrations", params, cloudBaseOptions);
163156
- // PushPGUserMigrations may return a TaskId without the migration having taken
163157
- // effect. Confirm against the remote history before reporting success, so callers
163158
- // never get a false-positive success for a silently dropped migration.
163321
+ const taskId = typeof result.TaskId === "string" ? result.TaskId.trim() : "";
163322
+ let taskResult = null;
163323
+ if (taskId) {
163324
+ try {
163325
+ taskResult = await waitPgMigrationTask(context, taskId, cloudBaseOptions);
163326
+ }
163327
+ catch (error) {
163328
+ const lastTask = error.lastTask;
163329
+ return buildPgToolResult({
163330
+ success: false,
163331
+ errorCode: "MIGRATION_TASK_TIMEOUT",
163332
+ data: {
163333
+ migrationVersion: version,
163334
+ migrationName: args.migrationName,
163335
+ localFileHint,
163336
+ hydratedRemoteCount: hydrated.remoteCount,
163337
+ apiResult: result,
163338
+ taskResult: lastTask ?? { TaskId: taskId },
163339
+ verified: null,
163340
+ },
163341
+ message: `PushPGUserMigrations returned TaskId=${taskId}, but waiting for DescribeTaskResult timed out: ` +
163342
+ `${error instanceof Error ? error.message : String(error)}. ` +
163343
+ "The migration may still be running — check action=listMigrations before retrying or falling back to execute.",
163344
+ nextActions: [
163345
+ buildNextAction(MANAGE_PG_DATABASE, "listMigrations", "Check whether the migrationVersion eventually landed.", { action: "listMigrations", limit: 20 }),
163346
+ ],
163347
+ });
163348
+ }
163349
+ const status = String(taskResult.Status || "").toLowerCase();
163350
+ if (status === "failed") {
163351
+ return buildPgToolResult({
163352
+ success: false,
163353
+ errorCode: "MIGRATION_TASK_FAILED",
163354
+ data: {
163355
+ migrationVersion: version,
163356
+ migrationName: args.migrationName,
163357
+ localFileHint,
163358
+ hydratedRemoteCount: hydrated.remoteCount,
163359
+ apiResult: result,
163360
+ taskResult: taskResult,
163361
+ verified: false,
163362
+ },
163363
+ message: `PushPGUserMigrations TaskId=${taskId} failed at phase=${taskResult.Phase || "-"}: ` +
163364
+ `${taskResult.Reason || "unknown reason"}. ` +
163365
+ "The migration did NOT take effect. Fix Conflicts/SQL (or use a newer migrationVersion), then retry applyMigration. " +
163366
+ "Urgent bypass: action=execute with allowDdlViaExecute=true (skips migration history).",
163367
+ nextActions: [
163368
+ buildNextAction(MANAGE_PG_DATABASE, "planMigration", "Preview again to inspect Conflicts before retrying apply.", {
163369
+ action: "planMigration",
163370
+ migrationName: args.migrationName,
163371
+ migrationVersion: version,
163372
+ sql: args.sql,
163373
+ ...(args.rollbackSql ? { rollbackSql: args.rollbackSql } : {}),
163374
+ }),
163375
+ buildNextAction(MANAGE_PG_DATABASE, "listMigrations", "Confirm the version is still absent from remote history.", { action: "listMigrations", limit: 20 }),
163376
+ ],
163377
+ });
163378
+ }
163379
+ }
163380
+ // Task Succeed (or sync response without TaskId): confirm history records the version.
163159
163381
  const verification = await verifyMigrationApplied(context, version, cloudBaseOptions);
163160
163382
  if (verification.applied === false) {
163161
163383
  return buildPgToolResult({
@@ -163165,10 +163387,12 @@ async function handleApplyMigration(args, context, deps, cloudBaseOptions) {
163165
163387
  migrationVersion: version,
163166
163388
  migrationName: args.migrationName,
163167
163389
  localFileHint,
163390
+ hydratedRemoteCount: hydrated.remoteCount,
163168
163391
  apiResult: result,
163392
+ taskResult: taskResult,
163169
163393
  verified: false,
163170
163394
  },
163171
- message: `PushPGUserMigrations returned without error, but migrationVersion=${version} is not present in the remote migration history, ` +
163395
+ message: `PushPGUserMigrations completed (TaskId=${taskId || "none"}), but migrationVersion=${version} is not present in the remote migration history, ` +
163172
163396
  "so the migration did NOT take effect. Do not assume the schema change is applied. " +
163173
163397
  "Re-check the SQL and migrationVersion, inspect the migration with action=migrationDetail, and retry action=applyMigration. " +
163174
163398
  "If the schema change is urgent you may fall back to action=execute with allowDdlViaExecute=true, but that bypasses migration history.",
@@ -163186,7 +163410,9 @@ async function handleApplyMigration(args, context, deps, cloudBaseOptions) {
163186
163410
  migrationVersion: version,
163187
163411
  migrationName: args.migrationName,
163188
163412
  localFileHint,
163413
+ hydratedRemoteCount: hydrated.remoteCount,
163189
163414
  apiResult: result,
163415
+ taskResult: taskResult,
163190
163416
  verified: null,
163191
163417
  },
163192
163418
  message: `PushPGUserMigrations was submitted, but verifying migrationVersion=${version} against the remote history failed: ${verification.error}. ` +
@@ -163202,10 +163428,12 @@ async function handleApplyMigration(args, context, deps, cloudBaseOptions) {
163202
163428
  migrationVersion: version,
163203
163429
  migrationName: args.migrationName,
163204
163430
  localFileHint,
163431
+ hydratedRemoteCount: hydrated.remoteCount,
163205
163432
  apiResult: result,
163433
+ taskResult: taskResult,
163206
163434
  verified: true,
163207
163435
  },
163208
- message: `Migrations applied via PushPGUserMigrations and verified present in the remote migration history. Ensure local file ${localFileHint} exists and matches.`,
163436
+ message: `Migrations applied via PushPGUserMigrations (hydrated ${hydrated.remoteCount} remote migration(s)), task ${taskId ? `TaskId=${taskId} ` : ""}verified present in the remote migration history. Ensure local file ${localFileHint} exists and matches.`,
163209
163437
  });
163210
163438
  }
163211
163439
  catch (error) {
@@ -198748,7 +198976,7 @@ ${envIdSection}
198748
198976
  ## 环境信息
198749
198977
  - 操作系统: ${os_1.default.type()} ${os_1.default.release()}
198750
198978
  - Node.js版本: ${process.version}
198751
- - MCP 版本:${process.env.npm_package_version || "2.25.3" || 0}
198979
+ - MCP 版本:${process.env.npm_package_version || "2.25.5" || 0}
198752
198980
  - 系统架构: ${os_1.default.arch()}
198753
198981
  - 时间: ${new Date().toISOString()}
198754
198982
  - 请求ID: ${requestId}
@@ -198829,7 +199057,7 @@ function createWrappedHandler(name, handler, server) {
198829
199057
  requestId: (typeof error === 'object' && error && 'requestId' in error) ? error.requestId : '',
198830
199058
  ide: server.ide || process.env.INTEGRATION_IDE || ''
198831
199059
  });
198832
- const mcpVersion = true ? "2.25.3" : 0;
199060
+ const mcpVersion = true ? "2.25.5" : 0;
198833
199061
  const requestIdSuffix = requestId ? `\n🆔 RequestId: ${requestId}` : '';
198834
199062
  const enhancedErrorMessage = `${errorMessage}${requestIdSuffix}\n\n📦 CloudBase MCP v${mcpVersion}\n🔗 遇到问题?请复制以下链接到浏览器打开\n即可自动携带错误详情快速创建 GitHub Issue:\n${issueLink}`;
198835
199063
  // 创建新的错误对象,保持原有的错误类型但更新消息
@@ -215417,7 +215645,7 @@ function registerSetupTools(server) {
215417
215645
  server.registerTool("downloadTemplate", {
215418
215646
  title: "下载项目模板",
215419
215647
  description: `自动下载并部署CloudBase项目模板。
215420
- **Note**: Call this tool when the user requests to create a new project using a CloudBase template.\n\n支持的模板:\n- react: React + CloudBase 全栈应用模板\n- vue: Vue + CloudBase 全栈应用模板\n- miniprogram: 微信小程序 + 云开发模板 \n- uniapp: UniApp + CloudBase 跨端应用模板\n- rules: 只包含AI编辑器配置文件(包含Cursor、WindSurf、CodeBuddy等所有主流编辑器配置),适合在已有项目中补充AI编辑器配置\n\n支持的IDE类型:\n- all: 下载所有IDE配置\n- cursor: Cursor AI编辑器\n- 其他IDE类型见下方列表\n\n注意:如果未传入 ide 参数且无法从环境变量检测到 IDE,将提示错误并要求传入 ide 参数\n- windsurf: WindSurf AI编辑器\n- codebuddy: CodeBuddy AI编辑器\n- claude-code: Claude Code AI编辑器\n- cline: Cline AI编辑器\n- gemini-cli: Gemini CLI\n- opencode: OpenCode AI编辑器\n- qwen-code: 通义灵码\n- baidu-comate: 百度Comate\n- openai-codex-cli: OpenAI Codex CLI\n- augment-code: Augment Code\n- github-copilot: GitHub Copilot\n- roocode: RooCode AI编辑器\n- tongyi-lingma: 通义灵码\n- trae: Trae AI编辑器\n- qoder: Qoder AI编辑器\n- antigravity: Google Antigravity AI编辑器\n- vscode: Visual Studio Code\n- kiro: Kiro AI编辑器\n- aider: Aider AI编辑器\n\n特别说明:\n- rules 模板会自动包含当前 mcp 版本号信息(版本号:${ true ? "2.25.3" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
215648
+ **Note**: Call this tool when the user requests to create a new project using a CloudBase template.\n\n支持的模板:\n- react: React + CloudBase 全栈应用模板\n- vue: Vue + CloudBase 全栈应用模板\n- miniprogram: 微信小程序 + 云开发模板 \n- uniapp: UniApp + CloudBase 跨端应用模板\n- rules: 只包含AI编辑器配置文件(包含Cursor、WindSurf、CodeBuddy等所有主流编辑器配置),适合在已有项目中补充AI编辑器配置\n\n支持的IDE类型:\n- all: 下载所有IDE配置\n- cursor: Cursor AI编辑器\n- 其他IDE类型见下方列表\n\n注意:如果未传入 ide 参数且无法从环境变量检测到 IDE,将提示错误并要求传入 ide 参数\n- windsurf: WindSurf AI编辑器\n- codebuddy: CodeBuddy AI编辑器\n- claude-code: Claude Code AI编辑器\n- cline: Cline AI编辑器\n- gemini-cli: Gemini CLI\n- opencode: OpenCode AI编辑器\n- qwen-code: 通义灵码\n- baidu-comate: 百度Comate\n- openai-codex-cli: OpenAI Codex CLI\n- augment-code: Augment Code\n- github-copilot: GitHub Copilot\n- roocode: RooCode AI编辑器\n- tongyi-lingma: 通义灵码\n- trae: Trae AI编辑器\n- qoder: Qoder AI编辑器\n- antigravity: Google Antigravity AI编辑器\n- vscode: Visual Studio Code\n- kiro: Kiro AI编辑器\n- aider: Aider AI编辑器\n\n特别说明:\n- rules 模板会自动包含当前 mcp 版本号信息(版本号:${ true ? "2.25.5" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
215421
215649
  inputSchema: {
215422
215650
  template: zod_1.z
215423
215651
  .enum(["react", "vue", "miniprogram", "uniapp", "rules"])
@@ -232521,6 +232749,7 @@ const QUERY_GATEWAY_ACTIONS = [
232521
232749
  "listRoutes",
232522
232750
  "getRoute",
232523
232751
  "listCustomDomains",
232752
+ "getPrivilege",
232524
232753
  ];
232525
232754
  const MANAGE_GATEWAY_ACTIONS = [
232526
232755
  "createRoute",
@@ -232528,6 +232757,8 @@ const MANAGE_GATEWAY_ACTIONS = [
232528
232757
  "deleteRoute",
232529
232758
  "bindCustomDomain",
232530
232759
  "deleteCustomDomain",
232760
+ "enableService",
232761
+ "authSwitch",
232531
232762
  ];
232532
232763
  /** DomainType of the environment default HTTP service (gateway) domain. */
232533
232764
  const HTTP_SERVICE_DOMAIN_TYPE = "HTTPSERVICE";
@@ -232624,6 +232855,32 @@ function registerGatewayTools(server) {
232624
232855
  candidates.find((item) => item.Enable !== false) ??
232625
232856
  candidates[0]);
232626
232857
  };
232858
+ const getGatewayPrivilege = async () => {
232859
+ const cloudbase = await getManager();
232860
+ const result = await cloudbase
232861
+ .commonService("tcb", "2018-06-08")
232862
+ .call({
232863
+ Action: "DescribeCloudBaseGWPrivilege",
232864
+ Param: {
232865
+ ServiceId: await resolveEnvId(),
232866
+ },
232867
+ });
232868
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
232869
+ return result ?? {};
232870
+ };
232871
+ const buildPrivilegeDescription = (privilege) => {
232872
+ const serviceStatus = privilege.EnableService === undefined
232873
+ ? "未知"
232874
+ : privilege.EnableService === true
232875
+ ? "已开启"
232876
+ : "未开启";
232877
+ const authStatus = privilege.EnableAuth === undefined
232878
+ ? "未知"
232879
+ : privilege.EnableAuth === true
232880
+ ? "已开启"
232881
+ : "未开启";
232882
+ return `HTTP 网关${serviceStatus},访问鉴权${authStatus}`;
232883
+ };
232627
232884
  const resolveDefaultHttpDomain = async () => {
232628
232885
  // Match console DescribeHTTPServiceRoute usage: filter DomainType=HTTPSERVICE.
232629
232886
  // Envs often also expose an IsDefault STATIC_STORE domain (*.tcloudbaseapp.com);
@@ -232796,6 +233053,28 @@ function registerGatewayTools(server) {
232796
233053
  },
232797
233054
  ]);
232798
233055
  }
233056
+ case "getPrivilege": {
233057
+ const privilege = await getGatewayPrivilege();
233058
+ const enableService = privilege.EnableService === true;
233059
+ const enableAuth = privilege.EnableAuth === true;
233060
+ return buildEnvelope({
233061
+ action: input.action,
233062
+ enableService,
233063
+ enableAuth,
233064
+ raw: privilege,
233065
+ }, buildPrivilegeDescription(privilege) +
233066
+ (enableService
233067
+ ? ""
233068
+ : ";若路由创建成功但访问报 HTTPSERVICE_NONACTIVATED(403),请先开启 HTTP 网关"), enableService
233069
+ ? undefined
233070
+ : [
233071
+ {
233072
+ tool: "manageGateway",
233073
+ action: "enableService",
233074
+ reason: "开启 HTTP 网关总开关(EnableService),开启后路由即可通过默认域访问",
233075
+ },
233076
+ ]);
233077
+ }
232799
233078
  default:
232800
233079
  throw new Error(`不支持的操作类型: ${input.action}`);
232801
233080
  }
@@ -232826,6 +233105,28 @@ function registerGatewayTools(server) {
232826
233105
  throw err;
232827
233106
  }
232828
233107
  (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
233108
+ // 探测 HTTP 网关总开关:未开启时提示 HTTPSERVICE_NONACTIVATED 风险并引导开启。
233109
+ // 探测失败不阻断路由创建结果,仅追加弱提示。
233110
+ let privilegeHint = "";
233111
+ let privilegeNextActions = [];
233112
+ try {
233113
+ const privilege = await getGatewayPrivilege();
233114
+ if (privilege.EnableService !== true) {
233115
+ privilegeHint =
233116
+ "⚠️ HTTP 网关总开关未开启,路由创建成功后访问仍将返回 HTTPSERVICE_NONACTIVATED(403);请先调用 manageGateway(action=\"enableService\", enable=true) 开启,再等待 30 秒到 3 分钟访问。";
233117
+ privilegeNextActions = [
233118
+ {
233119
+ tool: "manageGateway",
233120
+ action: "enableService",
233121
+ reason: "开启 HTTP 网关总开关(EnableService),否则访问路由会报 HTTPSERVICE_NONACTIVATED(403)",
233122
+ },
233123
+ ];
233124
+ }
233125
+ }
233126
+ catch {
233127
+ privilegeHint =
233128
+ "(无法确认 HTTP 网关开关状态;若访问报 HTTPSERVICE_NONACTIVATED,请用 queryGateway(action=\"getPrivilege\") 查询后用 manageGateway(action=\"enableService\") 开启)";
233129
+ }
232829
233130
  return buildEnvelope({
232830
233131
  action: input.action,
232831
233132
  model: "httpServiceRoute",
@@ -232848,7 +233149,12 @@ function registerGatewayTools(server) {
232848
233149
  : payload.resolved.enablePathTransmission === false
232849
233150
  ? ";路径透传关闭(网关会剥掉触发路径前缀后再转发给后端)"
232850
233151
  : ";路径透传未显式设置(平台默认 false,会剥掉触发路径前缀)") +
232851
- `。注意:路由配置传播通常需要等待 30 秒到 3 分钟,请勿立即访问。该操作只创建网关入口,不会自动放开上游权限;若上游是云函数且需要匿名或浏览器直接访问,请继续检查函数资源权限。`, routeMutationNextActions(payload.resolved.upstreamResourceName));
233152
+ `。注意:路由配置传播通常需要等待 30 秒到 3 分钟,请勿立即访问。该操作只创建网关入口,不会自动放开上游权限;若上游是云函数且需要匿名或浏览器直接访问,请继续检查函数资源权限。` +
233153
+ (privilegeHint ? ` ${privilegeHint}` : ""), [
233154
+ ...privilegeNextActions,
233155
+ ...(routeMutationNextActions(payload.resolved.upstreamResourceName) ??
233156
+ []),
233157
+ ]);
232852
233158
  }
232853
233159
  case "updateRoute": {
232854
233160
  const cloudbase = await getManager();
@@ -232907,12 +233213,28 @@ function registerGatewayTools(server) {
232907
233213
  if (!input.domain || !input.certificateId) {
232908
233214
  throw new Error("action=bindCustomDomain 时必须提供 domain 和 certificateId");
232909
233215
  }
233216
+ const accessType = input.accessType ?? "DIRECT";
233217
+ if (accessType === "CUSTOM" && !input.customCname) {
233218
+ throw new Error("action=bindCustomDomain 且 accessType=CUSTOM 时必须提供 customCname(自有 CDN/WAF 的回源/回填地址,不是 DNS 解析目标)。" +
233219
+ "说明:https://docs.cloudbase.net/service/custom-domain");
233220
+ }
233221
+ if (accessType !== "CUSTOM" && input.customCname) {
233222
+ throw new Error("customCname 仅在 accessType=CUSTOM 时可用;普通绑定用默认 DIRECT,不要传 customCname。" +
233223
+ "说明:https://docs.cloudbase.net/service/custom-domain");
233224
+ }
232910
233225
  const cloudbase = await getManager();
232911
233226
  const result = await cloudbase.env.bindCustomDomain({
232912
233227
  EnvId: await resolveEnvId(),
232913
233228
  Domain: {
232914
233229
  Domain: input.domain,
232915
233230
  CertId: input.certificateId,
233231
+ AccessType: accessType,
233232
+ ...(input.enable !== undefined
233233
+ ? { Enable: input.enable }
233234
+ : {}),
233235
+ ...(input.customCname
233236
+ ? { CustomCname: input.customCname }
233237
+ : {}),
232916
233238
  },
232917
233239
  });
232918
233240
  (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
@@ -232920,24 +233242,118 @@ function registerGatewayTools(server) {
232920
233242
  action: input.action,
232921
233243
  domain: input.domain,
232922
233244
  certificateId: input.certificateId,
233245
+ accessType,
233246
+ ...(input.customCname
233247
+ ? { customCname: input.customCname }
233248
+ : {}),
233249
+ ...(input.enable !== undefined
233250
+ ? { enable: input.enable }
233251
+ : {}),
232923
233252
  raw: result,
232924
- }, "自定义域名绑定成功");
233253
+ }, `自定义域名绑定成功(${accessType})`, [
233254
+ {
233255
+ tool: "manageGateway",
233256
+ action: "createRoute",
233257
+ reason: "绑定后需 createRoute 添加访问路径,并完成 DNS CNAME 解析后才可访问",
233258
+ },
233259
+ ]);
232925
233260
  }
232926
233261
  case "deleteCustomDomain": {
232927
233262
  if (!input.domain) {
232928
233263
  throw new Error("action=deleteCustomDomain 时必须提供 domain");
232929
233264
  }
232930
233265
  const cloudbase = await getManager();
232931
- const result = await cloudbase.env.deleteCustomDomain({
232932
- EnvId: await resolveEnvId(),
232933
- Domain: input.domain,
233266
+ try {
233267
+ const result = await cloudbase.env.deleteCustomDomain({
233268
+ EnvId: await resolveEnvId(),
233269
+ Domain: input.domain,
233270
+ });
233271
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
233272
+ return buildEnvelope({
233273
+ action: input.action,
233274
+ domain: input.domain,
233275
+ raw: result,
233276
+ }, "自定义域名删除成功");
233277
+ }
233278
+ catch (error) {
233279
+ const message = error instanceof Error ? error.message : String(error);
233280
+ // SDK 在域名下仍有路由绑定时抛错,需先删路由再删域名
233281
+ if (/route binding/i.test(message)) {
233282
+ return {
233283
+ success: false,
233284
+ data: { action: input.action, domain: input.domain },
233285
+ message: `域名 ${input.domain} 下仍有路由绑定,需先删除路由再删除域名。` +
233286
+ `原始错误:${message}`,
233287
+ nextActions: [
233288
+ {
233289
+ tool: "queryGateway",
233290
+ action: "listRoutes",
233291
+ reason: "查看该域名下的路由,确认需要删除的路径",
233292
+ },
233293
+ {
233294
+ tool: "manageGateway",
233295
+ action: "deleteRoute",
233296
+ reason: "先删除该域名下的全部路由(逐个 deleteRoute),再重试 deleteCustomDomain",
233297
+ },
233298
+ ],
233299
+ };
233300
+ }
233301
+ throw error;
233302
+ }
233303
+ }
233304
+ case "enableService": {
233305
+ if (typeof input.enable !== "boolean") {
233306
+ throw new Error('action=enableService 时必须提供 enable 参数(boolean),如 enable=true 开启 HTTP 网关总开关、enable=false 关闭;禁止省略或传非布尔值。');
233307
+ }
233308
+ const cloudbase = await getManager();
233309
+ const result = await cloudbase.access.switchAuth(input.enable);
233310
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
233311
+ const serviceText = input.enable ? "开启" : "关闭";
233312
+ return buildEnvelope({
233313
+ action: input.action,
233314
+ enable: input.enable,
233315
+ raw: result,
233316
+ }, `HTTP 网关总开关${serviceText}成功`, [
233317
+ {
233318
+ tool: "queryGateway",
233319
+ action: "getPrivilege",
233320
+ reason: "复核 HTTP 网关总开关与访问鉴权状态",
233321
+ },
233322
+ ]);
233323
+ }
233324
+ case "authSwitch": {
233325
+ if (typeof input.enable !== "boolean") {
233326
+ throw new Error('action=authSwitch 时必须提供 enable 参数(boolean),如 enable=true 开启访问鉴权、enable=false 关闭;禁止省略或传非布尔值。');
233327
+ }
233328
+ const cloudbase = await getManager();
233329
+ const result = await cloudbase
233330
+ .commonService("tcb", "2018-06-08")
233331
+ .call({
233332
+ Action: "ModifyCloudBaseGWPrivilege",
233333
+ Param: {
233334
+ ServiceId: await resolveEnvId(),
233335
+ EnableService: input.enable,
233336
+ Options: [
233337
+ {
233338
+ Key: "authswitch",
233339
+ Value: input.enable ? "true" : "false",
233340
+ },
233341
+ ],
233342
+ },
232934
233343
  });
232935
233344
  (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
233345
+ const serviceText = input.enable ? "开启" : "关闭";
232936
233346
  return buildEnvelope({
232937
233347
  action: input.action,
232938
- domain: input.domain,
233348
+ enable: input.enable,
232939
233349
  raw: result,
232940
- }, "自定义域名删除成功");
233350
+ }, `HTTP 访问服务鉴权${serviceText}成功`, [
233351
+ {
233352
+ tool: "queryGateway",
233353
+ action: "getPrivilege",
233354
+ reason: "复核 HTTP 网关总开关与访问鉴权状态",
233355
+ },
233356
+ ]);
232941
233357
  }
232942
233358
  default:
232943
233359
  throw new Error(`不支持的操作类型: ${input.action}`);
@@ -232947,12 +233363,14 @@ function registerGatewayTools(server) {
232947
233363
  title: "查询 CloudBase 网关",
232948
233364
  description: "CloudBase HTTP 网关统一只读入口(Domain/Route)。查询域名下路径路由及其上游:" +
232949
233365
  "WEB_SCF/SCF=云函数,CBR=云托管,STATIC_STORE=静态托管,LH=轻量应用服务器。" +
232950
- "主键为 Domain + Path;listRoutes / getRoute / listCustomDomains。" +
233366
+ "主键为 Domain + Path;listRoutes / getRoute / listCustomDomains / getPrivilege。" +
233367
+ "getPrivilege 查询 HTTP 网关总开关(enableService)与访问鉴权(enableAuth)状态。" +
232951
233368
  "实现自定义域名访问前,先 listCustomDomains:若已有自定义域名,优先 createRoute 挂路由(无需证书 ID);仅在没有可用自定义域名时才 bindCustomDomain。",
232952
233369
  inputSchema: {
232953
233370
  action: zod_1.z
232954
233371
  .enum(QUERY_GATEWAY_ACTIONS)
232955
- .describe("只读操作类型:listRoutes、getRoute、listCustomDomains。" +
233372
+ .describe("只读操作类型:listRoutes、getRoute、listCustomDomains、getPrivilege。" +
233373
+ "getPrivilege 无需其他参数,直接返回 HTTP 网关总开关与访问鉴权状态。" +
232956
233374
  "自定义域名访问场景先 listCustomDomains 确认是否已有域名可复用。"),
232957
233375
  targetName: zod_1.z
232958
233376
  .string()
@@ -232985,14 +233403,17 @@ function registerGatewayTools(server) {
232985
233403
  "createRoute 只建网关入口,不改上游权限。" +
232986
233404
  "enablePathTransmission:默认 false 剥触发路径前缀;true 透传完整路径(CBR 多路由、WEB_SCF 自管子路径常需 true;STATIC_STORE 自定义触发路径映射站点根通常 false)。" +
232987
233405
  "⚠️ 自定义域名访问:若环境已有自定义域名(先 queryGateway listCustomDomains),优先 createRoute 并显式传入该 domain,无需 certificateId;" +
232988
- "仅首次绑定全新自定义域名时用 bindCustomDomain(需 certificateId)。CORS/安全域名用 envDomainManagement。",
233406
+ "仅首次绑定全新自定义域名时用 bindCustomDomain(需 certificateId)。CORS/安全域名用 envDomainManagement。" +
233407
+ "enableService/authSwitch:HTTP 网关总开关与访问鉴权开关;createRoute 后若访问报 HTTPSERVICE_NONACTIVATED,通常是总开关未开启(用 queryGateway getPrivilege 查询、enableService 开启)。",
232989
233408
  inputSchema: {
232990
233409
  action: zod_1.z
232991
233410
  .enum(MANAGE_GATEWAY_ACTIONS)
232992
- .describe("写操作:createRoute/updateRoute/deleteRoute 管理路由;bindCustomDomain/deleteCustomDomain 管理自定义域名。" +
233411
+ .describe("写操作:createRoute/updateRoute/deleteRoute 管理路由;bindCustomDomain/deleteCustomDomain 管理自定义域名;" +
233412
+ "enableService/authSwitch 开关 HTTP 网关总开关与访问鉴权(需配合 enable 参数)。" +
232993
233413
  "createRoute/updateRoute 必须提供 upstreamResourceType。" +
232994
233414
  "已有自定义域名时优先 createRoute(domain=已有域名) 实现访问,不必再次 bindCustomDomain / 传入 certificateId;" +
232995
- "bindCustomDomain 仅用于首次绑定新域名。"),
233415
+ "bindCustomDomain 仅用于首次绑定新域名(需 certificateId;可选 accessType=DIRECT|CDN|CUSTOM,CUSTOM 需 customCname;普通场景用默认 DIRECT)。" +
233416
+ "接入说明:https://docs.cloudbase.net/service/custom-domain"),
232996
233417
  targetName: zod_1.z
232997
233418
  .string()
232998
233419
  .optional()
@@ -233055,6 +233476,24 @@ function registerGatewayTools(server) {
233055
233476
  .optional()
233056
233477
  .describe("证书 ID。仅首次 bindCustomDomain 必填。" +
233057
233478
  "在已有自定义域名上 createRoute / updateRoute / deleteRoute 不需要 certificateId。"),
233479
+ accessType: zod_1.z
233480
+ .enum(["DIRECT", "CDN", "CUSTOM"])
233481
+ .optional()
233482
+ .describe("绑定类型(仅 bindCustomDomain,默认 DIRECT)。" +
233483
+ "DIRECT=直连(普通绑域名用这个);CDN=云开发 CDN;CUSTOM=自有 CDN/WAF(需 customCname)。" +
233484
+ "详见 https://docs.cloudbase.net/service/custom-domain"),
233485
+ customCname: zod_1.z
233486
+ .string()
233487
+ .optional()
233488
+ .describe("自有 CDN/WAF 的回源/回填地址(仅 bindCustomDomain 且 accessType=CUSTOM)。" +
233489
+ "不是 DNS 里用户域名要解析到的那个 CNAME;DIRECT/CDN 不要传。" +
233490
+ "详见 https://docs.cloudbase.net/service/custom-domain"),
233491
+ enable: zod_1.z
233492
+ .boolean()
233493
+ .optional()
233494
+ .describe("开关目标状态(enableService / authSwitch 必填):enable=true 开启,enable=false 关闭。" +
233495
+ "bindCustomDomain 可选:enable=false 表示绑定后禁用域名(默认启用)。" +
233496
+ "省略或非布尔值会返回参数错误。"),
233058
233497
  },
233059
233498
  annotations: {
233060
233499
  readOnlyHint: false,