@cloudbase/cloudbase-mcp 2.23.6 → 2.23.8
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 +182 -22
- package/dist/index.js +182 -22
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -261,13 +261,14 @@ async function fetchAvailableEnvCandidates(cloudBaseOptions, server) {
|
|
|
261
261
|
return [];
|
|
262
262
|
}
|
|
263
263
|
}
|
|
264
|
-
const CODEBUDDY_AUTH_ACTIONS = ["status", "set_env"];
|
|
264
|
+
const CODEBUDDY_AUTH_ACTIONS = ["status", "set_env", "login_by_api_key"];
|
|
265
265
|
const DEFAULT_AUTH_ACTIONS = [
|
|
266
266
|
"status",
|
|
267
267
|
"start_auth",
|
|
268
268
|
"set_env",
|
|
269
269
|
"logout",
|
|
270
270
|
"get_temp_credentials",
|
|
271
|
+
"login_by_api_key",
|
|
271
272
|
];
|
|
272
273
|
function maskSensitiveValue(value) {
|
|
273
274
|
if (value.length <= 4) {
|
|
@@ -824,12 +825,12 @@ function registerEnvTools(server) {
|
|
|
824
825
|
if (server.ide !== 'wxide') {
|
|
825
826
|
server.registerTool?.("auth", {
|
|
826
827
|
title: "CloudBase 开发阶段登录与环境",
|
|
827
|
-
description: "CloudBase(腾讯云开发)开发阶段登录与环境绑定。登录后即可访问云资源;环境(env)是云函数、数据库、静态托管等资源的隔离单元,绑定环境后其他 MCP
|
|
828
|
+
description: "CloudBase(腾讯云开发)开发阶段登录与环境绑定。登录后即可访问云资源;环境(env)是云函数、数据库、静态托管等资源的隔离单元,绑定环境后其他 MCP 工具才能操作该环境。支持:查询状态、发起登录、API Key登录、绑定环境(set_env)、退出登录。",
|
|
828
829
|
inputSchema: {
|
|
829
830
|
action: zod_1.z
|
|
830
831
|
.enum(authActionEnum)
|
|
831
832
|
.optional()
|
|
832
|
-
.describe("动作:status=查询状态,start_auth=发起登录,set_env=绑定环境(传envId),logout=退出登录"),
|
|
833
|
+
.describe("动作:status=查询状态,start_auth=发起登录,login_by_api_key=API Key登录,set_env=绑定环境(传envId),logout=退出登录"),
|
|
833
834
|
...(supportedAuthActions.includes("start_auth")
|
|
834
835
|
? {
|
|
835
836
|
authMode: zod_1.z
|
|
@@ -854,6 +855,18 @@ function registerEnvTools(server) {
|
|
|
854
855
|
.string()
|
|
855
856
|
.optional()
|
|
856
857
|
.describe("环境ID(CloudBase 环境唯一标识),绑定后工具将操作该环境。action=set_env 时必填"),
|
|
858
|
+
...(supportedAuthActions.includes("login_by_api_key")
|
|
859
|
+
? {
|
|
860
|
+
apiKey: zod_1.z
|
|
861
|
+
.string()
|
|
862
|
+
.optional()
|
|
863
|
+
.describe("CloudBase API Key,action=login_by_api_key 时必填"),
|
|
864
|
+
apiKeyEnvId: zod_1.z
|
|
865
|
+
.string()
|
|
866
|
+
.optional()
|
|
867
|
+
.describe("CloudBase 环境ID(EnvId),action=login_by_api_key 时必填,用于指定 API Key 所属环境"),
|
|
868
|
+
}
|
|
869
|
+
: {}),
|
|
857
870
|
...(supportedAuthActions.includes("logout")
|
|
858
871
|
? {
|
|
859
872
|
confirm: zod_1.z
|
|
@@ -1169,6 +1182,78 @@ function registerEnvTools(server) {
|
|
|
1169
1182
|
next_step: envPreparation.nextStep,
|
|
1170
1183
|
});
|
|
1171
1184
|
}
|
|
1185
|
+
if (action === "login_by_api_key") {
|
|
1186
|
+
const toolApiKey = normalizeOptionalToolString(rawArgs.apiKey);
|
|
1187
|
+
const toolApiKeyEnvId = normalizeOptionalToolString(rawArgs.apiKeyEnvId);
|
|
1188
|
+
if (!toolApiKey || !toolApiKeyEnvId) {
|
|
1189
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1190
|
+
ok: false,
|
|
1191
|
+
code: "INVALID_ARGS",
|
|
1192
|
+
message: "action=login_by_api_key 时必须同时提供 apiKey 和 envId。",
|
|
1193
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("login_by_api_key", {
|
|
1194
|
+
suggestedArgs: { action: "login_by_api_key", apiKey: "<your-api-key>", envId: "<your-env-id>" },
|
|
1195
|
+
}),
|
|
1196
|
+
});
|
|
1197
|
+
}
|
|
1198
|
+
// 写入 process.env(与 cli.ts 处理 --api-key/--env-id 的逻辑一致)
|
|
1199
|
+
process.env.CLOUDBASE_API_KEY = toolApiKey;
|
|
1200
|
+
process.env.CLOUDBASE_ENV_ID = toolApiKeyEnvId;
|
|
1201
|
+
try {
|
|
1202
|
+
const loginState = await (0, auth_js_1.peekLoginState)();
|
|
1203
|
+
if (loginState) {
|
|
1204
|
+
const envPreparation = await prepareAuthEnvironment({
|
|
1205
|
+
server,
|
|
1206
|
+
cloudBaseOptions,
|
|
1207
|
+
loginState,
|
|
1208
|
+
});
|
|
1209
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1210
|
+
ok: true,
|
|
1211
|
+
code: "AUTH_READY",
|
|
1212
|
+
message: "API Key 认证成功,已获取临时密钥。",
|
|
1213
|
+
auth_mode: "api_key",
|
|
1214
|
+
...buildAuthEnvSetupPayload(envPreparation),
|
|
1215
|
+
next_step: envPreparation.nextStep,
|
|
1216
|
+
});
|
|
1217
|
+
}
|
|
1218
|
+
// API Key 换取失败:清理 env vars 并返回诊断信息
|
|
1219
|
+
delete process.env.CLOUDBASE_API_KEY;
|
|
1220
|
+
delete process.env.CLOUDBASE_ENV_ID;
|
|
1221
|
+
let diagMessage = "API Key 换取临时密钥失败。";
|
|
1222
|
+
diagMessage += `\n\n诊断信息:`;
|
|
1223
|
+
diagMessage += `\n- CLOUDBASE_ENV_ID: ${toolApiKeyEnvId}`;
|
|
1224
|
+
diagMessage += `\n- CLOUDBASE_API_KEY: ${toolApiKey.slice(0, 20)}...(已截断)`;
|
|
1225
|
+
diagMessage += `\n\n可能原因:`;
|
|
1226
|
+
diagMessage += `\n1. API Key 已过期或被删除`;
|
|
1227
|
+
diagMessage += `\n2. CLOUDBASE_ENV_ID 与 API Key 所属环境不匹配`;
|
|
1228
|
+
diagMessage += `\n3. 网络连接问题`;
|
|
1229
|
+
diagMessage += `\n\n建议:请检查 API Key 和环境 ID 是否正确。`;
|
|
1230
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1231
|
+
ok: false,
|
|
1232
|
+
code: "API_KEY_AUTH_FAILED",
|
|
1233
|
+
message: diagMessage,
|
|
1234
|
+
auth_mode: "api_key",
|
|
1235
|
+
envId: toolApiKeyEnvId,
|
|
1236
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("login_by_api_key", {
|
|
1237
|
+
suggestedArgs: { action: "login_by_api_key", apiKey: "<your-api-key>", envId: "<your-env-id>" },
|
|
1238
|
+
}),
|
|
1239
|
+
});
|
|
1240
|
+
}
|
|
1241
|
+
catch (error) {
|
|
1242
|
+
// 异常时清理 env vars
|
|
1243
|
+
delete process.env.CLOUDBASE_API_KEY;
|
|
1244
|
+
delete process.env.CLOUDBASE_ENV_ID;
|
|
1245
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1246
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1247
|
+
ok: false,
|
|
1248
|
+
code: "API_KEY_AUTH_FAILED",
|
|
1249
|
+
message: `API Key 认证异常: ${message}`,
|
|
1250
|
+
auth_mode: "api_key",
|
|
1251
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("login_by_api_key", {
|
|
1252
|
+
suggestedArgs: { action: "login_by_api_key", apiKey: "<your-api-key>", envId: "<your-env-id>" },
|
|
1253
|
+
}),
|
|
1254
|
+
});
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1172
1257
|
if (action === "set_env") {
|
|
1173
1258
|
const loginState = await (0, auth_js_1.peekLoginState)();
|
|
1174
1259
|
if (!loginState) {
|
|
@@ -2117,7 +2202,7 @@ ${envIdSection}
|
|
|
2117
2202
|
## 环境信息
|
|
2118
2203
|
- 操作系统: ${os_1.default.type()} ${os_1.default.release()}
|
|
2119
2204
|
- Node.js版本: ${process.version}
|
|
2120
|
-
- MCP 版本:${process.env.npm_package_version || "2.23.
|
|
2205
|
+
- MCP 版本:${process.env.npm_package_version || "2.23.8" || 0}
|
|
2121
2206
|
- 系统架构: ${os_1.default.arch()}
|
|
2122
2207
|
- 时间: ${new Date().toISOString()}
|
|
2123
2208
|
- 请求ID: ${requestId}
|
|
@@ -2198,7 +2283,7 @@ function createWrappedHandler(name, handler, server) {
|
|
|
2198
2283
|
requestId: (typeof error === 'object' && error && 'requestId' in error) ? error.requestId : '',
|
|
2199
2284
|
ide: server.ide || process.env.INTEGRATION_IDE || ''
|
|
2200
2285
|
});
|
|
2201
|
-
const mcpVersion = true ? "2.23.
|
|
2286
|
+
const mcpVersion = true ? "2.23.8" : 0;
|
|
2202
2287
|
const requestIdSuffix = requestId ? `\n🆔 RequestId: ${requestId}` : '';
|
|
2203
2288
|
const enhancedErrorMessage = `${errorMessage}${requestIdSuffix}\n\n📦 CloudBase MCP v${mcpVersion}\n🔗 遇到问题?请复制以下链接到浏览器打开\n即可自动携带错误详情快速创建 GitHub Issue:\n${issueLink}`;
|
|
2204
2289
|
// 创建新的错误对象,保持原有的错误类型但更新消息
|
|
@@ -7367,6 +7452,7 @@ function registerGatewayTools(server) {
|
|
|
7367
7452
|
const cloudbase = await getManager();
|
|
7368
7453
|
const accessPath = input.path ? normalizeAccessPath(input.path) : undefined;
|
|
7369
7454
|
let resolvedAccessId = input.accessId;
|
|
7455
|
+
let resolvedName;
|
|
7370
7456
|
if (!resolvedAccessId) {
|
|
7371
7457
|
if (!input.targetName && !accessPath) {
|
|
7372
7458
|
throw new Error("action=deleteAccess 时至少需要提供 accessId,或提供 targetName/path 用于定位入口");
|
|
@@ -7388,18 +7474,32 @@ function registerGatewayTools(server) {
|
|
|
7388
7474
|
throw new Error("匹配到多个访问入口,请补充 path 或直接传 accessId");
|
|
7389
7475
|
}
|
|
7390
7476
|
resolvedAccessId = candidates[0]?.APIId;
|
|
7477
|
+
resolvedName = candidates[0]?.Name;
|
|
7478
|
+
}
|
|
7479
|
+
else {
|
|
7480
|
+
// 仅传入 accessId 时,先查询获取 name 等信息,确保删除参数完整
|
|
7481
|
+
try {
|
|
7482
|
+
const accessList = await cloudbase.access.getAccessList({});
|
|
7483
|
+
const match = (accessList.APISet ?? []).find((item) => item.APIId === resolvedAccessId);
|
|
7484
|
+
if (match) {
|
|
7485
|
+
resolvedName = match.Name;
|
|
7486
|
+
}
|
|
7487
|
+
}
|
|
7488
|
+
catch {
|
|
7489
|
+
// 查询失败不影响主流程,继续用 accessId 删除
|
|
7490
|
+
}
|
|
7391
7491
|
}
|
|
7392
7492
|
if (!resolvedAccessId) {
|
|
7393
7493
|
throw new Error("无法解析访问入口 accessId,请改为显式传入 accessId");
|
|
7394
7494
|
}
|
|
7395
7495
|
const result = await cloudbase.access.deleteAccess({
|
|
7396
|
-
...(
|
|
7496
|
+
...(resolvedName ? { name: resolvedName } : {}),
|
|
7397
7497
|
apiId: resolvedAccessId,
|
|
7398
7498
|
});
|
|
7399
7499
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
7400
7500
|
return buildEnvelope({
|
|
7401
7501
|
action: input.action,
|
|
7402
|
-
targetName: input.targetName ?? null,
|
|
7502
|
+
targetName: resolvedName ?? input.targetName ?? null,
|
|
7403
7503
|
path: accessPath ?? null,
|
|
7404
7504
|
accessId: resolvedAccessId,
|
|
7405
7505
|
raw: result,
|
|
@@ -8169,14 +8269,43 @@ const ManageCloudRunInputSchema = {
|
|
|
8169
8269
|
})).optional().describe('扩缩容配置数组,用于配置服务的自动扩缩容策略。可配置多个扩缩容策略'),
|
|
8170
8270
|
CustomLogs: zod_1.z.string().optional().describe('自定义日志配置,用于配置服务的日志收集和存储策略'),
|
|
8171
8271
|
Port: zod_1.z.number().min(1).max(65535).optional().describe('服务监听端口配置。函数型服务固定为3000,容器型服务可自定义。服务代码必须监听此端口才能正常接收请求'),
|
|
8172
|
-
EnvParams: zod_1.z.string().optional().describe('环境变量配置,JSON字符串格式。用于传递配置信息给服务代码,如\'{"DATABASE_URL":"mysql://...","NODE_ENV":"production"}\'
|
|
8272
|
+
EnvParams: zod_1.z.string().optional().describe('环境变量配置,JSON字符串格式。用于传递配置信息给服务代码,如\'{"DATABASE_URL":"mysql://...","NODE_ENV":"production"}\'。SDK v5.6.1+ 会自动对传入的环境变量进行 AES-256-CBC 加密传输'),
|
|
8173
8273
|
Dockerfile: zod_1.z.string().optional().describe('Dockerfile文件名配置,仅容器型服务需要。指定用于构建容器镜像的Dockerfile文件路径,默认为项目根目录下的Dockerfile'),
|
|
8174
8274
|
BuildDir: zod_1.z.string().optional().describe('构建目录配置,指定代码构建的目录路径。当代码结构与标准不同时使用,默认为项目根目录'),
|
|
8175
8275
|
InternalAccess: zod_1.z.string().optional().describe('内网访问开关配置,控制是否启用内网访问。true=启用内网访问(可通过云开发SDK直接调用),false=关闭内网访问(仅公网访问)'),
|
|
8176
8276
|
InternalDomain: zod_1.z.string().optional().describe('内网域名配置,用于配置服务的内网访问域名。仅在启用内网访问时有效'),
|
|
8177
8277
|
EntryPoint: zod_1.z.array(zod_1.z.string()).optional().describe('Dockerfile EntryPoint参数配置,仅容器型服务需要。指定容器启动时的入口程序数组,如["node","app.js"]'),
|
|
8178
8278
|
Cmd: zod_1.z.array(zod_1.z.string()).optional().describe('Dockerfile Cmd参数配置,仅容器型服务需要。指定容器启动时的默认命令数组,如["npm","start"]'),
|
|
8179
|
-
|
|
8279
|
+
InitialDelaySeconds: zod_1.z.number().min(0).optional().describe('延迟检测时间(秒),用于配置服务启动后的健康检查延迟。在此期间内不会将请求路由到该实例,适用于启动时间较长的服务'),
|
|
8280
|
+
LogType: zod_1.z.string().optional().describe('日志类型配置,指定服务的日志收集类型。影响日志的采集方式和存储格式'),
|
|
8281
|
+
LogSetId: zod_1.z.string().optional().describe('CLS日志集ID配置,指定日志服务(CLS)的日志集ID。需要先开通CLS日志服务'),
|
|
8282
|
+
LogTopicId: zod_1.z.string().optional().describe('CLS日志主题ID配置,指定日志服务(CLS)的日志主题ID。需要先开通CLS日志服务'),
|
|
8283
|
+
LogParseType: zod_1.z.string().optional().describe('日志解析类型配置,指定日志的解析方式。用于将原始日志解析为结构化数据'),
|
|
8284
|
+
Tag: zod_1.z.string().optional().describe('服务标签配置,用于标识服务类型。如设置为"function:"表示函数型服务。SDK会自动根据配置生成'),
|
|
8285
|
+
OperationMode: zod_1.z.string().optional().describe('运行模式配置,指定服务的运行模式。影响服务的调度和资源分配方式'),
|
|
8286
|
+
SessionAffinity: zod_1.z.string().optional().describe('会话保持配置,用于控制是否启用会话保持功能。启用后会将同一客户端的请求路由到同一实例'),
|
|
8287
|
+
TimerScale: zod_1.z.array(zod_1.z.object({
|
|
8288
|
+
CycleType: zod_1.z.enum(['none', 'daily', 'weekly', 'monthly']).describe('循环类型:none=无循环,daily=每日循环,weekly=每周循环,monthly=每月循环'),
|
|
8289
|
+
StartDate: zod_1.z.string().optional().describe('循环起始日期,格式:YYYY-MM-DD'),
|
|
8290
|
+
EndDate: zod_1.z.string().optional().describe('循环结束日期,格式:YYYY-MM-DD'),
|
|
8291
|
+
StartTime: zod_1.z.string().describe('起始时间,格式:HH:mm:ss'),
|
|
8292
|
+
EndTime: zod_1.z.string().describe('结束时间,格式:HH:mm:ss'),
|
|
8293
|
+
ReplicaNum: zod_1.z.number().min(0).describe('定时扩缩容的目标副本数,最小值0(缩容到0)')
|
|
8294
|
+
})).optional().describe('定时扩缩容配置数组,用于配置服务的定时自动扩缩容策略。可配置多个时间段的扩缩容计划,支持每日/每周/每月循环'),
|
|
8295
|
+
VpcConf: zod_1.z.object({
|
|
8296
|
+
VpcId: zod_1.z.string().describe('VPC网络ID,指定服务所在的私有网络'),
|
|
8297
|
+
SubnetId: zod_1.z.string().describe('子网ID,指定服务所在的子网'),
|
|
8298
|
+
}).optional().describe('VPC网络配置,用于将云托管服务部署到指定的私有网络中。需要提前创建好VPC和子网'),
|
|
8299
|
+
VolumesConf: zod_1.z.array(zod_1.z.object({
|
|
8300
|
+
VolumeName: zod_1.z.string().describe('存储卷名称'),
|
|
8301
|
+
VolumeType: zod_1.z.string().describe('存储卷类型,如CFS表示云文件存储'),
|
|
8302
|
+
VolumePath: zod_1.z.string().describe('存储卷挂载路径,服务代码中的目标路径')
|
|
8303
|
+
})).optional().describe('存储卷配置数组,用于挂载云存储(如CFS)到服务实例中。可用于持久化数据或共享文件'),
|
|
8304
|
+
PublicNetConf: zod_1.z.object({
|
|
8305
|
+
PublicAccess: zod_1.z.boolean().optional().describe('是否开启公网访问,true=开启公网访问,false=关闭公网访问'),
|
|
8306
|
+
PublicAccessPath: zod_1.z.string().optional().describe('公网访问路径配置')
|
|
8307
|
+
}).optional().describe('公网访问配置,用于控制服务的公网访问策略。可配置是否开启公网访问及访问路径'),
|
|
8308
|
+
}).optional().describe('服务配置项,用于部署时设置服务的运行参数。包括资源规格、访问权限、环境变量、日志、网络等配置。不提供时使用默认配置'),
|
|
8180
8309
|
// Init operation parameters
|
|
8181
8310
|
template: zod_1.z.string().optional().default('helloworld').describe('项目模板标识符,用于指定初始化项目时使用的模板。可通过queryCloudRun的templates操作获取可用模板列表。常用模板:helloworld=Hello World示例,nodejs=Node.js项目模板,python=Python项目模板等'),
|
|
8182
8311
|
// Run operation parameters (function services only)
|
|
@@ -8231,18 +8360,31 @@ function checkIfAgentProject(projectPath) {
|
|
|
8231
8360
|
}
|
|
8232
8361
|
}
|
|
8233
8362
|
/**
|
|
8234
|
-
* Validate and normalize file path
|
|
8363
|
+
* Validate and normalize file path.
|
|
8364
|
+
* Accepts absolute paths as-is; for relative paths, resolves against CWD and
|
|
8365
|
+
* ensures the result does not escape the CWD (path-traversal protection).
|
|
8235
8366
|
* @param inputPath User provided path
|
|
8236
8367
|
* @returns Absolute path
|
|
8237
8368
|
*/
|
|
8238
8369
|
function validateAndNormalizePath(inputPath) {
|
|
8239
|
-
|
|
8240
|
-
//
|
|
8370
|
+
const normalizedPath = path_1.default.resolve(inputPath);
|
|
8371
|
+
// On Windows, path.resolve may return a path on a different drive/UNC share.
|
|
8372
|
+
// That is safe — the user explicitly provided an absolute path there.
|
|
8373
|
+
// Only apply the traversal check when the resolved path shares the same root
|
|
8374
|
+
// as CWD (i.e. the path was relative or on the same drive).
|
|
8241
8375
|
const cwd = process.cwd();
|
|
8242
|
-
const
|
|
8243
|
-
|
|
8244
|
-
|
|
8245
|
-
|
|
8376
|
+
const cwdRoot = path_1.default.parse(cwd).root;
|
|
8377
|
+
const pathRoot = path_1.default.parse(normalizedPath).root;
|
|
8378
|
+
if (cwdRoot === pathRoot) {
|
|
8379
|
+
// Same filesystem root — ensure the resolved path is still inside CWD
|
|
8380
|
+
// (or is exactly CWD) to block "../" traversal.
|
|
8381
|
+
const prefix = cwd.endsWith(path_1.default.sep) ? cwd : cwd + path_1.default.sep;
|
|
8382
|
+
if (!normalizedPath.startsWith(prefix) && normalizedPath !== cwd) {
|
|
8383
|
+
throw new Error(`Path must be within current working directory: ${cwd}`);
|
|
8384
|
+
}
|
|
8385
|
+
}
|
|
8386
|
+
// Cross-root absolute paths (e.g. D:\ on Windows when CWD is C:\) are
|
|
8387
|
+
// allowed — the user own the machine and the path is explicitly absolute.
|
|
8246
8388
|
return normalizedPath;
|
|
8247
8389
|
}
|
|
8248
8390
|
function buildManageCloudRunErrorMessage(action, serverName, error) {
|
|
@@ -9775,7 +9917,7 @@ class TelemetryReporter {
|
|
|
9775
9917
|
const nodeVersion = process.version; // Node.js版本
|
|
9776
9918
|
const arch = os_1.default.arch(); // 系统架构
|
|
9777
9919
|
// 从构建时注入的版本号获取MCP版本信息
|
|
9778
|
-
const mcpVersion = process.env.npm_package_version || "2.23.
|
|
9920
|
+
const mcpVersion = process.env.npm_package_version || "2.23.8" || 0;
|
|
9779
9921
|
return {
|
|
9780
9922
|
userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
|
|
9781
9923
|
deviceId: this.deviceId,
|
|
@@ -13786,7 +13928,7 @@ function registerSetupTools(server) {
|
|
|
13786
13928
|
server.registerTool("downloadTemplate", {
|
|
13787
13929
|
title: "下载项目模板",
|
|
13788
13930
|
description: `自动下载并部署CloudBase项目模板。
|
|
13789
|
-
**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.
|
|
13931
|
+
**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.8" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
|
|
13790
13932
|
inputSchema: {
|
|
13791
13933
|
template: zod_1.z
|
|
13792
13934
|
.enum(["react", "vue", "miniprogram", "uniapp", "rules"])
|
|
@@ -16939,6 +17081,18 @@ function buildErrorEnvelope(error) {
|
|
|
16939
17081
|
function normalizeString(value) {
|
|
16940
17082
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
|
16941
17083
|
}
|
|
17084
|
+
/**
|
|
17085
|
+
* Sanitize agent name for CloudBase backend.
|
|
17086
|
+
* The backend creates a cloud function alias from the agent name (e.g. "agent-{name}"),
|
|
17087
|
+
* and SCF aliases only allow alphanumeric characters and hyphens.
|
|
17088
|
+
* This function replaces any character that is not [a-zA-Z0-9] with a hyphen,
|
|
17089
|
+
* then collapses consecutive hyphens into one.
|
|
17090
|
+
*/
|
|
17091
|
+
function sanitizeAgentName(name) {
|
|
17092
|
+
return name
|
|
17093
|
+
.replace(/[^a-zA-Z0-9]+/g, "-")
|
|
17094
|
+
.replace(/^-+|-+$/g, "");
|
|
17095
|
+
}
|
|
16942
17096
|
function normalizeNumber(value) {
|
|
16943
17097
|
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
16944
17098
|
}
|
|
@@ -17093,13 +17247,19 @@ function registerAgentTools(server) {
|
|
|
17093
17247
|
}
|
|
17094
17248
|
// CloudBase 后端在创建 Agent 时会同步创建云函数,函数名/别名长度受 SCF 限制(最大 64 字符)。
|
|
17095
17249
|
// envId 可能被用作前缀或别名的一部分,因此这里预留足够余量,避免后端 CreateFunction 失败。
|
|
17096
|
-
|
|
17097
|
-
|
|
17098
|
-
|
|
17250
|
+
// 同时,后端会用 name 生成云函数 alias(如 "agent-{name}"),而 SCF alias 只允许字母、数字和连字符,
|
|
17251
|
+
// 因此需要对 name 做 sanitize,将非法字符(如下划线)替换为连字符。
|
|
17252
|
+
const sanitizedName = sanitizeAgentName(normalizedName);
|
|
17253
|
+
if (!sanitizedName) {
|
|
17254
|
+
throw new Error(`name "${normalizedName}" 经 sanitize 后为空,请使用包含字母或数字的 name`);
|
|
17255
|
+
}
|
|
17256
|
+
if (sanitizedName.length > 30) {
|
|
17257
|
+
throw new Error(`agent name 过长(当前 ${sanitizedName.length} 字符)。CloudBase 创建 Agent 时会同步创建云函数,` +
|
|
17258
|
+
`函数名/别名受 SCF 64 字符长度限制,且 envId 可能作为前缀拼接。请将 name 控制在 30 字符以内。`);
|
|
17099
17259
|
}
|
|
17100
17260
|
const createPayload = {
|
|
17101
17261
|
...payload,
|
|
17102
|
-
Name:
|
|
17262
|
+
Name: sanitizedName,
|
|
17103
17263
|
Runtime: normalizeString(payload.Runtime) ?? "Nodejs20.19",
|
|
17104
17264
|
};
|
|
17105
17265
|
const result = await cloudbase.agent.createAgent(createPayload);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudbase/cloudbase-mcp",
|
|
3
|
-
"version": "2.23.
|
|
3
|
+
"version": "2.23.8",
|
|
4
4
|
"packageManager": "pnpm@10.8.0",
|
|
5
5
|
"description": "腾讯云开发 MCP Server,通过AI提示词和MCP协议+云开发,让开发更智能、更高效,当你在Cursor/ VSCode GitHub Copilot/WinSurf/CodeBuddy/Augment Code/Claude Code等AI编程工具里写代码时,它能自动帮你生成可直接部署的前后端应用+小程序,并一键发布到腾讯云开发 CloudBase。",
|
|
6
6
|
"main": "./dist/index.cjs",
|