@@ -20,6 +20,159 @@ struct ToolTests {
2020 #expect( tool. inputSchema != nil )
2121 }
2222
23+ @Test ( " Tool Annotations initialization and properties " )
24+ func testToolAnnotationsInitialization( ) throws {
25+ // Empty annotations
26+ let emptyAnnotations = Tool . Annotations ( )
27+ #expect( emptyAnnotations. isEmpty)
28+ #expect( emptyAnnotations. title == nil )
29+ #expect( emptyAnnotations. readOnlyHint == nil )
30+ #expect( emptyAnnotations. destructiveHint == nil )
31+ #expect( emptyAnnotations. idempotentHint == nil )
32+ #expect( emptyAnnotations. openWorldHint == nil )
33+
34+ // Full annotations
35+ let fullAnnotations = Tool . Annotations (
36+ title: " Test Tool " ,
37+ readOnlyHint: true ,
38+ destructiveHint: false ,
39+ idempotentHint: true ,
40+ openWorldHint: false
41+ )
42+
43+ #expect( !fullAnnotations. isEmpty)
44+ #expect( fullAnnotations. title == " Test Tool " )
45+ #expect( fullAnnotations. readOnlyHint == true )
46+ #expect( fullAnnotations. destructiveHint == false )
47+ #expect( fullAnnotations. idempotentHint == true )
48+ #expect( fullAnnotations. openWorldHint == false )
49+
50+ // Partial annotations - should not be empty
51+ let partialAnnotations = Tool . Annotations ( title: " Partial Test " )
52+ #expect( !partialAnnotations. isEmpty)
53+ #expect( partialAnnotations. title == " Partial Test " )
54+
55+ // Initialize with nil literal
56+ let nilAnnotations : Tool . Annotations = nil
57+ #expect( nilAnnotations. isEmpty)
58+ }
59+
60+ @Test ( " Tool Annotations encoding and decoding " )
61+ func testToolAnnotationsEncodingDecoding( ) throws {
62+ let annotations = Tool . Annotations (
63+ title: " Test Tool " ,
64+ readOnlyHint: true ,
65+ destructiveHint: false ,
66+ idempotentHint: true ,
67+ openWorldHint: false
68+ )
69+
70+ #expect( !annotations. isEmpty)
71+
72+ let encoder = JSONEncoder ( )
73+ let decoder = JSONDecoder ( )
74+
75+ let data = try encoder. encode ( annotations)
76+ let decoded = try decoder. decode ( Tool . Annotations. self, from: data)
77+
78+ #expect( decoded. title == annotations. title)
79+ #expect( decoded. readOnlyHint == annotations. readOnlyHint)
80+ #expect( decoded. destructiveHint == annotations. destructiveHint)
81+ #expect( decoded. idempotentHint == annotations. idempotentHint)
82+ #expect( decoded. openWorldHint == annotations. openWorldHint)
83+
84+ // Test that empty annotations are encoded as expected
85+ let emptyAnnotations = Tool . Annotations ( )
86+ let emptyData = try encoder. encode ( emptyAnnotations)
87+ let decodedEmpty = try decoder. decode ( Tool . Annotations. self, from: emptyData)
88+
89+ #expect( decodedEmpty. isEmpty)
90+ }
91+
92+ @Test ( " Tool with annotations encoding and decoding " )
93+ func testToolWithAnnotationsEncodingDecoding( ) throws {
94+ let annotations = Tool . Annotations (
95+ title: " Calculator " ,
96+ destructiveHint: false
97+ )
98+
99+ let tool = Tool (
100+ name: " calculate " ,
101+ description: " Performs calculations " ,
102+ inputSchema: . object( [
103+ " expression " : . string( " Mathematical expression to evaluate " )
104+ ] ) ,
105+ annotations: annotations
106+ )
107+
108+ let encoder = JSONEncoder ( )
109+ let decoder = JSONDecoder ( )
110+
111+ let data = try encoder. encode ( tool)
112+ let decoded = try decoder. decode ( Tool . self, from: data)
113+
114+ #expect( decoded. name == tool. name)
115+ #expect( decoded. description == tool. description)
116+ #expect( decoded. annotations. title == annotations. title)
117+ #expect( decoded. annotations. destructiveHint == annotations. destructiveHint)
118+
119+ // Verify that the annotations field is properly included in the JSON
120+ let jsonString = String ( data: data, encoding: . utf8) !
121+ #expect( jsonString. contains ( " \" annotations \" " ) )
122+ #expect( jsonString. contains ( " \" title \" : \" Calculator \" " ) )
123+ }
124+
125+ @Test ( " Tool with empty annotations " )
126+ func testToolWithEmptyAnnotations( ) throws {
127+ var tool = Tool (
128+ name: " test_tool " ,
129+ description: " Test tool description "
130+ )
131+
132+ do {
133+ #expect( tool. annotations. isEmpty)
134+
135+ let encoder = JSONEncoder ( )
136+ let data = try encoder. encode ( tool)
137+
138+ // Verify that empty annotations are not included in the JSON
139+ let jsonString = String ( data: data, encoding: . utf8) !
140+ #expect( !jsonString. contains ( " \" annotations \" " ) )
141+ }
142+
143+ do {
144+ tool. annotations. title = " Test "
145+
146+ #expect( !tool. annotations. isEmpty)
147+
148+ let encoder = JSONEncoder ( )
149+ let data = try encoder. encode ( tool)
150+
151+ // Verify that empty annotations are not included in the JSON
152+ let jsonString = String ( data: data, encoding: . utf8) !
153+ #expect( jsonString. contains ( " \" annotations \" " ) )
154+ }
155+ }
156+
157+ @Test ( " Tool with nil literal annotations " )
158+ func testToolWithNilLiteralAnnotations( ) throws {
159+ let tool = Tool (
160+ name: " test_tool " ,
161+ description: " Test tool description " ,
162+ inputSchema: nil ,
163+ annotations: nil
164+ )
165+
166+ #expect( tool. annotations. isEmpty)
167+
168+ let encoder = JSONEncoder ( )
169+ let data = try encoder. encode ( tool)
170+
171+ // Verify that nil literal annotations are not included in the JSON
172+ let jsonString = String ( data: data, encoding: . utf8) !
173+ #expect( !jsonString. contains ( " \" annotations \" " ) )
174+ }
175+
23176 @Test ( " Tool encoding and decoding " )
24177 func testToolEncodingDecoding( ) throws {
25178 let tool = Tool (
0 commit comments