@cloudbase/cloudbase-mcp 2.32.4 → 2.32.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -4195,15 +4195,20 @@ async function fetchAccountEnvCandidates(cloudBaseOptions) {
4195
4195
  function isApiKeyCredentialMode() {
4196
4196
  return Boolean((0, auth_js_1.getCloudBaseApiKeyFromEnv)() && process.env.CLOUDBASE_ENV_ID);
4197
4197
  }
4198
- function getCredentialScope() {
4198
+ function getCredentialScope(cloudBaseOptions) {
4199
+ // 只认宿主的显式声明 credentialScope: 'env'(如 tcb-bff hosted OAuth 签发的
4200
+ // 环境级 federated STS)。账号级 DescribeEnvs(不带 EnvId)会被后端拒绝(invalid token)。
4201
+ // 注意:不能用 token 字段的有无推断范围——sessionToken 本身不携带权限范围语义。
4202
+ if (cloudBaseOptions?.credentialScope === "env")
4203
+ return "single_env";
4199
4204
  return isApiKeyCredentialMode() ? "single_env" : "account";
4200
4205
  }
4201
4206
  function buildCredentialBoundaryPayload(cloudBaseOptions) {
4202
- const credentialScope = getCredentialScope();
4207
+ const credentialScope = getCredentialScope(cloudBaseOptions);
4203
4208
  const currentRegion = (0, site_map_js_1.resolveSiteAndRegion)(cloudBaseOptions ?? {}).region;
4204
4209
  const pinnedEnvId = process.env.CLOUDBASE_ENV_ID || cloudBaseOptions?.envId || null;
4205
4210
  const scopeNote = credentialScope === "single_env"
4206
- ? `当前为环境级 API Key 登录(单环境权限)。只能访问已绑定的 envId${pinnedEnvId ? ` ${pinnedEnvId}` : ""},看不到账号下其他环境或其他地域。这是凭据权限边界,不是环境不存在。`
4211
+ ? `当前为环境级凭证登录(单环境权限,API Key 或托管授权 token)。只能访问已绑定的 envId${pinnedEnvId ? ` ${pinnedEnvId}` : ""},看不到账号下其他环境或其他地域。这是凭据权限边界,不是环境不存在。queryEnv(action="list") 会自动降级为仅返回绑定环境的信息。`
4207
4212
  : `当前为账号级登录。DescribeEnvs 按地域查询;未传 region 时使用当前地域 ${currentRegion}。其他地域请用 queryEnv(action="list", region="ap-singapore"),或 CLI: tcb env list -r ap-singapore。`;
4208
4213
  return {
4209
4214
  credential_scope: credentialScope,
@@ -4322,6 +4327,24 @@ function buildAuthEnvSetupPayload(preparation) {
4322
4327
  ...buildEnvCandidatePayload(preparation.envCandidates),
4323
4328
  };
4324
4329
  }
4330
+ // API Key 登录态 CAM 能力受限时的用户提示(实测:部分 API Key 换出的 STS 不带 CAM 策略)
4331
+ const API_KEY_CAM_LIMITATION_WARNING = "\n\n⚠️ 注意:该 API Key 换取的临时凭据无法调用管理面 API(CAM 鉴权不通过),管理类工具(queryEnv、queryAppAuth、manageAppAuth 等)将不可用。如需完整能力,请改用长期密钥 TENCENTCLOUD_SECRETID / TENCENTCLOUD_SECRETKEY 认证。";
4332
+ /**
4333
+ * API Key 登录态 AUTH_READY 出口统一追加 CAM 能力探测警告。
4334
+ * 仅在探测明确返回 limited(CAM 拒绝)时追加;capable/unknown 静默通过。
4335
+ */
4336
+ async function appendApiKeyCamWarningIfNeeded(loginState, message) {
4337
+ try {
4338
+ const probe = await (0, cloudbase_manager_js_1.probeApiKeyCamCapability)(loginState);
4339
+ return probe === "limited" ? message + API_KEY_CAM_LIMITATION_WARNING : message;
4340
+ }
4341
+ catch (e) {
4342
+ (0, logger_js_1.debug)("appendApiKeyCamWarningIfNeeded: probe threw", {
4343
+ error: e instanceof Error ? e.message : String(e),
4344
+ });
4345
+ return message;
4346
+ }
4347
+ }
4325
4348
  async function prepareAuthEnvironment(params) {
4326
4349
  const { server, cloudBaseOptions, loginState } = params;
4327
4350
  const currentEnvId = (0, cloudbase_manager_js_1.getCachedEnvId)() ||
@@ -4870,10 +4893,11 @@ function buildEnvQueryErrorMessage(error, action) {
4870
4893
  const hasEnvNotFoundError = /env|environment|环境.*不存在|not found/i.test(baseMessage);
4871
4894
  const suggestions = [];
4872
4895
  if (hasInvalidParameterError) {
4873
- suggestions.push("参数错误:可能是认证信息无效或已过期,请尝试以下步骤:");
4874
- suggestions.push("1. 先调用 auth(action=\"status\") 检查当前登录状态");
4875
- suggestions.push("2. 如果未登录,调用 auth(action=\"start_auth\", authMode=\"device\") 完成登录");
4876
- suggestions.push("3. 登录完成后再次调用 queryEnv(action=\"list\")");
4896
+ suggestions.push("参数错误:请求未通过服务端的参数校验,请检查本次调用的入参:");
4897
+ suggestions.push("1. 各参数取值是否在允许范围内(枚举值、时间粒度、数量上限等)");
4898
+ suggestions.push("2. 各参数格式是否正确,需要成对传入的参数是否齐全");
4899
+ suggestions.push("3. 必填参数是否都已提供,参数名与类型是否正确");
4900
+ suggestions.push(`4. 修正参数后重新调用 queryEnv(action=\"${action}\")`);
4877
4901
  }
4878
4902
  if (hasAuthError) {
4879
4903
  suggestions.push("认证错误:当前未登录或认证已过期。");
@@ -5409,7 +5433,7 @@ function registerEnvTools(server) {
5409
5433
  return (0, tool_result_js_1.buildJsonToolResult)({
5410
5434
  ok: true,
5411
5435
  code: "AUTH_READY",
5412
- message: "当前使用 API Key 认证模式,已自动完成登录,无需手动授权。",
5436
+ message: await appendApiKeyCamWarningIfNeeded(existingLoginState, "当前使用 API Key 认证模式,已自动完成登录,无需手动授权。"),
5413
5437
  auth_mode: "api_key",
5414
5438
  envId: process.env.CLOUDBASE_ENV_ID,
5415
5439
  });
@@ -5420,16 +5444,21 @@ function registerEnvTools(server) {
5420
5444
  (0, logger_js_1.debug)("start_auth: peekLoginState threw", { error: e instanceof Error ? e.message : String(e) });
5421
5445
  }
5422
5446
  // API Key exchange failed: return diagnostic details
5447
+ const exchangeRegion = (0, site_map_js_1.resolveApiKeyExchangeRegion)();
5423
5448
  let diagMessage = "当前配置了 API Key 认证模式,但换取临时密钥失败。";
5424
- const endpoint = process.env.CLOUDBASE_API_ENDPOINT || `https://${process.env.CLOUDBASE_ENV_ID}.ap-shanghai.tcb-api.tencentcloudapi.com`;
5449
+ const endpoint = process.env.CLOUDBASE_API_ENDPOINT ||
5450
+ `https://${process.env.CLOUDBASE_ENV_ID}.${exchangeRegion ?? "ap-shanghai"}.tcb-api.tencentcloudapi.com`;
5425
5451
  diagMessage += `\n\n诊断信息:`;
5426
5452
  diagMessage += `\n- CLOUDBASE_ENV_ID: ${process.env.CLOUDBASE_ENV_ID}`;
5427
5453
  diagMessage += `\n- CLOUDBASE_API_KEY: ${apiKeyFromEnv.slice(0, 20)}...(已截断)`;
5454
+ diagMessage += `\n- TCB_SITE: ${process.env.TCB_SITE || "(未设置)"}`;
5455
+ diagMessage += `\n- 换取网关地域: ${exchangeRegion ?? "ap-shanghai(国内站默认,多地域环境均经其路由)"}`;
5428
5456
  diagMessage += `\n- Endpoint: ${endpoint}`;
5429
5457
  diagMessage += `\n\n可能原因:`;
5430
5458
  diagMessage += `\n1. API Key 已过期或被删除`;
5431
5459
  diagMessage += `\n2. Endpoint 不可达(网络/DNS 问题)`;
5432
5460
  diagMessage += `\n3. CLOUDBASE_ENV_ID 与 API Key 所属环境不匹配`;
5461
+ diagMessage += `\n4. API Key 与站点不匹配:国际站环境的 Key 需配置 TCB_SITE=intl(走 ap-singapore 网关);国内站环境(含 ap-guangzhou/ap-singapore 地域)不要配置 intl`;
5433
5462
  diagMessage += `\n\n建议:检查 MCP 配置中的 CLOUDBASE_API_KEY(或兼容的 CLOUDBASE_APIKEY)和 CLOUDBASE_ENV_ID 环境变量是否正确。`;
5434
5463
  return (0, tool_result_js_1.buildJsonToolResult)({
5435
5464
  ok: false,
@@ -5640,7 +5669,7 @@ function registerEnvTools(server) {
5640
5669
  return (0, tool_result_js_1.buildJsonToolResult)({
5641
5670
  ok: true,
5642
5671
  code: "AUTH_READY",
5643
- message: "API Key 认证成功,已获取临时密钥。",
5672
+ message: await appendApiKeyCamWarningIfNeeded(loginState, "API Key 认证成功,已获取临时密钥。"),
5644
5673
  auth_mode: "api_key",
5645
5674
  ...buildAuthEnvSetupPayload(envPreparation),
5646
5675
  next_step: envPreparation.nextStep,
@@ -5653,10 +5682,12 @@ function registerEnvTools(server) {
5653
5682
  diagMessage += `\n\n诊断信息:`;
5654
5683
  diagMessage += `\n- CLOUDBASE_ENV_ID: ${toolApiKeyEnvId}`;
5655
5684
  diagMessage += `\n- CLOUDBASE_API_KEY: ${toolApiKey.slice(0, 20)}...(已截断)`;
5685
+ diagMessage += `\n- TCB_SITE: ${process.env.TCB_SITE || "(未设置)"}`;
5656
5686
  diagMessage += `\n\n可能原因:`;
5657
5687
  diagMessage += `\n1. API Key 已过期或被删除`;
5658
5688
  diagMessage += `\n2. CLOUDBASE_ENV_ID 与 API Key 所属环境不匹配`;
5659
- diagMessage += `\n3. 网络连接问题`;
5689
+ diagMessage += `\n3. API Key 与站点不匹配:国际站环境的 Key 需配置 TCB_SITE=intl(走 ap-singapore 网关);国内站环境(含 ap-guangzhou/ap-singapore 地域)不要配置 intl`;
5690
+ diagMessage += `\n4. 网络连接问题`;
5660
5691
  diagMessage += `\n\n建议:请检查 API Key 和环境 ID 是否正确。`;
5661
5692
  return (0, tool_result_js_1.buildJsonToolResult)({
5662
5693
  ok: false,
@@ -5880,9 +5911,19 @@ function registerEnvTools(server) {
5880
5911
  // API Key / env-var pin: skip DescribeEnvs (STS often cannot list).
5881
5912
  // Account-level sessions that only pinned CLOUDBASE_ENV_ID via set_env
5882
5913
  // can still pass region/alias/envId to list other environments.
5883
- const envIdFromEnv = !cloudBaseOptions?.requestFn && process.env.CLOUDBASE_ENV_ID;
5914
+ // Hosted OAuth: 宿主(tcb-bff)显式声明 credentialScope: 'env',签发的
5915
+ // 环境级 federated STS 调账号级 DescribeEnvs 会被拒("invalid token"),
5916
+ // 同样 pin 到绑定 envId 降级为 describeEnvInfo。
5917
+ const isEnvScopedCredential = cloudBaseOptions?.credentialScope === "env" &&
5918
+ typeof cloudBaseOptions?.envId === "string" &&
5919
+ cloudBaseOptions.envId.length > 0;
5920
+ const envIdFromEnv = !cloudBaseOptions?.requestFn &&
5921
+ (process.env.CLOUDBASE_ENV_ID ||
5922
+ (isEnvScopedCredential ? cloudBaseOptions.envId : undefined));
5884
5923
  const shouldPinToEnvVar = Boolean(envIdFromEnv &&
5885
- (isApiKeyCredentialMode() || (!region && !alias && !envId)));
5924
+ (isApiKeyCredentialMode() ||
5925
+ isEnvScopedCredential ||
5926
+ (!region && !alias && !envId)));
5886
5927
  if (shouldPinToEnvVar && envIdFromEnv) {
5887
5928
  try {
5888
5929
  const envInfo = await cloudbaseList.env.describeEnvInfo({ EnvId: envIdFromEnv });
@@ -5905,6 +5946,13 @@ function registerEnvTools(server) {
5905
5946
  (0, logger_js_1.debug)("DescribeEnvInfo 失败,返回基础环境信息:", envInfoError instanceof Error ? envInfoError : new Error(String(envInfoError)));
5906
5947
  result = { EnvList: [{ EnvId: envIdFromEnv }] };
5907
5948
  }
5949
+ // 给调用方 AI 说明降级原因,避免误判为"账号只有一个环境"
5950
+ if (isEnvScopedCredential) {
5951
+ result = {
5952
+ ...result,
5953
+ scope_note: `当前凭证为环境级(托管授权凭证绑定 ${envIdFromEnv}),账号级环境列表接口无权限,已降级为仅返回绑定环境的信息。如需查看账号下全部环境,请用有账号级权限的凭证登录。`,
5954
+ };
5955
+ }
5908
5956
  }
5909
5957
  else {
5910
5958
  // Use commonService to call DescribeEnvs with filter parameters
@@ -29421,6 +29469,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
29421
29469
  };
29422
29470
  Object.defineProperty(exports, "__esModule", ({ value: true }));
29423
29471
  exports.envManager = void 0;
29472
+ exports.probeApiKeyCamCapability = probeApiKeyCamCapability;
29424
29473
  exports.listAvailableEnvCandidates = listAvailableEnvCandidates;
29425
29474
  exports.resolveEnvCandidateByEnvId = resolveEnvCandidateByEnvId;
29426
29475
  exports.getEnvId = getEnvId;
@@ -29465,6 +29514,53 @@ function createManagerFromLoginState(loginState, region) {
29465
29514
  region: region ?? (0, site_map_js_1.resolveSiteAndRegion)().region,
29466
29515
  });
29467
29516
  }
29517
+ // 仅缓存确定性结果(capable/limited),unknown 不缓存以便下次重试
29518
+ const apiKeyCamProbeCache = new Map();
29519
+ const CAM_PROBE_TIMEOUT_MS = 8000;
29520
+ /**
29521
+ * 轻量探测 API Key 登录态能否调用管理面(CAM)API。
29522
+ * 背景:部分 API Key(如"AI 开发套件"形态的 JWT key)只能完成 tcb-api 网关的登录态换取,
29523
+ * 换出的 STS 凭据不带 CAM 策略,queryEnv/queryAppAuth 等管理类工具会全部失败。
29524
+ * 实测凭据:2026-09-01 国际站认证排查(specs/intl-auth-investigation)。
29525
+ */
29526
+ async function probeApiKeyCamCapability(loginState) {
29527
+ if (!loginState.secretId || !loginState.secretKey || !loginState.envId) {
29528
+ return "unknown";
29529
+ }
29530
+ const cacheKey = `${loginState.secretId}:${loginState.envId}`;
29531
+ const cached = apiKeyCamProbeCache.get(cacheKey);
29532
+ if (cached !== undefined) {
29533
+ return cached ? "capable" : "limited";
29534
+ }
29535
+ try {
29536
+ const manager = createManagerFromLoginState(loginState);
29537
+ // 查询环境详情(DescribeEnvInfo):单环境、入参仅 EnvId,比 DescribeEnvs 更贴合
29538
+ // "登录后查环境" 的首个真实调用;Action 名已对照 CAM 资源级策略文档确认
29539
+ const probeCall = manager.commonService("tcb").call({
29540
+ Action: "DescribeEnvInfo",
29541
+ Param: { EnvId: loginState.envId },
29542
+ });
29543
+ const timeout = new Promise((_, reject) => {
29544
+ const timer = setTimeout(() => reject(new Error("probe timeout")), CAM_PROBE_TIMEOUT_MS);
29545
+ // 不阻塞进程退出
29546
+ timer.unref?.();
29547
+ });
29548
+ await Promise.race([probeCall, timeout]);
29549
+ apiKeyCamProbeCache.set(cacheKey, true);
29550
+ return "capable";
29551
+ }
29552
+ catch (e) {
29553
+ const code = e?.code ?? (e instanceof Error ? e.message : String(e));
29554
+ // 仅把 CAM 明确拒绝判定为 limited;超时/网络等 inconclusive 失败归为 unknown
29555
+ if (code.includes("UnauthorizedOperation") || code.includes("invalid token")) {
29556
+ (0, logger_js_1.debug)("probeApiKeyCamCapability: CAM rejected", { code });
29557
+ apiKeyCamProbeCache.set(cacheKey, false);
29558
+ return "limited";
29559
+ }
29560
+ (0, logger_js_1.debug)("probeApiKeyCamCapability: inconclusive failure", { code });
29561
+ return "unknown";
29562
+ }
29563
+ }
29468
29564
  async function listAvailableEnvCandidates(options) {
29469
29565
  const { cloudBaseOptions, loginState: providedLoginState, region: regionOverride, ignorePinnedEnvId, } = options ?? {};
29470
29566
  if (!ignorePinnedEnvId) {
@@ -95078,10 +95174,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
95078
95174
  return (mod && mod.__esModule) ? mod : { "default": mod };
95079
95175
  };
95080
95176
  Object.defineProperty(exports, "__esModule", ({ value: true }));
95081
- exports.CUSTOM_IMAGE_RUNTIME = exports.LAYER_SOFT_WARN = exports.MANAGE_FUNCTION_ACTIONS = exports.QUERY_FUNCTION_ACTIONS = exports.TRIGGER_CONFIG_EXAMPLES = exports.SUPPORTED_TRIGGER_TYPES = exports.DEFAULT_NODEJS_RUNTIME = exports.SUPPORTED_NODEJS_RUNTIMES = exports.RECOMMENDED_RUNTIMES = exports.DEFAULT_RUNTIME = exports.ALL_SUPPORTED_RUNTIMES = exports.SUPPORTED_RUNTIMES = void 0;
95177
+ exports.CUSTOM_IMAGE_RUNTIME = exports.MASKED_ENV_VALUE = exports.LAYER_SOFT_WARN = exports.MANAGE_FUNCTION_ACTIONS = exports.QUERY_FUNCTION_ACTIONS = exports.TRIGGER_CONFIG_EXAMPLES = exports.SUPPORTED_TRIGGER_TYPES = exports.DEFAULT_NODEJS_RUNTIME = exports.SUPPORTED_NODEJS_RUNTIMES = exports.RECOMMENDED_RUNTIMES = exports.DEFAULT_RUNTIME = exports.ALL_SUPPORTED_RUNTIMES = exports.SUPPORTED_RUNTIMES = void 0;
95082
95178
  exports.formatRuntimeList = formatRuntimeList;
95083
95179
  exports.layerNameIncludesEnvId = layerNameIncludesEnvId;
95084
95180
  exports.buildCreateLayerNameWarning = buildCreateLayerNameWarning;
95181
+ exports.maskFunctionDetailEnvValues = maskFunctionDetailEnvValues;
95085
95182
  exports.validateTimerCron = validateTimerCron;
95086
95183
  exports.pickManageFunctionName = pickManageFunctionName;
95087
95184
  exports.shouldInstallDependencyForFunction = shouldInstallDependencyForFunction;
@@ -95206,8 +95303,33 @@ function buildCreateLayerNameWarning(layerName, envId) {
95206
95303
  }
95207
95304
  return exports.LAYER_SOFT_WARN.createNameFormat(envId);
95208
95305
  }
95209
- const VPC_SCHEMA = zod_1.z.object({
95210
- vpcId: zod_1.z
95306
+ /** 环境变量脱敏后的占位值(不保留任何明文片段)。 */
95307
+ exports.MASKED_ENV_VALUE = "***";
95308
+ /**
95309
+ * 对 getFunctionDetail 返回的 Environment.Variables 做脱敏:
95310
+ * 保留 Key 与原始值长度(ValueLength),Value 置为占位符。
95311
+ * 用于默认工具返回与日志落盘,避免明文进入模型上下文 / 持久化日志。
95312
+ */
95313
+ function maskFunctionDetailEnvValues(detail) {
95314
+ const variables = detail?.Environment?.Variables;
95315
+ if (!Array.isArray(variables) || variables.length === 0) {
95316
+ return detail;
95317
+ }
95318
+ return {
95319
+ ...detail,
95320
+ Environment: {
95321
+ ...detail.Environment,
95322
+ Variables: variables.map((item) => ({
95323
+ ...item,
95324
+ Value: exports.MASKED_ENV_VALUE,
95325
+ ...(typeof item.Value === "string"
95326
+ ? { ValueLength: item.Value.length }
95327
+ : {}),
95328
+ })),
95329
+ },
95330
+ };
95331
+ }
95332
+ const VPC_SCHEMA = zod_1.z.object({ vpcId: zod_1.z
95211
95333
  .string()
95212
95334
  .describe("VPC ID from the real database/network console (e.g. vpc-xxxxxxxx). Required for non-native TCP DB access. Do NOT invent or use placeholders."),
95213
95335
  subnetId: zod_1.z
@@ -95577,15 +95699,19 @@ function registerFunctionTools(server) {
95577
95699
  }
95578
95700
  const cloudbase = await getManager();
95579
95701
  const result = await cloudbase.functions.getFunctionDetail(input.functionName, input.codeSecret);
95580
- (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
95702
+ // 日志侧一律脱敏(持久化,不提供明文口子);工具返回侧按 revealEnvValues 决定
95703
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, maskFunctionDetailEnvValues(result));
95704
+ const functionDetail = input.revealEnvValues === true
95705
+ ? result
95706
+ : maskFunctionDetailEnvValues(result);
95581
95707
  return buildEnvelope({
95582
95708
  action: input.action,
95583
95709
  functionName: input.functionName,
95584
- functionDetail: result,
95710
+ functionDetail,
95585
95711
  layers: normalizeFunctionLayers(result.Layers),
95586
95712
  triggers: result.Triggers || [],
95587
95713
  requestId: result.RequestId,
95588
- raw: result,
95714
+ raw: functionDetail,
95589
95715
  }, `已获取函数 ${input.functionName} 的详情`, [
95590
95716
  {
95591
95717
  tool: "queryFunctions",
@@ -95803,13 +95929,16 @@ function registerFunctionTools(server) {
95803
95929
  }
95804
95930
  const cloudbase = await getManager();
95805
95931
  const result = await cloudbase.functions.getFunctionDetail(input.functionName, input.codeSecret);
95806
- (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
95932
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, maskFunctionDetailEnvValues(result));
95933
+ const detail = input.revealEnvValues === true
95934
+ ? result
95935
+ : maskFunctionDetailEnvValues(result);
95807
95936
  return buildEnvelope({
95808
95937
  action: input.action,
95809
95938
  functionName: input.functionName,
95810
- triggers: result.Triggers || [],
95811
- requestId: result.RequestId,
95812
- raw: result,
95939
+ triggers: detail.Triggers || [],
95940
+ requestId: detail.RequestId,
95941
+ raw: detail,
95813
95942
  }, `已获取函数 ${input.functionName} 的触发器列表`, [
95814
95943
  {
95815
95944
  tool: "manageFunctions",
@@ -96563,6 +96692,10 @@ function registerFunctionTools(server) {
96563
96692
  limit: zod_1.z.number().optional().describe("分页数量(limit)。列表类 action 可选,默认值由后端决定"),
96564
96693
  offset: zod_1.z.number().optional().describe("分页偏移(offset)。列表类 action 可选,默认 0"),
96565
96694
  codeSecret: zod_1.z.string().optional().describe("代码保护密钥,用于解密函数代码"),
96695
+ revealEnvValues: zod_1.z
96696
+ .boolean()
96697
+ .optional()
96698
+ .describe("getFunctionDetail / listFunctionTriggers 时是否返回环境变量明文值。默认 false:Value 脱敏为 ***,仅保留 Key 与 ValueLength,足以确认配置了哪些变量及变更是否生效;true 时返回明文,敏感变量会进入模型上下文,谨慎使用。如需查看明文,建议优先使用控制台或 CLI"),
96566
96699
  startTime: zod_1.z
96567
96700
  .string()
96568
96701
  .optional()
@@ -121607,7 +121740,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
121607
121740
  return (mod && mod.__esModule) ? mod : { "default": mod };
121608
121741
  };
121609
121742
  Object.defineProperty(exports, "__esModule", ({ value: true }));
121610
- exports.CLOUDRUN_ENV_TYPE = exports.CLOUDRUN_DEPLOY_REGISTRATION_INTERVAL_MS = exports.CLOUDRUN_DEPLOY_REGISTRATION_MAX_WAIT_MS = exports.CLOUDRUN_PACKAGE_TYPES = exports.CLOUDRUN_ACCESS_TYPES = exports.CLOUDRUN_SERVICE_TYPES = void 0;
121743
+ exports.CLOUDRUN_ENV_TYPE = exports.CLOUDRUN_DEPLOY_REGISTRATION_INTERVAL_MS = exports.CLOUDRUN_DEPLOY_REGISTRATION_MAX_WAIT_MS = exports.MASKED_CLOUDRUN_ENV_VALUE = exports.CLOUDRUN_PACKAGE_TYPES = exports.CLOUDRUN_ACCESS_TYPES = exports.CLOUDRUN_SERVICE_TYPES = void 0;
121744
+ exports.maskCloudRunDetailEnvParams = maskCloudRunDetailEnvParams;
121611
121745
  exports.buildManageCloudRunErrorMessage = buildManageCloudRunErrorMessage;
121612
121746
  exports.isValidCloudRunBuildId = isValidCloudRunBuildId;
121613
121747
  exports.isValidCloudRunRunId = isValidCloudRunRunId;
@@ -121641,6 +121775,40 @@ exports.CLOUDRUN_SERVICE_TYPES = ['function', 'container'];
121641
121775
  exports.CLOUDRUN_ACCESS_TYPES = ['OA', 'PUBLIC', 'MINIAPP', 'VPC'];
121642
121776
  // CloudRun env package types (CreateCloudRunEnv.PackageType)
121643
121777
  exports.CLOUDRUN_PACKAGE_TYPES = ['Trial', 'Standard', 'Professional', 'Enterprise'];
121778
+ /** 环境变量脱敏后的占位值(不保留任何明文片段)。 */
121779
+ exports.MASKED_CLOUDRUN_ENV_VALUE = "***";
121780
+ /**
121781
+ * 对云托管 detail 返回的 ServerConfig.EnvParams(JSON 字符串)做脱敏:
121782
+ * 解析后把所有 value 置为占位符、保留 key,再序列化回 JSON 字符串。
121783
+ * 解析失败(非 JSON)时整串替换为占位符,避免任何明文片段外泄。
121784
+ * 用于默认工具返回,避免明文进入模型上下文。
121785
+ */
121786
+ function maskCloudRunDetailEnvParams(detail) {
121787
+ const envParams = detail?.ServerConfig?.EnvParams;
121788
+ if (typeof envParams !== "string" || envParams === "") {
121789
+ return detail;
121790
+ }
121791
+ let masked;
121792
+ try {
121793
+ const parsed = JSON.parse(envParams);
121794
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
121795
+ masked = JSON.stringify(Object.fromEntries(Object.entries(parsed).map(([key]) => [key, exports.MASKED_CLOUDRUN_ENV_VALUE])));
121796
+ }
121797
+ else {
121798
+ masked = exports.MASKED_CLOUDRUN_ENV_VALUE;
121799
+ }
121800
+ }
121801
+ catch {
121802
+ masked = exports.MASKED_CLOUDRUN_ENV_VALUE;
121803
+ }
121804
+ return {
121805
+ ...detail,
121806
+ ServerConfig: {
121807
+ ...detail.ServerConfig,
121808
+ EnvParams: masked,
121809
+ },
121810
+ };
121811
+ }
121644
121812
  // Input schema for queryCloudRun tool
121645
121813
  const queryCloudRunInputSchema = {
121646
121814
  action: zod_1.z.enum(['list', 'detail', 'templates', 'getDeployLog', 'getProcessLog', 'getDeployRecords', 'envStatus']).describe('查询操作类型:list=获取云托管服务列表(支持分页和筛选),detail=查询指定服务的详细信息(包含服务配置和最新部署状态),templates=获取可用的项目模板列表(用于初始化新项目),getDeployLog=获取构建日志(仅云端源码构建有意义,走 CODING/DescribeCloudRunBuildLog;已有镜像部署无构建过程;未登录 CODING 的账号会报错),getProcessLog=获取运行日志(部署阶段步骤+容器启动/运行日志,走 tcbr/DescribeCloudRunProcessLog;镜像部署与源码构建均可用,不依赖 CODING;RunId 来自 detail/getDeployRecords 的 latestDeploy.RunId),getDeployRecords=获取指定服务的部署记录列表(按部署时间倒序,含 BuildId/RunId/FlowRatio/Status 等字段,用于查看历史发布与回滚上下文),envStatus=查询当前环境云托管是否已开通及开通状态(Status=creating开通中/normal已开通),用于initEnv之后轮询进度或deploy之前确认环境是否就绪'),
@@ -121654,6 +121822,7 @@ const queryCloudRunInputSchema = {
121654
121822
  detailServerName: zod_1.z.string().optional().describe('要查询详细信息、部署记录、构建日志或运行日志的服务名称。当action为detail、getDeployLog、getProcessLog或getDeployRecords时建议提供,必须是已存在的服务名称。可通过list操作获取可用的服务名称列表'),
121655
121823
  buildId: zod_1.z.number().optional().describe('构建ID,仅在action=getDeployLog时使用(构建日志,仅云端源码构建)。不传时默认返回最近一次部署的构建日志'),
121656
121824
  runId: zod_1.z.string().optional().describe('运行ID(RunId),仅在action=getProcessLog时使用。不传时默认取该服务最近一次部署记录的 RunId(与 detail/getDeployRecords 的 latestDeploy.RunId 同源)。镜像部署与源码构建均可查询运行日志'),
121825
+ revealEnvParams: zod_1.z.boolean().optional().default(false).describe('是否返回服务环境变量(ServerConfig.EnvParams)明文值(仅 action=detail 时生效)。默认 false,值脱敏为 "***"(保留 key,足够排查配置了哪些变量、变更是否生效);true 时返回明文,敏感变量(如带密码的 DATABASE_URL)可能暴露给模型上下文,谨慎使用'),
121657
121826
  };
121658
121827
  // Input schema for manageCloudRun tool
121659
121828
  const ManageCloudRunInputSchema = {
@@ -122519,7 +122688,8 @@ function registerCloudRunTools(server) {
122519
122688
  text: JSON.stringify({
122520
122689
  success: true,
122521
122690
  data: {
122522
- service: result,
122691
+ // 默认脱敏 ServerConfig.EnvParams 的值(保留 key);revealEnvParams=true 时返回明文
122692
+ service: input.revealEnvParams === true ? result : maskCloudRunDetailEnvParams(result),
122523
122693
  latestDeploy,
122524
122694
  // 若最新部署记录带镜像信息(镜像部署),透出便于展示
122525
122695
  ...(extractCloudRunImageInfo(result, latestDeploy)
@@ -129798,10 +129968,33 @@ function buildFailureResult(action, error) {
129798
129968
  message: enrichRateLimitMessage(error instanceof Error ? error.message : String(error)),
129799
129969
  });
129800
129970
  }
129971
+ function extractFileList(files) {
129972
+ // hosting.listFiles 直接返回文件数组
129973
+ if (Array.isArray(files))
129974
+ return files;
129975
+ // hosting.findFiles 返回 COS 风格对象,文件列表在 Contents 里
129976
+ if (typeof files === 'object' && files !== null) {
129977
+ const record = files;
129978
+ if (Array.isArray(record.Contents))
129979
+ return record.Contents;
129980
+ if (Array.isArray(record.contents))
129981
+ return record.contents;
129982
+ }
129983
+ return [];
129984
+ }
129985
+ function extractFilePagination(result) {
129986
+ if (typeof result !== 'object' || result === null)
129987
+ return {};
129988
+ const record = result;
129989
+ const isTruncated = record.IsTruncated ?? record.isTruncated;
129990
+ const nextMarker = record.NextMarker ?? record.nextMarker;
129991
+ return {
129992
+ isTruncated: typeof isTruncated === 'boolean' ? isTruncated : undefined,
129993
+ nextMarker: typeof nextMarker === 'string' && nextMarker.length > 0 ? nextMarker : undefined,
129994
+ };
129995
+ }
129801
129996
  function normalizeFileFields(files) {
129802
- if (!Array.isArray(files))
129803
- return [];
129804
- return files.map(file => {
129997
+ return extractFileList(files).map((file) => {
129805
129998
  if (typeof file !== 'object' || file === null)
129806
129999
  return file;
129807
130000
  const record = file;
@@ -129890,6 +130083,8 @@ function registerHostingTools(server) {
129890
130083
  });
129891
130084
  (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
129892
130085
  const normalizedFiles = normalizeFileFields(result);
130086
+ // findFiles 的 marker 是 COS 游标字符串,与 listFiles 的数字 offset 语义不同,此处只透传不做解析
130087
+ const { isTruncated, nextMarker } = extractFilePagination(result);
129893
130088
  return (0, tool_result_js_1.buildJsonToolResult)({
129894
130089
  success: true,
129895
130090
  data: {
@@ -129898,9 +130093,11 @@ function registerHostingTools(server) {
129898
130093
  marker: input.marker,
129899
130094
  maxKeys: input.maxKeys,
129900
130095
  files: normalizedFiles,
130096
+ nextMarker,
130097
+ isTruncated,
129901
130098
  result,
129902
130099
  },
129903
- message: `已按前缀 \`${input.prefix}\` 查询静态托管文件,共 ${Array.isArray(normalizedFiles) ? normalizedFiles.length : 0} 个。`,
130100
+ message: `已按前缀 \`${input.prefix}\` 查询静态托管文件,共 ${normalizedFiles.length} 个。${nextMarker ? ' 还有更多文件,可使用 nextMarker 继续查询。' : ''}`,
129904
130101
  });
129905
130102
  }
129906
130103
  case 'listFiles': {
@@ -149548,7 +149745,7 @@ class TelemetryReporter {
149548
149745
  const arch = os_1.default.arch(); // 系统架构
149549
149746
  // Build-time injected version; guard for vitest / non-webpack runtimes.
149550
149747
  const mcpVersion = process.env.npm_package_version ||
149551
- ( true ? "2.32.4" : 0);
149748
+ ( true ? "2.32.5" : 0);
149552
149749
  return {
149553
149750
  userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
149554
149751
  deviceId: this.deviceId,
@@ -178606,7 +178803,7 @@ async function handleReadOnlySql(args, context, deps) {
178606
178803
  message: `PostgreSQL read-only SQL execution failed: ${reason}`,
178607
178804
  data: {
178608
178805
  role: context.role,
178609
- sqlPreview: limitedSql.trim().slice(0, 500),
178806
+ sqlPreview: args.sql.trim().slice(0, 500),
178610
178807
  },
178611
178808
  });
178612
178809
  }
@@ -217980,8 +218177,7 @@ const cloudbase_manager_js_1 = __webpack_require__(3431);
217980
218177
  const json_content_js_1 = __webpack_require__(4365);
217981
218178
  const logger_js_1 = __webpack_require__(13039);
217982
218179
  // 1. 枚举定义
217983
- const KnowledgeBaseEnum = zod_1.z.enum(["cloudbase", "scf", "miniprogram"]);
217984
- const SearchKnowledgeModeEnum = zod_1.z.enum(["vector", "skill", "openapi", "docs"]);
218180
+ const SearchKnowledgeModeEnum = zod_1.z.enum(["skill", "openapi", "docs"]);
217985
218181
  const CloudBaseDocsActionEnum = zod_1.z.enum([
217986
218182
  "listModules",
217987
218183
  "listModuleDocs",
@@ -217989,12 +218185,6 @@ const CloudBaseDocsActionEnum = zod_1.z.enum([
217989
218185
  "readDoc",
217990
218186
  "searchDocs",
217991
218187
  ]);
217992
- // 2. 枚举到后端 id 的映射
217993
- const KnowledgeBaseIdMap = {
217994
- cloudbase: "ykfzskv4_ad28",
217995
- scf: "scfsczskzyws_4bdc",
217996
- miniprogram: "xcxzskws_25d8",
217997
- };
217998
218188
  // ============ 缓存配置 ============
217999
218189
  const CACHE_BASE_DIR = path.join(os.homedir(), ".cloudbase-mcp");
218000
218190
  const CACHE_META_FILE = path.join(CACHE_BASE_DIR, "cache-meta.json");
@@ -218118,32 +218308,6 @@ async function updateCache() {
218118
218308
  await fs.mkdir(CACHE_BASE_DIR, { recursive: true });
218119
218309
  await fs.writeFile(CACHE_META_FILE, JSON.stringify({ timestamp: Date.now() }, null, 2), "utf8");
218120
218310
  }
218121
- // 安全 JSON.parse
218122
- function safeParse(str) {
218123
- try {
218124
- return JSON.parse(str);
218125
- }
218126
- catch (e) {
218127
- return {};
218128
- }
218129
- }
218130
- // 安全 JSON.stringify,处理循环引用
218131
- function safeStringify(obj) {
218132
- const seen = new WeakSet();
218133
- try {
218134
- return JSON.stringify(obj, function (key, value) {
218135
- if (typeof value === "object" && value !== null) {
218136
- if (seen.has(value))
218137
- return;
218138
- seen.add(value);
218139
- }
218140
- return value;
218141
- });
218142
- }
218143
- catch (e) {
218144
- return "";
218145
- }
218146
- }
218147
218311
  function buildDocsEnvelope(action, data, message) {
218148
218312
  return {
218149
218313
  success: true,
@@ -218405,9 +218569,13 @@ async function registerRagTools(server) {
218405
218569
  ?.docs;
218406
218570
  server.registerTool?.("searchKnowledgeBase", {
218407
218571
  title: "云开发知识库检索",
218408
- description: `云开发知识库智能检索工具,支持向量查询 (vector)、固定技能文档 (skill)、OpenAPI 文档 (openapi) 和 CloudBase 官方文档 (docs) 查询。
218572
+ description: `云开发知识库检索工具,支持 CloudBase 官方文档 (docs)、固定技能文档 (skill) 和 OpenAPI 文档 (openapi) 查询。
218409
218573
 
218410
- 强烈推荐始终优先使用固定技能文档 (skill)、OpenAPI 文档 (openapi) 或 CloudBase 官方文档 (docs) 模式进行检索,仅当固定文档无法覆盖你的问题时,再使用向量查询 (vector) 模式。
218574
+ 按场景选择 mode:
218575
+ - 不确定答案在哪、需要对官方文档做全文检索时:mode=docs + action=searchDocs(传 query 关键词)
218576
+ - 已知文档标题、层级路径或 URL 时:mode=docs + action=findByName(传 input)或 action=readDoc(传 docPath)
218577
+ - 需要某个场景的落地指南 / 最佳实践时:mode=skill + skillName
218578
+ - 需要 HTTP API 的接口定义时:mode=openapi + apiName
218411
218579
 
218412
218580
  ⚠️ 重要:当 CloudBase skills 处于禁用状态或当前 IDE 不支持 skill 文件读取时,必须使用 searchKnowledgeBase(mode=skill, skillName=...) 来获取 CloudBase 技能文档内容,而不是尝试直接读取 skill 文件。直接读取可能返回 400 错误。示例:
218413
218581
  - 需要最小 Web+数据库 Demo 路径时:searchKnowledgeBase(mode=skill, skillName=minimal-web-baas-demo)
@@ -218445,37 +218613,13 @@ async function registerRagTools(server) {
218445
218613
  .string()
218446
218614
  .optional()
218447
218615
  .describe("mode=docs 且 action=searchDocs 时指定。全文检索关键词。"),
218448
- threshold: zod_1.z
218449
- .number()
218450
- .default(0.5)
218451
- .optional()
218452
- .describe("mode=vector 时指定。相似性检索阈值"),
218453
- id: KnowledgeBaseEnum.default("cloudbase").optional().describe("mode=vector 时指定。知识库范围,默认 cloudbase。cloudbase=云开发全量知识,scf=云开发的云函数知识, miniprogram=小程序知识(不包含云开发与云函数知识)"),
218454
- content: zod_1.z.string().describe("mode=vector 时指定。检索内容").optional(),
218455
- options: zod_1.z
218456
- .object({
218457
- chunkExpand: zod_1.z
218458
- .array(zod_1.z.number())
218459
- .min(2)
218460
- .max(2)
218461
- .default([3, 3])
218462
- .describe("指定返回的文档内容的展开长度,例如 [3,3]代表前后展开长度"),
218463
- })
218464
- .optional()
218465
- .describe("mode=vector 时指定。其他选项"),
218466
- limit: zod_1.z
218467
- .number()
218468
- .default(5)
218469
- .optional()
218470
- .describe("mode=vector 时指定。指定返回最相似的 Top K 的 K 的值"),
218471
218616
  },
218472
218617
  annotations: {
218473
218618
  readOnlyHint: true,
218474
218619
  openWorldHint: true,
218475
218620
  category: "rag",
218476
218621
  },
218477
- }, async ({ id, content, options, limit = 5, threshold = 0.5, mode, skillName, apiName, action, moduleName, input, docPath, query, }) => {
218478
- const chunkExpand = options?.chunkExpand ?? [3, 3];
218622
+ }, async ({ mode, skillName, apiName, action, moduleName, input, docPath, query, }) => {
218479
218623
  if (mode === "docs") {
218480
218624
  try {
218481
218625
  const resolvedAction = action;
@@ -218555,76 +218699,8 @@ async function registerRagTools(server) {
218555
218699
  ],
218556
218700
  };
218557
218701
  }
218558
- // 向量检索模式下必须提供 id 和 content,避免后端报「知识库名称不能为空」
218559
- const vectorKnowledgeBaseId = id ?? "cloudbase";
218560
- if (mode === "vector") {
218561
- if (!content || !content.trim()) {
218562
- throw new Error("检索内容不能为空: please provide non-empty `content` when mode=vector.");
218563
- }
218564
- }
218565
- // 枚举到后端 id 映射
218566
- const backendId = KnowledgeBaseIdMap[vectorKnowledgeBaseId] ||
218567
- vectorKnowledgeBaseId;
218568
- const signInRes = await fetch("https://tcb-advanced-a656fc.api.tcloudbasegateway.com/auth/v1/signin/anonymously", {
218569
- method: "POST",
218570
- headers: {
218571
- "Content-Type": "application/json",
218572
- Accept: "application/json",
218573
- "x-device-id": "cloudbase-ai-toolkit",
218574
- },
218575
- body: safeStringify({
218576
- collectionView: backendId,
218577
- options: {
218578
- chunkExpand,
218579
- },
218580
- search: {
218581
- content: content,
218582
- limit,
218583
- },
218584
- }),
218585
- });
218586
- const token = (await signInRes.json()).access_token;
218587
- const res = await fetch(`https://tcb-advanced-a656fc.api.tcloudbasegateway.com/v1/knowledge/search`, {
218588
- method: "POST",
218589
- headers: {
218590
- "Content-Type": "application/json",
218591
- Authorization: `Bearer ${token}`,
218592
- },
218593
- body: safeStringify({
218594
- collectionView: backendId,
218595
- options: {
218596
- chunkExpand,
218597
- },
218598
- search: {
218599
- content: content,
218600
- limit,
218601
- },
218602
- }),
218603
- });
218604
- const result = await res.json();
218605
- if (result.code) {
218606
- throw new Error(result.message);
218607
- }
218608
- return {
218609
- content: [
218610
- {
218611
- type: "text",
218612
- text: safeStringify(result.data.documents
218613
- .filter((item) => item.score >= threshold)
218614
- .map((item) => {
218615
- return {
218616
- score: item.score,
218617
- fileTile: item.documentSet.fileTitle,
218618
- url: safeParse(item.documentSet.fileMetaData).url,
218619
- paragraphTitle: item.data.paragraphTitle,
218620
- text: `${item.data.pre?.join("\n") || ""}
218621
- ${item.data.text}
218622
- ${item.data.next?.join("\n") || ""}`,
218623
- };
218624
- })),
218625
- },
218626
- ],
218627
- };
218702
+ // mode 是枚举,docs / skill / openapi 三个分支已在上面全部返回,这里不可达
218703
+ throw new Error(`unsupported mode: ${String(mode)}`);
218628
218704
  });
218629
218705
  }
218630
218706
  function extractDescriptionFromFrontMatter(content) {
@@ -227825,6 +227901,7 @@ exports.TCB_QUERY_REGIONS = exports.SITE_IDS = exports.SITE_REGION_MAP = void 0;
227825
227901
  exports.isSiteId = isSiteId;
227826
227902
  exports.normalizeSite = normalizeSite;
227827
227903
  exports.getSite = getSite;
227904
+ exports.resolveApiKeyExchangeRegion = resolveApiKeyExchangeRegion;
227828
227905
  exports.resolveSite = resolveSite;
227829
227906
  exports.resolveSiteAndRegion = resolveSiteAndRegion;
227830
227907
  const project_config_js_1 = __webpack_require__(68445);
@@ -227834,6 +227911,7 @@ exports.SITE_REGION_MAP = {
227834
227911
  label: "国内站",
227835
227912
  authHost: "tcb.cloud.tencent.com",
227836
227913
  consoleHost: "tcb.cloud.tencent.com",
227914
+ oauthEndpoint: "https://tcb-api.cloud.tencent.com/qcloud-tcb/v1/oauth",
227837
227915
  defaultRegion: "ap-shanghai",
227838
227916
  regions: ["ap-shanghai", "ap-guangzhou", "ap-singapore"],
227839
227917
  capabilities: { noSql: true },
@@ -227843,6 +227921,9 @@ exports.SITE_REGION_MAP = {
227843
227921
  label: "国际站",
227844
227922
  authHost: "tcb.tencentcloud.com",
227845
227923
  consoleHost: "tcb.tencentcloud.com",
227924
+ // 2026-09-01 实测:device/code + token 端点可用,且 device-code 注册表与国内站隔离
227925
+ // (国内站有效期内的 code 在该端点轮询返回 expired_token)
227926
+ oauthEndpoint: "https://tcb-api.tencentcloud.com/qcloud-tcb/v1/oauth",
227846
227927
  defaultRegion: "ap-singapore",
227847
227928
  regions: ["ap-singapore"],
227848
227929
  capabilities: { noSql: false },
@@ -227897,8 +227978,24 @@ function getSite(region, explicitSite) {
227897
227978
  return "domestic";
227898
227979
  }
227899
227980
  /**
227900
- * 认证/路由场景下解析站点:歧义(如 ap-singapore 未配 site)时默认 intl,保持既有国际站行为。
227981
+ * API Key 换取网关(POST /capi/credential 的 host)地域选型。
227982
+ *
227983
+ * 2026-09-01 同一把国内站 key 三地域网关实测:
227984
+ * - ap-shanghai / ap-guangzhou host 均换取成功(国内站集群共享 key 注册表,
227985
+ * URL 中的 region 段在国内站内部等价,互换可用)
227986
+ * - ap-singapore host 拒绝(SIGN_PARAM_INVALID:sg 网关为国际站独立部署,
227987
+ * key 注册表与国内站隔离)
227988
+ *
227989
+ * 因此换取 host 按**站点**选择,而非按环境所属地域:
227990
+ * - 显式 intl 站点(如 TCB_SITE=intl)→ 返回 intl 地域(ap-singapore)
227991
+ * - domestic / 歧义(如仅设 TCB_REGION=ap-singapore)/ 未配置 → 返回 undefined,
227992
+ * toolbox 回落默认 ap-shanghai;国内站多地域环境(ap-guangzhou / ap-singapore)
227993
+ * 经默认域名均可换取,盲目传环境地域反而会把国内站 key 打到 sg 网关导致换取失败
227901
227994
  */
227995
+ function resolveApiKeyExchangeRegion(opts = {}) {
227996
+ const resolved = resolveSiteAndRegion(opts);
227997
+ return resolved.site === "intl" && !resolved.ambiguous ? resolved.region : undefined;
227998
+ }
227902
227999
  function resolveSite(region, explicitSite) {
227903
228000
  const site = getSite(region, explicitSite);
227904
228001
  return site === "ambiguous" ? "intl" : site;
@@ -233414,7 +233511,7 @@ ${envIdSection}
233414
233511
  ## 环境信息
233415
233512
  - 操作系统: ${os_1.default.type()} ${os_1.default.release()}
233416
233513
  - Node.js版本: ${process.version}
233417
- - MCP 版本:${process.env.npm_package_version || ( true ? "2.32.4" : 0)}
233514
+ - MCP 版本:${process.env.npm_package_version || ( true ? "2.32.5" : 0)}
233418
233515
  - 系统架构: ${os_1.default.arch()}
233419
233516
  - 时间: ${new Date().toISOString()}
233420
233517
  - 请求ID: ${requestId}
@@ -233499,7 +233596,7 @@ function createWrappedHandler(name, handler, server) {
233499
233596
  requestId: (typeof error === 'object' && error && 'requestId' in error) ? error.requestId : '',
233500
233597
  ide: server.ide || process.env.INTEGRATION_IDE || ''
233501
233598
  });
233502
- const mcpVersion = true ? "2.32.4" : 0;
233599
+ const mcpVersion = true ? "2.32.5" : 0;
233503
233600
  const requestIdSuffix = requestId ? `\n🆔 RequestId: ${requestId}` : '';
233504
233601
  const enhancedErrorMessage = `${errorMessage}${requestIdSuffix}\n\n📦 CloudBase MCP v${mcpVersion}\n🔗 遇到问题?请复制以下链接到浏览器打开\n即可自动携带错误详情快速创建 GitHub Issue:\n${issueLink}`;
233505
233602
  // 创建新的错误对象,保持原有的错误类型但更新消息
@@ -252888,7 +252985,7 @@ function registerSetupTools(server) {
252888
252985
  server.registerTool("downloadTemplate", {
252889
252986
  title: "下载项目模板",
252890
252987
  description: `自动下载并部署CloudBase项目模板。
252891
- **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.32.4" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
252988
+ **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.32.5" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
252892
252989
  inputSchema: {
252893
252990
  template: zod_1.z
252894
252991
  .enum(["react", "vue", "miniprogram", "uniapp", "rules"])
@@ -255298,7 +255395,13 @@ async function peekLoginState(options) {
255298
255395
  try {
255299
255396
  // 优先使用 IDE 注入的工作目录,其次 process.cwd()
255300
255397
  const projectCwd = process.env.WORKSPACE_FOLDER_PATHS || process.cwd();
255301
- const credential = await auth.loginByApiKey(envVarLoginState.apiKey, envVarLoginState.envId, { cwd: projectCwd });
255398
+ // 换取网关按站点选型:显式 intl → ap-singapore;domestic/歧义 → toolbox 默认
255399
+ // ap-shanghai(国内站多地域环境均经其全局路由,详见 resolveApiKeyExchangeRegion)
255400
+ const exchangeRegion = (0, site_map_js_1.resolveApiKeyExchangeRegion)({
255401
+ site: options?.site,
255402
+ region: options?.region,
255403
+ });
255404
+ const credential = await auth.loginByApiKey(envVarLoginState.apiKey, envVarLoginState.envId, { cwd: projectCwd, ...(exchangeRegion ? { region: exchangeRegion } : {}) });
255302
255405
  return credential;
255303
255406
  }
255304
255407
  catch (e) {
@@ -255393,6 +255496,18 @@ async function ensureLogin(options) {
255393
255496
  if (resolvedAuthOptions.oauthEndpoint) {
255394
255497
  loginOptions.getOAuthEndpoint = () => resolvedAuthOptions.oauthEndpoint;
255395
255498
  }
255499
+ else if (resolvedSite === "intl") {
255500
+ // 国际站 OAuth 后端独立部署(2026-09-01 实测 device/code+token 可用,注册表与国内站隔离);
255501
+ // 不覆写时 toolbox 默认打国内站端点,国际站账号无法完成授权
255502
+ loginOptions.getOAuthEndpoint = () => site_map_js_1.SITE_REGION_MAP.intl.oauthEndpoint;
255503
+ }
255504
+ if (resolvedSite === "intl") {
255505
+ // device 模式的 verification_uri 标准模式下由客户端拼接,指向国内站授权页;
255506
+ // 与 web 模式同款 host 改写,把授权页切到国际站
255507
+ loginOptions.getAuthUrl = (url) => url
255508
+ .replace(`${site_map_js_1.SITE_REGION_MAP.domestic.authHost}/dev`, `${site_map_js_1.SITE_REGION_MAP.intl.authHost}/dev`)
255509
+ .replace(site_map_js_1.SITE_REGION_MAP.domestic.authHost, site_map_js_1.SITE_REGION_MAP.intl.authHost);
255510
+ }
255396
255511
  if (resolvedAuthOptions.oauthCustom) {
255397
255512
  loginOptions.custom = true;
255398
255513
  }