@@ -908,6 +908,193 @@ describe("tool()", () => {
908
908
expect ( result . tools [ 1 ] . annotations ) . toEqual ( result . tools [ 0 ] . annotations ) ;
909
909
} ) ;
910
910
911
+ /***
912
+ * Test: Internal Robustness - Tool Registration Parameter Parsing
913
+ * Tests that internal parsing logic correctly handles edge cases even when
914
+ * TypeScript types are bypassed (e.g., via loose tsconfig or type assertions)
915
+ */
916
+ test ( "should correctly parse callback position when undefined is passed in annotations position" , async ( ) => {
917
+ const mcpServer = new McpServer ( {
918
+ name : "test server" ,
919
+ version : "1.0" ,
920
+ } ) ;
921
+ const client = new Client ( {
922
+ name : "test client" ,
923
+ version : "1.0" ,
924
+ } ) ;
925
+
926
+ // Testing internal robustness: even if someone bypasses TypeScript and passes undefined
927
+ // the callback should still be found at the correct position
928
+ ( mcpServer . tool as any ) (
929
+ "test" ,
930
+ "A tool description" ,
931
+ { name : z . string ( ) } ,
932
+ undefined , // Not officially supported, but internal logic should handle it
933
+ async ( { name } : { name : string } ) => ( {
934
+ content : [ { type : "text" , text : `Hello, ${ name } !` } ]
935
+ } )
936
+ ) ;
937
+
938
+ const [ clientTransport , serverTransport ] =
939
+ InMemoryTransport . createLinkedPair ( ) ;
940
+
941
+ await Promise . all ( [
942
+ client . connect ( clientTransport ) ,
943
+ mcpServer . server . connect ( serverTransport ) ,
944
+ ] ) ;
945
+
946
+ const result = await client . request (
947
+ { method : "tools/list" } ,
948
+ ListToolsResultSchema ,
949
+ ) ;
950
+
951
+ expect ( result . tools ) . toHaveLength ( 1 ) ;
952
+ expect ( result . tools [ 0 ] . name ) . toBe ( "test" ) ;
953
+ expect ( result . tools [ 0 ] . description ) . toBe ( "A tool description" ) ;
954
+ expect ( result . tools [ 0 ] . inputSchema ) . toMatchObject ( {
955
+ type : "object" ,
956
+ properties : { name : { type : "string" } }
957
+ } ) ;
958
+ expect ( result . tools [ 0 ] . annotations ) . toBeUndefined ( ) ;
959
+
960
+ // Verify that the callback was correctly identified and works
961
+ const callResult = await client . request (
962
+ {
963
+ method : "tools/call" ,
964
+ params : {
965
+ name : "test" ,
966
+ arguments : { name : "World" }
967
+ }
968
+ } ,
969
+ CallToolResultSchema ,
970
+ ) ;
971
+
972
+ expect ( callResult . content ) . toHaveLength ( 1 ) ;
973
+ expect ( ( callResult . content [ 0 ] as TextContent ) . text ) . toBe ( "Hello, World!" ) ;
974
+ } ) ;
975
+
976
+ /***
977
+ * Test: Internal Robustness - Description Undefined
978
+ */
979
+ test ( "should correctly parse when description is undefined" , async ( ) => {
980
+ const mcpServer = new McpServer ( {
981
+ name : "test server" ,
982
+ version : "1.0" ,
983
+ } ) ;
984
+ const client = new Client ( {
985
+ name : "test client" ,
986
+ version : "1.0" ,
987
+ } ) ;
988
+
989
+ // Testing: tool(name, undefined, schema, callback)
990
+ ( mcpServer . tool as any ) (
991
+ "test" ,
992
+ undefined , // description is undefined
993
+ { name : z . string ( ) } ,
994
+ async ( { name } : { name : string } ) => ( {
995
+ content : [ { type : "text" , text : `Hello, ${ name } !` } ]
996
+ } )
997
+ ) ;
998
+
999
+ const [ clientTransport , serverTransport ] =
1000
+ InMemoryTransport . createLinkedPair ( ) ;
1001
+
1002
+ await Promise . all ( [
1003
+ client . connect ( clientTransport ) ,
1004
+ mcpServer . server . connect ( serverTransport ) ,
1005
+ ] ) ;
1006
+
1007
+ const result = await client . request (
1008
+ { method : "tools/list" } ,
1009
+ ListToolsResultSchema ,
1010
+ ) ;
1011
+
1012
+ expect ( result . tools ) . toHaveLength ( 1 ) ;
1013
+ expect ( result . tools [ 0 ] . name ) . toBe ( "test" ) ;
1014
+ expect ( result . tools [ 0 ] . description ) . toBeUndefined ( ) ;
1015
+ expect ( result . tools [ 0 ] . inputSchema ) . toMatchObject ( {
1016
+ type : "object" ,
1017
+ properties : { name : { type : "string" } }
1018
+ } ) ;
1019
+
1020
+ // Verify callback works
1021
+ const callResult = await client . request (
1022
+ {
1023
+ method : "tools/call" ,
1024
+ params : {
1025
+ name : "test" ,
1026
+ arguments : { name : "World" }
1027
+ }
1028
+ } ,
1029
+ CallToolResultSchema ,
1030
+ ) ;
1031
+
1032
+ expect ( callResult . content ) . toHaveLength ( 1 ) ;
1033
+ expect ( ( callResult . content [ 0 ] as TextContent ) . text ) . toBe ( "Hello, World!" ) ;
1034
+ } ) ;
1035
+
1036
+ /***
1037
+ * Test: Internal Robustness - ParamsSchema Undefined
1038
+ */
1039
+ test ( "should correctly parse when paramsSchema is undefined" , async ( ) => {
1040
+ const mcpServer = new McpServer ( {
1041
+ name : "test server" ,
1042
+ version : "1.0" ,
1043
+ } ) ;
1044
+ const client = new Client ( {
1045
+ name : "test client" ,
1046
+ version : "1.0" ,
1047
+ } ) ;
1048
+
1049
+ // Testing: tool(name, description, undefined, annotations, callback)
1050
+ ( mcpServer . tool as any ) (
1051
+ "test" ,
1052
+ "A tool description" ,
1053
+ undefined , // paramsSchema is undefined
1054
+ { title : "Test Tool" } ,
1055
+ async ( ) => ( {
1056
+ content : [ { type : "text" , text : "No params" } ]
1057
+ } )
1058
+ ) ;
1059
+
1060
+ const [ clientTransport , serverTransport ] =
1061
+ InMemoryTransport . createLinkedPair ( ) ;
1062
+
1063
+ await Promise . all ( [
1064
+ client . connect ( clientTransport ) ,
1065
+ mcpServer . server . connect ( serverTransport ) ,
1066
+ ] ) ;
1067
+
1068
+ const result = await client . request (
1069
+ { method : "tools/list" } ,
1070
+ ListToolsResultSchema ,
1071
+ ) ;
1072
+
1073
+ expect ( result . tools ) . toHaveLength ( 1 ) ;
1074
+ expect ( result . tools [ 0 ] . name ) . toBe ( "test" ) ;
1075
+ expect ( result . tools [ 0 ] . description ) . toBe ( "A tool description" ) ;
1076
+ expect ( result . tools [ 0 ] . annotations ?. title ) . toBe ( "Test Tool" ) ;
1077
+ expect ( result . tools [ 0 ] . inputSchema ) . toMatchObject ( {
1078
+ type : "object" ,
1079
+ properties : { }
1080
+ } ) ;
1081
+
1082
+ // Verify callback works
1083
+ const callResult = await client . request (
1084
+ {
1085
+ method : "tools/call" ,
1086
+ params : {
1087
+ name : "test" ,
1088
+ arguments : { }
1089
+ }
1090
+ } ,
1091
+ CallToolResultSchema ,
1092
+ ) ;
1093
+
1094
+ expect ( callResult . content ) . toHaveLength ( 1 ) ;
1095
+ expect ( ( callResult . content [ 0 ] as TextContent ) . text ) . toBe ( "No params" ) ;
1096
+ } ) ;
1097
+
911
1098
/***
912
1099
* Test: Tool Argument Validation
913
1100
*/
0 commit comments