@cloudbase/cloudbase-mcp 2.25.0 → 2.25.2

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
@@ -2233,7 +2233,7 @@ ${envIdSection}
2233
2233
  ## 环境信息
2234
2234
  - 操作系统: ${os_1.default.type()} ${os_1.default.release()}
2235
2235
  - Node.js版本: ${process.version}
2236
- - MCP 版本:${process.env.npm_package_version || "2.25.0" || 0}
2236
+ - MCP 版本:${process.env.npm_package_version || "2.25.2" || 0}
2237
2237
  - 系统架构: ${os_1.default.arch()}
2238
2238
  - 时间: ${new Date().toISOString()}
2239
2239
  - 请求ID: ${requestId}
@@ -2314,7 +2314,7 @@ function createWrappedHandler(name, handler, server) {
2314
2314
  requestId: (typeof error === 'object' && error && 'requestId' in error) ? error.requestId : '',
2315
2315
  ide: server.ide || process.env.INTEGRATION_IDE || ''
2316
2316
  });
2317
- const mcpVersion = true ? "2.25.0" : 0;
2317
+ const mcpVersion = true ? "2.25.2" : 0;
2318
2318
  const requestIdSuffix = requestId ? `\n🆔 RequestId: ${requestId}` : '';
2319
2319
  const enhancedErrorMessage = `${errorMessage}${requestIdSuffix}\n\n📦 CloudBase MCP v${mcpVersion}\n🔗 遇到问题?请复制以下链接到浏览器打开\n即可自动携带错误详情快速创建 GitHub Issue:\n${issueLink}`;
2320
2320
  // 创建新的错误对象,保持原有的错误类型但更新消息
@@ -2483,7 +2483,6 @@ const capi_js_1 = __webpack_require__(738);
2483
2483
  const cloudrun_js_1 = __webpack_require__(5023);
2484
2484
  const dataModel_js_1 = __webpack_require__(4052);
2485
2485
  const gateway_js_1 = __webpack_require__(4319);
2486
- const invite_code_js_1 = __webpack_require__(4760);
2487
2486
  const agents_js_1 = __webpack_require__(9527);
2488
2487
  const app_auth_js_1 = __webpack_require__(5313);
2489
2488
  const apps_js_1 = __webpack_require__(6817);
@@ -2514,7 +2513,6 @@ const DEFAULT_PLUGINS = [
2514
2513
  "logs",
2515
2514
  "agents",
2516
2515
  "download",
2517
- "invite-code",
2518
2516
  "capi",
2519
2517
  ];
2520
2518
  function registerDatabase(server) {
@@ -2556,7 +2554,6 @@ const AVAILABLE_PLUGINS = {
2556
2554
  logs: { name: "logs", register: logs_js_1.registerLogTools },
2557
2555
  agents: { name: "agents", register: agents_js_1.registerAgentTools },
2558
2556
  apps: { name: "apps", register: apps_js_1.registerAppTools },
2559
- "invite-code": { name: "invite-code", register: invite_code_js_1.registerInviteCodeTools },
2560
2557
  cloudrun: { name: "cloudrun", register: cloudrun_js_1.registerCloudRunTools },
2561
2558
  capi: { name: "capi", register: capi_js_1.registerCapiTools },
2562
2559
  };
@@ -2911,6 +2908,153 @@ function registerLogTools(server) {
2911
2908
 
2912
2909
  module.exports = __WEBPACK_EXTERNAL_MODULE__modelcontextprotocol_sdk_types_js_70eb1363__;
2913
2910
 
2911
+ /***/ }),
2912
+
2913
+ /***/ 2435:
2914
+ /***/ ((__unused_webpack_module, exports) => {
2915
+
2916
+
2917
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
2918
+ exports.rankGatewayAccessUrls = rankGatewayAccessUrls;
2919
+ exports.flattenHttpServiceRoutes = flattenHttpServiceRoutes;
2920
+ exports.filterRoutesByUpstream = filterRoutesByUpstream;
2921
+ exports.toAccessUrlEnvelope = toAccessUrlEnvelope;
2922
+ exports.resolveGatewayAccessUrls = resolveGatewayAccessUrls;
2923
+ exports.preferGatewayOrFallback = preferGatewayOrFallback;
2924
+ function normalizeAccessPath(path) {
2925
+ if (!path) {
2926
+ return "/";
2927
+ }
2928
+ return path.startsWith("/") ? path : `/${path}`;
2929
+ }
2930
+ function buildHttpsUrl(domain, path) {
2931
+ return `https://${domain}${normalizeAccessPath(path)}`;
2932
+ }
2933
+ /**
2934
+ * Rank gateway route URLs: custom domains (IsDefault !== true) before default domain.
2935
+ * Stable within each group; dedupe by full URL.
2936
+ */
2937
+ function rankGatewayAccessUrls(routes) {
2938
+ const mapped = routes
2939
+ .filter((route) => Boolean(route.Domain))
2940
+ .map((route) => {
2941
+ const path = normalizeAccessPath(route.Path);
2942
+ const isDefault = route.IsDefault === true;
2943
+ return {
2944
+ url: buildHttpsUrl(route.Domain, path),
2945
+ domain: route.Domain,
2946
+ path,
2947
+ isDefault,
2948
+ source: (isDefault
2949
+ ? "gateway.default"
2950
+ : "gateway.custom"),
2951
+ };
2952
+ });
2953
+ mapped.sort((a, b) => {
2954
+ if (a.isDefault === b.isDefault) {
2955
+ return 0;
2956
+ }
2957
+ return a.isDefault ? 1 : -1;
2958
+ });
2959
+ const seen = new Set();
2960
+ const deduped = [];
2961
+ for (const item of mapped) {
2962
+ if (seen.has(item.url)) {
2963
+ continue;
2964
+ }
2965
+ seen.add(item.url);
2966
+ deduped.push(item);
2967
+ }
2968
+ return deduped;
2969
+ }
2970
+ function flattenHttpServiceRoutes(result) {
2971
+ return (result.Domains ?? []).flatMap((domainItem) => (domainItem.Routes ?? []).map((route) => ({
2972
+ Domain: domainItem.Domain ?? "",
2973
+ IsDefault: domainItem.IsDefault,
2974
+ Path: typeof route.Path === "string" ? route.Path : undefined,
2975
+ UpstreamResourceType: typeof route.UpstreamResourceType === "string"
2976
+ ? route.UpstreamResourceType
2977
+ : undefined,
2978
+ UpstreamResourceName: typeof route.UpstreamResourceName === "string"
2979
+ ? route.UpstreamResourceName
2980
+ : undefined,
2981
+ })));
2982
+ }
2983
+ function filterRoutesByUpstream(routes, input) {
2984
+ const name = input.upstreamResourceName;
2985
+ const types = input.upstreamResourceTypes?.map((t) => String(t));
2986
+ return routes.filter((route) => {
2987
+ if (route.UpstreamResourceName !== name) {
2988
+ return false;
2989
+ }
2990
+ if (!types || types.length === 0) {
2991
+ return true;
2992
+ }
2993
+ return Boolean(route.UpstreamResourceType &&
2994
+ types.includes(String(route.UpstreamResourceType)));
2995
+ });
2996
+ }
2997
+ function toAccessUrlEnvelope(ranked) {
2998
+ if (ranked.length === 0) {
2999
+ return { accessUrls: [], routes: [] };
3000
+ }
3001
+ return {
3002
+ accessUrl: ranked[0].url,
3003
+ accessUrls: ranked.map((item) => item.url),
3004
+ accessUrlSource: ranked[0].source,
3005
+ routes: ranked,
3006
+ };
3007
+ }
3008
+ /**
3009
+ * Best-effort lookup of gateway access URLs for an upstream resource.
3010
+ * Never throws — returns empty lists on failure.
3011
+ */
3012
+ async function resolveGatewayAccessUrls(input) {
3013
+ try {
3014
+ const manager = await input.getManager();
3015
+ const result = await manager.env.describeHttpServiceRoute({
3016
+ EnvId: input.envId,
3017
+ Limit: 1000,
3018
+ });
3019
+ const flattened = flattenHttpServiceRoutes(result);
3020
+ const matched = filterRoutesByUpstream(flattened, {
3021
+ upstreamResourceName: input.upstreamResourceName,
3022
+ upstreamResourceTypes: input.upstreamResourceTypes,
3023
+ });
3024
+ return toAccessUrlEnvelope(rankGatewayAccessUrls(matched));
3025
+ }
3026
+ catch {
3027
+ return { accessUrls: [], routes: [] };
3028
+ }
3029
+ }
3030
+ /**
3031
+ * Merge ranked gateway URLs with a resource-native fallback URL.
3032
+ * Gateway custom/default always win over the fallback when present.
3033
+ */
3034
+ function preferGatewayOrFallback(input) {
3035
+ if (input.gateway.accessUrl) {
3036
+ const urls = [...input.gateway.accessUrls];
3037
+ if (input.fallbackUrl &&
3038
+ !urls.includes(input.fallbackUrl)) {
3039
+ urls.push(input.fallbackUrl);
3040
+ }
3041
+ return {
3042
+ accessUrl: input.gateway.accessUrl,
3043
+ accessUrls: urls,
3044
+ accessUrlSource: input.gateway.accessUrlSource,
3045
+ };
3046
+ }
3047
+ if (input.fallbackUrl) {
3048
+ return {
3049
+ accessUrl: input.fallbackUrl,
3050
+ accessUrls: [input.fallbackUrl],
3051
+ accessUrlSource: input.fallbackSource,
3052
+ };
3053
+ }
3054
+ return { accessUrls: [] };
3055
+ }
3056
+
3057
+
2914
3058
  /***/ }),
2915
3059
 
2916
3060
  /***/ 2448:
@@ -7151,6 +7295,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
7151
7295
  exports.registerGatewayTools = registerGatewayTools;
7152
7296
  const zod_1 = __webpack_require__(2971);
7153
7297
  const cloudbase_manager_js_1 = __webpack_require__(3431);
7298
+ const gateway_access_urls_js_1 = __webpack_require__(2435);
7154
7299
  const json_content_js_1 = __webpack_require__(4365);
7155
7300
  const QUERY_GATEWAY_ACTIONS = [
7156
7301
  "listRoutes",
@@ -7226,9 +7371,33 @@ function registerGatewayTools(server) {
7226
7371
  IsDefault: domainItem.IsDefault,
7227
7372
  ...route,
7228
7373
  })));
