@cloudbase/cloudbase-mcp 2.32.0 → 2.32.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3474,7 +3474,7 @@ ${envIdSection}
3474
3474
  ## 环境信息
3475
3475
  - 操作系统: ${os_1.default.type()} ${os_1.default.release()}
3476
3476
  - Node.js版本: ${process.version}
3477
- - MCP 版本:${process.env.npm_package_version || ( true ? "2.32.0" : 0)}
3477
+ - MCP 版本:${process.env.npm_package_version || ( true ? "2.32.1" : 0)}
3478
3478
  - 系统架构: ${os_1.default.arch()}
3479
3479
  - 时间: ${new Date().toISOString()}
3480
3480
  - 请求ID: ${requestId}
@@ -3555,7 +3555,7 @@ function createWrappedHandler(name, handler, server) {
3555
3555
  requestId: (typeof error === 'object' && error && 'requestId' in error) ? error.requestId : '',
3556
3556
  ide: server.ide || process.env.INTEGRATION_IDE || ''
3557
3557
  });
3558
- const mcpVersion = true ? "2.32.0" : 0;
3558
+ const mcpVersion = true ? "2.32.1" : 0;
3559
3559
  const requestIdSuffix = requestId ? `\n🆔 RequestId: ${requestId}` : '';
3560
3560
  const enhancedErrorMessage = `${errorMessage}${requestIdSuffix}\n\n📦 CloudBase MCP v${mcpVersion}\n🔗 遇到问题?请复制以下链接到浏览器打开\n即可自动携带错误详情快速创建 GitHub Issue:\n${issueLink}`;
3561
3561
  // 创建新的错误对象,保持原有的错误类型但更新消息
