@@ -168,100 +168,139 @@ type MinimalSearchUsersResult struct {
168
168
Items []MinimalUser `json:"items"`
169
169
}
170
170
171
- // SearchUsers creates a tool to search for GitHub users.
172
- func SearchUsers (getClient GetClientFn , t translations.TranslationHelperFunc ) (tool mcp.Tool , handler server.ToolHandlerFunc ) {
173
- return mcp .NewTool ("search_users" ,
174
- mcp .WithDescription (t ("TOOL_SEARCH_USERS_DESCRIPTION" , "Search for GitHub users" )),
175
- mcp .WithToolAnnotation (mcp.ToolAnnotation {
176
- Title : t ("TOOL_SEARCH_USERS_USER_TITLE" , "Search users" ),
177
- ReadOnlyHint : ToBoolPtr (true ),
178
- }),
179
- mcp .WithString ("q" ,
180
- mcp .Required (),
181
- mcp .Description ("Search query using GitHub users search syntax" ),
182
- ),
183
- mcp .WithString ("sort" ,
184
- mcp .Description ("Sort field by category" ),
185
- mcp .Enum ("followers" , "repositories" , "joined" ),
186
- ),
187
- mcp .WithString ("order" ,
188
- mcp .Description ("Sort order" ),
189
- mcp .Enum ("asc" , "desc" ),
190
- ),
191
- WithPagination (),
192
- ),
193
- func (ctx context.Context , request mcp.CallToolRequest ) (* mcp.CallToolResult , error ) {
194
- query , err := RequiredParam [string ](request , "q" )
195
- if err != nil {
196
- return mcp .NewToolResultError (err .Error ()), nil
197
- }
198
- sort , err := OptionalParam [string ](request , "sort" )
199
- if err != nil {
200
- return mcp .NewToolResultError (err .Error ()), nil
201
- }
202
- order , err := OptionalParam [string ](request , "order" )
203
- if err != nil {
204
- return mcp .NewToolResultError (err .Error ()), nil
205
- }
206
- pagination , err := OptionalPaginationParams (request )
207
- if err != nil {
208
- return mcp .NewToolResultError (err .Error ()), nil
209
- }
171
+ func userOrOrgHandler (accountType string , getClient GetClientFn ) server.ToolHandlerFunc {
172
+ return func (ctx context.Context , request mcp.CallToolRequest ) (* mcp.CallToolResult , error ) {
173
+ query , err := RequiredParam [string ](request , "query" )
174
+ if err != nil {
175
+ return mcp .NewToolResultError (err .Error ()), nil
176
+ }
177
+ sort , err := OptionalParam [string ](request , "sort" )
178
+ if err != nil {
179
+ return mcp .NewToolResultError (err .Error ()), nil
180
+ }
181
+ order , err := OptionalParam [string ](request , "order" )
182
+ if err != nil {
183
+ return mcp .NewToolResultError (err .Error ()), nil
184
+ }
185
+ pagination , err := OptionalPaginationParams (request )
186
+ if err != nil {
187
+ return mcp .NewToolResultError (err .Error ()), nil
188
+ }
210
189
211
- opts := & github.SearchOptions {
212
- Sort : sort ,
213
- Order : order ,
214
- ListOptions : github.ListOptions {
215
- PerPage : pagination .perPage ,
216
- Page : pagination .page ,
217
- },
218
- }
190
+ opts := & github.SearchOptions {
191
+ Sort : sort ,
192
+ Order : order ,
193
+ ListOptions : github.ListOptions {
194
+ PerPage : pagination .perPage ,
195
+ Page : pagination .page ,
196
+ },
197
+ }
219
198
220
- client , err := getClient (ctx )
221
- if err != nil {
222
- return nil , fmt .Errorf ("failed to get GitHub client: %w" , err )
223
- }
199
+ client , err := getClient (ctx )
200
+ if err != nil {
201
+ return nil , fmt .Errorf ("failed to get GitHub client: %w" , err )
202
+ }
224
203
225
- result , resp , err := client .Search .Users (ctx , "type:user " + query , opts )
204
+ searchQuery := "type:" + accountType + " " + query
205
+ result , resp , err := client .Search .Users (ctx , searchQuery , opts )
206
+ if err != nil {
207
+ return ghErrors .NewGitHubAPIErrorResponse (ctx ,
208
+ fmt .Sprintf ("failed to search %ss with query '%s'" , accountType , query ),
209
+ resp ,
210
+ err ,
211
+ ), nil
212
+ }
213
+ defer func () { _ = resp .Body .Close () }()
214
+
215
+ if resp .StatusCode != 200 {
216
+ body , err := io .ReadAll (resp .Body )
226
217
if err != nil {
227
- return ghErrors .NewGitHubAPIErrorResponse (ctx ,
228
- fmt .Sprintf ("failed to search users with query '%s'" , query ),
229
- resp ,
230
- err ,
231
- ), nil
218
+ return nil , fmt .Errorf ("failed to read response body: %w" , err )
232
219
}
233
- defer func () { _ = resp .Body .Close () }()
220
+ return mcp .NewToolResultError (fmt .Sprintf ("failed to search %ss: %s" , accountType , string (body ))), nil
221
+ }
234
222
235
- if resp .StatusCode != 200 {
236
- body , err := io .ReadAll (resp .Body )
237
- if err != nil {
238
- return nil , fmt .Errorf ("failed to read response body: %w" , err )
239
- }
240
- return mcp .NewToolResultError (fmt .Sprintf ("failed to search users: %s" , string (body ))), nil
241
- }
223
+ minimalUsers := make ([]MinimalUser , 0 , len (result .Users ))
242
224
243
- minimalUsers := make ([]MinimalUser , 0 , len (result .Users ))
244
- for _ , user := range result .Users {
245
- mu := MinimalUser {
246
- Login : user .GetLogin (),
247
- ID : user .GetID (),
248
- ProfileURL : user .GetHTMLURL (),
249
- AvatarURL : user .GetAvatarURL (),
225
+ for _ , user := range result .Users {
226
+ if user .Login != nil {
227
+ mu := MinimalUser {Login : * user .Login }
228
+ if user .ID != nil {
229
+ mu .ID = * user .ID
230
+ }
231
+ if user .HTMLURL != nil {
232
+ mu .ProfileURL = * user .HTMLURL
233
+ }
234
+ if user .AvatarURL != nil {
235
+ mu .AvatarURL = * user .AvatarURL
250
236
}
251
-
252
237
minimalUsers = append (minimalUsers , mu )
253
238
}
239
+ }
240
+ minimalResp := & MinimalSearchUsersResult {
241
+ TotalCount : result .GetTotal (),
242
+ IncompleteResults : result .GetIncompleteResults (),
243
+ Items : minimalUsers ,
244
+ }
245
+ if result .Total != nil {
246
+ minimalResp .TotalCount = * result .Total
247
+ }
248
+ if result .IncompleteResults != nil {
249
+ minimalResp .IncompleteResults = * result .IncompleteResults
250
+ }
254
251
255
- minimalResp := MinimalSearchUsersResult {
256
- TotalCount : result .GetTotal (),
257
- IncompleteResults : result .GetIncompleteResults (),
258
- Items : minimalUsers ,
259
- }
260
-
261
- r , err := json .Marshal (minimalResp )
262
- if err != nil {
263
- return nil , fmt .Errorf ("failed to marshal response: %w" , err )
264
- }
265
- return mcp .NewToolResultText (string (r )), nil
252
+ r , err := json .Marshal (minimalResp )
253
+ if err != nil {
254
+ return nil , fmt .Errorf ("failed to marshal response: %w" , err )
266
255
}
256
+ return mcp .NewToolResultText (string (r )), nil
257
+ }
258
+ }
259
+
260
+ // SearchUsers creates a tool to search for GitHub users.
261
+ func SearchUsers (getClient GetClientFn , t translations.TranslationHelperFunc ) (tool mcp.Tool , handler server.ToolHandlerFunc ) {
262
+ return mcp .NewTool ("search_users" ,
263
+ mcp .WithDescription (t ("TOOL_SEARCH_USERS_DESCRIPTION" , "Search for GitHub users exclusively" )),
264
+ mcp .WithToolAnnotation (mcp.ToolAnnotation {
265
+ Title : t ("TOOL_SEARCH_USERS_USER_TITLE" , "Search users" ),
266
+ ReadOnlyHint : ToBoolPtr (true ),
267
+ }),
268
+ mcp .WithString ("query" ,
269
+ mcp .Required (),
270
+ mcp .Description ("Search query using GitHub users search syntax scoped to type:user" ),
271
+ ),
272
+ mcp .WithString ("sort" ,
273
+ mcp .Description ("Sort field by category" ),
274
+ mcp .Enum ("followers" , "repositories" , "joined" ),
275
+ ),
276
+ mcp .WithString ("order" ,
277
+ mcp .Description ("Sort order" ),
278
+ mcp .Enum ("asc" , "desc" ),
279
+ ),
280
+ WithPagination (),
281
+ ), userOrOrgHandler ("user" , getClient )
282
+ }
283
+
284
+ // SearchOrgs creates a tool to search for GitHub organizations.
285
+ func SearchOrgs (getClient GetClientFn , t translations.TranslationHelperFunc ) (tool mcp.Tool , handler server.ToolHandlerFunc ) {
286
+ return mcp .NewTool ("search_orgs" ,
287
+ mcp .WithDescription (t ("TOOL_SEARCH_ORGS_DESCRIPTION" , "Search for GitHub organizations exclusively" )),
288
+ mcp .WithToolAnnotation (mcp.ToolAnnotation {
289
+ Title : t ("TOOL_SEARCH_ORGS_USER_TITLE" , "Search organizations" ),
290
+ ReadOnlyHint : ToBoolPtr (true ),
291
+ }),
292
+ mcp .WithString ("query" ,
293
+ mcp .Required (),
294
+ mcp .Description ("Search query using GitHub organizations search syntax scoped to type:org" ),
295
+ ),
296
+ mcp .WithString ("sort" ,
297
+ mcp .Description ("Sort field by category" ),
298
+ mcp .Enum ("followers" , "repositories" , "joined" ),
299
+ ),
300
+ mcp .WithString ("order" ,
301
+ mcp .Description ("Sort order" ),
302
+ mcp .Enum ("asc" , "desc" ),
303
+ ),
304
+ WithPagination (),
305
+ ), userOrOrgHandler ("org" , getClient )
267
306
}
0 commit comments