@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/cli.cjs +3 -3
- package/dist/index.cjs +446 -178
- package/dist/index.js +446 -178
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -62,6 +62,8 @@ function simplifyEnvList(envList) {
|
|
|
62
62
|
simplified.EnvType = env.EnvType;
|
|
63
63
|
if (env.Region !== undefined)
|
|
64
64
|
simplified.Region = env.Region;
|
|
65
|
+
if (env.PackageId !== undefined)
|
|
66
|
+
simplified.PackageId = env.PackageId;
|
|
65
67
|
if (env.PackageName !== undefined)
|
|
66
68
|
simplified.PackageName = env.PackageName;
|
|
67
69
|
if (env.IsDefault !== undefined)
|
|
@@ -76,6 +78,7 @@ const DEFAULT_ENV_FIELDS = [
|
|
|
76
78
|
"Status",
|
|
77
79
|
"EnvType",
|
|
78
80
|
"Region",
|
|
81
|
+
"PackageId",
|
|
79
82
|
"PackageName",
|
|
80
83
|
"IsDefault",
|
|
81
84
|
];
|
|
@@ -91,10 +94,14 @@ function selectEnvFields(env, fields) {
|
|
|
91
94
|
}
|
|
92
95
|
function filterEnvList(envList, filters) {
|
|
93
96
|
const alias = filters.alias?.trim().toLowerCase();
|
|
97
|
+
const aliasExact = filters.aliasExact === true;
|
|
94
98
|
const envId = filters.envId?.trim().toLowerCase();
|
|
95
99
|
return envList.filter((env) => {
|
|
100
|
+
const normalizedAlias = String(env.Alias ?? "").toLowerCase();
|
|
96
101
|
const matchesAlias = alias
|
|
97
|
-
?
|
|
102
|
+
? aliasExact
|
|
103
|
+
? normalizedAlias === alias
|
|
104
|
+
: normalizedAlias.includes(alias)
|
|
98
105
|
: true;
|
|
99
106
|
const matchesEnvId = envId
|
|
100
107
|
? String(env.EnvId ?? "").toLowerCase() === envId
|
|
@@ -198,9 +205,17 @@ function buildEnvQueryListResult(params) {
|
|
|
198
205
|
: envList;
|
|
199
206
|
const filteredList = filterEnvList(baseList, {
|
|
200
207
|
alias: params.filters.alias,
|
|
208
|
+
aliasExact: params.filters.aliasExact,
|
|
201
209
|
envId: params.filters.envId,
|
|
202
210
|
});
|
|
203
211
|
const paginated = paginateEnvList(filteredList, params.filters.offset, params.filters.limit);
|
|
212
|
+
const exactEnvIdSummaryHint = params.filters.envId
|
|
213
|
+
? {
|
|
214
|
+
tool: "envQuery",
|
|
215
|
+
action: "info",
|
|
216
|
+
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.",
|
|
217
|
+
}
|
|
218
|
+
: undefined;
|
|
204
219
|
return {
|
|
205
220
|
EnvList: paginated.items.map((env) => selectEnvFields(env, params.filters.fields)),
|
|
206
221
|
TotalCount: paginated.total,
|
|
@@ -209,12 +224,58 @@ function buildEnvQueryListResult(params) {
|
|
|
209
224
|
HasMore: paginated.offset + paginated.items.length < paginated.total,
|
|
210
225
|
AppliedFilters: {
|
|
211
226
|
alias: params.filters.alias ?? null,
|
|
227
|
+
aliasExact: params.filters.aliasExact ?? null,
|
|
212
228
|
envId: params.filters.envId ?? null,
|
|
213
229
|
fields: params.filters.fields ?? [...DEFAULT_ENV_FIELDS],
|
|
214
230
|
currentEnvOnly: shouldRestrictToCurrentEnv,
|
|
215
231
|
},
|
|
232
|
+
...(exactEnvIdSummaryHint
|
|
233
|
+
? {
|
|
234
|
+
RecommendedNextAction: exactEnvIdSummaryHint,
|
|
235
|
+
}
|
|
236
|
+
: {}),
|
|
216
237
|
};
|
|
217
238
|
}
|
|
239
|
+
async function enrichEnvInfoWithBilling(params) {
|
|
240
|
+
const targetEnvId = params.envId ||
|
|
241
|
+
params.result?.EnvInfo?.EnvId;
|
|
242
|
+
if (!targetEnvId || !params.result?.EnvInfo) {
|
|
243
|
+
return params.result;
|
|
244
|
+
}
|
|
245
|
+
try {
|
|
246
|
+
const billingResult = await params.manager.commonService("tcb", "2018-06-08").call({
|
|
247
|
+
Action: "DescribeBillingInfo",
|
|
248
|
+
Param: {
|
|
249
|
+
EnvId: targetEnvId,
|
|
250
|
+
},
|
|
251
|
+
});
|
|
252
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(params.logger, billingResult);
|
|
253
|
+
const billingList = billingResult?.EnvBillingInfoList ||
|
|
254
|
+
billingResult?.Response?.EnvBillingInfoList ||
|
|
255
|
+
billingResult?.Data?.EnvBillingInfoList ||
|
|
256
|
+
[];
|
|
257
|
+
const matchedBillingInfo = Array.isArray(billingList)
|
|
258
|
+
? billingList.find((item) => item?.EnvId === targetEnvId) ?? billingList[0]
|
|
259
|
+
: undefined;
|
|
260
|
+
if (!matchedBillingInfo) {
|
|
261
|
+
return params.result;
|
|
262
|
+
}
|
|
263
|
+
return {
|
|
264
|
+
...params.result,
|
|
265
|
+
EnvInfo: {
|
|
266
|
+
...params.result.EnvInfo,
|
|
267
|
+
BillingInfo: matchedBillingInfo,
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
catch (billingError) {
|
|
272
|
+
(0, logger_js_1.debug)("DescribeBillingInfo enrichment failed, continuing without billing info", {
|
|
273
|
+
error: billingError,
|
|
274
|
+
envId: targetEnvId,
|
|
275
|
+
});
|
|
276
|
+
return params.result;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
218
279
|
async function getGuidePrompt(server) {
|
|
219
280
|
if (getCurrentIde(server) === "CodeBuddy" ||
|
|
220
281
|
process.env.CLOUDBASE_GUIDE_PROMPT === "false") {
|
|
@@ -232,6 +293,16 @@ function registerEnvTools(server) {
|
|
|
232
293
|
// 获取 cloudBaseOptions,如果没有则为 undefined
|
|
233
294
|
const cloudBaseOptions = server.cloudBaseOptions;
|
|
234
295
|
const getManager = () => (0, cloudbase_manager_js_1.getCloudBaseManager)({ cloudBaseOptions, mcpServer: server });
|
|
296
|
+
const getManagerForEnvQuery = (targetEnvId, requireEnvId = true) => (0, cloudbase_manager_js_1.getCloudBaseManager)({
|
|
297
|
+
cloudBaseOptions: targetEnvId && targetEnvId !== cloudBaseOptions?.envId
|
|
298
|
+
? {
|
|
299
|
+
...cloudBaseOptions,
|
|
300
|
+
envId: targetEnvId,
|
|
301
|
+
}
|
|
302
|
+
: cloudBaseOptions,
|
|
303
|
+
requireEnvId,
|
|
304
|
+
mcpServer: server,
|
|
305
|
+
});
|
|
235
306
|
const hasEnvId = typeof cloudBaseOptions?.envId === 'string' && cloudBaseOptions?.envId.length > 0;
|
|
236
307
|
const supportedAuthActions = getSupportedAuthActions(server);
|
|
237
308
|
const authActionEnum = [...supportedAuthActions];
|
|
@@ -597,26 +668,27 @@ function registerEnvTools(server) {
|
|
|
597
668
|
// envQuery - 环境查询(合并 listEnvs + getEnvInfo + getEnvAuthDomains + getWebsiteConfig)
|
|
598
669
|
server.registerTool?.("envQuery", {
|
|
599
670
|
title: "环境查询",
|
|
600
|
-
description: "查询云开发环境相关信息,支持查询环境列表、当前环境信息、安全域名和静态网站托管配置。(原工具名:listEnvs/getEnvInfo/getEnvAuthDomains/getWebsiteConfig,为兼容旧AI规则可继续使用这些名称)当 action=list 时,标准返回字段为 EnvId、Alias、Status、EnvType、Region、PackageName、IsDefault,并支持通过 fields
|
|
671
|
+
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 等计费字段)。",
|
|
601
672
|
inputSchema: {
|
|
602
673
|
action: zod_1.z
|
|
603
674
|
.enum(["list", "info", "domains", "hosting"])
|
|
604
|
-
.describe("查询类型:list
|
|
675
|
+
.describe("查询类型:list=环境列表/摘要筛选(即使传 envId 也只返回 EnvId、Alias、Status、EnvType、Region、PackageId、PackageName、IsDefault,不支持 expiry),info=当前环境详细信息(详情中可查看更完整资源字段),domains=安全域名列表,hosting=静态网站托管配置"),
|
|
605
676
|
alias: zod_1.z.string().optional().describe("按环境别名筛选。action=list 时可选"),
|
|
606
|
-
|
|
677
|
+
aliasExact: zod_1.z.boolean().optional().describe("按环境别名精确筛选。action=list 时可选;与 alias 配合使用"),
|
|
678
|
+
envId: zod_1.z.string().optional().describe("按环境 ID 精确筛选。action=list 时可选;注意 list + envId 仍只返回摘要,如需该环境详情请改用 action=info"),
|
|
607
679
|
limit: zod_1.z.number().int().positive().optional().describe("返回数量上限。action=list 时可选"),
|
|
608
680
|
offset: zod_1.z.number().int().min(0).optional().describe("分页偏移。action=list 时可选"),
|
|
609
681
|
fields: zod_1.z
|
|
610
682
|
.array(zod_1.z.enum(DEFAULT_ENV_FIELDS))
|
|
611
683
|
.optional()
|
|
612
|
-
.describe("返回字段白名单。仅支持 EnvId、Alias、Status、EnvType、Region、PackageName、IsDefault。action=list 时可选"),
|
|
684
|
+
.describe("返回字段白名单。仅支持 EnvId、Alias、Status、EnvType、Region、PackageId、PackageName、IsDefault。action=list 时可选"),
|
|
613
685
|
},
|
|
614
686
|
annotations: {
|
|
615
687
|
readOnlyHint: true,
|
|
616
688
|
openWorldHint: true,
|
|
617
689
|
category: "env",
|
|
618
690
|
},
|
|
619
|
-
}, async ({ action, alias, envId, limit, offset, fields, }) => {
|
|
691
|
+
}, async ({ action, alias, aliasExact, envId, limit, offset, fields, }) => {
|
|
620
692
|
try {
|
|
621
693
|
let result;
|
|
622
694
|
switch (action) {
|
|
@@ -689,6 +761,7 @@ function registerEnvTools(server) {
|
|
|
689
761
|
hasEnvId,
|
|
690
762
|
filters: {
|
|
691
763
|
alias,
|
|
764
|
+
aliasExact,
|
|
692
765
|
envId,
|
|
693
766
|
limit,
|
|
694
767
|
offset,
|
|
@@ -697,20 +770,44 @@ function registerEnvTools(server) {
|
|
|
697
770
|
});
|
|
698
771
|
break;
|
|
699
772
|
case "info":
|
|
700
|
-
const cloudbaseInfo = await
|
|
773
|
+
const cloudbaseInfo = await getManagerForEnvQuery(envId);
|
|
701
774
|
result = await cloudbaseInfo.env.getEnvInfo();
|
|
702
775
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
776
|
+
result = await enrichEnvInfoWithBilling({
|
|
777
|
+
manager: cloudbaseInfo,
|
|
778
|
+
result,
|
|
779
|
+
envId,
|
|
780
|
+
logger: server.logger,
|
|
781
|
+
});
|
|
703
782
|
break;
|
|
704
783
|
case "domains":
|
|
705
784
|
const cloudbaseDomains = await getManager();
|
|
706
785
|
result = await cloudbaseDomains.env.getEnvAuthDomains();
|
|
707
786
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
708
787
|
break;
|
|
709
|
-
case "hosting":
|
|
788
|
+
case "hosting": {
|
|
710
789
|
const cloudbaseHosting = await getManager();
|
|
711
|
-
|
|
712
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger,
|
|
790
|
+
const websiteConfig = await cloudbaseHosting.hosting.getWebsiteConfig();
|
|
791
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, websiteConfig);
|
|
792
|
+
const hostingResult = {
|
|
793
|
+
...websiteConfig,
|
|
794
|
+
CdnDomain: websiteConfig.CdnDomain ?? null,
|
|
795
|
+
Bucket: websiteConfig.Bucket ?? null,
|
|
796
|
+
};
|
|
797
|
+
try {
|
|
798
|
+
const envInfo = await cloudbaseHosting.env.getEnvInfo();
|
|
799
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, envInfo);
|
|
800
|
+
hostingResult.CdnDomain = envInfo.EnvInfo?.StaticStorages?.[0]?.StaticDomain ?? hostingResult.CdnDomain;
|
|
801
|
+
hostingResult.Bucket = envInfo.EnvInfo?.StaticStorages?.[0]?.Bucket ?? hostingResult.Bucket;
|
|
802
|
+
}
|
|
803
|
+
catch (hostingInfoError) {
|
|
804
|
+
(0, logger_js_1.debug)("Failed to enrich hosting envQuery result with env info", {
|
|
805
|
+
error: hostingInfoError,
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
result = hostingResult;
|
|
713
809
|
break;
|
|
810
|
+
}
|
|
714
811
|
default:
|
|
715
812
|
throw new Error(`不支持的查询类型: ${action}`);
|
|
716
813
|
}
|
|
@@ -968,7 +1065,7 @@ function registerCapiTools(server) {
|
|
|
968
1065
|
const getManager = () => (0, cloudbase_manager_js_1.getCloudBaseManager)({ cloudBaseOptions });
|
|
969
1066
|
server.registerTool?.("callCloudApi", {
|
|
970
1067
|
title: "调用云API",
|
|
971
|
-
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
|
|
1068
|
+
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\`。`,
|
|
972
1069
|
inputSchema: {
|
|
973
1070
|
service: zod_1.z
|
|
974
1071
|
.enum(ALLOWED_SERVICES)
|
|
@@ -980,7 +1077,7 @@ function registerCapiTools(server) {
|
|
|
980
1077
|
params: zod_1.z
|
|
981
1078
|
.record(zod_1.z.any())
|
|
982
1079
|
.optional()
|
|
983
|
-
.describe("Action 对应的参数对象,键名需与官方 API 定义一致。某些 Action 需要携带 EnvId 等信息;如不确定参数结构,请先查官方文档。tcb 示例:`{ \"service\": \"tcb\", \"action\": \"DestroyEnv\", \"params\": { \"EnvId\": \"env-xxx\" } }`
|
|
1080
|
+
.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。"),
|
|
984
1081
|
},
|
|
985
1082
|
annotations: {
|
|
986
1083
|
readOnlyHint: false,
|
|
@@ -1112,7 +1209,7 @@ ${envIdSection}
|
|
|
1112
1209
|
## 环境信息
|
|
1113
1210
|
- 操作系统: ${os_1.default.type()} ${os_1.default.release()}
|
|
1114
1211
|
- Node.js版本: ${process.version}
|
|
1115
|
-
- MCP 版本:${process.env.npm_package_version || "2.15.2-beta.
|
|
1212
|
+
- MCP 版本:${process.env.npm_package_version || "2.15.2-beta.2" || 0}
|
|
1116
1213
|
- 系统架构: ${os_1.default.arch()}
|
|
1117
1214
|
- 时间: ${new Date().toISOString()}
|
|
1118
1215
|
- 请求ID: ${requestId}
|
|
@@ -5738,9 +5835,9 @@ async function getCloudBaseManager(options = {}) {
|
|
|
5738
5835
|
}
|
|
5739
5836
|
try {
|
|
5740
5837
|
// Get region from environment variable for auth URL
|
|
5741
|
-
const
|
|
5838
|
+
const fallbackRegion = cloudBaseOptions?.region ?? process.env.TCB_REGION;
|
|
5742
5839
|
const loginState = authStrategy === 'ensure'
|
|
5743
|
-
? await (0, auth_js_1.getLoginState)({ region })
|
|
5840
|
+
? await (0, auth_js_1.getLoginState)({ region: fallbackRegion })
|
|
5744
5841
|
: await (0, auth_js_1.peekLoginState)();
|
|
5745
5842
|
if (!loginState) {
|
|
5746
5843
|
const authState = await (0, auth_js_1.getAuthProgressState)();
|
|
@@ -5788,13 +5885,29 @@ async function getCloudBaseManager(options = {}) {
|
|
|
5788
5885
|
}
|
|
5789
5886
|
// envId priority: envManager.cachedEnvId > envManager.getEnvId() > loginState.envId > undefined
|
|
5790
5887
|
// Note: envManager.cachedEnvId has highest priority as it reflects user's latest environment switch
|
|
5791
|
-
// Region priority: process.env.TCB_REGION > undefined
|
|
5792
|
-
//
|
|
5793
|
-
//
|
|
5888
|
+
// Region priority: envCandidates[].region (actual env region) > process.env.TCB_REGION > undefined
|
|
5889
|
+
// Resolving the environment's own region avoids INVALID_REGION errors when TCB_REGION
|
|
5890
|
+
// is set to a different region than the target environment.
|
|
5891
|
+
const resolvedEnvId = finalEnvId || loginEnvId;
|
|
5892
|
+
let region = fallbackRegion;
|
|
5893
|
+
if (resolvedEnvId && !cloudBaseOptions?.region) {
|
|
5894
|
+
try {
|
|
5895
|
+
const envCandidates = await listAvailableEnvCandidates({ loginState });
|
|
5896
|
+
const matchedEnv = envCandidates.find(c => c.envId === resolvedEnvId);
|
|
5897
|
+
if (matchedEnv?.region) {
|
|
5898
|
+
region = matchedEnv.region;
|
|
5899
|
+
(0, logger_js_1.debug)('使用环境实际 region:', { envId: resolvedEnvId, region });
|
|
5900
|
+
}
|
|
5901
|
+
}
|
|
5902
|
+
catch {
|
|
5903
|
+
// If env listing fails, fall back to TCB_REGION / undefined
|
|
5904
|
+
(0, logger_js_1.debug)('无法获取环境列表,使用 fallback region');
|
|
5905
|
+
}
|
|
5906
|
+
}
|
|
5794
5907
|
const manager = new manager_node_1.default({
|
|
5795
5908
|
secretId,
|
|
5796
5909
|
secretKey,
|
|
5797
|
-
envId:
|
|
5910
|
+
envId: resolvedEnvId,
|
|
5798
5911
|
token,
|
|
5799
5912
|
proxy: process.env.http_proxy,
|
|
5800
5913
|
region,
|
|
@@ -6647,6 +6760,31 @@ async function getDatabaseInstanceId(getManager) {
|
|
|
6647
6760
|
function delay(ms) {
|
|
6648
6761
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
6649
6762
|
}
|
|
6763
|
+
function parseNoSqlDocument(value) {
|
|
6764
|
+
if (typeof value !== "string") {
|
|
6765
|
+
return value;
|
|
6766
|
+
}
|
|
6767
|
+
try {
|
|
6768
|
+
const parsed = JSON.parse(value);
|
|
6769
|
+
return parsed !== null && typeof parsed === "object" ? parsed : value;
|
|
6770
|
+
}
|
|
6771
|
+
catch {
|
|
6772
|
+
return value;
|
|
6773
|
+
}
|
|
6774
|
+
}
|
|
6775
|
+
function normalizeNoSqlDocuments(data) {
|
|
6776
|
+
if (!Array.isArray(data)) {
|
|
6777
|
+
return [];
|
|
6778
|
+
}
|
|
6779
|
+
return data.map((item) => parseNoSqlDocument(item));
|
|
6780
|
+
}
|
|
6781
|
+
function withCollectionName(collectionName, payload) {
|
|
6782
|
+
return {
|
|
6783
|
+
...payload,
|
|
6784
|
+
collection: collectionName,
|
|
6785
|
+
collectionName,
|
|
6786
|
+
};
|
|
6787
|
+
}
|
|
6650
6788
|
async function waitForCollectionReady({ cloudbase, collectionName, logger, timeoutMs = COLLECTION_READY_TIMEOUT_MS, pollIntervalMs = COLLECTION_READY_POLL_INTERVAL_MS, }) {
|
|
6651
6789
|
const startedAt = Date.now();
|
|
6652
6790
|
const deadline = startedAt + timeoutMs;
|
|
@@ -6772,14 +6910,14 @@ checkIndex: 检查索引是否存在`),
|
|
|
6772
6910
|
content: [
|
|
6773
6911
|
{
|
|
6774
6912
|
type: "text",
|
|
6775
|
-
text: JSON.stringify({
|
|
6913
|
+
text: JSON.stringify(withCollectionName(collectionName, {
|
|
6776
6914
|
success: true,
|
|
6777
6915
|
exists: result.Exists,
|
|
6778
6916
|
requestId: result.RequestId,
|
|
6779
6917
|
message: result.Exists
|
|
6780
6918
|
? "云开发数据库集合已存在"
|
|
6781
6919
|
: "云开发数据库集合不存在",
|
|
6782
|
-
}, null, 2),
|
|
6920
|
+
}), null, 2),
|
|
6783
6921
|
},
|
|
6784
6922
|
],
|
|
6785
6923
|
};
|
|
@@ -6794,13 +6932,13 @@ checkIndex: 检查索引是否存在`),
|
|
|
6794
6932
|
content: [
|
|
6795
6933
|
{
|
|
6796
6934
|
type: "text",
|
|
6797
|
-
text: JSON.stringify({
|
|
6935
|
+
text: JSON.stringify(withCollectionName(collectionName, {
|
|
6798
6936
|
success: true,
|
|
6799
6937
|
requestId: result.RequestId,
|
|
6800
6938
|
indexNum: result.IndexNum,
|
|
6801
6939
|
indexes: result.Indexes,
|
|
6802
6940
|
message: "获取云开发数据库集合信息成功",
|
|
6803
|
-
}, null, 2),
|
|
6941
|
+
}), null, 2),
|
|
6804
6942
|
},
|
|
6805
6943
|
],
|
|
6806
6944
|
};
|
|
@@ -6815,13 +6953,13 @@ checkIndex: 检查索引是否存在`),
|
|
|
6815
6953
|
content: [
|
|
6816
6954
|
{
|
|
6817
6955
|
type: "text",
|
|
6818
|
-
text: JSON.stringify({
|
|
6956
|
+
text: JSON.stringify(withCollectionName(collectionName, {
|
|
6819
6957
|
success: true,
|
|
6820
6958
|
requestId: result.RequestId,
|
|
6821
6959
|
indexNum: result.IndexNum,
|
|
6822
6960
|
indexes: result.Indexes,
|
|
6823
6961
|
message: "获取索引列表成功",
|
|
6824
|
-
}, null, 2),
|
|
6962
|
+
}), null, 2),
|
|
6825
6963
|
},
|
|
6826
6964
|
],
|
|
6827
6965
|
};
|
|
@@ -6836,12 +6974,13 @@ checkIndex: 检查索引是否存在`),
|
|
|
6836
6974
|
content: [
|
|
6837
6975
|
{
|
|
6838
6976
|
type: "text",
|
|
6839
|
-
text: JSON.stringify({
|
|
6977
|
+
text: JSON.stringify(withCollectionName(collectionName, {
|
|
6840
6978
|
success: true,
|
|
6979
|
+
indexName,
|
|
6841
6980
|
exists: result.Exists,
|
|
6842
6981
|
requestId: result.RequestId,
|
|
6843
6982
|
message: result.Exists ? "索引已存在" : "索引不存在",
|
|
6844
|
-
}, null, 2),
|
|
6983
|
+
}), null, 2),
|
|
6845
6984
|
},
|
|
6846
6985
|
],
|
|
6847
6986
|
};
|
|
@@ -6905,12 +7044,12 @@ deleteCollection: 删除集合`),
|
|
|
6905
7044
|
content: [
|
|
6906
7045
|
{
|
|
6907
7046
|
type: "text",
|
|
6908
|
-
text: JSON.stringify({
|
|
7047
|
+
text: JSON.stringify(withCollectionName(collectionName, {
|
|
6909
7048
|
success: true,
|
|
6910
7049
|
requestId: result.RequestId,
|
|
6911
7050
|
action,
|
|
6912
7051
|
message: "云开发数据库集合创建成功",
|
|
6913
|
-
}, null, 2),
|
|
7052
|
+
}), null, 2),
|
|
6914
7053
|
},
|
|
6915
7054
|
],
|
|
6916
7055
|
};
|
|
@@ -6925,12 +7064,12 @@ deleteCollection: 删除集合`),
|
|
|
6925
7064
|
content: [
|
|
6926
7065
|
{
|
|
6927
7066
|
type: "text",
|
|
6928
|
-
text: JSON.stringify({
|
|
7067
|
+
text: JSON.stringify(withCollectionName(collectionName, {
|
|
6929
7068
|
success: true,
|
|
6930
7069
|
requestId: result.RequestId,
|
|
6931
7070
|
action,
|
|
6932
7071
|
message: "云开发数据库集合更新成功",
|
|
6933
|
-
}, null, 2),
|
|
7072
|
+
}), null, 2),
|
|
6934
7073
|
},
|
|
6935
7074
|
],
|
|
6936
7075
|
};
|
|
@@ -6938,12 +7077,12 @@ deleteCollection: 删除集合`),
|
|
|
6938
7077
|
if (action === "deleteCollection") {
|
|
6939
7078
|
const result = await cloudbase.database.deleteCollection(collectionName);
|
|
6940
7079
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
6941
|
-
const body = {
|
|
7080
|
+
const body = withCollectionName(collectionName, {
|
|
6942
7081
|
success: true,
|
|
6943
7082
|
requestId: result.RequestId,
|
|
6944
7083
|
action,
|
|
6945
7084
|
message: result.Exists === false ? "集合不存在" : "云开发数据库集合删除成功",
|
|
6946
|
-
};
|
|
7085
|
+
});
|
|
6947
7086
|
if (result.Exists === false) {
|
|
6948
7087
|
body.exists = false;
|
|
6949
7088
|
}
|
|
@@ -7009,17 +7148,21 @@ deleteCollection: 删除集合`),
|
|
|
7009
7148
|
},
|
|
7010
7149
|
});
|
|
7011
7150
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
7151
|
+
const documents = normalizeNoSqlDocuments(result.Data);
|
|
7012
7152
|
return {
|
|
7013
7153
|
content: [
|
|
7014
7154
|
{
|
|
7015
7155
|
type: "text",
|
|
7016
|
-
text: JSON.stringify({
|
|
7156
|
+
text: JSON.stringify(withCollectionName(collectionName, {
|
|
7017
7157
|
success: true,
|
|
7018
7158
|
requestId: result.RequestId,
|
|
7019
|
-
data:
|
|
7159
|
+
data: documents,
|
|
7160
|
+
total: typeof result.Pager?.Total === "number"
|
|
7161
|
+
? result.Pager.Total
|
|
7162
|
+
: documents.length,
|
|
7020
7163
|
pager: result.Pager,
|
|
7021
7164
|
message: "文档查询成功",
|
|
7022
|
-
}, null, 2),
|
|
7165
|
+
}), null, 2),
|
|
7023
7166
|
},
|
|
7024
7167
|
],
|
|
7025
7168
|
};
|
|
@@ -7142,12 +7285,15 @@ async function insertDocuments({ collectionName, documents, getManager, logger,
|
|
|
7142
7285
|
},
|
|
7143
7286
|
});
|
|
7144
7287
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(logger, result);
|
|
7145
|
-
return JSON.stringify({
|
|
7288
|
+
return JSON.stringify(withCollectionName(collectionName, {
|
|
7146
7289
|
success: true,
|
|
7147
7290
|
requestId: result.RequestId,
|
|
7148
7291
|
insertedIds: result.InsertedIds,
|
|
7292
|
+
insertedCount: Array.isArray(result.InsertedIds)
|
|
7293
|
+
? result.InsertedIds.length
|
|
7294
|
+
: undefined,
|
|
7149
7295
|
message: "文档插入成功",
|
|
7150
|
-
}, null, 2);
|
|
7296
|
+
}), null, 2);
|
|
7151
7297
|
}
|
|
7152
7298
|
async function updateDocuments({ collectionName, query, update, isMulti, upsert, getManager, logger, }) {
|
|
7153
7299
|
const cloudbase = await getManager();
|
|
@@ -7165,14 +7311,14 @@ async function updateDocuments({ collectionName, query, update, isMulti, upsert,
|
|
|
7165
7311
|
},
|
|
7166
7312
|
});
|
|
7167
7313
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(logger, result);
|
|
7168
|
-
return JSON.stringify({
|
|
7314
|
+
return JSON.stringify(withCollectionName(collectionName, {
|
|
7169
7315
|
success: true,
|
|
7170
7316
|
requestId: result.RequestId,
|
|
7171
7317
|
modifiedCount: result.ModifiedNum,
|
|
7172
7318
|
matchedCount: result.MatchedNum,
|
|
7173
7319
|
upsertedId: result.UpsertedId,
|
|
7174
7320
|
message: "文档更新成功",
|
|
7175
|
-
}, null, 2);
|
|
7321
|
+
}), null, 2);
|
|
7176
7322
|
}
|
|
7177
7323
|
async function deleteDocuments({ collectionName, query, isMulti, getManager, logger, }) {
|
|
7178
7324
|
const cloudbase = await getManager();
|
|
@@ -7188,12 +7334,12 @@ async function deleteDocuments({ collectionName, query, isMulti, getManager, log
|
|
|
7188
7334
|
},
|
|
7189
7335
|
});
|
|
7190
7336
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(logger, result);
|
|
7191
|
-
return JSON.stringify({
|
|
7337
|
+
return JSON.stringify(withCollectionName(collectionName, {
|
|
7192
7338
|
success: true,
|
|
7193
7339
|
requestId: result.RequestId,
|
|
7194
7340
|
deleted: result.Deleted,
|
|
7195
7341
|
message: "文档删除成功",
|
|
7196
|
-
}, null, 2);
|
|
7342
|
+
}), null, 2);
|
|
7197
7343
|
}
|
|
7198
7344
|
|
|
7199
7345
|
|
|
@@ -9056,11 +9202,11 @@ function registerGatewayTools(server) {
|
|
|
9056
9202
|
targetName: input.targetName,
|
|
9057
9203
|
path: accessPath,
|
|
9058
9204
|
raw: result,
|
|
9059
|
-
}, `已为目标 ${input.targetName}
|
|
9205
|
+
}, `已为目标 ${input.targetName} 创建网关访问路径。注意:路由配置传播通常需要等待 30 秒到 3 分钟,请勿立即访问。`, [
|
|
9060
9206
|
{
|
|
9061
9207
|
tool: "queryGateway",
|
|
9062
9208
|
action: "getAccess",
|
|
9063
|
-
reason: "
|
|
9209
|
+
reason: "等待 30 秒到 3 分钟后再确认访问入口是否已生效",
|
|
9064
9210
|
},
|
|
9065
9211
|
]);
|
|
9066
9212
|
}
|
|
@@ -9316,7 +9462,7 @@ function registerStorageTools(server) {
|
|
|
9316
9462
|
// Tool 2: manageStorage - 管理存储文件(写操作)
|
|
9317
9463
|
server.registerTool("manageStorage", {
|
|
9318
9464
|
title: "管理存储文件",
|
|
9319
|
-
description: "
|
|
9465
|
+
description: "管理云存储文件,仅用于 COS/Storage 对象,不用于静态网站托管。支持上传文件/目录、下载文件/目录、删除文件/目录等操作。删除操作需要设置force=true进行确认,防止误删除重要文件。",
|
|
9320
9466
|
inputSchema: manageStorageInputSchema,
|
|
9321
9467
|
annotations: {
|
|
9322
9468
|
readOnlyHint: false,
|
|
@@ -10385,7 +10531,7 @@ class TelemetryReporter {
|
|
|
10385
10531
|
const nodeVersion = process.version; // Node.js版本
|
|
10386
10532
|
const arch = os_1.default.arch(); // 系统架构
|
|
10387
10533
|
// 从构建时注入的版本号获取MCP版本信息
|
|
10388
|
-
const mcpVersion = process.env.npm_package_version || "2.15.2-beta.
|
|
10534
|
+
const mcpVersion = process.env.npm_package_version || "2.15.2-beta.2" || 0;
|
|
10389
10535
|
return {
|
|
10390
10536
|
userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
|
|
10391
10537
|
deviceId: this.deviceId,
|
|
@@ -10699,11 +10845,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
10699
10845
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
10700
10846
|
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;
|
|
10701
10847
|
exports.formatRuntimeList = formatRuntimeList;
|
|
10848
|
+
exports.shouldInstallDependencyForFunction = shouldInstallDependencyForFunction;
|
|
10849
|
+
exports.buildFunctionOperationErrorMessage = buildFunctionOperationErrorMessage;
|
|
10702
10850
|
exports.registerFunctionTools = registerFunctionTools;
|
|
10703
10851
|
const zod_1 = __webpack_require__(2971);
|
|
10704
10852
|
const cloudbase_manager_js_1 = __webpack_require__(3431);
|
|
10705
10853
|
const cloud_mode_js_1 = __webpack_require__(9684);
|
|
10706
10854
|
const logger_js_1 = __webpack_require__(3039);
|
|
10855
|
+
const fs_1 = __webpack_require__(4421);
|
|
10707
10856
|
const path_1 = __importDefault(__webpack_require__(2521));
|
|
10708
10857
|
exports.SUPPORTED_RUNTIMES = {
|
|
10709
10858
|
nodejs: [
|
|
@@ -10892,6 +11041,12 @@ function getExpectedFunctionPath(functionRootPath, functionName) {
|
|
|
10892
11041
|
return undefined;
|
|
10893
11042
|
return path_1.default.join(path_1.default.normalize(functionRootPath), functionName);
|
|
10894
11043
|
}
|
|
11044
|
+
function shouldInstallDependencyForFunction(functionType, hasPackageJson) {
|
|
11045
|
+
if (functionType === "HTTP") {
|
|
11046
|
+
return hasPackageJson;
|
|
11047
|
+
}
|
|
11048
|
+
return true;
|
|
11049
|
+
}
|
|
10895
11050
|
function buildFunctionOperationErrorMessage(operation, functionName, functionRootPath, error) {
|
|
10896
11051
|
const baseMessage = error instanceof Error ? error.message : String(error);
|
|
10897
11052
|
const suggestions = [];
|
|
@@ -10903,6 +11058,13 @@ function buildFunctionOperationErrorMessage(operation, functionName, functionRoo
|
|
|
10903
11058
|
suggestions.push(`当前工具会从 \`functionRootPath + 函数名\` 查找代码目录,期望目录是 \`${expectedFunctionPath}\`。`);
|
|
10904
11059
|
suggestions.push("如果你传入的已经是函数目录本身,请改为传它的父目录。");
|
|
10905
11060
|
}
|
|
11061
|
+
if (/paths\[0\].*undefined/i.test(baseMessage)) {
|
|
11062
|
+
suggestions.push("HTTP 函数创建时需要提供 functionRootPath(指向 cloudfunctions 父目录)或 zipFile,否则 SDK 无法定位函数目录。");
|
|
11063
|
+
}
|
|
11064
|
+
if (/依赖安装失败|package\.json/i.test(baseMessage)) {
|
|
11065
|
+
suggestions.push("如果 HTTP 函数只使用原生 Node.js API 且没有第三方依赖,可以保留函数目录中的 index.js 和 scf_bootstrap,工具会跳过依赖安装。");
|
|
11066
|
+
suggestions.push("如果你确实依赖 npm 包,请在函数目录下补充 package.json 后重试。");
|
|
11067
|
+
}
|
|
10906
11068
|
if (suggestions.length === 0) {
|
|
10907
11069
|
suggestions.push("请检查函数名、目录结构和环境中的函数状态后重试。");
|
|
10908
11070
|
}
|
|
@@ -11278,8 +11440,21 @@ function registerFunctionTools(server) {
|
|
|
11278
11440
|
throw new Error(`不支持的运行时环境: "${String(func.runtime)}"\n\n支持的运行时:\n${formatRuntimeList()}`);
|
|
11279
11441
|
}
|
|
11280
11442
|
}
|
|
11281
|
-
func.installDependency = true;
|
|
11282
11443
|
const processedRootPath = processFunctionRootPath(input.functionRootPath, functionName);
|
|
11444
|
+
const functionType = typeof func.type === "string" ? func.type : undefined;
|
|
11445
|
+
const expectedFunctionPath = getExpectedFunctionPath(processedRootPath, functionName);
|
|
11446
|
+
if (functionType === "HTTP" && !processedRootPath && !input.zipFile) {
|
|
11447
|
+
throw new Error("createFunction 创建 HTTP 函数时,需要提供 functionRootPath(指向 cloudfunctions 父目录)或 zipFile。");
|
|
11448
|
+
}
|
|
11449
|
+
const hasPackageJson = expectedFunctionPath !== undefined
|
|
11450
|
+
? (0, fs_1.existsSync)(path_1.default.join(expectedFunctionPath, "package.json"))
|
|
11451
|
+
: false;
|
|
11452
|
+
func.installDependency = input.zipFile
|
|
11453
|
+
? true
|
|
11454
|
+
: shouldInstallDependencyForFunction(functionType, hasPackageJson);
|
|
11455
|
+
if (functionType === "HTTP" && processedRootPath && !hasPackageJson) {
|
|
11456
|
+
console.warn(`检测到 HTTP 函数 ${functionName} 目录下没有 package.json,已跳过依赖安装;如果你需要第三方依赖,请补充 package.json 后重试。`);
|
|
11457
|
+
}
|
|
11283
11458
|
let result;
|
|
11284
11459
|
try {
|
|
11285
11460
|
result = await cloudbase.functions.createFunction({
|
|
@@ -11292,11 +11467,7 @@ function registerFunctionTools(server) {
|
|
|
11292
11467
|
throw wrapFunctionOperationError("createFunction", functionName, processedRootPath, error);
|
|
11293
11468
|
}
|
|
11294
11469
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
11295
|
-
|
|
11296
|
-
action: input.action,
|
|
11297
|
-
functionName,
|
|
11298
|
-
raw: result,
|
|
11299
|
-
}, `已创建函数 ${functionName}`, [
|
|
11470
|
+
const nextActions = [
|
|
11300
11471
|
{
|
|
11301
11472
|
tool: "queryFunctions",
|
|
11302
11473
|
action: "getFunctionDetail",
|
|
@@ -11307,7 +11478,37 @@ function registerFunctionTools(server) {
|
|
|
11307
11478
|
action: "listFunctionTriggers",
|
|
11308
11479
|
reason: "检查函数触发器",
|
|
11309
11480
|
},
|
|
11310
|
-
]
|
|
11481
|
+
];
|
|
11482
|
+
if (func.type === "HTTP") {
|
|
11483
|
+
nextActions.push({
|
|
11484
|
+
tool: "manageGateway",
|
|
11485
|
+
action: "createAccess",
|
|
11486
|
+
reason: "如果需要通过 URL 访问 HTTP 函数,请按实际路径和鉴权需求显式创建访问入口,不要默认假设 /函数名 已存在",
|
|
11487
|
+
});
|
|
11488
|
+
nextActions.push({
|
|
11489
|
+
tool: "queryGateway",
|
|
11490
|
+
action: "getAccess",
|
|
11491
|
+
reason: "交付前确认 HTTP 访问路径是否已存在并已生效",
|
|
11492
|
+
});
|
|
11493
|
+
nextActions.push({
|
|
11494
|
+
tool: "readSecurityRule",
|
|
11495
|
+
action: "读取安全规则",
|
|
11496
|
+
reason: "评测、浏览器或其他外部调用方可能以匿名身份访问;若直接报 EXCEED_AUTHORITY,应先读取当前函数安全规则",
|
|
11497
|
+
});
|
|
11498
|
+
nextActions.push({
|
|
11499
|
+
tool: "writeSecurityRule",
|
|
11500
|
+
action: "写入安全规则",
|
|
11501
|
+
reason: "只有在确认需要匿名访问时,才按实际安全要求调整函数安全规则,例如处理 EXCEED_AUTHORITY",
|
|
11502
|
+
});
|
|
11503
|
+
}
|
|
11504
|
+
const message = func.type === "HTTP"
|
|
11505
|
+
? `已创建 HTTP 函数 ${functionName}。如果后续需要通过 URL 访问,请显式调用 manageGateway(action="createAccess") 按实际路径和鉴权需求创建访问入口。评测或其他外部调用方可能会以匿名身份访问,而且失败后不一定会把 EXCEED_AUTHORITY 再反馈给 AI;交付前请主动确认访问路径和函数安全规则,若已出现 EXCEED_AUTHORITY,请先调用 readSecurityRule(resourceType="function") 查看当前规则,再按需要使用 writeSecurityRule 调整权限。`
|
|
11506
|
+
: `已创建函数 ${functionName}`;
|
|
11507
|
+
return buildEnvelope({
|
|
11508
|
+
action: input.action,
|
|
11509
|
+
functionName,
|
|
11510
|
+
raw: result,
|
|
11511
|
+
}, message, nextActions);
|
|
11311
11512
|
}
|
|
11312
11513
|
case "updateFunctionCode": {
|
|
11313
11514
|
if (!input.functionName) {
|
|
@@ -11352,6 +11553,9 @@ function registerFunctionTools(server) {
|
|
|
11352
11553
|
}
|
|
11353
11554
|
const cloudbase = await getManager();
|
|
11354
11555
|
const functionDetail = await cloudbase.functions.getFunctionDetail(input.functionName);
|
|
11556
|
+
if (!functionDetail) {
|
|
11557
|
+
throw new Error(`函数 ${input.functionName} 不存在或无法获取详情`);
|
|
11558
|
+
}
|
|
11355
11559
|
const currentVpc = typeof functionDetail.VpcConfig === "object" &&
|
|
11356
11560
|
functionDetail.VpcConfig !== null &&
|
|
11357
11561
|
functionDetail.VpcConfig.SubnetId &&
|
|
@@ -12159,7 +12363,7 @@ function registerSetupTools(server) {
|
|
|
12159
12363
|
title: "下载项目模板",
|
|
12160
12364
|
description: `自动下载并部署CloudBase项目模板。⚠️ **MANDATORY FOR NEW PROJECTS** ⚠️
|
|
12161
12365
|
|
|
12162
|
-
**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.
|
|
12366
|
+
**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)`,
|
|
12163
12367
|
inputSchema: {
|
|
12164
12368
|
template: zod_1.z
|
|
12165
12369
|
.enum(["react", "vue", "miniprogram", "uniapp", "rules"])
|
|
@@ -13846,10 +14050,10 @@ function registerHostingTools(server) {
|
|
|
13846
14050
|
// uploadFiles - 上传文件到静态网站托管 (cloud-incompatible)
|
|
13847
14051
|
server.registerTool("uploadFiles", {
|
|
13848
14052
|
title: "上传静态文件",
|
|
13849
|
-
description: "
|
|
14053
|
+
description: "上传文件到静态网站托管,仅用于 Web 站点部署,不用于云存储对象上传。部署前请先完成构建;如果站点会部署到子路径,请检查构建配置中的 publicPath、base、assetPrefix 等是否使用相对路径,避免静态资源加载失败。若需要上传 COS 云存储文件,请使用 manageStorage。",
|
|
13850
14054
|
inputSchema: {
|
|
13851
14055
|
localPath: zod_1.z.string().optional().describe("本地文件或文件夹路径,需要是绝对路径,例如 /tmp/files/data.txt。"),
|
|
13852
|
-
cloudPath: zod_1.z.string().optional().describe("
|
|
14056
|
+
cloudPath: zod_1.z.string().optional().describe("静态托管云端文件或文件夹路径,例如 files/data.txt。若部署到子路径,请同时检查构建配置中的 publicPath、base、assetPrefix 等是否为相对路径。云存储对象路径请改用 manageStorage。"),
|
|
13853
14057
|
files: zod_1.z.array(zod_1.z.object({
|
|
13854
14058
|
localPath: zod_1.z.string(),
|
|
13855
14059
|
cloudPath: zod_1.z.string()
|
|
@@ -14579,11 +14783,68 @@ module.exports = __WEBPACK_EXTERNAL_MODULE_crypto__;
|
|
|
14579
14783
|
|
|
14580
14784
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
14581
14785
|
exports.WRITE_SECURITY_RULE = exports.READ_SECURITY_RULE = void 0;
|
|
14786
|
+
exports.normalizeCustomSecurityRule = normalizeCustomSecurityRule;
|
|
14787
|
+
exports.buildSecurityRuleErrorMessage = buildSecurityRuleErrorMessage;
|
|
14582
14788
|
exports.registerSecurityRuleTools = registerSecurityRuleTools;
|
|
14583
14789
|
const zod_1 = __webpack_require__(2971);
|
|
14584
14790
|
const cloudbase_manager_js_1 = __webpack_require__(3431);
|
|
14585
14791
|
exports.READ_SECURITY_RULE = "readSecurityRule";
|
|
14586
14792
|
exports.WRITE_SECURITY_RULE = "writeSecurityRule";
|
|
14793
|
+
const FUNCTION_CUSTOM_RULE_EXAMPLE = JSON.stringify({
|
|
14794
|
+
"*": {
|
|
14795
|
+
invoke: true,
|
|
14796
|
+
},
|
|
14797
|
+
}, null, 2);
|
|
14798
|
+
function isPlainObject(value) {
|
|
14799
|
+
return (typeof value === "object" &&
|
|
14800
|
+
value !== null &&
|
|
14801
|
+
!Array.isArray(value));
|
|
14802
|
+
}
|
|
14803
|
+
function formatSecurityRuleInputHint(resourceType) {
|
|
14804
|
+
if (resourceType === "function") {
|
|
14805
|
+
return `函数自定义安全规则应传 JSON 对象或 JSON 字符串,例如 ${FUNCTION_CUSTOM_RULE_EXAMPLE}。`;
|
|
14806
|
+
}
|
|
14807
|
+
if (resourceType === "noSqlDatabase") {
|
|
14808
|
+
return "NoSQL 自定义安全规则应传 JSON 对象或 JSON 字符串,例如 {\"read\":\"true\",\"write\":\"true\"}。";
|
|
14809
|
+
}
|
|
14810
|
+
return "自定义安全规则应传 JSON 对象或 JSON 字符串,并与 readSecurityRule 返回的规则结构保持一致。";
|
|
14811
|
+
}
|
|
14812
|
+
function normalizeCustomSecurityRule(resourceType, rule) {
|
|
14813
|
+
if (rule === undefined) {
|
|
14814
|
+
throw new Error(`resourceType=${resourceType} 且 aclTag=CUSTOM 时必须提供 rule 字段`);
|
|
14815
|
+
}
|
|
14816
|
+
if (typeof rule === "string") {
|
|
14817
|
+
try {
|
|
14818
|
+
const parsed = JSON.parse(rule);
|
|
14819
|
+
if (!isPlainObject(parsed)) {
|
|
14820
|
+
throw new Error(`rule 必须是 JSON 对象,不支持 ${Array.isArray(parsed) ? "数组" : typeof parsed}。`);
|
|
14821
|
+
}
|
|
14822
|
+
return JSON.stringify(parsed);
|
|
14823
|
+
}
|
|
14824
|
+
catch (error) {
|
|
14825
|
+
const baseMessage = error instanceof Error ? error.message : "rule 不是合法的 JSON 字符串";
|
|
14826
|
+
throw new Error(`${baseMessage} ${formatSecurityRuleInputHint(resourceType)}`);
|
|
14827
|
+
}
|
|
14828
|
+
}
|
|
14829
|
+
if (!isPlainObject(rule)) {
|
|
14830
|
+
throw new Error(`rule 必须是 JSON 对象或 JSON 字符串。${formatSecurityRuleInputHint(resourceType)}`);
|
|
14831
|
+
}
|
|
14832
|
+
return JSON.stringify(rule);
|
|
14833
|
+
}
|
|
14834
|
+
function buildSecurityRuleErrorMessage(operation, resourceType, aclTag, error) {
|
|
14835
|
+
const baseMessage = error instanceof Error ? error.message : String(error);
|
|
14836
|
+
const suggestions = [];
|
|
14837
|
+
if (operation === "writeSecurityRule" && aclTag === "CUSTOM") {
|
|
14838
|
+
suggestions.push(formatSecurityRuleInputHint(resourceType));
|
|
14839
|
+
}
|
|
14840
|
+
if (/INVALID_VALUE|ModifySecurityRule|错误的值|JSON/i.test(baseMessage)) {
|
|
14841
|
+
suggestions.push("请先把 CUSTOM 规则整理成 JSON 对象,再传给 writeSecurityRule。");
|
|
14842
|
+
}
|
|
14843
|
+
if (suggestions.length === 0) {
|
|
14844
|
+
suggestions.push("请检查 resourceType、aclTag 和 rule 是否与官方安全规则格式一致后重试。");
|
|
14845
|
+
}
|
|
14846
|
+
return `[${operation}] 调用失败: ${baseMessage}\n建议:${suggestions.join(" ")}`;
|
|
14847
|
+
}
|
|
14587
14848
|
/**
|
|
14588
14849
|
* 注册安全规则相关 Tool
|
|
14589
14850
|
* @param server MCP Server 实例
|
|
@@ -14594,7 +14855,7 @@ function registerSecurityRuleTools(server) {
|
|
|
14594
14855
|
// 读取安全规则 Tool
|
|
14595
14856
|
server.registerTool?.(exports.READ_SECURITY_RULE, {
|
|
14596
14857
|
title: "读取安全规则",
|
|
14597
|
-
description: `读取指定资源(noSQL 数据库、SQL
|
|
14858
|
+
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`,
|
|
14598
14859
|
inputSchema: {
|
|
14599
14860
|
resourceType: zod_1.z
|
|
14600
14861
|
.enum(["noSqlDatabase", "sqlDatabase", "function", "storage"])
|
|
@@ -14680,7 +14941,7 @@ function registerSecurityRuleTools(server) {
|
|
|
14680
14941
|
// 写入安全规则 Tool
|
|
14681
14942
|
server.registerTool?.(exports.WRITE_SECURITY_RULE, {
|
|
14682
14943
|
title: "写入安全规则",
|
|
14683
|
-
description:
|
|
14944
|
+
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"。`,
|
|
14684
14945
|
inputSchema: {
|
|
14685
14946
|
resourceType: zod_1.z
|
|
14686
14947
|
.enum(["sqlDatabase", "noSqlDatabase", "function", "storage"])
|
|
@@ -14692,9 +14953,9 @@ function registerSecurityRuleTools(server) {
|
|
|
14692
14953
|
.enum(["READONLY", "PRIVATE", "ADMINWRITE", "ADMINONLY", "CUSTOM"])
|
|
14693
14954
|
.describe("权限类别"),
|
|
14694
14955
|
rule: zod_1.z
|
|
14695
|
-
.string()
|
|
14956
|
+
.union([zod_1.z.string(), zod_1.z.record(zod_1.z.any())])
|
|
14696
14957
|
.optional()
|
|
14697
|
-
.describe(
|
|
14958
|
+
.describe(`自定义安全规则内容,仅当 aclTag 为 CUSTOM 时必填。可以直接传 JSON 对象,或者传可解析为 JSON 对象的字符串。函数示例:${FUNCTION_CUSTOM_RULE_EXAMPLE}`),
|
|
14698
14959
|
},
|
|
14699
14960
|
annotations: {
|
|
14700
14961
|
readOnlyHint: false,
|
|
@@ -14702,138 +14963,140 @@ function registerSecurityRuleTools(server) {
|
|
|
14702
14963
|
category: "security-rule",
|
|
14703
14964
|
},
|
|
14704
14965
|
}, async ({ resourceType, resourceId, aclTag, rule }) => {
|
|
14705
|
-
|
|
14706
|
-
|
|
14707
|
-
|
|
14708
|
-
|
|
14709
|
-
if (
|
|
14710
|
-
if (
|
|
14711
|
-
|
|
14712
|
-
|
|
14713
|
-
|
|
14714
|
-
|
|
14715
|
-
|
|
14716
|
-
|
|
14717
|
-
|
|
14718
|
-
|
|
14719
|
-
|
|
14720
|
-
|
|
14721
|
-
|
|
14966
|
+
try {
|
|
14967
|
+
const cloudbase = await getManager();
|
|
14968
|
+
const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
14969
|
+
let result;
|
|
14970
|
+
if (resourceType === "noSqlDatabase") {
|
|
14971
|
+
if (aclTag === "CUSTOM") {
|
|
14972
|
+
const normalizedRule = normalizeCustomSecurityRule(resourceType, rule);
|
|
14973
|
+
result = await cloudbase.commonService().call({
|
|
14974
|
+
Action: "ModifySafeRule",
|
|
14975
|
+
Param: {
|
|
14976
|
+
CollectionName: resourceId,
|
|
14977
|
+
EnvId: envId,
|
|
14978
|
+
AclTag: aclTag,
|
|
14979
|
+
Rule: normalizedRule,
|
|
14980
|
+
},
|
|
14981
|
+
});
|
|
14982
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
14983
|
+
}
|
|
14984
|
+
else {
|
|
14985
|
+
result = await cloudbase.commonService().call({
|
|
14986
|
+
Action: "ModifyDatabaseACL",
|
|
14987
|
+
Param: {
|
|
14988
|
+
CollectionName: resourceId,
|
|
14989
|
+
EnvId: envId,
|
|
14990
|
+
AclTag: aclTag,
|
|
14991
|
+
},
|
|
14992
|
+
});
|
|
14993
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
14994
|
+
}
|
|
14722
14995
|
}
|
|
14723
|
-
else {
|
|
14996
|
+
else if (resourceType === "function") {
|
|
14997
|
+
if (aclTag !== "CUSTOM")
|
|
14998
|
+
throw new Error("云函数安全规则仅支持 CUSTOM 权限类别");
|
|
14999
|
+
const normalizedRule = normalizeCustomSecurityRule(resourceType, rule);
|
|
14724
15000
|
result = await cloudbase.commonService().call({
|
|
14725
|
-
Action: "
|
|
15001
|
+
Action: "ModifySecurityRule",
|
|
14726
15002
|
Param: {
|
|
14727
|
-
CollectionName: resourceId,
|
|
14728
|
-
EnvId: envId,
|
|
14729
15003
|
AclTag: aclTag,
|
|
14730
|
-
},
|
|
14731
|
-
});
|
|
14732
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
14733
|
-
}
|
|
14734
|
-
}
|
|
14735
|
-
else if (resourceType === "function") {
|
|
14736
|
-
if (aclTag !== "CUSTOM")
|
|
14737
|
-
throw new Error("云函数安全规则仅支持 CUSTOM 权限类别");
|
|
14738
|
-
if (!rule)
|
|
14739
|
-
throw new Error("云函数自定义安全规则(CUSTOM)必须提供 rule 字段");
|
|
14740
|
-
result = await cloudbase.commonService().call({
|
|
14741
|
-
Action: "ModifySecurityRule",
|
|
14742
|
-
Param: {
|
|
14743
|
-
AclTag: aclTag,
|
|
14744
|
-
EnvId: envId,
|
|
14745
|
-
ResourceType: "FUNCTION",
|
|
14746
|
-
Rule: rule,
|
|
14747
|
-
},
|
|
14748
|
-
});
|
|
14749
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
14750
|
-
}
|
|
14751
|
-
else if (resourceType === "storage") {
|
|
14752
|
-
if (aclTag === "CUSTOM") {
|
|
14753
|
-
if (!rule)
|
|
14754
|
-
throw new Error("存储自定义安全规则(CUSTOM)必须提供 rule 字段");
|
|
14755
|
-
result = await cloudbase.commonService().call({
|
|
14756
|
-
Action: "ModifyStorageSafeRule",
|
|
14757
|
-
Param: {
|
|
14758
|
-
Bucket: resourceId,
|
|
14759
15004
|
EnvId: envId,
|
|
14760
|
-
|
|
14761
|
-
Rule:
|
|
15005
|
+
ResourceType: "FUNCTION",
|
|
15006
|
+
Rule: normalizedRule,
|
|
14762
15007
|
},
|
|
14763
15008
|
});
|
|
14764
15009
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
14765
15010
|
}
|
|
14766
|
-
else {
|
|
14767
|
-
|
|
14768
|
-
|
|
15011
|
+
else if (resourceType === "storage") {
|
|
15012
|
+
if (aclTag === "CUSTOM") {
|
|
15013
|
+
const normalizedRule = normalizeCustomSecurityRule(resourceType, rule);
|
|
15014
|
+
result = await cloudbase.commonService().call({
|
|
15015
|
+
Action: "ModifyStorageSafeRule",
|
|
15016
|
+
Param: {
|
|
15017
|
+
Bucket: resourceId,
|
|
15018
|
+
EnvId: envId,
|
|
15019
|
+
AclTag: aclTag,
|
|
15020
|
+
Rule: normalizedRule,
|
|
15021
|
+
},
|
|
15022
|
+
});
|
|
15023
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
15024
|
+
}
|
|
15025
|
+
else {
|
|
15026
|
+
result = await cloudbase.commonService().call({
|
|
15027
|
+
Action: "ModifyStorageSafeRule",
|
|
15028
|
+
Param: {
|
|
15029
|
+
Bucket: resourceId,
|
|
15030
|
+
EnvId: envId,
|
|
15031
|
+
AclTag: aclTag,
|
|
15032
|
+
},
|
|
15033
|
+
});
|
|
15034
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
15035
|
+
}
|
|
15036
|
+
}
|
|
15037
|
+
else if (resourceType === "sqlDatabase") {
|
|
15038
|
+
if (aclTag === "CUSTOM") {
|
|
15039
|
+
throw new Error("SQL 数据库不支持自定义安全规则(CUSTOM)");
|
|
15040
|
+
}
|
|
15041
|
+
const schema = envId;
|
|
15042
|
+
const tableName = resourceId;
|
|
15043
|
+
const instanceId = "default";
|
|
15044
|
+
const resource = `${instanceId}#${schema}#${tableName}`;
|
|
15045
|
+
const resourceType = "table";
|
|
15046
|
+
const effect = "allow";
|
|
15047
|
+
const policyList = [
|
|
15048
|
+
"allUser",
|
|
15049
|
+
"anonymousUser",
|
|
15050
|
+
"externalUser",
|
|
15051
|
+
"internalUser",
|
|
15052
|
+
].map((roleIdentity) => ({
|
|
15053
|
+
RoleIdentity: roleIdentity,
|
|
15054
|
+
ResourceType: resourceType,
|
|
15055
|
+
ResourceId: resource,
|
|
15056
|
+
RowPermission: [],
|
|
15057
|
+
Effect: effect,
|
|
15058
|
+
}));
|
|
15059
|
+
policyList[0].RowPermission = getRowPermission(aclTag);
|
|
15060
|
+
result = await cloudbase.commonService("lowcode").call({
|
|
15061
|
+
Action: "BatchCreateResourcePolicy",
|
|
14769
15062
|
Param: {
|
|
14770
|
-
Bucket: resourceId,
|
|
14771
15063
|
EnvId: envId,
|
|
14772
|
-
|
|
15064
|
+
PolicyList: policyList,
|
|
14773
15065
|
},
|
|
14774
15066
|
});
|
|
14775
15067
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
15068
|
+
function getRowPermission(policy) {
|
|
15069
|
+
return {
|
|
15070
|
+
READONLY: [
|
|
15071
|
+
{ Key: "all", Value: "r" },
|
|
15072
|
+
{ Key: "me", Value: "rw" },
|
|
15073
|
+
],
|
|
15074
|
+
PRIVATE: [{ Key: "me", Value: "rw" }],
|
|
15075
|
+
ADMINWRITE: [{ Key: "all", Value: "r" }],
|
|
15076
|
+
ADMINONLY: [],
|
|
15077
|
+
}[policy];
|
|
15078
|
+
}
|
|
14776
15079
|
}
|
|
14777
|
-
|
|
14778
|
-
|
|
14779
|
-
if (aclTag === "CUSTOM") {
|
|
14780
|
-
throw new Error("SQL 数据库不支持自定义安全规则(CUSTOM)");
|
|
14781
|
-
}
|
|
14782
|
-
const schema = envId;
|
|
14783
|
-
const tableName = resourceId;
|
|
14784
|
-
const instanceId = "default";
|
|
14785
|
-
const resource = `${instanceId}#${schema}#${tableName}`;
|
|
14786
|
-
const resourceType = "table";
|
|
14787
|
-
const effect = "allow";
|
|
14788
|
-
const policyList = [
|
|
14789
|
-
"allUser",
|
|
14790
|
-
"anonymousUser",
|
|
14791
|
-
"externalUser",
|
|
14792
|
-
"internalUser",
|
|
14793
|
-
].map((roleIdentity) => ({
|
|
14794
|
-
RoleIdentity: roleIdentity,
|
|
14795
|
-
ResourceType: resourceType,
|
|
14796
|
-
ResourceId: resource,
|
|
14797
|
-
RowPermission: [],
|
|
14798
|
-
Effect: effect,
|
|
14799
|
-
}));
|
|
14800
|
-
policyList[0].RowPermission = getRowPermission(aclTag);
|
|
14801
|
-
result = await cloudbase.commonService("lowcode").call({
|
|
14802
|
-
Action: "BatchCreateResourcePolicy",
|
|
14803
|
-
Param: {
|
|
14804
|
-
EnvId: envId,
|
|
14805
|
-
PolicyList: policyList,
|
|
14806
|
-
},
|
|
14807
|
-
});
|
|
14808
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
14809
|
-
function getRowPermission(policy) {
|
|
14810
|
-
return {
|
|
14811
|
-
READONLY: [
|
|
14812
|
-
{ Key: "all", Value: "r" },
|
|
14813
|
-
{ Key: "me", Value: "rw" },
|
|
14814
|
-
],
|
|
14815
|
-
PRIVATE: [{ Key: "me", Value: "rw" }],
|
|
14816
|
-
ADMINWRITE: [{ Key: "all", Value: "r" }],
|
|
14817
|
-
ADMINONLY: [],
|
|
14818
|
-
}[policy];
|
|
15080
|
+
else {
|
|
15081
|
+
throw new Error(`不支持的资源类型: ${resourceType}`);
|
|
14819
15082
|
}
|
|
15083
|
+
return {
|
|
15084
|
+
content: [
|
|
15085
|
+
{
|
|
15086
|
+
type: "text",
|
|
15087
|
+
text: JSON.stringify({
|
|
15088
|
+
success: true,
|
|
15089
|
+
requestId: result.RequestId,
|
|
15090
|
+
raw: result,
|
|
15091
|
+
message: "安全规则写入成功",
|
|
15092
|
+
}, null, 2),
|
|
15093
|
+
},
|
|
15094
|
+
],
|
|
15095
|
+
};
|
|
14820
15096
|
}
|
|
14821
|
-
|
|
14822
|
-
throw new Error(
|
|
15097
|
+
catch (error) {
|
|
15098
|
+
throw new Error(buildSecurityRuleErrorMessage("writeSecurityRule", resourceType, aclTag, error));
|
|
14823
15099
|
}
|
|
14824
|
-
return {
|
|
14825
|
-
content: [
|
|
14826
|
-
{
|
|
14827
|
-
type: "text",
|
|
14828
|
-
text: JSON.stringify({
|
|
14829
|
-
success: true,
|
|
14830
|
-
requestId: result.RequestId,
|
|
14831
|
-
raw: result,
|
|
14832
|
-
message: "安全规则写入成功",
|
|
14833
|
-
}, null, 2),
|
|
14834
|
-
},
|
|
14835
|
-
],
|
|
14836
|
-
};
|
|
14837
15100
|
});
|
|
14838
15101
|
}
|
|
14839
15102
|
|
|
@@ -14954,12 +15217,15 @@ As the most important part of application development, the following four core c
|
|
|
14954
15217
|
**Refer to deployment process in \`rules/web-development/rule.md\`**
|
|
14955
15218
|
- Use CloudBase static hosting after build completion
|
|
14956
15219
|
- Deploy using \`uploadFiles\` tool
|
|
15220
|
+
- \`uploadFiles\` is only for static hosting deployment; do not use it for COS / cloud storage uploads. For storage objects, use \`manageStorage(action="upload")\`
|
|
14957
15221
|
- Remind users that CDN has a few minutes of cache after deployment
|
|
14958
15222
|
- Generate markdown format access links with random queryString
|
|
14959
15223
|
|
|
14960
15224
|
### 4. Backend Deployment (Cloud Functions or CloudRun)
|
|
14961
15225
|
**Refer to \`rules/cloudrun-development/rule.md\`**
|
|
14962
|
-
- **Cloud Function Deployment**: Prefer \`queryFunctions\` to inspect current state, then use \`manageFunctions\` with \`action="createFunction"\` or \`action="updateFunctionCode"
|
|
15226
|
+
- **Cloud Function Deployment**: Prefer \`queryFunctions\` to inspect current state, then use \`manageFunctions\` with \`action="createFunction"\` or \`action="updateFunctionCode"\`.
|
|
15227
|
+
- 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.
|
|
15228
|
+
- For HTTP functions, create or update them through \`manageFunctions\` with \`func.type="HTTP"\` instead of relying on \`tcb fn deploy\` as the primary path.
|
|
14963
15229
|
- **CloudRun Deployment**: Use \`manageCloudRun\` tool for containerized deployment
|
|
14964
15230
|
- Ensure backend code supports CORS, prepare Dockerfile (for container type)
|
|
14965
15231
|
|
|
@@ -15058,11 +15324,11 @@ If remote links are needed in the application, can continue to call uploadFile t
|
|
|
15058
15324
|
|
|
15059
15325
|
### Deployment Process
|
|
15060
15326
|
|
|
15061
|
-
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.
|
|
15327
|
+
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.
|
|
15062
15328
|
|
|
15063
15329
|
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\`
|
|
15064
15330
|
|
|
15065
|
-
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\`
|
|
15331
|
+
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\`
|
|
15066
15332
|
|
|
15067
15333
|
### Documentation Generation Rules
|
|
15068
15334
|
|
|
@@ -16066,7 +16332,9 @@ function buildProvisionNextActions(status, request) {
|
|
|
16066
16332
|
return [];
|
|
16067
16333
|
}
|
|
16068
16334
|
return [
|
|
16069
|
-
buildNextAction(QUERY_SQL_DATABASE, "
|
|
16335
|
+
buildNextAction(QUERY_SQL_DATABASE, "describeCreateResult", "MySQL provisioning is still running. Check the create result again before initializing schema.", request
|
|
16336
|
+
? { action: "describeCreateResult", request }
|
|
16337
|
+
: { action: "describeCreateResult" }),
|
|
16070
16338
|
];
|
|
16071
16339
|
}
|
|
16072
16340
|
function inferTaskKind(request) {
|