@@ -39,6 +39,7 @@ import {
39
39
ReadResourceResult ,
40
40
ServerRequest ,
41
41
ServerNotification ,
42
+ ToolAnnotations ,
42
43
} from "../types.js" ;
43
44
import { Completable , CompletableDef } from "./completable.js" ;
44
45
import { UriTemplate , Variables } from "../shared/uriTemplate.js" ;
@@ -118,6 +119,7 @@ export class McpServer {
118
119
strictUnions : true ,
119
120
} ) as Tool [ "inputSchema" ] )
120
121
: EMPTY_OBJECT_JSON_SCHEMA ,
122
+ annotations : tool . annotations ,
121
123
} ;
122
124
} ,
123
125
) ,
@@ -605,44 +607,103 @@ export class McpServer {
605
607
tool ( name : string , description : string , cb : ToolCallback ) : RegisteredTool ;
606
608
607
609
/**
608
- * Registers a tool `name` accepting the given arguments, which must be an object containing named properties associated with Zod schemas. When the client calls it, the function will be run with the parsed and validated arguments.
610
+ * Registers a tool taking either a parameter schema for validation or annotations for additional metadata.
611
+ * This unified overload handles both `tool(name, paramsSchema, cb)` and `tool(name, annotations, cb)` cases.
612
+ *
613
+ * Note: We use a union type for the second parameter because TypeScript cannot reliably disambiguate
614
+ * between ToolAnnotations and ZodRawShape during overload resolution, as both are plain object types.
609
615
*/
610
616
tool < Args extends ZodRawShape > (
611
617
name : string ,
612
- paramsSchema : Args ,
618
+ paramsSchemaOrAnnotations : Args | ToolAnnotations ,
613
619
cb : ToolCallback < Args > ,
614
620
) : RegisteredTool ;
615
621
616
622
/**
617
- * Registers a tool `name` (with a description) accepting the given arguments, which must be an object containing named properties associated with Zod schemas. When the client calls it, the function will be run with the parsed and validated arguments.
623
+ * Registers a tool `name` (with a description) taking either parameter schema or annotations.
624
+ * This unified overload handles both `tool(name, description, paramsSchema, cb)` and
625
+ * `tool(name, description, annotations, cb)` cases.
626
+ *
627
+ * Note: We use a union type for the third parameter because TypeScript cannot reliably disambiguate
628
+ * between ToolAnnotations and ZodRawShape during overload resolution, as both are plain object types.
629
+ */
630
+ tool < Args extends ZodRawShape > (
631
+ name : string ,
632
+ description : string ,
633
+ paramsSchemaOrAnnotations : Args | ToolAnnotations ,
634
+ cb : ToolCallback < Args > ,
635
+ ) : RegisteredTool ;
636
+
637
+ /**
638
+ * Registers a tool with both parameter schema and annotations.
639
+ */
640
+ tool < Args extends ZodRawShape > (
641
+ name : string ,
642
+ paramsSchema : Args ,
643
+ annotations : ToolAnnotations ,
644
+ cb : ToolCallback < Args > ,
645
+ ) : RegisteredTool ;
646
+
647
+ /**
648
+ * Registers a tool with description, parameter schema, and annotations.
618
649
*/
619
650
tool < Args extends ZodRawShape > (
620
651
name : string ,
621
652
description : string ,
622
653
paramsSchema : Args ,
654
+ annotations : ToolAnnotations ,
623
655
cb : ToolCallback < Args > ,
624
656
) : RegisteredTool ;
625
657
626
658
tool ( name : string , ...rest : unknown [ ] ) : RegisteredTool {
627
659
if ( this . _registeredTools [ name ] ) {
628
660
throw new Error ( `Tool ${ name } is already registered` ) ;
629
661
}
662
+
663
+ // Helper to check if an object is a Zod schema (ZodRawShape)
664
+ const isZodRawShape = ( obj : unknown ) : obj is ZodRawShape => {
665
+ if ( typeof obj !== "object" || obj === null ) return false ;
666
+ // Check that at least one property is a ZodType instance
667
+ return Object . values ( obj as object ) . some ( v => v instanceof ZodType ) ;
668
+ } ;
630
669
631
670
let description : string | undefined ;
632
671
if ( typeof rest [ 0 ] === "string" ) {
633
672
description = rest . shift ( ) as string ;
634
673
}
635
674
636
675
let paramsSchema : ZodRawShape | undefined ;
676
+ let annotations : ToolAnnotations | undefined ;
677
+
678
+ // Handle the different overload combinations
637
679
if ( rest . length > 1 ) {
638
- paramsSchema = rest . shift ( ) as ZodRawShape ;
680
+ // We have at least two more args before the callback
681
+ const firstArg = rest [ 0 ] ;
682
+
683
+ if ( isZodRawShape ( firstArg ) ) {
684
+ // We have a params schema as the first arg
685
+ paramsSchema = rest . shift ( ) as ZodRawShape ;
686
+
687
+ // Check if the next arg is potentially annotations
688
+ if ( rest . length > 1 && typeof rest [ 0 ] === "object" && rest [ 0 ] !== null && ! ( isZodRawShape ( rest [ 0 ] ) ) ) {
689
+ // Case: tool(name, paramsSchema, annotations, cb)
690
+ // Or: tool(name, description, paramsSchema, annotations, cb)
691
+ annotations = rest . shift ( ) as ToolAnnotations ;
692
+ }
693
+ } else if ( typeof firstArg === "object" && firstArg !== null ) {
694
+ // Not a ZodRawShape, so must be annotations in this position
695
+ // Case: tool(name, annotations, cb)
696
+ // Or: tool(name, description, annotations, cb)
697
+ annotations = rest . shift ( ) as ToolAnnotations ;
698
+ }
639
699
}
640
700
641
701
const cb = rest [ 0 ] as ToolCallback < ZodRawShape | undefined > ;
642
702
const registeredTool : RegisteredTool = {
643
703
description,
644
704
inputSchema :
645
705
paramsSchema === undefined ? undefined : z . object ( paramsSchema ) ,
706
+ annotations,
646
707
callback : cb ,
647
708
enabled : true ,
648
709
disable : ( ) => registeredTool . update ( { enabled : false } ) ,
@@ -656,6 +717,7 @@ export class McpServer {
656
717
if ( typeof updates . description !== "undefined" ) registeredTool . description = updates . description
657
718
if ( typeof updates . paramsSchema !== "undefined" ) registeredTool . inputSchema = z . object ( updates . paramsSchema )
658
719
if ( typeof updates . callback !== "undefined" ) registeredTool . callback = updates . callback
720
+ if ( typeof updates . annotations !== "undefined" ) registeredTool . annotations = updates . annotations
659
721
if ( typeof updates . enabled !== "undefined" ) registeredTool . enabled = updates . enabled
660
722
this . sendToolListChanged ( )
661
723
} ,
@@ -853,11 +915,12 @@ export type ToolCallback<Args extends undefined | ZodRawShape = undefined> =
853
915
export type RegisteredTool = {
854
916
description ?: string ;
855
917
inputSchema ?: AnyZodObject ;
918
+ annotations ?: ToolAnnotations ;
856
919
callback : ToolCallback < undefined | ZodRawShape > ;
857
920
enabled : boolean ;
858
921
enable ( ) : void ;
859
922
disable ( ) : void ;
860
- update < Args extends ZodRawShape > ( updates : { name ?: string | null , description ?: string , paramsSchema ?: Args , callback ?: ToolCallback < Args > , enabled ?: boolean } ) : void
923
+ update < Args extends ZodRawShape > ( updates : { name ?: string | null , description ?: string , paramsSchema ?: Args , callback ?: ToolCallback < Args > , annotations ?: ToolAnnotations , enabled ?: boolean } ) : void
861
924
remove ( ) : void
862
925
} ;
863
926
0 commit comments