@cloudbase/cloudbase-mcp 2.15.2-beta.3 → 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/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 && (authMode === "device" || authMode === "web")
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-beta.3" || 0;
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)、固定文档 (doc) 和 OpenAPI 文档 (openapi) 查询。
192007
+ description: `云开发知识库智能检索工具,支持向量查询 (vector)、固定技能文档 (skill) 和 OpenAPI 文档 (openapi) 查询。
191947
192008
 
191948
- 强烈推荐始终优先使用固定文档 (doc) 或 OpenAPI 文档 (openapi) 模式进行检索,仅当固定文档无法覆盖你的问题时,再使用向量查询 (vector) 模式。
192009
+ 强烈推荐始终优先使用固定技能文档 (skill) 或 OpenAPI 文档 (openapi) 模式进行检索,仅当固定技能文档无法覆盖你的问题时,再使用向量查询 (vector) 模式。
191949
192010
 
191950
- 固定文档 (doc) 查询当前支持 ${skills.length} 个固定文档,分别是:
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", "doc", "openapi"]),
191961
- docName: zod_1.z
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=doc 时指定。文档名称。"),
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, docName, apiName, }) => {
191999
- if (mode === "doc") {
192000
- const absolutePath = skills.find((skill) => skill.absolutePath.includes(docName)).absolutePath;
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-beta.3" || 0}
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}
@@ -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-beta.3" : 0}),便于后续维护和版本追踪\n- 下载 rules 模板时,如果项目中已存在 README.md 文件,系统会自动保护该文件不被覆盖(除非设置 overwrite=true)`,
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 envMode = process.env.TCB_AUTH_MODE;
223517
- const normalizedEnvMode = envMode === "web" || envMode === "device" ? envMode : undefined;
223518
- const mode = options?.authMode || normalizedEnvMode || "device";
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 (options?.clientId) {
223538
- loginOptions.client_id = options.clientId;
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
- const deviceCodeResp = yield fetchDeviceCode({ client_id, endpoint });
263212
- if (deviceCodeResp.code !== SUCCESS_CODE) {
263213
- throw new error_1.CloudBaseError('Device Flow fetchDeviceCode failed', {
263214
- code: deviceCodeResp.code,
263215
- requestId: deviceCodeResp.reqId,
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 resp;
263447
+ let tokenData;
263448
+ let reqId;
263240
263449
  try {
263241
- resp = yield fetchPollToken({ device_code, interval: pollInterval, client_id, endpoint });
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
- const { code, result } = resp;
263247
- // 服务端返回业务错误(result 中携带 error 字段)
263248
- if (result && 'error' in result) {
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: resp.reqId,
263476
+ requestId: reqId,
263266
263477
  });
263267
263478
  }
263268
- // 服务端返回成功的 Credential
263269
- if (code === SUCCESS_CODE && result) {
263270
- return result;
263479
+ // 成功拿到 Credential
263480
+ if (tokenData) {
263481
+ return tokenData;
263271
263482
  }
263272
- throw new error_1.CloudBaseError(`Device Flow 授权失败,错误码: ${code}`, {
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 function ensureLogin(options?: {
116
+ export declare interface EnsureLoginOptions extends AuthOptions {
109
117
  fromCloudBaseLoginPage?: boolean;
110
118
  ignoreEnvVars?: boolean;
111
119
  region?: string;
112
- authMode?: AuthFlowMode;
113
- clientId?: string;
120
+ serverAuthOptions?: AuthOptions;
114
121
  onDeviceCode?: (info: DeviceFlowAuthInfo) => void;
115
- }): Promise<{
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?: Parameters<typeof ensureLogin>[0]): Promise<{
178
+ export declare function getLoginState(options?: EnsureLoginOptions): Promise<{
176
179
  secretId: string;
177
180
  secretKey: string;
178
181
  token: string | undefined;