@cloudbase/cloudbase-mcp 2.15.2-beta.2 → 2.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +3 -3
- package/dist/index.cjs +264 -56
- package/dist/index.d.ts +15 -12
- package/dist/index.js +194 -26
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2020,6 +2020,20 @@ async function getGuidePrompt(server) {
|
|
|
2020
2020
|
return "";
|
|
2021
2021
|
}
|
|
2022
2022
|
}
|
|
2023
|
+
function normalizeOptionalToolString(value) {
|
|
2024
|
+
return typeof value === "string" && value.trim().length > 0
|
|
2025
|
+
? value.trim()
|
|
2026
|
+
: undefined;
|
|
2027
|
+
}
|
|
2028
|
+
function normalizeOptionalToolBoolean(value) {
|
|
2029
|
+
return typeof value === "boolean" ? value : undefined;
|
|
2030
|
+
}
|
|
2031
|
+
function resolveToolAuthOptions(server, overrides) {
|
|
2032
|
+
return (0, auth_js_1.resolveAuthOptions)({
|
|
2033
|
+
...overrides,
|
|
2034
|
+
serverAuthOptions: server.authOptions,
|
|
2035
|
+
});
|
|
2036
|
+
}
|
|
2023
2037
|
function registerEnvTools(server) {
|
|
2024
2038
|
// 获取 cloudBaseOptions,如果没有则为 undefined
|
|
2025
2039
|
const cloudBaseOptions = server.cloudBaseOptions;
|
|
@@ -2052,6 +2066,18 @@ function registerEnvTools(server) {
|
|
|
2052
2066
|
.enum(["device", "web"])
|
|
2053
2067
|
.optional()
|
|
2054
2068
|
.describe("认证模式:device=设备码授权,web=浏览器回调授权"),
|
|
2069
|
+
oauthEndpoint: zod_1.z
|
|
2070
|
+
.string()
|
|
2071
|
+
.optional()
|
|
2072
|
+
.describe("高级可选:自定义 device-code 登录 endpoint。配置后 oauthCustom 默认按 true 处理"),
|
|
2073
|
+
clientId: zod_1.z
|
|
2074
|
+
.string()
|
|
2075
|
+
.optional()
|
|
2076
|
+
.describe("高级可选:自定义 device-code 登录 client_id,不传则使用默认值"),
|
|
2077
|
+
oauthCustom: zod_1.z
|
|
2078
|
+
.boolean()
|
|
2079
|
+
.optional()
|
|
2080
|
+
.describe("高级可选:自定义 endpoint 返回格式开关。未配置 endpoint 时默认 false;配置 endpoint 后默认 true,且不能设为 false"),
|
|
2055
2081
|
}
|
|
2056
2082
|
: {}),
|
|
2057
2083
|
envId: zod_1.z
|
|
@@ -2079,8 +2105,18 @@ function registerEnvTools(server) {
|
|
|
2079
2105
|
const authMode = rawArgs.authMode === "device" || rawArgs.authMode === "web"
|
|
2080
2106
|
? rawArgs.authMode
|
|
2081
2107
|
: undefined;
|
|
2108
|
+
const oauthEndpoint = normalizeOptionalToolString(rawArgs.oauthEndpoint);
|
|
2109
|
+
const clientId = normalizeOptionalToolString(rawArgs.clientId);
|
|
2110
|
+
const oauthCustom = normalizeOptionalToolBoolean(rawArgs.oauthCustom);
|
|
2082
2111
|
const envId = rawArgs.envId;
|
|
2083
2112
|
const confirm = rawArgs.confirm === "yes" ? "yes" : undefined;
|
|
2113
|
+
const resolvedAuthOptions = resolveToolAuthOptions(server, {
|
|
2114
|
+
authMode,
|
|
2115
|
+
oauthEndpoint,
|
|
2116
|
+
clientId,
|
|
2117
|
+
oauthCustom,
|
|
2118
|
+
});
|
|
2119
|
+
const authConfigSummary = (0, auth_js_1.buildAuthConfigSummary)(resolvedAuthOptions);
|
|
2084
2120
|
let deviceAuthInfo;
|
|
2085
2121
|
const onDeviceCode = (info) => {
|
|
2086
2122
|
deviceAuthInfo = info;
|
|
@@ -2137,6 +2173,7 @@ function registerEnvTools(server) {
|
|
|
2137
2173
|
auth_status: authStatus,
|
|
2138
2174
|
env_status: envStatus,
|
|
2139
2175
|
current_env_id: envId || null,
|
|
2176
|
+
auth_config: authConfigSummary,
|
|
2140
2177
|
...buildEnvCandidatePayload(envCandidates),
|
|
2141
2178
|
auth_challenge: authFlowState.status === "PENDING" && authFlowState.authChallenge
|
|
2142
2179
|
? {
|
|
@@ -2205,12 +2242,20 @@ function registerEnvTools(server) {
|
|
|
2205
2242
|
catch {
|
|
2206
2243
|
// 忽略 getLoginState 错误,继续尝试发起登录
|
|
2207
2244
|
}
|
|
2245
|
+
const validationError = (0, auth_js_1.getAuthConfigValidationError)(resolvedAuthOptions);
|
|
2246
|
+
if (validationError) {
|
|
2247
|
+
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
2248
|
+
ok: false,
|
|
2249
|
+
code: "INVALID_ARGS",
|
|
2250
|
+
message: validationError,
|
|
2251
|
+
auth_config: authConfigSummary,
|
|
2252
|
+
next_step: (0, tool_result_js_1.buildAuthNextStep)("start_auth", {
|
|
2253
|
+
suggestedArgs: { action: "start_auth", authMode: "device" },
|
|
2254
|
+
}),
|
|
2255
|
+
});
|
|
2256
|
+
}
|
|
2208
2257
|
// 2. 设备码模式:监听到 device code 即返回 AUTH_PENDING,后续由 toolbox 异步轮询并更新本地 credential
|
|
2209
|
-
const effectiveMode = authMode
|
|
2210
|
-
? authMode
|
|
2211
|
-
: process.env.TCB_AUTH_MODE === "web"
|
|
2212
|
-
? "web"
|
|
2213
|
-
: "device";
|
|
2258
|
+
const effectiveMode = resolvedAuthOptions.authMode;
|
|
2214
2259
|
if (effectiveMode === "device") {
|
|
2215
2260
|
let resolveCode;
|
|
2216
2261
|
let rejectCode;
|
|
@@ -2229,6 +2274,15 @@ function registerEnvTools(server) {
|
|
|
2229
2274
|
auth
|
|
2230
2275
|
.loginByWebAuth({
|
|
2231
2276
|
flow: "device",
|
|
2277
|
+
...(resolvedAuthOptions.clientId
|
|
2278
|
+
? { client_id: resolvedAuthOptions.clientId }
|
|
2279
|
+
: {}),
|
|
2280
|
+
...(resolvedAuthOptions.oauthEndpoint
|
|
2281
|
+
? { getOAuthEndpoint: () => resolvedAuthOptions.oauthEndpoint }
|
|
2282
|
+
: {}),
|
|
2283
|
+
...(resolvedAuthOptions.oauthCustom
|
|
2284
|
+
? { custom: true }
|
|
2285
|
+
: {}),
|
|
2232
2286
|
onDeviceCode: deviceOnCode,
|
|
2233
2287
|
})
|
|
2234
2288
|
.then(() => {
|
|
@@ -2287,6 +2341,9 @@ function registerEnvTools(server) {
|
|
|
2287
2341
|
const loginState = await (0, auth_js_1.ensureLogin)({
|
|
2288
2342
|
region,
|
|
2289
2343
|
authMode: effectiveMode,
|
|
2344
|
+
clientId: resolvedAuthOptions.clientId,
|
|
2345
|
+
oauthEndpoint: resolvedAuthOptions.oauthEndpoint,
|
|
2346
|
+
oauthCustom: resolvedAuthOptions.oauthCustom,
|
|
2290
2347
|
});
|
|
2291
2348
|
if (!loginState) {
|
|
2292
2349
|
return (0, tool_result_js_1.buildJsonToolResult)({
|
|
@@ -24932,6 +24989,7 @@ async function _promptAndSetEnvironmentId(autoSelectSingle, options) {
|
|
|
24932
24989
|
region,
|
|
24933
24990
|
authMode: options?.authMode,
|
|
24934
24991
|
clientId: options?.clientId,
|
|
24992
|
+
serverAuthOptions: server?.authOptions,
|
|
24935
24993
|
onDeviceCode: options?.onDeviceCode,
|
|
24936
24994
|
});
|
|
24937
24995
|
(0, logger_js_1.debug)("[interactive] Login state:", {
|
|
@@ -84648,7 +84706,7 @@ class AuthSupervisor {
|
|
|
84648
84706
|
*/
|
|
84649
84707
|
loginByWebAuth(options = {}) {
|
|
84650
84708
|
return __awaiter(this, void 0, void 0, function* () {
|
|
84651
|
-
const { getAuthUrl, throwError, noBrowser, callbackTimeout, flow = 'device', client_id, onDeviceCode, getOAuthEndpoint, silent } = options;
|
|
84709
|
+
const { getAuthUrl, throwError, noBrowser, callbackTimeout, flow = 'device', client_id, onDeviceCode, getOAuthEndpoint, silent, custom } = options;
|
|
84652
84710
|
if (this.cacheCredential && this.needCache && !this.isCacheExpire()) {
|
|
84653
84711
|
return this.cacheCredential;
|
|
84654
84712
|
}
|
|
@@ -84666,7 +84724,7 @@ class AuthSupervisor {
|
|
|
84666
84724
|
});
|
|
84667
84725
|
}
|
|
84668
84726
|
else {
|
|
84669
|
-
credential = yield (0, oauth_1.getAuthTokenByDeviceFlow)({ client_id, onDeviceCode, getOAuthEndpoint, getAuthUrl, silent });
|
|
84727
|
+
credential = yield (0, oauth_1.getAuthTokenByDeviceFlow)({ client_id, onDeviceCode, getOAuthEndpoint, getAuthUrl, silent, custom });
|
|
84670
84728
|
}
|
|
84671
84729
|
credential = (0, common_1.resolveCredential)(credential);
|
|
84672
84730
|
try {
|
|
@@ -105786,7 +105844,7 @@ function parseEnabledPlugins(pluginsEnabled, pluginsDisabled) {
|
|
|
105786
105844
|
* await server.connect(transport);
|
|
105787
105845
|
*/
|
|
105788
105846
|
async function createCloudBaseMcpServer(options) {
|
|
105789
|
-
const { name = "cloudbase-mcp", version = "1.0.0", enableTelemetry = true, cloudBaseOptions, cloudMode = false, ide, logger, pluginsEnabled, pluginsDisabled, } = options ?? {};
|
|
105847
|
+
const { name = "cloudbase-mcp", version = "1.0.0", enableTelemetry = true, cloudBaseOptions, authOptions, cloudMode = false, ide, logger, pluginsEnabled, pluginsDisabled, } = options ?? {};
|
|
105790
105848
|
// Enable cloud mode if specified
|
|
105791
105849
|
if (cloudMode) {
|
|
105792
105850
|
(0, cloud_mode_js_1.enableCloudMode)();
|
|
@@ -105824,6 +105882,9 @@ async function createCloudBaseMcpServer(options) {
|
|
|
105824
105882
|
if (cloudBaseOptions) {
|
|
105825
105883
|
server.cloudBaseOptions = cloudBaseOptions;
|
|
105826
105884
|
}
|
|
105885
|
+
if (authOptions) {
|
|
105886
|
+
server.authOptions = authOptions;
|
|
105887
|
+
}
|
|
105827
105888
|
// Store ide in server instance for telemetry
|
|
105828
105889
|
if (ide) {
|
|
105829
105890
|
server.ide = ide;
|
|
@@ -140533,7 +140594,7 @@ class TelemetryReporter {
|
|
|
140533
140594
|
const nodeVersion = process.version; // Node.js版本
|
|
140534
140595
|
const arch = os_1.default.arch(); // 系统架构
|
|
140535
140596
|
// 从构建时注入的版本号获取MCP版本信息
|
|
140536
|
-
const mcpVersion = process.env.npm_package_version || "2.15.2
|
|
140597
|
+
const mcpVersion = process.env.npm_package_version || "2.15.2" || 0;
|
|
140537
140598
|
return {
|
|
140538
140599
|
userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
|
|
140539
140600
|
deviceId: this.deviceId,
|
|
@@ -191943,11 +192004,11 @@ async function registerRagTools(server) {
|
|
|
191943
192004
|
}
|
|
191944
192005
|
server.registerTool?.("searchKnowledgeBase", {
|
|
191945
192006
|
title: "云开发知识库检索",
|
|
191946
|
-
description: `云开发知识库智能检索工具,支持向量查询 (vector)
|
|
192007
|
+
description: `云开发知识库智能检索工具,支持向量查询 (vector)、固定技能文档 (skill) 和 OpenAPI 文档 (openapi) 查询。
|
|
191947
192008
|
|
|
191948
|
-
|
|
192009
|
+
强烈推荐始终优先使用固定技能文档 (skill) 或 OpenAPI 文档 (openapi) 模式进行检索,仅当固定技能文档无法覆盖你的问题时,再使用向量查询 (vector) 模式。
|
|
191949
192010
|
|
|
191950
|
-
|
|
192011
|
+
固定技能文档 (skill) 查询当前支持 ${skills.length} 个固定文档,分别是:
|
|
191951
192012
|
${skills
|
|
191952
192013
|
.map((skill) => `文档名:${path.basename(path.dirname(skill.absolutePath))} 文档介绍:${skill.description}`)
|
|
191953
192014
|
.join("\n")}
|
|
@@ -191957,11 +192018,11 @@ async function registerRagTools(server) {
|
|
|
191957
192018
|
.map((api) => `API名:${api.name} API介绍:${api.description}`)
|
|
191958
192019
|
.join("\n")}`,
|
|
191959
192020
|
inputSchema: {
|
|
191960
|
-
mode: zod_1.z.enum(["vector", "
|
|
191961
|
-
|
|
192021
|
+
mode: zod_1.z.enum(["vector", "skill", "openapi"]),
|
|
192022
|
+
skillName: zod_1.z
|
|
191962
192023
|
.enum(skills.map((skill) => path.basename(path.dirname(skill.absolutePath))))
|
|
191963
192024
|
.optional()
|
|
191964
|
-
.describe("mode=
|
|
192025
|
+
.describe("mode=skill 时指定。技能名称。"),
|
|
191965
192026
|
apiName: zod_1.z
|
|
191966
192027
|
.enum(openapis.map((api) => api.name))
|
|
191967
192028
|
.optional()
|
|
@@ -191995,14 +192056,14 @@ async function registerRagTools(server) {
|
|
|
191995
192056
|
openWorldHint: true,
|
|
191996
192057
|
category: "rag",
|
|
191997
192058
|
},
|
|
191998
|
-
}, async ({ id, content, options: { chunkExpand = [3, 3] } = {}, limit = 5, threshold = 0.5, mode,
|
|
191999
|
-
if (mode === "
|
|
192000
|
-
const absolutePath = skills.find((skill) => skill.absolutePath.includes(
|
|
192059
|
+
}, async ({ id, content, options: { chunkExpand = [3, 3] } = {}, limit = 5, threshold = 0.5, mode, skillName, apiName, }) => {
|
|
192060
|
+
if (mode === "skill") {
|
|
192061
|
+
const absolutePath = skills.find((skill) => skill.absolutePath.includes(skillName)).absolutePath;
|
|
192001
192062
|
return {
|
|
192002
192063
|
content: [
|
|
192003
192064
|
{
|
|
192004
192065
|
type: "text",
|
|
192005
|
-
text: `The doc's absolute path is: ${absolutePath}. ${(await fs.readFile(absolutePath)).toString()}`,
|
|
192066
|
+
text: `The skill doc's absolute path is: ${absolutePath}. ${(await fs.readFile(absolutePath)).toString()}`,
|
|
192006
192067
|
},
|
|
192007
192068
|
],
|
|
192008
192069
|
};
|
|
@@ -207244,7 +207305,7 @@ ${envIdSection}
|
|
|
207244
207305
|
## 环境信息
|
|
207245
207306
|
- 操作系统: ${os_1.default.type()} ${os_1.default.release()}
|
|
207246
207307
|
- Node.js版本: ${process.version}
|
|
207247
|
-
- MCP 版本:${process.env.npm_package_version || "2.15.2
|
|
207308
|
+
- MCP 版本:${process.env.npm_package_version || "2.15.2" || 0}
|
|
207248
207309
|
- 系统架构: ${os_1.default.arch()}
|
|
207249
207310
|
- 时间: ${new Date().toISOString()}
|
|
207250
207311
|
- 请求ID: ${requestId}
|
|
@@ -215670,7 +215731,7 @@ deleteCollection: 删除集合`),
|
|
|
215670
215731
|
// writeNoSqlDatabaseContent
|
|
215671
215732
|
server.registerTool?.("writeNoSqlDatabaseContent", {
|
|
215672
215733
|
title: "修改 NoSQL 数据库数据记录",
|
|
215673
|
-
description: "修改 NoSQL
|
|
215734
|
+
description: "修改 NoSQL 数据库数据记录。可按 MongoDB updateOne/updateMany 的心智模型理解:部分更新必须使用 $set/$inc/$push 等更新操作符;如果直接传 { field: value } 这类普通对象,底层会把它当作替换内容,存在覆盖整条文档的风险。",
|
|
215674
215735
|
inputSchema: {
|
|
215675
215736
|
action: zod_1.z
|
|
215676
215737
|
.enum(["insert", "update", "delete"])
|
|
@@ -215687,7 +215748,7 @@ deleteCollection: 删除集合`),
|
|
|
215687
215748
|
update: zod_1.z
|
|
215688
215749
|
.union([zod_1.z.object({}).passthrough(), zod_1.z.string()])
|
|
215689
215750
|
.optional()
|
|
215690
|
-
.describe("更新内容(对象或字符串,推荐对象)(update 操作必填)"),
|
|
215751
|
+
.describe("更新内容(对象或字符串,推荐对象)(update 操作必填)。按 MongoDB 更新语义传入 MgoUpdate:部分更新请使用 $set/$inc/$unset/$push 等操作符,例如 { \"$set\": { \"status\": \"pending\" } };不要直接传 { \"status\": \"pending\" },否则可能替换整条文档。"),
|
|
215691
215752
|
isMulti: zod_1.z
|
|
215692
215753
|
.boolean()
|
|
215693
215754
|
.optional()
|
|
@@ -222103,7 +222164,7 @@ function registerSetupTools(server) {
|
|
|
222103
222164
|
title: "下载项目模板",
|
|
222104
222165
|
description: `自动下载并部署CloudBase项目模板。⚠️ **MANDATORY FOR NEW PROJECTS** ⚠️
|
|
222105
222166
|
|
|
222106
|
-
**CRITICAL**: This tool MUST be called FIRST when starting a new project.\n\n支持的模板:\n- react: React + CloudBase 全栈应用模板\n- vue: Vue + CloudBase 全栈应用模板\n- miniprogram: 微信小程序 + 云开发模板 \n- uniapp: UniApp + CloudBase 跨端应用模板\n- rules: 只包含AI编辑器配置文件(包含Cursor、WindSurf、CodeBuddy等所有主流编辑器配置),适合在已有项目中补充AI编辑器配置\n\n支持的IDE类型:\n- all: 下载所有IDE配置\n- cursor: Cursor AI编辑器\n- 其他IDE类型见下方列表\n\n注意:如果未传入 ide 参数且无法从环境变量检测到 IDE,将提示错误并要求传入 ide 参数\n- windsurf: WindSurf AI编辑器\n- codebuddy: CodeBuddy AI编辑器\n- claude-code: Claude Code AI编辑器\n- cline: Cline AI编辑器\n- gemini-cli: Gemini CLI\n- opencode: OpenCode AI编辑器\n- qwen-code: 通义灵码\n- baidu-comate: 百度Comate\n- openai-codex-cli: OpenAI Codex CLI\n- augment-code: Augment Code\n- github-copilot: GitHub Copilot\n- roocode: RooCode AI编辑器\n- tongyi-lingma: 通义灵码\n- trae: Trae AI编辑器\n- qoder: Qoder AI编辑器\n- antigravity: Google Antigravity AI编辑器\n- vscode: Visual Studio Code\n- kiro: Kiro AI编辑器\n- aider: Aider AI编辑器\n\n特别说明:\n- rules 模板会自动包含当前 mcp 版本号信息(版本号:${ true ? "2.15.2
|
|
222167
|
+
**CRITICAL**: This tool MUST be called FIRST when starting a new project.\n\n支持的模板:\n- react: React + CloudBase 全栈应用模板\n- vue: Vue + CloudBase 全栈应用模板\n- miniprogram: 微信小程序 + 云开发模板 \n- uniapp: UniApp + CloudBase 跨端应用模板\n- rules: 只包含AI编辑器配置文件(包含Cursor、WindSurf、CodeBuddy等所有主流编辑器配置),适合在已有项目中补充AI编辑器配置\n\n支持的IDE类型:\n- all: 下载所有IDE配置\n- cursor: Cursor AI编辑器\n- 其他IDE类型见下方列表\n\n注意:如果未传入 ide 参数且无法从环境变量检测到 IDE,将提示错误并要求传入 ide 参数\n- windsurf: WindSurf AI编辑器\n- codebuddy: CodeBuddy AI编辑器\n- claude-code: Claude Code AI编辑器\n- cline: Cline AI编辑器\n- gemini-cli: Gemini CLI\n- opencode: OpenCode AI编辑器\n- qwen-code: 通义灵码\n- baidu-comate: 百度Comate\n- openai-codex-cli: OpenAI Codex CLI\n- augment-code: Augment Code\n- github-copilot: GitHub Copilot\n- roocode: RooCode AI编辑器\n- tongyi-lingma: 通义灵码\n- trae: Trae AI编辑器\n- qoder: Qoder AI编辑器\n- antigravity: Google Antigravity AI编辑器\n- vscode: Visual Studio Code\n- kiro: Kiro AI编辑器\n- aider: Aider AI编辑器\n\n特别说明:\n- rules 模板会自动包含当前 mcp 版本号信息(版本号:${ true ? "2.15.2" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
|
|
222107
222168
|
inputSchema: {
|
|
222108
222169
|
template: zod_1.z
|
|
222109
222170
|
.enum(["react", "vue", "miniprogram", "uniapp", "rules"])
|
|
@@ -223397,6 +223458,9 @@ module.exports.sync = path => {
|
|
|
223397
223458
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
223398
223459
|
exports.getAuthProgressStateSync = getAuthProgressStateSync;
|
|
223399
223460
|
exports.getAuthProgressState = getAuthProgressState;
|
|
223461
|
+
exports.resolveAuthOptions = resolveAuthOptions;
|
|
223462
|
+
exports.getAuthConfigValidationError = getAuthConfigValidationError;
|
|
223463
|
+
exports.buildAuthConfigSummary = buildAuthConfigSummary;
|
|
223400
223464
|
exports.setPendingAuthProgressState = setPendingAuthProgressState;
|
|
223401
223465
|
exports.resolveAuthProgressState = resolveAuthProgressState;
|
|
223402
223466
|
exports.rejectAuthProgressState = rejectAuthProgressState;
|
|
@@ -223413,6 +223477,32 @@ const authProgressState = {
|
|
|
223413
223477
|
status: "IDLE",
|
|
223414
223478
|
updatedAt: Date.now(),
|
|
223415
223479
|
};
|
|
223480
|
+
function normalizeOptionalString(value) {
|
|
223481
|
+
if (typeof value !== "string") {
|
|
223482
|
+
return undefined;
|
|
223483
|
+
}
|
|
223484
|
+
const trimmed = value.trim();
|
|
223485
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
223486
|
+
}
|
|
223487
|
+
function normalizeAuthMode(value) {
|
|
223488
|
+
return value === "web" || value === "device" ? value : undefined;
|
|
223489
|
+
}
|
|
223490
|
+
function normalizeOptionalBoolean(value) {
|
|
223491
|
+
if (typeof value === "boolean") {
|
|
223492
|
+
return value;
|
|
223493
|
+
}
|
|
223494
|
+
if (typeof value !== "string") {
|
|
223495
|
+
return undefined;
|
|
223496
|
+
}
|
|
223497
|
+
const normalized = value.trim().toLowerCase();
|
|
223498
|
+
if (normalized === "true") {
|
|
223499
|
+
return true;
|
|
223500
|
+
}
|
|
223501
|
+
if (normalized === "false") {
|
|
223502
|
+
return false;
|
|
223503
|
+
}
|
|
223504
|
+
return undefined;
|
|
223505
|
+
}
|
|
223416
223506
|
function updateAuthProgressState(partial) {
|
|
223417
223507
|
Object.assign(authProgressState, partial, {
|
|
223418
223508
|
updatedAt: Date.now(),
|
|
@@ -223470,6 +223560,68 @@ async function getAuthProgressState() {
|
|
|
223470
223560
|
}
|
|
223471
223561
|
return getAuthProgressStateSync();
|
|
223472
223562
|
}
|
|
223563
|
+
function resolveAuthOptions(options) {
|
|
223564
|
+
const envAuthMode = options?.ignoreEnvVars
|
|
223565
|
+
? undefined
|
|
223566
|
+
: normalizeAuthMode(process.env.TCB_AUTH_MODE);
|
|
223567
|
+
const envClientId = options?.ignoreEnvVars
|
|
223568
|
+
? undefined
|
|
223569
|
+
: normalizeOptionalString(process.env.TCB_AUTH_CLIENT_ID);
|
|
223570
|
+
const envOAuthEndpoint = options?.ignoreEnvVars
|
|
223571
|
+
? undefined
|
|
223572
|
+
: normalizeOptionalString(process.env.TCB_AUTH_OAUTH_ENDPOINT);
|
|
223573
|
+
const envOAuthCustom = options?.ignoreEnvVars
|
|
223574
|
+
? undefined
|
|
223575
|
+
: normalizeOptionalBoolean(process.env.TCB_AUTH_OAUTH_CUSTOM);
|
|
223576
|
+
const explicitAuthMode = normalizeAuthMode(options?.authMode) ??
|
|
223577
|
+
normalizeAuthMode(options?.serverAuthOptions?.authMode) ??
|
|
223578
|
+
envAuthMode;
|
|
223579
|
+
const clientId = normalizeOptionalString(options?.clientId) ??
|
|
223580
|
+
normalizeOptionalString(options?.serverAuthOptions?.clientId) ??
|
|
223581
|
+
envClientId;
|
|
223582
|
+
const oauthEndpoint = normalizeOptionalString(options?.oauthEndpoint) ??
|
|
223583
|
+
normalizeOptionalString(options?.serverAuthOptions?.oauthEndpoint) ??
|
|
223584
|
+
envOAuthEndpoint;
|
|
223585
|
+
const explicitOAuthCustom = normalizeOptionalBoolean(options?.oauthCustom) ??
|
|
223586
|
+
normalizeOptionalBoolean(options?.serverAuthOptions?.oauthCustom) ??
|
|
223587
|
+
envOAuthCustom;
|
|
223588
|
+
const oauthCustom = explicitOAuthCustom ?? (oauthEndpoint ? true : false);
|
|
223589
|
+
const authMode = explicitAuthMode ?? "device";
|
|
223590
|
+
return {
|
|
223591
|
+
authMode,
|
|
223592
|
+
clientId,
|
|
223593
|
+
oauthEndpoint,
|
|
223594
|
+
oauthCustom,
|
|
223595
|
+
usesToolboxDefaults: explicitAuthMode === undefined &&
|
|
223596
|
+
clientId === undefined &&
|
|
223597
|
+
oauthEndpoint === undefined &&
|
|
223598
|
+
oauthCustom === false,
|
|
223599
|
+
};
|
|
223600
|
+
}
|
|
223601
|
+
function getAuthConfigValidationError(options) {
|
|
223602
|
+
if (options.authMode === "web" &&
|
|
223603
|
+
(options.clientId !== undefined ||
|
|
223604
|
+
options.oauthEndpoint !== undefined ||
|
|
223605
|
+
options.oauthCustom)) {
|
|
223606
|
+
return "自定义 device 登录参数仅支持 authMode=device。";
|
|
223607
|
+
}
|
|
223608
|
+
if (options.oauthCustom && !options.oauthEndpoint) {
|
|
223609
|
+
return "oauthCustom=true 时必须同时提供 oauthEndpoint。";
|
|
223610
|
+
}
|
|
223611
|
+
if (options.oauthEndpoint && !options.oauthCustom) {
|
|
223612
|
+
return "配置自定义 oauthEndpoint 时必须启用 oauthCustom=true。";
|
|
223613
|
+
}
|
|
223614
|
+
return null;
|
|
223615
|
+
}
|
|
223616
|
+
function buildAuthConfigSummary(options) {
|
|
223617
|
+
return {
|
|
223618
|
+
auth_mode: options.authMode,
|
|
223619
|
+
client_id: options.clientId ?? null,
|
|
223620
|
+
oauth_endpoint: options.oauthEndpoint ?? null,
|
|
223621
|
+
oauth_custom: options.oauthCustom,
|
|
223622
|
+
uses_toolbox_defaults: options.usesToolboxDefaults,
|
|
223623
|
+
};
|
|
223624
|
+
}
|
|
223473
223625
|
function setPendingAuthProgressState(challenge, authMode = "device") {
|
|
223474
223626
|
return updateAuthProgressState({
|
|
223475
223627
|
status: "PENDING",
|
|
@@ -223513,9 +223665,19 @@ async function ensureLogin(options) {
|
|
|
223513
223665
|
ignoreEnvVars: options?.ignoreEnvVars,
|
|
223514
223666
|
});
|
|
223515
223667
|
if (!loginState) {
|
|
223516
|
-
const
|
|
223517
|
-
|
|
223518
|
-
|
|
223668
|
+
const resolvedAuthOptions = resolveAuthOptions({
|
|
223669
|
+
authMode: options?.authMode,
|
|
223670
|
+
clientId: options?.clientId,
|
|
223671
|
+
oauthEndpoint: options?.oauthEndpoint,
|
|
223672
|
+
oauthCustom: options?.oauthCustom,
|
|
223673
|
+
ignoreEnvVars: options?.ignoreEnvVars,
|
|
223674
|
+
serverAuthOptions: options?.serverAuthOptions,
|
|
223675
|
+
});
|
|
223676
|
+
const validationError = getAuthConfigValidationError(resolvedAuthOptions);
|
|
223677
|
+
if (validationError) {
|
|
223678
|
+
throw new Error(validationError);
|
|
223679
|
+
}
|
|
223680
|
+
const mode = resolvedAuthOptions.authMode;
|
|
223519
223681
|
const loginOptions = { flow: mode };
|
|
223520
223682
|
if (mode === "web") {
|
|
223521
223683
|
loginOptions.getAuthUrl =
|
|
@@ -223534,8 +223696,14 @@ async function ensureLogin(options) {
|
|
|
223534
223696
|
};
|
|
223535
223697
|
}
|
|
223536
223698
|
else {
|
|
223537
|
-
if (
|
|
223538
|
-
loginOptions.client_id =
|
|
223699
|
+
if (resolvedAuthOptions.clientId) {
|
|
223700
|
+
loginOptions.client_id = resolvedAuthOptions.clientId;
|
|
223701
|
+
}
|
|
223702
|
+
if (resolvedAuthOptions.oauthEndpoint) {
|
|
223703
|
+
loginOptions.getOAuthEndpoint = () => resolvedAuthOptions.oauthEndpoint;
|
|
223704
|
+
}
|
|
223705
|
+
if (resolvedAuthOptions.oauthCustom) {
|
|
223706
|
+
loginOptions.custom = true;
|
|
223539
223707
|
}
|
|
223540
223708
|
if (options?.onDeviceCode) {
|
|
223541
223709
|
loginOptions.onDeviceCode = (info) => {
|
|
@@ -263204,25 +263372,64 @@ function sleep(ms) {
|
|
|
263204
263372
|
setTimeout(resolve, ms);
|
|
263205
263373
|
});
|
|
263206
263374
|
}
|
|
263375
|
+
/**
|
|
263376
|
+
* 将接口原始返回值归一化为裸数据。
|
|
263377
|
+
* - 标准模式:从 { code, result, reqId } 中解包,校验 code
|
|
263378
|
+
* - custom 模式:返回值本身即为裸数据,直接透传
|
|
263379
|
+
*/
|
|
263380
|
+
function unwrapDeviceCodeResponse(raw, custom) {
|
|
263381
|
+
if (custom) {
|
|
263382
|
+
if (!raw || !raw.device_code) {
|
|
263383
|
+
throw new error_1.CloudBaseError('Device Flow fetchDeviceCode failed (custom mode): 返回数据异常');
|
|
263384
|
+
}
|
|
263385
|
+
return { data: raw };
|
|
263386
|
+
}
|
|
263387
|
+
const resp = raw;
|
|
263388
|
+
if (resp.code !== SUCCESS_CODE) {
|
|
263389
|
+
throw new error_1.CloudBaseError('Device Flow fetchDeviceCode failed', {
|
|
263390
|
+
code: resp.code,
|
|
263391
|
+
requestId: resp.reqId,
|
|
263392
|
+
});
|
|
263393
|
+
}
|
|
263394
|
+
return { data: resp.result, reqId: resp.reqId };
|
|
263395
|
+
}
|
|
263396
|
+
function unwrapTokenResponse(raw, custom) {
|
|
263397
|
+
if (custom) {
|
|
263398
|
+
return { data: raw };
|
|
263399
|
+
}
|
|
263400
|
+
const resp = raw;
|
|
263401
|
+
// 标准模式下若外层 code 异常且无 result,直接抛错
|
|
263402
|
+
if (resp.code !== SUCCESS_CODE && !resp.result) {
|
|
263403
|
+
throw new error_1.CloudBaseError(`Device Flow 授权失败,错误码: ${resp.code}`, {
|
|
263404
|
+
code: resp.code,
|
|
263405
|
+
requestId: resp.reqId,
|
|
263406
|
+
});
|
|
263407
|
+
}
|
|
263408
|
+
return { data: resp.result, reqId: resp.reqId };
|
|
263409
|
+
}
|
|
263207
263410
|
function getAuthTokenByDeviceFlow(options = {}) {
|
|
263208
263411
|
return __awaiter(this, void 0, void 0, function* () {
|
|
263209
|
-
const { client_id, onDeviceCode, getOAuthEndpoint, getAuthUrl, silent } = options;
|
|
263412
|
+
const { client_id, onDeviceCode, getOAuthEndpoint, getAuthUrl, silent, custom } = options;
|
|
263210
263413
|
const endpoint = getOAuthEndpoint ? getOAuthEndpoint(OAUTH_ENDPOINT) : OAUTH_ENDPOINT;
|
|
263211
|
-
|
|
263212
|
-
|
|
263213
|
-
|
|
263214
|
-
|
|
263215
|
-
|
|
263216
|
-
|
|
263414
|
+
// ---- 获取 device code ----
|
|
263415
|
+
const deviceCodeRaw = yield fetchDeviceCode({ client_id, endpoint });
|
|
263416
|
+
const { data: deviceCodeData } = unwrapDeviceCodeResponse(deviceCodeRaw, !!custom);
|
|
263417
|
+
const { device_code, user_code, expires_in, interval } = deviceCodeData;
|
|
263418
|
+
// ---- 构造 verification_uri ----
|
|
263419
|
+
let verification_uri;
|
|
263420
|
+
if (custom) {
|
|
263421
|
+
// custom 模式直接使用接口返回的 verification_uri
|
|
263422
|
+
const rawUri = deviceCodeData.verification_uri || '';
|
|
263423
|
+
verification_uri = getAuthUrl ? getAuthUrl(rawUri) : rawUri;
|
|
263424
|
+
}
|
|
263425
|
+
else {
|
|
263426
|
+
// 标准模式由客户端拼接 verification_uri
|
|
263427
|
+
const defaultVerificationUri = `${web_auth_1.CLI_AUTH_BASE_URL}#/cli-auth`;
|
|
263428
|
+
// from=cli 后续考虑改用 client_id,因为 toolbox 作为公共依赖,可能被不同 client 所引用
|
|
263429
|
+
const rawVerificationUri = `${defaultVerificationUri}?user_code=${user_code}&from=cli&flow=device`;
|
|
263430
|
+
verification_uri = getAuthUrl ? getAuthUrl(rawVerificationUri) : rawVerificationUri;
|
|
263217
263431
|
}
|
|
263218
|
-
const { device_code, user_code, expires_in, interval } = deviceCodeResp.result;
|
|
263219
|
-
// 暂时不消费 verification_uri,由客户端控制跳转
|
|
263220
|
-
const defaultVerificationUri = `${web_auth_1.CLI_AUTH_BASE_URL}#/cli-auth`;
|
|
263221
|
-
// from=cli 后续考虑改用 client_id,因为 toolbox 作为公共依赖,可能被不同 client 所引用
|
|
263222
|
-
const rawVerificationUri = `${defaultVerificationUri}?user_code=${user_code}&from=cli&flow=device`;
|
|
263223
|
-
const verification_uri = getAuthUrl ? getAuthUrl(rawVerificationUri) : rawVerificationUri;
|
|
263224
263432
|
if (!silent) {
|
|
263225
|
-
// 打印授权信息,引导用户操作
|
|
263226
263433
|
console.log('\n\n若链接未自动打开,请手动复制至浏览器,或尝试其他登录方式:');
|
|
263227
263434
|
console.log(`\n${verification_uri}`);
|
|
263228
263435
|
console.log(`\n用户码: ${user_code}\n`);
|
|
@@ -263232,21 +263439,25 @@ function getAuthTokenByDeviceFlow(options = {}) {
|
|
|
263232
263439
|
if (onDeviceCode) {
|
|
263233
263440
|
onDeviceCode({ user_code, verification_uri, device_code, expires_in });
|
|
263234
263441
|
}
|
|
263442
|
+
// ---- 轮询 token ----
|
|
263235
263443
|
let pollInterval = interval;
|
|
263236
263444
|
const deadline = Date.now() + expires_in * 1000;
|
|
263237
263445
|
while (Date.now() < deadline) {
|
|
263238
263446
|
yield sleep(pollInterval * 1000);
|
|
263239
|
-
let
|
|
263447
|
+
let tokenData;
|
|
263448
|
+
let reqId;
|
|
263240
263449
|
try {
|
|
263241
|
-
|
|
263450
|
+
const tokenRaw = yield fetchPollToken({ device_code, interval: pollInterval, client_id, endpoint });
|
|
263451
|
+
({ data: tokenData, reqId } = unwrapTokenResponse(tokenRaw, !!custom));
|
|
263242
263452
|
}
|
|
263243
263453
|
catch (e) {
|
|
263454
|
+
if (e instanceof error_1.CloudBaseError)
|
|
263455
|
+
throw e;
|
|
263244
263456
|
throw new error_1.CloudBaseError('Device Flow 轮询请求失败', { original: e });
|
|
263245
263457
|
}
|
|
263246
|
-
|
|
263247
|
-
|
|
263248
|
-
|
|
263249
|
-
const { error, error_description } = result;
|
|
263458
|
+
// 服务端返回业务错误(携带 error 字段)
|
|
263459
|
+
if (tokenData && 'error' in tokenData) {
|
|
263460
|
+
const { error, error_description } = tokenData;
|
|
263250
263461
|
if (error === POLL_ERROR_CODES.AUTHORIZATION_PENDING) {
|
|
263251
263462
|
continue;
|
|
263252
263463
|
}
|
|
@@ -263262,17 +263473,14 @@ function getAuthTokenByDeviceFlow(options = {}) {
|
|
|
263262
263473
|
}
|
|
263263
263474
|
throw new error_1.CloudBaseError(error_description || `Device Flow 授权失败,错误: ${error}`, {
|
|
263264
263475
|
code: error,
|
|
263265
|
-
requestId:
|
|
263476
|
+
requestId: reqId,
|
|
263266
263477
|
});
|
|
263267
263478
|
}
|
|
263268
|
-
//
|
|
263269
|
-
if (
|
|
263270
|
-
return
|
|
263479
|
+
// 成功拿到 Credential
|
|
263480
|
+
if (tokenData) {
|
|
263481
|
+
return tokenData;
|
|
263271
263482
|
}
|
|
263272
|
-
throw new error_1.CloudBaseError(
|
|
263273
|
-
code,
|
|
263274
|
-
requestId: resp.reqId,
|
|
263275
|
-
});
|
|
263483
|
+
throw new error_1.CloudBaseError('Device Flow 授权失败:返回数据异常', { requestId: reqId });
|
|
263276
263484
|
}
|
|
263277
263485
|
throw new error_1.CloudBaseError('授权超时,用户未在有效期内完成授权,请重试');
|
|
263278
263486
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,14 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
|
5
5
|
|
|
6
6
|
export declare const ALL_SUPPORTED_RUNTIMES: ("Nodejs20.19" | "Nodejs18.15" | "Nodejs16.13" | "Nodejs14.18" | "Nodejs12.16" | "Nodejs10.15" | "Nodejs8.9" | "Python3.10" | "Python3.9" | "Python3.7" | "Python3.6" | "Python2.7" | "Php8.0" | "Php7.4" | "Php7.2" | "Java8" | "Java11" | "Golang1")[];
|
|
7
7
|
|
|
8
|
-
declare type AuthFlowMode = "web" | "device";
|
|
8
|
+
export declare type AuthFlowMode = "web" | "device";
|
|
9
|
+
|
|
10
|
+
export declare interface AuthOptions {
|
|
11
|
+
authMode?: AuthFlowMode;
|
|
12
|
+
clientId?: string;
|
|
13
|
+
oauthEndpoint?: string;
|
|
14
|
+
oauthCustom?: boolean;
|
|
15
|
+
}
|
|
9
16
|
|
|
10
17
|
export declare type CloudBaseOptions = NonNullable<ConstructorParameters<typeof CloudBase>[0]>;
|
|
11
18
|
|
|
@@ -41,6 +48,7 @@ export declare function createCloudBaseMcpServer(options?: {
|
|
|
41
48
|
version?: string;
|
|
42
49
|
enableTelemetry?: boolean;
|
|
43
50
|
cloudBaseOptions?: CloudBaseOptions;
|
|
51
|
+
authOptions?: AuthOptions;
|
|
44
52
|
cloudMode?: boolean;
|
|
45
53
|
ide?: string;
|
|
46
54
|
logger?: Logger;
|
|
@@ -93,7 +101,7 @@ export declare interface DeleteFileParams {
|
|
|
93
101
|
cloudPath: string;
|
|
94
102
|
}
|
|
95
103
|
|
|
96
|
-
declare interface DeviceFlowAuthInfo {
|
|
104
|
+
export declare interface DeviceFlowAuthInfo {
|
|
97
105
|
user_code: string;
|
|
98
106
|
verification_uri?: string;
|
|
99
107
|
device_code: string;
|
|
@@ -105,19 +113,13 @@ declare interface DeviceFlowAuthInfo {
|
|
|
105
113
|
*/
|
|
106
114
|
export declare function enableCloudMode(): void;
|
|
107
115
|
|
|
108
|
-
declare
|
|
116
|
+
export declare interface EnsureLoginOptions extends AuthOptions {
|
|
109
117
|
fromCloudBaseLoginPage?: boolean;
|
|
110
118
|
ignoreEnvVars?: boolean;
|
|
111
119
|
region?: string;
|
|
112
|
-
|
|
113
|
-
clientId?: string;
|
|
120
|
+
serverAuthOptions?: AuthOptions;
|
|
114
121
|
onDeviceCode?: (info: DeviceFlowAuthInfo) => void;
|
|
115
|
-
}
|
|
116
|
-
secretId: string;
|
|
117
|
-
secretKey: string;
|
|
118
|
-
token: string | undefined;
|
|
119
|
-
envId: string | undefined;
|
|
120
|
-
} | Credential_2>;
|
|
122
|
+
}
|
|
121
123
|
|
|
122
124
|
declare class EnvironmentManager {
|
|
123
125
|
private cachedEnvId;
|
|
@@ -136,6 +138,7 @@ export declare const error: (message: string, data?: object | Error) => void;
|
|
|
136
138
|
|
|
137
139
|
export declare interface ExtendedMcpServer extends McpServer {
|
|
138
140
|
cloudBaseOptions?: CloudBaseOptions;
|
|
141
|
+
authOptions?: AuthOptions;
|
|
139
142
|
ide?: string;
|
|
140
143
|
logger?: Logger;
|
|
141
144
|
setLogger(logger: Logger): void;
|
|
@@ -172,7 +175,7 @@ export declare interface GetFileInfoParams {
|
|
|
172
175
|
*/
|
|
173
176
|
export declare function getInteractiveServerAsync(): Promise<InteractiveServer>;
|
|
174
177
|
|
|
175
|
-
export declare function getLoginState(options?:
|
|
178
|
+
export declare function getLoginState(options?: EnsureLoginOptions): Promise<{
|
|
176
179
|
secretId: string;
|
|
177
180
|
secretKey: string;
|
|
178
181
|
token: string | undefined;
|