@cloudbase/cloudbase-mcp 2.25.1 → 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.1" || 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.1" : 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
  // 创建新的错误对象,保持原有的错误类型但更新消息
@@ -2908,6 +2908,153 @@ function registerLogTools(server) {
2908
2908
 
2909
2909
  module.exports = __WEBPACK_EXTERNAL_MODULE__modelcontextprotocol_sdk_types_js_70eb1363__;
2910
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
+
2911
3058
  /***/ }),
2912
3059
 
2913
3060
  /***/ 2448:
@@ -7148,6 +7295,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
7148
7295
  exports.registerGatewayTools = registerGatewayTools;
7149
7296
  const zod_1 = __webpack_require__(2971);
7150
7297
  const cloudbase_manager_js_1 = __webpack_require__(3431);
7298
+ const gateway_access_urls_js_1 = __webpack_require__(2435);
7151
7299
  const json_content_js_1 = __webpack_require__(4365);
7152
7300
  const QUERY_GATEWAY_ACTIONS = [
7153
7301
  "listRoutes",
@@ -7223,9 +7371,33 @@ function registerGatewayTools(server) {
7223
7371
  IsDefault: domainItem.IsDefault,
7224
7372
  ...route,
7225
7373
  })));
7226
- const buildRouteUrls = (routes) => Array.from(new Set(routes
7227
- .filter((route) => route.Domain && route.Path)
7228
- .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
+ };
7229
7401
  const resolveDefaultHttpDomain = async () => {
7230
7402
  const routeInfo = await listHttpServiceRoutes();
7231
7403
  const domains = routeInfo.Domains ?? [];
@@ -7336,6 +7508,7 @@ function registerGatewayTools(server) {
7336
7508
  action: input.action,
7337
7509
  routes,
7338
7510
  urls: buildRouteUrls(routes),
7511
+ ...buildAccessUrlFields(routes),
7339
7512
  total: result.TotalCount ?? routes.length,
7340
7513
  raw: result,
7341
7514
  }, `已获取 ${result.TotalCount ?? routes.length} 条 HTTP 路由`);
@@ -7377,6 +7550,7 @@ function registerGatewayTools(server) {
7377
7550
  routes: matches,
7378
7551
  total: matches.length,
7379
7552
  urls,
7553
+ ...buildAccessUrlFields(matches),
7380
7554
  raw: result,
7381
7555
  }, matches.length === 0
7382
7556
  ? "未找到对应路由"
@@ -7430,6 +7604,11 @@ function registerGatewayTools(server) {
7430
7604
  upstreamResourceName: payload.resolved.upstreamResourceName,
7431
7605
  auth: payload.resolved.enableAuth ?? null,
7432
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",
7433
7612
  raw: result,
7434
7613
  }, `已为目标 ${payload.resolved.upstreamResourceName} 在域名 ${payload.resolved.domain} 创建路由 ${payload.resolved.path}(${payload.resolved.upstreamResourceType})` +
7435
7614
  (payload.resolved.enablePathTransmission === true
@@ -7456,6 +7635,11 @@ function registerGatewayTools(server) {
7456
7635
  upstreamResourceName: payload.resolved.upstreamResourceName,
7457
7636
  auth: payload.resolved.enableAuth ?? null,
7458
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",
7459
7643
  raw: result,
7460
7644
  }, `HTTP 路由更新成功(${payload.resolved.domain}${payload.resolved.path}` +
7461
7645
  (payload.resolved.enablePathTransmission === true
@@ -8218,7 +8402,9 @@ const path_1 = __importDefault(__webpack_require__(2521));
8218
8402
  const zod_1 = __webpack_require__(2971);
8219
8403
  const cloudbase_manager_js_1 = __webpack_require__(3431);
8220
8404
  const logger_js_1 = __webpack_require__(3039);
8405
+ const gateway_access_urls_js_1 = __webpack_require__(2435);
8221
8406
  const notification_js_1 = __webpack_require__(2720);
8407
+ const cloudrun_config_js_1 = __webpack_require__(8266);
8222
8408
  // CloudRun service types
8223
8409
  exports.CLOUDRUN_SERVICE_TYPES = ['function', 'container'];
8224
8410
  // CloudRun access types
@@ -8237,10 +8423,11 @@ const queryCloudRunInputSchema = {
8237
8423
  };
8238
8424
  // Input schema for manageCloudRun tool
8239
8425
  const ManageCloudRunInputSchema = {
8240
- 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智能体)'),
8241
8427
  serverName: zod_1.z.string().describe('云托管服务名称,用于标识和管理服务。命名规则:支持大小写字母、数字、连字符和下划线,必须以字母开头,长度3-45个字符。在init操作中会作为在targetPath下创建的子目录名,在其他操作中作为目标服务名'),
8242
8428
  // Deploy operation parameters
8243
- 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 时生效'),
8244
8431
  serverConfig: zod_1.z.object({
8245
8432
  OpenAccessTypes: zod_1.z.array(zod_1.z.enum(exports.CLOUDRUN_ACCESS_TYPES)).optional().describe('公网访问类型配置,控制服务的访问权限:OA=办公网访问,PUBLIC=公网访问(默认,可通过HTTPS域名访问),MINIAPP=小程序访问,VPC=VPC访问(仅同VPC内可访问)。可配置多个类型'),
8246
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)。影响服务性能和计费'),
@@ -8279,7 +8466,7 @@ const ManageCloudRunInputSchema = {
8279
8466
  VpcConf: zod_1.z.object({
8280
8467
  VpcId: zod_1.z.string().describe('VPC网络ID,格式如 vpc-xxxxxxxx。必须与目标数据库/Redis 处于同一地域,并优先选择同一 VPC。禁止猜测或使用占位符;须来自数据库控制台、已有资源详情、callCloudApi 或用户确认。建议首次创建即配置;已存在服务也可在 deploy 时传入,部署后必须用 queryCloudRun detail 复核是否生效'),
8281
8468
  SubnetId: zod_1.z.string().describe('子网ID,格式如 subnet-xxxxxxxx。云托管实例将占用该子网 IP,需确保有足够可用 IP'),
8282
- }).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'),
8283
8470
  VolumesConf: zod_1.z.array(zod_1.z.object({
8284
8471
  VolumeName: zod_1.z.string().describe('存储卷名称'),
8285
8472
  VolumeType: zod_1.z.string().describe('存储卷类型,如CFS表示云文件存储'),
@@ -8289,7 +8476,7 @@ const ManageCloudRunInputSchema = {
8289
8476
  PublicAccess: zod_1.z.boolean().optional().describe('是否开启公网访问,true=开启公网访问,false=关闭公网访问'),
8290
8477
  PublicAccessPath: zod_1.z.string().optional().describe('公网访问路径配置')
8291
8478
  }).optional().describe('公网访问配置,用于控制服务的公网访问策略。可配置是否开启公网访问及访问路径'),
8292
- }).optional().describe('服务配置项,用于部署时设置服务的运行参数。包括资源规格、访问权限、环境变量、日志、网络等配置。不提供时使用默认配置'),
8479
+ }).optional().describe('服务配置项,用于 deploy / updateConfig。包括资源规格、访问权限、环境变量、日志、网络等。deploy 未提供时对已存在服务仍会从远程合并保留 VpcConf/EnvParams/OpenAccessTypes;updateConfig 至少需要一个配置字段'),
8293
8480
  // Init operation parameters
8294
8481
  template: zod_1.z.string().optional().default('helloworld').describe('项目模板标识符,用于指定初始化项目时使用的模板。可通过queryCloudRun的templates操作获取可用模板列表。常用模板:helloworld=Hello World示例,nodejs=Node.js项目模板,python=Python项目模板等'),
8295
8482
  // Run operation parameters (function services only)
@@ -8473,6 +8660,30 @@ function normalizeProcessLogText(logs) {
8473
8660
  })
8474
8661
  .join("\n");
8475
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
+ }
8476
8687
  /**
8477
8688
  * Format CloudRun service info for display
8478
8689
  */
@@ -8706,7 +8917,7 @@ function registerCloudRunTools(server) {
8706
8917
  // Tool 2: Manage CloudRun services (write operations)
8707
8918
  server.registerTool("manageCloudRun", {
8708
8919
  title: "管理 CloudRun 服务",
8709
- description: "管理云托管服务,按开发顺序支持:初始化项目(可从模板开始,模板列表可通过 queryCloudRun 查询)、下载服务代码、本地运行(仅函数型服务)、部署代码、删除服务。部署可配置CPU、内存、实例数、访问类型等参数。删除操作需要确认,建议设置force=true。",
8920
+ description: "管理云托管服务,按开发顺序支持:初始化项目(可从模板开始,模板列表可通过 queryCloudRun 查询)、下载服务代码、本地运行(仅函数型服务)、部署代码、仅更新配置(updateConfig,无需重新上传代码)、删除服务。deploy 对已存在服务会先读取远程配置再合并(保留 VpcConf/EnvParams/OpenAccessTypes)。updateConfig 对齐控制台服务设置页。删除操作需要确认,建议设置force=true。",
8710
8921
  inputSchema: ManageCloudRunInputSchema,
8711
8922
  annotations: {
8712
8923
  readOnlyHint: false,
@@ -8897,6 +9108,8 @@ for await (let x of res.textStream) {
8897
9108
  }
8898
9109
  // Determine service type - use input.serverType if provided, otherwise auto-detect
8899
9110
  let serverType;
9111
+ let remoteServerConfig = null;
9112
+ let existingService = false;
8900
9113
  if (input.serverType) {
8901
9114
  serverType = input.serverType;
8902
9115
  }
@@ -8905,6 +9118,8 @@ for await (let x of res.textStream) {
8905
9118
  // First try to get existing service details
8906
9119
  const details = await cloudrunService.detail({ serverName: input.serverName });
8907
9120
  serverType = details.BaseInfo?.ServerType || 'container';
9121
+ remoteServerConfig = (details.ServerConfig || null);
9122
+ existingService = true;
8908
9123
  }
8909
9124
  catch (e) {
8910
9125
  // If service doesn't exist, determine by project structure
@@ -8938,20 +9153,40 @@ for await (let x of res.textStream) {
8938
9153
  }
8939
9154
  }
8940
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
+ }
8941
9178
  const deployParams = {
8942
9179
  serverName: input.serverName,
8943
9180
  targetPath: targetPath,
8944
9181
  force: input.force,
8945
9182
  serverType: serverType,
8946
9183
  };
8947
- // Add server configuration if provided
8948
- if (input.serverConfig) {
8949
- deployParams.serverConfig = input.serverConfig;
9184
+ if (effectiveServerConfig && Object.keys(effectiveServerConfig).length > 0) {
9185
+ deployParams.serverConfig = effectiveServerConfig;
8950
9186
  }
8951
9187
  // Manager SDK create path prefers top-level vpcInfo (CreateCloudRunServer.VpcInfo).
8952
9188
  // Map serverConfig.VpcConf → vpcInfo so first-time create actually binds VPC.
8953
- // Update path still sends Items.VpcConf; platform may ignore VPC changes on existing services.
8954
- const vpcConf = input.serverConfig?.VpcConf;
9189
+ const vpcConf = effectiveServerConfig?.VpcConf;
8955
9190
  if (vpcConf?.VpcId?.trim() && vpcConf?.SubnetId?.trim()) {
8956
9191
  deployParams.vpcInfo = {
8957
9192
  VpcId: vpcConf.VpcId.trim(),
@@ -8982,47 +9217,46 @@ for await (let x of res.textStream) {
8982
9217
  catch (error) {
8983
9218
  (0, logger_js_1.debug)('cloudbaserc.json creation skipped:', error instanceof Error ? error : new Error(String(error)));
8984
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
+ }
8985
9254
  // Send deployment notification to CodeBuddy IDE
8986
9255
  try {
8987
- // Query service details to get access URL
8988
- let serviceUrl = "";
8989
- try {
8990
- const serviceDetails = await cloudrunService.detail({ serverName: input.serverName });
8991
- // Extract access URL from service details
8992
- // Priority: DefaultDomainName > CustomDomainName > PublicDomain > InternalDomain
8993
- const details = serviceDetails; // Use any to access dynamic properties
8994
- if (details?.BaseInfo?.DefaultDomainName) {
8995
- // DefaultDomainName is already a complete URL (e.g., https://...)
8996
- serviceUrl = details.BaseInfo.DefaultDomainName;
8997
- }
8998
- else if (details?.BaseInfo?.CustomDomainName) {
8999
- // CustomDomainName might be a domain without protocol
9000
- const customDomain = details.BaseInfo.CustomDomainName;
9001
- serviceUrl = customDomain.startsWith('http') ? customDomain : `https://${customDomain}`;
9002
- }
9003
- else if (details?.BaseInfo?.PublicDomain) {
9004
- serviceUrl = `https://${details.BaseInfo.PublicDomain}`;
9005
- }
9006
- else if (details?.BaseInfo?.InternalDomain) {
9007
- serviceUrl = `https://${details.BaseInfo.InternalDomain}`;
9008
- }
9009
- else if (details?.AccessInfo?.PublicDomain) {
9010
- serviceUrl = `https://${details.AccessInfo.PublicDomain}`;
9011
- }
9012
- else {
9013
- serviceUrl = ""; // URL not available
9014
- }
9015
- }
9016
- catch (detailErr) {
9017
- // If query fails, continue with empty URL
9018
- serviceUrl = "";
9019
- }
9020
- // Extract project name from targetPath
9021
9256
  const projectName = path_1.default.basename(targetPath);
9022
- // Send notification
9023
9257
  await (0, notification_js_1.sendDeployNotification)(server, {
9024
9258
  deployType: 'cloudrun',
9025
- url: serviceUrl,
9259
+ url: preferredAccessUrl ?? "",
9026
9260
  projectId: currentEnvId,
9027
9261
  projectName: projectName,
9028
9262
  consoleUrl: consoleUrl
@@ -9033,8 +9267,8 @@ for await (let x of res.textStream) {
9033
9267
  // Error is already logged in sendDeployNotification
9034
9268
  }
9035
9269
  const dbNetworkRisk = detectCloudRunDbNetworkRisk({
9036
- envParams: input.serverConfig?.EnvParams,
9037
- vpcConf: input.serverConfig?.VpcConf,
9270
+ envParams: effectiveServerConfig?.EnvParams,
9271
+ vpcConf: effectiveServerConfig?.VpcConf,
9038
9272
  });
9039
9273
  const warnings = dbNetworkRisk ? [dbNetworkRisk] : [];
9040
9274
  const warningSuffix = dbNetworkRisk
@@ -9053,6 +9287,25 @@ for await (let x of res.textStream) {
9053
9287
  serverType: serverType,
9054
9288
  cloudbasercGenerated: true,
9055
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
+ : {}),
9056
9309
  ...(warnings.length > 0 ? { warnings } : {}),
9057
9310
  },
9058
9311
  message: `Triggered deployment for ${serverType} service '${input.serverName}' from ${targetPath}. You can follow the progress in ${consoleUrl}.${warningSuffix}`
@@ -9061,6 +9314,125 @@ for await (let x of res.textStream) {
9061
9314
  ]
9062
9315
  };
9063
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
+ }
9064
9436
  case 'run': {
9065
9437
  if (!targetPath) {
9066
9438
  throw new Error("targetPath is required for run operation");
@@ -9984,7 +10356,7 @@ class TelemetryReporter {
9984
10356
  const nodeVersion = process.version; // Node.js版本
9985
10357
  const arch = os_1.default.arch(); // 系统架构
9986
10358
  // 从构建时注入的版本号获取MCP版本信息
9987
- const mcpVersion = process.env.npm_package_version || "2.25.1" || 0;
10359
+ const mcpVersion = process.env.npm_package_version || "2.25.2" || 0;
9988
10360
  return {
9989
10361
  userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
9990
10362
  deviceId: this.deviceId,
@@ -10328,6 +10700,7 @@ exports.registerFunctionTools = registerFunctionTools;
10328
10700
  const zod_1 = __webpack_require__(2971);
10329
10701
  const cloudbase_manager_js_1 = __webpack_require__(3431);
10330
10702
  const cloud_mode_js_1 = __webpack_require__(9684);
10703
+ const gateway_access_urls_js_1 = __webpack_require__(2435);
10331
10704
  const json_content_js_1 = __webpack_require__(4365);
10332
10705
  const logger_js_1 = __webpack_require__(3039);
10333
10706
  const fs_1 = __webpack_require__(4421);
@@ -11172,9 +11545,33 @@ function registerFunctionTools(server) {
11172
11545
  const message = func.type === "HTTP"
11173
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") 调整权限。`
11174
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
+ }
11175
11569
  return buildEnvelope({
11176
11570
  action: input.action,
11177
11571
  functionName,
11572
+ ...(accessUrl ? { accessUrl } : {}),
11573
+ ...(accessUrls.length > 0 ? { accessUrls } : {}),
11574
+ ...(accessUrlSource ? { accessUrlSource } : {}),
11178
11575
  raw: result,
11179
11576
  }, message, nextActions);
11180
11577
  }
@@ -11213,11 +11610,33 @@ function registerFunctionTools(server) {
11213
11610
  throw wrapFunctionOperationError("updateFunctionCode", input.functionName, undefined, error);
11214
11611
  }
11215
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
+ });
11216
11626
  return buildEnvelope({
11217
11627
  action: input.action,
11218
11628
  functionName: input.functionName,
11219
11629
  deployMode: "image",
11220
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
+ : {}),
11221
11640
  raw: imageResult,
11222
11641
  }, `已将函数 ${input.functionName} 的镜像更新为 ${updateImageConfig.imageUri}。` +
11223
11642
  `部署后可用 queryFunctions(action="getFunctionDetail") 确认函数已就绪(Active)。`, [
@@ -11248,9 +11667,29 @@ function registerFunctionTools(server) {
11248
11667
  throw wrapFunctionOperationError("updateFunctionCode", input.functionName, processedRootPath, error);
11249
11668
  }
11250
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
+ });
11251
11683
  return buildEnvelope({
11252
11684
  action: input.action,
11253
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
+ : {}),
11254
11693
  raw: result,
11255
11694
  }, `已更新函数 ${input.functionName} 的代码`, [
11256
11695
  {
@@ -14296,7 +14735,7 @@ function registerSetupTools(server) {
14296
14735
  server.registerTool("downloadTemplate", {
14297
14736
  title: "下载项目模板",
14298
14737
  description: `自动下载并部署CloudBase项目模板。
14299
- **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.1" : 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)`,
14300
14739
  inputSchema: {
14301
14740
  template: zod_1.z
14302
14741
  .enum(["react", "vue", "miniprogram", "uniapp", "rules"])
@@ -14492,6 +14931,7 @@ const zod_1 = __webpack_require__(2971);
14492
14931
  const cloudbase_manager_js_1 = __webpack_require__(3431);
14493
14932
  const json_content_js_1 = __webpack_require__(4365);
14494
14933
  const cloud_mode_js_1 = __webpack_require__(9684);
14934
+ const gateway_access_urls_js_1 = __webpack_require__(2435);
14495
14935
  const QUERY_APP_ACTIONS = ["listApps", "getApp", "listAppVersions", "getAppVersion", "getBuildLog"];
14496
14936
  const MANAGE_APP_ACTIONS = ["deployApp", "getUploadUrl", "deleteApp", "deleteAppVersion"];
14497
14937
  const APP_FRAMEWORKS = ["vue", "react", "next", "nuxt", "vite", "angular", "static"];
@@ -14868,6 +15308,8 @@ function registerAppTools(server) {
14868
15308
  let appInfo;
14869
15309
  let domain;
14870
15310
  let accessUrl;
15311
+ let accessUrls = [];
15312
+ let accessUrlSource;
14871
15313
  let accessUrlLookupWarning;
14872
15314
  try {
14873
15315
  appInfo = await appService.describeAppInfo({
@@ -14876,9 +15318,34 @@ function registerAppTools(server) {
14876
15318
  });
14877
15319
  (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, appInfo);
14878
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;
14879
15342
  }
14880
15343
  catch (error) {
14881
15344
  accessUrlLookupWarning = error instanceof Error ? error.message : String(error);
15345
+ if (accessUrl) {
15346
+ accessUrls = [accessUrl];
15347
+ accessUrlSource = "describeAppInfo.Domain";
15348
+ }
14882
15349
  }
14883
15350
  return (0, json_content_js_1.jsonContent)(buildEnvelope({
14884
15351
  action,
@@ -14887,7 +15354,8 @@ function registerAppTools(server) {
14887
15354
  buildId: BuildId,
14888
15355
  domain,
14889
15356
  accessUrl,
14890
- accessUrlSource: accessUrl ? "describeAppInfo.Domain" : undefined,
15357
+ accessUrls: accessUrls.length > 0 ? accessUrls : undefined,
15358
+ accessUrlSource,
14891
15359
  accessUrlLookupWarning,
14892
15360
  app: appInfo,
14893
15361
  upload: { cosTimestamp: cosTs },
@@ -15444,6 +15912,7 @@ const path_1 = __importDefault(__webpack_require__(2521));
15444
15912
  const zod_1 = __webpack_require__(2971);
15445
15913
  const cloudbase_manager_js_1 = __webpack_require__(3431);
15446
15914
  const cloud_mode_js_1 = __webpack_require__(9684);
15915
+ const gateway_access_urls_js_1 = __webpack_require__(2435);
15447
15916
  const notification_js_1 = __webpack_require__(2720);
15448
15917
  const tool_result_js_1 = __webpack_require__(9835);
15449
15918
  const HOSTING_CDN_SWITCH_VALUES = ['on', 'off'];
@@ -15979,9 +16448,48 @@ function registerHostingTools(server) {
15979
16448
  // StaticDomain there but not in DescribeStaticStore.
15980
16449
  const cdnFromStore = (store.CdnDomain ?? store.StaticDomain);
15981
16450
  const staticDomain = cdnFromStore || await resolveHostingStaticDomain(cloudbase, server.logger);
15982
- 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
+ }
15983
16492
  try {
15984
- const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
15985
16493
  let projectName = 'unknown';
15986
16494
  if (input.localPath) {
15987
16495
  try {
@@ -16016,6 +16524,8 @@ function registerHostingTools(server) {
16016
16524
  ignore: input.ignore,
16017
16525
  staticDomain,
16018
16526
  accessUrl,
16527
+ accessUrls,
16528
+ accessUrlSource,
16019
16529
  result,
16020
16530
  nextActions: uploadPrefix ? [buildFindFilesNextStep(uploadPrefix.replace(/^\/+/, ''))] : undefined,
16021
16531
  },
@@ -16615,6 +17125,219 @@ module.exports = __WEBPACK_EXTERNAL_MODULE_fs_promises_f8dae9d1__;
16615
17125
 
16616
17126
  module.exports = __WEBPACK_EXTERNAL_MODULE_os__;
16617
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
+
16618
17341
  /***/ }),
16619
17342
 
16620
17343
  /***/ 9097: