@@ -43,7 +43,7 @@ import (
4343func main () {
4444 s := server.NewMCPServer (" StreamableHTTP API Server" , " 1.0.0" ,
4545 server.WithToolCapabilities (true ),
46- server.WithResourceCapabilities (true ),
46+ server.WithResourceCapabilities (true , true ),
4747 )
4848
4949 // Add RESTful tools
@@ -60,7 +60,7 @@ func main() {
6060 mcp.WithDescription (" Create a new user" ),
6161 mcp.WithString (" name" , mcp.Required ()),
6262 mcp.WithString (" email" , mcp.Required ()),
63- mcp.WithInteger (" age" , mcp.Minimum (0 )),
63+ mcp.WithNumber (" age" , mcp.Min (0 )),
6464 ),
6565 handleCreateUser,
6666 )
@@ -69,8 +69,8 @@ func main() {
6969 mcp.NewTool (" search_users" ,
7070 mcp.WithDescription (" Search users with filters" ),
7171 mcp.WithString (" query" , mcp.Description (" Search query" )),
72- mcp.WithInteger (" limit" , mcp.Default (10 ), mcp.Maximum (100 )),
73- mcp.WithInteger (" offset" , mcp.Default (0 ), mcp.Minimum (0 )),
72+ mcp.WithNumber (" limit" , mcp.DefaultNumber (10 ), mcp.Max (100 )),
73+ mcp.WithNumber (" offset" , mcp.DefaultNumber (0 ), mcp.Min (0 )),
7474 ),
7575 handleSearchUsers,
7676 )
@@ -95,21 +95,29 @@ func main() {
9595}
9696
9797func handleGetUser (ctx context .Context , req mcp .CallToolRequest ) (*mcp .CallToolResult , error ) {
98- userID := req.Params .Arguments [" user_id" ].(string )
98+ userID := req.GetString (" user_id" , " " )
99+ if userID == " " {
100+ return nil , fmt.Errorf (" user_id is required" )
101+ }
99102
100103 // Simulate database lookup
101104 user , err := getUserFromDB (userID)
102105 if err != nil {
103106 return nil , fmt.Errorf (" user not found: %s " , userID)
104107 }
105108
106- return mcp.NewToolResultJSON (user), nil
109+ return mcp.NewToolResultText (fmt.Sprintf (` {"id":"%s","name":"%s","email":"%s","age":%d}` ,
110+ user.ID , user.Name , user.Email , user.Age )), nil
107111}
108112
109113func handleCreateUser (ctx context .Context , req mcp .CallToolRequest ) (*mcp .CallToolResult , error ) {
110- name := req.Params .Arguments [" name" ].(string )
111- email := req.Params .Arguments [" email" ].(string )
112- age := int (req.Params .Arguments [" age" ].(float64 ))
114+ name := req.GetString (" name" , " " )
115+ email := req.GetString (" email" , " " )
116+ age := req.GetInt (" age" , 0 )
117+
118+ if name == " " || email == " " {
119+ return nil , fmt.Errorf (" name and email are required" )
120+ }
113121
114122 // Validate input
115123 if !isValidEmail (email) {
@@ -129,11 +137,8 @@ func handleCreateUser(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallTo
129137 return nil , fmt.Errorf (" failed to create user: % w" , err)
130138 }
131139
132- return mcp.NewToolResultJSON (map [string ]interface {}{
133- " id" : user.ID ,
134- " message" : " User created successfully" ,
135- " user" : user,
136- }), nil
140+ return mcp.NewToolResultText (fmt.Sprintf (` {"id":"%s","message":"User created successfully","user":{"id":"%s","name":"%s","email":"%s","age":%d}}` ,
141+ user.ID , user.ID , user.Name , user.Email , user.Age )), nil
137142}
138143
139144// Helper functions and types for the examples
@@ -156,7 +161,6 @@ func getUserFromDB(userID string) (*User, error) {
156161}
157162
158163func isValidEmail (email string ) bool {
159- // Simple email validation
160164 return strings.Contains (email, " @" ) && strings.Contains (email, " ." )
161165}
162166
@@ -171,54 +175,38 @@ func saveUserToDB(user *User) error {
171175}
172176
173177func handleSearchUsers (ctx context .Context , req mcp .CallToolRequest ) (*mcp .CallToolResult , error ) {
174- query := getStringParam ( req.Params . Arguments , " query" , " " )
175- limit := int ( getFloatParam ( req.Params . Arguments , " limit" , 10 ) )
176- offset := int ( getFloatParam ( req.Params . Arguments , " offset" , 0 ) )
178+ query := req.GetString ( " query" , " " )
179+ limit := req.GetInt ( " limit" , 10 )
180+ offset := req.GetInt ( " offset" , 0 )
177181
178182 // Search users with pagination
179183 users , total , err := searchUsersInDB (query, limit, offset)
180184 if err != nil {
181185 return nil , fmt.Errorf (" search failed: % w" , err)
182186 }
183187
184- return mcp.NewToolResultJSON (map [string ]interface {}{
185- " users" : users,
186- " total" : total,
187- " limit" : limit,
188- " offset" : offset,
189- " query" : query,
190- }), nil
188+ return mcp.
NewToolResultText (fmt.
Sprintf (
` {"users":[{"id":"1","name":"John Doe","email":"[email protected] ","age":30},{"id":"2","name":"Jane Smith","email":"[email protected] ","age":25}],"total":%d,"limit":%d,"offset":%d,"query":"%s"}` ,
189+ total, limit, offset, query)), nil
191190}
192191
193- func handleUserResource (ctx context .Context , req mcp .ReadResourceRequest ) (* mcp .ReadResourceResult , error ) {
192+ func handleUserResource (ctx context .Context , req mcp .ReadResourceRequest ) ([] mcp .ResourceContents , error ) {
194193 userID := extractUserIDFromURI (req.Params .URI )
195194
196195 user , err := getUserFromDB (userID)
197196 if err != nil {
198197 return nil , fmt.Errorf (" user not found: %s " , userID)
199198 }
200199
201- return mcp.NewResourceResultJSON (user), nil
202- }
203-
204- // Additional helper functions for parameter handling
205- func getStringParam (args map [string ]interface {}, key , defaultValue string ) string {
206- if val , ok := args[key]; ok && val != nil {
207- if str , ok := val.(string ); ok {
208- return str
209- }
210- }
211- return defaultValue
200+ return []mcp.ResourceContents {
201+ mcp.TextResourceContents {
202+ URI: req.Params .URI ,
203+ MIMEType: " application/json" ,
204+ Text: fmt.Sprintf (` {"id":"%s","name":"%s","email":"%s","age":%d}` , user.ID , user.Name , user.Email , user.Age ),
205+ },
206+ }, nil
212207}
213208
214- func getFloatParam (args map [string ]interface {}, key string , defaultValue float64 ) float64 {
215- if val , ok := args[key]; ok && val != nil {
216- if f , ok := val.(float64 ); ok {
217- return f
218- }
219- }
220- return defaultValue
221- }
209+ // Additional helper functions
222210
223211func searchUsersInDB (query string , limit , offset int ) ([]*User , int , error ) {
224212 // Placeholder implementation
@@ -231,9 +219,8 @@ func searchUsersInDB(query string, limit, offset int) ([]*User, int, error) {
231219
232220func extractUserIDFromURI (uri string ) string {
233221 // Extract user ID from URI like "users://123"
234- parts := strings.Split (uri, " ://" )
235- if len (parts) > 1 {
236- return parts[1 ]
222+ if len (uri) > 8 && uri[:8 ] == " users://" {
223+ return uri[8 :]
237224 }
238225 return uri
239226}
@@ -244,39 +231,24 @@ func extractUserIDFromURI(uri string) string {
244231``` go
245232func main () {
246233 s := server.NewMCPServer (" Advanced StreamableHTTP Server" , " 1.0.0" ,
247- server.WithAllCapabilities (),
248- server.WithRecovery (),
249- server.WithHooks (&server.Hooks {
250- OnToolCall: logToolCall,
251- OnResourceRead: logResourceRead,
252- }),
234+ server.WithResourceCapabilities (true , true ),
235+ server.WithPromptCapabilities (true ),
236+ server.WithToolCapabilities (true ),
237+ server.WithLogging (),
253238 )
254239
255- // Configure StreamableHTTP-specific options
256- streamableHTTPOptions := server.StreamableHTTPOptions {
257- BasePath: " /api/v1/mcp" ,
258- ReadTimeout: 30 * time.Second ,
259- WriteTimeout: 30 * time.Second ,
260- IdleTimeout: 60 * time.Second ,
261- MaxBodySize: 10 * 1024 * 1024 , // 10MB
262- EnableCORS: true ,
263- AllowedOrigins: []string {" https://myapp.com" , " http://localhost:3000" },
264- AllowedMethods: []string {" GET" , " POST" , " OPTIONS" },
265- AllowedHeaders: []string {" Content-Type" , " Authorization" },
266- EnableGzip: true ,
267- TrustedProxies: []string {" 10.0.0.0/8" , " 172.16.0.0/12" },
268- }
269-
270- // Add middleware
271- addStreamableHTTPMiddleware (s)
272-
273- // Add comprehensive tools
240+ // Add comprehensive tools and resources
274241 addCRUDTools (s)
275242 addBatchTools (s)
276243 addAnalyticsTools (s)
277244
278245 log.Println (" Starting advanced StreamableHTTP server on :8080" )
279- httpServer := server.NewStreamableHTTPServer (s, streamableHTTPOptions...)
246+ httpServer := server.NewStreamableHTTPServer (s,
247+ server.WithEndpointPath (" /api/v1/mcp" ),
248+ server.WithHeartbeatInterval (30 *time.Second ),
249+ server.WithStateLess (false ),
250+ )
251+
280252 if err := httpServer.Start (" :8080" ); err != nil {
281253 log.Fatal (err)
282254 }
0 commit comments