@@ -13752,7 +13752,7 @@ class TelemetryReporter {
13752
13752
  const arch = os_1.default.arch(); // 系统架构
13753
13753
  // Build-time injected version; guard for vitest / non-webpack runtimes.
13754
13754
  const mcpVersion = process.env.npm_package_version ||
13755
- ( true ? "2.32.0" : 0);
13755
+ ( true ? "2.32.1" : 0);
13756
13756
  return {
13757
13757
  userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
13758
13758
  deviceId: this.deviceId,
@@ -19659,7 +19659,7 @@ function registerSetupTools(server) {
19659
19659
  server.registerTool("downloadTemplate", {
19660
19660
  title: "下载项目模板",
19661
19661
  description: `自动下载并部署CloudBase项目模板。
19662
- **Note**: Call this tool when the user requests to create a new project using a CloudBase template.\n\n支持的模板:\n- react: React + CloudBase 全栈应用模板\n- vue: Vue + CloudBase 全栈应用模板\n- miniprogram: 微信小程序 + 云开发模板 \n- uniapp: UniApp + CloudBase 跨端应用模板\n- rules: 只包含AI编辑器配置文件(包含Cursor、WindSurf、CodeBuddy等所有主流编辑器配置),适合在已有项目中补充AI编辑器配置\n\n支持的IDE类型:\n- all: 下载所有IDE配置\n- cursor: Cursor AI编辑器\n- 其他IDE类型见下方列表\n\n注意:如果未传入 ide 参数且无法从环境变量检测到 IDE,将提示错误并要求传入 ide 参数\n- windsurf: WindSurf AI编辑器\n- codebuddy: CodeBuddy AI编辑器\n- claude-code: Claude Code AI编辑器\n- cline: Cline AI编辑器\n- gemini-cli: Gemini CLI\n- opencode: OpenCode AI编辑器\n- qwen-code: 通义灵码\n- baidu-comate: 百度Comate\n- openai-codex-cli: OpenAI Codex CLI\n- augment-code: Augment Code\n- github-copilot: GitHub Copilot\n- roocode: RooCode AI编辑器\n- tongyi-lingma: 通义灵码\n- trae: Trae AI编辑器\n- qoder: Qoder AI编辑器\n- antigravity: Google Antigravity AI编辑器\n- vscode: Visual Studio Code\n- kiro: Kiro AI编辑器\n- aider: Aider AI编辑器\n\n特别说明:\n- rules 模板会自动包含当前 mcp 版本号信息(版本号:${ true ? "2.32.0" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
19662
+ **Note**: Call this tool when the user requests to create a new project using a CloudBase template.\n\n支持的模板:\n- react: React + CloudBase 全栈应用模板\n- vue: Vue + CloudBase 全栈应用模板\n- miniprogram: 微信小程序 + 云开发模板 \n- uniapp: UniApp + CloudBase 跨端应用模板\n- rules: 只包含AI编辑器配置文件(包含Cursor、WindSurf、CodeBuddy等所有主流编辑器配置),适合在已有项目中补充AI编辑器配置\n\n支持的IDE类型:\n- all: 下载所有IDE配置\n- cursor: Cursor AI编辑器\n- 其他IDE类型见下方列表\n\n注意:如果未传入 ide 参数且无法从环境变量检测到 IDE,将提示错误并要求传入 ide 参数\n- windsurf: WindSurf AI编辑器\n- codebuddy: CodeBuddy AI编辑器\n- claude-code: Claude Code AI编辑器\n- cline: Cline AI编辑器\n- gemini-cli: Gemini CLI\n- opencode: OpenCode AI编辑器\n- qwen-code: 通义灵码\n- baidu-comate: 百度Comate\n- openai-codex-cli: OpenAI Codex CLI\n- augment-code: Augment Code\n- github-copilot: GitHub Copilot\n- roocode: RooCode AI编辑器\n- tongyi-lingma: 通义灵码\n- trae: Trae AI编辑器\n- qoder: Qoder AI编辑器\n- antigravity: Google Antigravity AI编辑器\n- vscode: Visual Studio Code\n- kiro: Kiro AI编辑器\n- aider: Aider AI编辑器\n\n特别说明:\n- rules 模板会自动包含当前 mcp 版本号信息(版本号:${ true ? "2.32.1" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
19663
19663
  inputSchema: {
19664
19664
  template: zod_1.z
19665
19665
  .enum(["react", "vue", "miniprogram", "uniapp", "rules"])
@@ -22279,6 +22279,8 @@ exports.QbaseError = exports.MSG_TYPES = exports.XPAY_EVENT_TYPES = void 0;
22279
22279
  exports.mergeSubscribeList = mergeSubscribeList;
22280
22280
  exports.mergeUnsubscribeList = mergeUnsubscribeList;
22281
22281
  exports.mergeSetEnableList = mergeSetEnableList;
22282
+ exports.resolvePushMode = resolvePushMode;
22283
+ exports.pickContainerConfigPublic = pickContainerConfigPublic;
22282
22284
  exports.registerMsgPushTools = registerMsgPushTools;
22283
22285
  const zod_1 = __webpack_require__(2971);
22284
22286
  const tool_result_js_1 = __webpack_require__(9835);
@@ -22565,6 +22567,25 @@ async function uploadCallbackConfig(server, appid, state) {
22565
22567
  throw new QbaseError(ret, `uploadappconfig 失败(ret=${ret}): ${errmsg || "未知错误"}。请重新查询最新配置后重试。`);
22566
22568
  }
22567
22569
  }
22570
+ function resolvePushMode(container) {
22571
+ return container?.qbase_open === true ? "container" : "cloudfunction";
22572
+ }
22573
+ /** Public subset of container callback fields returned to agents */
22574
+ function pickContainerConfigPublic(container) {
22575
+ if (!container)
22576
+ return undefined;
22577
+ return {
22578
+ qbase_open: container.qbase_open === true,
22579
+ qbase_container_path: typeof container.qbase_container_path === "string"
22580
+ ? container.qbase_container_path
22581
+ : undefined,
22582
+ qbase_env: typeof container.qbase_env === "string" ? container.qbase_env : undefined,
22583
+ text_mode: typeof container.text_mode === "number" ? container.text_mode : undefined,
22584
+ };
22585
+ }
22586
+ const CONTAINER_MODE_BLOCK_NOTE = "当前为云托管模式(整包接收),云函数 callbacks 存在但不生效;如需云函数模式请调 ensureCloudFunctionMode 切换";
22587
+ const CONTAINER_MODE_WRITE_ERROR = "当前 pushMode=container(云托管整包接收),云函数回调配置存在但不生效。" +
22588
+ "如需云函数模式请调 action=ensureCloudFunctionMode 切换。";
22568
22589
  /** 读取云托管消息推送配置;无配置(云函数模式)返回 null */
22569
22590
  async function readContainerConfig(server, appid) {
22570
22591
  const resp = await callQbase(server, appid, "getContainerCallbackConfig", {});
@@ -22585,6 +22606,55 @@ async function setContainerConfig(server, appid, cfg) {
22585
22606
  throw new QbaseError(ret, `setcontainercallbackconfig 失败(ret=${ret}): ${resp.base_resp?.errmsg ?? "未知错误"}`);
22586
22607
  }
22587
22608
  }
22609
+ function buildContainerModeBlockedPayload(action) {
22610
+ return (0, tool_result_js_1.buildJsonToolResult)({
22611
+ ok: false,
22612
+ code: "CONTAINER_MODE_ACTIVE",
22613
+ pushMode: "container",
22614
+ message: CONTAINER_MODE_WRITE_ERROR,
22615
+ next_step: {
22616
+ tool: "manageMessagePush",
22617
+ action: "ensureCloudFunctionMode",
22618
+ required_params: ["appid", "env_id", "function_name", "confirm"],
22619
+ hint: `先切换到云函数模式后再执行 ${action}`,
22620
+ },
22621
+ });
22622
+ }
22623
+ /**
22624
+ * Verify function_name exists in envId via optional host hook or CloudBase Manager list.
22625
+ * Returns an error tool result when missing / unreadable; null when OK.
22626
+ */
22627
+ async function assertCloudFunctionExists(server, envId, functionName) {
22628
+ const override = server.pluginOptions?.msgPush?.listCloudFunctions;
22629
+ // 兼容性降级:host 未提供 listCloudFunctions hook(如微信 IDE 无腾讯云凭据)时
22630
+ // 跳过存在性校验,保持原有 subscribe 行为(写配置不阻断);仅 host 显式启用时校验。
22631
+ if (!override) {
22632
+ return null;
22633
+ }
22634
+ let names;
22635
+ try {
22636
+ names = await override(envId);
22637
+ }
22638
+ catch (e) {
22639
+ // hook 本身失败(如网络/权限)时降级放行,不阻断订阅
22640
+ return null;
22641
+ }
22642
+ if (!names.includes(functionName)) {
22643
+ return (0, tool_result_js_1.buildJsonToolResult)({
22644
+ ok: false,
22645
+ code: "FUNCTION_NOT_FOUND",
22646
+ message: `云函数 ${functionName} 不存在于环境 ${envId},请先创建或修正参数`,
22647
+ envId,
22648
+ function_name: functionName,
22649
+ next_step: {
22650
+ tool: "manageFunctions",
22651
+ action: "createFunction",
22652
+ required_params: ["functionName"],
22653
+ },
22654
+ });
22655
+ }
22656
+ return null;
22657
+ }
22588
22658
  function buildTransportUnavailablePayload(toolName, action) {
22589
22659
  return (0, tool_result_js_1.buildJsonToolResult)({
22590
22660
  ok: false,
@@ -22653,11 +22723,11 @@ function registerMsgPushTools(server) {
22653
22723
  server.registerTool?.("queryMessagePush", {
22654
22724
  title: "查询小程序消息推送配置",
22655
22725
  description: "查询小程序云开发消息推送配置(qbase getappconfig)或全部合法消息推送事件约束(getcallbacksupportlist)。" +
22656
- "消息推送把小程序事件/消息(含虚拟支付回调、text/image 等消息类型)送到云函数,无需自建服务器。" +
22657
- "action=list 返回当前配置列表(msgType/event/env/functionName/enable)与 version(乐观锁版本号);" +
22658
- "action=listSupportedEvents 返回全部合法约束(按消息类型分组:event 组含事件名列表;text/image/voice/video/miniprogrampage 组 events 为空数组)," +
22659
- "事件类用 manageMessagePush(event_types=...),消息类型用 manageMessagePush(msg_type=...)。" +
22660
- "需要微信 IDE 登录态通道(宿主注入 cloudBaseOptions.requestFn),独立 CloudBase MCP 运行会返回指引错误。",
22726
+ "推送模式有两种:云函数(默认,按 (msgType,event) 逐条回调)与云托管(qbase_open=true,整包接收所有消息到容器 path)。" +
22727
+ "action=list 同时返回 pushMode(cloudfunction|container)、containerConfig、callbacks 与 version;" +
22728
+ "云托管模式下 callbacks 可能仍存在但不生效(见 note),需 ensureCloudFunctionMode 切回云函数模式后才会按回调推送。" +
22729
+ "action=listSupportedEvents 返回全部合法约束(按消息类型分组)。" +
22730
+ "需要微信 IDE 登录态通道(宿主注入 cloudBaseOptions.requestFn)。",
22661
22731
  inputSchema: {
22662
22732
  appid: zod_1.z
22663
22733
  .string()
@@ -22665,7 +22735,7 @@ function registerMsgPushTools(server) {
22665
22735
  env: zod_1.z.string().optional().describe("可选:环境 ID;传入时 list 仅返回该环境的订阅条目"),
22666
22736
  action: zod_1.z
22667
22737
  .enum(["list", "listSupportedEvents"])
22668
- .describe("list: 查询当前消息推送配置列表\nlistSupportedEvents: 查询全部合法消息推送事件约束(按 msgType 分组)"),
22738
+ .describe("list: 查询当前消息推送配置列表(含 pushMode/containerConfig)\nlistSupportedEvents: 查询全部合法消息推送事件约束(按 msgType 分组)"),
22669
22739
  },
22670
22740
  annotations: {
22671
22741
  readOnlyHint: true,
@@ -22677,7 +22747,11 @@ function registerMsgPushTools(server) {
22677
22747
  return buildTransportUnavailablePayload("queryMessagePush", action);
22678
22748
  }
22679
22749
  if (action === "list") {
22680
- const state = await readCallbackConfig(server, appid);
22750
+ const [state, container] = await Promise.all([
22751
+ readCallbackConfig(server, appid),
22752
+ readContainerConfig(server, appid),
22753
+ ]);
22754
+ const pushMode = resolvePushMode(container);
22681
22755
  const callbacks = env
22682
22756
  ? state.list.filter((c) => c.env === env)
22683
22757
  : state.list;
@@ -22687,12 +22761,22 @@ function registerMsgPushTools(server) {
22687
22761
  message: "查询消息推送配置成功",
22688
22762
  version: state.version,
22689
22763
  enable: state.enable,
22764
+ pushMode,
22765
+ containerConfig: pickContainerConfigPublic(container),
22690
22766
  callbacks,
22767
+ note: pushMode === "container" ? CONTAINER_MODE_BLOCK_NOTE : undefined,
22691
22768
  filteredByEnv: env ?? undefined,
22692
- next_steps: [
22693
- "manageMessagePush(action=subscribe) 订阅事件(缺省 event_types 时默认订阅虚拟支付 7 事件)",
22694
- "queryMessagePush(action=listSupportedEvents) 查看全部合法事件",
22695
- ],
22769
+ next_steps: pushMode === "container"
22770
+ ? [
22771
+ "当前为云托管模式:云函数 subscribe/unsubscribe/setEnable 会被拒绝",
22772
+ "manageMessagePush(action=ensureCloudFunctionMode) 切回云函数模式",
22773
+ "manageMessagePush(action=setContainerCallback) 更新云托管 path/env/text_mode",
22774
+ ]
22775
+ : [
22776
+ "manageMessagePush(action=subscribe) 订阅事件(缺省 event_types 时默认订阅虚拟支付 7 事件)",
22777
+ "manageMessagePush(action=ensureContainerMode) 切换到云托管整包接收",
22778
+ "queryMessagePush(action=listSupportedEvents) 查看全部合法事件",
22779
+ ],
22696
22780
  });
22697
22781
  }
22698
22782
  if (action === "listSupportedEvents") {
@@ -22737,29 +22821,38 @@ function registerMsgPushTools(server) {
22737
22821
  server.registerTool?.("manageMessagePush", {
22738
22822
  title: "管理小程序消息推送配置",
22739
22823
  description: "管理小程序云开发消息推送配置(写操作,需 confirm=\"yes\" 确认)。" +
22740
- "基于「读全量 → merge → 全量覆盖(带 version 乐观锁)」实现声明式幂等(对齐 kubectl apply:event_types 是期望集合,重复执行收敛到同一状态;" +
22741
- "version 冲突即 RFC 7232 If-Match 412,返回可重试错误:重读 → merge → 重试)。" +
22742
- "msg_type 区分两类条目(缺省 \"event\",向后兼容):" +
22743
- "msg_type=\"event\" 操作事件类(需 event_types;subscribe 缺省时默认虚拟支付 7 个 xpay_* 事件);" +
22744
- "msg_type=\"text\"|\"image\"|\"voice\"|\"video\"|\"miniprogrampage\" 操作消息类型条目(event 固定空串,勿传 event_types)。" +
22745
- "action=subscribe 订阅到指定云函数;同一 (msgType,event) 只能推到一个云函数(一事一函数),已绑定其他函数会自动重绑并说明。" +
22746
- "action=unsubscribe 移除匹配订阅(msg_type=event 时 event_types 必填;消息类型时按 msg_type 移除)。" +
22747
- "action=setEnable 启用/停用匹配订阅(msg_type=event 时 event_types + enable 必填;消息类型时 msg_type + enable)。" +
22748
- "action=ensureCloudFunctionMode 确保推送模式为云函数(若为云托管整包接收则切换 qbase_open=false,需确认)。" +
22749
- "集合无变化时不发起写请求(幂等 no-op,无需确认)。" +
22750
- "需要微信 IDE 登录态通道(宿主注入 cloudBaseOptions.requestFn)。",
22824
+ "推送模式:云函数(默认,按 (msgType,event) 回调)vs 云托管(整包接收;云托管模式下 subscribe/unsubscribe/setEnable 会被拒绝,先 ensureCloudFunctionMode)。" +
22825
+ "基于「读全量 → merge → 全量覆盖(带 version 乐观锁)」实现声明式幂等。" +
22826
+ "msg_type 缺省 \"event\";消息类型用 msg_type=text|image|voice|video|miniprogrampage。" +
22827
+ "action=subscribe 前会校验 function_name 在环境中真实存在。" +
22828
+ "action=ensureCloudFunctionMode 关闭云托管整包接收;action=ensureContainerMode 开启云托管(需 qbase_container_path/qbase_env/text_mode);" +
22829
+ "action=setContainerCallback 更新云托管 path/env/text_mode。" +
22830
+ "集合无变化时不发起写请求(幂等 no-op)。需要微信 IDE 登录态通道。",
22751
22831
  inputSchema: {
22752
22832
  appid: zod_1.z
22753
22833
  .string()
22754
22834
  .describe("小程序 AppID(必填,与微信开发者工具一致;用于选择微信登录态会话)"),
22755
- env_id: zod_1.z.string().describe("环境 ID(订阅条目绑定的云开发环境)"),
22756
- function_name: zod_1.z.string().describe("接收消息推送的云函数名"),
22835
+ env_id: zod_1.z
22836
+ .string()
22837
+ .describe("环境 ID(云函数订阅绑定的云开发环境;ensureContainerMode/setContainerCallback 未传 qbase_env 时也可作为云托管环境默认值)"),
22838
+ function_name: zod_1.z
22839
+ .string()
22840
+ .describe("接收消息推送的云函数名(subscribe/unsubscribe/setEnable/ensureCloudFunctionMode 使用;云托管相关 action 可传占位)"),
22757
22841
  action: zod_1.z
22758
- .enum(["subscribe", "unsubscribe", "setEnable", "ensureCloudFunctionMode"])
22759
- .describe("subscribe: 订阅到指定云函数(msg_type=event 时 event_types 缺省=虚拟支付 7 事件;消息类型时按 msg_type 订阅)\n" +
22760
- "unsubscribe: 移除匹配订阅(msg_type=event 时 event_types 必填)\n" +
22761
- "setEnable: 启用/停用匹配订阅(msg_type=event 时 event_types + enable 必填)\n" +
22762
- "ensureCloudFunctionMode: 确保为云函数推送模式(云托管整包接收时切换,需确认)"),
22842
+ .enum([
22843
+ "subscribe",
22844
+ "unsubscribe",
22845
+ "setEnable",
22846
+ "ensureCloudFunctionMode",
22847
+ "ensureContainerMode",
22848
+ "setContainerCallback",
22849
+ ])
22850
+ .describe("subscribe: 订阅到指定云函数(云托管模式下拒绝)\n" +
22851
+ "unsubscribe: 移除匹配订阅(云托管模式下拒绝)\n" +
22852
+ "setEnable: 启用/停用匹配订阅(云托管模式下拒绝)\n" +
22853
+ "ensureCloudFunctionMode: 切到云函数推送模式(关闭 qbase_open)\n" +
22854
+ "ensureContainerMode: 切到云托管整包接收(需 qbase_container_path + text_mode)\n" +
22855
+ "setContainerCallback: 更新云托管回调 path/env/text_mode"),
22763
22856
  msg_type: zod_1.z
22764
22857
  .enum(exports.MSG_TYPES)
22765
22858
  .optional()
@@ -22770,10 +22863,20 @@ function registerMsgPushTools(server) {
22770
22863
  .array(zod_1.z.string())
22771
22864
  .optional()
22772
22865
  .describe("要操作的事件列表(仅 msg_type=\"event\" 时使用;可先 queryMessagePush(action=listSupportedEvents) 查询全量约束)。" +
22773
- "subscribe 缺省时默认订阅虚拟支付 7 个事件:xpay_goods_deliver_notify、xpay_coin_pay_notify、xpay_complaint_notify、" +
22774
- "xpay_subscribe_signing_result_notify、xpay_subscribe_pay_fail_notify、xpay_subscribe_ios_refund_query_notify、xpay_refund_notify;" +
22775
- "unsubscribe / setEnable 且 msg_type=event 时必填。消息类型操作请勿传本参数。"),
22866
+ "subscribe 缺省时默认订阅虚拟支付 7 个事件;unsubscribe / setEnable 且 msg_type=event 时必填。"),
22776
22867
  enable: zod_1.z.boolean().optional().describe("setEnable 时必填:true 启用订阅 / false 停用订阅"),
22868
+ qbase_container_path: zod_1.z
22869
+ .string()
22870
+ .optional()
22871
+ .describe("云托管回调路径/URL(ensureContainerMode 必填;setContainerCallback 可选更新)"),
22872
+ qbase_env: zod_1.z
22873
+ .string()
22874
+ .optional()
22875
+ .describe("云托管服务所在环境 ID(ensureContainerMode/setContainerCallback 可选;缺省用 env_id)"),
22876
+ text_mode: zod_1.z
22877
+ .union([zod_1.z.literal(1), zod_1.z.literal(2)])
22878
+ .optional()
22879
+ .describe("云托管消息正文编码:1=json,2=xml(ensureContainerMode 必填;setContainerCallback 可选更新)"),
22777
22880
  confirm: zod_1.z
22778
22881
  .string()
22779
22882
  .optional()
@@ -22786,7 +22889,7 @@ function registerMsgPushTools(server) {
22786
22889
  openWorldHint: true,
22787
22890
  category: CATEGORY,
22788
22891
  },
22789
- }, async ({ appid, env_id, function_name, action, msg_type, event_types, enable, confirm, }) => {
22892
+ }, async ({ appid, env_id, function_name, action, msg_type, event_types, enable, qbase_container_path, qbase_env, text_mode, confirm, }) => {
22790
22893
  if (!getTransport(server)) {
22791
22894
  return buildTransportUnavailablePayload("manageMessagePush", action);
22792
22895
  }
@@ -22801,16 +22904,16 @@ function registerMsgPushTools(server) {
22801
22904
  success: true,
22802
22905
  code: "NO_CHANGE",
22803
22906
  message: "当前已是云函数推送模式(云托管整包接收未开启),无需变更",
22804
- containerConfig: current ?? undefined,
22907
+ pushMode: "cloudfunction",
22908
+ containerConfig: pickContainerConfigPublic(current),
22805
22909
  });
22806
22910
  }
22807
22911
  if (!confirmed) {
22808
22912
  return buildConfirmPayload({
22809
22913
  toolName: "manageMessagePush",
22810
22914
  action,
22811
- message: `当前推送模式为云托管整包接收(qbase_open=true,环境 ${current.qbase_env ?? "-"},路径 ${current.qbase_container_path ?? "-"}),` +
22812
- `事件会整包进入云托管而非云函数。\n即将执行 setcontainercallbackconfig 关闭云托管整包接收(qbase_open=false),` +
22813
- `使消息推送按事件进入云函数 ${env_id}/${function_name}。`,
22915
+ message: `切换后停止云托管整包接收(qbase_open=false),消息按云函数回调推送;若 callbacks 为空则收不到任何消息。\n` +
22916
+ `当前云托管配置:环境 ${current.qbase_env ?? "-"},路径 ${current.qbase_container_path ?? "-"},text_mode=${current.text_mode ?? "-"}。`,
22814
22917
  requiredParams: ["appid", "env_id", "function_name", "confirm"],
22815
22918
  });
22816
22919
  }
@@ -22830,6 +22933,140 @@ function registerMsgPushTools(server) {
22830
22933
  success: true,
22831
22934
  message: "已切换到云函数推送模式(setcontainercallbackconfig qbase_open=false 成功)",
22832
22935
  action,
22936
+ pushMode: "cloudfunction",
22937
+ });
22938
+ }
22939
+ if (action === "ensureContainerMode") {
22940
+ const path = qbase_container_path?.trim();
22941
+ const containerEnv = (qbase_env ?? env_id)?.trim();
22942
+ if (!path) {
22943
+ throw new Error('ensureContainerMode 必须提供 qbase_container_path(云托管回调路径/URL)');
22944
+ }
22945
+ if (text_mode !== 1 && text_mode !== 2) {
22946
+ throw new Error("ensureContainerMode 必须提供 text_mode(1=json / 2=xml)");
22947
+ }
22948
+ if (!containerEnv) {
22949
+ throw new Error("ensureContainerMode 必须提供 qbase_env 或 env_id(云托管服务所在环境)");
22950
+ }
22951
+ const current = await readContainerConfig(server, appid);
22952
+ const alreadySame = current?.qbase_open === true &&
22953
+ current.qbase_container_path === path &&
22954
+ current.qbase_env === containerEnv &&
22955
+ Number(current.text_mode) === text_mode;
22956
+ if (alreadySame) {
22957
+ return (0, tool_result_js_1.buildJsonToolResult)({
22958
+ ok: true,
22959
+ success: true,
22960
+ code: "NO_CHANGE",
22961
+ message: "当前已是云托管推送模式且配置一致,无需变更",
22962
+ pushMode: "container",
22963
+ containerConfig: pickContainerConfigPublic(current),
22964
+ });
22965
+ }
22966
+ if (!confirmed) {
22967
+ return buildConfirmPayload({
22968
+ toolName: "manageMessagePush",
22969
+ action,
22970
+ message: `切换后所有消息类型整包推送到云托管服务(path=${path},env=${containerEnv},text_mode=${text_mode}),云函数回调失效。\n` +
22971
+ `当前:pushMode=${resolvePushMode(current)},` +
22972
+ `path=${current?.qbase_container_path ?? "-"},env=${current?.qbase_env ?? "-"},text_mode=${current?.text_mode ?? "-"}。`,
22973
+ requiredParams: [
22974
+ "appid",
22975
+ "env_id",
22976
+ "qbase_container_path",
22977
+ "text_mode",
22978
+ "confirm",
22979
+ ],
22980
+ });
22981
+ }
22982
+ const nextCfg = {
22983
+ ...(current ?? {}),
22984
+ qbase_open: true,
22985
+ qbase_container_path: path,
22986
+ qbase_env: containerEnv,
22987
+ text_mode,
22988
+ };
22989
+ await setContainerConfig(server, appid, nextCfg);
22990
+ logger?.({
22991
+ type: "toolInfo",
22992
+ toolName: "manageMessagePush",
22993
+ message: "已切换到云托管推送模式",
22994
+ appid,
22995
+ envId: containerEnv,
22996
+ });
22997
+ return (0, tool_result_js_1.buildJsonToolResult)({
22998
+ ok: true,
22999
+ success: true,
23000
+ message: "已切换到云托管推送模式(qbase_open=true)",
23001
+ action,
23002
+ pushMode: "container",
23003
+ containerConfig: pickContainerConfigPublic(nextCfg),
23004
+ });
23005
+ }
23006
+ if (action === "setContainerCallback") {
23007
+ const current = await readContainerConfig(server, appid);
23008
+ const nextPath = qbase_container_path?.trim() ||
23009
+ (typeof current?.qbase_container_path === "string"
23010
+ ? current.qbase_container_path
23011
+ : undefined);
23012
+ const nextEnv = (qbase_env ?? env_id)?.trim() ||
23013
+ (typeof current?.qbase_env === "string" ? current.qbase_env : undefined);
23014
+ const nextTextMode = text_mode === 1 || text_mode === 2
23015
+ ? text_mode
23016
+ : typeof current?.text_mode === "number"
23017
+ ? current.text_mode
23018
+ : undefined;
23019
+ if (!nextPath) {
23020
+ throw new Error("setContainerCallback 需要 qbase_container_path(或当前已有配置可沿用)");
23021
+ }
23022
+ if (!nextEnv) {
23023
+ throw new Error("setContainerCallback 需要 qbase_env 或 env_id(或当前已有配置可沿用)");
23024
+ }
23025
+ if (nextTextMode !== 1 && nextTextMode !== 2) {
23026
+ throw new Error("setContainerCallback 需要 text_mode(1=json / 2=xml,或当前已有配置可沿用)");
23027
+ }
23028
+ const nextCfg = {
23029
+ ...(current ?? {}),
23030
+ qbase_open: current?.qbase_open === true,
23031
+ qbase_container_path: nextPath,
23032
+ qbase_env: nextEnv,
23033
+ text_mode: nextTextMode,
23034
+ };
23035
+ const same = current?.qbase_container_path === nextPath &&
23036
+ current?.qbase_env === nextEnv &&
23037
+ Number(current?.text_mode) === nextTextMode &&
23038
+ (current?.qbase_open === true) === (nextCfg.qbase_open === true);
23039
+ if (same) {
23040
+ return (0, tool_result_js_1.buildJsonToolResult)({
23041
+ ok: true,
23042
+ success: true,
23043
+ code: "NO_CHANGE",
23044
+ message: "云托管回调配置无变化(幂等)",
23045
+ pushMode: resolvePushMode(current),
23046
+ containerConfig: pickContainerConfigPublic(current),
23047
+ });
23048
+ }
23049
+ if (!confirmed) {
23050
+ const before = pickContainerConfigPublic(current) ?? {};
23051
+ const after = pickContainerConfigPublic(nextCfg) ?? {};
23052
+ return buildConfirmPayload({
23053
+ toolName: "manageMessagePush",
23054
+ action,
23055
+ message: `即将更新云托管回调配置:\n` +
23056
+ `- 旧: path=${before.qbase_container_path ?? "-"}, env=${before.qbase_env ?? "-"}, text_mode=${before.text_mode ?? "-"}, qbase_open=${before.qbase_open ?? false}\n` +
23057
+ `- 新: path=${after.qbase_container_path ?? "-"}, env=${after.qbase_env ?? "-"}, text_mode=${after.text_mode ?? "-"}, qbase_open=${after.qbase_open ?? false}`,
23058
+ requiredParams: ["appid", "confirm"],
23059
+ });
23060
+ }
23061
+ await setContainerConfig(server, appid, nextCfg);
23062
+ return (0, tool_result_js_1.buildJsonToolResult)({
23063
+ ok: true,
23064
+ success: true,
23065
+ message: "已更新云托管回调配置",
23066
+ action,
23067
+ pushMode: resolvePushMode(nextCfg),
23068
+ before: pickContainerConfigPublic(current),
23069
+ after: pickContainerConfigPublic(nextCfg),
22833
23070
  });
22834
23071
  }
22835
23072
  // Message-type entries use a fixed empty event; event_types must not be supplied
@@ -22837,6 +23074,13 @@ function registerMsgPushTools(server) {
22837
23074
  throw new Error(`msg_type="${resolvedMsgType}" 时不应传 event_types(消息类型条目的 event 固定为空串 "");` +
22838
23075
  `请去掉 event_types,仅传 msg_type / function_name / enable(setEnable 时)`);
22839
23076
  }
23077
+ // Reject cloud-function callback writes while container mode is active (silent-failure guard)
23078
+ {
23079
+ const container = await readContainerConfig(server, appid);
23080
+ if (resolvePushMode(container) === "container") {
23081
+ return buildContainerModeBlockedPayload(action);
23082
+ }
23083
+ }
22840
23084
  // subscribe / unsubscribe / setEnable 共用流程:读 → 校验 → merge → 确认 → 覆盖写
22841
23085
  let eventList;
22842
23086
  if (!isEventMsgType) {
@@ -22932,6 +23176,12 @@ function registerMsgPushTools(server) {
22932
23176
  warnings: warnings.length ? warnings : undefined,
22933
23177
  });
22934
23178
  }
23179
+ // 4b. subscribe:校验云函数真实存在(仅有变更时)
23180
+ if (action === "subscribe") {
23181
+ const missing = await assertCloudFunctionExists(server, env_id, function_name);
23182
+ if (missing)
23183
+ return missing;
23184
+ }
22935
23185
  // 5. 有变更 → 需确认
22936
23186
  const diffText = buildMergeDiffText(action, result, env_id, function_name);
22937
23187
  if (!confirmed) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudbase/cloudbase-mcp",
3
- "version": "2.32.0",
3
+ "version": "2.32.1",
4
4
  "mcpName": "io.github.TencentCloudBase/cloudbase-mcp",
5
5
  "packageManager": "pnpm@10.8.0",
6
6
  "description": "CloudBase MCP Server — operate Tencent CloudBase (database, auth, functions, storage, hosting) from AI coding tools via the Model Context Protocol. Part of CloudBase AI Toolkit.",
package/server.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "io.github.TencentCloudBase/cloudbase-mcp",
4
4
  "title": "CloudBase",
5
5
  "description": "CloudBase MCP: DB, functions, storage, hosting via @cloudbase/cloudbase-mcp",
6
- "version": "2.32.0",
6
+ "version": "2.32.1",
7
7
  "websiteUrl": "https://github.com/TencentCloudBase/CloudBase-AI-Toolkit",
8
8
  "repository": {
9
9
  "url": "https://github.com/TencentCloudBase/CloudBase-AI-Toolkit",
@@ -25,7 +25,7 @@
25
25
  "registryType": "npm",
26
26
  "registryBaseUrl": "https://registry.npmjs.org",
27
27
  "identifier": "@cloudbase/cloudbase-mcp",
28
- "version": "2.32.0",
28
+ "version": "2.32.1",
29
29
  "runtimeHint": "npx",
30
30
  "transport": {
31
31
  "type": "stdio"