@@ -54,27 +54,72 @@ func (t *manualGreeter) greet(_ context.Context, req *mcp.CallToolRequest) (*mcp
5454 // Handle the parsing and validation of input and output.
5555 //
5656 // Note that errors here are treated as tool errors, not protocol errors.
57+
58+ // First, unmarshal to a map[string]any and validate.
59+ if err := unmarshalAndValidate (req .Params .Arguments , t .inputSchema ); err != nil {
60+ return errf ("invalid input: %v" , err ), nil
61+ }
62+
63+ // Now unmarshal again to input.
5764 var input Input
5865 if err := json .Unmarshal (req .Params .Arguments , & input ); err != nil {
5966 return errf ("failed to unmarshal arguments: %v" , err ), nil
6067 }
61- if err := t .inputSchema .Validate (input ); err != nil {
62- return errf ("invalid input: %v" , err ), nil
63- }
6468 output := Output {Greeting : "Hi " + input .Name }
65- if err := t .outputSchema .Validate (output ); err != nil {
66- return errf ("tool produced invalid output: %v" , err ), nil
67- }
6869 outputJSON , err := json .Marshal (output )
6970 if err != nil {
7071 return errf ("output failed to marshal: %v" , err ), nil
7172 }
73+ //
74+ if err := unmarshalAndValidate (outputJSON , t .outputSchema ); err != nil {
75+ return errf ("invalid output: %v" , err ), nil
76+ }
77+
7278 return & mcp.CallToolResult {
7379 Content : []mcp.Content {& mcp.TextContent {Text : string (outputJSON )}},
7480 StructuredContent : output ,
7581 }, nil
7682}
7783
84+ // unmarshalAndValidate unmarshals data to a map[string]any, then validates that against res.
85+ func unmarshalAndValidate (data []byte , res * jsonschema.Resolved ) error {
86+ var m map [string ]any
87+ if err := json .Unmarshal (data , & m ); err != nil {
88+ return err
89+ }
90+ return res .Validate (m )
91+ }
92+
93+ var (
94+ inputSchema = & jsonschema.Schema {
95+ Type : "object" ,
96+ Properties : map [string ]* jsonschema.Schema {
97+ "name" : {Type : "string" , MaxLength : jsonschema .Ptr (10 )},
98+ },
99+ }
100+ outputSchema = & jsonschema.Schema {
101+ Type : "object" ,
102+ Properties : map [string ]* jsonschema.Schema {
103+ "greeting" : {Type : "string" },
104+ },
105+ }
106+ )
107+
108+ func newManualGreeter () (* manualGreeter , error ) {
109+ resIn , err := inputSchema .Resolve (nil )
110+ if err != nil {
111+ return nil , err
112+ }
113+ resOut , err := outputSchema .Resolve (nil )
114+ if err != nil {
115+ return nil , err
116+ }
117+ return & manualGreeter {
118+ inputSchema : resIn ,
119+ outputSchema : resOut ,
120+ }, nil
121+ }
122+
78123func main () {
79124 server := mcp .NewServer (& mcp.Implementation {Name : "greeter" }, nil )
80125
@@ -90,27 +135,7 @@ func main() {
90135 //
91136 // We don't need to do all this work: below, we use jsonschema.For to start
92137 // from the default schema.
93- var (
94- manual manualGreeter
95- err error
96- )
97- inputSchema := & jsonschema.Schema {
98- Type : "object" ,
99- Properties : map [string ]* jsonschema.Schema {
100- "name" : {Type : "string" , MaxLength : jsonschema .Ptr (10 )},
101- },
102- }
103- manual .inputSchema , err = inputSchema .Resolve (nil )
104- if err != nil {
105- log .Fatal (err )
106- }
107- outputSchema := & jsonschema.Schema {
108- Type : "object" ,
109- Properties : map [string ]* jsonschema.Schema {
110- "greeting" : {Type : "string" },
111- },
112- }
113- manual .outputSchema , err = outputSchema .Resolve (nil )
138+ manual , err := newManualGreeter ()
114139 if err != nil {
115140 log .Fatal (err )
116141 }
0 commit comments