@cloudbase/cloudbase-mcp 2.19.4 → 2.20.0-beta.0
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/508.index.cjs +0 -305
- package/dist/cli.cjs +5 -5
- package/dist/index.cjs +2445 -113
- package/dist/index.d.ts +8 -7
- package/dist/index.js +281 -64
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import CloudBase from '@cloudbase/manager-node';
|
|
2
|
-
import { Credential as Credential_2 } from '@cloudbase/toolbox';
|
|
3
2
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
3
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
5
4
|
|
|
@@ -176,12 +175,7 @@ export declare interface GetFileInfoParams {
|
|
|
176
175
|
*/
|
|
177
176
|
export declare function getInteractiveServerAsync(): Promise<InteractiveServer>;
|
|
178
177
|
|
|
179
|
-
export declare function getLoginState(options?: EnsureLoginOptions): Promise<
|
|
180
|
-
secretId: string;
|
|
181
|
-
secretKey: string;
|
|
182
|
-
token: string | undefined;
|
|
183
|
-
envId: string | undefined;
|
|
184
|
-
} | Credential_2>;
|
|
178
|
+
export declare function getLoginState(options?: EnsureLoginOptions): Promise<LoginState | null>;
|
|
185
179
|
|
|
186
180
|
declare interface GetManagerOptions {
|
|
187
181
|
requireEnvId?: boolean;
|
|
@@ -271,6 +265,13 @@ declare type Logger = (data: {
|
|
|
271
265
|
[key: string]: any;
|
|
272
266
|
}) => void;
|
|
273
267
|
|
|
268
|
+
declare interface LoginState {
|
|
269
|
+
secretId: string;
|
|
270
|
+
secretKey: string;
|
|
271
|
+
token?: string;
|
|
272
|
+
envId?: string;
|
|
273
|
+
}
|
|
274
|
+
|
|
274
275
|
export declare function logout(): Promise<void>;
|
|
275
276
|
|
|
276
277
|
export { McpServer }
|
package/dist/index.js
CHANGED
|
@@ -727,6 +727,8 @@ function registerEnvTools(server) {
|
|
|
727
727
|
if (action === "status") {
|
|
728
728
|
const loginState = await (0, auth_js_1.peekLoginState)();
|
|
729
729
|
const authFlowState = await (0, auth_js_1.getAuthProgressState)();
|
|
730
|
+
// 判断是否为 API Key 模式
|
|
731
|
+
const isApiKeyMode = !!(process.env.CLOUDBASE_API_KEY && process.env.CLOUDBASE_ENV_ID);
|
|
730
732
|
const authStatus = loginState
|
|
731
733
|
? "READY"
|
|
732
734
|
: authFlowState.status === "PENDING"
|
|
@@ -751,6 +753,7 @@ function registerEnvTools(server) {
|
|
|
751
753
|
ok: true,
|
|
752
754
|
code: "STATUS",
|
|
753
755
|
auth_status: authStatus,
|
|
756
|
+
...(isApiKeyMode ? { auth_mode: "api_key" } : {}),
|
|
754
757
|
auth_config: authConfigSummary,
|
|
755
758
|
...(envPreparation
|
|
756
759
|
? buildAuthEnvSetupPayload(envPreparation)
|
|
@@ -773,6 +776,46 @@ function registerEnvTools(server) {
|
|
|
773
776
|
});
|
|
774
777
|
}
|
|
775
778
|
if (action === "start_auth") {
|
|
779
|
+
// API Key 模式:尝试换取临时密钥
|
|
780
|
+
if (process.env.CLOUDBASE_API_KEY && process.env.CLOUDBASE_ENV_ID) {
|
|
781
|
+
try {
|
|
782
|
+
const existingLoginState = await (0, auth_js_1.peekLoginState)();
|
|
783
|
+
if (existingLoginState) {
|
|
784
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
785
|
+
ok: true,
|
|
786
|
+
code: "AUTH_READY",
|
|
787
|
+
message: "当前使用 API Key 认证模式,已自动完成登录,无需手动授权。",
|
|
788
|
+
auth_mode: "api_key",
|
|
789
|
+
envId: process.env.CLOUDBASE_ENV_ID,
|
|
790
|
+
});
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
catch (e) {
|
|
794
|
+
// peekLoginState 内部异常,记录后 fall through
|
|
795
|
+
(0, logger_js_1.debug)("start_auth: peekLoginState threw", { error: e instanceof Error ? e.message : String(e) });
|
|
796
|
+
}
|
|
797
|
+
// API Key 换取失败:返回详细诊断信息
|
|
798
|
+
// 尝试获取更详细的错误信息
|
|
799
|
+
let diagMessage = "当前配置了 API Key 认证模式,但换取临时密钥失败。";
|
|
800
|
+
const endpoint = process.env.CLOUDBASE_API_ENDPOINT || `https://${process.env.CLOUDBASE_ENV_ID}.ap-shanghai.tcb-api.tencentcloudapi.com`;
|
|
801
|
+
diagMessage += `\n\n诊断信息:`;
|
|
802
|
+
diagMessage += `\n- CLOUDBASE_ENV_ID: ${process.env.CLOUDBASE_ENV_ID}`;
|
|
803
|
+
diagMessage += `\n- CLOUDBASE_API_KEY: ${process.env.CLOUDBASE_API_KEY.slice(0, 20)}...(已截断)`;
|
|
804
|
+
diagMessage += `\n- Endpoint: ${endpoint}`;
|
|
805
|
+
diagMessage += `\n\n可能原因:`;
|
|
806
|
+
diagMessage += `\n1. API Key 已过期或被删除`;
|
|
807
|
+
diagMessage += `\n2. Endpoint 不可达(网络/DNS 问题)`;
|
|
808
|
+
diagMessage += `\n3. CLOUDBASE_ENV_ID 与 API Key 所属环境不匹配`;
|
|
809
|
+
diagMessage += `\n\n建议:检查 MCP 配置中的 CLOUDBASE_API_KEY 和 CLOUDBASE_ENV_ID 环境变量是否正确。`;
|
|
810
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
811
|
+
ok: false,
|
|
812
|
+
code: "API_KEY_AUTH_FAILED",
|
|
813
|
+
message: diagMessage,
|
|
814
|
+
auth_mode: "api_key",
|
|
815
|
+
envId: process.env.CLOUDBASE_ENV_ID,
|
|
816
|
+
endpoint,
|
|
817
|
+
});
|
|
818
|
+
}
|
|
776
819
|
const region = server.cloudBaseOptions?.region || process.env.TCB_REGION;
|
|
777
820
|
const auth = toolbox_1.AuthSupervisor.getInstance({});
|
|
778
821
|
const authFlowState = await (0, auth_js_1.getAuthProgressState)();
|
|
@@ -977,6 +1020,15 @@ function registerEnvTools(server) {
|
|
|
977
1020
|
});
|
|
978
1021
|
}
|
|
979
1022
|
if (action === "logout") {
|
|
1023
|
+
// API Key 模式下不允许 logout
|
|
1024
|
+
if (process.env.CLOUDBASE_API_KEY && process.env.CLOUDBASE_ENV_ID) {
|
|
1025
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1026
|
+
ok: false,
|
|
1027
|
+
code: "LOGOUT_NOT_ALLOWED",
|
|
1028
|
+
message: "当前使用 API Key 认证模式,不支持退出登录。如需切换认证方式,请移除 CLOUDBASE_API_KEY 环境变量后重启。",
|
|
1029
|
+
auth_mode: "api_key",
|
|
1030
|
+
});
|
|
1031
|
+
}
|
|
980
1032
|
if (confirm !== "yes") {
|
|
981
1033
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
982
1034
|
ok: false,
|
|
@@ -1103,29 +1155,58 @@ function registerEnvTools(server) {
|
|
|
1103
1155
|
requireEnvId: true,
|
|
1104
1156
|
mcpServer: server, // Pass server for IDE detection
|
|
1105
1157
|
});
|
|
1106
|
-
//
|
|
1107
|
-
//
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1158
|
+
// 当环境变量设置了 CLOUDBASE_ENV_ID 时(如 API Key 模式),
|
|
1159
|
+
// 避免调用 DescribeEnvs(临时密钥可能不支持该接口),
|
|
1160
|
+
// 改为通过 DescribeEnvInfo 获取单环境信息
|
|
1161
|
+
const envIdFromEnv = process.env.CLOUDBASE_ENV_ID;
|
|
1162
|
+
if (envIdFromEnv) {
|
|
1163
|
+
try {
|
|
1164
|
+
const envInfo = await cloudbaseList.env.describeEnvInfo({ EnvId: envIdFromEnv });
|
|
1165
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, envInfo);
|
|
1166
|
+
// DescribeEnvInfo 返回结构: { EnvInfo: { EnvBaseInfo: { EnvId, Alias, ... }, BillingInfo, ... } }
|
|
1167
|
+
// 需要提取 EnvBaseInfo 作为扁平 env 对象以匹配 DescribeEnvs 返回格式
|
|
1168
|
+
const baseInfo = envInfo?.EnvInfo?.EnvBaseInfo;
|
|
1169
|
+
if (baseInfo) {
|
|
1170
|
+
result = { EnvList: [baseInfo] };
|
|
1171
|
+
}
|
|
1172
|
+
else if (envInfo?.EnvInfo) {
|
|
1173
|
+
// 兼容: 如果没有 EnvBaseInfo 但有 EnvInfo,尝试直接使用
|
|
1174
|
+
result = { EnvList: [{ EnvId: envIdFromEnv, ...envInfo.EnvInfo }] };
|
|
1175
|
+
}
|
|
1176
|
+
else {
|
|
1177
|
+
result = { EnvList: [{ EnvId: envIdFromEnv }] };
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
catch (envInfoError) {
|
|
1181
|
+
(0, logger_js_1.debug)("DescribeEnvInfo 失败,返回基础环境信息:", envInfoError instanceof Error ? envInfoError : new Error(String(envInfoError)));
|
|
1182
|
+
result = { EnvList: [{ EnvId: envIdFromEnv }] };
|
|
1183
|
+
}
|
|
1123
1184
|
}
|
|
1124
1185
|
else {
|
|
1125
|
-
//
|
|
1126
|
-
|
|
1127
|
-
result = await cloudbaseList.
|
|
1186
|
+
// Use commonService to call DescribeEnvs with filter parameters
|
|
1187
|
+
// Filter parameters match the reference conditions provided by user
|
|
1188
|
+
result = await cloudbaseList.commonService("tcb", "2018-06-08").call({
|
|
1189
|
+
Action: "DescribeEnvs",
|
|
1190
|
+
Param: {
|
|
1191
|
+
EnvTypes: ["weda", "baas"], // Include weda and baas (normal) environments
|
|
1192
|
+
IsVisible: false, // Filter out invisible environments
|
|
1193
|
+
Channels: ["dcloud", "iotenable", "tem", "scene_module"], // Filter special channels
|
|
1194
|
+
},
|
|
1195
|
+
});
|
|
1128
1196
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
1197
|
+
// Transform response format to match original listEnvs() format
|
|
1198
|
+
if (result && result.EnvList) {
|
|
1199
|
+
result = { EnvList: result.EnvList };
|
|
1200
|
+
}
|
|
1201
|
+
else if (result && result.Data && result.Data.EnvList) {
|
|
1202
|
+
result = { EnvList: result.Data.EnvList };
|
|
1203
|
+
}
|
|
1204
|
+
else {
|
|
1205
|
+
// Fallback to original method if format is unexpected
|
|
1206
|
+
(0, logger_js_1.debug)("Unexpected response format, falling back to listEnvs()");
|
|
1207
|
+
result = await cloudbaseList.env.listEnvs();
|
|
1208
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
1209
|
+
}
|
|
1129
1210
|
}
|
|
1130
1211
|
}
|
|
1131
1212
|
catch (error) {
|
|
@@ -1622,7 +1703,7 @@ ${envIdSection}
|
|
|
1622
1703
|
## 环境信息
|
|
1623
1704
|
- 操作系统: ${os_1.default.type()} ${os_1.default.release()}
|
|
1624
1705
|
- Node.js版本: ${process.version}
|
|
1625
|
-
- MCP 版本:${process.env.npm_package_version || "2.
|
|
1706
|
+
- MCP 版本:${process.env.npm_package_version || "2.20.0-beta.0" || 0}
|
|
1626
1707
|
- 系统架构: ${os_1.default.arch()}
|
|
1627
1708
|
- 时间: ${new Date().toISOString()}
|
|
1628
1709
|
- 请求ID: ${requestId}
|
|
@@ -1670,7 +1751,7 @@ function createWrappedHandler(name, handler, server) {
|
|
|
1670
1751
|
success = true;
|
|
1671
1752
|
requestId = extractRequestIdFromToolResult(result);
|
|
1672
1753
|
const duration = Date.now() - startTime;
|
|
1673
|
-
(0, logger_js_1.debug)(`工具执行成功: ${name}`, { duration });
|
|
1754
|
+
(0, logger_js_1.debug)(`工具执行成功: ${name}`, { duration, requestId: requestId || undefined });
|
|
1674
1755
|
if (!isTestEnvironment) {
|
|
1675
1756
|
server.logger?.({ type: 'afterToolCall', toolName: name, args: sanitizeArgs(args), result: result, duration });
|
|
1676
1757
|
}
|
|
@@ -1682,6 +1763,7 @@ function createWrappedHandler(name, handler, server) {
|
|
|
1682
1763
|
requestId = (typeof error === 'object' && error && 'requestId' in error) ? error.requestId : '';
|
|
1683
1764
|
(0, logger_js_1.debug)(`工具执行失败: ${name}`, {
|
|
1684
1765
|
error: errorMessage,
|
|
1766
|
+
requestId: requestId || undefined,
|
|
1685
1767
|
duration: Date.now() - startTime
|
|
1686
1768
|
});
|
|
1687
1769
|
const isTestEnvironment = false || process.env.VITEST === "true";
|
|
@@ -1702,8 +1784,9 @@ function createWrappedHandler(name, handler, server) {
|
|
|
1702
1784
|
requestId: (typeof error === 'object' && error && 'requestId' in error) ? error.requestId : '',
|
|
1703
1785
|
ide: server.ide || process.env.INTEGRATION_IDE || ''
|
|
1704
1786
|
});
|
|
1705
|
-
const mcpVersion = true ? "2.
|
|
1706
|
-
const
|
|
1787
|
+
const mcpVersion = true ? "2.20.0-beta.0" : 0;
|
|
1788
|
+
const requestIdSuffix = requestId ? `\n🆔 RequestId: ${requestId}` : '';
|
|
1789
|
+
const enhancedErrorMessage = `${errorMessage}${requestIdSuffix}\n\n📦 CloudBase MCP v${mcpVersion}\n🔗 遇到问题?请复制以下链接到浏览器打开\n即可自动携带错误详情快速创建 GitHub Issue:\n${issueLink}`;
|
|
1707
1790
|
// 创建新的错误对象,保持原有的错误类型但更新消息
|
|
1708
1791
|
const enhancedError = error instanceof Error
|
|
1709
1792
|
? new Error(enhancedErrorMessage)
|
|
@@ -3325,11 +3408,20 @@ function createManagerFromLoginState(loginState, region) {
|
|
|
3325
3408
|
}
|
|
3326
3409
|
async function listAvailableEnvCandidates(options) {
|
|
3327
3410
|
const { cloudBaseOptions, loginState: providedLoginState } = options ?? {};
|
|
3411
|
+
// 优先使用显式传入的 envId
|
|
3328
3412
|
if (cloudBaseOptions?.envId) {
|
|
3329
3413
|
return [{
|
|
3330
3414
|
envId: cloudBaseOptions.envId,
|
|
3331
3415
|
}];
|
|
3332
3416
|
}
|
|
3417
|
+
// 当环境变量设置了 CLOUDBASE_ENV_ID 且没有显式 credentials 时,直接返回(避免调 DescribeEnvs)
|
|
3418
|
+
// 有显式 credentials 时需要重新查询,因为可能是不同账号
|
|
3419
|
+
const hasExplicitCredentials = !!(cloudBaseOptions?.secretId && cloudBaseOptions?.secretKey);
|
|
3420
|
+
if (process.env.CLOUDBASE_ENV_ID && !hasExplicitCredentials) {
|
|
3421
|
+
return [{
|
|
3422
|
+
envId: process.env.CLOUDBASE_ENV_ID,
|
|
3423
|
+
}];
|
|
3424
|
+
}
|
|
3333
3425
|
let cloudbase;
|
|
3334
3426
|
if (cloudBaseOptions?.secretId && cloudBaseOptions?.secretKey) {
|
|
3335
3427
|
cloudbase = createCloudBaseManagerWithOptions(cloudBaseOptions);
|
|
@@ -3656,6 +3748,7 @@ async function getCloudBaseManager(options = {}) {
|
|
|
3656
3748
|
await throwPendingAuthError();
|
|
3657
3749
|
}
|
|
3658
3750
|
throwAuthRequiredError();
|
|
3751
|
+
return undefined; // unreachable, helps TypeScript narrow
|
|
3659
3752
|
}
|
|
3660
3753
|
const { envId: loginEnvId, secretId, secretKey, token } = loginState;
|
|
3661
3754
|
let finalEnvId = cloudBaseOptions?.envId;
|
|
@@ -4057,7 +4150,7 @@ checkIndex: 检查指定索引是否存在`),
|
|
|
4057
4150
|
text: JSON.stringify({
|
|
4058
4151
|
success: true,
|
|
4059
4152
|
requestId: result.RequestId,
|
|
4060
|
-
collections: result.
|
|
4153
|
+
collections: result.Tables,
|
|
4061
4154
|
pager: result.Pager,
|
|
4062
4155
|
message: "获取 NoSQL 数据库集合列表成功",
|
|
4063
4156
|
}, null, 2),
|
|
@@ -4199,7 +4292,11 @@ checkIndex: 检查指定索引是否存在`),
|
|
|
4199
4292
|
]).describe(`createCollection: 创建集合
|
|
4200
4293
|
updateCollection: 更新集合配置;添加索引请传 updateOptions.CreateIndexes,删除索引请传 updateOptions.DropIndexes
|
|
4201
4294
|
deleteCollection: 删除集合`),
|
|
4202
|
-
collectionName: zod_1.z
|
|
4295
|
+
collectionName: zod_1.z
|
|
4296
|
+
.string()
|
|
4297
|
+
.trim()
|
|
4298
|
+
.min(1, "collectionName 不能为空")
|
|
4299
|
+
.describe("集合名称"),
|
|
4203
4300
|
updateOptions: zod_1.z
|
|
4204
4301
|
.object({
|
|
4205
4302
|
CreateIndexes: zod_1.z
|
|
@@ -4323,31 +4420,40 @@ deleteCollection: 删除集合`),
|
|
|
4323
4420
|
};
|
|
4324
4421
|
}
|
|
4325
4422
|
if (action === "deleteCollection") {
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
});
|
|
4333
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
4334
|
-
const body = withCollectionName(collectionName, {
|
|
4335
|
-
success: true,
|
|
4336
|
-
requestId: result.RequestId,
|
|
4337
|
-
action,
|
|
4338
|
-
message: result.Exists === false ? "集合不存在" : "云开发数据库集合删除成功",
|
|
4339
|
-
});
|
|
4340
|
-
if (result.Exists === false) {
|
|
4341
|
-
body.exists = false;
|
|
4342
|
-
}
|
|
4343
|
-
return {
|
|
4344
|
-
content: [
|
|
4345
|
-
{
|
|
4346
|
-
type: "text",
|
|
4347
|
-
text: JSON.stringify(body, null, 2),
|
|
4423
|
+
try {
|
|
4424
|
+
const result = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
4425
|
+
Action: "DeleteTable",
|
|
4426
|
+
Param: {
|
|
4427
|
+
EnvId: await (0, cloudbase_manager_js_1.getEnvId)(server.cloudBaseOptions),
|
|
4428
|
+
TableName: collectionName,
|
|
4348
4429
|
},
|
|
4349
|
-
|
|
4350
|
-
|
|
4430
|
+
});
|
|
4431
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
4432
|
+
const body = withCollectionName(collectionName, {
|
|
4433
|
+
success: true,
|
|
4434
|
+
requestId: result.RequestId,
|
|
4435
|
+
action,
|
|
4436
|
+
message: result.Exists === false ? "集合不存在" : "云开发数据库集合删除成功",
|
|
4437
|
+
});
|
|
4438
|
+
if (result.Exists === false) {
|
|
4439
|
+
body.exists = false;
|
|
4440
|
+
}
|
|
4441
|
+
return {
|
|
4442
|
+
content: [
|
|
4443
|
+
{
|
|
4444
|
+
type: "text",
|
|
4445
|
+
text: JSON.stringify(body, null, 2),
|
|
4446
|
+
},
|
|
4447
|
+
],
|
|
4448
|
+
};
|
|
4449
|
+
}
|
|
4450
|
+
catch (error) {
|
|
4451
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4452
|
+
if (/parameter invalid|invalid parameter|param(eter)?\s+invalid/i.test(message)) {
|
|
4453
|
+
throw new Error(`deleteCollection 参数校验失败,请确认 collectionName 合法且已存在。当前 collectionName=\"${collectionName}\"。原始错误:${message}`);
|
|
4454
|
+
}
|
|
4455
|
+
throw error;
|
|
4456
|
+
}
|
|
4351
4457
|
}
|
|
4352
4458
|
throw new Error(`不支持的操作类型: ${action}`);
|
|
4353
4459
|
});
|
|
@@ -6861,15 +6967,42 @@ function registerGatewayTools(server) {
|
|
|
6861
6967
|
case "deleteAccess": {
|
|
6862
6968
|
const cloudbase = await getManager();
|
|
6863
6969
|
const accessPath = input.path ? normalizeAccessPath(input.path) : undefined;
|
|
6970
|
+
let resolvedAccessId = input.accessId;
|
|
6971
|
+
if (!resolvedAccessId) {
|
|
6972
|
+
if (!input.targetName && !accessPath) {
|
|
6973
|
+
throw new Error("action=deleteAccess 时至少需要提供 accessId,或提供 targetName/path 用于定位入口");
|
|
6974
|
+
}
|
|
6975
|
+
const accessList = await cloudbase.access.getAccessList({
|
|
6976
|
+
...(input.targetName ? { name: input.targetName } : {}),
|
|
6977
|
+
...(accessPath ? { path: accessPath } : {}),
|
|
6978
|
+
});
|
|
6979
|
+
const candidates = (accessList.APISet ?? []).filter((item) => {
|
|
6980
|
+
if (!accessPath) {
|
|
6981
|
+
return true;
|
|
6982
|
+
}
|
|
6983
|
+
return normalizeAccessPath(item.Path) === accessPath;
|
|
6984
|
+
});
|
|
6985
|
+
if (candidates.length === 0) {
|
|
6986
|
+
throw new Error("未找到可删除的访问入口,请确认 targetName/path 或直接传 accessId");
|
|
6987
|
+
}
|
|
6988
|
+
if (candidates.length > 1 && !accessPath) {
|
|
6989
|
+
throw new Error("匹配到多个访问入口,请补充 path 或直接传 accessId");
|
|
6990
|
+
}
|
|
6991
|
+
resolvedAccessId = candidates[0]?.APIId;
|
|
6992
|
+
}
|
|
6993
|
+
if (!resolvedAccessId) {
|
|
6994
|
+
throw new Error("无法解析访问入口 accessId,请改为显式传入 accessId");
|
|
6995
|
+
}
|
|
6864
6996
|
const result = await cloudbase.access.deleteAccess({
|
|
6865
6997
|
...(input.targetName ? { name: input.targetName } : {}),
|
|
6866
|
-
|
|
6998
|
+
apiId: resolvedAccessId,
|
|
6867
6999
|
});
|
|
6868
7000
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
6869
7001
|
return buildEnvelope({
|
|
6870
7002
|
action: input.action,
|
|
6871
7003
|
targetName: input.targetName ?? null,
|
|
6872
7004
|
path: accessPath ?? null,
|
|
7005
|
+
accessId: resolvedAccessId,
|
|
6873
7006
|
raw: result,
|
|
6874
7007
|
}, "网关访问入口删除成功");
|
|
6875
7008
|
}
|
|
@@ -6971,6 +7104,7 @@ function registerGatewayTools(server) {
|
|
|
6971
7104
|
domain: zod_1.z.string().optional().describe("自定义域名"),
|
|
6972
7105
|
certificateId: zod_1.z.string().optional().describe("证书 ID"),
|
|
6973
7106
|
accessName: zod_1.z.string().optional().describe("访问入口名称,保留字段"),
|
|
7107
|
+
accessId: zod_1.z.string().optional().describe("访问入口 ID。deleteAccess 时可直接传入,避免参数歧义"),
|
|
6974
7108
|
},
|
|
6975
7109
|
annotations: {
|
|
6976
7110
|
readOnlyHint: false,
|
|
@@ -9122,7 +9256,7 @@ class TelemetryReporter {
|
|
|
9122
9256
|
const nodeVersion = process.version; // Node.js版本
|
|
9123
9257
|
const arch = os_1.default.arch(); // 系统架构
|
|
9124
9258
|
// 从构建时注入的版本号获取MCP版本信息
|
|
9125
|
-
const mcpVersion = process.env.npm_package_version || "2.
|
|
9259
|
+
const mcpVersion = process.env.npm_package_version || "2.20.0-beta.0" || 0;
|
|
9126
9260
|
return {
|
|
9127
9261
|
userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
|
|
9128
9262
|
deviceId: this.deviceId,
|
|
@@ -11023,10 +11157,11 @@ function registerPermissionTools(server) {
|
|
|
11023
11157
|
roleId: zod_1.z.string().optional(),
|
|
11024
11158
|
roleIds: zod_1.z.array(zod_1.z.string()).optional(),
|
|
11025
11159
|
roleName: zod_1.z.string().optional(),
|
|
11026
|
-
roleIdentity: zod_1.z.string().optional(),
|
|
11160
|
+
roleIdentity: zod_1.z.string().optional().describe("角色标识符(字母/数字/_-:@.),action=createRole 时必填,用于程序化引用角色"),
|
|
11027
11161
|
description: zod_1.z.string().optional(),
|
|
11028
11162
|
memberUids: zod_1.z.array(zod_1.z.string()).optional(),
|
|
11029
11163
|
policies: zod_1.z.array(zod_1.z.record(zod_1.z.any())).optional(),
|
|
11164
|
+
policyIds: zod_1.z.array(zod_1.z.string()).optional().describe("策略 ID 列表(当前不支持直接按 ID 绑定,请改传 policies 详情对象)"),
|
|
11030
11165
|
uid: zod_1.z.string().optional(),
|
|
11031
11166
|
uids: zod_1.z.array(zod_1.z.string()).optional(),
|
|
11032
11167
|
username: zod_1.z.string().optional(),
|
|
@@ -11040,7 +11175,7 @@ function registerPermissionTools(server) {
|
|
|
11040
11175
|
openWorldHint: true,
|
|
11041
11176
|
category: "permissions",
|
|
11042
11177
|
},
|
|
11043
|
-
}, async ({ action, resourceType, resourceId, permission, securityRule, roleId, roleIds, roleName, roleIdentity, description, memberUids, policies, uid, uids, username, password, userStatus, }) => withEnvelope(async () => {
|
|
11178
|
+
}, async ({ action, resourceType, resourceId, permission, securityRule, roleId, roleIds, roleName, roleIdentity, description, memberUids, policies, policyIds, uid, uids, username, password, userStatus, }) => withEnvelope(async () => {
|
|
11044
11179
|
const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
11045
11180
|
const cloudbase = await getManager();
|
|
11046
11181
|
const normalizedPolicies = normalizeRecordArray(policies, "policies");
|
|
@@ -11100,6 +11235,14 @@ function registerPermissionTools(server) {
|
|
|
11100
11235
|
if (!roleId) {
|
|
11101
11236
|
throw new Error(`action=${action} 时必须提供 roleId`);
|
|
11102
11237
|
}
|
|
11238
|
+
if (action === "addRolePolicies" || action === "removeRolePolicies") {
|
|
11239
|
+
if (policyIds?.length) {
|
|
11240
|
+
throw new Error(`action=${action} 暂不支持 policyIds。请改传 policies,且每项至少包含 ResourceType 和 Resource。`);
|
|
11241
|
+
}
|
|
11242
|
+
if (!normalizedPolicies?.length) {
|
|
11243
|
+
throw new Error(`action=${action} 时必须提供 policies,且每项至少包含 ResourceType 和 Resource。`);
|
|
11244
|
+
}
|
|
11245
|
+
}
|
|
11103
11246
|
const result = await cloudbase.permission.modifyRole({
|
|
11104
11247
|
roleId,
|
|
11105
11248
|
...(action === "updateRole"
|
|
@@ -11669,7 +11812,7 @@ function registerSetupTools(server) {
|
|
|
11669
11812
|
server.registerTool("downloadTemplate", {
|
|
11670
11813
|
title: "下载项目模板",
|
|
11671
11814
|
description: `自动下载并部署CloudBase项目模板。
|
|
11672
|
-
**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.
|
|
11815
|
+
**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.20.0-beta.0" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
|
|
11673
11816
|
inputSchema: {
|
|
11674
11817
|
template: zod_1.z
|
|
11675
11818
|
.enum(["react", "vue", "miniprogram", "uniapp", "rules"])
|
|
@@ -13467,8 +13610,21 @@ function updateAuthProgressState(partial) {
|
|
|
13467
13610
|
return getAuthProgressStateSync();
|
|
13468
13611
|
}
|
|
13469
13612
|
function normalizeLoginStateFromEnvVars(options) {
|
|
13613
|
+
if (options?.ignoreEnvVars) {
|
|
13614
|
+
return null;
|
|
13615
|
+
}
|
|
13616
|
+
// 优先检查 CloudBase API Key(优先级高于 TENCENTCLOUD_*)
|
|
13617
|
+
const { CLOUDBASE_API_KEY, CLOUDBASE_ENV_ID: CLOUDBASE_ENV, } = process.env;
|
|
13618
|
+
if (CLOUDBASE_API_KEY && CLOUDBASE_ENV) {
|
|
13619
|
+
return {
|
|
13620
|
+
_type: 'api_key',
|
|
13621
|
+
apiKey: CLOUDBASE_API_KEY,
|
|
13622
|
+
envId: CLOUDBASE_ENV,
|
|
13623
|
+
};
|
|
13624
|
+
}
|
|
13625
|
+
// 然后检查腾讯云密钥环境变量
|
|
13470
13626
|
const { TENCENTCLOUD_SECRETID, TENCENTCLOUD_SECRETKEY, TENCENTCLOUD_SESSIONTOKEN, } = process.env;
|
|
13471
|
-
if (
|
|
13627
|
+
if (TENCENTCLOUD_SECRETID && TENCENTCLOUD_SECRETKEY) {
|
|
13472
13628
|
return {
|
|
13473
13629
|
secretId: TENCENTCLOUD_SECRETID,
|
|
13474
13630
|
secretKey: TENCENTCLOUD_SECRETKEY,
|
|
@@ -13611,13 +13767,30 @@ function resetAuthProgressState() {
|
|
|
13611
13767
|
async function peekLoginState(options) {
|
|
13612
13768
|
const envVarLoginState = normalizeLoginStateFromEnvVars(options);
|
|
13613
13769
|
if (envVarLoginState) {
|
|
13770
|
+
// API Key 模式:需要先用 API Key 换取临时密钥
|
|
13771
|
+
if ('_type' in envVarLoginState && envVarLoginState._type === 'api_key') {
|
|
13772
|
+
(0, logger_js_1.debug)("peekLoginState: detected CLOUDBASE_API_KEY env var");
|
|
13773
|
+
try {
|
|
13774
|
+
// 优先使用 IDE 注入的工作目录,其次 process.cwd()
|
|
13775
|
+
const projectCwd = process.env.WORKSPACE_FOLDER_PATHS || process.cwd();
|
|
13776
|
+
const credential = await auth.loginByApiKey(envVarLoginState.apiKey, envVarLoginState.envId, { cwd: projectCwd });
|
|
13777
|
+
return credential;
|
|
13778
|
+
}
|
|
13779
|
+
catch (e) {
|
|
13780
|
+
(0, logger_js_1.debug)("peekLoginState: API Key login failed", { error: e instanceof Error ? e.message : String(e) });
|
|
13781
|
+
return null;
|
|
13782
|
+
}
|
|
13783
|
+
}
|
|
13784
|
+
// 腾讯云密钥模式:直接返回
|
|
13614
13785
|
(0, logger_js_1.debug)("loginByApiSecret");
|
|
13615
13786
|
return envVarLoginState;
|
|
13616
13787
|
}
|
|
13788
|
+
// 尝试从 toolbox 本地存储读取(包括项目级 API Key 凭证)
|
|
13617
13789
|
return auth.getLoginState();
|
|
13618
13790
|
}
|
|
13619
13791
|
async function ensureLogin(options) {
|
|
13620
13792
|
(0, logger_js_1.debug)("TENCENTCLOUD_SECRETID", { hasSecretId: !!process.env.TENCENTCLOUD_SECRETID });
|
|
13793
|
+
(0, logger_js_1.debug)("CLOUDBASE_API_KEY", { hasApiKey: !!process.env.CLOUDBASE_API_KEY });
|
|
13621
13794
|
const loginState = await peekLoginState({
|
|
13622
13795
|
ignoreEnvVars: options?.ignoreEnvVars,
|
|
13623
13796
|
});
|
|
@@ -13693,7 +13866,8 @@ async function getLoginState(options) {
|
|
|
13693
13866
|
return ensureLogin(options);
|
|
13694
13867
|
}
|
|
13695
13868
|
async function logout() {
|
|
13696
|
-
const
|
|
13869
|
+
const cwd = process.env.WORKSPACE_FOLDER_PATHS || process.cwd();
|
|
13870
|
+
const result = await auth.logout({ cwd });
|
|
13697
13871
|
resetAuthProgressState();
|
|
13698
13872
|
return result;
|
|
13699
13873
|
}
|
|
@@ -14376,10 +14550,11 @@ function normalizeAgentPayload(params) {
|
|
|
14376
14550
|
if (!params) {
|
|
14377
14551
|
return {};
|
|
14378
14552
|
}
|
|
14379
|
-
const { name, agentId, runtime, timeout, memorySize, installDependency, ...rest } = params;
|
|
14553
|
+
const { name, description, agentId, runtime, timeout, memorySize, installDependency, zipFile, cosBucketRegion, tempCosObjectName, sessionConfig, ...rest } = params;
|
|
14380
14554
|
return {
|
|
14381
14555
|
...rest,
|
|
14382
14556
|
...(normalizeString(name) ? { Name: normalizeString(name) } : {}),
|
|
14557
|
+
...(normalizeString(description) ? { Description: normalizeString(description) } : {}),
|
|
14383
14558
|
...(normalizeString(agentId) ? { AgentId: normalizeString(agentId) } : {}),
|
|
14384
14559
|
...(normalizeString(runtime) ? { Runtime: normalizeString(runtime) } : {}),
|
|
14385
14560
|
...(normalizeNumber(timeout) !== undefined ? { Timeout: normalizeNumber(timeout) } : {}),
|
|
@@ -14389,6 +14564,14 @@ function normalizeAgentPayload(params) {
|
|
|
14389
14564
|
...(normalizeBoolean(installDependency) !== undefined
|
|
14390
14565
|
? { InstallDependency: normalizeBoolean(installDependency) }
|
|
14391
14566
|
: {}),
|
|
14567
|
+
...(normalizeString(zipFile) ? { ZipFile: normalizeString(zipFile) } : {}),
|
|
14568
|
+
...(normalizeString(cosBucketRegion)
|
|
14569
|
+
? { CosBucketRegion: normalizeString(cosBucketRegion) }
|
|
14570
|
+
: {}),
|
|
14571
|
+
...(normalizeString(tempCosObjectName)
|
|
14572
|
+
? { TempCosObjectName: normalizeString(tempCosObjectName) }
|
|
14573
|
+
: {}),
|
|
14574
|
+
...(sessionConfig && typeof sessionConfig === "object" ? { SessionConfig: sessionConfig } : {}),
|
|
14392
14575
|
};
|
|
14393
14576
|
}
|
|
14394
14577
|
function registerAgentTools(server) {
|
|
@@ -14463,6 +14646,17 @@ function registerAgentTools(server) {
|
|
|
14463
14646
|
inputSchema: {
|
|
14464
14647
|
action: zod_1.z.enum(MANAGE_AGENT_ACTIONS),
|
|
14465
14648
|
agentId: zod_1.z.string().optional(),
|
|
14649
|
+
name: zod_1.z.string().optional(),
|
|
14650
|
+
description: zod_1.z.string().optional(),
|
|
14651
|
+
runtime: zod_1.z.string().optional(),
|
|
14652
|
+
timeout: zod_1.z.number().optional(),
|
|
14653
|
+
memorySize: zod_1.z.number().optional(),
|
|
14654
|
+
installDependency: zod_1.z.boolean().optional(),
|
|
14655
|
+
zipFile: zod_1.z.string().optional(),
|
|
14656
|
+
cosBucketRegion: zod_1.z.string().optional(),
|
|
14657
|
+
tempCosObjectName: zod_1.z.string().optional(),
|
|
14658
|
+
sessionConfig: zod_1.z.record(zod_1.z.any()).optional(),
|
|
14659
|
+
cwd: zod_1.z.string().optional(),
|
|
14466
14660
|
params: zod_1.z.record(zod_1.z.any()).optional(),
|
|
14467
14661
|
},
|
|
14468
14662
|
annotations: {
|
|
@@ -14472,14 +14666,31 @@ function registerAgentTools(server) {
|
|
|
14472
14666
|
openWorldHint: true,
|
|
14473
14667
|
category: "agents",
|
|
14474
14668
|
},
|
|
14475
|
-
}, async ({ action, agentId, params, }) => {
|
|
14669
|
+
}, async ({ action, agentId, name, description, runtime, timeout, memorySize, installDependency, zipFile, cosBucketRegion, tempCosObjectName, sessionConfig, cwd, params, }) => {
|
|
14476
14670
|
try {
|
|
14477
14671
|
const cloudbase = await getManager();
|
|
14478
|
-
const payload = normalizeAgentPayload(
|
|
14672
|
+
const payload = normalizeAgentPayload({
|
|
14673
|
+
name,
|
|
14674
|
+
description,
|
|
14675
|
+
runtime,
|
|
14676
|
+
timeout,
|
|
14677
|
+
memorySize,
|
|
14678
|
+
installDependency,
|
|
14679
|
+
zipFile,
|
|
14680
|
+
cosBucketRegion,
|
|
14681
|
+
tempCosObjectName,
|
|
14682
|
+
sessionConfig,
|
|
14683
|
+
cwd,
|
|
14684
|
+
...(params ?? {}),
|
|
14685
|
+
});
|
|
14479
14686
|
if (action === "createAgent") {
|
|
14687
|
+
const normalizedName = normalizeString(payload.Name);
|
|
14688
|
+
if (!normalizedName) {
|
|
14689
|
+
throw new Error("action=createAgent 时必须提供 name(可通过顶层 name 或 params.name 传入)");
|
|
14690
|
+
}
|
|
14480
14691
|
const createPayload = {
|
|
14481
14692
|
...payload,
|
|
14482
|
-
Name:
|
|
14693
|
+
Name: normalizedName,
|
|
14483
14694
|
Runtime: normalizeString(payload.Runtime) ?? "Nodejs20.19",
|
|
14484
14695
|
};
|
|
14485
14696
|
const result = await cloudbase.agent.createAgent(createPayload);
|
|
@@ -14607,6 +14818,8 @@ function shouldRegisterTool(toolName) {
|
|
|
14607
14818
|
'manageCloudRun',
|
|
14608
14819
|
// Download tools - local file downloads
|
|
14609
14820
|
'manageStorage',
|
|
14821
|
+
// Apps tools - deployApp reads local filePath for code upload
|
|
14822
|
+
'manageApps',
|
|
14610
14823
|
];
|
|
14611
14824
|
const shouldRegister = !cloudIncompatibleTools.includes(toolName);
|
|
14612
14825
|
if (!shouldRegister) {
|
|
@@ -14637,6 +14850,7 @@ const QUERY_ACTIONS = [
|
|
|
14637
14850
|
"describeCreateResult",
|
|
14638
14851
|
"describeTaskStatus",
|
|
14639
14852
|
"getInstanceInfo",
|
|
14853
|
+
"describeInstance",
|
|
14640
14854
|
];
|
|
14641
14855
|
const MANAGE_ACTIONS = [
|
|
14642
14856
|
"provisionMySQL",
|
|
@@ -14900,7 +15114,9 @@ async function getSqlInstanceInfo({ getManager, cloudBaseOptions, server, }) {
|
|
|
14900
15114
|
}
|
|
14901
15115
|
catch (error) {
|
|
14902
15116
|
const errorCode = extractErrorCode(error);
|
|
14903
|
-
const
|
|
15117
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
15118
|
+
const isNotFound = errorCode === "FailedOperation.DataSourceNotExist"
|
|
15119
|
+
|| /envLink not exist|not exist|not found/i.test(errorMessage);
|
|
14904
15120
|
if (!isNotFound) {
|
|
14905
15121
|
throw error;
|
|
14906
15122
|
}
|
|
@@ -14910,7 +15126,7 @@ async function getSqlInstanceInfo({ getManager, cloudBaseOptions, server, }) {
|
|
|
14910
15126
|
instanceId: "default",
|
|
14911
15127
|
schema: envId,
|
|
14912
15128
|
rawStatus: typeof createRawStatus === "string" ? createRawStatus : null,
|
|
14913
|
-
status: createStatus,
|
|
15129
|
+
status: createStatus === "PENDING" || createStatus === "RUNNING" ? createStatus : "NOT_CREATED",
|
|
14914
15130
|
createResult: createData ?? createResult,
|
|
14915
15131
|
};
|
|
14916
15132
|
}
|
|
@@ -15457,7 +15673,7 @@ function registerSQLDatabaseTools(server) {
|
|
|
15457
15673
|
inputSchema: {
|
|
15458
15674
|
action: zod_1.z
|
|
15459
15675
|
.enum(QUERY_ACTIONS)
|
|
15460
|
-
.describe("runQuery=execute read-only SQL; describeCreateResult=query CreateMySQL result; describeTaskStatus=query MySQL task status; getInstanceInfo=get current SQL instance context"),
|
|
15676
|
+
.describe("runQuery=execute read-only SQL; describeCreateResult=query CreateMySQL result; describeTaskStatus=query MySQL task status; getInstanceInfo=get current SQL instance context; describeInstance=alias of getInstanceInfo"),
|
|
15461
15677
|
sql: zod_1.z
|
|
15462
15678
|
.string()
|
|
15463
15679
|
.optional()
|
|
@@ -15488,6 +15704,7 @@ function registerSQLDatabaseTools(server) {
|
|
|
15488
15704
|
case "describeTaskStatus":
|
|
15489
15705
|
return handleDescribeTaskStatus(args, context);
|
|
15490
15706
|
case "getInstanceInfo":
|
|
15707
|
+
case "describeInstance":
|
|
15491
15708
|
return handleGetInstanceInfo(context);
|
|
15492
15709
|
default:
|
|
15493
15710
|
throw new Error(`Unsupported SQL query action: ${args.action}`);
|