@cloudbase/cloudbase-mcp 2.35.1 → 2.35.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/README.md +16 -4
- package/dist/cli.cjs +1 -1
- package/dist/index.cjs +218 -10
- package/dist/index.d.ts +19 -0
- package/dist/index.js +218 -10
- package/package.json +1 -1
- package/server.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -204110,7 +204110,7 @@ const types_js_1 = __webpack_require__(89921);
|
|
|
204110
204110
|
exports.env = (0, types_js_1.defineModule)({
|
|
204111
204111
|
// ---- 工具级 meta(description/title 由 server.ts 注册包装层按词典 key 解析)----
|
|
204112
204112
|
authTitle: "CloudBase 开发阶段登录与环境",
|
|
204113
|
-
authDescription: "CloudBase
|
|
204113
|
+
authDescription: "CloudBase(腾讯云开发)开发阶段登录与环境绑定。不确定该从哪开始?先调一次 auth(status)(只读、不用参数),确认登录态和当前环境。登录后即可访问云资源;环境(env)是云函数、数据库、静态托管等资源的隔离单元,绑定环境后其他 MCP 工具才能操作该环境。还没有环境时:国内站新用户可以免费开通一个体验环境,开通后再用 set_env 绑定。支持:查询状态、发起登录、API Key登录、绑定环境(set_env)、退出登录。auth(status) 会返回 credential_scope(account=账号级 / single_env=环境级 API Key)与当前 region;环境级 API Key 只能看到绑定的 envId,查不到其他地域环境是权限边界而非环境不存在。可选 site/region/lang 参数:site=站点(domestic/intl),region=地域,lang=输出语言(zh/en)。",
|
|
204114
204114
|
queryTitle: "CloudBase 环境查询",
|
|
204115
204115
|
queryDescription: "查询 CloudBase 环境相关信息,支持查询环境列表、指定环境详情、安全域名、资源用量与监控指标。(曾用名:envQuery、listEnvs、getEnvInfo、getEnvAuthDomains)当 action=list 时,会按 DescribeEnvs 语义做列表/筛选,标准返回字段为 EnvId、Alias、Status、EnvType、Region、PackageId、PackageName、IsDefault,并支持通过 fields 白名单裁剪这些字段;aliasExact=true 时会按别名精确筛选,避免把前缀相近的环境误当作候选;即使传入 envId,action=list 也只返回摘要,不会返回完整资源明细或 expiry。账号级登录可传 region(ap-shanghai/ap-guangzhou/ap-singapore)查询对应地域,对齐 CLI `tcb env list -r <region>`;环境级凭证(API Key / 托管授权 token)只能看到绑定的 envId,返回 credential_scope=single_env,此时 region 不参与查询会在 ignored_params 中如实说明(AppliedFilters.region 为 null),不要误判为环境不存在或地域过滤失效。如需查询某个已知 EnvId 对应环境的详细信息(包括资源字段和计费信息),必须使用 action=info 并传入目标环境的 envId 参数。action=info 会在可用时补充 BillingInfo(如 ExpireTime、PayMode、IsAutoRenew 等计费字段)。\n\n📊 action=usage 对齐 tcb env usage/info:透传 Manager SDK describeEnvAccountCircle + describeCreditsUsageDetail,返回计费周期与各模块资源点用量(FLEXDB/SCF/COS 等)。envId 必填;type 可选过滤模块;未传 startDate/endDate 时自动使用当前计费周期。\n\n📈 action=metrics 对齐 TCB DescribeCurveData(manager.monitor.describeCurveData,不是云监控 GetMonitorData):查询环境/网关 QPS、云函数调用与错误、数据库 CPU/内存/磁盘、云托管 CPU/QPS 等时序。envId 与 metricName 必填;startTime/endTime 格式 YYYY-MM-DD HH:mm:ss,须成对传入,不传则默认最近 24 小时;period 仅 300/3600/86400。GatewayTraceEnvQPS 未传 resourceID 时自动填环境级 all|:|all|:|all|:|all;云托管 Tke* 指标必须传服务名 resourceID。禁止用 callCloudApi 猜测监控 Action。\n\n🔍 action=info 还会派生三个用于后端选型的字段:\n- `EnvInfo.RuntimeMode`:'postgresql' 或 'nosql',表示新业务建议默认使用的后端(PG 已开通时为 postgresql,否则为 nosql)。\n- `EnvInfo.RuntimeBackends`:`{postgresql, nosql, mysql}` 三个布尔值,描述当前环境实际并存的后端。\n- `EnvInfo.RuntimeModeHints`:每个后端对应的 API/工具/skill 提示。\n\n🌐 action=info 还会在不改写 `StaticStorages[].StaticDomain`(云 API 名义域名)的前提下,投影网关路由 Enable 状态:`StaticStorages[].staticDomainRouteEnabled` 与 `EnvInfo.staticDomainRouteEnabled`(与 queryHosting websiteConfig 同源)。`false` 表示默认静态域名根路由已禁用(访问会返回 GATEWAY_ROUTE_DISABLED),勿把名义域名当成可达 URL。\n\nAI 在写业务/权限/存储代码前必须先看这三项:PG 模式下新业务推荐 `app.rdb()` + RLS(`managePgDatabase action=execute` 跑 `CREATE POLICY`)+ pgstore;已存在的 NoSQL 集合 / 旧 storage / `managePermissions(resourceType=\"noSqlDatabase\")` 在 PG 环境下仍然有效。真正不适用的是 MySQL:当 `RuntimeBackends.mysql === false` 时,`manageMysqlDatabase` / `queryMysqlDatabase` / `relational-database-mcp-cloudbase` skill 都不该使用。",
|
|
204116
204116
|
domainTitle: "CloudBase 环境安全域名管理(浏览器 CORS 白名单)【已废弃】",
|
|
@@ -204373,7 +204373,7 @@ exports.env = (0, types_js_1.defineModule)({
|
|
|
204373
204373
|
}, {
|
|
204374
204374
|
// ---- Tool-level meta ----
|
|
204375
204375
|
authTitle: "CloudBase dev-stage login and environment",
|
|
204376
|
-
authDescription: "CloudBase (Tencent CloudBase) dev-stage login and environment binding. After login you can access cloud resources; an environment (env) is the isolation unit for cloud functions, databases, static hosting, etc. Other MCP tools operate on the bound environment. Supports: status, start_auth (login), login_by_api_key, set_env (bind env), logout. auth(status) returns credential_scope (account / single_env API Key) and current region; a single-env API Key can only see its bound envId — missing other-region envs is a permission boundary, not a missing environment. Optional site/region/lang params: site=domestic|intl, region=e.g. ap-shanghai|ap-singapore, lang=zh|en output language.",
|
|
204376
|
+
authDescription: "CloudBase (Tencent CloudBase) dev-stage login and environment binding. Unsure where to start? Call auth(status) first (read-only, no arguments) to confirm the login state and the current environment. After login you can access cloud resources; an environment (env) is the isolation unit for cloud functions, databases, static hosting, etc. Other MCP tools operate on the bound environment. No environment yet? On the China site a new user can create a trial environment for free, then bind it with set_env. Supports: status, start_auth (login), login_by_api_key, set_env (bind env), logout. auth(status) returns credential_scope (account / single_env API Key) and current region; a single-env API Key can only see its bound envId — missing other-region envs is a permission boundary, not a missing environment. Optional site/region/lang params: site=domestic|intl, region=e.g. ap-shanghai|ap-singapore, lang=zh|en output language.",
|
|
204377
204377
|
queryTitle: "Query CloudBase environments",
|
|
204378
204378
|
queryDescription: "Query CloudBase environment information: environment list, details of a specific environment, security domains, resource usage and monitoring metrics. (Former names: envQuery, listEnvs, getEnvInfo, getEnvAuthDomains) When action=list, listing/filtering follows DescribeEnvs semantics; the standard returned fields are EnvId, Alias, Status, EnvType, Region, PackageId, PackageName, IsDefault, and those fields can be trimmed via the fields whitelist; aliasExact=true filters by exact alias so environments with similar prefixes are not mistaken for candidates; even when envId is passed, action=list still returns only a summary, never full resource details or expiry. Account-level logins may pass region (ap-shanghai/ap-guangzhou/ap-singapore) to query that region, matching CLI `tcb env list -r <region>`; an env-level credential (API Key / hosted authorization token) can only see its bound envId and returns credential_scope=single_env; in that case region plays no part in the query and is reported as such in ignored_params (AppliedFilters.region is null) — do not mistake that for a missing environment or a region filter that failed to apply. To query details of a known EnvId (including resource fields and billing info), you must use action=info and pass the target environment's envId. action=info appends BillingInfo when available (billing fields such as ExpireTime, PayMode, IsAutoRenew).\n\n📊 action=usage matches tcb env usage/info: it passes through Manager SDK describeEnvAccountCircle + describeCreditsUsageDetail and returns the billing cycle and per-module resource-point usage (FLEXDB/SCF/COS, etc.). envId is required; type optionally filters modules; when startDate/endDate are omitted the current billing cycle is used.\n\n📈 action=metrics matches TCB DescribeCurveData (manager.monitor.describeCurveData, not Cloud Monitor GetMonitorData): query time series for env/gateway QPS, cloud function invocations and errors, database CPU/memory/disk, CloudRun CPU/QPS, and more. envId and metricName are required; startTime/endTime use the format YYYY-MM-DD HH:mm:ss and must be passed as a pair, defaulting to the last 24 hours when omitted; period only supports 300/3600/86400. When resourceID is omitted for GatewayTraceEnvQPS, the env-level all|:|all|:|all|:|all is filled in automatically; CloudRun Tke* metrics must pass the service name as resourceID. Do not use callCloudApi to guess monitoring Actions.\n\n🔍 action=info also derives three fields used for backend selection:\n- `EnvInfo.RuntimeMode`: 'postgresql' or 'nosql', the backend recommended by default for new work (postgresql when PG is enabled, otherwise nosql).\n- `EnvInfo.RuntimeBackends`: the three booleans `{postgresql, nosql, mysql}`, describing the backends that actually coexist in the current environment.\n- `EnvInfo.RuntimeModeHints`: the API/tool/skill hints for each backend.\n\n🌐 action=info also projects the gateway route Enable state without rewriting `StaticStorages[].StaticDomain` (the Cloud API nominal domain): `StaticStorages[].staticDomainRouteEnabled` and `EnvInfo.staticDomainRouteEnabled` (same source as queryHosting websiteConfig). `false` means the default static domain root route is disabled (requests return GATEWAY_ROUTE_DISABLED) — do not treat the nominal domain as a reachable URL.\n\nBefore writing business/permission/storage code, AI must check these three items first: in PG mode, new work should prefer `app.rdb()` + RLS (`managePgDatabase action=execute` running `CREATE POLICY`) + pgstore; existing NoSQL collections / legacy storage / `managePermissions(resourceType=\"noSqlDatabase\")` remain valid in a PG environment. What truly does not apply is MySQL: when `RuntimeBackends.mysql === false`, none of `manageMysqlDatabase` / `queryMysqlDatabase` / the `relational-database-mcp-cloudbase` skill should be used.",
|
|
204379
204379
|
domainTitle: "CloudBase environment security domain management (browser CORS allowlist) [DEPRECATED]",
|
|
@@ -206685,9 +206685,10 @@ exports.rag = (0, types_js_1.defineModule)({
|
|
|
206685
206685
|
|
|
206686
206686
|
⚠️ 重要:当 CloudBase skills 处于禁用状态或当前 IDE 不支持 skill 文件读取时,必须使用 searchKnowledgeBase(mode=skill, skillName=...) 来获取 CloudBase 技能文档内容,而不是尝试直接读取 skill 文件。直接读取可能返回 400 错误。示例:
|
|
206687
206687
|
- 需要最小 Web+数据库 Demo 路径时:searchKnowledgeBase(mode=skill, skillName=minimal-web-baas-demo)
|
|
206688
|
-
- 需要 auth-tool 指南时:searchKnowledgeBase(mode=skill, skillName=auth-tool)
|
|
206689
|
-
- 需要 auth-web 指南时:searchKnowledgeBase(mode=skill, skillName=auth-web)
|
|
206688
|
+
- 需要 auth-tool-cloudbase 指南时:searchKnowledgeBase(mode=skill, skillName=auth-tool-cloudbase)
|
|
206689
|
+
- 需要 auth-web-cloudbase 指南时:searchKnowledgeBase(mode=skill, skillName=auth-web-cloudbase)
|
|
206690
206690
|
- 需要 cloudbase-agent 指南时:searchKnowledgeBase(mode=skill, skillName=cloudbase-agent)
|
|
206691
|
+
- 需要 MCP 接入方式(本地 / 远程)、用 mcporter 在命令行调用工具、或站点 / 插件开关时:searchKnowledgeBase(mode=skill, skillName=cloudbase-mcp)
|
|
206691
206692
|
|
|
206692
206693
|
返回内容包含该 skill 的 SKILL.md 全文,以及它在远端聚合仓(CNB raw)中的全部 .md 文件地址清单(SKILL.md 与 references/ 等,可直接 HTTP 抓取)。正文中代码栅栏之外的相对链接也会改写为绝对地址;若该 skill 在远端仓中不存在,则只返回内联内容并明确标注,不返回失效链接。
|
|
206693
206694
|
|
|
@@ -206743,9 +206744,10 @@ exports.rag = (0, types_js_1.defineModule)({
|
|
|
206743
206744
|
|
|
206744
206745
|
⚠️ Important: when CloudBase skills are disabled or the current IDE does not support reading skill files, use searchKnowledgeBase(mode=skill, skillName=...) to get CloudBase skill doc content instead of trying to read skill files directly. Direct reads may return 400 errors. Examples:
|
|
206745
206746
|
- Minimal Web+database demo path: searchKnowledgeBase(mode=skill, skillName=minimal-web-baas-demo)
|
|
206746
|
-
- auth-tool guide: searchKnowledgeBase(mode=skill, skillName=auth-tool)
|
|
206747
|
-
- auth-web guide: searchKnowledgeBase(mode=skill, skillName=auth-web)
|
|
206747
|
+
- auth-tool-cloudbase guide: searchKnowledgeBase(mode=skill, skillName=auth-tool-cloudbase)
|
|
206748
|
+
- auth-web-cloudbase guide: searchKnowledgeBase(mode=skill, skillName=auth-web-cloudbase)
|
|
206748
206749
|
- cloudbase-agent guide: searchKnowledgeBase(mode=skill, skillName=cloudbase-agent)
|
|
206750
|
+
- MCP connection modes (local / remote), calling tools from the shell with mcporter, or the site / plugin switches: searchKnowledgeBase(mode=skill, skillName=cloudbase-mcp)
|
|
206749
206751
|
|
|
206750
206752
|
The response contains the full SKILL.md of the skill plus the list of all its .md file URLs in the remote aggregate repo (CNB raw) — SKILL.md and references/ etc., fetchable over HTTP. Relative links outside code fences are rewritten to absolute URLs; when the skill is absent from the remote repo only the inline content is returned and that is stated explicitly, so no dead links are handed out.
|
|
206751
206753
|
|
|
@@ -207442,6 +207444,84 @@ function createLocalCloudApiRequestFn(endpoint) {
|
|
|
207442
207444
|
}
|
|
207443
207445
|
|
|
207444
207446
|
|
|
207447
|
+
/***/ },
|
|
207448
|
+
|
|
207449
|
+
/***/ 81808
|
|
207450
|
+
(__unused_webpack_module, exports) {
|
|
207451
|
+
|
|
207452
|
+
"use strict";
|
|
207453
|
+
|
|
207454
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
207455
|
+
exports.SERVER_INSTRUCTIONS = exports.SERVER_INSTRUCTIONS_MAX_CHARS = void 0;
|
|
207456
|
+
exports.resolveServerInstructions = resolveServerInstructions;
|
|
207457
|
+
/**
|
|
207458
|
+
* MCP `initialize` 结果里的 `instructions`(服务端自述「怎么用我」)。
|
|
207459
|
+
*
|
|
207460
|
+
* 为什么放这里而不是 i18n 词典:词典是给工具 description / 输出文案用的短句,
|
|
207461
|
+
* 这是一整段免协商的自述文本,跟着 server 走、由实例语言选一份。
|
|
207462
|
+
*
|
|
207463
|
+
* 四条约束(改文案前先读):
|
|
207464
|
+
* 1. **≤ MAX_CHARS**(≈500 tokens)。工具定义本身已经吃掉 3 万 tokens(44 个工具),
|
|
207465
|
+
* 这里再堆就是雪上加霜 —— 所以只写「先做一次调用 + 顺序 + 3 条可照抄问法」,
|
|
207466
|
+
* **不列工具清单**(除 `auth` 与「别猜、先查」要用的检索入口外不点名工具)。
|
|
207467
|
+
* 2. **只写使用者照着做什么**,不写内部实现、不写安全须知(那是 rules 的活)。
|
|
207468
|
+
* 3. 提到的 action 名必须与 `auth` 工具 schema 一致(`status` / `start_auth` /
|
|
207469
|
+
* `login_by_api_key` / `set_env` / `logout`),改 auth 时这里要一起改。
|
|
207470
|
+
* 4. **第一句就给一个「零参数、只读、现在就能做」的动作**。读这段文本的模型如果在
|
|
207471
|
+
* 犹豫该不该动,成本最低的出口就是它 —— 这直接对着「连上了但一次都不调用」那条断点。
|
|
207472
|
+
* 5. **不重复**:同一个动作/同一条建议只说一次(`auth(status)` 只在首段出现,
|
|
207473
|
+
* 下面的顺序里不再复述它查登录态)。
|
|
207474
|
+
*
|
|
207475
|
+
* ⚠️ 客户端是否把 instructions 注入上下文**不由协议保证**,也**看不出来**(它不是
|
|
207476
|
+
* capability)⇒ 同样的话在工具 description(首推 `auth`)里要留兜底,不要把它当唯一引导。
|
|
207477
|
+
*/
|
|
207478
|
+
exports.SERVER_INSTRUCTIONS_MAX_CHARS = 2000;
|
|
207479
|
+
exports.SERVER_INSTRUCTIONS = {
|
|
207480
|
+
zh: [
|
|
207481
|
+
"CloudBase MCP:操作腾讯云开发(CloudBase)环境里的云函数、数据库、静态托管等资源。",
|
|
207482
|
+
"",
|
|
207483
|
+
'第一步先调一次 auth(action="status") —— 只读、不用参数,返回登录态和当前环境;不确定从哪开始就先调它。',
|
|
207484
|
+
"",
|
|
207485
|
+
"接下来按顺序走:",
|
|
207486
|
+
"1. 需要登录时,照 auth(status) 返回的指引完成登录。",
|
|
207487
|
+
'2. auth(action="set_env", envId="环境ID") 绑定环境 —— 没绑定前其他工具都用不了。还没有环境?国内站新用户可以免费开通一个体验环境。',
|
|
207488
|
+
"3. 做一件小事确认链路通,例如「列出这个环境的云函数」。",
|
|
207489
|
+
"",
|
|
207490
|
+
"不要凭记忆猜 API、参数和用法:先读 CloudBase Skill 或调 searchKnowledgeBase 确认;查不到就说查不到。",
|
|
207491
|
+
"",
|
|
207492
|
+
"可以直接照抄的问法:",
|
|
207493
|
+
"- 看下数据库里最新的 10 条记录",
|
|
207494
|
+
"- 把我当前项目部署到静态托管",
|
|
207495
|
+
"- 列出这个环境的云函数和最近的日志",
|
|
207496
|
+
"",
|
|
207497
|
+
"报错时按报错文案里的指引处理,不要反复重试同一个调用。",
|
|
207498
|
+
].join("\n"),
|
|
207499
|
+
en: [
|
|
207500
|
+
"CloudBase MCP: work with resources in a Tencent CloudBase environment — cloud functions, databases, static hosting, and more.",
|
|
207501
|
+
"",
|
|
207502
|
+
'Start with one call: auth(action="status") — read-only, no arguments; it returns the login state and current environment. When unsure where to begin, call it first.',
|
|
207503
|
+
"",
|
|
207504
|
+
"Then follow this order:",
|
|
207505
|
+
"1. If login is required, follow what auth(status) returns.",
|
|
207506
|
+
'2. auth(action="set_env", envId="your-env-id") binds an environment — the other tools are unusable until one is bound. No environment yet? On the China site a new user can create a trial environment for free.',
|
|
207507
|
+
'3. Do one small thing to confirm the path works, e.g. "list the cloud functions in this environment".',
|
|
207508
|
+
"",
|
|
207509
|
+
"Do not guess API names, parameters or usage from memory: read the CloudBase Skill or confirm through searchKnowledgeBase first; if it is not documented, say so.",
|
|
207510
|
+
"",
|
|
207511
|
+
"Prompts you can copy as-is:",
|
|
207512
|
+
"- Show me the 10 most recent records in the database",
|
|
207513
|
+
"- Deploy my current project to static hosting",
|
|
207514
|
+
"- List this environment's cloud functions and their recent logs",
|
|
207515
|
+
"",
|
|
207516
|
+
"When a call fails, follow the guidance in the error message instead of retrying the same call repeatedly.",
|
|
207517
|
+
].join("\n"),
|
|
207518
|
+
};
|
|
207519
|
+
/** 按实例语言取 instructions;未知语言回退 zh(与 i18n 的默认一致) */
|
|
207520
|
+
function resolveServerInstructions(lang) {
|
|
207521
|
+
return exports.SERVER_INSTRUCTIONS[lang] ?? exports.SERVER_INSTRUCTIONS.zh;
|
|
207522
|
+
}
|
|
207523
|
+
|
|
207524
|
+
|
|
207445
207525
|
/***/ },
|
|
207446
207526
|
|
|
207447
207527
|
/***/ 46324
|
|
@@ -207480,6 +207560,7 @@ const msg_push_js_1 = __webpack_require__(87707);
|
|
|
207480
207560
|
const feedback_js_1 = __webpack_require__(6332);
|
|
207481
207561
|
const index_js_1 = __webpack_require__(24908);
|
|
207482
207562
|
const schema_js_1 = __webpack_require__(56273);
|
|
207563
|
+
const server_instructions_js_1 = __webpack_require__(81808);
|
|
207483
207564
|
const cloud_mode_js_1 = __webpack_require__(88694);
|
|
207484
207565
|
const logger_js_1 = __webpack_require__(40781);
|
|
207485
207566
|
const site_map_js_1 = __webpack_require__(34533);
|
|
@@ -207646,6 +207727,9 @@ async function createCloudBaseMcpServer(options) {
|
|
|
207646
207727
|
(0, cloud_mode_js_1.enableCloudMode)();
|
|
207647
207728
|
}
|
|
207648
207729
|
// Create server instance
|
|
207730
|
+
// 实例语言必须在构造前解析:`instructions` 是 initialize 的返回字段,构造时就得定稿,
|
|
207731
|
+
// 不能像工具 description 那样等注册包装层再按 lang 改写。
|
|
207732
|
+
const instanceLang = (0, index_js_1.resolveInstanceLang)(lang);
|
|
207649
207733
|
const server = new mcp_js_1.McpServer({
|
|
207650
207734
|
name,
|
|
207651
207735
|
version,
|
|
@@ -207654,11 +207738,13 @@ async function createCloudBaseMcpServer(options) {
|
|
|
207654
207738
|
tools: {},
|
|
207655
207739
|
...(ide === "CodeBuddy" ? { logging: {} } : {}),
|
|
207656
207740
|
},
|
|
207741
|
+
// 免协商的「怎么用我」自述:不占 tools/list 的上下文,客户端不支持时自然忽略。
|
|
207742
|
+
instructions: (0, server_instructions_js_1.resolveServerInstructions)(instanceLang),
|
|
207657
207743
|
});
|
|
207658
207744
|
// 初始化 toolDefs,用于外部提取工具列表(如微信 IDE)
|
|
207659
207745
|
server.toolDefs = [];
|
|
207660
207746
|
// 实例语言解析(须在工具注册前完成:registerTool 包装层按 lang 解析词典 key 形式的 description)
|
|
207661
|
-
server.lang =
|
|
207747
|
+
server.lang = instanceLang;
|
|
207662
207748
|
// 同步到 i18n 模块级 instanceLang:否则 t() 无 langOverride 时会退化成
|
|
207663
207749
|
// TCB_LANG/project.json/zh,导致 options.lang 只影响工具 description、不影响工具输出文案。
|
|
207664
207750
|
(0, index_js_1.setInstanceLang)(server.lang);
|
|
@@ -235893,10 +235979,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
235893
235979
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
235894
235980
|
};
|
|
235895
235981
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
235896
|
-
exports.reportToolkitLifecycle = exports.reportToolCall = exports.telemetryReporter = void 0;
|
|
235982
|
+
exports.reportToolkitLifecycle = exports.reportElicitationResult = exports.reportToolCall = exports.MCP_UI_EXTENSION = exports.telemetryReporter = void 0;
|
|
235897
235983
|
exports.extractMcpClientInfo = extractMcpClientInfo;
|
|
235898
235984
|
exports.readMcpClientInfoFromServer = readMcpClientInfoFromServer;
|
|
235899
235985
|
exports.normalizeClientName = normalizeClientName;
|
|
235986
|
+
exports.extractClientCapabilities = extractClientCapabilities;
|
|
235987
|
+
exports.readClientCapabilitiesFromServer = readClientCapabilitiesFromServer;
|
|
235900
235988
|
exports.resolveLoginUin = resolveLoginUin;
|
|
235901
235989
|
const crypto_1 = __importDefault(__webpack_require__(55511));
|
|
235902
235990
|
const http_1 = __importDefault(__webpack_require__(81630));
|
|
@@ -235960,7 +236048,7 @@ class TelemetryReporter {
|
|
|
235960
236048
|
const arch = os_1.default.arch(); // 系统架构
|
|
235961
236049
|
// Build-time injected version; guard for vitest / non-webpack runtimes.
|
|
235962
236050
|
const mcpVersion = process.env.npm_package_version ||
|
|
235963
|
-
( true ? "2.35.
|
|
236051
|
+
( true ? "2.35.2" : 0);
|
|
235964
236052
|
return {
|
|
235965
236053
|
userAgent: `${osType} ${osRelease} ${arch} ${nodeVersion} CloudBase-MCP/${mcpVersion}`,
|
|
235966
236054
|
deviceId: this.deviceId,
|
|
@@ -236243,6 +236331,88 @@ function appendMcpClientInfoFields(eventData, clientInfo) {
|
|
|
236243
236331
|
eventData.mcpClientTitle = clientInfo.title;
|
|
236244
236332
|
}
|
|
236245
236333
|
}
|
|
236334
|
+
// ---- MCP 客户端能力(capabilities)----
|
|
236335
|
+
//
|
|
236336
|
+
// 为什么要有:灯塔侧原本只记「客户端是谁」(mcpClientName / ide),**没有任何字段承载
|
|
236337
|
+
// 「它声明了什么能力」** ⇒ 本地 stdio 的支持矩阵完全空白,elicitation / MCP Apps 铺不铺
|
|
236338
|
+
// 只能靠远程日志外推(两条实现未必一致)。远程能从 CLS 事后翻 `initialize` 的
|
|
236339
|
+
// clientInfo,本地是我们自己的进程 —— 声明本来就在手上,不记白不记。
|
|
236340
|
+
/** MCP Apps(SEP-1865)扩展标识:宿主与服务端**双向声明**才谈得上渲染 */
|
|
236341
|
+
exports.MCP_UI_EXTENSION = 'io.modelcontextprotocol/ui';
|
|
236342
|
+
/** 把 `getClientCapabilities()` 的原始值压成可上报的形状 */
|
|
236343
|
+
function extractClientCapabilities(raw) {
|
|
236344
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
236345
|
+
return undefined;
|
|
236346
|
+
}
|
|
236347
|
+
const caps = raw;
|
|
236348
|
+
const elicitation = caps.elicitation && typeof caps.elicitation === 'object' && !Array.isArray(caps.elicitation)
|
|
236349
|
+
? caps.elicitation
|
|
236350
|
+
: undefined;
|
|
236351
|
+
const extensions = caps.extensions && typeof caps.extensions === 'object' && !Array.isArray(caps.extensions)
|
|
236352
|
+
? caps.extensions
|
|
236353
|
+
: undefined;
|
|
236354
|
+
const elicitationForm = Boolean(elicitation?.form);
|
|
236355
|
+
const elicitationUrl = Boolean(elicitation?.url);
|
|
236356
|
+
const ui = Boolean(extensions && exports.MCP_UI_EXTENSION in extensions);
|
|
236357
|
+
const roots = Boolean(caps.roots);
|
|
236358
|
+
const sampling = Boolean(caps.sampling);
|
|
236359
|
+
const present = [];
|
|
236360
|
+
// 声明了 elicitation 但两个模式都没识别出来(例如只写了未知子字段):记一个不带模式的名字,
|
|
236361
|
+
// 不要伪造成 form —— 上报宁可少一个维度,也不能多一个假的。
|
|
236362
|
+
if (elicitation && !elicitationForm && !elicitationUrl) {
|
|
236363
|
+
present.push('elicitation');
|
|
236364
|
+
}
|
|
236365
|
+
if (elicitationForm) {
|
|
236366
|
+
present.push('elicitation:form');
|
|
236367
|
+
}
|
|
236368
|
+
if (elicitationUrl) {
|
|
236369
|
+
present.push('elicitation:url');
|
|
236370
|
+
}
|
|
236371
|
+
if (ui) {
|
|
236372
|
+
present.push('ui');
|
|
236373
|
+
}
|
|
236374
|
+
if (roots) {
|
|
236375
|
+
present.push('roots');
|
|
236376
|
+
}
|
|
236377
|
+
if (sampling) {
|
|
236378
|
+
present.push('sampling');
|
|
236379
|
+
}
|
|
236380
|
+
return {
|
|
236381
|
+
elicitationForm,
|
|
236382
|
+
elicitationUrl,
|
|
236383
|
+
ui,
|
|
236384
|
+
roots,
|
|
236385
|
+
sampling,
|
|
236386
|
+
summary: present.length > 0 ? present.join(',') : 'none',
|
|
236387
|
+
};
|
|
236388
|
+
}
|
|
236389
|
+
/**
|
|
236390
|
+
* 从 McpServer 读客户端能力。**每次工具调用都读**(不是只记首次):
|
|
236391
|
+
* SDK 在 initialize 后缓存,读取是纯内存操作;每次都记的好处是同一会话内
|
|
236392
|
+
* 客户端能力变化(重连换客户端)不会只反映在第一条上。
|
|
236393
|
+
*
|
|
236394
|
+
* ⚠️ 与 `readMcpClientInfoFromServer` **同源同风险**:值挂在 server 实例上,而
|
|
236395
|
+
* hosted/cloud 模式若把 McpServer 实例跨请求复用,读到的可能是**上一次** initialize
|
|
236396
|
+
* 的值(与 BFF 的 `Already connected` 同一片区域 —— 实例生命周期没隔离)。
|
|
236397
|
+
* 协议层没有按请求携带 clientInfo 的通道,这里不可能读得更准;要修得连同
|
|
236398
|
+
* `mcpClientName` 一起在 BFF 侧修实例隔离。发现能力分布明显串味时先从那里查。
|
|
236399
|
+
*/
|
|
236400
|
+
function readClientCapabilitiesFromServer(server) {
|
|
236401
|
+
try {
|
|
236402
|
+
return extractClientCapabilities(server?.server?.getClientCapabilities?.());
|
|
236403
|
+
}
|
|
236404
|
+
catch {
|
|
236405
|
+
return undefined;
|
|
236406
|
+
}
|
|
236407
|
+
}
|
|
236408
|
+
function appendMcpClientCapabilityFields(eventData, capabilities) {
|
|
236409
|
+
if (!capabilities) {
|
|
236410
|
+
return;
|
|
236411
|
+
}
|
|
236412
|
+
eventData.mcpCaps = capabilities.summary;
|
|
236413
|
+
eventData.mcpCapsElicitation = capabilities.elicitationForm ? 'true' : 'false';
|
|
236414
|
+
eventData.mcpCapsUi = capabilities.ui ? 'true' : 'false';
|
|
236415
|
+
}
|
|
236246
236416
|
// ---- 账号级归因(login_uin)----
|
|
236247
236417
|
// 缓存键必须能区分凭证身份:hosted 是单进程多租户(网关按凭证缓存 MCP server 实例,
|
|
236248
236418
|
// 同进程内并存多个租户),无键的进程级缓存会把 A 账号的 uin 上报到 B 账号的事件上。
|
|
@@ -236398,6 +236568,7 @@ const reportToolCall = async (params) => {
|
|
|
236398
236568
|
eventData.client = client;
|
|
236399
236569
|
}
|
|
236400
236570
|
appendMcpClientInfoFields(eventData, params.mcpClientInfo);
|
|
236571
|
+
appendMcpClientCapabilityFields(eventData, params.mcpClientCapabilities);
|
|
236401
236572
|
// Debug: 打印最终上报参数
|
|
236402
236573
|
(0, logger_js_1.debug)('[telemetry] 工具调用上报参数', {
|
|
236403
236574
|
toolName: params.toolName,
|
|
@@ -236411,6 +236582,42 @@ const reportToolCall = async (params) => {
|
|
|
236411
236582
|
exports.telemetryReporter.report('toolkit_tool_call', eventData);
|
|
236412
236583
|
};
|
|
236413
236584
|
exports.reportToolCall = reportToolCall;
|
|
236585
|
+
const reportElicitationResult = async (params) => {
|
|
236586
|
+
const { nodeVersion, osType, osRelease, arch, mcpVersion } = exports.telemetryReporter.getUserAgent();
|
|
236587
|
+
const { envId } = resolveEnvId(params.cloudBaseOptions);
|
|
236588
|
+
const siteRegion = resolveTelemetrySiteRegion(params.cloudBaseOptions);
|
|
236589
|
+
const loginUin = await resolveLoginUin(params.cloudBaseOptions);
|
|
236590
|
+
const eventData = {
|
|
236591
|
+
phase: params.phase,
|
|
236592
|
+
field: params.field,
|
|
236593
|
+
optionCount: String(params.optionCount),
|
|
236594
|
+
toolName: params.toolName,
|
|
236595
|
+
duration: params.durationMs !== undefined ? String(params.durationMs) : undefined,
|
|
236596
|
+
value: params.value,
|
|
236597
|
+
// 与工具调用同一套截断规则,避免长错误撑爆列
|
|
236598
|
+
error: params.error ? params.error.substring(0, 200) : undefined,
|
|
236599
|
+
envId: envId || 'unknown',
|
|
236600
|
+
region: siteRegion.region,
|
|
236601
|
+
site: siteRegion.site,
|
|
236602
|
+
login_uin: loginUin,
|
|
236603
|
+
nodeVersion,
|
|
236604
|
+
osType,
|
|
236605
|
+
osRelease,
|
|
236606
|
+
arch,
|
|
236607
|
+
mcpVersion,
|
|
236608
|
+
};
|
|
236609
|
+
if (params.ide) {
|
|
236610
|
+
eventData.ide = params.ide;
|
|
236611
|
+
}
|
|
236612
|
+
const client = resolveClientName(params.client);
|
|
236613
|
+
if (client) {
|
|
236614
|
+
eventData.client = client;
|
|
236615
|
+
}
|
|
236616
|
+
appendMcpClientInfoFields(eventData, params.mcpClientInfo);
|
|
236617
|
+
appendMcpClientCapabilityFields(eventData, params.mcpClientCapabilities);
|
|
236618
|
+
exports.telemetryReporter.report('toolkit_elicitation', eventData);
|
|
236619
|
+
};
|
|
236620
|
+
exports.reportElicitationResult = reportElicitationResult;
|
|
236414
236621
|
// Toolkit 生命周期上报
|
|
236415
236622
|
const reportToolkitLifecycle = async (params) => {
|
|
236416
236623
|
const { nodeVersion, osType, osRelease, arch, mcpVersion } = exports.telemetryReporter.getUserAgent();
|
|
@@ -236720,7 +236927,7 @@ function createWrappedHandler(name, handler, server) {
|
|
|
236720
236927
|
if (isTestEnvironment) {
|
|
236721
236928
|
throw error instanceof Error ? error : new Error(String(error));
|
|
236722
236929
|
}
|
|
236723
|
-
const mcpVersion = true ? "2.35.
|
|
236930
|
+
const mcpVersion = true ? "2.35.2" : 0;
|
|
236724
236931
|
const requestIdSuffix = requestId ? `\n🆔 RequestId: ${requestId}` : '';
|
|
236725
236932
|
const enhancedErrorMessage = `${errorMessage}${requestIdSuffix}\n\n📦 CloudBase MCP v${mcpVersion}\n${contributionHint(server)}`;
|
|
236726
236933
|
// 创建新的错误对象,保持原有的错误类型但更新消息
|
|
@@ -236760,6 +236967,7 @@ function createWrappedHandler(name, handler, server) {
|
|
|
236760
236967
|
ide: server.ide || process.env.INTEGRATION_IDE, // 传递集成IDE信息
|
|
236761
236968
|
client: server.client || process.env.CLOUDBASE_MCP_CLIENT, // 传递 MCP client 来源标识
|
|
236762
236969
|
mcpClientInfo: (0, telemetry_js_1.readMcpClientInfoFromServer)(server),
|
|
236970
|
+
mcpClientCapabilities: (0, telemetry_js_1.readClientCapabilitiesFromServer)(server),
|
|
236763
236971
|
}).catch(err => {
|
|
236764
236972
|
// 静默处理上报错误,不影响主要功能
|
|
236765
236973
|
(0, logger_js_1.debug)('遥测上报失败', { toolName: name, error: err instanceof Error ? err.message : String(err) });
|
package/dist/index.d.ts
CHANGED
|
@@ -494,6 +494,24 @@ export declare function logout(_options?: {
|
|
|
494
494
|
site?: string;
|
|
495
495
|
}): Promise<void>;
|
|
496
496
|
|
|
497
|
+
/**
|
|
498
|
+
* 归一化后的客户端能力(字段名保持语义,报表侧再映射到列)。
|
|
499
|
+
* `undefined` = 握手未完成,与「握手完成但什么都没声明」必须分开:
|
|
500
|
+
* 后者是客户端事实,前者只是我们还没拿到。
|
|
501
|
+
*/
|
|
502
|
+
declare type McpClientCapabilities = {
|
|
503
|
+
/** 表单模式 elicitation(客户端声明 `elicitation:{}` 或 `elicitation.form`) */
|
|
504
|
+
elicitationForm: boolean;
|
|
505
|
+
/** URL 模式 elicitation(凭据跳转用;本期不做,只记录) */
|
|
506
|
+
elicitationUrl: boolean;
|
|
507
|
+
/** 声明了 MCP Apps 扩展 */
|
|
508
|
+
ui: boolean;
|
|
509
|
+
roots: boolean;
|
|
510
|
+
sampling: boolean;
|
|
511
|
+
/** 报表友好摘要:`none` 或稳定排序的逗号串(elicitation:form / elicitation:url / ui / roots / sampling) */
|
|
512
|
+
summary: string;
|
|
513
|
+
};
|
|
514
|
+
|
|
497
515
|
/** MCP initialize clientInfo fields available after handshake via Server.getClientVersion(). */
|
|
498
516
|
declare type McpClientInfo = {
|
|
499
517
|
name?: string;
|
|
@@ -573,6 +591,7 @@ export declare const reportToolCall: (params: {
|
|
|
573
591
|
ide?: string;
|
|
574
592
|
client?: string;
|
|
575
593
|
mcpClientInfo?: McpClientInfo;
|
|
594
|
+
mcpClientCapabilities?: McpClientCapabilities;
|
|
576
595
|
}) => Promise<void>;
|
|
577
596
|
|
|
578
597
|
export declare const reportToolkitLifecycle: (params: {
|