7229
- const buildRouteUrls = (routes) => Array.from(new Set(routes
7230
- .filter((route) => route.Domain && route.Path)
7231
- .map((route) => `https://${route.Domain}${normalizeAccessPath(String(route.Path))}`)));
7374
+ const buildRouteUrls = (routes) => {
7375
+ const candidates = routes.map((route) => ({
7376
+ Domain: route.Domain,
7377
+ Path: route.Path,
7378
+ IsDefault: route.IsDefault,
7379
+ UpstreamResourceType: route.UpstreamResourceType,
7380
+ UpstreamResourceName: route.UpstreamResourceName,
7381
+ }));
7382
+ return (0, gateway_access_urls_js_1.rankGatewayAccessUrls)(candidates).map((item) => item.url);
7383
+ };
7384
+ const buildAccessUrlFields = (routes) => {
7385
+ const candidates = routes.map((route) => ({
7386
+ Domain: route.Domain,
7387
+ Path: route.Path,
7388
+ IsDefault: route.IsDefault,
7389
+ UpstreamResourceType: route.UpstreamResourceType,
7390
+ UpstreamResourceName: route.UpstreamResourceName,
7391
+ }));
7392
+ const envelope = (0, gateway_access_urls_js_1.toAccessUrlEnvelope)((0, gateway_access_urls_js_1.rankGatewayAccessUrls)(candidates));
7393
+ return {
7394
+ ...(envelope.accessUrl ? { accessUrl: envelope.accessUrl } : {}),
7395
+ accessUrls: envelope.accessUrls,
7396
+ ...(envelope.accessUrlSource
7397
+ ? { accessUrlSource: envelope.accessUrlSource }
7398
+ : {}),
7399
+ };
7400
+ };
7232
7401
  const resolveDefaultHttpDomain = async () => {
7233
7402
  const routeInfo = await listHttpServiceRoutes();
7234
7403
  const domains = routeInfo.Domains ?? [];
@@ -7247,36 +7416,24 @@ function registerGatewayTools(server) {
7247
7416
  }
7248
7417
  return resolveDefaultHttpDomain();
7249
7418
  };
7250
- const mapUpstreamResourceType = (input) => {
7251
- if (input.upstreamResourceType) {
7252
- return input.upstreamResourceType;
7253
- }
7254
- if (input.type === "HTTP") {
7255
- return "WEB_SCF";
7256
- }
7257
- if (input.type === "Event") {
7258
- return "SCF";
7259
- }
7260
- if (input.requiresFunctionType || input.targetType === "function") {
7261
- throw new Error("为云函数创建/更新路由时必须显式提供 type(HTTP→WEB_SCF,Event→SCF)或 route.upstreamResourceType。省略会导致 HTTP 与 Event 函数互相误标,访问时可能返回 FUNCTION_PARAM_INVALID 或网关内部错误。");
7262
- }
7263
- throw new Error("必须提供 route.upstreamResourceType(SCF / WEB_SCF / CBR / STATIC_STORE / LH),或在函数场景提供 type=\"HTTP\"|\"Event\"。");
7419
+ const resolveUpstreamResourceType = (input) => {
7420
+ const resolved = input.routeUpstreamResourceType ?? input.upstreamResourceType;
7421
+ if (resolved) {
7422
+ return resolved;
7423
+ }
7424
+ throw new Error("必须提供 upstreamResourceType(或 route.upstreamResourceType):" +
7425
+ "WEB_SCF=HTTP云函数,SCF=Event云函数,CBR=云托管,STATIC_STORE=静态托管,LH=轻量应用服务器。" +
7426
+ "禁止仅凭 targetName/serviceName 推断上游类型。");
7264
7427
  };
7265
7428
  const normalizeRoutePayload = async (input) => {
7266
7429
  const upstreamResourceName = input.route?.serviceName ?? input.targetName;
7267
7430
  if (!upstreamResourceName) {
7268
- throw new Error("必须提供 targetName 或 route.serviceName 作为上游资源名称(例如云函数名)");
7269
- }
7270
- const isFunctionRoute = input.targetType === "function" ||
7271
- input.type !== undefined ||
7272
- input.route?.upstreamResourceType === "SCF" ||
7273
- input.route?.upstreamResourceType === "WEB_SCF" ||
7274
- (!input.route?.upstreamResourceType && Boolean(input.targetName));
7275
- const upstreamResourceType = mapUpstreamResourceType({
7276
- type: input.type,
7277
- targetType: input.targetType,
7278
- upstreamResourceType: input.route?.upstreamResourceType,
7279
- requiresFunctionType: isFunctionRoute,
7431
+ throw new Error("必须提供 targetName 或 route.serviceName 作为上游资源名称:" +
7432
+ "云函数名、云托管服务名,或静态托管实例名(常见为 staticstore)。");
7433
+ }
7434
+ const upstreamResourceType = resolveUpstreamResourceType({
7435
+ upstreamResourceType: input.upstreamResourceType,
7436
+ routeUpstreamResourceType: input.route?.upstreamResourceType,
7280
7437
  });
7281
7438
  const path = normalizeAccessPath(input.route?.path ?? input.path ?? `/${upstreamResourceName}`);
7282
7439
  const domain = await resolveRouteDomain(input.domain);
@@ -7285,18 +7442,25 @@ function registerGatewayTools(server) {
7285
7442
  : input.auth !== undefined
7286
7443
  ? input.auth
7287
7444
  : undefined;
7445
+ const enablePathTransmission = input.route?.enablePathTransmission !== undefined
7446
+ ? input.route.enablePathTransmission
7447
+ : input.enablePathTransmission !== undefined
7448
+ ? input.enablePathTransmission
7449
+ : undefined;
7450
+ const route = {
7451
+ Path: path,
7452
+ UpstreamResourceType: upstreamResourceType,
7453
+ UpstreamResourceName: upstreamResourceName,
7454
+ EnableAuth: enableAuth,
7455
+ };
7456
+ if (enablePathTransmission !== undefined) {
7457
+ route.EnablePathTransmission = enablePathTransmission;
7458
+ }
7288
7459
  return {
7289
7460
  EnvId: await resolveEnvId(),
7290
7461
  Domain: {
7291
7462
  Domain: domain,
7292
- Routes: [
7293
- {
7294
- Path: path,
7295
- UpstreamResourceType: upstreamResourceType,
7296
- UpstreamResourceName: upstreamResourceName,
7297
- EnableAuth: enableAuth,
7298
- },
7299
- ],
7463
+ Routes: [route],
7300
7464
  },
7301
7465
  resolved: {
7302
7466
  domain,
@@ -7304,6 +7468,7 @@ function registerGatewayTools(server) {
7304
7468
  upstreamResourceType,
7305
7469
  upstreamResourceName,
7306
7470
  enableAuth,
7471
+ enablePathTransmission,
7307
7472
  },
7308
7473
  };
7309
7474
  };
@@ -7343,6 +7508,7 @@ function registerGatewayTools(server) {
7343
7508
  action: input.action,
7344
7509
  routes,
7345
7510
  urls: buildRouteUrls(routes),
7511
+ ...buildAccessUrlFields(routes),
7346
7512
  total: result.TotalCount ?? routes.length,
7347
7513
  raw: result,
7348
7514
  }, `已获取 ${result.TotalCount ?? routes.length} 条 HTTP 路由`);
@@ -7384,6 +7550,7 @@ function registerGatewayTools(server) {
7384
7550
  routes: matches,
7385
7551
  total: matches.length,
7386
7552
  urls,
7553
+ ...buildAccessUrlFields(matches),
7387
7554
  raw: result,
7388
7555
  }, matches.length === 0
7389
7556
  ? "未找到对应路由"
@@ -7417,9 +7584,10 @@ function registerGatewayTools(server) {
7417
7584
  const message = err instanceof Error ? err.message : String(err);
7418
7585
  if (message.includes("An error has occurred")) {
7419
7586
  let hint = "为目标资源配置访问路由失败(后端内部错误)。请确保:1) 目标云函数已成功创建并处于 Active 状态;2) 环境默认 HTTP 域名已完成初始化(IsDefault);3) 该访问路径未被占用。";
7420
- if (input.type === "HTTP") {
7587
+ if (payload.resolved.upstreamResourceType === "WEB_SCF" ||
7588
+ payload.resolved.upstreamResourceType === "SCF") {
7421
7589
  hint +=
7422
- "此外注意:如果目标函数最初是作为 Event 函数创建的,这里 type 仍必须传 Event(UpstreamResourceType=SCF);误传 HTTP/WEB_SCF 会导致此错误。";
7590
+ "此外注意:HTTP 云函数必须用 upstreamResourceType=WEB_SCF,Event 云函数必须用 SCF;互标会导致此错误。";
7423
7591
  }
7424
7592
  throw new Error(`${hint} 原始错误:${message}`);
7425
7593
  }
@@ -7429,15 +7597,26 @@ function registerGatewayTools(server) {
7429
7597
  return buildEnvelope({
7430
7598
  action: input.action,
7431
7599
  model: "httpServiceRoute",
7432
- targetType: input.targetType ?? null,
7433
7600
  targetName: payload.resolved.upstreamResourceName,
7434
7601
  domain: payload.resolved.domain,
7435
7602
  path: payload.resolved.path,
7436
7603
  upstreamResourceType: payload.resolved.upstreamResourceType,
7437
7604
  upstreamResourceName: payload.resolved.upstreamResourceName,
7438
7605
  auth: payload.resolved.enableAuth ?? null,
7606
+ enablePathTransmission: payload.resolved.enablePathTransmission ?? null,
7607
+ accessUrl: `https://${payload.resolved.domain}${payload.resolved.path}`,
7608
+ accessUrls: [`https://${payload.resolved.domain}${payload.resolved.path}`],
7609
+ accessUrlSource: input.domain && input.domain === payload.resolved.domain
7610
+ ? "gateway.custom"
7611
+ : "gateway.default",
7439
7612
  raw: result,
7440
- }, `已为目标 ${payload.resolved.upstreamResourceName} 在域名 ${payload.resolved.domain} 创建路由 ${payload.resolved.path}(${payload.resolved.upstreamResourceType})。注意:路由配置传播通常需要等待 30 秒到 3 分钟,请勿立即访问。该操作只创建网关入口,不会自动放开函数安全规则;若需要匿名或浏览器直接访问,请继续检查函数资源权限。`, routeMutationNextActions(payload.resolved.upstreamResourceName));
7613
+ }, `已为目标 ${payload.resolved.upstreamResourceName} 在域名 ${payload.resolved.domain} 创建路由 ${payload.resolved.path}(${payload.resolved.upstreamResourceType})` +
7614
+ (payload.resolved.enablePathTransmission === true
7615
+ ? ";已开启路径透传(后端收到完整请求路径)"
7616
+ : payload.resolved.enablePathTransmission === false
7617
+ ? ";路径透传关闭(网关会剥掉触发路径前缀后再转发给后端)"
7618
+ : ";路径透传未显式设置(平台默认 false,会剥掉触发路径前缀)") +
7619
+ `。注意:路由配置传播通常需要等待 30 秒到 3 分钟,请勿立即访问。该操作只创建网关入口,不会自动放开上游权限;若上游是云函数且需要匿名或浏览器直接访问,请继续检查函数资源权限。`, routeMutationNextActions(payload.resolved.upstreamResourceName));
7441
7620
  }
7442
7621
  case "updateRoute": {
7443
7622
  const cloudbase = await getManager();
@@ -7455,8 +7634,20 @@ function registerGatewayTools(server) {
7455
7634
  upstreamResourceType: payload.resolved.upstreamResourceType,
7456
7635
  upstreamResourceName: payload.resolved.upstreamResourceName,
7457
7636
  auth: payload.resolved.enableAuth ?? null,
7637
+ enablePathTransmission: payload.resolved.enablePathTransmission ?? null,
7638
+ accessUrl: `https://${payload.resolved.domain}${payload.resolved.path}`,
7639
+ accessUrls: [`https://${payload.resolved.domain}${payload.resolved.path}`],
7640
+ accessUrlSource: input.domain && input.domain === payload.resolved.domain
7641
+ ? "gateway.custom"
7642
+ : "gateway.default",
7458
7643
  raw: result,
7459
- }, `HTTP 路由更新成功(${payload.resolved.domain}${payload.resolved.path})`, routeMutationNextActions(payload.resolved.upstreamResourceName));
7644
+ }, `HTTP 路由更新成功(${payload.resolved.domain}${payload.resolved.path}` +
7645
+ (payload.resolved.enablePathTransmission === true
7646
+ ? ",路径透传=开启"
7647
+ : payload.resolved.enablePathTransmission === false
7648
+ ? ",路径透传=关闭"
7649
+ : "") +
7650
+ `)`, routeMutationNextActions(payload.resolved.upstreamResourceName));
7460
7651
  }
