@cloudbase/cloudbase-mcp 2.23.5 → 2.23.7

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
@@ -1990,13 +1990,14 @@ async function fetchAvailableEnvCandidates(cloudBaseOptions, server) {
1990
1990
  return [];
1991
1991
  }
1992
1992
  }
1993
- const CODEBUDDY_AUTH_ACTIONS = ["status", "set_env"];
1993
+ const CODEBUDDY_AUTH_ACTIONS = ["status", "set_env", "login_by_api_key"];
1994
1994
  const DEFAULT_AUTH_ACTIONS = [
1995
1995
  "status",
1996
1996
  "start_auth",
1997
1997
  "set_env",
1998
1998
  "logout",
1999
1999
  "get_temp_credentials",
2000
+ "login_by_api_key",
2000
2001
  ];
2001
2002
  function maskSensitiveValue(value) {
2002
2003
  if (value.length <= 4) {
@@ -2322,7 +2323,7 @@ async function enrichEnvInfoWithBilling(params) {
2322
2323
  * for new code, including an explicit `MysqlNotAvailable` line when
2323
2324
  * MySQL is absent — that one IS a hard "do not use" signal.
2324
2325
  */
2325
- function enrichEnvInfoWithRuntimeMode(result) {
2326
+ async function enrichEnvInfoWithRuntimeMode(result, manager) {
2326
2327
  const envInfo = result?.EnvInfo;
2327
2328
  if (!envInfo || typeof envInfo !== "object") {
2328
2329
  return result;
@@ -2352,7 +2353,29 @@ function enrichEnvInfoWithRuntimeMode(result) {
2352
2353
  }
2353
2354
  return [];
2354
2355
  })();
2355
- const hasMysql = mysqlList.length > 0;
2356
+ let hasMysql = mysqlList.length > 0;
2357
+ // Fallback: if MySQL not detected from DescribeEnvInfo fields, probe via
2358
+ // DescribeMySQLClusterDetail (dedicated MySQL API). This covers cases where
2359
+ // the SDK strips MySQL fields from the DescribeEnvInfo response.
2360
+ if (!hasMysql && manager?.commonService) {
2361
+ try {
2362
+ const probeResult = await manager
2363
+ .commonService("tcb", "2018-06-08")
2364
+ .call({
2365
+ Action: "DescribeMySQLClusterDetail",
2366
+ Param: { EnvId: envInfo.EnvId },
2367
+ });
2368
+ const clusterId = probeResult?.DbClusterId ||
2369
+ probeResult?.Response?.DbClusterId ||
2370
+ probeResult?.Data?.DbClusterId;
2371
+ if (clusterId) {
2372
+ hasMysql = true;
2373
+ }
2374
+ }
2375
+ catch {
2376
+ // Probe failure means MySQL is not provisioned — keep hasMysql = false
2377
+ }
2378
+ }
2356
2379
  // Primary mode: prefer PG when it is provisioned, otherwise fall back to
2357
2380
  // legacy NoSQL labeling. This drives "what skill to read first / what API
2358
2381
  // to reach for when starting new business code".
@@ -2370,7 +2393,7 @@ function enrichEnvInfoWithRuntimeMode(result) {
2370
2393
  : "No legacy NoSQL Database/Storage observed in this env.",
2371
2394
  MysqlNotAvailable: hasMysql
2372
2395
  ? "MySQL instance(s) detected — see EnvInfo.MysqlInstances."
2373
- : "No MySQL instance is provisioned for this env. Do NOT use `manageSqlDatabase` / `querySqlDatabase` (those are MySQL-specific) and do NOT read the `relational-database-tool` skill — that family targets MySQL, not CloudBase PG.",
2396
+ : "No MySQL instance is provisioned for this env. Do NOT use `manageMysqlDatabase` / `queryMysqlDatabase` (those are MySQL-specific) and do NOT read the `relational-database-tool` skill — that family targets MySQL, not CloudBase PG.",
2374
2397
  RecommendedSkills: "Read `postgresql-development` first for new PG code. `no-sql-web-sdk` is still applicable for existing NoSQL collections in this env. Skip `relational-database-tool` (MySQL-only) entirely.",
2375
2398
  }
2376
2399
  : {
@@ -2380,7 +2403,7 @@ function enrichEnvInfoWithRuntimeMode(result) {
2380
2403
  Storage: "Browser uploads use `app.uploadFile()` against the bucket exposed in `EnvInfo.Storages[].Bucket`.",
2381
2404
  MysqlNotAvailable: hasMysql
2382
2405
  ? "MySQL instance(s) detected — see EnvInfo.MysqlInstances."
2383
- : "No MySQL instance in this env. `manageSqlDatabase` / `querySqlDatabase` and the `relational-database-tool` skill are not applicable.",
2406
+ : "No MySQL instance in this env. `manageMysqlDatabase` / `queryMysqlDatabase` and the `relational-database-tool` skill are not applicable.",
2384
2407
  RecommendedSkills: "Read `no-sql-web-sdk` (and `cloud-storage-web` for uploads). `postgresql-development` and `relational-database-tool` are not applicable to this env.",
2385
2408
  };
2386
2409
  return {
@@ -2531,12 +2554,12 @@ function registerEnvTools(server) {
2531
2554
  if (server.ide !== 'wxide') {
2532
2555
  server.registerTool?.("auth", {
2533
2556
  title: "CloudBase 开发阶段登录与环境",
2534
- description: "CloudBase(腾讯云开发)开发阶段登录与环境绑定。登录后即可访问云资源;环境(env)是云函数、数据库、静态托管等资源的隔离单元,绑定环境后其他 MCP 工具才能操作该环境。支持:查询状态、发起登录、绑定环境(set_env)、退出登录。",
2557
+ description: "CloudBase(腾讯云开发)开发阶段登录与环境绑定。登录后即可访问云资源;环境(env)是云函数、数据库、静态托管等资源的隔离单元,绑定环境后其他 MCP 工具才能操作该环境。支持:查询状态、发起登录、API Key登录、绑定环境(set_env)、退出登录。",
2535
2558
  inputSchema: {
2536
2559
  action: zod_1.z
2537
2560
  .enum(authActionEnum)
2538
2561
  .optional()
2539
- .describe("动作:status=查询状态,start_auth=发起登录,set_env=绑定环境(传envId),logout=退出登录"),
2562
+ .describe("动作:status=查询状态,start_auth=发起登录,login_by_api_key=API Key登录,set_env=绑定环境(传envId),logout=退出登录"),
2540
2563
  ...(supportedAuthActions.includes("start_auth")
2541
2564
  ? {
2542
2565
  authMode: zod_1.z
@@ -2561,6 +2584,18 @@ function registerEnvTools(server) {
2561
2584
  .string()
2562
2585
  .optional()
2563
2586
  .describe("环境ID(CloudBase 环境唯一标识),绑定后工具将操作该环境。action=set_env 时必填"),
2587
+ ...(supportedAuthActions.includes("login_by_api_key")
2588
+ ? {
2589
+ apiKey: zod_1.z
2590
+ .string()
2591
+ .optional()
2592
+ .describe("CloudBase API Key,action=login_by_api_key 时必填"),
2593
+ apiKeyEnvId: zod_1.z
2594
+ .string()
2595
+ .optional()
2596
+ .describe("CloudBase 环境ID(EnvId),action=login_by_api_key 时必填,用于指定 API Key 所属环境"),
2597
+ }
2598
+ : {}),
2564
2599
  ...(supportedAuthActions.includes("logout")
2565
2600
  ? {
2566
2601
  confirm: zod_1.z
@@ -2876,6 +2911,78 @@ function registerEnvTools(server) {
2876
2911
  next_step: envPreparation.nextStep,
2877
2912
  });
2878
2913
  }
2914
+ if (action === "login_by_api_key") {
2915
+ const toolApiKey = normalizeOptionalToolString(rawArgs.apiKey);
2916
+ const toolApiKeyEnvId = normalizeOptionalToolString(rawArgs.apiKeyEnvId);
2917
+ if (!toolApiKey || !toolApiKeyEnvId) {
2918
+ return (0, tool_result_js_1.buildJsonToolResult)({
2919
+ ok: false,
2920
+ code: "INVALID_ARGS",
2921
+ message: "action=login_by_api_key 时必须同时提供 apiKey 和 envId。",
2922
+ next_step: (0, tool_result_js_1.buildAuthNextStep)("login_by_api_key", {
2923
+ suggestedArgs: { action: "login_by_api_key", apiKey: "<your-api-key>", envId: "<your-env-id>" },
2924
+ }),
2925
+ });
2926
+ }
2927
+ // 写入 process.env(与 cli.ts 处理 --api-key/--env-id 的逻辑一致)
2928
+ process.env.CLOUDBASE_API_KEY = toolApiKey;
2929
+ process.env.CLOUDBASE_ENV_ID = toolApiKeyEnvId;
2930
+ try {
2931
+ const loginState = await (0, auth_js_1.peekLoginState)();
2932
+ if (loginState) {
2933
+ const envPreparation = await prepareAuthEnvironment({
2934
+ server,
2935
+ cloudBaseOptions,
2936
+ loginState,
2937
+ });
2938
+ return (0, tool_result_js_1.buildJsonToolResult)({
2939
+ ok: true,
2940
+ code: "AUTH_READY",
2941
+ message: "API Key 认证成功,已获取临时密钥。",
2942
+ auth_mode: "api_key",
2943
+ ...buildAuthEnvSetupPayload(envPreparation),
2944
+ next_step: envPreparation.nextStep,
2945
+ });
2946
+ }
2947
+ // API Key 换取失败:清理 env vars 并返回诊断信息
2948
+ delete process.env.CLOUDBASE_API_KEY;
2949
+ delete process.env.CLOUDBASE_ENV_ID;
2950
+ let diagMessage = "API Key 换取临时密钥失败。";
2951
+ diagMessage += `\n\n诊断信息:`;
2952
+ diagMessage += `\n- CLOUDBASE_ENV_ID: ${toolApiKeyEnvId}`;
2953
+ diagMessage += `\n- CLOUDBASE_API_KEY: ${toolApiKey.slice(0, 20)}...(已截断)`;
2954
+ diagMessage += `\n\n可能原因:`;
2955
+ diagMessage += `\n1. API Key 已过期或被删除`;
2956
+ diagMessage += `\n2. CLOUDBASE_ENV_ID 与 API Key 所属环境不匹配`;
2957
+ diagMessage += `\n3. 网络连接问题`;
2958
+ diagMessage += `\n\n建议:请检查 API Key 和环境 ID 是否正确。`;
2959
+ return (0, tool_result_js_1.buildJsonToolResult)({
2960
+ ok: false,
2961
+ code: "API_KEY_AUTH_FAILED",
2962
+ message: diagMessage,
2963
+ auth_mode: "api_key",
2964
+ envId: toolApiKeyEnvId,
2965
+ next_step: (0, tool_result_js_1.buildAuthNextStep)("login_by_api_key", {
2966
+ suggestedArgs: { action: "login_by_api_key", apiKey: "<your-api-key>", envId: "<your-env-id>" },
2967
+ }),
2968
+ });
2969
+ }
2970
+ catch (error) {
2971
+ // 异常时清理 env vars
2972
+ delete process.env.CLOUDBASE_API_KEY;
2973
+ delete process.env.CLOUDBASE_ENV_ID;
2974
+ const message = error instanceof Error ? error.message : String(error);
2975
+ return (0, tool_result_js_1.buildJsonToolResult)({
2976
+ ok: false,
2977
+ code: "API_KEY_AUTH_FAILED",
2978
+ message: `API Key 认证异常: ${message}`,
2979
+ auth_mode: "api_key",
2980
+ next_step: (0, tool_result_js_1.buildAuthNextStep)("login_by_api_key", {
2981
+ suggestedArgs: { action: "login_by_api_key", apiKey: "<your-api-key>", envId: "<your-env-id>" },
2982
+ }),
2983
+ });
2984
+ }
2985
+ }
2879
2986
  if (action === "set_env") {
2880
2987
  const loginState = await (0, auth_js_1.peekLoginState)();
2881
2988
  if (!loginState) {
@@ -3144,7 +3251,7 @@ function registerEnvTools(server) {
3144
3251
  if (envId) {
3145
3252
  result = await enrichEnvInfoWithMissingFields(cloudbaseInfo, result, envId);
3146
3253
  }
3147
- result = enrichEnvInfoWithRuntimeMode(result);
3254
+ result = await enrichEnvInfoWithRuntimeMode(result, cloudbaseInfo);
3148
3255
  break;
3149
3256
  case "domains":
3150
3257
  const cloudbaseDomains = await getManager();
@@ -3212,7 +3319,7 @@ function registerEnvTools(server) {
3212
3319
  // Register primary tool name (queryEnv)
3213
3320
  const queryEnvToolSchema = {
3214
3321
  title: "CloudBase 环境查询",
3215
- description: "查询 CloudBase 环境相关信息,支持查询环境列表、指定环境详情和安全域名。(曾用名:envQuery、listEnvs、getEnvInfo、getEnvAuthDomains)当 action=list 时,会按 DescribeEnvs 语义做列表/筛选,标准返回字段为 EnvId、Alias、Status、EnvType、Region、PackageId、PackageName、IsDefault,并支持通过 fields 白名单裁剪这些字段;aliasExact=true 时会按别名精确筛选,避免把前缀相近的环境误当作候选;即使传入 envId,action=list 也只返回摘要,不会返回完整资源明细或 expiry。如需查询某个已知 EnvId 对应环境的详细信息(包括资源字段和计费信息),必须使用 action=info 并传入目标环境的 envId 参数。action=info 会在可用时补充 BillingInfo(如 ExpireTime、PayMode、IsAutoRenew 等计费字段)。\n\n🔍 action=info 还会派生三个用于后端选型的字段:\n- `EnvInfo.RuntimeMode`:'postgresql' 或 'nosql',表示新业务建议默认使用的后端(PG 已开通时为 postgresql,否则为 nosql)。\n- `EnvInfo.RuntimeBackends`:`{postgresql, nosql, mysql}` 三个布尔值,描述当前环境实际并存的后端。\n- `EnvInfo.RuntimeModeHints`:每个后端对应的 API/工具/skill 提示。\n\nAI 在写业务/权限/存储代码前必须先看这三项:PG 模式下新业务推荐 `app.rdb()` + RLS(`managePgDatabase action=execute` 跑 `CREATE POLICY`)+ pgstore;已存在的 NoSQL 集合 / 旧 storage / `managePermissions(resourceType=\"noSqlDatabase\")` 在 PG 环境下仍然有效。真正不适用的是 MySQL:当 `RuntimeBackends.mysql === false` 时,`manageSqlDatabase` / `querySqlDatabase` / `relational-database-tool` skill 都不该使用。",
3322
+ description: "查询 CloudBase 环境相关信息,支持查询环境列表、指定环境详情和安全域名。(曾用名:envQuery、listEnvs、getEnvInfo、getEnvAuthDomains)当 action=list 时,会按 DescribeEnvs 语义做列表/筛选,标准返回字段为 EnvId、Alias、Status、EnvType、Region、PackageId、PackageName、IsDefault,并支持通过 fields 白名单裁剪这些字段;aliasExact=true 时会按别名精确筛选,避免把前缀相近的环境误当作候选;即使传入 envId,action=list 也只返回摘要,不会返回完整资源明细或 expiry。如需查询某个已知 EnvId 对应环境的详细信息(包括资源字段和计费信息),必须使用 action=info 并传入目标环境的 envId 参数。action=info 会在可用时补充 BillingInfo(如 ExpireTime、PayMode、IsAutoRenew 等计费字段)。\n\n🔍 action=info 还会派生三个用于后端选型的字段:\n- `EnvInfo.RuntimeMode`:'postgresql' 或 'nosql',表示新业务建议默认使用的后端(PG 已开通时为 postgresql,否则为 nosql)。\n- `EnvInfo.RuntimeBackends`:`{postgresql, nosql, mysql}` 三个布尔值,描述当前环境实际并存的后端。\n- `EnvInfo.RuntimeModeHints`:每个后端对应的 API/工具/skill 提示。\n\nAI 在写业务/权限/存储代码前必须先看这三项:PG 模式下新业务推荐 `app.rdb()` + RLS(`managePgDatabase action=execute` 跑 `CREATE POLICY`)+ pgstore;已存在的 NoSQL 集合 / 旧 storage / `managePermissions(resourceType=\"noSqlDatabase\")` 在 PG 环境下仍然有效。真正不适用的是 MySQL:当 `RuntimeBackends.mysql === false` 时,`manageMysqlDatabase` / `queryMysqlDatabase` / `relational-database-tool` skill 都不该使用。",
3216
3323
  inputSchema: {
3217
3324
  action: zod_1.z
3218
3325
  .enum(["list", "info", "domains"])
@@ -39115,6 +39222,18 @@ function buildErrorEnvelope(error) {
39115
39222
  function normalizeString(value) {
39116
39223
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
39117
39224
  }
39225
+ /**
39226
+ * Sanitize agent name for CloudBase backend.
39227
+ * The backend creates a cloud function alias from the agent name (e.g. "agent-{name}"),
39228
+ * and SCF aliases only allow alphanumeric characters and hyphens.
39229
+ * This function replaces any character that is not [a-zA-Z0-9] with a hyphen,
39230
+ * then collapses consecutive hyphens into one.
39231
+ */
39232
+ function sanitizeAgentName(name) {
39233
+ return name
39234
+ .replace(/[^a-zA-Z0-9]+/g, "-")
39235
+ .replace(/^-+|-+$/g, "");
39236
+ }
39118
39237
  function normalizeNumber(value) {
39119
39238
  return typeof value === "number" && Number.isFinite(value) ? value : undefined;
39120
39239
  }
@@ -39269,13 +39388,19 @@ function registerAgentTools(server) {
39269
39388
  }
39270
39389
  // CloudBase 后端在创建 Agent 时会同步创建云函数,函数名/别名长度受 SCF 限制(最大 64 字符)。
39271
39390
  // envId 可能被用作前缀或别名的一部分,因此这里预留足够余量,避免后端 CreateFunction 失败。
39272
- if (normalizedName.length > 30) {
39273
- throw new Error(`agent name 过长(当前 ${normalizedName.length} 字符)。CloudBase 创建 Agent 时会同步创建云函数,` +
39274
- `函数名/别名受 SCF 64 字符限制,且 envId 可能作为前缀拼接。请将 name 控制在 30 字符以内。`);
39391
+ // 同时,后端会用 name 生成云函数 alias(如 "agent-{name}"),而 SCF alias 只允许字母、数字和连字符,
39392
+ // 因此需要对 name 做 sanitize,将非法字符(如下划线)替换为连字符。
39393
+ const sanitizedName = sanitizeAgentName(normalizedName);
39394
+ if (!sanitizedName) {
39395
+ throw new Error(`name "${normalizedName}" 经 sanitize 后为空,请使用包含字母或数字的 name`);
39396
+ }
39397
+ if (sanitizedName.length > 30) {
39398
+ throw new Error(`agent name 过长(当前 ${sanitizedName.length} 字符)。CloudBase 创建 Agent 时会同步创建云函数,` +
39399
+ `函数名/别名受 SCF 64 字符长度限制,且 envId 可能作为前缀拼接。请将 name 控制在 30 字符以内。`);
39275
39400
  }
39276
39401
  const createPayload = {
39277
39402
  ...payload,
39278
- Name: normalizedName,
39403
+ Name: sanitizedName,
39279
39404
  Runtime: normalizeString(payload.Runtime) ?? "Nodejs20.19",
39280
39405
  };
39281
39406
  const result = await cloudbase.agent.createAgent(createPayload);
@@ -40629,7 +40754,7 @@ async function checkMysqlGate(server) {
40629
40754
  success: false,
40630
40755
  errorCode: "MYSQL_NOT_AVAILABLE",
40631
40756
  message: `This environment (${envId}) does not have MySQL. Use managePgDatabase / queryPgDatabase instead.`,
40632
- nextActions: [{ tool: "managePgDatabase", params: { action: "execute" }, description: "Use managePgDatabase" }],
40757
+ nextActions: [{ tool: "managePgDatabase", params: { action: "execute" }, description: "Use managePgDatabase for PostgreSQL operations" }],
40633
40758
  });
40634
40759
  }
40635
40760
  try {
@@ -40641,7 +40766,7 @@ async function checkMysqlGate(server) {
40641
40766
  return (0, tool_result_js_1.buildJsonToolResult)({
40642
40767
  success: false,
40643
40768
  errorCode: "MYSQL_NOT_AVAILABLE",
40644
- message: `This environment (${envId}) has PostgreSQL enabled but MySQL is NOT available. Use managePgDatabase / queryPgDatabase instead of manageSqlDatabase / querySqlDatabase.`,
40769
+ message: `This environment (${envId}) has PostgreSQL enabled but MySQL is NOT available. Use managePgDatabase / queryPgDatabase instead of manageMysqlDatabase / queryMysqlDatabase.`,
40645
40770
  nextActions: [{ tool: "managePgDatabase", params: { action: "execute" }, description: "Use managePgDatabase for PostgreSQL operations" }],
40646
40771
  });
40647
40772
  }
@@ -40650,8 +40775,8 @@ async function checkMysqlGate(server) {
40650
40775
  MYSQL_GATE_CACHE.set(envId, true);
40651
40776
  return null;
40652
40777
  }
40653
- const QUERY_SQL_DATABASE = "querySqlDatabase";
40654
- const MANAGE_SQL_DATABASE = "manageSqlDatabase";
40778
+ const QUERY_MYSQL_DATABASE = "queryMysqlDatabase";
40779
+ const MANAGE_MYSQL_DATABASE = "manageMysqlDatabase";
40655
40780
  const QUERY_PERMISSIONS = "queryPermissions";
40656
40781
  const MANAGE_PERMISSIONS = "managePermissions";
40657
40782
  const QUERY_ACTIONS = [
@@ -40943,14 +41068,14 @@ async function getSqlInstanceInfo({ getManager, cloudBaseOptions, server, }) {
40943
41068
  function buildProvisionNextActions(status, request) {
40944
41069
  if (status === "READY") {
40945
41070
  return [
40946
- buildNextAction(MANAGE_SQL_DATABASE, "initializeSchema", "MySQL is ready. Initialize tables and indexes next."),
41071
+ buildNextAction(MANAGE_MYSQL_DATABASE, "initializeSchema", "MySQL is ready. Initialize tables and indexes next."),
40947
41072
  ];
40948
41073
  }
40949
41074
  if (status === "FAILED") {
40950
41075
  return [];
40951
41076
  }
40952
41077
  return [
40953
- buildNextAction(QUERY_SQL_DATABASE, "describeCreateResult", "MySQL provisioning is still running. Check the create result again before initializing schema.", request
41078
+ buildNextAction(QUERY_MYSQL_DATABASE, "describeCreateResult", "MySQL provisioning is still running. Check the create result again before initializing schema.", request
40954
41079
  ? { action: "describeCreateResult", request }
40955
41080
  : { action: "describeCreateResult" }),
40956
41081
  ];
@@ -40969,15 +41094,15 @@ function buildTaskStatusNextActions(status, request) {
40969
41094
  if (status === "READY") {
40970
41095
  if (inferTaskKind(request) === "destroy") {
40971
41096
  return [
40972
- buildNextAction(QUERY_SQL_DATABASE, "getInstanceInfo", "The destroy task completed. Confirm whether the MySQL instance no longer exists."),
41097
+ buildNextAction(QUERY_MYSQL_DATABASE, "getInstanceInfo", "The destroy task completed. Confirm whether the MySQL instance no longer exists."),
40973
41098
  ];
40974
41099
  }
40975
41100
  return [
40976
- buildNextAction(MANAGE_SQL_DATABASE, "initializeSchema", "MySQL is ready. Initialize tables and indexes next."),
41101
+ buildNextAction(MANAGE_MYSQL_DATABASE, "initializeSchema", "MySQL is ready. Initialize tables and indexes next."),
40977
41102
  ];
40978
41103
  }
40979
41104
  return [
40980
- buildNextAction(QUERY_SQL_DATABASE, "describeTaskStatus", "MySQL task is still running. Check task status again before continuing.", request ? { action: "describeTaskStatus", request } : { action: "describeTaskStatus" }),
41105
+ buildNextAction(QUERY_MYSQL_DATABASE, "describeTaskStatus", "MySQL task is still running. Check task status again before continuing.", request ? { action: "describeTaskStatus", request } : { action: "describeTaskStatus" }),
40981
41106
  ];
40982
41107
  }
40983
41108
  async function handleRunQuery(args, context) {
@@ -40987,7 +41112,7 @@ async function handleRunQuery(args, context) {
40987
41112
  errorCode: "SQL_REQUIRED",
40988
41113
  message: "`sql` is required when action is `runQuery`.",
40989
41114
  nextActions: [
40990
- buildNextAction(QUERY_SQL_DATABASE, "runQuery", "Provide a read-only SQL statement such as SELECT/SHOW/DESCRIBE."),
41115
+ buildNextAction(QUERY_MYSQL_DATABASE, "runQuery", "Provide a read-only SQL statement such as SELECT/SHOW/DESCRIBE."),
40991
41116
  ],
40992
41117
  });
40993
41118
  }
@@ -40995,9 +41120,9 @@ async function handleRunQuery(args, context) {
40995
41120
  return buildSqlToolResult({
40996
41121
  success: false,
40997
41122
  errorCode: "READ_ONLY_SQL_REQUIRED",
40998
- message: "`querySqlDatabase(action=runQuery)` only accepts read-only SQL statements.",
41123
+ message: "`queryMysqlDatabase(action=runQuery)` only accepts read-only SQL statements.",
40999
41124
  nextActions: [
41000
- buildNextAction(MANAGE_SQL_DATABASE, "runStatement", "Use the manage tool for INSERT/UPDATE/DELETE/DDL statements."),
41125
+ buildNextAction(MANAGE_MYSQL_DATABASE, "runStatement", "Use the manage tool for INSERT/UPDATE/DELETE/DDL statements."),
41001
41126
  ],
41002
41127
  });
41003
41128
  }
@@ -41025,7 +41150,7 @@ async function handleRunQuery(args, context) {
41025
41150
  errorCode: "MYSQL_NOT_CREATED",
41026
41151
  message: "MySQL is not provisioned yet or not found. Please provision MySQL before running queries.",
41027
41152
  nextActions: [
41028
- buildNextAction(MANAGE_SQL_DATABASE, "provisionMySQL", "Provision MySQL before querying data.", { action: "provisionMySQL", confirm: true }),
41153
+ buildNextAction(MANAGE_MYSQL_DATABASE, "provisionMySQL", "Provision MySQL before querying data.", { action: "provisionMySQL", confirm: true }),
41029
41154
  ],
41030
41155
  });
41031
41156
  }
@@ -41124,7 +41249,7 @@ async function handleGetInstanceInfo(context) {
41124
41249
  nextActions: instanceInfo.exists
41125
41250
  ? undefined
41126
41251
  : [
41127
- buildNextAction(MANAGE_SQL_DATABASE, "provisionMySQL", "Provision MySQL before running SQL statements or schema initialization.", { action: "provisionMySQL", confirm: true }),
41252
+ buildNextAction(MANAGE_MYSQL_DATABASE, "provisionMySQL", "Provision MySQL before running SQL statements or schema initialization.", { action: "provisionMySQL", confirm: true }),
41128
41253
  ],
41129
41254
  });
41130
41255
  }
@@ -41135,7 +41260,7 @@ async function handleProvisionMySQL(args, context) {
41135
41260
  errorCode: "CONFIRM_REQUIRED",
41136
41261
  message: "Provisioning MySQL creates billable resources. Re-run with `confirm: true` to continue.",
41137
41262
  nextActions: [
41138
- buildNextAction(MANAGE_SQL_DATABASE, "provisionMySQL", "Explicit confirmation is required before provisioning MySQL.", { action: "provisionMySQL", confirm: true }),
41263
+ buildNextAction(MANAGE_MYSQL_DATABASE, "provisionMySQL", "Explicit confirmation is required before provisioning MySQL.", { action: "provisionMySQL", confirm: true }),
41139
41264
  ],
41140
41265
  });
41141
41266
  }
@@ -41149,7 +41274,7 @@ async function handleProvisionMySQL(args, context) {
41149
41274
  message: "A SQL database instance already exists for the current environment.",
41150
41275
  nextActions: existing.status === "READY"
41151
41276
  ? [
41152
- buildNextAction(MANAGE_SQL_DATABASE, "initializeSchema", "The instance already exists. You can initialize schema next if needed."),
41277
+ buildNextAction(MANAGE_MYSQL_DATABASE, "initializeSchema", "The instance already exists. You can initialize schema next if needed."),
41153
41278
  ]
41154
41279
  : undefined,
41155
41280
  });
@@ -41195,7 +41320,7 @@ async function handleDestroyMySQL(args, context) {
41195
41320
  errorCode: "CONFIRM_REQUIRED",
41196
41321
  message: "Destroying MySQL removes database resources. Re-run with `confirm: true` to continue.",
41197
41322
  nextActions: [
41198
- buildNextAction(MANAGE_SQL_DATABASE, "destroyMySQL", "Explicit confirmation is required before destroying MySQL.", { action: "destroyMySQL", confirm: true }),
41323
+ buildNextAction(MANAGE_MYSQL_DATABASE, "destroyMySQL", "Explicit confirmation is required before destroying MySQL.", { action: "destroyMySQL", confirm: true }),
41199
41324
  ],
41200
41325
  });
41201
41326
  }
@@ -41242,7 +41367,7 @@ async function handleDestroyMySQL(args, context) {
41242
41367
  : "MySQL destroy request was rejected.",
41243
41368
  nextActions: isSuccess
41244
41369
  ? [
41245
- buildNextAction(QUERY_SQL_DATABASE, "describeTaskStatus", "Check the MySQL destroy task status before assuming the instance is gone.", {
41370
+ buildNextAction(QUERY_MYSQL_DATABASE, "describeTaskStatus", "Check the MySQL destroy task status before assuming the instance is gone.", {
41246
41371
  action: "describeTaskStatus",
41247
41372
  request: taskRequest,
41248
41373
  }),
@@ -41265,7 +41390,7 @@ async function handleRunStatement(args, context) {
41265
41390
  errorCode: "MYSQL_NOT_CREATED",
41266
41391
  message: "MySQL is not provisioned for the current environment yet.",
41267
41392
  nextActions: [
41268
- buildNextAction(MANAGE_SQL_DATABASE, "provisionMySQL", "Provision MySQL before executing write statements or DDL.", { action: "provisionMySQL", confirm: true }),
41393
+ buildNextAction(MANAGE_MYSQL_DATABASE, "provisionMySQL", "Provision MySQL before executing write statements or DDL.", { action: "provisionMySQL", confirm: true }),
41269
41394
  ],
41270
41395
  });
41271
41396
  }
@@ -41275,7 +41400,7 @@ async function handleRunStatement(args, context) {
41275
41400
  errorCode: "MYSQL_NOT_READY",
41276
41401
  message: `MySQL is not ready yet (current status: ${instanceInfo.status}).`,
41277
41402
  nextActions: [
41278
- buildNextAction(QUERY_SQL_DATABASE, "getInstanceInfo", "Check current instance status before retrying the statement."),
41403
+ buildNextAction(QUERY_MYSQL_DATABASE, "getInstanceInfo", "Check current instance status before retrying the statement."),
41279
41404
  ],
41280
41405
  });
41281
41406
  }
@@ -41302,7 +41427,7 @@ async function handleRunStatement(args, context) {
41302
41427
  errorCode: "MYSQL_NOT_CREATED",
41303
41428
  message: "MySQL is not provisioned yet or not found. Please provision MySQL before running statements.",
41304
41429
  nextActions: [
41305
- buildNextAction(MANAGE_SQL_DATABASE, "provisionMySQL", "Provision MySQL before executing statements.", { action: "provisionMySQL", confirm: true }),
41430
+ buildNextAction(MANAGE_MYSQL_DATABASE, "provisionMySQL", "Provision MySQL before executing statements.", { action: "provisionMySQL", confirm: true }),
41306
41431
  ],
41307
41432
  });
41308
41433
  }
@@ -41331,7 +41456,7 @@ async function resolveInitializationReadiness(args, context) {
41331
41456
  errorCode: "MYSQL_NOT_CREATED",
41332
41457
  message: "MySQL is not provisioned yet. Initialize schema only after provisioning completes.",
41333
41458
  nextActions: [
41334
- buildNextAction(MANAGE_SQL_DATABASE, "provisionMySQL", "Provision MySQL before schema initialization.", { action: "provisionMySQL", confirm: true }),
41459
+ buildNextAction(MANAGE_MYSQL_DATABASE, "provisionMySQL", "Provision MySQL before schema initialization.", { action: "provisionMySQL", confirm: true }),
41335
41460
  ],
41336
41461
  }),
41337
41462
  };
@@ -41371,7 +41496,7 @@ async function resolveInitializationReadiness(args, context) {
41371
41496
  rawStatus,
41372
41497
  },
41373
41498
  nextActions: [
41374
- buildNextAction(QUERY_SQL_DATABASE, "describeTaskStatus", "Check MySQL task status until the instance becomes ready.", args.statusContext?.taskStatusRequest
41499
+ buildNextAction(QUERY_MYSQL_DATABASE, "describeTaskStatus", "Check MySQL task status until the instance becomes ready.", args.statusContext?.taskStatusRequest
41375
41500
  ? {
41376
41501
  action: "describeTaskStatus",
41377
41502
  request: args.statusContext.taskStatusRequest,
@@ -41428,7 +41553,7 @@ async function handleInitializeSchema(args, context) {
41428
41553
  errorCode: "MYSQL_NOT_CREATED",
41429
41554
  message: "MySQL is not provisioned yet or not found. Please provision MySQL before initializing schema.",
41430
41555
  nextActions: [
41431
- buildNextAction(MANAGE_SQL_DATABASE, "provisionMySQL", "Provision MySQL before executing statements.", { action: "provisionMySQL", confirm: true }),
41556
+ buildNextAction(MANAGE_MYSQL_DATABASE, "provisionMySQL", "Provision MySQL before executing statements.", { action: "provisionMySQL", confirm: true }),
41432
41557
  ],
41433
41558
  });
41434
41559
  }
@@ -41476,7 +41601,7 @@ function registerSQLDatabaseTools(server) {
41476
41601
  cloudBaseOptions,
41477
41602
  server,
41478
41603
  };
41479
- server.registerTool?.(QUERY_SQL_DATABASE, {
41604
+ server.registerTool?.(QUERY_MYSQL_DATABASE, {
41480
41605
  title: "查询 CloudBase MySQL 数据库状态或执行只读 SQL",
41481
41606
  description: "查询 CloudBase MySQL 数据库信息。支持执行只读 SQL、查询 MySQL 开通结果、查询 MySQL 任务状态,以及获取当前实例上下文信息。",
41482
41607
  inputSchema: {
@@ -41522,7 +41647,7 @@ function registerSQLDatabaseTools(server) {
41522
41647
  throw new Error(`Unsupported SQL query action: ${args.action}`);
41523
41648
  }
41524
41649
  });
41525
- server.registerTool?.(MANAGE_SQL_DATABASE, {
41650
+ server.registerTool?.(MANAGE_MYSQL_DATABASE, {
41526
41651
  title: "管理 CloudBase MySQL 数据库生命周期或执行写入 SQL",
41527
41652
  description: "管理 CloudBase MySQL 数据库资源。支持开通 MySQL、销毁 MySQL、执行写入 SQL/DDL,以及初始化数据库 Schema。注意:必须先开通 MySQL(action=provisionMySQL,confirm=true)才能执行 runStatement 或 initializeSchema。若 MySQL 尚未开通,工具会返回 MYSQL_NOT_CREATED 并给出开通的 nextAction 提示。",
41528
41653
  inputSchema: {
@@ -103269,6 +103394,7 @@ const DEFAULT_PLUGINS = [
103269
103394
  "database",
103270
103395
  "pg_database",
103271
103396
  "pg_storage",
103397
+ "mysql_database",
103272
103398
  "functions",
103273
103399
  "hosting",
103274
103400
  "storage",
@@ -103291,10 +103417,6 @@ function registerDatabase(server) {
103291
103417
  if (!(0, tencent_cloud_js_1.isInternationalRegion)(region)) {
103292
103418
  (0, databaseNoSQL_js_1.registerDatabaseTools)(server);
103293
103419
  }
103294
- const pgPluginEnabled = server.enabledPlugins?.some((pluginName) => pluginName === "pg_database" || pluginName === "pg_storage");
103295
- if (!pgPluginEnabled) {
103296
- (0, databaseSQL_js_1.registerSQLDatabaseTools)(server);
103297
- }
103298
103420
  (0, dataModel_js_1.registerDataModelTools)(server);
103299
103421
  }
103300
103422
  function registerMysqlDatabase(server) {
@@ -113912,18 +114034,31 @@ function checkIfAgentProject(projectPath) {
113912
114034
  }
113913
114035
  }
113914
114036
  /**
113915
- * Validate and normalize file path
114037
+ * Validate and normalize file path.
114038
+ * Accepts absolute paths as-is; for relative paths, resolves against CWD and
114039
+ * ensures the result does not escape the CWD (path-traversal protection).
113916
114040
  * @param inputPath User provided path
113917
114041
  * @returns Absolute path
113918
114042
  */
113919
114043
  function validateAndNormalizePath(inputPath) {
113920
- let normalizedPath = path_1.default.resolve(inputPath);
113921
- // Security check - ensure path is within current working directory
114044
+ const normalizedPath = path_1.default.resolve(inputPath);
114045
+ // On Windows, path.resolve may return a path on a different drive/UNC share.
114046
+ // That is safe — the user explicitly provided an absolute path there.
114047
+ // Only apply the traversal check when the resolved path shares the same root
114048
+ // as CWD (i.e. the path was relative or on the same drive).
113922
114049
  const cwd = process.cwd();
113923
- const prefix = cwd.endsWith(path_1.default.sep) ? cwd : cwd + path_1.default.sep;
113924
- if (!normalizedPath.startsWith(prefix) && normalizedPath !== cwd) {
113925
- throw new Error(`Path must be within current working directory: ${cwd}`);
113926
- }
114050
+ const cwdRoot = path_1.default.parse(cwd).root;
114051
+ const pathRoot = path_1.default.parse(normalizedPath).root;
114052
+ if (cwdRoot === pathRoot) {
114053
+ // Same filesystem root — ensure the resolved path is still inside CWD
114054
+ // (or is exactly CWD) to block "../" traversal.
114055
+ const prefix = cwd.endsWith(path_1.default.sep) ? cwd : cwd + path_1.default.sep;
114056
+ if (!normalizedPath.startsWith(prefix) && normalizedPath !== cwd) {
114057
+ throw new Error(`Path must be within current working directory: ${cwd}`);
114058
+ }
114059
+ }
114060
+ // Cross-root absolute paths (e.g. D:\ on Windows when CWD is C:\) are
114061
+ // allowed — the user own the machine and the path is explicitly absolute.
113927
114062
  return normalizedPath;
113928
114063
  }
113929
114064
  function buildManageCloudRunErrorMessage(action, serverName, error) {
@@ -136672,7 +136807,7 @@ class TelemetryReporter {
136672
136807
  const nodeVersion = process.version; // Node.js版本
136673
136808
  const arch = os_1.default.arch(); // 系统架构
136674
136809
  // 从构建时注入的版本号获取MCP版本信息
136675
- const mcpVersion = process.env.npm_package_version || "2.23.5" || 0;
136810
+ const mcpVersion = process.env.npm_package_version || "2.23.7" || 0;
136676
136811
  return {
136677
136812
  userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
136678
136813
  deviceId: this.deviceId,
@@ -196457,7 +196592,7 @@ ${envIdSection}
196457
196592
  ## 环境信息
196458
196593
  - 操作系统: ${os_1.default.type()} ${os_1.default.release()}
196459
196594
  - Node.js版本: ${process.version}
196460
- - MCP 版本:${process.env.npm_package_version || "2.23.5" || 0}
196595
+ - MCP 版本:${process.env.npm_package_version || "2.23.7" || 0}
196461
196596
  - 系统架构: ${os_1.default.arch()}
196462
196597
  - 时间: ${new Date().toISOString()}
196463
196598
  - 请求ID: ${requestId}
@@ -196538,7 +196673,7 @@ function createWrappedHandler(name, handler, server) {
196538
196673
  requestId: (typeof error === 'object' && error && 'requestId' in error) ? error.requestId : '',
196539
196674
  ide: server.ide || process.env.INTEGRATION_IDE || ''
196540
196675
  });
196541
- const mcpVersion = true ? "2.23.5" : 0;
196676
+ const mcpVersion = true ? "2.23.7" : 0;
196542
196677
  const requestIdSuffix = requestId ? `\n🆔 RequestId: ${requestId}` : '';
196543
196678
  const enhancedErrorMessage = `${errorMessage}${requestIdSuffix}\n\n📦 CloudBase MCP v${mcpVersion}\n🔗 遇到问题?请复制以下链接到浏览器打开\n即可自动携带错误详情快速创建 GitHub Issue:\n${issueLink}`;
196544
196679
  // 创建新的错误对象,保持原有的错误类型但更新消息
@@ -211744,7 +211879,7 @@ function registerPermissionTools(server) {
211744
211879
  }));
211745
211880
  server.registerTool?.("managePermissions", {
211746
211881
  title: "管理 CloudBase 权限与用户配置",
211747
- description: "管理 CloudBase 权限与用户配置,支持修改资源权限(数据库/云函数/存储桶等)、角色管理、成员与策略增删、应用用户 CRUD。\n\n示例:\n- 设置存储桶为私有:`action=\"updateResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\", permission=\"PRIVATE\"`\n- 创建角色:`action=\"createRole\", roleName=\"admin\", roleIdentity=\"admin\"`\n\n注意:`createUser` / `updateUser` 是环境侧应用用户管理能力,适合测试账号、管理员或预置用户,不应替代浏览器里的 Web SDK 注册表单;前端用户名密码注册应使用 `auth.signUp({ username, password })`,登录应使用 `auth.signInWithPassword({ username, password })`。直接在浏览器里用 `auth.signUp` 创建用户名密码用户取决于 SDK/provider 支持,使用前必须验证;不支持时应走后端或管理端边界,不能在浏览器暴露密钥。`securityRule` 的详细语义取决于 `resourceType`:`doc._openid`、`auth.openid`、查询条件子集校验,以及 `create` / `update` / `delete` JSON 模板仅适用于 `resourceType=\"noSqlDatabase\"` 的文档数据库安全规则;配置 `function` 或 `storage` 时,请参考各自官方安全规则文档,而不是复用 NoSQL 模板。\n\n📌 跨后端边界提示:调用前先用 `envQuery(action=\"info\", envId=...)` 看 `EnvInfo.RuntimeBackends`:\n- `resourceType=\"noSqlDatabase\"` 仅作用于 CloudBase NoSQL 文档数据库的集合;CloudBase PostgreSQL(PG)表的行级权限**不**受它控制——PG 表请改用 RLS:`managePgDatabase(action=\"execute\", confirm=true)` 跑 `ALTER TABLE ... ENABLE ROW LEVEL SECURITY` 与 `CREATE POLICY ...`。同一个 PG 环境里如果还有 NoSQL 集合在用,对那些**集合**继续使用 `noSqlDatabase` 规则是正确的——不是\"PG 环境就禁用本工具\"。\n- `resourceType=\"storage\"` 控制的是 NoSQL/COS 存储桶 ACL;PG 的 `pgstore` bucket 不在此 `resourceType` 覆盖范围内。\n- 本工具不涉及 MySQL;MySQL 数据库权限请走 MySQL 自身的 GRANT/REVOKE 语句(通过 `manageSqlDatabase`)。",
211882
+ description: "管理 CloudBase 权限与用户配置,支持修改资源权限(数据库/云函数/存储桶等)、角色管理、成员与策略增删、应用用户 CRUD。\n\n示例:\n- 设置存储桶为私有:`action=\"updateResourcePermission\", resourceType=\"storage\", resourceId=\"bucket-name\", permission=\"PRIVATE\"`\n- 创建角色:`action=\"createRole\", roleName=\"admin\", roleIdentity=\"admin\"`\n\n注意:`createUser` / `updateUser` 是环境侧应用用户管理能力,适合测试账号、管理员或预置用户,不应替代浏览器里的 Web SDK 注册表单;前端用户名密码注册应使用 `auth.signUp({ username, password })`,登录应使用 `auth.signInWithPassword({ username, password })`。直接在浏览器里用 `auth.signUp` 创建用户名密码用户取决于 SDK/provider 支持,使用前必须验证;不支持时应走后端或管理端边界,不能在浏览器暴露密钥。`securityRule` 的详细语义取决于 `resourceType`:`doc._openid`、`auth.openid`、查询条件子集校验,以及 `create` / `update` / `delete` JSON 模板仅适用于 `resourceType=\"noSqlDatabase\"` 的文档数据库安全规则;配置 `function` 或 `storage` 时,请参考各自官方安全规则文档,而不是复用 NoSQL 模板。\n\n📌 跨后端边界提示:调用前先用 `envQuery(action=\"info\", envId=...)` 看 `EnvInfo.RuntimeBackends`:\n- `resourceType=\"noSqlDatabase\"` 仅作用于 CloudBase NoSQL 文档数据库的集合;CloudBase PostgreSQL(PG)表的行级权限**不**受它控制——PG 表请改用 RLS:`managePgDatabase(action=\"execute\", confirm=true)` 跑 `ALTER TABLE ... ENABLE ROW LEVEL SECURITY` 与 `CREATE POLICY ...`。同一个 PG 环境里如果还有 NoSQL 集合在用,对那些**集合**继续使用 `noSqlDatabase` 规则是正确的——不是\"PG 环境就禁用本工具\"。\n- `resourceType=\"storage\"` 控制的是 NoSQL/COS 存储桶 ACL;PG 的 `pgstore` bucket 不在此 `resourceType` 覆盖范围内。\n- 本工具不涉及 MySQL;MySQL 数据库权限请走 MySQL 自身的 GRANT/REVOKE 语句(通过 `manageMysqlDatabase`)。",
211748
211883
  inputSchema: {
211749
211884
  action: zod_1.z.enum(MANAGE_PERMISSION_ACTIONS),
211750
211885
  resourceType: zod_1.z
@@ -212552,7 +212687,7 @@ function registerSetupTools(server) {
212552
212687
  server.registerTool("downloadTemplate", {
212553
212688
  title: "下载项目模板",
212554
212689
  description: `自动下载并部署CloudBase项目模板。
212555
- **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.23.5" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
212690
+ **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.23.7" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
212556
212691
  inputSchema: {
212557
212692
  template: zod_1.z
212558
212693
  .enum(["react", "vue", "miniprogram", "uniapp", "rules"])
@@ -229973,6 +230108,7 @@ function registerGatewayTools(server) {
229973
230108
  const cloudbase = await getManager();
229974
230109
  const accessPath = input.path ? normalizeAccessPath(input.path) : undefined;
229975
230110
  let resolvedAccessId = input.accessId;
230111
+ let resolvedName;
229976
230112
  if (!resolvedAccessId) {
229977
230113
  if (!input.targetName && !accessPath) {
229978
230114
  throw new Error("action=deleteAccess 时至少需要提供 accessId,或提供 targetName/path 用于定位入口");
@@ -229994,18 +230130,32 @@ function registerGatewayTools(server) {
229994
230130
  throw new Error("匹配到多个访问入口,请补充 path 或直接传 accessId");
229995
230131
  }
229996
230132
  resolvedAccessId = candidates[0]?.APIId;
230133
+ resolvedName = candidates[0]?.Name;
230134
+ }
230135
+ else {
230136
+ // 仅传入 accessId 时,先查询获取 name 等信息,确保删除参数完整
230137
+ try {
230138
+ const accessList = await cloudbase.access.getAccessList({});
230139
+ const match = (accessList.APISet ?? []).find((item) => item.APIId === resolvedAccessId);
230140
+ if (match) {
230141
+ resolvedName = match.Name;
230142
+ }
230143
+ }
230144
+ catch {
230145
+ // 查询失败不影响主流程,继续用 accessId 删除
230146
+ }
229997
230147
  }
229998
230148
  if (!resolvedAccessId) {
229999
230149
  throw new Error("无法解析访问入口 accessId,请改为显式传入 accessId");
230000
230150
  }
230001
230151
  const result = await cloudbase.access.deleteAccess({
230002
- ...(input.targetName ? { name: input.targetName } : {}),
230152
+ ...(resolvedName ? { name: resolvedName } : {}),
230003
230153
  apiId: resolvedAccessId,
230004
230154
  });
230005
230155
  (0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
230006
230156
  return buildEnvelope({
230007
230157
  action: input.action,
230008
- targetName: input.targetName ?? null,
230158
+ targetName: resolvedName ?? input.targetName ?? null,
230009
230159
  path: accessPath ?? null,
230010
230160
  accessId: resolvedAccessId,
230011
230161
  raw: result,