Skip to content

Commit bb7117c

Browse files
author
CodeBuddy Attribution Bot
committed
fix(attribution): callCloudApi MCP 工具的 schema/prompt 未清晰标注 CreateUser 必填参数(EnvId),且参数命名约定不 (issue_mojd35i1_ptw5mr)
1 parent e2ca73f commit bb7117c

1 file changed

Lines changed: 26 additions & 3 deletions

File tree

mcp/src/tools/capi.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { z } from "zod";
2-
import { getCloudBaseManager, logCloudBaseResult } from "../cloudbase-manager.js";
2+
import { getCloudBaseManager, getEnvId, logCloudBaseResult } from "../cloudbase-manager.js";
33
import { TCB_ACTION_INDEX_MAP } from "../generated/tcb-action-index.js";
44
import { ExtendedMcpServer } from "../server.js";
55

@@ -189,6 +189,11 @@ export function registerCapiTools(server: ExtendedMcpServer) {
189189
**云函数**: \`DescribeFunctions\`、\`CreateFunction\`、\`UpdateFunctionCode\`、\`DeleteFunction\`
190190
**数据库**: \`CreateMySQLInstance\`、\`DescribeMySQLInstances\`、\`DestroyMySQLInstance\`
191191
192+
重要参数约定:
193+
1. **EnvId 自动注入**:tcb 的绝大多数 Action 都要求 \`EnvId\` 作为必填参数。如果调用时 params 中未传 \`EnvId\`,工具会自动从当前环境注入,无需手动填写。
194+
2. **参数必须扁平传递**:params 中的字段必须是 API 定义的顶层参数,不要嵌套在子对象中。例如 CreateUser 的参数应直接放在 params 里:\`{ "Name": "zhangsan", "NickName": "张三", "Type": "internalUser", "UserStatus": "ACTIVE" }\`,而不是 \`{ "User": { ... } }\`。
195+
3. **参数名严格区分大小写**:必须使用 API 官方定义的参数名,例如用户名用 \`Name\`(不是 \`UserName\`),用户类型用 \`Type\`(不是 \`UserType\`),用户状态用 \`UserStatus\`(不是 \`Status\`)。如不确定参数名,请先查官方文档。
196+
192197
销毁环境时,常见做法是至少带上 \`EnvId\` 和 \`BypassCheck: true\`,如果环境已经处于隔离期再按文档补 \`IsForce: true\`。`,
193198
inputSchema: {
194199
service: z
@@ -204,7 +209,7 @@ export function registerCapiTools(server: ExtendedMcpServer) {
204209
.record(z.any())
205210
.optional()
206211
.describe(
207-
"Action 对应的参数对象,键名需与官方 API 定义一致。某些 Action 需要携带 EnvId 等信息;如不确定参数结构,请先查官方文档。tcb 示例:`{ \"service\": \"tcb\", \"action\": \"DestroyEnv\", \"params\": { \"EnvId\": \"env-xxx\", \"BypassCheck\": true } }`,如果环境已经处于隔离期,可再补 `IsForce: true`;更新环境别名则可用 `{ \"service\": \"tcb\", \"action\": \"ModifyEnv\", \"params\": { \"EnvId\": \"env-xxx\", \"Alias\": \"demo\" } }`。若你的场景是通过 HTTP 协议直接集成 auth/functions/cloudrun/storage/mysqldb 等 CloudBase 业务 API,请优先使用 OpenAPI / Swagger 或 searchKnowledgeBase(mode=\"openapi\"),而不是优先使用 callCloudApi。",
212+
"Action 对应的参数对象,键名需与官方 API 定义一致(区分大小写)。参数必须扁平传递,不要嵌套在子对象中。tcb 的绝大多数 Action 都要求 EnvId,如未传则自动从当前环境注入。tcb 示例:`{ \"service\": \"tcb\", \"action\": \"CreateUser\", \"params\": { \"Name\": \"zhangsan\", \"NickName\": \"张三\", \"Type\": \"internalUser\", \"Phone\": \"13800138000\", \"Email\": \"zhangsan@example.com\", \"UserStatus\": \"ACTIVE\" } }`(注意:用户名用 Name 不是 UserName,类型用 Type 不是 UserType,状态用 UserStatus 不是 Status,且不要嵌套在 User 对象中);销毁环境:`{ \"service\": \"tcb\", \"action\": \"DestroyEnv\", \"params\": { \"EnvId\": \"env-xxx\", \"BypassCheck\": true } }`。若你的场景是通过 HTTP 协议直接集成 auth/functions/cloudrun/storage/mysqldb 等 CloudBase 业务 API,请优先使用 OpenAPI / Swagger 或 searchKnowledgeBase(mode=\"openapi\"),而不是优先使用 callCloudApi。",
208213
),
209214
},
210215
annotations: {
@@ -231,6 +236,24 @@ export function registerCapiTools(server: ExtendedMcpServer) {
231236
}
232237

233238
const cloudbase = await getManager();
239+
240+
// Auto-inject EnvId for tcb actions that require it but caller omitted it.
241+
// Most tcb actions require EnvId; models frequently forget to include it,
242+
// causing a wasted round-trip. We resolve the current environment ID from
243+
// the auth context and inject it automatically.
244+
let finalParams = params ?? {};
245+
if (service === 'tcb' && !finalParams.EnvId) {
246+
const tcbEntry = findTcbActionEntry(action);
247+
if (!tcbEntry || tcbEntry.requiredKeys.includes('EnvId')) {
248+
try {
249+
const resolvedEnvId = await getEnvId(cloudBaseOptions);
250+
finalParams = { ...finalParams, EnvId: resolvedEnvId };
251+
} catch {
252+
// If env resolution fails, let the API call proceed and
253+
// produce its own "missing EnvId" error with guidance.
254+
}
255+
}
256+
}
234257
if (['1', 'true'].includes(process.env.CLOUDBASE_EVALUATE_MODE ?? '')) {
235258
if (service === 'lowcode') {
236259
throw new Error(`${service}/${action} Cloud API is not exposed or does not exist. Please use another API.`);
@@ -263,7 +286,7 @@ export function registerCapiTools(server: ExtendedMcpServer) {
263286
try {
264287
result = await cloudbase.commonService(service).call({
265288
Action: action,
266-
Param: params ?? {},
289+
Param: finalParams,
267290
});
268291
} catch (error) {
269292
throw new Error(buildCapiErrorMessage(service, action, error));

0 commit comments

Comments
 (0)