@@ -43,7 +43,7 @@ import (
43
43
func main () {
44
44
s := server.NewMCPServer (" StreamableHTTP API Server" , " 1.0.0" ,
45
45
server.WithToolCapabilities (true ),
46
- server.WithResourceCapabilities (true ),
46
+ server.WithResourceCapabilities (true , true ),
47
47
)
48
48
49
49
// Add RESTful tools
@@ -60,7 +60,7 @@ func main() {
60
60
mcp.WithDescription (" Create a new user" ),
61
61
mcp.WithString (" name" , mcp.Required ()),
62
62
mcp.WithString (" email" , mcp.Required ()),
63
- mcp.WithInteger (" age" , mcp.Minimum (0 )),
63
+ mcp.WithNumber (" age" , mcp.Min (0 )),
64
64
),
65
65
handleCreateUser,
66
66
)
@@ -69,8 +69,8 @@ func main() {
69
69
mcp.NewTool (" search_users" ,
70
70
mcp.WithDescription (" Search users with filters" ),
71
71
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 )),
74
74
),
75
75
handleSearchUsers,
76
76
)
@@ -95,21 +95,29 @@ func main() {
95
95
}
96
96
97
97
func 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
+ }
99
102
100
103
// Simulate database lookup
101
104
user , err := getUserFromDB (userID)
102
105
if err != nil {
103
106
return nil , fmt.Errorf (" user not found: %s " , userID)
104
107
}
105
108
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
107
111
}
108
112
109
113
func 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
+ }
113
121
114
122
// Validate input
115
123
if !isValidEmail (email) {
@@ -129,11 +137,8 @@ func handleCreateUser(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallTo
129
137
return nil , fmt.Errorf (" failed to create user: % w" , err)
130
138
}
131
139
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
137
142
}
138
143
139
144
// Helper functions and types for the examples
@@ -156,7 +161,6 @@ func getUserFromDB(userID string) (*User, error) {
156
161
}
157
162
158
163
func isValidEmail (email string ) bool {
159
- // Simple email validation
160
164
return strings.Contains (email, " @" ) && strings.Contains (email, " ." )
161
165
}
162
166
@@ -171,54 +175,38 @@ func saveUserToDB(user *User) error {
171
175
}
172
176
173
177
func 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 )
177
181
178
182
// Search users with pagination
179
183
users , total , err := searchUsersInDB (query, limit, offset)
180
184
if err != nil {
181
185
return nil , fmt.Errorf (" search failed: % w" , err)
182
186
}
183
187
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
191
190
}
192
191
193
- func handleUserResource (ctx context .Context , req mcp .ReadResourceRequest ) (* mcp .ReadResourceResult , error ) {
192
+ func handleUserResource (ctx context .Context , req mcp .ReadResourceRequest ) ([] mcp .ResourceContents , error ) {
194
193
userID := extractUserIDFromURI (req.Params .URI )
195
194
196
195
user , err := getUserFromDB (userID)
197
196
if err != nil {
198
197
return nil , fmt.Errorf (" user not found: %s " , userID)
199
198
}
200
199
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
212
207
}
213
208
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
222
210
223
211
func searchUsersInDB (query string , limit , offset int ) ([]*User , int , error ) {
224
212
// Placeholder implementation
@@ -231,9 +219,8 @@ func searchUsersInDB(query string, limit, offset int) ([]*User, int, error) {
231
219
232
220
func extractUserIDFromURI (uri string ) string {
233
221
// 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 :]
237
224
}
238
225
return uri
239
226
}
@@ -244,39 +231,24 @@ func extractUserIDFromURI(uri string) string {
244
231
``` go
245
232
func main () {
246
233
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 (),
253
238
)
254
239
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
274
241
addCRUDTools (s)
275
242
addBatchTools (s)
276
243
addAnalyticsTools (s)
277
244
278
245
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
+
280
252
if err := httpServer.Start (" :8080" ); err != nil {
281
253
log.Fatal (err)
282
254
}
0 commit comments