@cloudbase/cloudbase-mcp 2.21.0 → 2.21.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli.cjs +3 -3
- package/dist/index.cjs +801 -700
- package/dist/index.d.ts +109 -1
- package/dist/index.js +770 -695
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -183,17 +183,17 @@ function buildEnvDomainManagementResult(params) {
|
|
|
183
183
|
operation: action,
|
|
184
184
|
targetDomains: domains,
|
|
185
185
|
asyncState: "PENDING",
|
|
186
|
-
message: '安全域名已提交添加请求。该变更通常需要约 10 分钟传播,请继续轮询
|
|
186
|
+
message: '安全域名已提交添加请求。该变更通常需要约 10 分钟传播,请继续轮询 queryEnv(action="domains"),直到目标域名状态为 ENABLE。',
|
|
187
187
|
propagation: {
|
|
188
188
|
requiresPolling: true,
|
|
189
|
-
pollTool: "
|
|
189
|
+
pollTool: "queryEnv",
|
|
190
190
|
pollAction: "domains",
|
|
191
191
|
pollIntervalSuggestionSeconds: 10,
|
|
192
192
|
timeoutSuggestionSeconds: 600,
|
|
193
|
-
successCondition: '目标域名出现在
|
|
193
|
+
successCondition: '目标域名出现在 queryEnv(action="domains") 返回中,且 Status 为 ENABLE。',
|
|
194
194
|
},
|
|
195
195
|
next_step: {
|
|
196
|
-
tool: "
|
|
196
|
+
tool: "queryEnv",
|
|
197
197
|
action: "domains",
|
|
198
198
|
suggested_args: {
|
|
199
199
|
action: "domains",
|
|
@@ -208,17 +208,17 @@ function buildEnvDomainManagementResult(params) {
|
|
|
208
208
|
operation: action,
|
|
209
209
|
targetDomains: domains,
|
|
210
210
|
asyncState: "PENDING",
|
|
211
|
-
message: '安全域名已提交删除请求。该变更可能需要数分钟传播,请继续轮询
|
|
211
|
+
message: '安全域名已提交删除请求。该变更可能需要数分钟传播,请继续轮询 queryEnv(action="domains"),直到目标域名不再出现。',
|
|
212
212
|
propagation: {
|
|
213
213
|
requiresPolling: true,
|
|
214
|
-
pollTool: "
|
|
214
|
+
pollTool: "queryEnv",
|
|
215
215
|
pollAction: "domains",
|
|
216
216
|
pollIntervalSuggestionSeconds: 10,
|
|
217
217
|
timeoutSuggestionSeconds: 600,
|
|
218
|
-
successCondition: '目标域名不再出现在
|
|
218
|
+
successCondition: '目标域名不再出现在 queryEnv(action="domains") 返回中。',
|
|
219
219
|
},
|
|
220
220
|
next_step: {
|
|
221
|
-
tool: "
|
|
221
|
+
tool: "queryEnv",
|
|
222
222
|
action: "domains",
|
|
223
223
|
suggested_args: {
|
|
224
224
|
action: "domains",
|
|
@@ -492,7 +492,7 @@ function buildEnvQueryListResult(params) {
|
|
|
492
492
|
const paginated = paginateEnvList(filteredList, params.filters.offset, params.filters.limit);
|
|
493
493
|
const exactEnvIdSummaryHint = params.filters.envId
|
|
494
494
|
? {
|
|
495
|
-
tool: "
|
|
495
|
+
tool: "queryEnv",
|
|
496
496
|
action: "info",
|
|
497
497
|
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.",
|
|
498
498
|
}
|
|
@@ -563,7 +563,7 @@ function normalizeOptionalToolString(value) {
|
|
|
563
563
|
: undefined;
|
|
564
564
|
}
|
|
565
565
|
/**
|
|
566
|
-
* Build enhanced error message for
|
|
566
|
+
* Build enhanced error message for queryEnv tool errors
|
|
567
567
|
* Provides actionable guidance based on error patterns
|
|
568
568
|
*/
|
|
569
569
|
function buildEnvQueryErrorMessage(error, action) {
|
|
@@ -579,7 +579,7 @@ function buildEnvQueryErrorMessage(error, action) {
|
|
|
579
579
|
suggestions.push("参数错误:可能是认证信息无效或已过期,请尝试以下步骤:");
|
|
580
580
|
suggestions.push("1. 先调用 auth(action=\"status\") 检查当前登录状态");
|
|
581
581
|
suggestions.push("2. 如果未登录,调用 auth(action=\"start_auth\", authMode=\"device\") 完成登录");
|
|
582
|
-
suggestions.push("3. 登录完成后再次调用
|
|
582
|
+
suggestions.push("3. 登录完成后再次调用 queryEnv(action=\"list\")");
|
|
583
583
|
}
|
|
584
584
|
if (hasAuthError) {
|
|
585
585
|
suggestions.push("认证错误:当前未登录或认证已过期。");
|
|
@@ -591,7 +591,7 @@ function buildEnvQueryErrorMessage(error, action) {
|
|
|
591
591
|
}
|
|
592
592
|
if (hasEnvNotFoundError) {
|
|
593
593
|
suggestions.push("环境错误:指定的环境不存在或无法访问。");
|
|
594
|
-
suggestions.push("请使用
|
|
594
|
+
suggestions.push("请使用 queryEnv(action=\"list\") 查看可用的环境列表。");
|
|
595
595
|
}
|
|
596
596
|
if (hasNetworkError) {
|
|
597
597
|
suggestions.push("网络错误:请检查网络连接,稍后重试。");
|
|
@@ -603,7 +603,7 @@ function buildEnvQueryErrorMessage(error, action) {
|
|
|
603
603
|
suggestions.push("2. 如未登录,执行 auth(action=\"start_auth\") 完成认证");
|
|
604
604
|
suggestions.push("3. 确认环境 ID 正确且可访问");
|
|
605
605
|
}
|
|
606
|
-
return `[
|
|
606
|
+
return `[queryEnv/${action}] 调用失败: ${baseMessage}\n\n解决建议:\n${suggestions.join("\n")}`;
|
|
607
607
|
}
|
|
608
608
|
function normalizeOptionalToolBoolean(value) {
|
|
609
609
|
return typeof value === "boolean" ? value : undefined;
|
|
@@ -632,519 +632,500 @@ function registerEnvTools(server) {
|
|
|
632
632
|
const supportedAuthActions = getSupportedAuthActions(server);
|
|
633
633
|
const authActionEnum = [...supportedAuthActions];
|
|
634
634
|
// auth - CloudBase (云开发) 开发阶段登录与环境绑定
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
.
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
.
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
.
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
.
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
.
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
envId: zod_1.z
|
|
664
|
-
.string()
|
|
665
|
-
.optional()
|
|
666
|
-
.describe("环境ID(CloudBase 环境唯一标识),绑定后工具将操作该环境。action=set_env 时必填"),
|
|
667
|
-
...(supportedAuthActions.includes("logout")
|
|
668
|
-
? {
|
|
669
|
-
confirm: zod_1.z
|
|
670
|
-
.literal("yes")
|
|
671
|
-
.optional()
|
|
672
|
-
.describe("action=logout 时确认操作,传 yes"),
|
|
673
|
-
}
|
|
674
|
-
: {}),
|
|
675
|
-
...(supportedAuthActions.includes("get_temp_credentials")
|
|
676
|
-
? {
|
|
677
|
-
reveal: zod_1.z
|
|
678
|
-
.boolean()
|
|
679
|
-
.optional()
|
|
680
|
-
.describe("action=get_temp_credentials 时可选。true=返回明文临时密钥;默认 false 仅返回脱敏结果"),
|
|
681
|
-
}
|
|
682
|
-
: {}),
|
|
683
|
-
},
|
|
684
|
-
annotations: {
|
|
685
|
-
readOnlyHint: false,
|
|
686
|
-
destructiveHint: false,
|
|
687
|
-
idempotentHint: false,
|
|
688
|
-
openWorldHint: true,
|
|
689
|
-
category: "env",
|
|
690
|
-
},
|
|
691
|
-
}, async (rawArgs) => {
|
|
692
|
-
const action = rawArgs.action ?? "status";
|
|
693
|
-
const authMode = rawArgs.authMode === "device" || rawArgs.authMode === "web"
|
|
694
|
-
? rawArgs.authMode
|
|
695
|
-
: undefined;
|
|
696
|
-
const oauthEndpoint = normalizeOptionalToolString(rawArgs.oauthEndpoint);
|
|
697
|
-
const clientId = normalizeOptionalToolString(rawArgs.clientId);
|
|
698
|
-
const oauthCustom = normalizeOptionalToolBoolean(rawArgs.oauthCustom);
|
|
699
|
-
const envId = rawArgs.envId;
|
|
700
|
-
const confirm = rawArgs.confirm === "yes" ? "yes" : undefined;
|
|
701
|
-
const reveal = normalizeOptionalToolBoolean(rawArgs.reveal) === true;
|
|
702
|
-
const resolvedAuthOptions = resolveToolAuthOptions(server, {
|
|
703
|
-
authMode,
|
|
704
|
-
oauthEndpoint,
|
|
705
|
-
clientId,
|
|
706
|
-
oauthCustom,
|
|
707
|
-
});
|
|
708
|
-
const authConfigSummary = (0, auth_js_1.buildAuthConfigSummary)(resolvedAuthOptions);
|
|
709
|
-
let deviceAuthInfo;
|
|
710
|
-
const onDeviceCode = (info) => {
|
|
711
|
-
deviceAuthInfo = info;
|
|
712
|
-
(0, auth_js_1.setPendingAuthProgressState)(info, "device");
|
|
713
|
-
// emitDeviceAuthNotice(server, info);
|
|
714
|
-
};
|
|
715
|
-
const authChallenge = () => (0, auth_js_1.buildDeviceAuthChallengePayload)(deviceAuthInfo);
|
|
716
|
-
try {
|
|
717
|
-
if (!supportedAuthActions.includes(action)) {
|
|
718
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
719
|
-
ok: false,
|
|
720
|
-
code: "NOT_SUPPORTED",
|
|
721
|
-
message: `当前 IDE 不支持 auth(action="${action}")。`,
|
|
722
|
-
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
723
|
-
suggestedArgs: { action: "status" },
|
|
724
|
-
}),
|
|
725
|
-
});
|
|
726
|
-
}
|
|
727
|
-
if (action === "status") {
|
|
728
|
-
const loginState = await (0, auth_js_1.peekLoginState)();
|
|
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);
|
|
732
|
-
const authStatus = loginState
|
|
733
|
-
? "READY"
|
|
734
|
-
: authFlowState.status === "PENDING"
|
|
735
|
-
? "PENDING"
|
|
736
|
-
: "REQUIRED";
|
|
737
|
-
let envPreparation;
|
|
738
|
-
const message = authStatus === "READY"
|
|
739
|
-
? undefined
|
|
740
|
-
: authStatus === "PENDING"
|
|
741
|
-
? "设备码授权进行中,请完成浏览器授权后再次调用 auth(action=\"status\")"
|
|
742
|
-
: isCodeBuddyIde(server)
|
|
743
|
-
? "当前未登录。CodeBuddy 暂不支持在 tool 内发起认证,请在外部完成认证后再次调用 auth(action=\"status\")。"
|
|
744
|
-
: "当前未登录,请先执行 auth(action=\"start_auth\")";
|
|
745
|
-
if (authStatus === "READY" && loginState) {
|
|
746
|
-
envPreparation = await prepareAuthEnvironment({
|
|
747
|
-
server,
|
|
748
|
-
cloudBaseOptions,
|
|
749
|
-
loginState,
|
|
750
|
-
});
|
|
751
|
-
}
|
|
752
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
753
|
-
ok: true,
|
|
754
|
-
code: "STATUS",
|
|
755
|
-
auth_status: authStatus,
|
|
756
|
-
...(isApiKeyMode ? { auth_mode: "api_key" } : {}),
|
|
757
|
-
auth_config: authConfigSummary,
|
|
758
|
-
...(envPreparation
|
|
759
|
-
? buildAuthEnvSetupPayload(envPreparation)
|
|
760
|
-
: {
|
|
761
|
-
env_status: "NONE",
|
|
762
|
-
current_env_id: null,
|
|
763
|
-
...buildEnvCandidatePayload([]),
|
|
764
|
-
}),
|
|
765
|
-
auth_challenge: authFlowState.status === "PENDING"
|
|
766
|
-
? (0, auth_js_1.buildDeviceAuthChallengePayload)(authFlowState.authChallenge)
|
|
767
|
-
: undefined,
|
|
768
|
-
message,
|
|
769
|
-
next_step: authStatus === "REQUIRED"
|
|
770
|
-
? buildAuthRequiredNextStep(server)
|
|
771
|
-
: authStatus === "PENDING"
|
|
772
|
-
? (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
773
|
-
suggestedArgs: { action: "status" },
|
|
774
|
-
})
|
|
775
|
-
: envPreparation?.nextStep,
|
|
776
|
-
});
|
|
777
|
-
}
|
|
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
|
-
}
|
|
635
|
+
// 微信 IDE 使用票据认证,不需要登录工具
|
|
636
|
+
if (server.ide !== 'wxide') {
|
|
637
|
+
server.registerTool?.("auth", {
|
|
638
|
+
title: "CloudBase 开发阶段登录与环境",
|
|
639
|
+
description: "CloudBase(腾讯云开发)开发阶段登录与环境绑定。登录后即可访问云资源;环境(env)是云函数、数据库、静态托管等资源的隔离单元,绑定环境后其他 MCP 工具才能操作该环境。支持:查询状态、发起登录、绑定环境(set_env)、退出登录。",
|
|
640
|
+
inputSchema: {
|
|
641
|
+
action: zod_1.z
|
|
642
|
+
.enum(authActionEnum)
|
|
643
|
+
.optional()
|
|
644
|
+
.describe("动作:status=查询状态,start_auth=发起登录,set_env=绑定环境(传envId),logout=退出登录"),
|
|
645
|
+
...(supportedAuthActions.includes("start_auth")
|
|
646
|
+
? {
|
|
647
|
+
authMode: zod_1.z
|
|
648
|
+
.enum(["device", "web"])
|
|
649
|
+
.optional()
|
|
650
|
+
.describe("认证模式:device=设备码授权,web=浏览器回调授权"),
|
|
651
|
+
oauthEndpoint: zod_1.z
|
|
652
|
+
.string()
|
|
653
|
+
.optional()
|
|
654
|
+
.describe("高级可选:自定义 device-code 登录 endpoint。配置后 oauthCustom 默认按 true 处理"),
|
|
655
|
+
clientId: zod_1.z
|
|
656
|
+
.string()
|
|
657
|
+
.optional()
|
|
658
|
+
.describe("高级可选:自定义 device-code 登录 client_id,不传则使用默认值"),
|
|
659
|
+
oauthCustom: zod_1.z
|
|
660
|
+
.boolean()
|
|
661
|
+
.optional()
|
|
662
|
+
.describe("高级可选:自定义 endpoint 返回格式开关。未配置 endpoint 时默认 false;配置 endpoint 后默认 true,且不能设为 false"),
|
|
792
663
|
}
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
664
|
+
: {}),
|
|
665
|
+
envId: zod_1.z
|
|
666
|
+
.string()
|
|
667
|
+
.optional()
|
|
668
|
+
.describe("环境ID(CloudBase 环境唯一标识),绑定后工具将操作该环境。action=set_env 时必填"),
|
|
669
|
+
...(supportedAuthActions.includes("logout")
|
|
670
|
+
? {
|
|
671
|
+
confirm: zod_1.z
|
|
672
|
+
.literal("yes")
|
|
673
|
+
.optional()
|
|
674
|
+
.describe("action=logout 时确认操作,传 yes"),
|
|
675
|
+
}
|
|
676
|
+
: {}),
|
|
677
|
+
...(supportedAuthActions.includes("get_temp_credentials")
|
|
678
|
+
? {
|
|
679
|
+
reveal: zod_1.z
|
|
680
|
+
.boolean()
|
|
681
|
+
.optional()
|
|
682
|
+
.describe("action=get_temp_credentials 时可选。true=返回明文临时密钥;默认 false 仅返回脱敏结果"),
|
|
796
683
|
}
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
684
|
+
: {}),
|
|
685
|
+
},
|
|
686
|
+
annotations: {
|
|
687
|
+
readOnlyHint: false,
|
|
688
|
+
destructiveHint: false,
|
|
689
|
+
idempotentHint: false,
|
|
690
|
+
openWorldHint: true,
|
|
691
|
+
category: "env",
|
|
692
|
+
},
|
|
693
|
+
}, async (rawArgs) => {
|
|
694
|
+
const action = rawArgs.action ?? "status";
|
|
695
|
+
const authMode = rawArgs.authMode === "device" || rawArgs.authMode === "web"
|
|
696
|
+
? rawArgs.authMode
|
|
697
|
+
: undefined;
|
|
698
|
+
const oauthEndpoint = normalizeOptionalToolString(rawArgs.oauthEndpoint);
|
|
699
|
+
const clientId = normalizeOptionalToolString(rawArgs.clientId);
|
|
700
|
+
const oauthCustom = normalizeOptionalToolBoolean(rawArgs.oauthCustom);
|
|
701
|
+
const envId = rawArgs.envId;
|
|
702
|
+
const confirm = rawArgs.confirm === "yes" ? "yes" : undefined;
|
|
703
|
+
const reveal = normalizeOptionalToolBoolean(rawArgs.reveal) === true;
|
|
704
|
+
const resolvedAuthOptions = resolveToolAuthOptions(server, {
|
|
705
|
+
authMode,
|
|
706
|
+
oauthEndpoint,
|
|
707
|
+
clientId,
|
|
708
|
+
oauthCustom,
|
|
709
|
+
});
|
|
710
|
+
const authConfigSummary = (0, auth_js_1.buildAuthConfigSummary)(resolvedAuthOptions);
|
|
711
|
+
let deviceAuthInfo;
|
|
712
|
+
const onDeviceCode = (info) => {
|
|
713
|
+
deviceAuthInfo = info;
|
|
714
|
+
(0, auth_js_1.setPendingAuthProgressState)(info, "device");
|
|
715
|
+
// emitDeviceAuthNotice(server, info);
|
|
716
|
+
};
|
|
717
|
+
const authChallenge = () => (0, auth_js_1.buildDeviceAuthChallengePayload)(deviceAuthInfo);
|
|
718
|
+
try {
|
|
719
|
+
if (!supportedAuthActions.includes(action)) {
|
|
810
720
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
811
721
|
ok: false,
|
|
812
|
-
code: "
|
|
813
|
-
message:
|
|
814
|
-
auth_mode: "api_key",
|
|
815
|
-
envId: process.env.CLOUDBASE_ENV_ID,
|
|
816
|
-
endpoint,
|
|
817
|
-
});
|
|
818
|
-
}
|
|
819
|
-
const region = server.cloudBaseOptions?.region || process.env.TCB_REGION;
|
|
820
|
-
const auth = toolbox_1.AuthSupervisor.getInstance({});
|
|
821
|
-
const authFlowState = await (0, auth_js_1.getAuthProgressState)();
|
|
822
|
-
if (authFlowState.status === "PENDING" && authFlowState.authChallenge) {
|
|
823
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
824
|
-
ok: true,
|
|
825
|
-
code: "AUTH_PENDING",
|
|
826
|
-
message: "设备码授权进行中,请在浏览器中打开 verification_uri 并输入 user_code 完成授权。",
|
|
827
|
-
auth_challenge: (0, auth_js_1.buildDeviceAuthChallengePayload)(authFlowState.authChallenge),
|
|
722
|
+
code: "NOT_SUPPORTED",
|
|
723
|
+
message: `当前 IDE 不支持 auth(action="${action}")。`,
|
|
828
724
|
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
829
725
|
suggestedArgs: { action: "status" },
|
|
830
726
|
}),
|
|
831
727
|
});
|
|
832
728
|
}
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
const
|
|
836
|
-
|
|
837
|
-
|
|
729
|
+
if (action === "status") {
|
|
730
|
+
const loginState = await (0, auth_js_1.peekLoginState)();
|
|
731
|
+
const authFlowState = await (0, auth_js_1.getAuthProgressState)();
|
|
732
|
+
// 判断是否为 API Key 模式
|
|
733
|
+
const isApiKeyMode = !!(process.env.CLOUDBASE_API_KEY && process.env.CLOUDBASE_ENV_ID);
|
|
734
|
+
const authStatus = loginState
|
|
735
|
+
? "READY"
|
|
736
|
+
: authFlowState.status === "PENDING"
|
|
737
|
+
? "PENDING"
|
|
738
|
+
: "REQUIRED";
|
|
739
|
+
let envPreparation;
|
|
740
|
+
const message = authStatus === "READY"
|
|
741
|
+
? undefined
|
|
742
|
+
: authStatus === "PENDING"
|
|
743
|
+
? "设备码授权进行中,请完成浏览器授权后再次调用 auth(action=\"status\")"
|
|
744
|
+
: isCodeBuddyIde(server)
|
|
745
|
+
? "当前未登录。CodeBuddy 暂不支持在 tool 内发起认证,请在外部完成认证后再次调用 auth(action=\"status\")。"
|
|
746
|
+
: "当前未登录,请先执行 auth(action=\"start_auth\")";
|
|
747
|
+
if (authStatus === "READY" && loginState) {
|
|
748
|
+
envPreparation = await prepareAuthEnvironment({
|
|
838
749
|
server,
|
|
839
750
|
cloudBaseOptions,
|
|
840
|
-
loginState
|
|
841
|
-
});
|
|
842
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
843
|
-
ok: true,
|
|
844
|
-
code: "AUTH_READY",
|
|
845
|
-
message: envPreparation.message,
|
|
846
|
-
auth_challenge: authChallenge(),
|
|
847
|
-
...buildAuthEnvSetupPayload(envPreparation),
|
|
848
|
-
next_step: envPreparation.nextStep,
|
|
751
|
+
loginState,
|
|
849
752
|
});
|
|
850
753
|
}
|
|
851
|
-
}
|
|
852
|
-
catch {
|
|
853
|
-
// 忽略 getLoginState 错误,继续尝试发起登录
|
|
854
|
-
}
|
|
855
|
-
const validationError = (0, auth_js_1.getAuthConfigValidationError)(resolvedAuthOptions);
|
|
856
|
-
if (validationError) {
|
|
857
754
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
858
|
-
ok:
|
|
859
|
-
code: "
|
|
860
|
-
|
|
755
|
+
ok: true,
|
|
756
|
+
code: "STATUS",
|
|
757
|
+
auth_status: authStatus,
|
|
758
|
+
...(isApiKeyMode ? { auth_mode: "api_key" } : {}),
|
|
861
759
|
auth_config: authConfigSummary,
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
760
|
+
...(envPreparation
|
|
761
|
+
? buildAuthEnvSetupPayload(envPreparation)
|
|
762
|
+
: {
|
|
763
|
+
env_status: "NONE",
|
|
764
|
+
current_env_id: null,
|
|
765
|
+
...buildEnvCandidatePayload([]),
|
|
766
|
+
}),
|
|
767
|
+
auth_challenge: authFlowState.status === "PENDING"
|
|
768
|
+
? (0, auth_js_1.buildDeviceAuthChallengePayload)(authFlowState.authChallenge)
|
|
769
|
+
: undefined,
|
|
770
|
+
message,
|
|
771
|
+
next_step: authStatus === "REQUIRED"
|
|
772
|
+
? buildAuthRequiredNextStep(server)
|
|
773
|
+
: authStatus === "PENDING"
|
|
774
|
+
? (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
775
|
+
suggestedArgs: { action: "status" },
|
|
776
|
+
})
|
|
777
|
+
: envPreparation?.nextStep,
|
|
865
778
|
});
|
|
866
779
|
}
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
}
|
|
881
|
-
};
|
|
882
|
-
try {
|
|
883
|
-
// 启动 Device Flow,全流程由 toolbox 负责轮询和写入 credential,这里不等待完成
|
|
884
|
-
auth
|
|
885
|
-
.loginByWebAuth({
|
|
886
|
-
flow: "device",
|
|
887
|
-
...(resolvedAuthOptions.clientId
|
|
888
|
-
? { client_id: resolvedAuthOptions.clientId }
|
|
889
|
-
: {}),
|
|
890
|
-
...(resolvedAuthOptions.oauthEndpoint
|
|
891
|
-
? { getOAuthEndpoint: () => resolvedAuthOptions.oauthEndpoint }
|
|
892
|
-
: {}),
|
|
893
|
-
...(resolvedAuthOptions.oauthCustom
|
|
894
|
-
? { custom: true }
|
|
895
|
-
: {}),
|
|
896
|
-
onDeviceCode: deviceOnCode,
|
|
897
|
-
})
|
|
898
|
-
.then(() => {
|
|
899
|
-
(0, auth_js_1.resolveAuthProgressState)();
|
|
900
|
-
})
|
|
901
|
-
.catch((err) => {
|
|
902
|
-
(0, auth_js_1.rejectAuthProgressState)(err);
|
|
903
|
-
// 如果在拿到 device code 之前就失败,则唤醒当前调用并返回错误
|
|
904
|
-
if (!deviceAuthInfo && rejectCode) {
|
|
905
|
-
rejectCode(err);
|
|
780
|
+
if (action === "start_auth") {
|
|
781
|
+
// API Key 模式:尝试换取临时密钥
|
|
782
|
+
if (process.env.CLOUDBASE_API_KEY && process.env.CLOUDBASE_ENV_ID) {
|
|
783
|
+
try {
|
|
784
|
+
const existingLoginState = await (0, auth_js_1.peekLoginState)();
|
|
785
|
+
if (existingLoginState) {
|
|
786
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
787
|
+
ok: true,
|
|
788
|
+
code: "AUTH_READY",
|
|
789
|
+
message: "当前使用 API Key 认证模式,已自动完成登录,无需手动授权。",
|
|
790
|
+
auth_mode: "api_key",
|
|
791
|
+
envId: process.env.CLOUDBASE_ENV_ID,
|
|
792
|
+
});
|
|
906
793
|
}
|
|
794
|
+
}
|
|
795
|
+
catch (e) {
|
|
796
|
+
// peekLoginState 内部异常,记录后 fall through
|
|
797
|
+
(0, logger_js_1.debug)("start_auth: peekLoginState threw", { error: e instanceof Error ? e.message : String(e) });
|
|
798
|
+
}
|
|
799
|
+
// API Key 换取失败:返回详细诊断信息
|
|
800
|
+
// 尝试获取更详细的错误信息
|
|
801
|
+
let diagMessage = "当前配置了 API Key 认证模式,但换取临时密钥失败。";
|
|
802
|
+
const endpoint = process.env.CLOUDBASE_API_ENDPOINT || `https://${process.env.CLOUDBASE_ENV_ID}.ap-shanghai.tcb-api.tencentcloudapi.com`;
|
|
803
|
+
diagMessage += `\n\n诊断信息:`;
|
|
804
|
+
diagMessage += `\n- CLOUDBASE_ENV_ID: ${process.env.CLOUDBASE_ENV_ID}`;
|
|
805
|
+
diagMessage += `\n- CLOUDBASE_API_KEY: ${process.env.CLOUDBASE_API_KEY.slice(0, 20)}...(已截断)`;
|
|
806
|
+
diagMessage += `\n- Endpoint: ${endpoint}`;
|
|
807
|
+
diagMessage += `\n\n可能原因:`;
|
|
808
|
+
diagMessage += `\n1. API Key 已过期或被删除`;
|
|
809
|
+
diagMessage += `\n2. Endpoint 不可达(网络/DNS 问题)`;
|
|
810
|
+
diagMessage += `\n3. CLOUDBASE_ENV_ID 与 API Key 所属环境不匹配`;
|
|
811
|
+
diagMessage += `\n\n建议:检查 MCP 配置中的 CLOUDBASE_API_KEY 和 CLOUDBASE_ENV_ID 环境变量是否正确。`;
|
|
812
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
813
|
+
ok: false,
|
|
814
|
+
code: "API_KEY_AUTH_FAILED",
|
|
815
|
+
message: diagMessage,
|
|
816
|
+
auth_mode: "api_key",
|
|
817
|
+
envId: process.env.CLOUDBASE_ENV_ID,
|
|
818
|
+
endpoint,
|
|
907
819
|
});
|
|
908
820
|
}
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
821
|
+
const region = server.cloudBaseOptions?.region || process.env.TCB_REGION;
|
|
822
|
+
const auth = toolbox_1.AuthSupervisor.getInstance({});
|
|
823
|
+
const authFlowState = await (0, auth_js_1.getAuthProgressState)();
|
|
824
|
+
if (authFlowState.status === "PENDING" && authFlowState.authChallenge) {
|
|
825
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
826
|
+
ok: true,
|
|
827
|
+
code: "AUTH_PENDING",
|
|
828
|
+
message: "设备码授权进行中,请在浏览器中打开 verification_uri 并输入 user_code 完成授权。",
|
|
829
|
+
auth_challenge: (0, auth_js_1.buildDeviceAuthChallengePayload)(authFlowState.authChallenge),
|
|
830
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
831
|
+
suggestedArgs: { action: "status" },
|
|
832
|
+
}),
|
|
833
|
+
});
|
|
913
834
|
}
|
|
835
|
+
// 1. 如果已经有登录态,直接返回 AUTH_READY
|
|
914
836
|
try {
|
|
915
|
-
await
|
|
837
|
+
const existingLoginState = await (0, auth_js_1.peekLoginState)();
|
|
838
|
+
if (existingLoginState) {
|
|
839
|
+
const envPreparation = await prepareAuthEnvironment({
|
|
840
|
+
server,
|
|
841
|
+
cloudBaseOptions,
|
|
842
|
+
loginState: existingLoginState,
|
|
843
|
+
});
|
|
844
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
845
|
+
ok: true,
|
|
846
|
+
code: "AUTH_READY",
|
|
847
|
+
message: envPreparation.message,
|
|
848
|
+
auth_challenge: authChallenge(),
|
|
849
|
+
...buildAuthEnvSetupPayload(envPreparation),
|
|
850
|
+
next_step: envPreparation.nextStep,
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
catch {
|
|
855
|
+
// 忽略 getLoginState 错误,继续尝试发起登录
|
|
916
856
|
}
|
|
917
|
-
|
|
918
|
-
|
|
857
|
+
const validationError = (0, auth_js_1.getAuthConfigValidationError)(resolvedAuthOptions);
|
|
858
|
+
if (validationError) {
|
|
919
859
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
920
860
|
ok: false,
|
|
921
|
-
code: "
|
|
922
|
-
message:
|
|
861
|
+
code: "INVALID_ARGS",
|
|
862
|
+
message: validationError,
|
|
863
|
+
auth_config: authConfigSummary,
|
|
923
864
|
next_step: (0, tool_result_js_1.buildAuthNextStep)("start_auth", {
|
|
924
865
|
suggestedArgs: { action: "start_auth", authMode: "device" },
|
|
925
866
|
}),
|
|
926
867
|
});
|
|
927
868
|
}
|
|
928
|
-
|
|
869
|
+
// 2. 设备码模式:监听到 device code 即返回 AUTH_PENDING,后续由 toolbox 异步轮询并更新本地 credential
|
|
870
|
+
const effectiveMode = resolvedAuthOptions.authMode;
|
|
871
|
+
if (effectiveMode === "device") {
|
|
872
|
+
let resolveCode;
|
|
873
|
+
let rejectCode;
|
|
874
|
+
const codeReady = new Promise((resolve, reject) => {
|
|
875
|
+
resolveCode = resolve;
|
|
876
|
+
rejectCode = reject;
|
|
877
|
+
});
|
|
878
|
+
const deviceOnCode = (info) => {
|
|
879
|
+
onDeviceCode(info);
|
|
880
|
+
if (resolveCode) {
|
|
881
|
+
resolveCode();
|
|
882
|
+
}
|
|
883
|
+
};
|
|
884
|
+
try {
|
|
885
|
+
// 启动 Device Flow,全流程由 toolbox 负责轮询和写入 credential,这里不等待完成
|
|
886
|
+
auth
|
|
887
|
+
.loginByWebAuth({
|
|
888
|
+
flow: "device",
|
|
889
|
+
...(resolvedAuthOptions.clientId
|
|
890
|
+
? { client_id: resolvedAuthOptions.clientId }
|
|
891
|
+
: {}),
|
|
892
|
+
...(resolvedAuthOptions.oauthEndpoint
|
|
893
|
+
? { getOAuthEndpoint: () => resolvedAuthOptions.oauthEndpoint }
|
|
894
|
+
: {}),
|
|
895
|
+
...(resolvedAuthOptions.oauthCustom
|
|
896
|
+
? { custom: true }
|
|
897
|
+
: {}),
|
|
898
|
+
onDeviceCode: deviceOnCode,
|
|
899
|
+
})
|
|
900
|
+
.then(() => {
|
|
901
|
+
(0, auth_js_1.resolveAuthProgressState)();
|
|
902
|
+
})
|
|
903
|
+
.catch((err) => {
|
|
904
|
+
(0, auth_js_1.rejectAuthProgressState)(err);
|
|
905
|
+
// 如果在拿到 device code 之前就失败,则唤醒当前调用并返回错误
|
|
906
|
+
if (!deviceAuthInfo && rejectCode) {
|
|
907
|
+
rejectCode(err);
|
|
908
|
+
}
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
catch (err) {
|
|
912
|
+
if (rejectCode) {
|
|
913
|
+
rejectCode(err);
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
try {
|
|
917
|
+
await codeReady;
|
|
918
|
+
}
|
|
919
|
+
catch (err) {
|
|
920
|
+
const message = err instanceof Error ? err.message : String(err ?? "unknown error");
|
|
921
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
922
|
+
ok: false,
|
|
923
|
+
code: "AUTH_REQUIRED",
|
|
924
|
+
message: `设备码登录初始化失败: ${message}`,
|
|
925
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("start_auth", {
|
|
926
|
+
suggestedArgs: { action: "start_auth", authMode: "device" },
|
|
927
|
+
}),
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
if (!deviceAuthInfo) {
|
|
931
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
932
|
+
ok: false,
|
|
933
|
+
code: "AUTH_REQUIRED",
|
|
934
|
+
message: "未获取到设备码信息,请重试设备码登录",
|
|
935
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("start_auth", {
|
|
936
|
+
suggestedArgs: { action: "start_auth", authMode: "device" },
|
|
937
|
+
}),
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
const envCandidates = await fetchAvailableEnvCandidates(cloudBaseOptions, server);
|
|
941
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
942
|
+
ok: true,
|
|
943
|
+
code: "AUTH_PENDING",
|
|
944
|
+
message: "已发起设备码登录,请在浏览器中打开 verification_uri 并输入 user_code 完成授权。授权完成后请再次调用 auth(action=\"status\")。",
|
|
945
|
+
auth_challenge: authChallenge(),
|
|
946
|
+
...buildEnvCandidatePayload(envCandidates),
|
|
947
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
948
|
+
suggestedArgs: { action: "status" },
|
|
949
|
+
}),
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
// 3. 非 Device Flow(显式 web 模式)仍然使用 getLoginState 阻塞等待
|
|
953
|
+
const loginState = await (0, auth_js_1.ensureLogin)({
|
|
954
|
+
region,
|
|
955
|
+
authMode: effectiveMode,
|
|
956
|
+
clientId: resolvedAuthOptions.clientId,
|
|
957
|
+
oauthEndpoint: resolvedAuthOptions.oauthEndpoint,
|
|
958
|
+
oauthCustom: resolvedAuthOptions.oauthCustom,
|
|
959
|
+
});
|
|
960
|
+
if (!loginState) {
|
|
929
961
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
930
962
|
ok: false,
|
|
931
963
|
code: "AUTH_REQUIRED",
|
|
932
|
-
message: "
|
|
964
|
+
message: "未获取到登录态,请先完成认证",
|
|
933
965
|
next_step: (0, tool_result_js_1.buildAuthNextStep)("start_auth", {
|
|
934
|
-
suggestedArgs: { action: "start_auth", authMode:
|
|
966
|
+
suggestedArgs: { action: "start_auth", authMode: effectiveMode },
|
|
935
967
|
}),
|
|
936
968
|
});
|
|
937
969
|
}
|
|
938
|
-
const
|
|
970
|
+
const envPreparation = await prepareAuthEnvironment({
|
|
971
|
+
server,
|
|
972
|
+
cloudBaseOptions,
|
|
973
|
+
loginState,
|
|
974
|
+
});
|
|
939
975
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
940
976
|
ok: true,
|
|
941
|
-
code: "
|
|
942
|
-
message:
|
|
977
|
+
code: "AUTH_READY",
|
|
978
|
+
message: envPreparation.message,
|
|
943
979
|
auth_challenge: authChallenge(),
|
|
944
|
-
...
|
|
945
|
-
next_step:
|
|
946
|
-
suggestedArgs: { action: "status" },
|
|
947
|
-
}),
|
|
980
|
+
...buildAuthEnvSetupPayload(envPreparation),
|
|
981
|
+
next_step: envPreparation.nextStep,
|
|
948
982
|
});
|
|
949
983
|
}
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
const loginState = await (0, auth_js_1.peekLoginState)();
|
|
984
|
-
if (!loginState) {
|
|
985
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
986
|
-
ok: false,
|
|
987
|
-
code: "AUTH_REQUIRED",
|
|
988
|
-
message: isCodeBuddyIde(server)
|
|
989
|
-
? "当前未登录。CodeBuddy 暂不支持在 tool 内发起认证,请在外部完成认证后再次调用 auth(action=\"status\")。"
|
|
990
|
-
: "当前未登录,请先执行 auth(action=\"start_auth\")。",
|
|
991
|
-
next_step: buildAuthRequiredNextStep(server),
|
|
992
|
-
});
|
|
993
|
-
}
|
|
994
|
-
const envCandidates = await fetchAvailableEnvCandidates(cloudBaseOptions, server);
|
|
995
|
-
if (!envId) {
|
|
996
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
997
|
-
ok: false,
|
|
998
|
-
code: "INVALID_ARGS",
|
|
999
|
-
message: "action=set_env 时必须提供 envId",
|
|
1000
|
-
...buildEnvCandidatePayload(envCandidates),
|
|
1001
|
-
next_step: buildSetEnvNextStep(envCandidates),
|
|
1002
|
-
});
|
|
1003
|
-
}
|
|
1004
|
-
const target = envCandidates.find((item) => item.envId === envId);
|
|
1005
|
-
if (envCandidates.length > 0 && !target) {
|
|
984
|
+
if (action === "set_env") {
|
|
985
|
+
const loginState = await (0, auth_js_1.peekLoginState)();
|
|
986
|
+
if (!loginState) {
|
|
987
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
988
|
+
ok: false,
|
|
989
|
+
code: "AUTH_REQUIRED",
|
|
990
|
+
message: isCodeBuddyIde(server)
|
|
991
|
+
? "当前未登录。CodeBuddy 暂不支持在 tool 内发起认证,请在外部完成认证后再次调用 auth(action=\"status\")。"
|
|
992
|
+
: "当前未登录,请先执行 auth(action=\"start_auth\")。",
|
|
993
|
+
next_step: buildAuthRequiredNextStep(server),
|
|
994
|
+
});
|
|
995
|
+
}
|
|
996
|
+
const envCandidates = await fetchAvailableEnvCandidates(cloudBaseOptions, server);
|
|
997
|
+
if (!envId) {
|
|
998
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
999
|
+
ok: false,
|
|
1000
|
+
code: "INVALID_ARGS",
|
|
1001
|
+
message: "action=set_env 时必须提供 envId",
|
|
1002
|
+
...buildEnvCandidatePayload(envCandidates),
|
|
1003
|
+
next_step: buildSetEnvNextStep(envCandidates),
|
|
1004
|
+
});
|
|
1005
|
+
}
|
|
1006
|
+
const target = envCandidates.find((item) => item.envId === envId);
|
|
1007
|
+
if (envCandidates.length > 0 && !target) {
|
|
1008
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1009
|
+
ok: false,
|
|
1010
|
+
code: "INVALID_ARGS",
|
|
1011
|
+
message: `未找到环境: ${envId}`,
|
|
1012
|
+
...buildEnvCandidatePayload(envCandidates),
|
|
1013
|
+
next_step: buildSetEnvNextStep(envCandidates),
|
|
1014
|
+
});
|
|
1015
|
+
}
|
|
1016
|
+
await cloudbase_manager_js_1.envManager.setEnvId(envId);
|
|
1006
1017
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1007
|
-
ok:
|
|
1008
|
-
code: "
|
|
1009
|
-
message:
|
|
1010
|
-
|
|
1011
|
-
next_step: buildSetEnvNextStep(envCandidates),
|
|
1018
|
+
ok: true,
|
|
1019
|
+
code: "ENV_READY",
|
|
1020
|
+
message: `环境设置成功,当前环境: ${envId}`,
|
|
1021
|
+
current_env_id: envId,
|
|
1012
1022
|
});
|
|
1013
1023
|
}
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1024
|
+
if (action === "logout") {
|
|
1025
|
+
// API Key 模式下不允许 logout
|
|
1026
|
+
if (process.env.CLOUDBASE_API_KEY && process.env.CLOUDBASE_ENV_ID) {
|
|
1027
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1028
|
+
ok: false,
|
|
1029
|
+
code: "LOGOUT_NOT_ALLOWED",
|
|
1030
|
+
message: "当前使用 API Key 认证模式,不支持退出登录。如需切换认证方式,请移除 CLOUDBASE_API_KEY 环境变量后重启。",
|
|
1031
|
+
auth_mode: "api_key",
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1034
|
+
if (confirm !== "yes") {
|
|
1035
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1036
|
+
ok: false,
|
|
1037
|
+
code: "INVALID_ARGS",
|
|
1038
|
+
message: "action=logout 时必须传 confirm=\"yes\"",
|
|
1039
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("logout", {
|
|
1040
|
+
suggestedArgs: { action: "logout", confirm: "yes" },
|
|
1041
|
+
}),
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
1044
|
+
await (0, auth_js_1.logout)();
|
|
1045
|
+
(0, cloudbase_manager_js_1.resetCloudBaseManagerCache)();
|
|
1025
1046
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1026
|
-
ok:
|
|
1027
|
-
code: "
|
|
1028
|
-
message: "
|
|
1029
|
-
auth_mode: "api_key",
|
|
1047
|
+
ok: true,
|
|
1048
|
+
code: "LOGGED_OUT",
|
|
1049
|
+
message: "✅ 已退出登录",
|
|
1030
1050
|
});
|
|
1031
1051
|
}
|
|
1032
|
-
if (
|
|
1052
|
+
if (action === "get_temp_credentials") {
|
|
1053
|
+
const loginState = (await (0, auth_js_1.peekLoginState)());
|
|
1054
|
+
if (!loginState) {
|
|
1055
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1056
|
+
ok: false,
|
|
1057
|
+
code: "AUTH_REQUIRED",
|
|
1058
|
+
message: "当前未登录,请先完成管理端认证后再获取临时密钥。",
|
|
1059
|
+
next_step: buildAuthRequiredNextStep(server),
|
|
1060
|
+
});
|
|
1061
|
+
}
|
|
1062
|
+
if (confirm !== "yes") {
|
|
1063
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1064
|
+
ok: false,
|
|
1065
|
+
code: "INVALID_ARGS",
|
|
1066
|
+
message: "action=get_temp_credentials 时必须显式传 confirm=\"yes\",以确认你要导出当前管理端临时密钥。",
|
|
1067
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("get_temp_credentials", {
|
|
1068
|
+
suggestedArgs: { action: "get_temp_credentials", confirm: "yes" },
|
|
1069
|
+
}),
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
if (!isTemporaryCredentialLoginState(loginState)) {
|
|
1073
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1074
|
+
ok: false,
|
|
1075
|
+
code: "UNSUPPORTED_CREDENTIAL_TYPE",
|
|
1076
|
+
message: "当前登录态不是可导出的临时密钥。仅支持通过 Web / device 登录得到的临时密钥,永久密钥登录不允许导出。",
|
|
1077
|
+
});
|
|
1078
|
+
}
|
|
1079
|
+
const secretId = normalizeOptionalToolString(loginState.secretId);
|
|
1080
|
+
const secretKey = normalizeOptionalToolString(loginState.secretKey);
|
|
1081
|
+
const token = normalizeOptionalToolString(loginState.token);
|
|
1082
|
+
if (!secretId || !secretKey || !token) {
|
|
1083
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1084
|
+
ok: false,
|
|
1085
|
+
code: "INTERNAL_ERROR",
|
|
1086
|
+
message: "当前登录态缺少完整的临时密钥字段,请重新登录后再试。",
|
|
1087
|
+
});
|
|
1088
|
+
}
|
|
1033
1089
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1034
|
-
ok:
|
|
1035
|
-
code: "
|
|
1036
|
-
message:
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1090
|
+
ok: true,
|
|
1091
|
+
code: "TEMP_CREDENTIALS_READY",
|
|
1092
|
+
message: reveal
|
|
1093
|
+
? "当前管理端临时密钥已准备好,请注意避免泄露。"
|
|
1094
|
+
: "当前管理端临时密钥已准备好,默认仅返回脱敏结果。",
|
|
1095
|
+
env_id: normalizeOptionalToolString(loginState.envId) ?? null,
|
|
1096
|
+
credentials: {
|
|
1097
|
+
secretId: reveal ? secretId : maskSensitiveValue(secretId),
|
|
1098
|
+
secretKey: reveal ? secretKey : maskSensitiveValue(secretKey),
|
|
1099
|
+
token: reveal ? token : maskSensitiveValue(token),
|
|
1100
|
+
masked: !reveal,
|
|
1101
|
+
},
|
|
1040
1102
|
});
|
|
1041
1103
|
}
|
|
1042
|
-
await (0, auth_js_1.logout)();
|
|
1043
|
-
(0, cloudbase_manager_js_1.resetCloudBaseManagerCache)();
|
|
1044
1104
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1045
|
-
ok:
|
|
1046
|
-
code: "
|
|
1047
|
-
message:
|
|
1105
|
+
ok: false,
|
|
1106
|
+
code: "NOT_SUPPORTED",
|
|
1107
|
+
message: `不支持的 auth action: ${action}`,
|
|
1108
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
1109
|
+
suggestedArgs: { action: "status" },
|
|
1110
|
+
}),
|
|
1048
1111
|
});
|
|
1049
1112
|
}
|
|
1050
|
-
|
|
1051
|
-
const
|
|
1052
|
-
if (!loginState) {
|
|
1053
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1054
|
-
ok: false,
|
|
1055
|
-
code: "AUTH_REQUIRED",
|
|
1056
|
-
message: "当前未登录,请先完成管理端认证后再获取临时密钥。",
|
|
1057
|
-
next_step: buildAuthRequiredNextStep(server),
|
|
1058
|
-
});
|
|
1059
|
-
}
|
|
1060
|
-
if (confirm !== "yes") {
|
|
1061
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1062
|
-
ok: false,
|
|
1063
|
-
code: "INVALID_ARGS",
|
|
1064
|
-
message: "action=get_temp_credentials 时必须显式传 confirm=\"yes\",以确认你要导出当前管理端临时密钥。",
|
|
1065
|
-
next_step: (0, tool_result_js_1.buildAuthNextStep)("get_temp_credentials", {
|
|
1066
|
-
suggestedArgs: { action: "get_temp_credentials", confirm: "yes" },
|
|
1067
|
-
}),
|
|
1068
|
-
});
|
|
1069
|
-
}
|
|
1070
|
-
if (!isTemporaryCredentialLoginState(loginState)) {
|
|
1071
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1072
|
-
ok: false,
|
|
1073
|
-
code: "UNSUPPORTED_CREDENTIAL_TYPE",
|
|
1074
|
-
message: "当前登录态不是可导出的临时密钥。仅支持通过 Web / device 登录得到的临时密钥,永久密钥登录不允许导出。",
|
|
1075
|
-
});
|
|
1076
|
-
}
|
|
1077
|
-
const secretId = normalizeOptionalToolString(loginState.secretId);
|
|
1078
|
-
const secretKey = normalizeOptionalToolString(loginState.secretKey);
|
|
1079
|
-
const token = normalizeOptionalToolString(loginState.token);
|
|
1080
|
-
if (!secretId || !secretKey || !token) {
|
|
1081
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1082
|
-
ok: false,
|
|
1083
|
-
code: "INTERNAL_ERROR",
|
|
1084
|
-
message: "当前登录态缺少完整的临时密钥字段,请重新登录后再试。",
|
|
1085
|
-
});
|
|
1086
|
-
}
|
|
1113
|
+
catch (error) {
|
|
1114
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1087
1115
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1088
|
-
ok:
|
|
1089
|
-
code: "
|
|
1090
|
-
message:
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
secretId: reveal ? secretId : maskSensitiveValue(secretId),
|
|
1096
|
-
secretKey: reveal ? secretKey : maskSensitiveValue(secretKey),
|
|
1097
|
-
token: reveal ? token : maskSensitiveValue(token),
|
|
1098
|
-
masked: !reveal,
|
|
1099
|
-
},
|
|
1116
|
+
ok: false,
|
|
1117
|
+
code: "INTERNAL_ERROR",
|
|
1118
|
+
message: `auth 执行失败: ${message}`,
|
|
1119
|
+
auth_challenge: authChallenge(),
|
|
1120
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
1121
|
+
suggestedArgs: { action: "status" },
|
|
1122
|
+
}),
|
|
1100
1123
|
});
|
|
1101
1124
|
}
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
1107
|
-
suggestedArgs: { action: "status" },
|
|
1108
|
-
}),
|
|
1109
|
-
});
|
|
1110
|
-
}
|
|
1111
|
-
catch (error) {
|
|
1112
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1113
|
-
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
1114
|
-
ok: false,
|
|
1115
|
-
code: "INTERNAL_ERROR",
|
|
1116
|
-
message: `auth 执行失败: ${message}`,
|
|
1117
|
-
auth_challenge: authChallenge(),
|
|
1118
|
-
next_step: (0, tool_result_js_1.buildAuthNextStep)("status", {
|
|
1119
|
-
suggestedArgs: { action: "status" },
|
|
1120
|
-
}),
|
|
1121
|
-
});
|
|
1122
|
-
}
|
|
1123
|
-
});
|
|
1124
|
-
// envQuery - 环境查询(合并 listEnvs + getEnvInfo + getEnvAuthDomains)
|
|
1125
|
-
server.registerTool?.("envQuery", {
|
|
1126
|
-
title: "CloudBase 环境查询",
|
|
1127
|
-
description: "查询 CloudBase 环境相关信息,支持查询环境列表、指定环境详情和安全域名。(原工具名:listEnvs/getEnvInfo/getEnvAuthDomains,为兼容旧AI规则可继续使用这些名称)当 action=list 时,会按 DescribeEnvs 语义做列表/筛选,标准返回字段为 EnvId、Alias、Status、EnvType、Region、PackageId、PackageName、IsDefault,并支持通过 fields 白名单裁剪这些字段;aliasExact=true 时会按别名精确筛选,避免把前缀相近的环境误当作候选;即使传入 envId,action=list 也只返回摘要,不会返回完整资源明细或 expiry。如需查询某个已知 EnvId 对应环境的详细信息(包括资源字段和计费信息),必须使用 action=info 并传入目标环境的 envId 参数。action=info 会在可用时补充 BillingInfo(如 ExpireTime、PayMode、IsAutoRenew 等计费字段)。",
|
|
1128
|
-
inputSchema: {
|
|
1129
|
-
action: zod_1.z
|
|
1130
|
-
.enum(["list", "info", "domains"])
|
|
1131
|
-
.describe("查询类型:list=环境列表/摘要筛选(按 DescribeEnvs 语义筛选,支持通过 envId 筛选,返回 EnvId、Alias、Status、EnvType、Region、PackageId、PackageName、IsDefault,不支持 expiry),info=指定环境的详细信息(必须传入 envId,返回资源字段和计费信息),domains=安全域名列表"),
|
|
1132
|
-
alias: zod_1.z.string().optional().describe("按环境别名筛选。action=list 时可选"),
|
|
1133
|
-
aliasExact: zod_1.z.boolean().optional().describe("按环境别名精确筛选。action=list 时可选;与 alias 配合使用"),
|
|
1134
|
-
envId: zod_1.z.string().optional().describe("按环境 ID 筛选。action=list 时可选(仅按 DescribeEnvs 语义做筛选,仍返回摘要);action=info 时必填(返回该环境的详细信息,包含资源字段和计费信息)。如果任务已经给出了明确的 EnvId 并要求查询详情,请直接使用 action=info + envId,而不是 action=list"),
|
|
1135
|
-
limit: zod_1.z.number().int().positive().optional().describe("返回数量上限。action=list 时可选"),
|
|
1136
|
-
offset: zod_1.z.number().int().min(0).optional().describe("分页偏移。action=list 时可选"),
|
|
1137
|
-
fields: zod_1.z
|
|
1138
|
-
.array(zod_1.z.enum(DEFAULT_ENV_FIELDS))
|
|
1139
|
-
.optional()
|
|
1140
|
-
.describe("返回字段白名单。仅支持 EnvId、Alias、Status、EnvType、Region、PackageId、PackageName、IsDefault。action=list 时可选"),
|
|
1141
|
-
},
|
|
1142
|
-
annotations: {
|
|
1143
|
-
readOnlyHint: true,
|
|
1144
|
-
openWorldHint: true,
|
|
1145
|
-
category: "env",
|
|
1146
|
-
},
|
|
1147
|
-
}, async ({ action, alias, aliasExact, envId, limit, offset, fields, }) => {
|
|
1125
|
+
});
|
|
1126
|
+
} // end: wxide guard for auth tool
|
|
1127
|
+
// queryEnv - 环境查询(合并 listEnvs + getEnvInfo + getEnvAuthDomains)
|
|
1128
|
+
const queryEnvHandler = async ({ action, alias, aliasExact, envId, limit, offset, fields, }) => {
|
|
1148
1129
|
try {
|
|
1149
1130
|
let result;
|
|
1150
1131
|
switch (action) {
|
|
@@ -1158,7 +1139,8 @@ function registerEnvTools(server) {
|
|
|
1158
1139
|
// 当环境变量设置了 CLOUDBASE_ENV_ID 时(如 API Key 模式),
|
|
1159
1140
|
// 避免调用 DescribeEnvs(临时密钥可能不支持该接口),
|
|
1160
1141
|
// 改为通过 DescribeEnvInfo 获取单环境信息
|
|
1161
|
-
|
|
1142
|
+
// 注意:requestFn 模式(如微信 IDE)使用 DescribeEnvs,不走此分支
|
|
1143
|
+
const envIdFromEnv = !cloudBaseOptions?.requestFn && process.env.CLOUDBASE_ENV_ID;
|
|
1162
1144
|
if (envIdFromEnv) {
|
|
1163
1145
|
try {
|
|
1164
1146
|
const envInfo = await cloudbaseList.env.describeEnvInfo({ EnvId: envIdFromEnv });
|
|
@@ -1325,61 +1307,91 @@ function registerEnvTools(server) {
|
|
|
1325
1307
|
],
|
|
1326
1308
|
};
|
|
1327
1309
|
}
|
|
1328
|
-
}
|
|
1329
|
-
//
|
|
1330
|
-
|
|
1331
|
-
title: "CloudBase
|
|
1332
|
-
description: "
|
|
1310
|
+
};
|
|
1311
|
+
// Register primary tool name (queryEnv)
|
|
1312
|
+
const queryEnvToolSchema = {
|
|
1313
|
+
title: "CloudBase 环境查询",
|
|
1314
|
+
description: "查询 CloudBase 环境相关信息,支持查询环境列表、指定环境详情和安全域名。(曾用名:envQuery、listEnvs、getEnvInfo、getEnvAuthDomains)当 action=list 时,会按 DescribeEnvs 语义做列表/筛选,标准返回字段为 EnvId、Alias、Status、EnvType、Region、PackageId、PackageName、IsDefault,并支持通过 fields 白名单裁剪这些字段;aliasExact=true 时会按别名精确筛选,避免把前缀相近的环境误当作候选;即使传入 envId,action=list 也只返回摘要,不会返回完整资源明细或 expiry。如需查询某个已知 EnvId 对应环境的详细信息(包括资源字段和计费信息),必须使用 action=info 并传入目标环境的 envId 参数。action=info 会在可用时补充 BillingInfo(如 ExpireTime、PayMode、IsAutoRenew 等计费字段)。",
|
|
1333
1315
|
inputSchema: {
|
|
1334
1316
|
action: zod_1.z
|
|
1335
|
-
.enum(["
|
|
1336
|
-
.describe("
|
|
1337
|
-
|
|
1317
|
+
.enum(["list", "info", "domains"])
|
|
1318
|
+
.describe("查询类型:list=环境列表/摘要筛选(按 DescribeEnvs 语义筛选,支持通过 envId 筛选,返回 EnvId、Alias、Status、EnvType、Region、PackageId、PackageName、IsDefault,不支持 expiry),info=指定环境的详细信息(必须传入 envId,返回资源字段和计费信息),domains=安全域名列表"),
|
|
1319
|
+
alias: zod_1.z.string().optional().describe("按环境别名筛选。action=list 时可选"),
|
|
1320
|
+
aliasExact: zod_1.z.boolean().optional().describe("按环境别名精确筛选。action=list 时可选;与 alias 配合使用"),
|
|
1321
|
+
envId: zod_1.z.string().optional().describe("按环境 ID 筛选。action=list 时可选(仅按 DescribeEnvs 语义做筛选,仍返回摘要);action=info 时必填(返回该环境的详细信息,包含资源字段和计费信息)。如果任务已经给出了明确的 EnvId 并要求查询详情,请直接使用 action=info + envId,而不是 action=list"),
|
|
1322
|
+
limit: zod_1.z.number().int().positive().optional().describe("返回数量上限。action=list 时可选"),
|
|
1323
|
+
offset: zod_1.z.number().int().min(0).optional().describe("分页偏移。action=list 时可选"),
|
|
1324
|
+
fields: zod_1.z
|
|
1325
|
+
.array(zod_1.z.enum(DEFAULT_ENV_FIELDS))
|
|
1326
|
+
.optional()
|
|
1327
|
+
.describe("返回字段白名单。仅支持 EnvId、Alias、Status、EnvType、Region、PackageId、PackageName、IsDefault。action=list 时可选"),
|
|
1338
1328
|
},
|
|
1339
1329
|
annotations: {
|
|
1340
|
-
readOnlyHint:
|
|
1341
|
-
destructiveHint: false, // 注意:delete操作虽然是破坏性的,但这里采用较宽松的标注
|
|
1342
|
-
idempotentHint: false,
|
|
1330
|
+
readOnlyHint: true,
|
|
1343
1331
|
openWorldHint: true,
|
|
1344
1332
|
category: "env",
|
|
1345
1333
|
},
|
|
1346
|
-
}
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1334
|
+
};
|
|
1335
|
+
server.registerTool?.("queryEnv", queryEnvToolSchema, queryEnvHandler);
|
|
1336
|
+
// 向后兼容:envQuery 作为 queryEnv 的别名注册
|
|
1337
|
+
server.registerTool?.("envQuery", queryEnvToolSchema, queryEnvHandler);
|
|
1338
|
+
// envDomainManagement - 环境域名管理(合并 createEnvDomain + deleteEnvDomain)
|
|
1339
|
+
// 微信 IDE 场景不需要域名管理
|
|
1340
|
+
if (server.ide !== 'wxide') {
|
|
1341
|
+
server.registerTool?.("envDomainManagement", {
|
|
1342
|
+
title: "CloudBase 环境域名管理(安全域名 / CORS 白名单)",
|
|
1343
|
+
description: "管理 CloudBase 环境的安全域名(安全域名 / CORS 白名单),支持添加和删除操作。(原工具名:createEnvDomain/deleteEnvDomain,为兼容旧AI规则可继续使用这些名称)当浏览器 Web 应用需要从本地 Vite / dev server 直接访问 CloudBase 资源时,应先用 queryEnv(action=domains) 检查当前实际浏览器 origin 对应的 host:port 是否已在白名单中,再按该实际值添加。新增或删除后通常需要继续轮询 queryEnv(action=domains) 确认状态收敛;安全域名一般约 10 分钟生效。⚠️ 重要:此工具仅用于 CORS/请求来源验证,不涉及 SSL 证书。如需绑定自定义域名供公网 HTTPS 访问,请使用 manageGateway(action=\"bindCustomDomain\")。",
|
|
1344
|
+
inputSchema: {
|
|
1345
|
+
action: zod_1.z
|
|
1346
|
+
.enum(["create", "delete"])
|
|
1347
|
+
.describe("操作类型:create=添加安全域名,delete=删除安全域名"),
|
|
1348
|
+
domains: zod_1.z.array(zod_1.z.string()).describe("安全域名数组(格式:host:port,例如 localhost:5173 或 127.0.0.1:4173)。注意:不是自定义域名,不需要证书。"),
|
|
1349
|
+
},
|
|
1350
|
+
annotations: {
|
|
1351
|
+
readOnlyHint: false,
|
|
1352
|
+
destructiveHint: false, // 注意:delete操作虽然是破坏性的,但这里采用较宽松的标注
|
|
1353
|
+
idempotentHint: false,
|
|
1354
|
+
openWorldHint: true,
|
|
1355
|
+
category: "env",
|
|
1356
|
+
},
|
|
1357
|
+
}, async ({ action, domains, }) => {
|
|
1358
|
+
try {
|
|
1359
|
+
const cloudbase = await getManager();
|
|
1360
|
+
let result;
|
|
1361
|
+
switch (action) {
|
|
1362
|
+
case "create":
|
|
1363
|
+
result = await cloudbase.env.createEnvDomain(domains);
|
|
1364
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
1365
|
+
break;
|
|
1366
|
+
case "delete":
|
|
1367
|
+
result = await cloudbase.env.deleteEnvDomain(domains);
|
|
1368
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
1369
|
+
break;
|
|
1370
|
+
default:
|
|
1371
|
+
throw new Error(`不支持的操作类型: ${action}`);
|
|
1372
|
+
}
|
|
1373
|
+
return (0, tool_result_js_1.buildJsonToolResult)(buildEnvDomainManagementResult({
|
|
1374
|
+
action,
|
|
1375
|
+
domains,
|
|
1376
|
+
result,
|
|
1377
|
+
}));
|
|
1361
1378
|
}
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1379
|
+
catch (error) {
|
|
1380
|
+
const toolPayloadResult = (0, tool_result_js_1.toolPayloadErrorToResult)(error);
|
|
1381
|
+
if (toolPayloadResult) {
|
|
1382
|
+
return toolPayloadResult;
|
|
1383
|
+
}
|
|
1384
|
+
return {
|
|
1385
|
+
content: [
|
|
1386
|
+
{
|
|
1387
|
+
type: "text",
|
|
1388
|
+
text: `域名管理操作失败: ${error instanceof Error ? error.message : String(error)}`,
|
|
1389
|
+
},
|
|
1390
|
+
],
|
|
1391
|
+
};
|
|
1372
1392
|
}
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
{
|
|
1376
|
-
type: "text",
|
|
1377
|
-
text: `域名管理操作失败: ${error instanceof Error ? error.message : String(error)}`,
|
|
1378
|
-
},
|
|
1379
|
-
],
|
|
1380
|
-
};
|
|
1381
|
-
}
|
|
1382
|
-
});
|
|
1393
|
+
});
|
|
1394
|
+
} // end: wxide guard for envDomainManagement
|
|
1383
1395
|
}
|
|
1384
1396
|
|
|
1385
1397
|
|
|
@@ -1703,7 +1715,7 @@ ${envIdSection}
|
|
|
1703
1715
|
## 环境信息
|
|
1704
1716
|
- 操作系统: ${os_1.default.type()} ${os_1.default.release()}
|
|
1705
1717
|
- Node.js版本: ${process.version}
|
|
1706
|
-
- MCP 版本:${process.env.npm_package_version || "2.21.
|
|
1718
|
+
- MCP 版本:${process.env.npm_package_version || "2.21.1-beta.1" || 0}
|
|
1707
1719
|
- 系统架构: ${os_1.default.arch()}
|
|
1708
1720
|
- 时间: ${new Date().toISOString()}
|
|
1709
1721
|
- 请求ID: ${requestId}
|
|
@@ -1784,7 +1796,7 @@ function createWrappedHandler(name, handler, server) {
|
|
|
1784
1796
|
requestId: (typeof error === 'object' && error && 'requestId' in error) ? error.requestId : '',
|
|
1785
1797
|
ide: server.ide || process.env.INTEGRATION_IDE || ''
|
|
1786
1798
|
});
|
|
1787
|
-
const mcpVersion = true ? "2.21.
|
|
1799
|
+
const mcpVersion = true ? "2.21.1-beta.1" : 0;
|
|
1788
1800
|
const requestIdSuffix = requestId ? `\n🆔 RequestId: ${requestId}` : '';
|
|
1789
1801
|
const enhancedErrorMessage = `${errorMessage}${requestIdSuffix}\n\n📦 CloudBase MCP v${mcpVersion}\n🔗 遇到问题?请复制以下链接到浏览器打开\n即可自动携带错误详情快速创建 GitHub Issue:\n${issueLink}`;
|
|
1790
1802
|
// 创建新的错误对象,保持原有的错误类型但更新消息
|
|
@@ -1990,10 +2002,19 @@ function registerDatabase(server) {
|
|
|
1990
2002
|
(0, databaseSQL_js_1.registerSQLDatabaseTools)(server);
|
|
1991
2003
|
(0, dataModel_js_1.registerDataModelTools)(server);
|
|
1992
2004
|
}
|
|
2005
|
+
function registerNoSQLDatabase(server) {
|
|
2006
|
+
const region = server.cloudBaseOptions?.region || process.env.TCB_REGION;
|
|
2007
|
+
if (!(0, tencent_cloud_js_1.isInternationalRegion)(region)) {
|
|
2008
|
+
(0, databaseNoSQL_js_1.registerDatabaseTools)(server);
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
1993
2011
|
// 可用插件映射
|
|
1994
2012
|
const AVAILABLE_PLUGINS = {
|
|
1995
2013
|
env: { name: "env", register: env_js_1.registerEnvTools },
|
|
1996
2014
|
database: { name: "database", register: registerDatabase },
|
|
2015
|
+
"database-nosql": { name: "database-nosql", register: registerNoSQLDatabase },
|
|
2016
|
+
"database-sql": { name: "database-sql", register: databaseSQL_js_1.registerSQLDatabaseTools },
|
|
2017
|
+
"data-model": { name: "data-model", register: dataModel_js_1.registerDataModelTools },
|
|
1997
2018
|
functions: { name: "functions", register: functions_js_1.registerFunctionTools },
|
|
1998
2019
|
hosting: { name: "hosting", register: hosting_js_1.registerHostingTools },
|
|
1999
2020
|
storage: { name: "storage", register: storage_js_1.registerStorageTools },
|
|
@@ -2081,7 +2102,7 @@ function parseEnabledPlugins(pluginsEnabled, pluginsDisabled) {
|
|
|
2081
2102
|
* await server.connect(transport);
|
|
2082
2103
|
*/
|
|
2083
2104
|
async function createCloudBaseMcpServer(options) {
|
|
2084
|
-
const { name = "cloudbase-mcp", version = "1.0.0", enableTelemetry = true, cloudBaseOptions, authOptions, cloudMode = false, ide, logger, pluginsEnabled, pluginsDisabled, } = options ?? {};
|
|
2105
|
+
const { name = "cloudbase-mcp", version = "1.0.0", enableTelemetry = true, cloudBaseOptions, authOptions, cloudMode = false, ide, logger, pluginsEnabled, pluginsDisabled, pluginOptions, } = options ?? {};
|
|
2085
2106
|
// Enable cloud mode if specified
|
|
2086
2107
|
if (cloudMode) {
|
|
2087
2108
|
(0, cloud_mode_js_1.enableCloudMode)();
|
|
@@ -2096,20 +2117,31 @@ async function createCloudBaseMcpServer(options) {
|
|
|
2096
2117
|
...(ide === "CodeBuddy" ? { logging: {} } : {}),
|
|
2097
2118
|
},
|
|
2098
2119
|
});
|
|
2120
|
+
// 初始化 toolDefs,用于外部提取工具列表(如微信 IDE)
|
|
2121
|
+
server.toolDefs = [];
|
|
2099
2122
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
2100
|
-
server.registerTool = ((name, meta, handler) =>
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2123
|
+
server.registerTool = ((name, meta, handler) => {
|
|
2124
|
+
// 同步记录到 toolDefs
|
|
2125
|
+
server.toolDefs.push({
|
|
2126
|
+
name,
|
|
2127
|
+
description: meta?.description ?? meta?.title ?? '',
|
|
2128
|
+
inputSchema: meta?.inputSchema ?? {},
|
|
2129
|
+
handler,
|
|
2130
|
+
});
|
|
2131
|
+
return originalRegisterTool(name, meta, async (args) => {
|
|
2132
|
+
try {
|
|
2133
|
+
return await handler(args);
|
|
2109
2134
|
}
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2135
|
+
catch (error) {
|
|
2136
|
+
if ((0, tool_result_js_1.isToolPayloadError)(error)) {
|
|
2137
|
+
// 在结构化错误返回中注入 MCP 版本号
|
|
2138
|
+
const payload = { ...error.payload, mcpVersion: version };
|
|
2139
|
+
return (0, tool_result_js_1.buildJsonToolResult)(payload);
|
|
2140
|
+
}
|
|
2141
|
+
throw error;
|
|
2142
|
+
}
|
|
2143
|
+
});
|
|
2144
|
+
});
|
|
2113
2145
|
// Only set logging handler if logging capability is declared
|
|
2114
2146
|
if (ide === "CodeBuddy") {
|
|
2115
2147
|
server.server.setRequestHandler(types_js_1.SetLevelRequestSchema, (request, extra) => {
|
|
@@ -2124,6 +2156,10 @@ async function createCloudBaseMcpServer(options) {
|
|
|
2124
2156
|
if (authOptions) {
|
|
2125
2157
|
server.authOptions = authOptions;
|
|
2126
2158
|
}
|
|
2159
|
+
// Store pluginOptions in server instance for plugins to access
|
|
2160
|
+
if (pluginOptions) {
|
|
2161
|
+
server.pluginOptions = pluginOptions;
|
|
2162
|
+
}
|
|
2127
2163
|
// Store ide in server instance for telemetry
|
|
2128
2164
|
if (ide) {
|
|
2129
2165
|
server.ide = ide;
|
|
@@ -2231,8 +2267,8 @@ function registerLogTools(server) {
|
|
|
2231
2267
|
const cloudBaseOptions = server.cloudBaseOptions;
|
|
2232
2268
|
const getManager = () => (0, cloudbase_manager_js_1.getCloudBaseManager)({ cloudBaseOptions });
|
|
2233
2269
|
server.registerTool?.("queryLogs", {
|
|
2234
|
-
title: "
|
|
2235
|
-
description: "日志域统一只读入口。支持检查日志服务状态并搜索 CLS 日志。" +
|
|
2270
|
+
title: "查询 CloudBase 日志服务",
|
|
2271
|
+
description: "CloudBase 日志域统一只读入口。支持检查日志服务状态并搜索 CLS 日志。" +
|
|
2236
2272
|
"\n\n**重要区分**:" +
|
|
2237
2273
|
"\n- 查询云函数日志:使用 `queryFunctions(action=\"listFunctionLogs\", functionName=\"xxx\")`" +
|
|
2238
2274
|
"\n- 查询 CLS 日志(跨服务日志聚合):使用本工具 `queryLogs(action=\"searchLogs\")`" +
|
|
@@ -3284,7 +3320,7 @@ if (shouldUseConsole()) {
|
|
|
3284
3320
|
stderrLevels: ['error', 'warn', 'info', 'debug'], // All logs go to stderr
|
|
3285
3321
|
}));
|
|
3286
3322
|
}
|
|
3287
|
-
if (!(0, cloud_mode_js_1.isCloudMode)()) {
|
|
3323
|
+
if (!(0, cloud_mode_js_1.isCloudMode)() && process.env.CLOUDBASE_MCP_DISABLE_LOG_FILE !== 'true') {
|
|
3288
3324
|
// File transport with daily rotation
|
|
3289
3325
|
transports.push(new DailyRotateFile({
|
|
3290
3326
|
dirname: logDir,
|
|
@@ -3703,8 +3739,9 @@ async function getDatabaseInstanceId(options) {
|
|
|
3703
3739
|
async function getCloudBaseManager(options = {}) {
|
|
3704
3740
|
const { requireEnvId = true, cloudBaseOptions, authStrategy = 'fail_fast', } = options;
|
|
3705
3741
|
const hasDirectCredentials = !!(cloudBaseOptions?.secretId && cloudBaseOptions?.secretKey);
|
|
3706
|
-
|
|
3707
|
-
|
|
3742
|
+
const hasRequestFn = !!(cloudBaseOptions?.requestFn);
|
|
3743
|
+
// 如果传入了完整凭据或 requestFn,优先使用显式 CloudBase 配置
|
|
3744
|
+
if (cloudBaseOptions && (hasDirectCredentials || hasRequestFn)) {
|
|
3708
3745
|
let resolvedEnvId = cloudBaseOptions.envId;
|
|
3709
3746
|
if (requireEnvId && !resolvedEnvId) {
|
|
3710
3747
|
const envCandidates = await listAvailableEnvCandidates({ cloudBaseOptions });
|
|
@@ -4018,6 +4055,13 @@ async function callNoSqlContentApi(options) {
|
|
|
4018
4055
|
instanceIdSource: "envId",
|
|
4019
4056
|
requestId: result?.RequestId,
|
|
4020
4057
|
});
|
|
4058
|
+
// 检查 API 层返回的业务错误(如集合不存在)并抛出
|
|
4059
|
+
if (result?.Error) {
|
|
4060
|
+
const err = new Error(`${result.Error.Code}: ${result.Error.Message}`);
|
|
4061
|
+
err.code = result.Error.Code;
|
|
4062
|
+
err.requestId = result.RequestId;
|
|
4063
|
+
throw err;
|
|
4064
|
+
}
|
|
4021
4065
|
return result;
|
|
4022
4066
|
}
|
|
4023
4067
|
catch (error) {
|
|
@@ -4031,7 +4075,7 @@ async function callNoSqlContentApi(options) {
|
|
|
4031
4075
|
throw error;
|
|
4032
4076
|
}
|
|
4033
4077
|
}
|
|
4034
|
-
async function waitForCollectionReady({ cloudbase, collectionName, logger, timeoutMs = COLLECTION_READY_TIMEOUT_MS, pollIntervalMs = COLLECTION_READY_POLL_INTERVAL_MS, }) {
|
|
4078
|
+
async function waitForCollectionReady({ cloudbase, collectionName, logger, cloudBaseOptions, timeoutMs = COLLECTION_READY_TIMEOUT_MS, pollIntervalMs = COLLECTION_READY_POLL_INTERVAL_MS, }) {
|
|
4035
4079
|
const startedAt = Date.now();
|
|
4036
4080
|
const deadline = startedAt + timeoutMs;
|
|
4037
4081
|
let lastError;
|
|
@@ -4045,17 +4089,40 @@ async function waitForCollectionReady({ cloudbase, collectionName, logger, timeo
|
|
|
4045
4089
|
});
|
|
4046
4090
|
while (Date.now() <= deadline) {
|
|
4047
4091
|
try {
|
|
4048
|
-
//
|
|
4049
|
-
|
|
4050
|
-
const
|
|
4051
|
-
|
|
4092
|
+
// 用 PutItem 探测集合是否真正就绪(DescribeTable 可能误报),插入一个空占位文档
|
|
4093
|
+
// 如果成功,立即删除该文档;如果仍 ResourceNotFound,继续等待
|
|
4094
|
+
const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
4095
|
+
const probeDoc = JSON.stringify({ _readyProbe: true, _ts: Date.now() });
|
|
4096
|
+
const probeResult = await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
4097
|
+
Action: "PutItem",
|
|
4052
4098
|
Param: {
|
|
4053
4099
|
EnvId: envId,
|
|
4054
4100
|
TableName: collectionName,
|
|
4101
|
+
MgoDocs: [probeDoc],
|
|
4055
4102
|
},
|
|
4056
4103
|
});
|
|
4057
|
-
(0, cloudbase_manager_js_1.logCloudBaseResult)(logger,
|
|
4058
|
-
|
|
4104
|
+
(0, cloudbase_manager_js_1.logCloudBaseResult)(logger, probeResult);
|
|
4105
|
+
if (probeResult?.Error) {
|
|
4106
|
+
// 集合还未就绪,继续轮询
|
|
4107
|
+
throw new Error(probeResult.Error.Message);
|
|
4108
|
+
}
|
|
4109
|
+
// 集合就绪,清理探测文档
|
|
4110
|
+
if (Array.isArray(probeResult?.InsertedIds) && probeResult.InsertedIds.length > 0) {
|
|
4111
|
+
try {
|
|
4112
|
+
await cloudbase.commonService("tcb", "2018-06-08").call({
|
|
4113
|
+
Action: "DeleteItem",
|
|
4114
|
+
Param: {
|
|
4115
|
+
EnvId: envId,
|
|
4116
|
+
TableName: collectionName,
|
|
4117
|
+
MgoQuery: JSON.stringify({ _readyProbe: true }),
|
|
4118
|
+
MgoIsMulti: true,
|
|
4119
|
+
},
|
|
4120
|
+
});
|
|
4121
|
+
}
|
|
4122
|
+
catch {
|
|
4123
|
+
// 清理失败不影响主流程
|
|
4124
|
+
}
|
|
4125
|
+
}
|
|
4059
4126
|
logger?.({
|
|
4060
4127
|
type: "toolInfo",
|
|
4061
4128
|
toolName: "writeNoSqlDatabaseStructure",
|
|
@@ -4094,8 +4161,8 @@ function registerDatabaseTools(server) {
|
|
|
4094
4161
|
const getManager = () => (0, cloudbase_manager_js_1.getCloudBaseManager)({ cloudBaseOptions });
|
|
4095
4162
|
// readNoSqlDatabaseStructure
|
|
4096
4163
|
server.registerTool?.("readNoSqlDatabaseStructure", {
|
|
4097
|
-
title: "读取 NoSQL 数据库结构",
|
|
4098
|
-
description: "读取 NoSQL 数据库集合与索引结构,支持列出集合、查看集合详情、列出索引以及检查索引是否存在。本工具为服务端管理工具,用于管理端查询数据库结构,不用于编写客户端代码。",
|
|
4164
|
+
title: "读取 CloudBase NoSQL 数据库结构",
|
|
4165
|
+
description: "读取 CloudBase NoSQL 数据库集合与索引结构,支持列出集合、查看集合详情、列出索引以及检查索引是否存在。本工具为服务端管理工具,用于管理端查询数据库结构,不用于编写客户端代码。",
|
|
4099
4166
|
inputSchema: {
|
|
4100
4167
|
action: zod_1.z.enum([
|
|
4101
4168
|
"listCollections",
|
|
@@ -4282,8 +4349,8 @@ checkIndex: 检查指定索引是否存在`),
|
|
|
4282
4349
|
});
|
|
4283
4350
|
// writeNoSqlDatabaseStructure
|
|
4284
4351
|
server.registerTool?.("writeNoSqlDatabaseStructure", {
|
|
4285
|
-
title: "创建并管理 NoSQL 数据库集合",
|
|
4286
|
-
description: "创建、删除和管理 NoSQL 数据库集合(collection)。支持创建新集合、删除现有集合,以及通过 updateCollection 的 updateOptions.CreateIndexes / updateOptions.DropIndexes 添加索引和删除索引。当需要新建集合时,使用 action=createCollection。本工具为服务端管理工具,用于管理端操作集合和索引结构,不用于编写客户端代码。",
|
|
4352
|
+
title: "创建并管理 CloudBase NoSQL 数据库集合",
|
|
4353
|
+
description: "创建、删除和管理 CloudBase NoSQL 数据库集合(collection)。支持创建新集合、删除现有集合,以及通过 updateCollection 的 updateOptions.CreateIndexes / updateOptions.DropIndexes 添加索引和删除索引。当需要新建集合时,使用 action=createCollection。本工具为服务端管理工具,用于管理端操作集合和索引结构,不用于编写客户端代码。",
|
|
4287
4354
|
inputSchema: {
|
|
4288
4355
|
action: zod_1.z.enum([
|
|
4289
4356
|
"createCollection",
|
|
@@ -4343,8 +4410,14 @@ deleteCollection: 删除集合`),
|
|
|
4343
4410
|
Action: "DescribeTable",
|
|
4344
4411
|
Param: { EnvId: envId, TableName: collectionName },
|
|
4345
4412
|
});
|
|
4346
|
-
|
|
4347
|
-
|
|
4413
|
+
if (descResult?.Error) {
|
|
4414
|
+
// 集合不存在(ResourceNotFound)或其他错误,继续创建
|
|
4415
|
+
existsRequestId = descResult.RequestId ?? "";
|
|
4416
|
+
}
|
|
4417
|
+
else {
|
|
4418
|
+
collectionExists = true;
|
|
4419
|
+
existsRequestId = descResult?.RequestId ?? "";
|
|
4420
|
+
}
|
|
4348
4421
|
}
|
|
4349
4422
|
catch (e) {
|
|
4350
4423
|
existsRequestId = e?.requestId ?? "";
|
|
@@ -4377,6 +4450,7 @@ deleteCollection: 删除集合`),
|
|
|
4377
4450
|
cloudbase,
|
|
4378
4451
|
collectionName,
|
|
4379
4452
|
logger: server.logger,
|
|
4453
|
+
cloudBaseOptions: server.cloudBaseOptions,
|
|
4380
4454
|
});
|
|
4381
4455
|
return {
|
|
4382
4456
|
content: [
|
|
@@ -4459,8 +4533,8 @@ deleteCollection: 删除集合`),
|
|
|
4459
4533
|
});
|
|
4460
4534
|
// readNoSqlDatabaseContent
|
|
4461
4535
|
server.registerTool?.("readNoSqlDatabaseContent", {
|
|
4462
|
-
title: "查询并获取 NoSQL 数据库数据记录",
|
|
4463
|
-
description: "
|
|
4536
|
+
title: "查询并获取 CloudBase NoSQL 数据库数据记录",
|
|
4537
|
+
description: "查询 CloudBase NoSQL 数据库中的数据记录。支持按条件筛选、分页、排序,适用于管理端数据查询与运维。",
|
|
4464
4538
|
inputSchema: {
|
|
4465
4539
|
collectionName: zod_1.z.string().describe("集合名称"),
|
|
4466
4540
|
instanceId: zod_1.z
|
|
@@ -4546,8 +4620,10 @@ deleteCollection: 删除集合`),
|
|
|
4546
4620
|
});
|
|
4547
4621
|
// writeNoSqlDatabaseContent
|
|
4548
4622
|
server.registerTool?.("writeNoSqlDatabaseContent", {
|
|
4549
|
-
title: "修改 NoSQL 数据库数据记录",
|
|
4550
|
-
description: "修改 NoSQL
|
|
4623
|
+
title: "修改 CloudBase NoSQL 数据库数据记录",
|
|
4624
|
+
description: "修改 CloudBase NoSQL 数据库中的数据记录。支持插入、更新(含 $set/$inc/$push 等操作符)、删除、upsert 等操作,适用于管理端数据写入与运维。" +
|
|
4625
|
+
"⚠️ 服务端写入不含 _openid:若集合依赖客户端 SDK(@cloudbase/js-sdk 或微信小程序 wx.cloud.database())的行级安全规则(如 doc._openid == auth.openid),服务端写入时需手动补充 _openid 字段,否则客户端将无法读取到该数据。" +
|
|
4626
|
+
"⚠️ 部分更新嵌套字段须使用点号路径,如 `$set: {\"shipping.city\": \"guangzhou\"}`,直接传嵌套对象会覆盖整个字段。",
|
|
4551
4627
|
inputSchema: {
|
|
4552
4628
|
action: zod_1.z
|
|
4553
4629
|
.enum(["insert", "update", "delete"])
|
|
@@ -6240,99 +6316,6 @@ async function downloadResources() {
|
|
|
6240
6316
|
return resourceDownloadPromise;
|
|
6241
6317
|
}
|
|
6242
6318
|
async function registerRagTools(server) {
|
|
6243
|
-
// 联网搜索
|
|
6244
|
-
server.registerTool?.("searchWeb", {
|
|
6245
|
-
title: "联网搜索",
|
|
6246
|
-
description: "使用联网来进行信息检索,如查询最新的新闻、文章、股价、天气等。支持自然语言查询,也可以直接输入网址获取网页内容",
|
|
6247
|
-
inputSchema: {
|
|
6248
|
-
query: zod_1.z.string().describe("搜索关键词、问题或网址,支持自然语言"),
|
|
6249
|
-
},
|
|
6250
|
-
annotations: {
|
|
6251
|
-
readOnlyHint: true,
|
|
6252
|
-
openWorldHint: true,
|
|
6253
|
-
category: "web",
|
|
6254
|
-
},
|
|
6255
|
-
}, async ({ query }) => {
|
|
6256
|
-
try {
|
|
6257
|
-
// 使用混元进行联网搜索
|
|
6258
|
-
const signInRes = await fetch("https://tcb-advanced-a656fc.api.tcloudbasegateway.com/auth/v1/signin/anonymously", {
|
|
6259
|
-
method: "POST",
|
|
6260
|
-
headers: {
|
|
6261
|
-
"Content-Type": "application/json",
|
|
6262
|
-
Accept: "application/json",
|
|
6263
|
-
"x-device-id": "cloudbase-ai-toolkit",
|
|
6264
|
-
},
|
|
6265
|
-
body: safeStringify({}),
|
|
6266
|
-
});
|
|
6267
|
-
const { access_token } = await signInRes.json();
|
|
6268
|
-
// 调用混元API进行联网搜索
|
|
6269
|
-
const searchRes = await fetch("https://tcb-advanced-a656fc.api.tcloudbasegateway.com/v1/ai/hunyuan-beta/openapi/v1/chat/completions", {
|
|
6270
|
-
method: "POST",
|
|
6271
|
-
headers: {
|
|
6272
|
-
"Content-Type": "application/json",
|
|
6273
|
-
Authorization: `Bearer ${access_token}`,
|
|
6274
|
-
},
|
|
6275
|
-
body: safeStringify({
|
|
6276
|
-
model: "hunyuan",
|
|
6277
|
-
messages: [
|
|
6278
|
-
{
|
|
6279
|
-
role: "user",
|
|
6280
|
-
content: `你好,你将扮演一个知识库的角色,联网查询到问题的答案之后回答给我`,
|
|
6281
|
-
},
|
|
6282
|
-
{
|
|
6283
|
-
role: "assistant",
|
|
6284
|
-
content: "好的",
|
|
6285
|
-
},
|
|
6286
|
-
{
|
|
6287
|
-
role: "user",
|
|
6288
|
-
content: query,
|
|
6289
|
-
},
|
|
6290
|
-
],
|
|
6291
|
-
enable_enhancement: true,
|
|
6292
|
-
search_info: true,
|
|
6293
|
-
enable_speed_search: true,
|
|
6294
|
-
force_search_enhancement: true,
|
|
6295
|
-
}),
|
|
6296
|
-
});
|
|
6297
|
-
const result = await searchRes.json();
|
|
6298
|
-
if (result.error) {
|
|
6299
|
-
throw new Error(result.error.message || "联网搜索失败");
|
|
6300
|
-
}
|
|
6301
|
-
const content = result.choices?.[0]?.message?.content || "";
|
|
6302
|
-
const searchResults = result.search_info?.search_results || [];
|
|
6303
|
-
return {
|
|
6304
|
-
content: [
|
|
6305
|
-
{
|
|
6306
|
-
type: "text",
|
|
6307
|
-
text: safeStringify({
|
|
6308
|
-
type: "web_search",
|
|
6309
|
-
content: content,
|
|
6310
|
-
search_results: searchResults.map((item) => ({
|
|
6311
|
-
title: item.title,
|
|
6312
|
-
url: item.url,
|
|
6313
|
-
snippet: item.snippet,
|
|
6314
|
-
})),
|
|
6315
|
-
status: "success",
|
|
6316
|
-
}),
|
|
6317
|
-
},
|
|
6318
|
-
],
|
|
6319
|
-
};
|
|
6320
|
-
}
|
|
6321
|
-
catch (error) {
|
|
6322
|
-
return {
|
|
6323
|
-
content: [
|
|
6324
|
-
{
|
|
6325
|
-
type: "text",
|
|
6326
|
-
text: safeStringify({
|
|
6327
|
-
type: "error",
|
|
6328
|
-
message: error instanceof Error ? error.message : "联网搜索失败",
|
|
6329
|
-
status: "error",
|
|
6330
|
-
}),
|
|
6331
|
-
},
|
|
6332
|
-
],
|
|
6333
|
-
};
|
|
6334
|
-
}
|
|
6335
|
-
});
|
|
6336
6319
|
let openapis = [];
|
|
6337
6320
|
let skills = [];
|
|
6338
6321
|
let fallbackSkillsRoot;
|
|
@@ -7344,6 +7327,7 @@ async function resolveStoragePublicAccess(params) {
|
|
|
7344
7327
|
function registerStorageTools(server) {
|
|
7345
7328
|
// 获取 cloudBaseOptions,如果没有则为 undefined
|
|
7346
7329
|
const cloudBaseOptions = server.cloudBaseOptions;
|
|
7330
|
+
const storageOverrides = server.pluginOptions?.storage;
|
|
7347
7331
|
// 创建闭包函数来获取 CloudBase Manager
|
|
7348
7332
|
const getManager = () => (0, cloudbase_manager_js_1.getCloudBaseManager)({ cloudBaseOptions });
|
|
7349
7333
|
// Tool 1: queryStorage - 查询存储信息(只读操作)
|
|
@@ -7365,7 +7349,14 @@ function registerStorageTools(server) {
|
|
|
7365
7349
|
const storageService = manager.storage;
|
|
7366
7350
|
switch (input.action) {
|
|
7367
7351
|
case 'list': {
|
|
7368
|
-
|
|
7352
|
+
let files;
|
|
7353
|
+
if (storageOverrides?.listFiles) {
|
|
7354
|
+
files = await storageOverrides.listFiles({ cloudPath: input.cloudPath });
|
|
7355
|
+
}
|
|
7356
|
+
else {
|
|
7357
|
+
const result = await storageService.listDirectoryFiles(input.cloudPath);
|
|
7358
|
+
files = result || [];
|
|
7359
|
+
}
|
|
7369
7360
|
return {
|
|
7370
7361
|
content: [
|
|
7371
7362
|
{
|
|
@@ -7375,17 +7366,23 @@ function registerStorageTools(server) {
|
|
|
7375
7366
|
data: {
|
|
7376
7367
|
action: 'list',
|
|
7377
7368
|
cloudPath: input.cloudPath,
|
|
7378
|
-
files
|
|
7379
|
-
totalCount:
|
|
7369
|
+
files,
|
|
7370
|
+
totalCount: files.length
|
|
7380
7371
|
},
|
|
7381
|
-
message: `Successfully listed ${
|
|
7372
|
+
message: `Successfully listed ${files.length} files in directory '${input.cloudPath}'`
|
|
7382
7373
|
}, null, 2)
|
|
7383
7374
|
}
|
|
7384
7375
|
]
|
|
7385
7376
|
};
|
|
7386
7377
|
}
|
|
7387
7378
|
case 'info': {
|
|
7388
|
-
|
|
7379
|
+
let fileInfo;
|
|
7380
|
+
if (storageOverrides?.getFileInfo) {
|
|
7381
|
+
fileInfo = await storageOverrides.getFileInfo({ cloudPath: input.cloudPath });
|
|
7382
|
+
}
|
|
7383
|
+
else {
|
|
7384
|
+
fileInfo = await storageService.getFileInfo(input.cloudPath);
|
|
7385
|
+
}
|
|
7389
7386
|
return {
|
|
7390
7387
|
content: [
|
|
7391
7388
|
{
|
|
@@ -7395,7 +7392,7 @@ function registerStorageTools(server) {
|
|
|
7395
7392
|
data: {
|
|
7396
7393
|
action: 'info',
|
|
7397
7394
|
cloudPath: input.cloudPath,
|
|
7398
|
-
fileInfo
|
|
7395
|
+
fileInfo
|
|
7399
7396
|
},
|
|
7400
7397
|
message: `Successfully retrieved file info for '${input.cloudPath}'`
|
|
7401
7398
|
}, null, 2)
|
|
@@ -7439,10 +7436,15 @@ function registerStorageTools(server) {
|
|
|
7439
7436
|
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), STORAGE_READ_TEMP_PREFIX));
|
|
7440
7437
|
const localPath = path.join(tempDir, getStorageTempFileName(input.cloudPath));
|
|
7441
7438
|
try {
|
|
7442
|
-
|
|
7443
|
-
cloudPath: input.cloudPath,
|
|
7444
|
-
|
|
7445
|
-
|
|
7439
|
+
if (storageOverrides?.downloadFile) {
|
|
7440
|
+
await storageOverrides.downloadFile({ cloudPath: input.cloudPath, localPath });
|
|
7441
|
+
}
|
|
7442
|
+
else {
|
|
7443
|
+
await storageService.downloadFile({
|
|
7444
|
+
cloudPath: input.cloudPath,
|
|
7445
|
+
localPath
|
|
7446
|
+
});
|
|
7447
|
+
}
|
|
7446
7448
|
const buffer = await fs.readFile(localPath);
|
|
7447
7449
|
const decoded = decodeInlineTextContent(buffer);
|
|
7448
7450
|
return {
|
|
@@ -7497,22 +7499,32 @@ function registerStorageTools(server) {
|
|
|
7497
7499
|
switch (input.action) {
|
|
7498
7500
|
case 'upload': {
|
|
7499
7501
|
if (input.isDirectory) {
|
|
7500
|
-
|
|
7501
|
-
localPath: input.localPath,
|
|
7502
|
-
|
|
7503
|
-
|
|
7504
|
-
|
|
7505
|
-
|
|
7506
|
-
|
|
7502
|
+
if (storageOverrides?.uploadDirectory) {
|
|
7503
|
+
await storageOverrides.uploadDirectory({ localPath: input.localPath, cloudPath: input.cloudPath });
|
|
7504
|
+
}
|
|
7505
|
+
else {
|
|
7506
|
+
await storageService.uploadDirectory({
|
|
7507
|
+
localPath: input.localPath,
|
|
7508
|
+
cloudPath: input.cloudPath,
|
|
7509
|
+
onProgress: (progressData) => {
|
|
7510
|
+
console.log("Upload directory progress:", progressData);
|
|
7511
|
+
}
|
|
7512
|
+
});
|
|
7513
|
+
}
|
|
7507
7514
|
}
|
|
7508
7515
|
else {
|
|
7509
|
-
|
|
7510
|
-
localPath: input.localPath,
|
|
7511
|
-
|
|
7512
|
-
|
|
7513
|
-
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
+
if (storageOverrides?.uploadFile) {
|
|
7517
|
+
await storageOverrides.uploadFile({ localPath: input.localPath, cloudPath: input.cloudPath });
|
|
7518
|
+
}
|
|
7519
|
+
else {
|
|
7520
|
+
await storageService.uploadFile({
|
|
7521
|
+
localPath: input.localPath,
|
|
7522
|
+
cloudPath: input.cloudPath,
|
|
7523
|
+
onProgress: (progressData) => {
|
|
7524
|
+
console.log("Upload file progress:", progressData);
|
|
7525
|
+
}
|
|
7526
|
+
});
|
|
7527
|
+
}
|
|
7516
7528
|
}
|
|
7517
7529
|
const fileUrls = await storageService.getTemporaryUrl([{
|
|
7518
7530
|
cloudPath: input.cloudPath,
|
|
@@ -7548,16 +7560,26 @@ function registerStorageTools(server) {
|
|
|
7548
7560
|
}
|
|
7549
7561
|
case 'download': {
|
|
7550
7562
|
if (input.isDirectory) {
|
|
7551
|
-
|
|
7552
|
-
cloudPath: input.cloudPath,
|
|
7553
|
-
|
|
7554
|
-
|
|
7563
|
+
if (storageOverrides?.downloadDirectory) {
|
|
7564
|
+
await storageOverrides.downloadDirectory({ cloudPath: input.cloudPath, localPath: input.localPath });
|
|
7565
|
+
}
|
|
7566
|
+
else {
|
|
7567
|
+
await storageService.downloadDirectory({
|
|
7568
|
+
cloudPath: input.cloudPath,
|
|
7569
|
+
localPath: input.localPath
|
|
7570
|
+
});
|
|
7571
|
+
}
|
|
7555
7572
|
}
|
|
7556
7573
|
else {
|
|
7557
|
-
|
|
7558
|
-
cloudPath: input.cloudPath,
|
|
7559
|
-
|
|
7560
|
-
|
|
7574
|
+
if (storageOverrides?.downloadFile) {
|
|
7575
|
+
await storageOverrides.downloadFile({ cloudPath: input.cloudPath, localPath: input.localPath });
|
|
7576
|
+
}
|
|
7577
|
+
else {
|
|
7578
|
+
await storageService.downloadFile({
|
|
7579
|
+
cloudPath: input.cloudPath,
|
|
7580
|
+
localPath: input.localPath
|
|
7581
|
+
});
|
|
7582
|
+
}
|
|
7561
7583
|
}
|
|
7562
7584
|
return {
|
|
7563
7585
|
content: [
|
|
@@ -7593,10 +7615,20 @@ function registerStorageTools(server) {
|
|
|
7593
7615
|
};
|
|
7594
7616
|
}
|
|
7595
7617
|
if (input.isDirectory) {
|
|
7596
|
-
|
|
7618
|
+
if (storageOverrides?.deleteDirectory) {
|
|
7619
|
+
await storageOverrides.deleteDirectory({ cloudPath: input.cloudPath });
|
|
7620
|
+
}
|
|
7621
|
+
else {
|
|
7622
|
+
await storageService.deleteDirectory(input.cloudPath);
|
|
7623
|
+
}
|
|
7597
7624
|
}
|
|
7598
7625
|
else {
|
|
7599
|
-
|
|
7626
|
+
if (storageOverrides?.deleteFiles) {
|
|
7627
|
+
await storageOverrides.deleteFiles({ cloudPaths: [input.cloudPath] });
|
|
7628
|
+
}
|
|
7629
|
+
else {
|
|
7630
|
+
await storageService.deleteFile([input.cloudPath]);
|
|
7631
|
+
}
|
|
7600
7632
|
}
|
|
7601
7633
|
return {
|
|
7602
7634
|
content: [
|
|
@@ -9275,7 +9307,7 @@ class TelemetryReporter {
|
|
|
9275
9307
|
const nodeVersion = process.version; // Node.js版本
|
|
9276
9308
|
const arch = os_1.default.arch(); // 系统架构
|
|
9277
9309
|
// 从构建时注入的版本号获取MCP版本信息
|
|
9278
|
-
const mcpVersion = process.env.npm_package_version || "2.21.
|
|
9310
|
+
const mcpVersion = process.env.npm_package_version || "2.21.1-beta.1" || 0;
|
|
9279
9311
|
return {
|
|
9280
9312
|
userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
|
|
9281
9313
|
deviceId: this.deviceId,
|
|
@@ -9666,6 +9698,7 @@ exports.MANAGE_FUNCTION_ACTIONS = [
|
|
|
9666
9698
|
"attachLayer",
|
|
9667
9699
|
"detachLayer",
|
|
9668
9700
|
"updateFunctionLayers",
|
|
9701
|
+
"incrementalDeployFunction", // 增量部署,需通过 pluginOptions.functions 注入实现
|
|
9669
9702
|
];
|
|
9670
9703
|
const VPC_SCHEMA = zod_1.z.object({
|
|
9671
9704
|
vpcId: zod_1.z.string(),
|
|
@@ -9847,6 +9880,7 @@ function wrapFunctionOperationError(operation, functionName, functionRootPath, e
|
|
|
9847
9880
|
}
|
|
9848
9881
|
function registerFunctionTools(server) {
|
|
9849
9882
|
const cloudBaseOptions = server.cloudBaseOptions;
|
|
9883
|
+
const deployOverrides = server.pluginOptions?.functions;
|
|
9850
9884
|
const getManager = () => (0, cloudbase_manager_js_1.getCloudBaseManager)({ cloudBaseOptions });
|
|
9851
9885
|
const buildEnvelope = (data, message, nextActions) => ({
|
|
9852
9886
|
success: true,
|
|
@@ -10211,6 +10245,16 @@ function registerFunctionTools(server) {
|
|
|
10211
10245
|
ensureActionAllowedInCloudMode(input);
|
|
10212
10246
|
switch (input.action) {
|
|
10213
10247
|
case "createFunction": {
|
|
10248
|
+
if (deployOverrides?.createFunction) {
|
|
10249
|
+
const result = await deployOverrides.createFunction({
|
|
10250
|
+
functionName: String(input.func?.name ?? input.functionName ?? ''),
|
|
10251
|
+
functionRootPath: input.functionRootPath ?? '',
|
|
10252
|
+
runtime: input.func?.runtime,
|
|
10253
|
+
force: input.force,
|
|
10254
|
+
installDependency: input.func?.installDependency,
|
|
10255
|
+
});
|
|
10256
|
+
return buildEnvelope({ action: input.action, result }, '云函数部署成功(override)');
|
|
10257
|
+
}
|
|
10214
10258
|
if (!input.func?.name || typeof input.func.name !== "string") {
|
|
10215
10259
|
throw new Error("createFunction 操作时,func.name 参数是必需的");
|
|
10216
10260
|
}
|
|
@@ -10298,6 +10342,15 @@ function registerFunctionTools(server) {
|
|
|
10298
10342
|
}, message, nextActions);
|
|
10299
10343
|
}
|
|
10300
10344
|
case "updateFunctionCode": {
|
|
10345
|
+
if (deployOverrides?.updateFunctionCode) {
|
|
10346
|
+
const result = await deployOverrides.updateFunctionCode({
|
|
10347
|
+
functionName: input.functionName ?? '',
|
|
10348
|
+
functionRootPath: input.functionRootPath ?? '',
|
|
10349
|
+
force: input.force,
|
|
10350
|
+
installDependency: input.func?.installDependency,
|
|
10351
|
+
});
|
|
10352
|
+
return buildEnvelope({ action: input.action, result }, '云函数代码更新成功(override)');
|
|
10353
|
+
}
|
|
10301
10354
|
if (!input.functionName) {
|
|
10302
10355
|
throw new Error("updateFunctionCode 操作时,functionName 参数是必需的");
|
|
10303
10356
|
}
|
|
@@ -10631,6 +10684,19 @@ function registerFunctionTools(server) {
|
|
|
10631
10684
|
]);
|
|
10632
10685
|
}
|
|
10633
10686
|
default:
|
|
10687
|
+
// incrementalDeployFunction:无默认实现,必须通过 pluginOptions 注入
|
|
10688
|
+
if (input.action === 'incrementalDeployFunction') {
|
|
10689
|
+
const fn = deployOverrides?.incrementalDeployFunction;
|
|
10690
|
+
if (!fn) {
|
|
10691
|
+
throw new Error('incrementalDeployFunction 需要通过 pluginOptions.functions.incrementalDeployFunction 注入实现(仅在支持的 IDE 环境中可用)');
|
|
10692
|
+
}
|
|
10693
|
+
const result = await fn({
|
|
10694
|
+
functionName: input.functionName ?? '',
|
|
10695
|
+
functionRootPath: input.functionRootPath ?? '',
|
|
10696
|
+
incrementalFile: input.incrementalFile ?? '',
|
|
10697
|
+
});
|
|
10698
|
+
return buildEnvelope({ action: input.action, result }, '云函数增量部署成功');
|
|
10699
|
+
}
|
|
10634
10700
|
throw new Error(`不支持的操作类型: ${input.action}`);
|
|
10635
10701
|
}
|
|
10636
10702
|
};
|
|
@@ -10703,7 +10769,7 @@ function registerFunctionTools(server) {
|
|
|
10703
10769
|
inputSchema: {
|
|
10704
10770
|
action: zod_1.z
|
|
10705
10771
|
.enum(exports.MANAGE_FUNCTION_ACTIONS)
|
|
10706
|
-
.describe("写操作类型,例如 createFunction、updateFunctionCode、invokeFunction、deleteFunction、" +
|
|
10772
|
+
.describe("写操作类型,例如 createFunction、updateFunctionCode、incrementalDeployFunction、invokeFunction、deleteFunction、" +
|
|
10707
10773
|
"createFunctionTrigger(定时任务 / cron / timer)、deleteFunctionTrigger、attachLayer、detachLayer"),
|
|
10708
10774
|
func: CREATE_FUNCTION_SCHEMA.optional().describe("createFunction 操作的函数配置"),
|
|
10709
10775
|
functionRootPath: zod_1.z.string().optional().describe("创建或更新函数代码时默认推荐的本地目录方式。" +
|
|
@@ -10739,6 +10805,7 @@ function registerFunctionTools(server) {
|
|
|
10739
10805
|
.describe("updateFunctionLayers 的目标层列表,顺序即最终顺序"),
|
|
10740
10806
|
codeSecret: zod_1.z.string().optional().describe("层绑定时的代码保护密钥"),
|
|
10741
10807
|
confirm: zod_1.z.boolean().optional().describe("危险操作确认开关。deleteFunction、deleteFunctionTrigger、deleteLayerVersion、detachLayer 等删除类操作需要显式传入 confirm=true"),
|
|
10808
|
+
incrementalFile: zod_1.z.string().optional().describe("incrementalDeployFunction 增量部署时的变更文件路径"),
|
|
10742
10809
|
},
|
|
10743
10810
|
annotations: {
|
|
10744
10811
|
readOnlyHint: false,
|
|
@@ -11845,7 +11912,7 @@ function registerSetupTools(server) {
|
|
|
11845
11912
|
server.registerTool("downloadTemplate", {
|
|
11846
11913
|
title: "下载项目模板",
|
|
11847
11914
|
description: `自动下载并部署CloudBase项目模板。
|
|
11848
|
-
**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.21.
|
|
11915
|
+
**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.21.1-beta.1" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
|
|
11849
11916
|
inputSchema: {
|
|
11850
11917
|
template: zod_1.z
|
|
11851
11918
|
.enum(["react", "vue", "miniprogram", "uniapp", "rules"])
|
|
@@ -13292,13 +13359,16 @@ async function resolveHostingStaticDomain(cloudbase, logger) {
|
|
|
13292
13359
|
return undefined;
|
|
13293
13360
|
}
|
|
13294
13361
|
}
|
|
13295
|
-
|
|
13362
|
+
// Returns the first hosting store record from DescribeStaticStore, which is
|
|
13363
|
+
// the authoritative source for Mini Program-sourced environments (those envs
|
|
13364
|
+
// do not populate StaticStorages in DescribeEnvs / getEnvInfo).
|
|
13365
|
+
// Throws when no valid store is found so upload can fail fast with a clear msg.
|
|
13366
|
+
async function getHostingStoreOrThrow(cloudbase, cloudBaseOptions, logger) {
|
|
13296
13367
|
const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
13297
|
-
const
|
|
13298
|
-
|
|
13299
|
-
|
|
13300
|
-
|
|
13301
|
-
return;
|
|
13368
|
+
const result = await callTcbHostingAction(cloudbase, 'DescribeStaticStore', { EnvId: envId }, logger);
|
|
13369
|
+
const hostingInfo = extractStaticStores(result);
|
|
13370
|
+
if (hostingInfo.length > 0 && hostingInfo[0].Bucket) {
|
|
13371
|
+
return hostingInfo[0];
|
|
13302
13372
|
}
|
|
13303
13373
|
throw new Error(`当前环境 ${envId} 未发现静态托管资源配置,无法上传文件。请先确认 MCP 已绑定到已开通静态托管的 CloudBase 环境;如需切换环境,请调用 auth(action="set_env", envId="目标环境ID") 后重试。`);
|
|
13304
13374
|
}
|
|
@@ -13506,8 +13576,9 @@ function registerHostingTools(server) {
|
|
|
13506
13576
|
throw new Error('manageHosting(action="upload") 需要提供 localPath + cloudPath,或提供 files 多文件上传列表。');
|
|
13507
13577
|
}
|
|
13508
13578
|
let result;
|
|
13579
|
+
let store;
|
|
13509
13580
|
try {
|
|
13510
|
-
await
|
|
13581
|
+
store = await getHostingStoreOrThrow(cloudbase, cloudBaseOptions, server.logger);
|
|
13511
13582
|
result = await cloudbase.hosting.uploadFiles({
|
|
13512
13583
|
localPath: input.localPath,
|
|
13513
13584
|
cloudPath: input.cloudPath,
|
|
@@ -13519,7 +13590,11 @@ function registerHostingTools(server) {
|
|
|
13519
13590
|
throw new Error(buildUploadErrorMessage(error, input.localPath));
|
|
13520
13591
|
}
|
|
13521
13592
|
(0, cloudbase_manager_js_1.logCloudBaseResult)(server.logger, result);
|
|
13522
|
-
|
|
13593
|
+
// Prefer CdnDomain from the DescribeStaticStore result we already
|
|
13594
|
+
// fetched; fall back to getEnvInfo for environments that populate
|
|
13595
|
+
// StaticDomain there but not in DescribeStaticStore.
|
|
13596
|
+
const cdnFromStore = (store.CdnDomain ?? store.StaticDomain);
|
|
13597
|
+
const staticDomain = cdnFromStore || await resolveHostingStaticDomain(cloudbase, server.logger);
|
|
13523
13598
|
const accessUrl = buildHostingAccessUrl(staticDomain, input.cloudPath, input.localPath);
|
|
13524
13599
|
try {
|
|
13525
13600
|
const envId = await (0, cloudbase_manager_js_1.getEnvId)(cloudBaseOptions);
|
|
@@ -15921,8 +15996,8 @@ function registerSQLDatabaseTools(server) {
|
|
|
15921
15996
|
server,
|
|
15922
15997
|
};
|
|
15923
15998
|
server.registerTool?.(QUERY_SQL_DATABASE, {
|
|
15924
|
-
title: "
|
|
15925
|
-
description: "
|
|
15999
|
+
title: "查询 CloudBase MySQL 数据库状态或执行只读 SQL",
|
|
16000
|
+
description: "查询 CloudBase MySQL 数据库信息。支持执行只读 SQL、查询 MySQL 开通结果、查询 MySQL 任务状态,以及获取当前实例上下文信息。",
|
|
15926
16001
|
inputSchema: {
|
|
15927
16002
|
action: zod_1.z
|
|
15928
16003
|
.enum(QUERY_ACTIONS)
|
|
@@ -15964,8 +16039,8 @@ function registerSQLDatabaseTools(server) {
|
|
|
15964
16039
|
}
|
|
15965
16040
|
});
|
|
15966
16041
|
server.registerTool?.(MANAGE_SQL_DATABASE, {
|
|
15967
|
-
title: "
|
|
15968
|
-
description: "
|
|
16042
|
+
title: "管理 CloudBase MySQL 数据库生命周期或执行写入 SQL",
|
|
16043
|
+
description: "管理 CloudBase MySQL 数据库资源。支持开通 MySQL、销毁 MySQL、执行写入 SQL/DDL,以及初始化数据库 Schema。注意:必须先开通 MySQL(action=provisionMySQL,confirm=true)才能执行 runStatement 或 initializeSchema。若 MySQL 尚未开通,工具会返回 MYSQL_NOT_CREATED 并给出开通的 nextAction 提示。",
|
|
15969
16044
|
inputSchema: {
|
|
15970
16045
|
action: zod_1.z
|
|
15971
16046
|
.enum(MANAGE_ACTIONS)
|