1package mcp
2
3import (
4 "encoding/json"
5 "fmt"
6
7 "github.com/spf13/cast"
8)
9
10// ClientRequest types
11var _ ClientRequest = &PingRequest{}
12var _ ClientRequest = &InitializeRequest{}
13var _ ClientRequest = &CompleteRequest{}
14var _ ClientRequest = &SetLevelRequest{}
15var _ ClientRequest = &GetPromptRequest{}
16var _ ClientRequest = &ListPromptsRequest{}
17var _ ClientRequest = &ListResourcesRequest{}
18var _ ClientRequest = &ReadResourceRequest{}
19var _ ClientRequest = &SubscribeRequest{}
20var _ ClientRequest = &UnsubscribeRequest{}
21var _ ClientRequest = &CallToolRequest{}
22var _ ClientRequest = &ListToolsRequest{}
23
24// ClientNotification types
25var _ ClientNotification = &CancelledNotification{}
26var _ ClientNotification = &ProgressNotification{}
27var _ ClientNotification = &InitializedNotification{}
28var _ ClientNotification = &RootsListChangedNotification{}
29
30// ClientResult types
31var _ ClientResult = &EmptyResult{}
32var _ ClientResult = &CreateMessageResult{}
33var _ ClientResult = &ListRootsResult{}
34
35// ServerRequest types
36var _ ServerRequest = &PingRequest{}
37var _ ServerRequest = &CreateMessageRequest{}
38var _ ServerRequest = &ListRootsRequest{}
39
40// ServerNotification types
41var _ ServerNotification = &CancelledNotification{}
42var _ ServerNotification = &ProgressNotification{}
43var _ ServerNotification = &LoggingMessageNotification{}
44var _ ServerNotification = &ResourceUpdatedNotification{}
45var _ ServerNotification = &ResourceListChangedNotification{}
46var _ ServerNotification = &ToolListChangedNotification{}
47var _ ServerNotification = &PromptListChangedNotification{}
48
49// ServerResult types
50var _ ServerResult = &EmptyResult{}
51var _ ServerResult = &InitializeResult{}
52var _ ServerResult = &CompleteResult{}
53var _ ServerResult = &GetPromptResult{}
54var _ ServerResult = &ListPromptsResult{}
55var _ ServerResult = &ListResourcesResult{}
56var _ ServerResult = &ReadResourceResult{}
57var _ ServerResult = &CallToolResult{}
58var _ ServerResult = &ListToolsResult{}
59
60// Helper functions for type assertions
61
62// asType attempts to cast the given interface to the given type
63func asType[T any](content any) (*T, bool) {
64 tc, ok := content.(T)
65 if !ok {
66 return nil, false
67 }
68 return &tc, true
69}
70
71// AsTextContent attempts to cast the given interface to TextContent
72func AsTextContent(content any) (*TextContent, bool) {
73 return asType[TextContent](content)
74}
75
76// AsImageContent attempts to cast the given interface to ImageContent
77func AsImageContent(content any) (*ImageContent, bool) {
78 return asType[ImageContent](content)
79}
80
81// AsAudioContent attempts to cast the given interface to AudioContent
82func AsAudioContent(content any) (*AudioContent, bool) {
83 return asType[AudioContent](content)
84}
85
86// AsEmbeddedResource attempts to cast the given interface to EmbeddedResource
87func AsEmbeddedResource(content any) (*EmbeddedResource, bool) {
88 return asType[EmbeddedResource](content)
89}
90
91// AsTextResourceContents attempts to cast the given interface to TextResourceContents
92func AsTextResourceContents(content any) (*TextResourceContents, bool) {
93 return asType[TextResourceContents](content)
94}
95
96// AsBlobResourceContents attempts to cast the given interface to BlobResourceContents
97func AsBlobResourceContents(content any) (*BlobResourceContents, bool) {
98 return asType[BlobResourceContents](content)
99}
100
101// Helper function for JSON-RPC
102
103// NewJSONRPCResponse creates a new JSONRPCResponse with the given id and result
104func NewJSONRPCResponse(id RequestId, result Result) JSONRPCResponse {
105 return JSONRPCResponse{
106 JSONRPC: JSONRPC_VERSION,
107 ID: id,
108 Result: result,
109 }
110}
111
112// NewJSONRPCError creates a new JSONRPCResponse with the given id, code, and message
113func NewJSONRPCError(
114 id RequestId,
115 code int,
116 message string,
117 data any,
118) JSONRPCError {
119 return JSONRPCError{
120 JSONRPC: JSONRPC_VERSION,
121 ID: id,
122 Error: struct {
123 Code int `json:"code"`
124 Message string `json:"message"`
125 Data any `json:"data,omitempty"`
126 }{
127 Code: code,
128 Message: message,
129 Data: data,
130 },
131 }
132}
133
134// NewProgressNotification
135// Helper function for creating a progress notification
136func NewProgressNotification(
137 token ProgressToken,
138 progress float64,
139 total *float64,
140 message *string,
141) ProgressNotification {
142 notification := ProgressNotification{
143 Notification: Notification{
144 Method: "notifications/progress",
145 },
146 Params: struct {
147 ProgressToken ProgressToken `json:"progressToken"`
148 Progress float64 `json:"progress"`
149 Total float64 `json:"total,omitempty"`
150 Message string `json:"message,omitempty"`
151 }{
152 ProgressToken: token,
153 Progress: progress,
154 },
155 }
156 if total != nil {
157 notification.Params.Total = *total
158 }
159 if message != nil {
160 notification.Params.Message = *message
161 }
162 return notification
163}
164
165// NewLoggingMessageNotification
166// Helper function for creating a logging message notification
167func NewLoggingMessageNotification(
168 level LoggingLevel,
169 logger string,
170 data any,
171) LoggingMessageNotification {
172 return LoggingMessageNotification{
173 Notification: Notification{
174 Method: "notifications/message",
175 },
176 Params: struct {
177 Level LoggingLevel `json:"level"`
178 Logger string `json:"logger,omitempty"`
179 Data any `json:"data"`
180 }{
181 Level: level,
182 Logger: logger,
183 Data: data,
184 },
185 }
186}
187
188// NewPromptMessage
189// Helper function to create a new PromptMessage
190func NewPromptMessage(role Role, content Content) PromptMessage {
191 return PromptMessage{
192 Role: role,
193 Content: content,
194 }
195}
196
197// NewTextContent
198// Helper function to create a new TextContent
199func NewTextContent(text string) TextContent {
200 return TextContent{
201 Type: "text",
202 Text: text,
203 }
204}
205
206// NewImageContent
207// Helper function to create a new ImageContent
208func NewImageContent(data, mimeType string) ImageContent {
209 return ImageContent{
210 Type: "image",
211 Data: data,
212 MIMEType: mimeType,
213 }
214}
215
216// Helper function to create a new AudioContent
217func NewAudioContent(data, mimeType string) AudioContent {
218 return AudioContent{
219 Type: "audio",
220 Data: data,
221 MIMEType: mimeType,
222 }
223}
224
225// Helper function to create a new ResourceLink
226func NewResourceLink(uri, name, description, mimeType string) ResourceLink {
227 return ResourceLink{
228 Type: "resource_link",
229 URI: uri,
230 Name: name,
231 Description: description,
232 MIMEType: mimeType,
233 }
234}
235
236// Helper function to create a new EmbeddedResource
237func NewEmbeddedResource(resource ResourceContents) EmbeddedResource {
238 return EmbeddedResource{
239 Type: "resource",
240 Resource: resource,
241 }
242}
243
244// NewToolResultText creates a new CallToolResult with a text content
245func NewToolResultText(text string) *CallToolResult {
246 return &CallToolResult{
247 Content: []Content{
248 TextContent{
249 Type: "text",
250 Text: text,
251 },
252 },
253 }
254}
255
256// NewToolResultImage creates a new CallToolResult with both text and image content
257func NewToolResultImage(text, imageData, mimeType string) *CallToolResult {
258 return &CallToolResult{
259 Content: []Content{
260 TextContent{
261 Type: "text",
262 Text: text,
263 },
264 ImageContent{
265 Type: "image",
266 Data: imageData,
267 MIMEType: mimeType,
268 },
269 },
270 }
271}
272
273// NewToolResultAudio creates a new CallToolResult with both text and audio content
274func NewToolResultAudio(text, imageData, mimeType string) *CallToolResult {
275 return &CallToolResult{
276 Content: []Content{
277 TextContent{
278 Type: "text",
279 Text: text,
280 },
281 AudioContent{
282 Type: "audio",
283 Data: imageData,
284 MIMEType: mimeType,
285 },
286 },
287 }
288}
289
290// NewToolResultResource creates a new CallToolResult with an embedded resource
291func NewToolResultResource(
292 text string,
293 resource ResourceContents,
294) *CallToolResult {
295 return &CallToolResult{
296 Content: []Content{
297 TextContent{
298 Type: "text",
299 Text: text,
300 },
301 EmbeddedResource{
302 Type: "resource",
303 Resource: resource,
304 },
305 },
306 }
307}
308
309// NewToolResultError creates a new CallToolResult with an error message.
310// Any errors that originate from the tool SHOULD be reported inside the result object.
311func NewToolResultError(text string) *CallToolResult {
312 return &CallToolResult{
313 Content: []Content{
314 TextContent{
315 Type: "text",
316 Text: text,
317 },
318 },
319 IsError: true,
320 }
321}
322
323// NewToolResultErrorFromErr creates a new CallToolResult with an error message.
324// If an error is provided, its details will be appended to the text message.
325// Any errors that originate from the tool SHOULD be reported inside the result object.
326func NewToolResultErrorFromErr(text string, err error) *CallToolResult {
327 if err != nil {
328 text = fmt.Sprintf("%s: %v", text, err)
329 }
330 return &CallToolResult{
331 Content: []Content{
332 TextContent{
333 Type: "text",
334 Text: text,
335 },
336 },
337 IsError: true,
338 }
339}
340
341// NewToolResultErrorf creates a new CallToolResult with an error message.
342// The error message is formatted using the fmt package.
343// Any errors that originate from the tool SHOULD be reported inside the result object.
344func NewToolResultErrorf(format string, a ...any) *CallToolResult {
345 return &CallToolResult{
346 Content: []Content{
347 TextContent{
348 Type: "text",
349 Text: fmt.Sprintf(format, a...),
350 },
351 },
352 IsError: true,
353 }
354}
355
356// NewListResourcesResult creates a new ListResourcesResult
357func NewListResourcesResult(
358 resources []Resource,
359 nextCursor Cursor,
360) *ListResourcesResult {
361 return &ListResourcesResult{
362 PaginatedResult: PaginatedResult{
363 NextCursor: nextCursor,
364 },
365 Resources: resources,
366 }
367}
368
369// NewListResourceTemplatesResult creates a new ListResourceTemplatesResult
370func NewListResourceTemplatesResult(
371 templates []ResourceTemplate,
372 nextCursor Cursor,
373) *ListResourceTemplatesResult {
374 return &ListResourceTemplatesResult{
375 PaginatedResult: PaginatedResult{
376 NextCursor: nextCursor,
377 },
378 ResourceTemplates: templates,
379 }
380}
381
382// NewReadResourceResult creates a new ReadResourceResult with text content
383func NewReadResourceResult(text string) *ReadResourceResult {
384 return &ReadResourceResult{
385 Contents: []ResourceContents{
386 TextResourceContents{
387 Text: text,
388 },
389 },
390 }
391}
392
393// NewListPromptsResult creates a new ListPromptsResult
394func NewListPromptsResult(
395 prompts []Prompt,
396 nextCursor Cursor,
397) *ListPromptsResult {
398 return &ListPromptsResult{
399 PaginatedResult: PaginatedResult{
400 NextCursor: nextCursor,
401 },
402 Prompts: prompts,
403 }
404}
405
406// NewGetPromptResult creates a new GetPromptResult
407func NewGetPromptResult(
408 description string,
409 messages []PromptMessage,
410) *GetPromptResult {
411 return &GetPromptResult{
412 Description: description,
413 Messages: messages,
414 }
415}
416
417// NewListToolsResult creates a new ListToolsResult
418func NewListToolsResult(tools []Tool, nextCursor Cursor) *ListToolsResult {
419 return &ListToolsResult{
420 PaginatedResult: PaginatedResult{
421 NextCursor: nextCursor,
422 },
423 Tools: tools,
424 }
425}
426
427// NewInitializeResult creates a new InitializeResult
428func NewInitializeResult(
429 protocolVersion string,
430 capabilities ServerCapabilities,
431 serverInfo Implementation,
432 instructions string,
433) *InitializeResult {
434 return &InitializeResult{
435 ProtocolVersion: protocolVersion,
436 Capabilities: capabilities,
437 ServerInfo: serverInfo,
438 Instructions: instructions,
439 }
440}
441
442// FormatNumberResult
443// Helper for formatting numbers in tool results
444func FormatNumberResult(value float64) *CallToolResult {
445 return NewToolResultText(fmt.Sprintf("%.2f", value))
446}
447
448func ExtractString(data map[string]any, key string) string {
449 if value, ok := data[key]; ok {
450 if str, ok := value.(string); ok {
451 return str
452 }
453 }
454 return ""
455}
456
457func ExtractMap(data map[string]any, key string) map[string]any {
458 if value, ok := data[key]; ok {
459 if m, ok := value.(map[string]any); ok {
460 return m
461 }
462 }
463 return nil
464}
465
466func ParseContent(contentMap map[string]any) (Content, error) {
467 contentType := ExtractString(contentMap, "type")
468
469 switch contentType {
470 case "text":
471 text := ExtractString(contentMap, "text")
472 return NewTextContent(text), nil
473
474 case "image":
475 data := ExtractString(contentMap, "data")
476 mimeType := ExtractString(contentMap, "mimeType")
477 if data == "" || mimeType == "" {
478 return nil, fmt.Errorf("image data or mimeType is missing")
479 }
480 return NewImageContent(data, mimeType), nil
481
482 case "audio":
483 data := ExtractString(contentMap, "data")
484 mimeType := ExtractString(contentMap, "mimeType")
485 if data == "" || mimeType == "" {
486 return nil, fmt.Errorf("audio data or mimeType is missing")
487 }
488 return NewAudioContent(data, mimeType), nil
489
490 case "resource_link":
491 uri := ExtractString(contentMap, "uri")
492 name := ExtractString(contentMap, "name")
493 description := ExtractString(contentMap, "description")
494 mimeType := ExtractString(contentMap, "mimeType")
495 if uri == "" || name == "" {
496 return nil, fmt.Errorf("resource_link uri or name is missing")
497 }
498 return NewResourceLink(uri, name, description, mimeType), nil
499
500 case "resource":
501 resourceMap := ExtractMap(contentMap, "resource")
502 if resourceMap == nil {
503 return nil, fmt.Errorf("resource is missing")
504 }
505
506 resourceContents, err := ParseResourceContents(resourceMap)
507 if err != nil {
508 return nil, err
509 }
510
511 return NewEmbeddedResource(resourceContents), nil
512 }
513
514 return nil, fmt.Errorf("unsupported content type: %s", contentType)
515}
516
517func ParseGetPromptResult(rawMessage *json.RawMessage) (*GetPromptResult, error) {
518 if rawMessage == nil {
519 return nil, fmt.Errorf("response is nil")
520 }
521
522 var jsonContent map[string]any
523 if err := json.Unmarshal(*rawMessage, &jsonContent); err != nil {
524 return nil, fmt.Errorf("failed to unmarshal response: %w", err)
525 }
526
527 result := GetPromptResult{}
528
529 meta, ok := jsonContent["_meta"]
530 if ok {
531 if metaMap, ok := meta.(map[string]any); ok {
532 result.Meta = metaMap
533 }
534 }
535
536 description, ok := jsonContent["description"]
537 if ok {
538 if descriptionStr, ok := description.(string); ok {
539 result.Description = descriptionStr
540 }
541 }
542
543 messages, ok := jsonContent["messages"]
544 if ok {
545 messagesArr, ok := messages.([]any)
546 if !ok {
547 return nil, fmt.Errorf("messages is not an array")
548 }
549
550 for _, message := range messagesArr {
551 messageMap, ok := message.(map[string]any)
552 if !ok {
553 return nil, fmt.Errorf("message is not an object")
554 }
555
556 // Extract role
557 roleStr := ExtractString(messageMap, "role")
558 if roleStr == "" || (roleStr != string(RoleAssistant) && roleStr != string(RoleUser)) {
559 return nil, fmt.Errorf("unsupported role: %s", roleStr)
560 }
561
562 // Extract content
563 contentMap, ok := messageMap["content"].(map[string]any)
564 if !ok {
565 return nil, fmt.Errorf("content is not an object")
566 }
567
568 // Process content
569 content, err := ParseContent(contentMap)
570 if err != nil {
571 return nil, err
572 }
573
574 // Append processed message
575 result.Messages = append(result.Messages, NewPromptMessage(Role(roleStr), content))
576
577 }
578 }
579
580 return &result, nil
581}
582
583func ParseCallToolResult(rawMessage *json.RawMessage) (*CallToolResult, error) {
584 if rawMessage == nil {
585 return nil, fmt.Errorf("response is nil")
586 }
587
588 var jsonContent map[string]any
589 if err := json.Unmarshal(*rawMessage, &jsonContent); err != nil {
590 return nil, fmt.Errorf("failed to unmarshal response: %w", err)
591 }
592
593 var result CallToolResult
594
595 meta, ok := jsonContent["_meta"]
596 if ok {
597 if metaMap, ok := meta.(map[string]any); ok {
598 result.Meta = metaMap
599 }
600 }
601
602 isError, ok := jsonContent["isError"]
603 if ok {
604 if isErrorBool, ok := isError.(bool); ok {
605 result.IsError = isErrorBool
606 }
607 }
608
609 contents, ok := jsonContent["content"]
610 if !ok {
611 return nil, fmt.Errorf("content is missing")
612 }
613
614 contentArr, ok := contents.([]any)
615 if !ok {
616 return nil, fmt.Errorf("content is not an array")
617 }
618
619 for _, content := range contentArr {
620 // Extract content
621 contentMap, ok := content.(map[string]any)
622 if !ok {
623 return nil, fmt.Errorf("content is not an object")
624 }
625
626 // Process content
627 content, err := ParseContent(contentMap)
628 if err != nil {
629 return nil, err
630 }
631
632 result.Content = append(result.Content, content)
633 }
634
635 return &result, nil
636}
637
638func ParseResourceContents(contentMap map[string]any) (ResourceContents, error) {
639 uri := ExtractString(contentMap, "uri")
640 if uri == "" {
641 return nil, fmt.Errorf("resource uri is missing")
642 }
643
644 mimeType := ExtractString(contentMap, "mimeType")
645
646 if text := ExtractString(contentMap, "text"); text != "" {
647 return TextResourceContents{
648 URI: uri,
649 MIMEType: mimeType,
650 Text: text,
651 }, nil
652 }
653
654 if blob := ExtractString(contentMap, "blob"); blob != "" {
655 return BlobResourceContents{
656 URI: uri,
657 MIMEType: mimeType,
658 Blob: blob,
659 }, nil
660 }
661
662 return nil, fmt.Errorf("unsupported resource type")
663}
664
665func ParseReadResourceResult(rawMessage *json.RawMessage) (*ReadResourceResult, error) {
666 if rawMessage == nil {
667 return nil, fmt.Errorf("response is nil")
668 }
669
670 var jsonContent map[string]any
671 if err := json.Unmarshal(*rawMessage, &jsonContent); err != nil {
672 return nil, fmt.Errorf("failed to unmarshal response: %w", err)
673 }
674
675 var result ReadResourceResult
676
677 meta, ok := jsonContent["_meta"]
678 if ok {
679 if metaMap, ok := meta.(map[string]any); ok {
680 result.Meta = metaMap
681 }
682 }
683
684 contents, ok := jsonContent["contents"]
685 if !ok {
686 return nil, fmt.Errorf("contents is missing")
687 }
688
689 contentArr, ok := contents.([]any)
690 if !ok {
691 return nil, fmt.Errorf("contents is not an array")
692 }
693
694 for _, content := range contentArr {
695 // Extract content
696 contentMap, ok := content.(map[string]any)
697 if !ok {
698 return nil, fmt.Errorf("content is not an object")
699 }
700
701 // Process content
702 content, err := ParseResourceContents(contentMap)
703 if err != nil {
704 return nil, err
705 }
706
707 result.Contents = append(result.Contents, content)
708 }
709
710 return &result, nil
711}
712
713func ParseArgument(request CallToolRequest, key string, defaultVal any) any {
714 args := request.GetArguments()
715 if _, ok := args[key]; !ok {
716 return defaultVal
717 } else {
718 return args[key]
719 }
720}
721
722// ParseBoolean extracts and converts a boolean parameter from a CallToolRequest.
723// If the key is not found in the Arguments map, the defaultValue is returned.
724// The function uses cast.ToBool for conversion which handles various string representations
725// such as "true", "yes", "1", etc.
726func ParseBoolean(request CallToolRequest, key string, defaultValue bool) bool {
727 v := ParseArgument(request, key, defaultValue)
728 return cast.ToBool(v)
729}
730
731// ParseInt64 extracts and converts an int64 parameter from a CallToolRequest.
732// If the key is not found in the Arguments map, the defaultValue is returned.
733func ParseInt64(request CallToolRequest, key string, defaultValue int64) int64 {
734 v := ParseArgument(request, key, defaultValue)
735 return cast.ToInt64(v)
736}
737
738// ParseInt32 extracts and converts an int32 parameter from a CallToolRequest.
739func ParseInt32(request CallToolRequest, key string, defaultValue int32) int32 {
740 v := ParseArgument(request, key, defaultValue)
741 return cast.ToInt32(v)
742}
743
744// ParseInt16 extracts and converts an int16 parameter from a CallToolRequest.
745func ParseInt16(request CallToolRequest, key string, defaultValue int16) int16 {
746 v := ParseArgument(request, key, defaultValue)
747 return cast.ToInt16(v)
748}
749
750// ParseInt8 extracts and converts an int8 parameter from a CallToolRequest.
751func ParseInt8(request CallToolRequest, key string, defaultValue int8) int8 {
752 v := ParseArgument(request, key, defaultValue)
753 return cast.ToInt8(v)
754}
755
756// ParseInt extracts and converts an int parameter from a CallToolRequest.
757func ParseInt(request CallToolRequest, key string, defaultValue int) int {
758 v := ParseArgument(request, key, defaultValue)
759 return cast.ToInt(v)
760}
761
762// ParseUInt extracts and converts an uint parameter from a CallToolRequest.
763func ParseUInt(request CallToolRequest, key string, defaultValue uint) uint {
764 v := ParseArgument(request, key, defaultValue)
765 return cast.ToUint(v)
766}
767
768// ParseUInt64 extracts and converts an uint64 parameter from a CallToolRequest.
769func ParseUInt64(request CallToolRequest, key string, defaultValue uint64) uint64 {
770 v := ParseArgument(request, key, defaultValue)
771 return cast.ToUint64(v)
772}
773
774// ParseUInt32 extracts and converts an uint32 parameter from a CallToolRequest.
775func ParseUInt32(request CallToolRequest, key string, defaultValue uint32) uint32 {
776 v := ParseArgument(request, key, defaultValue)
777 return cast.ToUint32(v)
778}
779
780// ParseUInt16 extracts and converts an uint16 parameter from a CallToolRequest.
781func ParseUInt16(request CallToolRequest, key string, defaultValue uint16) uint16 {
782 v := ParseArgument(request, key, defaultValue)
783 return cast.ToUint16(v)
784}
785
786// ParseUInt8 extracts and converts an uint8 parameter from a CallToolRequest.
787func ParseUInt8(request CallToolRequest, key string, defaultValue uint8) uint8 {
788 v := ParseArgument(request, key, defaultValue)
789 return cast.ToUint8(v)
790}
791
792// ParseFloat32 extracts and converts a float32 parameter from a CallToolRequest.
793func ParseFloat32(request CallToolRequest, key string, defaultValue float32) float32 {
794 v := ParseArgument(request, key, defaultValue)
795 return cast.ToFloat32(v)
796}
797
798// ParseFloat64 extracts and converts a float64 parameter from a CallToolRequest.
799func ParseFloat64(request CallToolRequest, key string, defaultValue float64) float64 {
800 v := ParseArgument(request, key, defaultValue)
801 return cast.ToFloat64(v)
802}
803
804// ParseString extracts and converts a string parameter from a CallToolRequest.
805func ParseString(request CallToolRequest, key string, defaultValue string) string {
806 v := ParseArgument(request, key, defaultValue)
807 return cast.ToString(v)
808}
809
810// ParseStringMap extracts and converts a string map parameter from a CallToolRequest.
811func ParseStringMap(request CallToolRequest, key string, defaultValue map[string]any) map[string]any {
812 v := ParseArgument(request, key, defaultValue)
813 return cast.ToStringMap(v)
814}
815
816// ToBoolPtr returns a pointer to the given boolean value
817func ToBoolPtr(b bool) *bool {
818 return &b
819}