@cloudbase/cloudbase-mcp 2.15.2-beta.1 → 2.15.2-beta.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.cjs CHANGED
@@ -1793,6 +1793,8 @@ function simplifyEnvList(envList) {
1793
1793
  simplified.EnvType = env.EnvType;
1794
1794
  if (env.Region !== undefined)
1795
1795
  simplified.Region = env.Region;
1796
+ if (env.PackageId !== undefined)
1797
+ simplified.PackageId = env.PackageId;
1796
1798
  if (env.PackageName !== undefined)
1797
1799
  simplified.PackageName = env.PackageName;
1798
1800
  if (env.IsDefault !== undefined)
@@ -1807,6 +1809,7 @@ const DEFAULT_ENV_FIELDS = [
1807
1809
  "Status",
1808
1810
  "EnvType",
1809
1811
  "Region",
1812
+ "PackageId",
1810
1813
  "PackageName",
1811
1814
  "IsDefault",
1812
1815
  ];
@@ -1822,10 +1825,14 @@ function selectEnvFields(env, fields) {
1822
1825
  }
1823
1826
  function filterEnvList(envList, filters) {
1824
1827
  const alias = filters.alias?.trim().toLowerCase();
1828
+ const aliasExact = filters.aliasExact === true;
1825
1829
  const envId = filters.envId?.trim().toLowerCase();
1826
1830
  return envList.filter((env) => {
1831
+ const normalizedAlias = String(env.Alias ?? "").toLowerCase();
1827
1832
  const matchesAlias = alias
1828
- ? String(env.Alias ?? "").toLowerCase().includes(alias)
1833
+ ? aliasExact
1834
+ ? normalizedAlias === alias
1835
+ : normalizedAlias.includes(alias)
1829
1836
  : true;
1830
1837
  const matchesEnvId = envId
1831
1838
  ? String(env.EnvId ?? "").toLowerCase() === envId
@@ -1929,9 +1936,17 @@ function buildEnvQueryListResult(params) {
1929
1936
  : envList;
1930
1937
  const filteredList = filterEnvList(baseList, {
1931
1938
  alias: params.filters.alias,
1939
+ aliasExact: params.filters.aliasExact,
1932
1940
  envId: params.filters.envId,
1933
1941
  });
1934
1942
  const paginated = paginateEnvList(filteredList, params.filters.offset, params.filters.limit);
1943
+ const exactEnvIdSummaryHint = params.filters.envId
1944
+ ? {
1945
+ tool: "envQuery",
1946
+ action: "info",
1947
+ reason: "action=list with envId only returns a concise summary. Use action=info to fetch detailed environment information such as full resource metadata and additional environment details.",
1948
+ }
1949
+ : undefined;
1935
1950
  return {
1936
1951
  EnvList: paginated.items.map((env) => selectEnvFields(env, params.filters.fields)),
1937
1952
  TotalCount: paginated.total,
@@ -1940,12 +1955,58 @@ function buildEnvQueryListResult(params) {
1940
1955
  HasMore: paginated.offset + paginated.items.length < paginated.total,
1941
1956
  AppliedFilters: {
1942
1957
  alias: params.filters.alias ?? null,
1958
+ aliasExact: params.filters.aliasExact ?? null,
1943
1959
  envId: params.filters.envId ?? null,
1944
1960
  fields: params.filters.fields ?? [...DEFAULT_ENV_FIELDS],
1945
1961
  currentEnvOnly: shouldRestrictToCurrentEnv,
1946
1962
  },
1963
+ ...(exactEnvIdSummaryHint
1964
+ ? {
1965
+ RecommendedNextAction: exactEnvIdSummaryHint,
1966
+ }
1967
+ : {}),
1947
1968
  };
1948
1969
  }
1970
+ async function enrichEnvInfoWithBilling(params) {
1971
+ const targetEnvId = params.envId ||
1972
+ params.result?.EnvInfo?.EnvId;
1973
+ if (!targetEnvId || !params.result?.EnvInfo) {
1974
+ return params.result;
1975
+ }
1976
+ try {
1977
+ const billingResult = await params.manager.commonService("tcb", "2018-06-08").call({
1978
+ Action: "DescribeBillingInfo",
1979
+ Param: {
1980
+ EnvId: targetEnvId,
1981
+ },
1982
+ });
1983
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(params.logger, billingResult);
1984
+ const billingList = billingResult?.EnvBillingInfoList ||
1985
+ billingResult?.Response?.EnvBillingInfoList ||
1986
+ billingResult?.Data?.EnvBillingInfoList ||
1987
+ [];
1988
+ const matchedBillingInfo = Array.isArray(billingList)
1989
+ ? billingList.find((item) => item?.EnvId === targetEnvId) ?? billingList[0]
1990
+ : undefined;
1991
+ if (!matchedBillingInfo) {
1992
+ return params.result;
1993
+ }
1994
+ return {
1995
+ ...params.result,
1996
+ EnvInfo: {
1997
+ ...params.result.EnvInfo,
1998
+ BillingInfo: matchedBillingInfo,
1999
+ },
2000
+ };
2001
+ }
2002
+ catch (billingError) {
2003
+ (0, logger_js_1.debug)("DescribeBillingInfo enrichment failed, continuing without billing info", {
2004
+ error: billingError,
2005
+ envId: targetEnvId,
2006
+ });
2007
+ return params.result;
2008
+ }
2009
+ }
1949
2010
  async function getGuidePrompt(server) {
1950
2011
  if (getCurrentIde(server) === "CodeBuddy" ||
1951
2012
  process.env.CLOUDBASE_GUIDE_PROMPT === "false") {
@@ -1963,6 +2024,16 @@ function registerEnvTools(server) {
1963
2024
  // 获取 cloudBaseOptions,如果没有则为 undefined
1964
2025
  const cloudBaseOptions = server.cloudBaseOptions;
1965
2026
  const getManager = () => (0, cloudbase_manager_js_1.getCloudBaseManager)({ cloudBaseOptions, mcpServer: server });
2027
+ const getManagerForEnvQuery = (targetEnvId, requireEnvId = true) => (0, cloudbase_manager_js_1.getCloudBaseManager)({
2028
+ cloudBaseOptions: targetEnvId && targetEnvId !== cloudBaseOptions?.envId
2029
+ ? {
2030
+ ...cloudBaseOptions,
2031
+ envId: targetEnvId,
2032
+ }
2033
+ : cloudBaseOptions,
2034
+ requireEnvId,
2035
+ mcpServer: server,
2036
+ });
1966
2037
  const hasEnvId = typeof cloudBaseOptions?.envId === 'string' && cloudBaseOptions?.envId.length > 0;
1967
2038
  const supportedAuthActions = getSupportedAuthActions(server);
1968
2039
  const authActionEnum = [...supportedAuthActions];
@@ -2328,26 +2399,27 @@ function registerEnvTools(server) {
2328
2399
  // envQuery - 环境查询(合并 listEnvs + getEnvInfo + getEnvAuthDomains + getWebsiteConfig)
2329
2400
  server.registerTool?.("envQuery", {
2330
2401
  title: "环境查询",
2331
- description: "查询云开发环境相关信息,支持查询环境列表、当前环境信息、安全域名和静态网站托管配置。(原工具名:listEnvs/getEnvInfo/getEnvAuthDomains/getWebsiteConfig,为兼容旧AI规则可继续使用这些名称)当 action=list 时,标准返回字段为 EnvId、Alias、Status、EnvType、Region、PackageName、IsDefault,并支持通过 fields 白名单裁剪这些字段。当前 MCP 输出不支持套餐/计划到期时间(expiry / expire time)查询。",
2402
+ description: "查询云开发环境相关信息,支持查询环境列表、当前环境信息、安全域名和静态网站托管配置。(原工具名:listEnvs/getEnvInfo/getEnvAuthDomains/getWebsiteConfig,为兼容旧AI规则可继续使用这些名称)当 action=list 时,标准返回字段为 EnvId、Alias、Status、EnvType、Region、PackageId、PackageName、IsDefault,并支持通过 fields 白名单裁剪这些字段;aliasExact=true 时会按别名精确筛选,避免把前缀相近的环境误当作候选;即使传入 envId,action=list 也只返回摘要,不会返回完整资源明细或 expiry。如需查询某个已知环境的详细信息,请使用 action=info。action=info 会在可用时补充 BillingInfo(如 ExpireTime、PayMode、IsAutoRenew 等计费字段)。",
2332
2403
  inputSchema: {
2333
2404
  action: zod_1.z
2334
2405
  .enum(["list", "info", "domains", "hosting"])
2335
- .describe("查询类型:list=环境列表(标准字段:EnvId、Alias、Status、EnvType、Region、PackageName、IsDefault;不支持 expiry),info=当前环境信息,domains=安全域名列表,hosting=静态网站托管配置"),
2406
+ .describe("查询类型:list=环境列表/摘要筛选(即使传 envId 也只返回 EnvId、Alias、Status、EnvType、Region、PackageId、PackageName、IsDefault,不支持 expiry),info=当前环境详细信息(详情中可查看更完整资源字段),domains=安全域名列表,hosting=静态网站托管配置"),
2336
2407
  alias: zod_1.z.string().optional().describe("按环境别名筛选。action=list 时可选"),
2337
- envId: zod_1.z.string().optional().describe("按环境 ID 精确筛选。action=list 时可选"),
2408
+ aliasExact: zod_1.z.boolean().optional().describe("按环境别名精确筛选。action=list 时可选;与 alias 配合使用"),
2409
+ envId: zod_1.z.string().optional().describe("按环境 ID 精确筛选。action=list 时可选;注意 list + envId 仍只返回摘要,如需该环境详情请改用 action=info"),
2338
2410
  limit: zod_1.z.number().int().positive().optional().describe("返回数量上限。action=list 时可选"),
2339
2411
  offset: zod_1.z.number().int().min(0).optional().describe("分页偏移。action=list 时可选"),
2340
2412
  fields: zod_1.z
2341
2413
  .array(zod_1.z.enum(DEFAULT_ENV_FIELDS))
2342
2414
  .optional()
2343
- .describe("返回字段白名单。仅支持 EnvId、Alias、Status、EnvType、Region、PackageName、IsDefault。action=list 时可选"),
2415
+ .describe("返回字段白名单。仅支持 EnvId、Alias、Status、EnvType、Region、PackageId、PackageName、IsDefault。action=list 时可选"),
2344
2416
  },
2345
2417
  annotations: {
2346
2418
  readOnlyHint: true,
2347
2419
  openWorldHint: true,
2348
2420
  category: "env",
2349
2421
  },
2350
- }, async ({ action, alias, envId, limit, offset, fields, }) => {
2422
+ }, async ({ action, alias, aliasExact, envId, limit, offset, fields, }) => {
2351
2423
  try {
2352
2424
  let result;
2353
2425
  switch (action) {
@@ -2420,6 +2492,7 @@ function registerEnvTools(server) {
2420
2492
  hasEnvId,
2421
2493
  filters: {
2422
2494
  alias,
2495
+ aliasExact,
2423
2496
  envId,
2424
2497
  limit,
2425
2498
  offset,
@@ -2428,20 +2501,44 @@ function registerEnvTools(server) {
2428
2501
  });
2429
2502
  break;
2430
2503
  case "info":
2431
- const cloudbaseInfo = await getManager();
2504
+ const cloudbaseInfo = await getManagerForEnvQuery(envId);
2432
2505
  result = await cloudbaseInfo.env.getEnvInfo();
2433
2506
  (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
2507
+ result = await enrichEnvInfoWithBilling({
2508
+ manager: cloudbaseInfo,
2509
+ result,
2510
+ envId,
2511
+ logger: server.logger,
2512
+ });
2434
2513
  break;
2435
2514
  case "domains":
2436
2515
  const cloudbaseDomains = await getManager();
2437
2516
  result = await cloudbaseDomains.env.getEnvAuthDomains();
2438
2517
  (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
2439
2518
  break;
2440
- case "hosting":
2519
+ case "hosting": {
2441
2520
  const cloudbaseHosting = await getManager();
2442
- result = await cloudbaseHosting.hosting.getWebsiteConfig();
2443
- (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
2521
+ const websiteConfig = await cloudbaseHosting.hosting.getWebsiteConfig();
2522
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, websiteConfig);
2523
+ const hostingResult = {
2524
+ ...websiteConfig,
2525
+ CdnDomain: websiteConfig.CdnDomain ?? null,
2526
+ Bucket: websiteConfig.Bucket ?? null,
2527
+ };
2528
+ try {
2529
+ const envInfo = await cloudbaseHosting.env.getEnvInfo();
2530
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, envInfo);
2531
+ hostingResult.CdnDomain = envInfo.EnvInfo?.StaticStorages?.[0]?.StaticDomain ?? hostingResult.CdnDomain;
2532
+ hostingResult.Bucket = envInfo.EnvInfo?.StaticStorages?.[0]?.Bucket ?? hostingResult.Bucket;
2533
+ }
2534
+ catch (hostingInfoError) {
2535
+ (0, logger_js_1.debug)("Failed to enrich hosting envQuery result with env info", {
2536
+ error: hostingInfoError,
2537
+ });
2538
+ }
2539
+ result = hostingResult;
2444
2540
  break;
2541
+ }
2445
2542
  default:
2446
2543
  throw new Error(`不支持的查询类型: ${action}`);
2447
2544
  }
@@ -24517,9 +24614,9 @@ async function getCloudBaseManager(options = {}) {
24517
24614
  }
24518
24615
  try {
24519
24616
  // Get region from environment variable for auth URL
24520
- const region = cloudBaseOptions?.region ?? process.env.TCB_REGION;
24617
+ const fallbackRegion = cloudBaseOptions?.region ?? process.env.TCB_REGION;
24521
24618
  const loginState = authStrategy === 'ensure'
24522
- ? await (0, auth_js_1.getLoginState)({ region })
24619
+ ? await (0, auth_js_1.getLoginState)({ region: fallbackRegion })
24523
24620
  : await (0, auth_js_1.peekLoginState)();
24524
24621
  if (!loginState) {
24525
24622
  const authState = await (0, auth_js_1.getAuthProgressState)();
@@ -24567,13 +24664,29 @@ async function getCloudBaseManager(options = {}) {
24567
24664
  }
24568
24665
  // envId priority: envManager.cachedEnvId > envManager.getEnvId() > loginState.envId > undefined
24569
24666
  // Note: envManager.cachedEnvId has highest priority as it reflects user's latest environment switch
24570
- // Region priority: process.env.TCB_REGION > undefined (use SDK default)
24571
- // At this point, cloudBaseOptions is undefined (checked above), so only use env var if present
24572
- // Reuse region variable declared above (line 259) for CloudBase initialization
24667
+ // Region priority: envCandidates[].region (actual env region) > process.env.TCB_REGION > undefined
24668
+ // Resolving the environment's own region avoids INVALID_REGION errors when TCB_REGION
24669
+ // is set to a different region than the target environment.
24670
+ const resolvedEnvId = finalEnvId || loginEnvId;
24671
+ let region = fallbackRegion;
24672
+ if (resolvedEnvId && !cloudBaseOptions?.region) {
24673
+ try {
24674
+ const envCandidates = await listAvailableEnvCandidates({ loginState });
24675
+ const matchedEnv = envCandidates.find(c => c.envId === resolvedEnvId);
24676
+ if (matchedEnv?.region) {
24677
+ region = matchedEnv.region;
24678
+ (0, logger_js_1.debug)('使用环境实际 region:', { envId: resolvedEnvId, region });
24679
+ }
24680
+ }
24681
+ catch {
24682
+ // If env listing fails, fall back to TCB_REGION / undefined
24683
+ (0, logger_js_1.debug)('无法获取环境列表,使用 fallback region');
24684
+ }
24685
+ }
24573
24686
  const manager = new manager_node_1.default({
24574
24687
  secretId,
24575
24688
  secretKey,
24576
- envId: finalEnvId || loginEnvId,
24689
+ envId: resolvedEnvId,
24577
24690
  token,
24578
24691
  proxy: process.env.http_proxy,
24579
24692
  region,
@@ -36256,11 +36369,68 @@ function wrap (fn) {
36256
36369
 
36257
36370
  Object.defineProperty(exports, "__esModule", ({ value: true }));
36258
36371
  exports.WRITE_SECURITY_RULE = exports.READ_SECURITY_RULE = void 0;
36372
+ exports.normalizeCustomSecurityRule = normalizeCustomSecurityRule;
36373
+ exports.buildSecurityRuleErrorMessage = buildSecurityRuleErrorMessage;
36259
36374
  exports.registerSecurityRuleTools = registerSecurityRuleTools;
36260
36375
  const zod_1 = __webpack_require__(21614);
36261
36376
  const cloudbase_manager_js_1 = __webpack_require__(3431);
36262
36377
  exports.READ_SECURITY_RULE = "readSecurityRule";
36263
36378
  exports.WRITE_SECURITY_RULE = "writeSecurityRule";
36379
+ const FUNCTION_CUSTOM_RULE_EXAMPLE = JSON.stringify({
36380
+ "*": {
36381
+ invoke: true,
36382
+ },
36383
+ }, null, 2);
36384
+ function isPlainObject(value) {
36385
+ return (typeof value === "object" &&
36386
+ value !== null &&
36387
+ !Array.isArray(value));
36388
+ }
36389
+ function formatSecurityRuleInputHint(resourceType) {
36390
+ if (resourceType === "function") {
36391
+ return `函数自定义安全规则应传 JSON 对象或 JSON 字符串,例如 ${FUNCTION_CUSTOM_RULE_EXAMPLE}。`;
36392
+ }
36393
+ if (resourceType === "noSqlDatabase") {
36394
+ return "NoSQL 自定义安全规则应传 JSON 对象或 JSON 字符串,例如 {\"read\":\"true\",\"write\":\"true\"}。";
36395
+ }
36396
+ return "自定义安全规则应传 JSON 对象或 JSON 字符串,并与 readSecurityRule 返回的规则结构保持一致。";
36397
+ }
36398
+ function normalizeCustomSecurityRule(resourceType, rule) {
36399
+ if (rule === undefined) {
36400
+ throw new Error(`resourceType=${resourceType} 且 aclTag=CUSTOM 时必须提供 rule 字段`);
36401
+ }
36402
+ if (typeof rule === "string") {
36403
+ try {
36404
+ const parsed = JSON.parse(rule);
36405
+ if (!isPlainObject(parsed)) {
36406
+ throw new Error(`rule 必须是 JSON 对象,不支持 ${Array.isArray(parsed) ? "数组" : typeof parsed}。`);
36407
+ }
36408
+ return JSON.stringify(parsed);
36409
+ }
36410
+ catch (error) {
36411
+ const baseMessage = error instanceof Error ? error.message : "rule 不是合法的 JSON 字符串";
36412
+ throw new Error(`${baseMessage} ${formatSecurityRuleInputHint(resourceType)}`);
36413
+ }
36414
+ }
36415
+ if (!isPlainObject(rule)) {
36416
+ throw new Error(`rule 必须是 JSON 对象或 JSON 字符串。${formatSecurityRuleInputHint(resourceType)}`);
36417
+ }
36418
+ return JSON.stringify(rule);
36419
+ }
36420
+ function buildSecurityRuleErrorMessage(operation, resourceType, aclTag, error) {
36421
+ const baseMessage = error instanceof Error ? error.message : String(error);
36422
+ const suggestions = [];
36423
+ if (operation === "writeSecurityRule" && aclTag === "CUSTOM") {
36424
+ suggestions.push(formatSecurityRuleInputHint(resourceType));
36425
+ }
36426
+ if (/INVALID_VALUE|ModifySecurityRule|错误的值|JSON/i.test(baseMessage)) {
36427
+ suggestions.push("请先把 CUSTOM 规则整理成 JSON 对象,再传给 writeSecurityRule。");
36428
+ }
36429
+ if (suggestions.length === 0) {
36430
+ suggestions.push("请检查 resourceType、aclTag 和 rule 是否与官方安全规则格式一致后重试。");
36431
+ }
36432
+ return `[${operation}] 调用失败: ${baseMessage}\n建议:${suggestions.join(" ")}`;
36433
+ }
36264
36434
  /**
36265
36435
  * 注册安全规则相关 Tool
36266
36436
  * @param server MCP Server 实例
@@ -36271,7 +36441,7 @@ function registerSecurityRuleTools(server) {
36271
36441
  // 读取安全规则 Tool
36272
36442
  server.registerTool?.(exports.READ_SECURITY_RULE, {
36273
36443
  title: "读取安全规则",
36274
- description: `读取指定资源(noSQL 数据库、SQL 数据库、云函数、存储桶)的安全规则和权限类别。`,
36444
+ description: `读取指定资源(noSQL 数据库、SQL 数据库、云函数、存储桶)的安全规则和权限类别。\n\n安全规则文档:\n- 云函数安全规则:https://docs.cloudbase.net/cloud-function/security-rules\n- 存储安全规则:https://docs.cloudbase.net/storage/security-rules\n- 文档型数据库安全规则:https://docs.cloudbase.net/database/security-rules`,
36275
36445
  inputSchema: {
36276
36446
  resourceType: zod_1.z
36277
36447
  .enum(["noSqlDatabase", "sqlDatabase", "function", "storage"])
@@ -36357,7 +36527,7 @@ function registerSecurityRuleTools(server) {
36357
36527
  // 写入安全规则 Tool
36358
36528
  server.registerTool?.(exports.WRITE_SECURITY_RULE, {
36359
36529
  title: "写入安全规则",
36360
- description: `设置指定资源(数据库集合、云函数、存储桶)的安全规则。`,
36530
+ description: `设置指定资源(数据库集合、云函数、存储桶)的安全规则。\n\n安全规则文档:\n- 云函数安全规则:https://docs.cloudbase.net/cloud-function/security-rules\n- 存储安全规则:https://docs.cloudbase.net/storage/security-rules\n- 数据库安全规则:https://docs.cloudbase.net/database/security-rules\n\n云函数安全规则仅支持 aclTag="CUSTOM",rule 字段为 JSON 字符串。例如放开所有访问可设置 rule="true"。`,
36361
36531
  inputSchema: {
36362
36532
  resourceType: zod_1.z
36363
36533
  .enum(["sqlDatabase", "noSqlDatabase", "function", "storage"])
@@ -36369,9 +36539,9 @@ function registerSecurityRuleTools(server) {
36369
36539
  .enum(["READONLY", "PRIVATE", "ADMINWRITE", "ADMINONLY", "CUSTOM"])
36370
36540
  .describe("权限类别"),
36371
36541
  rule: zod_1.z
36372
- .string()
36542
+ .union([zod_1.z.string(), zod_1.z.record(zod_1.z.any())])
36373
36543
  .optional()
36374
- .describe("自定义安全规则内容,仅当 aclTag 为 CUSTOM 时必填"),
36544
+ .describe(`自定义安全规则内容,仅当 aclTag 为 CUSTOM 时必填。可以直接传 JSON 对象,或者传可解析为 JSON 对象的字符串。函数示例:${FUNCTION_CUSTOM_RULE_EXAMPLE}`),
36375
36545
  },
36376
36546
  annotations: {
36377
36547
  readOnlyHint: false,
@@ -36379,138 +36549,140 @@ function registerSecurityRuleTools(server) {
36379
36549
  category: "security-rule",
36380
36550
  },
36381
36551
  }, async ({ resourceType, resourceId, aclTag, rule }) => {
36382
- const cloudbase = await getManager();
36383
- const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
36384
- let result;
36385
- if (resourceType === "noSqlDatabase") {
36386
- if (aclTag === "CUSTOM") {
36387
- if (!rule)
36388
- throw new Error("noSQL 数据库自定义安全规则(CUSTOM)必须提供 rule 字段");
36389
- result = await cloudbase.commonService().call({
36390
- Action: "ModifySafeRule",
36391
- Param: {
36392
- CollectionName: resourceId,
36393
- EnvId: envId,
36394
- AclTag: aclTag,
36395
- Rule: rule,
36396
- },
36397
- });
36398
- (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
36552
+ try {
36553
+ const cloudbase = await getManager();
36554
+ const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
36555
+ let result;
36556
+ if (resourceType === "noSqlDatabase") {
36557
+ if (aclTag === "CUSTOM") {
36558
+ const normalizedRule = normalizeCustomSecurityRule(resourceType, rule);
36559
+ result = await cloudbase.commonService().call({
36560
+ Action: "ModifySafeRule",
36561
+ Param: {
36562
+ CollectionName: resourceId,
36563
+ EnvId: envId,
36564
+ AclTag: aclTag,
36565
+ Rule: normalizedRule,
36566
+ },
36567
+ });
36568
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
36569
+ }
36570
+ else {
36571
+ result = await cloudbase.commonService().call({
36572
+ Action: "ModifyDatabaseACL",
36573
+ Param: {
36574
+ CollectionName: resourceId,
36575
+ EnvId: envId,
36576
+ AclTag: aclTag,
36577
+ },
36578
+ });
36579
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
36580
+ }
36399
36581
  }
36400
- else {
36582
+ else if (resourceType === "function") {
36583
+ if (aclTag !== "CUSTOM")
36584
+ throw new Error("云函数安全规则仅支持 CUSTOM 权限类别");
36585
+ const normalizedRule = normalizeCustomSecurityRule(resourceType, rule);
36401
36586
  result = await cloudbase.commonService().call({
36402
- Action: "ModifyDatabaseACL",
36587
+ Action: "ModifySecurityRule",
36403
36588
  Param: {
36404
- CollectionName: resourceId,
36405
- EnvId: envId,
36406
36589
  AclTag: aclTag,
36407
- },
36408
- });
36409
- (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
36410
- }
36411
- }
36412
- else if (resourceType === "function") {
36413
- if (aclTag !== "CUSTOM")
36414
- throw new Error("云函数安全规则仅支持 CUSTOM 权限类别");
36415
- if (!rule)
36416
- throw new Error("云函数自定义安全规则(CUSTOM)必须提供 rule 字段");
36417
- result = await cloudbase.commonService().call({
36418
- Action: "ModifySecurityRule",
36419
- Param: {
36420
- AclTag: aclTag,
36421
- EnvId: envId,
36422
- ResourceType: "FUNCTION",
36423
- Rule: rule,
36424
- },
36425
- });
36426
- (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
36427
- }
36428
- else if (resourceType === "storage") {
36429
- if (aclTag === "CUSTOM") {
36430
- if (!rule)
36431
- throw new Error("存储自定义安全规则(CUSTOM)必须提供 rule 字段");
36432
- result = await cloudbase.commonService().call({
36433
- Action: "ModifyStorageSafeRule",
36434
- Param: {
36435
- Bucket: resourceId,
36436
36590
  EnvId: envId,
36437
- AclTag: aclTag,
36438
- Rule: rule,
36591
+ ResourceType: "FUNCTION",
36592
+ Rule: normalizedRule,
36439
36593
  },
36440
36594
  });
36441
36595
  (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
36442
36596
  }
36443
- else {
36444
- result = await cloudbase.commonService().call({
36445
- Action: "ModifyStorageSafeRule",
36597
+ else if (resourceType === "storage") {
36598
+ if (aclTag === "CUSTOM") {
36599
+ const normalizedRule = normalizeCustomSecurityRule(resourceType, rule);
36600
+ result = await cloudbase.commonService().call({
36601
+ Action: "ModifyStorageSafeRule",
36602
+ Param: {
36603
+ Bucket: resourceId,
36604
+ EnvId: envId,
36605
+ AclTag: aclTag,
36606
+ Rule: normalizedRule,
36607
+ },
36608
+ });
36609
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
36610
+ }
36611
+ else {
36612
+ result = await cloudbase.commonService().call({
36613
+ Action: "ModifyStorageSafeRule",
36614
+ Param: {
36615
+ Bucket: resourceId,
36616
+ EnvId: envId,
36617
+ AclTag: aclTag,
36618
+ },
36619
+ });
36620
+ (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
36621
+ }
36622
+ }
36623
+ else if (resourceType === "sqlDatabase") {
36624
+ if (aclTag === "CUSTOM") {
36625
+ throw new Error("SQL 数据库不支持自定义安全规则(CUSTOM)");
36626
+ }
36627
+ const schema = envId;
36628
+ const tableName = resourceId;
36629
+ const instanceId = "default";
36630
+ const resource = `${instanceId}#${schema}#${tableName}`;
36631
+ const resourceType = "table";
36632
+ const effect = "allow";
36633
+ const policyList = [
36634
+ "allUser",
36635
+ "anonymousUser",
36636
+ "externalUser",
36637
+ "internalUser",
36638
+ ].map((roleIdentity) => ({
36639
+ RoleIdentity: roleIdentity,
36640
+ ResourceType: resourceType,
36641
+ ResourceId: resource,
36642
+ RowPermission: [],
36643
+ Effect: effect,
36644
+ }));
36645
+ policyList[0].RowPermission = getRowPermission(aclTag);
36646
+ result = await cloudbase.commonService("lowcode").call({
36647
+ Action: "BatchCreateResourcePolicy",
36446
36648
  Param: {
36447
- Bucket: resourceId,
36448
36649
  EnvId: envId,
36449
- AclTag: aclTag,
36650
+ PolicyList: policyList,
36450
36651
  },
36451
36652
  });
36452
36653
  (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
36654
+ function getRowPermission(policy) {
36655
+ return {
36656
+ READONLY: [
36657
+ { Key: "all", Value: "r" },
36658
+ { Key: "me", Value: "rw" },
36659
+ ],
36660
+ PRIVATE: [{ Key: "me", Value: "rw" }],
36661
+ ADMINWRITE: [{ Key: "all", Value: "r" }],
36662
+ ADMINONLY: [],
36663
+ }[policy];
36664
+ }
36453
36665
  }
36454
- }
36455
- else if (resourceType === "sqlDatabase") {
36456
- if (aclTag === "CUSTOM") {
36457
- throw new Error("SQL 数据库不支持自定义安全规则(CUSTOM)");
36458
- }
36459
- const schema = envId;
36460
- const tableName = resourceId;
36461
- const instanceId = "default";
36462
- const resource = `${instanceId}#${schema}#${tableName}`;
36463
- const resourceType = "table";
36464
- const effect = "allow";
36465
- const policyList = [
36466
- "allUser",
36467
- "anonymousUser",
36468
- "externalUser",
36469
- "internalUser",
36470
- ].map((roleIdentity) => ({
36471
- RoleIdentity: roleIdentity,
36472
- ResourceType: resourceType,
36473
- ResourceId: resource,
36474
- RowPermission: [],
36475
- Effect: effect,
36476
- }));
36477
- policyList[0].RowPermission = getRowPermission(aclTag);
36478
- result = await cloudbase.commonService("lowcode").call({
36479
- Action: "BatchCreateResourcePolicy",
36480
- Param: {
36481
- EnvId: envId,
36482
- PolicyList: policyList,
36483
- },
36484
- });
36485
- (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
36486
- function getRowPermission(policy) {
36487
- return {
36488
- READONLY: [
36489
- { Key: "all", Value: "r" },
36490
- { Key: "me", Value: "rw" },
36491
- ],
36492
- PRIVATE: [{ Key: "me", Value: "rw" }],
36493
- ADMINWRITE: [{ Key: "all", Value: "r" }],
36494
- ADMINONLY: [],
36495
- }[policy];
36666
+ else {
36667
+ throw new Error(`不支持的资源类型: ${resourceType}`);
36496
36668
  }
36669
+ return {
36670
+ content: [
36671
+ {
36672
+ type: "text",
36673
+ text: JSON.stringify({
36674
+ success: true,
36675
+ requestId: result.RequestId,
36676
+ raw: result,
36677
+ message: "安全规则写入成功",
36678
+ }, null, 2),
36679
+ },
36680
+ ],
36681
+ };
36497
36682
  }
36498
- else {
36499
- throw new Error(`不支持的资源类型: ${resourceType}`);
36683
+ catch (error) {
36684
+ throw new Error(buildSecurityRuleErrorMessage("writeSecurityRule", resourceType, aclTag, error));
36500
36685
  }
36501
- return {
36502
- content: [
36503
- {
36504
- type: "text",
36505
- text: JSON.stringify({
36506
- success: true,
36507
- requestId: result.RequestId,
36508
- raw: result,
36509
- message: "安全规则写入成功",
36510
- }, null, 2),
36511
- },
36512
- ],
36513
- };
36514
36686
  });
36515
36687
  }
36516
36688
 
@@ -41375,7 +41547,9 @@ function buildProvisionNextActions(status, request) {
41375
41547
  return [];
41376
41548
  }
41377
41549
  return [
41378
- buildNextAction(QUERY_SQL_DATABASE, "describeTaskStatus", "MySQL provisioning is still running. Check task status before initializing schema.", request ? { action: "describeTaskStatus", request } : { action: "describeTaskStatus" }),
41550
+ buildNextAction(QUERY_SQL_DATABASE, "describeCreateResult", "MySQL provisioning is still running. Check the create result again before initializing schema.", request
41551
+ ? { action: "describeCreateResult", request }
41552
+ : { action: "describeCreateResult" }),
41379
41553
  ];
41380
41554
  }
41381
41555
  function inferTaskKind(request) {
@@ -91737,11 +91911,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
91737
91911
  Object.defineProperty(exports, "__esModule", ({ value: true }));
91738
91912
  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;
91739
91913
  exports.formatRuntimeList = formatRuntimeList;
91914
+ exports.shouldInstallDependencyForFunction = shouldInstallDependencyForFunction;
91915
+ exports.buildFunctionOperationErrorMessage = buildFunctionOperationErrorMessage;
91740
91916
  exports.registerFunctionTools = registerFunctionTools;
91741
91917
  const zod_1 = __webpack_require__(21614);
91742
91918
  const cloudbase_manager_js_1 = __webpack_require__(3431);
91743
91919
  const cloud_mode_js_1 = __webpack_require__(89684);
91744
91920
  const logger_js_1 = __webpack_require__(13039);
91921
+ const fs_1 = __webpack_require__(29021);
91745
91922
  const path_1 = __importDefault(__webpack_require__(39902));
91746
91923
  exports.SUPPORTED_RUNTIMES = {
91747
91924
  nodejs: [
@@ -91930,6 +92107,12 @@ function getExpectedFunctionPath(functionRootPath, functionName) {
91930
92107
  return undefined;
91931
92108
  return path_1.default.join(path_1.default.normalize(functionRootPath), functionName);
91932
92109
  }
92110
+ function shouldInstallDependencyForFunction(functionType, hasPackageJson) {
92111
+ if (functionType === "HTTP") {
92112
+ return hasPackageJson;
92113
+ }
92114
+ return true;
92115
+ }
91933
92116
  function buildFunctionOperationErrorMessage(operation, functionName, functionRootPath, error) {
91934
92117
  const baseMessage = error instanceof Error ? error.message : String(error);
91935
92118
  const suggestions = [];
@@ -91941,6 +92124,13 @@ function buildFunctionOperationErrorMessage(operation, functionName, functionRoo
91941
92124
  suggestions.push(`当前工具会从 \`functionRootPath + 函数名\` 查找代码目录,期望目录是 \`${expectedFunctionPath}\`。`);
91942
92125
  suggestions.push("如果你传入的已经是函数目录本身,请改为传它的父目录。");
91943
92126
  }
92127
+ if (/paths\[0\].*undefined/i.test(baseMessage)) {
92128
+ suggestions.push("HTTP 函数创建时需要提供 functionRootPath(指向 cloudfunctions 父目录)或 zipFile,否则 SDK 无法定位函数目录。");
92129
+ }
92130
+ if (/依赖安装失败|package\.json/i.test(baseMessage)) {
92131
+ suggestions.push("如果 HTTP 函数只使用原生 Node.js API 且没有第三方依赖,可以保留函数目录中的 index.js 和 scf_bootstrap,工具会跳过依赖安装。");
92132
+ suggestions.push("如果你确实依赖 npm 包,请在函数目录下补充 package.json 后重试。");
92133
+ }
91944
92134
  if (suggestions.length === 0) {
91945
92135
  suggestions.push("请检查函数名、目录结构和环境中的函数状态后重试。");
91946
92136
  }
@@ -92316,8 +92506,21 @@ function registerFunctionTools(server) {
92316
92506
  throw new Error(`不支持的运行时环境: "${String(func.runtime)}"\n\n支持的运行时:\n${formatRuntimeList()}`);
92317
92507
  }
92318
92508
  }
92319
- func.installDependency = true;
92320
92509
  const processedRootPath = processFunctionRootPath(input.functionRootPath, functionName);
92510
+ const functionType = typeof func.type === "string" ? func.type : undefined;
92511
+ const expectedFunctionPath = getExpectedFunctionPath(processedRootPath, functionName);
92512
+ if (functionType === "HTTP" && !processedRootPath && !input.zipFile) {
92513
+ throw new Error("createFunction 创建 HTTP 函数时,需要提供 functionRootPath(指向 cloudfunctions 父目录)或 zipFile。");
92514
+ }
92515
+ const hasPackageJson = expectedFunctionPath !== undefined
92516
+ ? (0, fs_1.existsSync)(path_1.default.join(expectedFunctionPath, "package.json"))
92517
+ : false;
92518
+ func.installDependency = input.zipFile
92519
+ ? true
92520
+ : shouldInstallDependencyForFunction(functionType, hasPackageJson);
92521
+ if (functionType === "HTTP" && processedRootPath && !hasPackageJson) {
92522
+ console.warn(`检测到 HTTP 函数 ${functionName} 目录下没有 package.json,已跳过依赖安装;如果你需要第三方依赖,请补充 package.json 后重试。`);
92523
+ }
92321
92524
  let result;
92322
92525
  try {
92323
92526
  result = await cloudbase.functions.createFunction({
@@ -92330,11 +92533,7 @@ function registerFunctionTools(server) {
92330
92533
  throw wrapFunctionOperationError("createFunction", functionName, processedRootPath, error);
92331
92534
  }
92332
92535
  (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
92333
- return buildEnvelope({
92334
- action: input.action,
92335
- functionName,
92336
- raw: result,
92337
- }, `已创建函数 ${functionName}`, [
92536
+ const nextActions = [
92338
92537
  {
92339
92538
  tool: "queryFunctions",
92340
92539
  action: "getFunctionDetail",
@@ -92345,7 +92544,37 @@ function registerFunctionTools(server) {
92345
92544
  action: "listFunctionTriggers",
92346
92545
  reason: "检查函数触发器",
92347
92546
  },
92348
- ]);
92547
+ ];
92548
+ if (func.type === "HTTP") {
92549
+ nextActions.push({
92550
+ tool: "manageGateway",
92551
+ action: "createAccess",
92552
+ reason: "如果需要通过 URL 访问 HTTP 函数,请按实际路径和鉴权需求显式创建访问入口,不要默认假设 /函数名 已存在",
92553
+ });
92554
+ nextActions.push({
92555
+ tool: "queryGateway",
92556
+ action: "getAccess",
92557
+ reason: "交付前确认 HTTP 访问路径是否已存在并已生效",
92558
+ });
92559
+ nextActions.push({
92560
+ tool: "readSecurityRule",
92561
+ action: "读取安全规则",
92562
+ reason: "评测、浏览器或其他外部调用方可能以匿名身份访问;若直接报 EXCEED_AUTHORITY,应先读取当前函数安全规则",
92563
+ });
92564
+ nextActions.push({
92565
+ tool: "writeSecurityRule",
92566
+ action: "写入安全规则",
92567
+ reason: "只有在确认需要匿名访问时,才按实际安全要求调整函数安全规则,例如处理 EXCEED_AUTHORITY",
92568
+ });
92569
+ }
92570
+ const message = func.type === "HTTP"
92571
+ ? `已创建 HTTP 函数 ${functionName}。如果后续需要通过 URL 访问,请显式调用 manageGateway(action="createAccess") 按实际路径和鉴权需求创建访问入口。评测或其他外部调用方可能会以匿名身份访问,而且失败后不一定会把 EXCEED_AUTHORITY 再反馈给 AI;交付前请主动确认访问路径和函数安全规则,若已出现 EXCEED_AUTHORITY,请先调用 readSecurityRule(resourceType="function") 查看当前规则,再按需要使用 writeSecurityRule 调整权限。`
92572
+ : `已创建函数 ${functionName}`;
92573
+ return buildEnvelope({
92574
+ action: input.action,
92575
+ functionName,
92576
+ raw: result,
92577
+ }, message, nextActions);
92349
92578
  }
92350
92579
  case "updateFunctionCode": {
92351
92580
  if (!input.functionName) {
@@ -92390,6 +92619,9 @@ function registerFunctionTools(server) {
92390
92619
  }
92391
92620
  const cloudbase = await getManager();
92392
92621
  const functionDetail = await cloudbase.functions.getFunctionDetail(input.functionName);
92622
+ if (!functionDetail) {
92623
+ throw new Error(`函数 ${input.functionName} 不存在或无法获取详情`);
92624
+ }
92393
92625
  const currentVpc = typeof functionDetail.VpcConfig === "object" &&
92394
92626
  functionDetail.VpcConfig !== null &&
92395
92627
  functionDetail.VpcConfig.SubnetId &&
@@ -120049,10 +120281,10 @@ function registerHostingTools(server) {
120049
120281
  // uploadFiles - 上传文件到静态网站托管 (cloud-incompatible)
120050
120282
  server.registerTool("uploadFiles", {
120051
120283
  title: "上传静态文件",
120052
- description: "上传文件到静态网站托管。部署前请先完成构建;如果站点会部署到子路径,请检查构建配置中的 publicPath、base、assetPrefix 等是否使用相对路径,避免静态资源加载失败。",
120284
+ description: "上传文件到静态网站托管,仅用于 Web 站点部署,不用于云存储对象上传。部署前请先完成构建;如果站点会部署到子路径,请检查构建配置中的 publicPath、base、assetPrefix 等是否使用相对路径,避免静态资源加载失败。若需要上传 COS 云存储文件,请使用 manageStorage。",
120053
120285
  inputSchema: {
120054
120286
  localPath: zod_1.z.string().optional().describe("本地文件或文件夹路径,需要是绝对路径,例如 /tmp/files/data.txt。"),
120055
- cloudPath: zod_1.z.string().optional().describe("云端文件或文件夹路径,例如 files/data.txt。若部署到子路径,请同时检查构建配置中的 publicPath、base、assetPrefix 等是否为相对路径。"),
120287
+ cloudPath: zod_1.z.string().optional().describe("静态托管云端文件或文件夹路径,例如 files/data.txt。若部署到子路径,请同时检查构建配置中的 publicPath、base、assetPrefix 等是否为相对路径。云存储对象路径请改用 manageStorage。"),
120056
120288
  files: zod_1.z.array(zod_1.z.object({
120057
120289
  localPath: zod_1.z.string(),
120058
120290
  cloudPath: zod_1.z.string()
@@ -128640,7 +128872,7 @@ function registerCapiTools(server) {
128640
128872
  const getManager = () => (0, cloudbase_manager_js_1.getCloudBaseManager)({ cloudBaseOptions });
128641
128873
  server.registerTool?.("callCloudApi", {
128642
128874
  title: "调用云API",
128643
- description: `通用的云 API 调用工具,主要用于 CloudBase / 腾讯云管控面与依赖资源相关 API 调用。调用前请先确认 service、Action 与 Param,避免猜测 Action 名称。如果你的目标是通过 HTTP 协议直接集成 auth/functions/cloudrun/storage/mysqldb 等 CloudBase 业务 API,请不要优先使用 callCloudApi,而应优先查看对应 OpenAPI / Swagger。现有 OpenAPI / Swagger 能力不是通用的管控面 Action 集合;管控面 API 请优先参考 CloudBase API 概览 ${CLOUDBASE_CONTROL_PLANE_DOC_URL} 与云开发依赖资源接口指引 ${CLOUDBASE_DEPENDENCY_API_DOC_URL}。对于 tcb,可参考类似 \`CreateEnv\`、\`ModifyEnv\`、\`DestroyEnv\` 这类真实 Action 组织请求。`,
128875
+ description: `通用的云 API 调用工具,主要用于 CloudBase / 腾讯云管控面与依赖资源相关 API 调用。调用前请先确认 service、Action 与 Param,避免猜测 Action 名称。如果你的目标是通过 HTTP 协议直接集成 auth/functions/cloudrun/storage/mysqldb 等 CloudBase 业务 API,请不要优先使用 callCloudApi,而应优先查看对应 OpenAPI / Swagger。现有 OpenAPI / Swagger 能力不是通用的管控面 Action 集合;管控面 API 请优先参考 CloudBase API 概览 ${CLOUDBASE_CONTROL_PLANE_DOC_URL} 与云开发依赖资源接口指引 ${CLOUDBASE_DEPENDENCY_API_DOC_URL}。对于 tcb,可参考类似 \`CreateEnv\`、\`ModifyEnv\`、\`DestroyEnv\` 这类真实 Action 组织请求;销毁环境时,常见做法是至少带上 \`EnvId\` 和 \`BypassCheck: true\`,如果环境已经处于隔离期再按文档补 \`IsForce: true\`。`,
128644
128876
  inputSchema: {
128645
128877
  service: zod_1.z
128646
128878
  .enum(ALLOWED_SERVICES)
@@ -128652,7 +128884,7 @@ function registerCapiTools(server) {
128652
128884
  params: zod_1.z
128653
128885
  .record(zod_1.z.any())
128654
128886
  .optional()
128655
- .describe("Action 对应的参数对象,键名需与官方 API 定义一致。某些 Action 需要携带 EnvId 等信息;如不确定参数结构,请先查官方文档。tcb 示例:`{ \"service\": \"tcb\", \"action\": \"DestroyEnv\", \"params\": { \"EnvId\": \"env-xxx\" } }` 或 `{ \"service\": \"tcb\", \"action\": \"ModifyEnv\", \"params\": { \"EnvId\": \"env-xxx\", \"Alias\": \"demo\" } }`。若你的场景是通过 HTTP 协议直接集成 auth/functions/cloudrun/storage/mysqldb 等 CloudBase 业务 API,请优先使用 OpenAPI / Swagger 或 searchKnowledgeBase(mode=\"openapi\"),而不是优先使用 callCloudApi。"),
128887
+ .describe("Action 对应的参数对象,键名需与官方 API 定义一致。某些 Action 需要携带 EnvId 等信息;如不确定参数结构,请先查官方文档。tcb 示例:`{ \"service\": \"tcb\", \"action\": \"DestroyEnv\", \"params\": { \"EnvId\": \"env-xxx\", \"BypassCheck\": true } }`,如果环境已经处于隔离期,可再补 `IsForce: true`;更新环境别名则可用 `{ \"service\": \"tcb\", \"action\": \"ModifyEnv\", \"params\": { \"EnvId\": \"env-xxx\", \"Alias\": \"demo\" } }`。若你的场景是通过 HTTP 协议直接集成 auth/functions/cloudrun/storage/mysqldb 等 CloudBase 业务 API,请优先使用 OpenAPI / Swagger 或 searchKnowledgeBase(mode=\"openapi\"),而不是优先使用 callCloudApi。"),
128656
128888
  },
128657
128889
  annotations: {
128658
128890
  readOnlyHint: false,
@@ -140301,7 +140533,7 @@ class TelemetryReporter {
140301
140533
  const nodeVersion = process.version; // Node.js版本
140302
140534
  const arch = os_1.default.arch(); // 系统架构
140303
140535
  // 从构建时注入的版本号获取MCP版本信息
140304
- const mcpVersion = process.env.npm_package_version || "2.15.2-beta.1" || 0;
140536
+ const mcpVersion = process.env.npm_package_version || "2.15.2-beta.2" || 0;
140305
140537
  return {
140306
140538
  userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
140307
140539
  deviceId: this.deviceId,
@@ -201727,12 +201959,15 @@ As the most important part of application development, the following four core c
201727
201959
  **Refer to deployment process in \`rules/web-development/rule.md\`**
201728
201960
  - Use CloudBase static hosting after build completion
201729
201961
  - Deploy using \`uploadFiles\` tool
201962
+ - \`uploadFiles\` is only for static hosting deployment; do not use it for COS / cloud storage uploads. For storage objects, use \`manageStorage(action="upload")\`
201730
201963
  - Remind users that CDN has a few minutes of cache after deployment
201731
201964
  - Generate markdown format access links with random queryString
201732
201965
 
201733
201966
  ### 4. Backend Deployment (Cloud Functions or CloudRun)
201734
201967
  **Refer to \`rules/cloudrun-development/rule.md\`**
201735
- - **Cloud Function Deployment**: Prefer \`queryFunctions\` to inspect current state, then use \`manageFunctions\` with \`action="createFunction"\` or \`action="updateFunctionCode"\`
201968
+ - **Cloud Function Deployment**: Prefer \`queryFunctions\` to inspect current state, then use \`manageFunctions\` with \`action="createFunction"\` or \`action="updateFunctionCode"\`.
201969
+ - In agent / non-interactive runs, treat \`manageFunctions\` as the default deployment path for both Event and HTTP functions; do not fall back to CLI login flows unless MCP tools are unavailable.
201970
+ - For HTTP functions, create or update them through \`manageFunctions\` with \`func.type="HTTP"\` instead of relying on \`tcb fn deploy\` as the primary path.
201736
201971
  - **CloudRun Deployment**: Use \`manageCloudRun\` tool for containerized deployment
201737
201972
  - Ensure backend code supports CORS, prepare Dockerfile (for container type)
201738
201973
 
@@ -201831,11 +202066,11 @@ If remote links are needed in the application, can continue to call uploadFile t
201831
202066
 
201832
202067
  ### Deployment Process
201833
202068
 
201834
- 1. **Cloud Function Deployment Process**: Prefer \`queryFunctions\` to query current functions, then call \`manageFunctions\` with \`action="createFunction"\` or \`action="updateFunctionCode"\` to deploy cloud function code. Only need to point \`functionRootPath\` to the parent directory of the cloud function directory (for example, the absolute path of the \`cloudfunctions\` directory). No need for code compression or other preprocessing.
202069
+ 1. **Cloud Function Deployment Process**: Prefer \`queryFunctions\` to query current functions, then call \`manageFunctions\` with \`action="createFunction"\` or \`action="updateFunctionCode"\` to deploy cloud function code. In agent / non-interactive runs, keep deployment on MCP tools instead of CLI login flows. For HTTP functions, set \`func.type="HTTP"\` when creating them. Only need to point \`functionRootPath\` to the parent directory of the cloud function directory (for example, the absolute path of the \`cloudfunctions\` directory). No need for code compression or other preprocessing.
201835
202070
 
201836
202071
  2. **CloudRun Deployment Process**: For non-cloud function backend services (Java, Go, PHP, Python, Node.js, etc.), use manageCloudRun tool for deployment. Ensure backend code supports CORS, prepare Dockerfile, then call manageCloudRun for containerized deployment. For details, refer to \`rules/cloudrun-development/rule.md\`
201837
202072
 
201838
- 3. **Static Hosting Deployment Process**: Deploy using uploadFiles tool. After deployment, remind users that CDN has a few minutes of cache. Can generate markdown format access links with random queryString. For details, refer to \`rules/web-development/rule.md\`
202073
+ 3. **Static Hosting Deployment Process**: Deploy using uploadFiles tool for static hosting only. If the task needs a COS object that must be queried or polled with the storage SDK, use \`manageStorage\` / \`queryStorage\` instead. After deployment, remind users that CDN has a few minutes of cache. Can generate markdown format access links with random queryString. For details, refer to \`rules/web-development/rule.md\`
201839
202074
 
201840
202075
  ### Documentation Generation Rules
201841
202076
 
@@ -207009,7 +207244,7 @@ ${envIdSection}
207009
207244
  ## 环境信息
207010
207245
  - 操作系统: ${os_1.default.type()} ${os_1.default.release()}
207011
207246
  - Node.js版本: ${process.version}
207012
- - MCP 版本:${process.env.npm_package_version || "2.15.2-beta.1" || 0}
207247
+ - MCP 版本:${process.env.npm_package_version || "2.15.2-beta.2" || 0}
207013
207248
  - 系统架构: ${os_1.default.arch()}
207014
207249
  - 时间: ${new Date().toISOString()}
207015
207250
  - 请求ID: ${requestId}
@@ -215025,6 +215260,31 @@ async function getDatabaseInstanceId(getManager) {
215025
215260
  function delay(ms) {
215026
215261
  return new Promise((resolve) => setTimeout(resolve, ms));
215027
215262
  }
215263
+ function parseNoSqlDocument(value) {
215264
+ if (typeof value !== "string") {
215265
+ return value;
215266
+ }
215267
+ try {
215268
+ const parsed = JSON.parse(value);
215269
+ return parsed !== null && typeof parsed === "object" ? parsed : value;
215270
+ }
215271
+ catch {
215272
+ return value;
215273
+ }
215274
+ }
215275
+ function normalizeNoSqlDocuments(data) {
215276
+ if (!Array.isArray(data)) {
215277
+ return [];
215278
+ }
215279
+ return data.map((item) => parseNoSqlDocument(item));
215280
+ }
215281
+ function withCollectionName(collectionName, payload) {
215282
+ return {
215283
+ ...payload,
215284
+ collection: collectionName,
215285
+ collectionName,
215286
+ };
215287
+ }
215028
215288
  async function waitForCollectionReady({ cloudbase, collectionName, logger, timeoutMs = COLLECTION_READY_TIMEOUT_MS, pollIntervalMs = COLLECTION_READY_POLL_INTERVAL_MS, }) {
215029
215289
  const startedAt = Date.now();
215030
215290
  const deadline = startedAt + timeoutMs;
@@ -215150,14 +215410,14 @@ checkIndex: 检查索引是否存在`),
215150
215410
  content: [
215151
215411
  {
215152
215412
  type: "text",
215153
- text: JSON.stringify({
215413
+ text: JSON.stringify(withCollectionName(collectionName, {
215154
215414
  success: true,
215155
215415
  exists: result.Exists,
215156
215416
  requestId: result.RequestId,
215157
215417
  message: result.Exists
215158
215418
  ? "云开发数据库集合已存在"
215159
215419
  : "云开发数据库集合不存在",
215160
- }, null, 2),
215420
+ }), null, 2),
215161
215421
  },
215162
215422
  ],
215163
215423
  };
@@ -215172,13 +215432,13 @@ checkIndex: 检查索引是否存在`),
215172
215432
  content: [
215173
215433
  {
215174
215434
  type: "text",
215175
- text: JSON.stringify({
215435
+ text: JSON.stringify(withCollectionName(collectionName, {
215176
215436
  success: true,
215177
215437
  requestId: result.RequestId,
215178
215438
  indexNum: result.IndexNum,
215179
215439
  indexes: result.Indexes,
215180
215440
  message: "获取云开发数据库集合信息成功",
215181
- }, null, 2),
215441
+ }), null, 2),
215182
215442
  },
215183
215443
  ],
215184
215444
  };
@@ -215193,13 +215453,13 @@ checkIndex: 检查索引是否存在`),
215193
215453
  content: [
215194
215454
  {
215195
215455
  type: "text",
215196
- text: JSON.stringify({
215456
+ text: JSON.stringify(withCollectionName(collectionName, {
215197
215457
  success: true,
215198
215458
  requestId: result.RequestId,
215199
215459
  indexNum: result.IndexNum,
215200
215460
  indexes: result.Indexes,
215201
215461
  message: "获取索引列表成功",
215202
- }, null, 2),
215462
+ }), null, 2),
215203
215463
  },
215204
215464
  ],
215205
215465
  };
@@ -215214,12 +215474,13 @@ checkIndex: 检查索引是否存在`),
215214
215474
  content: [
215215
215475
  {
215216
215476
  type: "text",
215217
- text: JSON.stringify({
215477
+ text: JSON.stringify(withCollectionName(collectionName, {
215218
215478
  success: true,
215479
+ indexName,
215219
215480
  exists: result.Exists,
215220
215481
  requestId: result.RequestId,
215221
215482
  message: result.Exists ? "索引已存在" : "索引不存在",
215222
- }, null, 2),
215483
+ }), null, 2),
215223
215484
  },
215224
215485
  ],
215225
215486
  };
@@ -215283,12 +215544,12 @@ deleteCollection: 删除集合`),
215283
215544
  content: [
215284
215545
  {
215285
215546
  type: "text",
215286
- text: JSON.stringify({
215547
+ text: JSON.stringify(withCollectionName(collectionName, {
215287
215548
  success: true,
215288
215549
  requestId: result.RequestId,
215289
215550
  action,
215290
215551
  message: "云开发数据库集合创建成功",
215291
- }, null, 2),
215552
+ }), null, 2),
215292
215553
  },
215293
215554
  ],
215294
215555
  };
@@ -215303,12 +215564,12 @@ deleteCollection: 删除集合`),
215303
215564
  content: [
215304
215565
  {
215305
215566
  type: "text",
215306
- text: JSON.stringify({
215567
+ text: JSON.stringify(withCollectionName(collectionName, {
215307
215568
  success: true,
215308
215569
  requestId: result.RequestId,
215309
215570
  action,
215310
215571
  message: "云开发数据库集合更新成功",
215311
- }, null, 2),
215572
+ }), null, 2),
215312
215573
  },
215313
215574
  ],
215314
215575
  };
@@ -215316,12 +215577,12 @@ deleteCollection: 删除集合`),
215316
215577
  if (action === "deleteCollection") {
215317
215578
  const result = await cloudbase.database.deleteCollection(collectionName);
215318
215579
  (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
215319
- const body = {
215580
+ const body = withCollectionName(collectionName, {
215320
215581
  success: true,
215321
215582
  requestId: result.RequestId,
215322
215583
  action,
215323
215584
  message: result.Exists === false ? "集合不存在" : "云开发数据库集合删除成功",
215324
- };
215585
+ });
215325
215586
  if (result.Exists === false) {
215326
215587
  body.exists = false;
215327
215588
  }
@@ -215387,17 +215648,21 @@ deleteCollection: 删除集合`),
215387
215648
  },
215388
215649
  });
215389
215650
  (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
215651
+ const documents = normalizeNoSqlDocuments(result.Data);
215390
215652
  return {
215391
215653
  content: [
215392
215654
  {
215393
215655
  type: "text",
215394
- text: JSON.stringify({
215656
+ text: JSON.stringify(withCollectionName(collectionName, {
215395
215657
  success: true,
215396
215658
  requestId: result.RequestId,
215397
- data: result.Data,
215659
+ data: documents,
215660
+ total: typeof result.Pager?.Total === "number"
215661
+ ? result.Pager.Total
215662
+ : documents.length,
215398
215663
  pager: result.Pager,
215399
215664
  message: "文档查询成功",
215400
- }, null, 2),
215665
+ }), null, 2),
215401
215666
  },
215402
215667
  ],
215403
215668
  };
@@ -215520,12 +215785,15 @@ async function insertDocuments({ collectionName, documents, getManager, logger,
215520
215785
  },
215521
215786
  });
215522
215787
  (0, cloudbase_manager_js_1.logCloudBaseResult)(logger, result);
215523
- return JSON.stringify({
215788
+ return JSON.stringify(withCollectionName(collectionName, {
215524
215789
  success: true,
215525
215790
  requestId: result.RequestId,
215526
215791
  insertedIds: result.InsertedIds,
215792
+ insertedCount: Array.isArray(result.InsertedIds)
215793
+ ? result.InsertedIds.length
215794
+ : undefined,
215527
215795
  message: "文档插入成功",
215528
- }, null, 2);
215796
+ }), null, 2);
215529
215797
  }
215530
215798
  async function updateDocuments({ collectionName, query, update, isMulti, upsert, getManager, logger, }) {
215531
215799
  const cloudbase = await getManager();
@@ -215543,14 +215811,14 @@ async function updateDocuments({ collectionName, query, update, isMulti, upsert,
215543
215811
  },
215544
215812
  });
215545
215813
  (0, cloudbase_manager_js_1.logCloudBaseResult)(logger, result);
215546
- return JSON.stringify({
215814
+ return JSON.stringify(withCollectionName(collectionName, {
215547
215815
  success: true,
215548
215816
  requestId: result.RequestId,
215549
215817
  modifiedCount: result.ModifiedNum,
215550
215818
  matchedCount: result.MatchedNum,
215551
215819
  upsertedId: result.UpsertedId,
215552
215820
  message: "文档更新成功",
215553
- }, null, 2);
215821
+ }), null, 2);
215554
215822
  }
215555
215823
  async function deleteDocuments({ collectionName, query, isMulti, getManager, logger, }) {
215556
215824
  const cloudbase = await getManager();
@@ -215566,12 +215834,12 @@ async function deleteDocuments({ collectionName, query, isMulti, getManager, log
215566
215834
  },
215567
215835
  });
215568
215836
  (0, cloudbase_manager_js_1.logCloudBaseResult)(logger, result);
215569
- return JSON.stringify({
215837
+ return JSON.stringify(withCollectionName(collectionName, {
215570
215838
  success: true,
215571
215839
  requestId: result.RequestId,
215572
215840
  deleted: result.Deleted,
215573
215841
  message: "文档删除成功",
215574
- }, null, 2);
215842
+ }), null, 2);
215575
215843
  }
215576
215844
 
215577
215845
 
@@ -221835,7 +222103,7 @@ function registerSetupTools(server) {
221835
222103
  title: "下载项目模板",
221836
222104
  description: `自动下载并部署CloudBase项目模板。⚠️ **MANDATORY FOR NEW PROJECTS** ⚠️
221837
222105
 
221838
- **CRITICAL**: This tool MUST be called FIRST when starting a new project.\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.15.2-beta.1" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
222106
+ **CRITICAL**: This tool MUST be called FIRST when starting a new project.\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.15.2-beta.2" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
221839
222107
  inputSchema: {
221840
222108
  template: zod_1.z
221841
222109
  .enum(["react", "vue", "miniprogram", "uniapp", "rules"])
@@ -240314,11 +240582,11 @@ function registerGatewayTools(server) {
240314
240582
  targetName: input.targetName,
240315
240583
  path: accessPath,
240316
240584
  raw: result,
240317
- }, `已为目标 ${input.targetName} 创建网关访问路径`, [
240585
+ }, `已为目标 ${input.targetName} 创建网关访问路径。注意:路由配置传播通常需要等待 30 秒到 3 分钟,请勿立即访问。`, [
240318
240586
  {
240319
240587
  tool: "queryGateway",
240320
240588
  action: "getAccess",
240321
- reason: "确认访问入口是否已生效",
240589
+ reason: "等待 30 秒到 3 分钟后再确认访问入口是否已生效",
240322
240590
  },
240323
240591
  ]);
240324
240592
  }
@@ -269366,7 +269634,7 @@ function registerStorageTools(server) {
269366
269634
  // Tool 2: manageStorage - 管理存储文件(写操作)
269367
269635
  server.registerTool("manageStorage", {
269368
269636
  title: "管理存储文件",
269369
- description: "管理云存储文件,支持上传文件/目录、下载文件/目录、删除文件/目录等操作。删除操作需要设置force=true进行确认,防止误删除重要文件。",
269637
+ description: "管理云存储文件,仅用于 COS/Storage 对象,不用于静态网站托管。支持上传文件/目录、下载文件/目录、删除文件/目录等操作。删除操作需要设置force=true进行确认,防止误删除重要文件。",
269370
269638
  inputSchema: manageStorageInputSchema,
269371
269639
  annotations: {
269372
269640
  readOnlyHint: false,