@@ -436,6 +436,80 @@ function wrapFunctionOperationError(
436436 return wrappedError ;
437437}
438438
439+ /**
440+ * Build a helpful error message for function query operations
441+ * when the API returns generic errors like "invalid parameter value"
442+ */
443+ export function buildFunctionQueryErrorMessage (
444+ action : string ,
445+ input : QueryFunctionsInput ,
446+ error : unknown ,
447+ ) : string {
448+ const baseMessage = error instanceof Error ? error . message : String ( error ) ;
449+ const suggestions : string [ ] = [ ] ;
450+
451+ // Check for generic parameter errors from CloudBase API
452+ if ( / i n v a l i d p a r a m e t e r | i n v a l i d p a r a m | 参 数 错 误 | 参 数 无 效 | 4 0 0 / i. test ( baseMessage ) ) {
453+ suggestions . push ( `API 返回参数错误,请检查以下${ action } 必需的参数:` ) ;
454+
455+ // Add specific parameter guidance based on action
456+ switch ( action ) {
457+ case "getFunctionDetail" :
458+ suggestions . push ( "- functionName: 函数名称(必填,例如 'getUserInfo')" ) ;
459+ suggestions . push ( "- codeSecret: 代码保护密钥(可选,如果函数设置了代码保护则需要)" ) ;
460+ break ;
461+ case "listFunctionLogs" :
462+ suggestions . push ( "- functionName: 函数名称(必填)" ) ;
463+ suggestions . push ( "- startTime/endTime: 日志查询时间范围(可选,格式如 '2024-01-01 00:00:00')" ) ;
464+ suggestions . push ( "- offset/limit: 分页参数(可选)" ) ;
465+ break ;
466+ case "listFunctionLayers" :
467+ case "listFunctionTriggers" :
468+ suggestions . push ( "- functionName: 函数名称(必填)" ) ;
469+ break ;
470+ case "getFunctionLogDetail" :
471+ suggestions . push ( "- requestId: 日志请求 ID(必填)" ) ;
472+ suggestions . push ( "- startTime/endTime: 查询时间范围(可选)" ) ;
473+ break ;
474+ case "listLayerVersions" :
475+ suggestions . push ( "- layerName: 层名称(必填)" ) ;
476+ break ;
477+ case "getLayerVersionDetail" :
478+ suggestions . push ( "- layerName: 层名称(必填)" ) ;
479+ suggestions . push ( "- layerVersion: 层版本号(必填,数字类型)" ) ;
480+ break ;
481+ default :
482+ suggestions . push ( "- functionName: 函数名称(函数相关操作必填)" ) ;
483+ }
484+
485+ // Add the actual input received for debugging
486+ const relevantParams = Object . entries ( input )
487+ . filter ( ( [ key , value ] ) => value !== undefined && key !== "action" )
488+ . map ( ( [ key , value ] ) => `${ key } =${ JSON . stringify ( value ) } ` ) ;
489+
490+ if ( relevantParams . length > 0 ) {
491+ suggestions . push ( `\n当前传入的参数:${ relevantParams . join ( ", " ) } ` ) ;
492+ } else {
493+ suggestions . push ( "\n当前没有传入任何参数。" ) ;
494+ }
495+ }
496+
497+ // Check for function not found errors
498+ if ( / f u n c t i o n .* n o t f o u n d | 未 找 到 .* 函 数 | 函 数 不 存 在 / i. test ( baseMessage ) ) {
499+ suggestions . push ( "\n提示:函数可能不存在或名称拼写错误。" ) ;
500+ suggestions . push ( "请先使用 listFunctions 查看环境中所有函数。" ) ;
501+ if ( input . functionName ) {
502+ suggestions . push ( `当前查询的函数名:'${ input . functionName } '` ) ;
503+ }
504+ }
505+
506+ if ( suggestions . length === 0 ) {
507+ return `[${ action } ] ${ baseMessage } ` ;
508+ }
509+
510+ return `[${ action } ] ${ baseMessage } \n\n${ suggestions . join ( "\n" ) } ` ;
511+ }
512+
439513export function registerFunctionTools ( server : ExtendedMcpServer ) {
440514 const cloudBaseOptions = server . cloudBaseOptions ;
441515 const getManager = ( ) => getCloudBaseManager ( { cloudBaseOptions } ) ;
@@ -451,15 +525,28 @@ export function registerFunctionTools(server: ExtendedMcpServer) {
451525 ...( nextActions ?. length ? { nextActions } : { } ) ,
452526 } ) ;
453527
454- const buildErrorEnvelope = (
455- error : unknown ,
456- errorCode ?: string ,
457- ) : Record < string , unknown > => ( {
458- success : false ,
459- data : { } ,
460- message : error instanceof Error ? error . message : String ( error ) ,
461- ...( errorCode ? { errorCode } : { } ) ,
462- } ) ;
528+ const buildErrorEnvelope = (
529+ error : unknown ,
530+ errorCode ?: string ,
531+ ) : Record < string , unknown > => ( {
532+ success : false ,
533+ data : { } ,
534+ message : error instanceof Error ? error . message : String ( error ) ,
535+ ...( errorCode ? { errorCode } : { } ) ,
536+ } ) ;
537+
538+ const withQueryEnvelope = async (
539+ action : string ,
540+ input : QueryFunctionsInput ,
541+ handler : ( ) => Promise < FunctionToolEnvelope > ,
542+ ) => {
543+ try {
544+ return jsonContent ( await handler ( ) ) ;
545+ } catch ( error ) {
546+ const enhancedMessage = buildFunctionQueryErrorMessage ( action , input , error ) ;
547+ return jsonContent ( buildErrorEnvelope ( new Error ( enhancedMessage ) ) ) ;
548+ }
549+ } ;
463550
464551 const withEnvelope = async ( handler : ( ) => Promise < FunctionToolEnvelope > ) => {
465552 try {
@@ -561,43 +648,51 @@ export function registerFunctionTools(server: ExtendedMcpServer) {
561648 }
562649 case "getFunctionDetail" : {
563650 if ( ! input . functionName ) {
564- throw new Error ( "getFunctionDetail 操作时,functionName 参数是必需的" ) ;
651+ throw new Error (
652+ "getFunctionDetail 操作时,functionName 参数是必需的\n\n" +
653+ "正确示例:{ action: 'getFunctionDetail', functionName: 'getUserInfo' }\n" +
654+ "请提供环境中已存在的函数名称,可使用 listFunctions 查看所有函数。"
655+ ) ;
565656 }
566657 const cloudbase = await getManager ( ) ;
567- const result = await cloudbase . functions . getFunctionDetail (
568- input . functionName ,
569- input . codeSecret ,
570- ) ;
571- logCloudBaseResult ( server . logger , result ) ;
572- return buildEnvelope (
573- {
574- action : input . action ,
575- functionName : input . functionName ,
576- functionDetail : result ,
577- layers : normalizeFunctionLayers ( result . Layers ) ,
578- triggers : result . Triggers || [ ] ,
579- requestId : result . RequestId ,
580- raw : result ,
581- } ,
582- `已获取函数 ${ input . functionName } 的详情` ,
583- [
584- {
585- tool : "queryFunctions" ,
586- action : "listFunctionLogs" ,
587- reason : "查看该函数的执行日志" ,
588- } ,
589- {
590- tool : "manageFunctions" ,
591- action : "updateFunctionConfig" ,
592- reason : "更新该函数配置" ,
593- } ,
658+ try {
659+ const result = await cloudbase . functions . getFunctionDetail (
660+ input . functionName ,
661+ input . codeSecret ,
662+ ) ;
663+ logCloudBaseResult ( server . logger , result ) ;
664+ return buildEnvelope (
594665 {
595- tool : "queryGateway" ,
596- action : "getAccess" ,
597- reason : "查看该函数是否已暴露网关访问入口" ,
666+ action : input . action ,
667+ functionName : input . functionName ,
668+ functionDetail : result ,
669+ layers : normalizeFunctionLayers ( result . Layers ) ,
670+ triggers : result . Triggers || [ ] ,
671+ requestId : result . RequestId ,
672+ raw : result ,
598673 } ,
599- ] ,
600- ) ;
674+ `已获取函数 ${ input . functionName } 的详情` ,
675+ [
676+ {
677+ tool : "queryFunctions" ,
678+ action : "listFunctionLogs" ,
679+ reason : "查看该函数的执行日志" ,
680+ } ,
681+ {
682+ tool : "manageFunctions" ,
683+ action : "updateFunctionConfig" ,
684+ reason : "更新该函数配置" ,
685+ } ,
686+ {
687+ tool : "queryGateway" ,
688+ action : "getAccess" ,
689+ reason : "查看该函数是否已暴露网关访问入口" ,
690+ } ,
691+ ] ,
692+ ) ;
693+ } catch ( apiError ) {
694+ throw new Error ( buildFunctionQueryErrorMessage ( input . action , input , apiError ) ) ;
695+ }
601696 }
602697 case "listFunctionLogs" : {
603698 if ( ! input . functionName ) {
@@ -1416,19 +1511,33 @@ export function registerFunctionTools(server: ExtendedMcpServer) {
14161511 inputSchema : {
14171512 action : z
14181513 . enum ( QUERY_FUNCTION_ACTIONS )
1419- . describe ( "只读操作类型,例如 listFunctions、getFunctionDetail、listFunctionLogs" ) ,
1420- functionName : z . string ( ) . optional ( ) . describe ( "函数名称。函数相关 action 必填" ) ,
1421- limit : z . number ( ) . optional ( ) . describe ( "分页数量。列表类 action 可选" ) ,
1422- offset : z . number ( ) . optional ( ) . describe ( "分页偏移。列表类 action 可选" ) ,
1423- codeSecret : z . string ( ) . optional ( ) . describe ( "代码保护密钥" ) ,
1424- startTime : z . string ( ) . optional ( ) . describe ( "日志查询开始时间" ) ,
1425- endTime : z . string ( ) . optional ( ) . describe ( "日志查询结束时间" ) ,
1426- requestId : z . string ( ) . optional ( ) . describe ( "日志 requestId。获取日志详情时必填" ) ,
1427- qualifier : z . string ( ) . optional ( ) . describe ( "函数版本,日志查询时可选" ) ,
1428- runtime : z . string ( ) . optional ( ) . describe ( "层查询的运行时筛选" ) ,
1429- searchKey : z . string ( ) . optional ( ) . describe ( "层名称搜索关键字" ) ,
1430- layerName : z . string ( ) . optional ( ) . describe ( "层名称。层相关 action 必填" ) ,
1431- layerVersion : z . number ( ) . optional ( ) . describe ( "层版本号。获取层版本详情时必填" ) ,
1514+ . describe (
1515+ "只读操作类型。\n" +
1516+ "- listFunctions: 列出所有函数(无需 functionName)\n" +
1517+ "- getFunctionDetail: 获取函数详情(必须提供 functionName)\n" +
1518+ "- listFunctionLogs: 获取函数日志(必须提供 functionName)\n" +
1519+ "- getFunctionLogDetail: 获取单条日志详情(必须提供 requestId)\n" +
1520+ "- listFunctionLayers: 获取函数绑定的层(必须提供 functionName)\n" +
1521+ "- listFunctionTriggers: 获取函数触发器(必须提供 functionName)\n" +
1522+ "- listLayers: 列出所有层(无需额外参数)\n" +
1523+ "- listLayerVersions: 获取层版本列表(必须提供 layerName)\n" +
1524+ "- getLayerVersionDetail: 获取层版本详情(必须提供 layerName 和 layerVersion)\n" +
1525+ "- getFunctionDownloadUrl: 获取函数代码下载链接(必须提供 functionName)"
1526+ ) ,
1527+ functionName : z . string ( ) . optional ( ) . describe (
1528+ "函数名称。getFunctionDetail、listFunctionLogs、listFunctionLayers、listFunctionTriggers、getFunctionDownloadUrl 时必填"
1529+ ) ,
1530+ limit : z . number ( ) . optional ( ) . describe ( "分页数量。listFunctions、listLayers 等列表类 action 可选,默认返回全部" ) ,
1531+ offset : z . number ( ) . optional ( ) . describe ( "分页偏移。listFunctions、listLayers 等列表类 action 可选" ) ,
1532+ codeSecret : z . string ( ) . optional ( ) . describe ( "代码保护密钥。如果函数设置了代码保护,获取详情或下载代码时需要提供" ) ,
1533+ startTime : z . string ( ) . optional ( ) . describe ( "日志查询开始时间。格式如 '2024-01-15 10:00:00',listFunctionLogs/getFunctionLogDetail 可选" ) ,
1534+ endTime : z . string ( ) . optional ( ) . describe ( "日志查询结束时间。格式如 '2024-01-15 11:00:00',与 startTime 间隔不能超过一天" ) ,
1535+ requestId : z . string ( ) . optional ( ) . describe ( "日志请求 ID。getFunctionLogDetail 时必填,可从 listFunctionLogs 返回的日志中获取" ) ,
1536+ qualifier : z . string ( ) . optional ( ) . describe ( "函数版本,如 $LATEST。listFunctionLogs 时可选" ) ,
1537+ runtime : z . string ( ) . optional ( ) . describe ( "层查询的运行时筛选。listLayers 时可选,例如 Nodejs18.15、Python3.9" ) ,
1538+ searchKey : z . string ( ) . optional ( ) . describe ( "层名称搜索关键字。listLayers 时可选,用于模糊搜索层名称" ) ,
1539+ layerName : z . string ( ) . optional ( ) . describe ( "层名称。listLayerVersions、getLayerVersionDetail 时必填" ) ,
1540+ layerVersion : z . number ( ) . optional ( ) . describe ( "层版本号。getLayerVersionDetail 时必填,正整数如 1、2、3" ) ,
14321541 } ,
14331542 annotations : {
14341543 readOnlyHint : true ,
0 commit comments