7461
7652
  case "deleteRoute": {
7462
7653
  const routePath = input.route?.path ?? input.path;
@@ -7522,19 +7713,17 @@ function registerGatewayTools(server) {
7522
7713
  };
7523
7714
  server.registerTool?.("queryGateway", {
7524
7715
  title: "查询 CloudBase 网关",
7525
- description: "CloudBase 网关统一只读入口(Domain/Route 模型)。通过 listRoutes / getRoute / listCustomDomains 查询域名与路由;主键为 Domain + Path,上游类型为 SCF / WEB_SCF / CBR / STATIC_STORE / LH。",
7716
+ description: "CloudBase HTTP 网关统一只读入口(Domain/Route)。查询域名下路径路由及其上游:" +
7717
+ "WEB_SCF/SCF=云函数,CBR=云托管,STATIC_STORE=静态托管,LH=轻量应用服务器。" +
7718
+ "主键为 Domain + Path;listRoutes / getRoute / listCustomDomains。",
7526
7719
  inputSchema: {
7527
7720
  action: zod_1.z
7528
7721
  .enum(QUERY_GATEWAY_ACTIONS)
7529
7722
  .describe("只读操作类型:listRoutes、getRoute、listCustomDomains"),
7530
- targetType: zod_1.z
7531
- .enum(["function"])
7532
- .optional()
7533
- .describe("目标资源类型。当前支持 function"),
7534
7723
  targetName: zod_1.z
7535
7724
  .string()
7536
7725
  .optional()
7537
- .describe("上游资源名称。getRoute 时可按云函数名过滤"),
7726
+ .describe("上游资源名过滤(UpstreamResourceName):云函数名、云托管服务名,或静态托管实例名(常见 staticstore)。"),
7538
7727
  routeId: zod_1.z.string().optional().describe("路由 ID。getRoute 时可选"),
7539
7728
  path: zod_1.z
7540
7729
  .string()
@@ -7553,40 +7742,68 @@ function registerGatewayTools(server) {
7553
7742
  }, async (input) => withEnvelope(() => handleQueryGateway(input)));
7554
7743
  server.registerTool?.("manageGateway", {
7555
7744
  title: "管理 CloudBase 网关",
7556
- description: "CloudBase 网关统一写入口(Domain/Route 模型)。为已存在的 HTTP 云函数补默认域名访问时,使用 createRoute,并提供 targetType=\"function\"、targetName、type=\"HTTP\"(映射 WEB_SCF)与期望 path;Event 函数传 type=\"Event\"(映射 SCF)。未传 domain 时自动解析 IsDefault 默认域名。注意 createRoute 只创建网关入口,不会自动修改函数资源权限。更新鉴权用 updateRoute;删除用 deleteRoute(Domain+Path)。⚠️ 绑定带 SSL 证书的自定义域名用 bindCustomDomain;CORS/安全域名请使用 envDomainManagement。",
7745
+ description: "CloudBase HTTP 网关统一写入口(Domain/Route)。createRoute/updateRoute/deleteRoute 把域名下的 path 转到上游;未传 domain 时用 IsDefault 默认域名。" +
7746
+ "上游类型只用一个参数 upstreamResourceType(也可写在 route.upstreamResourceType,route 优先):" +
7747
+ "WEB_SCF=HTTP云函数,SCF=Event云函数,CBR=云托管,STATIC_STORE=静态托管,LH=轻量应用服务器;" +
7748
+ "配合 targetName 或 route.serviceName(云函数名/云托管服务名/静态托管实例名,常见 staticstore)。" +
7749
+ "createRoute 只建网关入口,不改上游权限。" +
7750
+ "enablePathTransmission:默认 false 剥触发路径前缀;true 透传完整路径(CBR 多路由、WEB_SCF 自管子路径常需 true;STATIC_STORE 自定义触发路径映射站点根通常 false)。" +
7751
+ "⚠️ SSL 自定义域名用 bindCustomDomain;CORS/安全域名用 envDomainManagement。",
7557
7752
  inputSchema: {
7558
7753
  action: zod_1.z
7559
7754
  .enum(MANAGE_GATEWAY_ACTIONS)
7560
- .describe("写操作类型。为已有函数补默认域名访问入口时使用 createRoute;函数场景必须显式提供 type(HTTP→WEB_SCF,Event→SCF)或 route.upstreamResourceType。"),
7561
- targetType: zod_1.z
7562
- .enum(["function"])
7563
- .optional()
7564
- .describe("目标资源类型。当前支持 function"),
7755
+ .describe("写操作:createRoute/updateRoute/deleteRoute 管理路由;bindCustomDomain/deleteCustomDomain 管理自定义域名。" +
7756
+ "createRoute/updateRoute 必须提供 upstreamResourceType。"),
7565
7757
  targetName: zod_1.z
7566
7758
  .string()
7567
7759
  .optional()
7568
- .describe("目标资源名称。createRoute 到云函数时填写函数名"),
7760
+ .describe("上游资源名称(UpstreamResourceName),与 route.serviceName 二选一(route 优先)。" +
7761
+ "云函数=函数名;云托管=服务名;静态托管=实例名(常见 staticstore)。不会自动推断上游类型。"),
7569
7762
  path: zod_1.z
7570
7763
  .string()
7571
7764
  .optional()
7572
- .describe("访问路径,默认 /{targetName}。例如为 HTTP 函数暴露 /api/hello 时传 /api/hello。该参数只创建网关入口,不会自动放开函数资源权限。"),
7573
- type: zod_1.z
7574
- .enum(["Event", "HTTP"])
7765
+ .describe("触发路径(网关匹配前缀),默认 /{上游名}。例:云函数 /api/hello、云托管 /api、静态托管 / 或 /app。" +
7766
+ "只建网关入口;与 enablePathTransmission 共同决定上游实际收到的路径。"),
7767
+ upstreamResourceType: zod_1.z
7768
+ .enum(UPSTREAM_RESOURCE_TYPES)
7575
7769
  .optional()
7576
- .describe("目标函数运行时类型,不是接入协议。HTTP 云函数传 HTTP(UpstreamResourceType=WEB_SCF);Event 函数传 Event(SCF)。误标会导致 FUNCTION_PARAM_INVALID 或网关错误。函数路由场景必须显式提供 type 或 route.upstreamResourceType。"),
7770
+ .describe("上游类型(与 route.upstreamResourceType 二选一,route 优先)。" +
7771
+ "WEB_SCF=HTTP云函数,SCF=Event云函数,CBR=云托管,STATIC_STORE=静态托管,LH=轻量应用服务器。" +
7772
+ "createRoute/updateRoute 必填其一;勿把 manageFunctions 的 type=HTTP|Event 传到本字段。"),
7577
7773
  auth: zod_1.z
7578
7774
  .boolean()
7579
7775
  .optional()
7580
- .describe("是否开启网关路径鉴权(EnableAuth)。若要走默认域名做匿名或浏览器访问,通常设为 false;该开关仅控制网关入口本身,不会修改函数资源权限。"),
7776
+ .describe("网关路径鉴权(EnableAuth)。匿名/浏览器公网访问通常 false。" +
7777
+ "只控制网关入口;云函数安全规则、云托管鉴权、静态托管权限需各自工具另行配置。"),
7778
+ enablePathTransmission: zod_1.z
7779
+ .boolean()
7780
+ .optional()
7781
+ .describe("路径透传(EnablePathTransmission),平台默认 false。例 path=/api 且请求 /api/users:" +
7782
+ "false→上游收到 /users;true→上游收到 /api/users。" +
7783
+ "CBR 云托管(Express 等自管子路由)与 WEB_SCF 多路径函数常需 true;" +
7784
+ "STATIC_STORE 把触发路径映射到站点根目录(如 /app → 托管 /)时通常 false;" +
7785
+ "单入口/根路径处理保持 false。也可用 route.enablePathTransmission(route 优先)。"),
7581
7786
  route: zod_1.z
7582
7787
  .object({
7583
7788
  path: zod_1.z.string().optional(),
7584
- serviceName: zod_1.z.string().optional(),
7585
- upstreamResourceType: zod_1.z.enum(UPSTREAM_RESOURCE_TYPES).optional(),
7789
+ serviceName: zod_1.z
7790
+ .string()
7791
+ .optional()
7792
+ .describe("上游实例名:云函数名 / 云托管服务名 / 静态托管实例名(常见 staticstore)/ LH 实例。优先于顶层 targetName。"),
7793
+ upstreamResourceType: zod_1.z
7794
+ .enum(UPSTREAM_RESOURCE_TYPES)
7795
+ .optional()
7796
+ .describe("同顶层 upstreamResourceType。route 内设置时优先于顶层。"),
7586
7797
  auth: zod_1.z.boolean().optional(),
7798
+ enablePathTransmission: zod_1.z
7799
+ .boolean()
7800
+ .optional()
7801
+ .describe("同顶层 enablePathTransmission。route 内设置时优先于顶层。"),
7587
7802
  })
7588
7803
  .optional()
7589
- .describe("HTTP 路由配置。upstreamResourceType 可选 SCF / WEB_SCF / CBR / STATIC_STORE / LH"),
7804
+ .describe("路由对象(可选写法)。例:云函数 {upstreamResourceType:\"WEB_SCF\",serviceName:\"fn\",path:\"/api\"};" +
7805
+ "云托管 {upstreamResourceType:\"CBR\",serviceName:\"svc\",path:\"/api\"};" +
7806
+ "静态托管 {upstreamResourceType:\"STATIC_STORE\",serviceName:\"staticstore\",path:\"/\"}。"),
7590
7807
  domain: zod_1.z
7591
7808
  .string()
7592
7809
  .optional()
@@ -7648,70 +7865,6 @@ module.exports = __WEBPACK_EXTERNAL_MODULE_fs__;
7648
7865
 
7649
7866
  module.exports = __WEBPACK_EXTERNAL_MODULE__modelcontextprotocol_sdk_server_mcp_js_45c326f0__;
7650
7867
 
7651
- /***/ }),
7652
-
7653
- /***/ 4760:
7654
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
7655
-
7656
-
7657
- Object.defineProperty(exports, "__esModule", ({ value: true }));
7658
- exports.registerInviteCodeTools = registerInviteCodeTools;
7659
- const zod_1 = __webpack_require__(2971);
7660
- const cloudbase_manager_js_1 = __webpack_require__(3431);
7661
- function registerInviteCodeTools(server) {
7662
- const cloudBaseOptions = server.cloudBaseOptions;
7663
- const getManager = () => (0, cloudbase_manager_js_1.getCloudBaseManager)({ cloudBaseOptions });
7664
- server.registerTool?.("activateInviteCode", {
7665
- title: "激活邀请码",
7666
- description: "云开发 AI编程激励计划,通过邀请码激活用户激励。",
7667
- inputSchema: {
7668
- InviteCode: zod_1.z.string().describe("待激活的邀请码")
7669
- },
7670
- annotations: {
7671
- readOnlyHint: false,
7672
- destructiveHint: false,
7673
- idempotentHint: false,
7674
- openWorldHint: true,
7675
- category: "invite-code"
7676
- }
7677
- }, async ({ InviteCode }) => {
7678
- if (!InviteCode) {
7679
- return {
7680
- content: [
7681
- {
7682
- type: "text",
7683
- text: JSON.stringify({
7684
- ErrorCode: 'MissingParameter',
7685
- ErrorMsg: '邀请码为必填项',
7686
- RequestId: ''
7687
- }, null, 2)
7688
- }
7689
- ]
7690
- };
7691
- }
7692
- const manager = await getManager();
7693
- const EnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
7694
- const result = await manager.commonService().call({
7695
- Action: 'ActivateInviteCode',
7696
- Param: { InviteCode, EnvId }
7697
- });
7698
- (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
7699
- return {
7700
- content: [
7701
- {
7702
- type: "text",
7703
- text: JSON.stringify({
7704
- ErrorCode: result?.ErrorCode || '',
7705
- ErrorMsg: result?.ErrorMsg || '',
7706
- RequestId: result?.RequestId || ''
7707
- }, null, 2)
7708
- }
7709
- ]
7710
- };
7711
- });
7712
- }
7713
-
7714
-
7715
7868
  /***/ }),
7716
7869
 
7717
7870
  /***/ 4848:
@@ -8249,7 +8402,9 @@ const path_1 = __importDefault(__webpack_require__(2521));
8249
8402
  const zod_1 = __webpack_require__(2971);
8250
8403
  const cloudbase_manager_js_1 = __webpack_require__(3431);
8251
8404
  const logger_js_1 = __webpack_require__(3039);
8405
+ const gateway_access_urls_js_1 = __webpack_require__(2435);
8252
8406
  const notification_js_1 = __webpack_require__(2720);
8407
+ const cloudrun_config_js_1 = __webpack_require__(8266);
8253
8408
  // CloudRun service types
8254
8409
  exports.CLOUDRUN_SERVICE_TYPES = ['function', 'container'];
8255
8410
  // CloudRun access types
@@ -8268,10 +8423,11 @@ const queryCloudRunInputSchema = {
8268
8423
  };
8269
8424
  // Input schema for manageCloudRun tool
8270
8425
  const ManageCloudRunInputSchema = {
8271
- action: zod_1.z.enum(['init', 'download', 'run', 'deploy', 'delete', 'createAgent']).describe('云托管服务管理操作类型:init=从模板初始化新的云托管项目代码(在targetPath目录下创建以serverName命名的子目录,支持多种语言和框架模板),download=从云端下载现有服务的代码到本地进行开发,run=在本地运行函数型云托管服务(用于开发和调试,仅支持函数型服务),deploy=将本地代码部署到云端云托管服务(支持函数型和容器型),delete=删除指定的云托管服务(不可恢复,需要确认),createAgent=创建函数型Agent(基于函数型云托管开发AI智能体)'),
8426
+ action: zod_1.z.enum(['init', 'download', 'run', 'deploy', 'delete', 'createAgent', 'updateConfig']).describe('云托管服务管理操作类型:init=从模板初始化新的云托管项目代码(在targetPath目录下创建以serverName命名的子目录,支持多种语言和框架模板),download=从云端下载现有服务的代码到本地进行开发,run=在本地运行函数型云托管服务(用于开发和调试,仅支持函数型服务),deploy=将本地代码部署到云端云托管服务(支持函数型和容器型;已存在服务会 Read-Merge-Write 保留远程 VpcConf/EnvParams/OpenAccessTypes),updateConfig=仅更新服务配置不重新上传代码(对齐控制台服务设置,走 SubmitServerConfigChangeDiff;不需要 targetPath),delete=删除指定的云托管服务(不可恢复,需要确认),createAgent=创建函数型Agent(基于函数型云托管开发AI智能体)'),
8272
8427
  serverName: zod_1.z.string().describe('云托管服务名称,用于标识和管理服务。命名规则:支持大小写字母、数字、连字符和下划线,必须以字母开头,长度3-45个字符。在init操作中会作为在targetPath下创建的子目录名,在其他操作中作为目标服务名'),
8273
8428
  // Deploy operation parameters
8274
- targetPath: zod_1.z.string().optional().describe('本地代码路径,必须是绝对路径。在deploy操作中指定要部署的代码目录,在download操作中指定下载目标目录,在init操作中指定云托管服务的上级目录(会在该目录下创建以serverName命名的子目录)。建议约定:项目根目录下的cloudrun/目录,例如:/Users/username/projects/my-project/cloudrun'),
8429
+ targetPath: zod_1.z.string().optional().describe('本地代码路径,必须是绝对路径。在deploy操作中指定要部署的代码目录,在download操作中指定下载目标目录,在init操作中指定云托管服务的上级目录(会在该目录下创建以serverName命名的子目录)。updateConfig 不需要此参数。建议约定:项目根目录下的cloudrun/目录,例如:/Users/username/projects/my-project/cloudrun'),
8430
+ envParamsReplaceAll: zod_1.z.boolean().optional().default(false).describe('EnvParams 合并策略(deploy / updateConfig):false(默认)= 与远程按 key 合并(输入覆盖同名 key,远程其余 key 保留);true= 用输入 EnvParams 整包替换远程。仅当显式传入 EnvParams 时生效'),
8275
8431
  serverConfig: zod_1.z.object({
8276
8432
  OpenAccessTypes: zod_1.z.array(zod_1.z.enum(exports.CLOUDRUN_ACCESS_TYPES)).optional().describe('公网访问类型配置,控制服务的访问权限:OA=办公网访问,PUBLIC=公网访问(默认,可通过HTTPS域名访问),MINIAPP=小程序访问,VPC=VPC访问(仅同VPC内可访问)。可配置多个类型'),
8277
8433
  Cpu: zod_1.z.number().positive().optional().describe('CPU规格配置,单位为核。可选值:0.25、0.5、1、2、4、8等。注意:内存规格必须是CPU规格的2倍(如CPU=0.25时内存=0.5,CPU=1时内存=2)。影响服务性能和计费'),
@@ -8310,7 +8466,7 @@ const ManageCloudRunInputSchema = {
8310
8466
  VpcConf: zod_1.z.object({
8311
8467
  VpcId: zod_1.z.string().describe('VPC网络ID,格式如 vpc-xxxxxxxx。必须与目标数据库/Redis 处于同一地域,并优先选择同一 VPC。禁止猜测或使用占位符;须来自数据库控制台、已有资源详情、callCloudApi 或用户确认。建议首次创建即配置;已存在服务也可在 deploy 时传入,部署后必须用 queryCloudRun detail 复核是否生效'),
8312
8468
  SubnetId: zod_1.z.string().describe('子网ID,格式如 subnet-xxxxxxxx。云托管实例将占用该子网 IP,需确保有足够可用 IP'),
8313
- }).optional().describe('VPC网络配置(实例出网/私有网络)。用于让云托管实例接入指定 VPC,从而内网访问 MySQL/PostgreSQL/Redis/CVM 等资源。与 OpenAccessTypes(外部如何访问本服务)是不同概念。TCP 连库场景必须配置。禁止猜测 VpcId/SubnetId,须来自数据库控制台、已有资源详情、callCloudApi 或用户确认。MCP 在创建时会将 VpcConf 映射为 SDK vpcInfo(CreateType=2);更新后必须用 queryCloudRun detail 复核 ServerConfig.VpcConf,未生效再走控制台网络设置或删建兜底'),
8469
+ }).optional().describe('VPC网络配置(实例出网/私有网络)。用于让云托管实例接入指定 VPC,从而内网访问 MySQL/PostgreSQL/Redis/CVM 等资源。与 OpenAccessTypes(外部如何访问本服务)是不同概念。TCP 连库场景必须配置。禁止猜测 VpcId/SubnetId,须来自数据库控制台、已有资源详情、callCloudApi 或用户确认。创建时映射为 SDK vpcInfo(CreateType=2);已存在服务可用 updateConfig 或 deploy(RMW 会保留未传入的远程 VpcConf)。部署/更新后必须用 queryCloudRun detail 复核 ServerConfig.VpcConf'),
8314
8470
  VolumesConf: zod_1.z.array(zod_1.z.object({
8315
8471
  VolumeName: zod_1.z.string().describe('存储卷名称'),
8316
8472
  VolumeType: zod_1.z.string().describe('存储卷类型,如CFS表示云文件存储'),
@@ -8320,7 +8476,7 @@ const ManageCloudRunInputSchema = {
8320
8476
  PublicAccess: zod_1.z.boolean().optional().describe('是否开启公网访问,true=开启公网访问,false=关闭公网访问'),
8321
8477
  PublicAccessPath: zod_1.z.string().optional().describe('公网访问路径配置')
8322
8478
  }).optional().describe('公网访问配置,用于控制服务的公网访问策略。可配置是否开启公网访问及访问路径'),
8323
- }).optional().describe('服务配置项,用于部署时设置服务的运行参数。包括资源规格、访问权限、环境变量、日志、网络等配置。不提供时使用默认配置'),
8479
+ }).optional().describe('服务配置项,用于 deploy / updateConfig。包括资源规格、访问权限、环境变量、日志、网络等。deploy 未提供时对已存在服务仍会从远程合并保留 VpcConf/EnvParams/OpenAccessTypes;updateConfig 至少需要一个配置字段'),
8324
8480
  // Init operation parameters
8325
8481
  template: zod_1.z.string().optional().default('helloworld').describe('项目模板标识符,用于指定初始化项目时使用的模板。可通过queryCloudRun的templates操作获取可用模板列表。常用模板:helloworld=Hello World示例,nodejs=Node.js项目模板,python=Python项目模板等'),
8326
8482
  // Run operation parameters (function services only)
@@ -8504,6 +8660,30 @@ function normalizeProcessLogText(logs) {
8504
8660
  })
8505
8661
  .join("\n");
8506
8662
  }
8663
+ function normalizeCloudRunDomainUrl(input) {
8664
+ if (typeof input !== "string" || !input.trim())
8665
+ return undefined;
8666
+ const raw = input.trim();
8667
+ return raw.startsWith("http://") || raw.startsWith("https://")
8668
+ ? raw
8669
+ : `https://${raw}`;
8670
+ }
8671
+ function resolveCloudRunFallbackAccess(details) {
8672
+ const custom = normalizeCloudRunDomainUrl(details?.BaseInfo?.CustomDomainName);
8673
+ if (custom)
8674
+ return { url: custom, source: "cloudrun.customDomain" };
8675
+ const defaultDomain = normalizeCloudRunDomainUrl(details?.BaseInfo?.DefaultDomainName);
8676
+ if (defaultDomain)
8677
+ return { url: defaultDomain, source: "cloudrun.defaultDomain" };
8678
+ const publicDomain = normalizeCloudRunDomainUrl(details?.BaseInfo?.PublicDomain) ??
8679
+ normalizeCloudRunDomainUrl(details?.AccessInfo?.PublicDomain);
8680
+ if (publicDomain)
8681
+ return { url: publicDomain, source: "cloudrun.publicDomain" };
8682
+ const internal = normalizeCloudRunDomainUrl(details?.BaseInfo?.InternalDomain);
8683
+ if (internal)
8684
+ return { url: internal, source: "cloudrun.internalDomain" };
8685
+ return {};
8686
+ }
8507
8687
  /**
8508
8688
  * Format CloudRun service info for display
8509
8689
  */
@@ -8737,7 +8917,7 @@ function registerCloudRunTools(server) {
8737
8917
  // Tool 2: Manage CloudRun services (write operations)
8738
8918
  server.registerTool("manageCloudRun", {
8739
8919
  title: "管理 CloudRun 服务",
8740
- description: "管理云托管服务,按开发顺序支持:初始化项目(可从模板开始,模板列表可通过 queryCloudRun 查询)、下载服务代码、本地运行(仅函数型服务)、部署代码、删除服务。部署可配置CPU、内存、实例数、访问类型等参数。删除操作需要确认,建议设置force=true。",
8920
+ description: "管理云托管服务,按开发顺序支持:初始化项目(可从模板开始,模板列表可通过 queryCloudRun 查询)、下载服务代码、本地运行(仅函数型服务)、部署代码、仅更新配置(updateConfig,无需重新上传代码)、删除服务。deploy 对已存在服务会先读取远程配置再合并(保留 VpcConf/EnvParams/OpenAccessTypes)。updateConfig 对齐控制台服务设置页。删除操作需要确认,建议设置force=true。",
8741
8921
  inputSchema: ManageCloudRunInputSchema,
8742
8922
  annotations: {
8743
8923
  readOnlyHint: false,
@@ -8928,6 +9108,8 @@ for await (let x of res.textStream) {
8928
9108
  }
8929
9109
  // Determine service type - use input.serverType if provided, otherwise auto-detect
8930
9110
  let serverType;
9111
+ let remoteServerConfig = null;
9112
+ let existingService = false;
8931
9113
  if (input.serverType) {
8932
9114
  serverType = input.serverType;
8933
9115
  }
@@ -8936,6 +9118,8 @@ for await (let x of res.textStream) {
8936
9118
  // First try to get existing service details
8937
9119
  const details = await cloudrunService.detail({ serverName: input.serverName });
8938
9120
  serverType = details.BaseInfo?.ServerType || 'container';
9121
+ remoteServerConfig = (details.ServerConfig || null);
9122
+ existingService = true;
8939
9123
  }
8940
9124
  catch (e) {
8941
9125
  // If service doesn't exist, determine by project structure
@@ -8969,20 +9153,40 @@ for await (let x of res.textStream) {
8969
9153
  }
8970
9154
  }
8971
9155
  }
9156
+ // When serverType was provided explicitly, still try to load remote config for RMW.
9157
+ if (!existingService) {
9158
+ try {
9159
+ const details = await cloudrunService.detail({ serverName: input.serverName });
9160
+ remoteServerConfig = (details.ServerConfig || null);
9161
+ existingService = true;
9162
+ }
9163
+ catch {
9164
+ // New service create path
9165
+ }
9166
+ }
9167
+ let mergedFromRemote = [];
9168
+ let effectiveServerConfig = input.serverConfig;
9169
+ if (existingService) {
9170
+ const mergedResult = (0, cloudrun_config_js_1.mergeCloudRunServerConfig)({
9171
+ remote: remoteServerConfig,
9172
+ input: input.serverConfig || {},
9173
+ envParamsReplaceAll: Boolean(input.envParamsReplaceAll),
9174
+ });
9175
+ effectiveServerConfig = mergedResult.merged;
9176
+ mergedFromRemote = mergedResult.mergedFromRemote;
9177
+ }
8972
9178
  const deployParams = {
8973
9179
  serverName: input.serverName,
8974
9180
  targetPath: targetPath,
8975
9181
  force: input.force,
8976
9182
  serverType: serverType,
8977
9183
  };
8978
- // Add server configuration if provided
8979
- if (input.serverConfig) {
8980
- deployParams.serverConfig = input.serverConfig;
9184
+ if (effectiveServerConfig && Object.keys(effectiveServerConfig).length > 0) {
9185
+ deployParams.serverConfig = effectiveServerConfig;
8981
9186
  }
8982
9187
  // Manager SDK create path prefers top-level vpcInfo (CreateCloudRunServer.VpcInfo).
8983
9188
  // Map serverConfig.VpcConf → vpcInfo so first-time create actually binds VPC.
8984
- // Update path still sends Items.VpcConf; platform may ignore VPC changes on existing services.
8985
- const vpcConf = input.serverConfig?.VpcConf;
9189
+ const vpcConf = effectiveServerConfig?.VpcConf;
8986
9190
  if (vpcConf?.VpcId?.trim() && vpcConf?.SubnetId?.trim()) {
8987
9191
  deployParams.vpcInfo = {
8988
9192
  VpcId: vpcConf.VpcId.trim(),
@@ -9013,47 +9217,46 @@ for await (let x of res.textStream) {
9013
9217
  catch (error) {
9014
9218
  (0, logger_js_1.debug)('cloudbaserc.json creation skipped:', error instanceof Error ? error : new Error(String(error)));
9015
9219
  }
9220
+ let preferredAccessUrl;
9221
+ let preferredAccessUrls = [];
9222
+ let preferredAccessSource;
9223
+ let verifiedConfigSnapshot;
9224
+ try {
9225
+ const serviceDetails = await cloudrunService.detail({
9226
+ serverName: input.serverName,
9227
+ });
9228
+ verifiedConfigSnapshot = (0, cloudrun_config_js_1.summarizeConfigSnapshot)(serviceDetails?.ServerConfig);
9229
+ const fallback = resolveCloudRunFallbackAccess(serviceDetails);
9230
+ const gateway = await (0, gateway_access_urls_js_1.resolveGatewayAccessUrls)({
9231
+ envId: currentEnvId,
9232
+ upstreamResourceName: input.serverName,
9233
+ upstreamResourceTypes: ["CBR"],
9234
+ getManager: async () => {
9235
+ const manager = await getManager();
9236
+ if (!manager) {
9237
+ throw new Error("cloudbase manager unavailable");
9238
+ }
9239
+ return manager;
9240
+ },
9241
+ });
9242
+ const preferred = (0, gateway_access_urls_js_1.preferGatewayOrFallback)({
9243
+ gateway,
9244
+ fallbackUrl: fallback.url,
9245
+ fallbackSource: fallback.source,
9246
+ });
9247
+ preferredAccessUrl = preferred.accessUrl;
9248
+ preferredAccessUrls = preferred.accessUrls;
9249
+ preferredAccessSource = preferred.accessUrlSource;
9250
+ }
9251
+ catch {
9252
+ // best-effort URL enrichment only
9253
+ }
9016
9254
  // Send deployment notification to CodeBuddy IDE
9017
9255
  try {
9018
- // Query service details to get access URL
9019
- let serviceUrl = "";
9020
- try {
9021
- const serviceDetails = await cloudrunService.detail({ serverName: input.serverName });
9022
- // Extract access URL from service details
9023
- // Priority: DefaultDomainName > CustomDomainName > PublicDomain > InternalDomain
9024
- const details = serviceDetails; // Use any to access dynamic properties
9025
- if (details?.BaseInfo?.DefaultDomainName) {
9026
- // DefaultDomainName is already a complete URL (e.g., https://...)
9027
- serviceUrl = details.BaseInfo.DefaultDomainName;
9028
- }
9029
- else if (details?.BaseInfo?.CustomDomainName) {
9030
- // CustomDomainName might be a domain without protocol
9031
- const customDomain = details.BaseInfo.CustomDomainName;
9032
- serviceUrl = customDomain.startsWith('http') ? customDomain : `https://${customDomain}`;
9033
- }
9034
- else if (details?.BaseInfo?.PublicDomain) {
9035
- serviceUrl = `https://${details.BaseInfo.PublicDomain}`;
9036
- }
9037
- else if (details?.BaseInfo?.InternalDomain) {
9038
- serviceUrl = `https://${details.BaseInfo.InternalDomain}`;
9039
- }
9040
- else if (details?.AccessInfo?.PublicDomain) {
9041
- serviceUrl = `https://${details.AccessInfo.PublicDomain}`;
9042
- }
9043
- else {
9044
- serviceUrl = ""; // URL not available
9045
- }
9046
- }
9047
- catch (detailErr) {
9048
- // If query fails, continue with empty URL
9049
- serviceUrl = "";
9050
- }
9051
- // Extract project name from targetPath
9052
9256
  const projectName = path_1.default.basename(targetPath);
9053
- // Send notification
9054
9257
  await (0, notification_js_1.sendDeployNotification)(server, {
9055
9258
  deployType: 'cloudrun',
9056
- url: serviceUrl,
9259
+ url: preferredAccessUrl ?? "",
9057
9260
  projectId: currentEnvId,
9058
9261
  projectName: projectName,
9059
9262
  consoleUrl: consoleUrl
@@ -9064,8 +9267,8 @@ for await (let x of res.textStream) {
9064
9267
  // Error is already logged in sendDeployNotification
9065
9268
  }
9066
9269
  const dbNetworkRisk = detectCloudRunDbNetworkRisk({
9067
- envParams: input.serverConfig?.EnvParams,
9068
- vpcConf: input.serverConfig?.VpcConf,
9270
+ envParams: effectiveServerConfig?.EnvParams,
9271
+ vpcConf: effectiveServerConfig?.VpcConf,
9069
9272
  });
9070
9273
  const warnings = dbNetworkRisk ? [dbNetworkRisk] : [];
9071
9274
  const warningSuffix = dbNetworkRisk
@@ -9084,6 +9287,25 @@ for await (let x of res.textStream) {
9084
9287
  serverType: serverType,
9085
9288
  cloudbasercGenerated: true,
9086
9289
  consoleUrl,
9290
+ ...(existingService
9291
+ ? {
9292
+ configMerge: {
9293
+ existingService: true,
9294
+ mergedFromRemote,
9295
+ appliedConfig: (0, cloudrun_config_js_1.summarizeConfigSnapshot)(effectiveServerConfig),
9296
+ ...(verifiedConfigSnapshot
9297
+ ? { verifiedAfterDeploy: verifiedConfigSnapshot }
9298
+ : {}),
9299
+ },
9300
+ }
9301
+ : {}),
9302
+ ...(preferredAccessUrl ? { accessUrl: preferredAccessUrl } : {}),
9303
+ ...(preferredAccessUrls.length > 0
9304
+ ? { accessUrls: preferredAccessUrls }
9305
+ : {}),
9306
+ ...(preferredAccessSource
9307
+ ? { accessUrlSource: preferredAccessSource }
9308
+ : {}),
9087
9309
  ...(warnings.length > 0 ? { warnings } : {}),
9088
9310
  },
9089
9311
  message: `Triggered deployment for ${serverType} service '${input.serverName}' from ${targetPath}. You can follow the progress in ${consoleUrl}.${warningSuffix}`
@@ -9092,6 +9314,125 @@ for await (let x of res.textStream) {
9092
9314
  ]
9093
9315
  };
9094
9316
  }
9317
+ case 'updateConfig': {
9318
+ if (!input.serverConfig || Object.keys(input.serverConfig).length === 0) {
9319
+ throw new Error("serverConfig with at least one field is required for updateConfig");
9320
+ }
9321
+ let remoteServerConfig = {};
9322
+ try {
9323
+ const details = await cloudrunService.detail({
9324
+ serverName: input.serverName,
9325
+ });
9326
+ remoteServerConfig = (details.ServerConfig ||
9327
+ {});
9328
+ }
9329
+ catch (error) {
9330
+ throw new Error(buildManageCloudRunErrorMessage("updateConfig", input.serverName, error));
9331
+ }
9332
+ // EnvParams on Diff replaces the whole blob — merge keys unless replaceAll.
9333
+ const dirty = { ...input.serverConfig };
9334
+ if (Object.prototype.hasOwnProperty.call(input.serverConfig, "EnvParams")) {
9335
+ const { merged } = (0, cloudrun_config_js_1.mergeCloudRunServerConfig)({
9336
+ remote: { EnvParams: remoteServerConfig.EnvParams },
9337
+ input: { EnvParams: input.serverConfig.EnvParams },
9338
+ envParamsReplaceAll: Boolean(input.envParamsReplaceAll),
9339
+ });
9340
+ if (merged.EnvParams !== undefined) {
9341
+ dirty.EnvParams = merged.EnvParams;
9342
+ }
9343
+ }
9344
+ let Items;
9345
+ try {
9346
+ Items = (0, cloudrun_config_js_1.parseServerConfigToDiffItems)(dirty);
9347
+ }
9348
+ catch (error) {
9349
+ throw new Error(buildManageCloudRunErrorMessage("updateConfig", input.serverName, error));
9350
+ }
9351
+ if (Items.length === 0) {
9352
+ return {
9353
+ content: [
9354
+ {
9355
+ type: "text",
9356
+ text: JSON.stringify({
9357
+ success: true,
9358
+ data: {
9359
+ serviceName: input.serverName,
9360
+ status: "noop",
9361
+ itemsCount: 0,
9362
+ appliedConfig: (0, cloudrun_config_js_1.summarizeConfigSnapshot)(dirty),
9363
+ verifiedConfig: (0, cloudrun_config_js_1.summarizeConfigSnapshot)(remoteServerConfig),
9364
+ },
9365
+ message: `No effective config changes for '${input.serverName}'.`,
9366
+ }, null, 2),
9367
+ },
9368
+ ],
9369
+ };
9370
+ }
9371
+ const currentEnvId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
9372
+ if (!manager.commonService) {
9373
+ throw new Error("Current CloudBase Manager does not support commonService; cannot call SubmitServerConfigChangeDiff.");
9374
+ }
9375
+ let diffResult;
9376
+ try {
9377
+ diffResult = await manager
9378
+ .commonService("tcbr", "2022-02-17")
9379
+ .call({
9380
+ Action: "SubmitServerConfigChangeDiff",
9381
+ Param: {
9382
+ EnvId: currentEnvId,
9383
+ ServerName: input.serverName,
9384
+ Items,
9385
+ },
9386
+ });
9387
+ }
9388
+ catch (error) {
9389
+ const msg = error instanceof Error ? error.message : String(error);
9390
+ if (/ResourceInUse|task|running|进行中/i.test(msg)) {
9391
+ throw new Error(buildManageCloudRunErrorMessage("updateConfig", input.serverName, new Error(`${msg} A deploy or config task may still be running. Wait, then retry; or use queryCloudRun(action="getDeployLog").`)));
9392
+ }
9393
+ throw new Error(buildManageCloudRunErrorMessage("updateConfig", input.serverName, error));
9394
+ }
9395
+ let verifiedConfig = (0, cloudrun_config_js_1.summarizeConfigSnapshot)(remoteServerConfig);
9396
+ try {
9397
+ const after = await cloudrunService.detail({
9398
+ serverName: input.serverName,
9399
+ });
9400
+ verifiedConfig = (0, cloudrun_config_js_1.summarizeConfigSnapshot)(after?.ServerConfig);
9401
+ }
9402
+ catch {
9403
+ // best-effort verify
9404
+ }
9405
+ const likelyRedeploy = (0, cloudrun_config_js_1.listLikelyRedeployFields)(dirty);
9406
+ const consoleUrl = `https://tcb.cloud.tencent.com/dev?envId=${currentEnvId}#/platform-run/service/detail?serverName=${input.serverName}&tabId=overview&envId=${currentEnvId}`;
9407
+ const taskId = diffResult?.TaskId ??
9408
+ diffResult?.Response?.TaskId ??
9409
+ diffResult?.taskId;
9410
+ const redeployHint = likelyRedeploy.length > 0
9411
+ ? ` Fields that often trigger redeploy-with-online-image: ${likelyRedeploy.join(", ")}.`
9412
+ : " Change may apply as a hot update (e.g. MinNum/MaxNum/AccessTypes).";
9413
+ return {
9414
+ content: [
9415
+ {
9416
+ type: "text",
9417
+ text: JSON.stringify({
9418
+ success: true,
9419
+ data: {
9420
+ serviceName: input.serverName,
9421
+ status: "configUpdating",
9422
+ itemsCount: Items.length,
9423
+ itemsKeys: Items.map((i) => i.Key),
9424
+ ...(taskId ? { taskId } : {}),
9425
+ appliedConfig: (0, cloudrun_config_js_1.summarizeConfigSnapshot)(dirty),
9426
+ verifiedConfig,
9427
+ likelyRedeployFields: likelyRedeploy,
9428
+ consoleUrl,
9429
+ },
9430
+ message: `Submitted config change for '${input.serverName}'.${redeployHint} Verify with queryCloudRun(action="detail"). Console: ${consoleUrl}`,
9431
+ }, null, 2),
9432
+ },
9433
+ ],
9434
+ };
9435
+ }
9095
9436
  case 'run': {
9096
9437
  if (!targetPath) {
9097
9438
  throw new Error("targetPath is required for run operation");
@@ -10015,7 +10356,7 @@ class TelemetryReporter {
10015
10356
  const nodeVersion = process.version; // Node.js版本
10016
10357
  const arch = os_1.default.arch(); // 系统架构
10017
10358
  // 从构建时注入的版本号获取MCP版本信息
10018
- const mcpVersion = process.env.npm_package_version || "2.25.0" || 0;
10359
+ const mcpVersion = process.env.npm_package_version || "2.25.2" || 0;
10019
10360
  return {
10020
10361
  userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
10021
10362
  deviceId: this.deviceId,
@@ -10359,6 +10700,7 @@ exports.registerFunctionTools = registerFunctionTools;
10359
10700
  const zod_1 = __webpack_require__(2971);
10360
10701
  const cloudbase_manager_js_1 = __webpack_require__(3431);
10361
10702
  const cloud_mode_js_1 = __webpack_require__(9684);
10703
+ const gateway_access_urls_js_1 = __webpack_require__(2435);
10362
10704
  const json_content_js_1 = __webpack_require__(4365);
10363
10705
  const logger_js_1 = __webpack_require__(3039);
10364
10706
  const fs_1 = __webpack_require__(4421);
@@ -11111,7 +11453,7 @@ function registerFunctionTools(server) {
11111
11453
  raw: imageResult,
11112
11454
  }, `已基于镜像 ${createImageConfig.imageUri} 创建 HTTP 函数 ${functionName}。` +
11113
11455
  `请确认 TCR、SCF 与构建管道处于同一地域;如需通过 URL 访问,请显式调用 ` +
11114
- `manageGateway(action="createRoute", type="HTTP") 并按需调整函数安全规则。` +
11456
+ `manageGateway(action="createRoute", upstreamResourceType="WEB_SCF") 并按需调整函数安全规则。` +
11115
11457
  `部署后可用 queryFunctions(action="getFunctionDetail") 确认函数已就绪。`, [
11116
11458
  {
11117
11459
  tool: "queryFunctions",
@@ -11182,7 +11524,7 @@ function registerFunctionTools(server) {
11182
11524
  nextActions.push({
11183
11525
  tool: "manageGateway",
11184
11526
  action: "createRoute",
11185
- reason: "如果需要通过 URL 访问 HTTP 函数,请调用 manageGateway(action=\"createRoute\") 并显式传 type=\"HTTP\"(映射 WEB_SCF),再按实际路径和鉴权需求创建访问入口,不要默认假设 /函数名 已存在",
11527
+ reason: "如果需要通过 URL 访问 HTTP 函数,请调用 manageGateway(action=\"createRoute\") 并显式传 upstreamResourceType=\"WEB_SCF\",再按实际路径和鉴权需求创建访问入口,不要默认假设 /函数名 已存在",
11186
11528
  });
11187
11529
  nextActions.push({
11188
11530
  tool: "queryGateway",
@@ -11201,11 +11543,35 @@ function registerFunctionTools(server) {
11201
11543
  });
11202
11544
  }
11203
11545
  const message = func.type === "HTTP"
11204
- ? `已创建 HTTP 函数 ${functionName}。如果后续需要通过 URL 访问,请显式调用 manageGateway(action="createRoute"),并把 type="HTTP" 一起传入(映射 UpstreamResourceType=WEB_SCF),再按实际路径和鉴权需求创建访问入口。评测或其他外部调用方可能会以匿名身份访问,而且失败后不一定会把 EXCEED_AUTHORITY 再反馈给 AI;交付前请主动确认访问路径和函数安全规则,若已出现 EXCEED_AUTHORITY,请先调用 queryPermissions(action="getResourcePermission", resourceType="function", resourceId="${functionName}") 查看当前规则,再按需要使用 managePermissions(action="updateResourcePermission") 调整权限。`
11546
+ ? `已创建 HTTP 函数 ${functionName}。如果后续需要通过 URL 访问,请显式调用 manageGateway(action="createRoute"),并把 upstreamResourceType="WEB_SCF" 一起传入,再按实际路径和鉴权需求创建访问入口。评测或其他外部调用方可能会以匿名身份访问,而且失败后不一定会把 EXCEED_AUTHORITY 再反馈给 AI;交付前请主动确认访问路径和函数安全规则,若已出现 EXCEED_AUTHORITY,请先调用 queryPermissions(action="getResourcePermission", resourceType="function", resourceId="${functionName}") 查看当前规则,再按需要使用 managePermissions(action="updateResourcePermission") 调整权限。`
11205
11547
  : `已创建函数 ${functionName}`;
11548
+ let accessUrl;
11549
+ let accessUrls = [];
11550
+ let accessUrlSource;
11551
+ if (func.type === "HTTP") {
11552
+ const envId = cloudBaseOptions?.envId ?? await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
11553
+ const gateway = await (0, gateway_access_urls_js_1.resolveGatewayAccessUrls)({
11554
+ envId,
11555
+ upstreamResourceName: functionName,
11556
+ upstreamResourceTypes: ["WEB_SCF", "SCF"],
11557
+ getManager: async () => {
11558
+ const manager = await getManager();
11559
+ if (!manager) {
11560
+ throw new Error("cloudbase manager unavailable");
11561
+ }
11562
+ return manager;
11563
+ },
11564
+ });
11565
+ accessUrl = gateway.accessUrl;
11566
+ accessUrls = gateway.accessUrls;
11567
+ accessUrlSource = gateway.accessUrlSource;
11568
+ }
11206
11569
  return buildEnvelope({
11207
11570
  action: input.action,
11208
11571
  functionName,
11572
+ ...(accessUrl ? { accessUrl } : {}),
11573
+ ...(accessUrls.length > 0 ? { accessUrls } : {}),
11574
+ ...(accessUrlSource ? { accessUrlSource } : {}),
11209
11575
  raw: result,
11210
11576
  }, message, nextActions);
11211
11577
  }
@@ -11244,11 +11610,33 @@ function registerFunctionTools(server) {
11244
11610
  throw wrapFunctionOperationError("updateFunctionCode", input.functionName, undefined, error);
11245
11611
  }
11246
11612
  (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, imageResult);
11613
+ const envId = cloudBaseOptions?.envId ?? await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
11614
+ const imageGatewayAccess = await (0, gateway_access_urls_js_1.resolveGatewayAccessUrls)({
11615
+ envId,
11616
+ upstreamResourceName: input.functionName,
11617
+ upstreamResourceTypes: ["WEB_SCF", "SCF"],
11618
+ getManager: async () => {
11619
+ const manager = await getManager();
11620
+ if (!manager) {
11621
+ throw new Error("cloudbase manager unavailable");
11622
+ }
11623
+ return manager;
11624
+ },
11625
+ });
11247
11626
  return buildEnvelope({
11248
11627
  action: input.action,
11249
11628
  functionName: input.functionName,
11250
11629
  deployMode: "image",
11251
11630
  imageUri: updateImageConfig.imageUri,
11631
+ ...(imageGatewayAccess.accessUrl
11632
+ ? { accessUrl: imageGatewayAccess.accessUrl }
11633
+ : {}),
11634
+ ...(imageGatewayAccess.accessUrls.length > 0
11635
+ ? { accessUrls: imageGatewayAccess.accessUrls }
11636
+ : {}),
11637
+ ...(imageGatewayAccess.accessUrlSource
11638
+ ? { accessUrlSource: imageGatewayAccess.accessUrlSource }
11639
+ : {}),
11252
11640
  raw: imageResult,
11253
11641
  }, `已将函数 ${input.functionName} 的镜像更新为 ${updateImageConfig.imageUri}。` +
11254
11642
  `部署后可用 queryFunctions(action="getFunctionDetail") 确认函数已就绪(Active)。`, [
@@ -11279,9 +11667,29 @@ function registerFunctionTools(server) {
11279
11667
  throw wrapFunctionOperationError("updateFunctionCode", input.functionName, processedRootPath, error);
11280
11668
  }
11281
11669
  (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
11670
+ const envId = cloudBaseOptions?.envId ?? await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
11671
+ const gatewayAccess = await (0, gateway_access_urls_js_1.resolveGatewayAccessUrls)({
11672
+ envId,
11673
+ upstreamResourceName: input.functionName,
11674
+ upstreamResourceTypes: ["WEB_SCF", "SCF"],
11675
+ getManager: async () => {
11676
+ const manager = await getManager();
11677
+ if (!manager) {
11678
+ throw new Error("cloudbase manager unavailable");
11679
+ }
11680
+ return manager;
11681
+ },
11682
+ });
11282
11683
  return buildEnvelope({
11283
11684
  action: input.action,
11284
11685
  functionName: input.functionName,
11686
+ ...(gatewayAccess.accessUrl ? { accessUrl: gatewayAccess.accessUrl } : {}),
11687
+ ...(gatewayAccess.accessUrls.length > 0
11688
+ ? { accessUrls: gatewayAccess.accessUrls }
11689
+ : {}),
11690
+ ...(gatewayAccess.accessUrlSource
11691
+ ? { accessUrlSource: gatewayAccess.accessUrlSource }
11692
+ : {}),
11285
11693
  raw: result,
11286
11694
  }, `已更新函数 ${input.functionName} 的代码`, [
11287
11695
  {
@@ -14327,7 +14735,7 @@ function registerSetupTools(server) {
14327
14735
  server.registerTool("downloadTemplate", {
14328
14736
  title: "下载项目模板",
14329
14737
  description: `自动下载并部署CloudBase项目模板。
14330
- **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.0" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
14738
+ **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.2" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
14331
14739
  inputSchema: {
14332
14740
  template: zod_1.z
14333
14741
  .enum(["react", "vue", "miniprogram", "uniapp", "rules"])
@@ -14523,6 +14931,7 @@ const zod_1 = __webpack_require__(2971);
14523
14931
  const cloudbase_manager_js_1 = __webpack_require__(3431);
14524
14932
  const json_content_js_1 = __webpack_require__(4365);
14525
14933
  const cloud_mode_js_1 = __webpack_require__(9684);
14934
+ const gateway_access_urls_js_1 = __webpack_require__(2435);
14526
14935
  const QUERY_APP_ACTIONS = ["listApps", "getApp", "listAppVersions", "getAppVersion", "getBuildLog"];
14527
14936
  const MANAGE_APP_ACTIONS = ["deployApp", "getUploadUrl", "deleteApp", "deleteAppVersion"];
14528
14937
  const APP_FRAMEWORKS = ["vue", "react", "next", "nuxt", "vite", "angular", "static"];
@@ -14899,6 +15308,8 @@ function registerAppTools(server) {
14899
15308
  let appInfo;
14900
15309
  let domain;
14901
15310
  let accessUrl;
15311
+ let accessUrls = [];
15312
+ let accessUrlSource;
14902
15313
  let accessUrlLookupWarning;
14903
15314
  try {
14904
15315
  appInfo = await appService.describeAppInfo({
@@ -14907,9 +15318,34 @@ function registerAppTools(server) {
14907
15318
  });
14908
15319
  (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, appInfo);
14909
15320
  ({ domain, accessUrl } = normalizeAccessUrlFromDomain(appInfo?.Domain));
15321
+ const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
15322
+ const gateway = await (0, gateway_access_urls_js_1.resolveGatewayAccessUrls)({
15323
+ envId,
15324
+ upstreamResourceName: serviceName,
15325
+ upstreamResourceTypes: ["STATIC_STORE"],
15326
+ getManager: async () => {
15327
+ const manager = await getManager();
15328
+ if (!manager) {
15329
+ throw new Error("cloudbase manager unavailable");
15330
+ }
15331
+ return manager;
15332
+ },
15333
+ });
15334
+ const preferred = (0, gateway_access_urls_js_1.preferGatewayOrFallback)({
15335
+ gateway,
15336
+ fallbackUrl: accessUrl,
15337
+ fallbackSource: "describeAppInfo.Domain",
15338
+ });
15339
+ accessUrl = preferred.accessUrl;
15340
+ accessUrls = preferred.accessUrls;
15341
+ accessUrlSource = preferred.accessUrlSource;
14910
15342
  }
14911
15343
  catch (error) {
14912
15344
  accessUrlLookupWarning = error instanceof Error ? error.message : String(error);
15345
+ if (accessUrl) {
15346
+ accessUrls = [accessUrl];
15347
+ accessUrlSource = "describeAppInfo.Domain";
15348
+ }
14913
15349
  }
14914
15350
  return (0, json_content_js_1.jsonContent)(buildEnvelope({
14915
15351
  action,
@@ -14918,7 +15354,8 @@ function registerAppTools(server) {
14918
15354
  buildId: BuildId,
14919
15355
  domain,
14920
15356
  accessUrl,
14921
- accessUrlSource: accessUrl ? "describeAppInfo.Domain" : undefined,
15357
+ accessUrls: accessUrls.length > 0 ? accessUrls : undefined,
15358
+ accessUrlSource,
14922
15359
  accessUrlLookupWarning,
14923
15360
  app: appInfo,
14924
15361
  upload: { cosTimestamp: cosTs },
@@ -15475,6 +15912,7 @@ const path_1 = __importDefault(__webpack_require__(2521));
15475
15912
  const zod_1 = __webpack_require__(2971);
15476
15913
  const cloudbase_manager_js_1 = __webpack_require__(3431);
15477
15914
  const cloud_mode_js_1 = __webpack_require__(9684);
15915
+ const gateway_access_urls_js_1 = __webpack_require__(2435);
15478
15916
  const notification_js_1 = __webpack_require__(2720);
15479
15917
  const tool_result_js_1 = __webpack_require__(9835);
15480
15918
  const HOSTING_CDN_SWITCH_VALUES = ['on', 'off'];
@@ -16010,9 +16448,48 @@ function registerHostingTools(server) {
16010
16448
  // StaticDomain there but not in DescribeStaticStore.
16011
16449
  const cdnFromStore = (store.CdnDomain ?? store.StaticDomain);
16012
16450
  const staticDomain = cdnFromStore || await resolveHostingStaticDomain(cloudbase, server.logger);
16013
- const accessUrl = buildHostingAccessUrl(staticDomain, input.cloudPath, input.localPath);
16451
+ const fallbackAccessUrl = buildHostingAccessUrl(staticDomain, input.cloudPath, input.localPath);
16452
+ const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
16453
+ const gatewayCandidates = Array.from(new Set([
16454
+ store.StaticStoreName,
16455
+ store.Name,
16456
+ store.StoreName,
16457
+ store.Bucket,
16458
+ "staticstore",
16459
+ ]
16460
+ .map((item) => (typeof item === "string" ? item.trim() : ""))
16461
+ .filter(Boolean)));
16462
+ let accessUrl = fallbackAccessUrl;
16463
+ let accessUrls = accessUrl ? [accessUrl] : [];
16464
+ let accessUrlSource = accessUrl
16465
+ ? "hosting.staticDomain"
16466
+ : undefined;
16467
+ for (const upstreamName of gatewayCandidates) {
16468
+ const gateway = await (0, gateway_access_urls_js_1.resolveGatewayAccessUrls)({
16469
+ envId,
16470
+ upstreamResourceName: upstreamName,
16471
+ upstreamResourceTypes: ["STATIC_STORE"],
16472
+ getManager: async () => {
16473
+ const manager = await getManager();
16474
+ if (!manager) {
16475
+ throw new Error("cloudbase manager unavailable");
16476
+ }
16477
+ return manager;
16478
+ },
16479
+ });
16480
+ const preferred = (0, gateway_access_urls_js_1.preferGatewayOrFallback)({
16481
+ gateway,
16482
+ fallbackUrl: fallbackAccessUrl || undefined,
16483
+ fallbackSource: "hosting.staticDomain",
16484
+ });
16485
+ if (preferred.accessUrl) {
16486
+ accessUrl = preferred.accessUrl;
16487
+ accessUrls = preferred.accessUrls;
16488
+ accessUrlSource = preferred.accessUrlSource;
16489
+ break;
16490
+ }
16491
+ }
16014
16492
  try {
16015
- const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
16016
16493
  let projectName = 'unknown';
16017
16494
  if (input.localPath) {
16018
16495
  try {
@@ -16047,6 +16524,8 @@ function registerHostingTools(server) {
16047
16524
  ignore: input.ignore,
16048
16525
  staticDomain,
16049
16526
  accessUrl,
16527
+ accessUrls,
16528
+ accessUrlSource,
16050
16529
  result,
16051
16530
  nextActions: uploadPrefix ? [buildFindFilesNextStep(uploadPrefix.replace(/^\/+/, ''))] : undefined,
16052
16531
  },
@@ -16646,6 +17125,219 @@ module.exports = __WEBPACK_EXTERNAL_MODULE_fs_promises_f8dae9d1__;
16646
17125
 
16647
17126
  module.exports = __WEBPACK_EXTERNAL_MODULE_os__;
16648
17127
 
17128
+ /***/ }),
17129
+
17130
+ /***/ 8266:
17131
+ /***/ ((__unused_webpack_module, exports) => {
17132
+
17133
+
17134
+ /**
17135
+ * CloudRun serverConfig merge (RMW) and DiffConfigItem helpers.
17136
+ * Aligns with console SubmitServerConfigChangeDiff field mapping.
17137
+ */
17138
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
17139
+ exports.CONFIG_FIELDS_LIKELY_REDEPLOY = void 0;
17140
+ exports.mergeCloudRunServerConfig = mergeCloudRunServerConfig;
17141
+ exports.assertCpuMemPair = assertCpuMemPair;
17142
+ exports.parseServerConfigToDiffItems = parseServerConfigToDiffItems;
17143
+ exports.summarizeConfigSnapshot = summarizeConfigSnapshot;
17144
+ exports.listLikelyRedeployFields = listLikelyRedeployFields;
17145
+ const SUBMIT_DIFF_MAP = {
17146
+ Cpu: "CpuSpecs",
17147
+ Mem: "MemSpecs",
17148
+ OpenAccessTypes: "AccessTypes",
17149
+ EnvParams: "EnvParam",
17150
+ CustomLogs: "LogPath",
17151
+ };
17152
+ const STRING_KEYS = new Set([
17153
+ "CustomLogs",
17154
+ "EnvParams",
17155
+ "CreateTime",
17156
+ "Dockerfile",
17157
+ "BuildDir",
17158
+ "LogType",
17159
+ "LogSetId",
17160
+ "LogTopicId",
17161
+ "LogParseType",
17162
+ "Tag",
17163
+ "InternalAccess",
17164
+ "InternalDomain",
17165
+ "OperationMode",
17166
+ "SessionAffinity",
17167
+ ]);
17168
+ const INT_KEYS = new Set(["MinNum", "MaxNum", "InitialDelaySeconds", "Port"]);
17169
+ const BOOL_KEYS = new Set(["HasDockerfile"]);
17170
+ const FLOAT_KEYS = new Set(["Cpu", "Mem"]);
17171
+ const ARRAY_KEYS = new Set(["OpenAccessTypes", "EntryPoint", "Cmd"]);
17172
+ function parseEnvParamsObject(raw) {
17173
+ if (!raw || !String(raw).trim()) {
17174
+ return {};
17175
+ }
17176
+ try {
17177
+ const value = JSON.parse(String(raw));
17178
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
17179
+ return {};
17180
+ }
17181
+ const out = {};
17182
+ for (const [k, v] of Object.entries(value)) {
17183
+ if (v === undefined || v === null)
17184
+ continue;
17185
+ out[k] = typeof v === "string" ? v : String(v);
17186
+ }
17187
+ return out;
17188
+ }
17189
+ catch {
17190
+ return {};
17191
+ }
17192
+ }
17193
+ function stringifyEnvParams(obj) {
17194
+ return JSON.stringify(obj);
17195
+ }
17196
+ function isCompleteVpcConf(vpc) {
17197
+ return Boolean(vpc?.VpcId?.trim() && vpc?.SubnetId?.trim());
17198
+ }
17199
+ /**
17200
+ * Merge remote ServerConfig with deploy/update input.
17201
+ * Explicit input wins for provided fields; EnvParams merges by key unless replaceAll.
17202
+ */
17203
+ function mergeCloudRunServerConfig(options) {
17204
+ const remote = options.remote || {};
17205
+ const input = options.input || {};
17206
+ const mergedFromRemote = [];
17207
+ const merged = { ...input };
17208
+ if (isCompleteVpcConf(input.VpcConf)) {
17209
+ merged.VpcConf = {
17210
+ VpcId: input.VpcConf.VpcId.trim(),
17211
+ SubnetId: input.VpcConf.SubnetId.trim(),
17212
+ ...(input.VpcConf.VpcCIDR ? { VpcCIDR: input.VpcConf.VpcCIDR } : {}),
17213
+ ...(input.VpcConf.SubnetCIDR ? { SubnetCIDR: input.VpcConf.SubnetCIDR } : {}),
17214
+ };
17215
+ }
17216
+ else if (isCompleteVpcConf(remote.VpcConf)) {
17217
+ merged.VpcConf = {
17218
+ VpcId: remote.VpcConf.VpcId.trim(),
17219
+ SubnetId: remote.VpcConf.SubnetId.trim(),
17220
+ ...(remote.VpcConf.VpcCIDR ? { VpcCIDR: remote.VpcConf.VpcCIDR } : {}),
17221
+ ...(remote.VpcConf.SubnetCIDR ? { SubnetCIDR: remote.VpcConf.SubnetCIDR } : {}),
17222
+ };
17223
+ mergedFromRemote.push("VpcConf");
17224
+ }
17225
+ else {
17226
+ delete merged.VpcConf;
17227
+ }
17228
+ const inputHasEnv = Object.prototype.hasOwnProperty.call(input, "EnvParams");
17229
+ const remoteEnv = parseEnvParamsObject(remote.EnvParams);
17230
+ const inputEnv = parseEnvParamsObject(input.EnvParams);
17231
+ if (options.envParamsReplaceAll && inputHasEnv) {
17232
+ merged.EnvParams = stringifyEnvParams(inputEnv);
17233
+ }
17234
+ else if (inputHasEnv || Object.keys(remoteEnv).length > 0) {
17235
+ const combined = options.envParamsReplaceAll
17236
+ ? { ...inputEnv }
17237
+ : { ...remoteEnv, ...inputEnv };
17238
+ if (Object.keys(remoteEnv).length > 0 && !options.envParamsReplaceAll) {
17239
+ const preserved = Object.keys(remoteEnv).filter((k) => !(k in inputEnv));
17240
+ if (preserved.length > 0) {
17241
+ mergedFromRemote.push("EnvParams");
17242
+ }
17243
+ }
17244
+ if (Object.keys(combined).length > 0 || inputHasEnv) {
17245
+ merged.EnvParams = stringifyEnvParams(combined);
17246
+ }
17247
+ }
17248
+ // Must be explicit so Manager SDK update path cannot wipe with OA/PUBLIC/MINIAPP defaults.
17249
+ if (Array.isArray(input.OpenAccessTypes) && input.OpenAccessTypes.length > 0) {
17250
+ merged.OpenAccessTypes = [...input.OpenAccessTypes];
17251
+ }
17252
+ else if (Array.isArray(remote.OpenAccessTypes) && remote.OpenAccessTypes.length > 0) {
17253
+ merged.OpenAccessTypes = [...remote.OpenAccessTypes];
17254
+ mergedFromRemote.push("OpenAccessTypes");
17255
+ }
17256
+ return { merged, mergedFromRemote };
17257
+ }
17258
+ function assertCpuMemPair(config) {
17259
+ const hasCpu = config.Cpu !== undefined && config.Cpu !== null;
17260
+ const hasMem = config.Mem !== undefined && config.Mem !== null;
17261
+ if (hasCpu !== hasMem) {
17262
+ throw new Error("Cpu and Mem must be provided together when updating CloudRun config (platform requires the pair).");
17263
+ }
17264
+ }
17265
+ /**
17266
+ * Convert serverConfig object to DiffConfigItem[] for SubmitServerConfigChangeDiff.
17267
+ */
17268
+ function parseServerConfigToDiffItems(data) {
17269
+ assertCpuMemPair(data);
17270
+ const Items = [];
17271
+ for (const [k, v] of Object.entries(data)) {
17272
+ if (v === undefined || v === null)
17273
+ continue;
17274
+ const Key = SUBMIT_DIFF_MAP[k] || k;
17275
+ if (STRING_KEYS.has(k)) {
17276
+ if (v !== "") {
17277
+ Items.push({ Key, Value: String(v) });
17278
+ }
17279
+ }
17280
+ else if (INT_KEYS.has(k)) {
17281
+ Items.push({ Key, IntValue: Number(v) });
17282
+ }
17283
+ else if (BOOL_KEYS.has(k)) {
17284
+ Items.push({ Key, BoolValue: Boolean(v) });
17285
+ }
17286
+ else if (FLOAT_KEYS.has(k)) {
17287
+ Items.push({ Key, FloatValue: Number(v) });
17288
+ }
17289
+ else if (ARRAY_KEYS.has(k)) {
17290
+ Items.push({ Key, ArrayValue: v });
17291
+ }
17292
+ else if (k === "PolicyDetails") {
17293
+ Items.push({ Key, PolicyDetails: v });
17294
+ }
17295
+ else if (k === "TimerScale") {
17296
+ Items.push({ Key, TimerScale: v });
17297
+ }
17298
+ else if (k === "VpcConf") {
17299
+ Items.push({ Key, VpcConf: v });
17300
+ }
17301
+ else if (k === "VolumesConf") {
17302
+ Items.push({ Key, VolumesConf: v });
17303
+ }
17304
+ else if (k === "PublicNetConf") {
17305
+ Items.push({ Key, PublicNetConf: v });
17306
+ }
17307
+ }
17308
+ return Items;
17309
+ }
17310
+ function summarizeConfigSnapshot(config) {
17311
+ const vpc = config?.VpcConf;
17312
+ const envKeys = Object.keys(parseEnvParamsObject(config?.EnvParams));
17313
+ return {
17314
+ hasVpcConf: isCompleteVpcConf(vpc),
17315
+ ...(vpc?.VpcId ? { vpcId: vpc.VpcId } : {}),
17316
+ ...(vpc?.SubnetId ? { subnetId: vpc.SubnetId } : {}),
17317
+ ...(Array.isArray(config?.OpenAccessTypes)
17318
+ ? { openAccessTypes: config.OpenAccessTypes }
17319
+ : {}),
17320
+ envParamKeys: envKeys,
17321
+ };
17322
+ }
17323
+ exports.CONFIG_FIELDS_LIKELY_REDEPLOY = [
17324
+ "VpcConf",
17325
+ "EnvParams",
17326
+ "Cpu",
17327
+ "Mem",
17328
+ "Port",
17329
+ "Dockerfile",
17330
+ "BuildDir",
17331
+ "VolumesConf",
17332
+ "LogType",
17333
+ "LogSetId",
17334
+ "LogTopicId",
17335
+ ];
17336
+ function listLikelyRedeployFields(config) {
17337
+ return exports.CONFIG_FIELDS_LIKELY_REDEPLOY.filter((k) => Object.prototype.hasOwnProperty.call(config, k));
17338
+ }
17339
+
17340
+
16649
17341
  /***/ }),
16650
17342
 
16651
17343
  /***/ 9097: