@@ -168,100 +168,139 @@ type MinimalSearchUsersResult struct {
168168 Items []MinimalUser `json:"items"`
169169}
170170
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+ }
210189
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+ }
219198
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+ }
224203
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 )
226217 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 )
232219 }
233- defer func () { _ = resp .Body .Close () }()
220+ return mcp .NewToolResultError (fmt .Sprintf ("failed to search %ss: %s" , accountType , string (body ))), nil
221+ }
234222
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 ))
242224
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
250236 }
251-
252237 minimalUsers = append (minimalUsers , mu )
253238 }
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+ }
254251
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 )
266255 }
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 )
267306}
0 commit comments