@@ -206,3 +206,139 @@ func TestToolsets(t *testing.T) {
206
206
require .True (t ,toolsContains ("list_branches" ),"expected to find 'list_branches' tool" )
207
207
require .False (t ,toolsContains ("get_pull_request" ),"expected not to find 'get_pull_request' tool" )
208
208
}
209
+
210
+ func TestTags (t * testing.T ) {
211
+ mcpClient := setupMCPClient (t )
212
+
213
+ ctx := context .Background ()
214
+
215
+ // First, who am I
216
+ getMeRequest := mcp.CallToolRequest {}
217
+ getMeRequest .Params .Name = "get_me"
218
+
219
+ t .Log ("Getting current user..." )
220
+ resp ,err := mcpClient .CallTool (ctx ,getMeRequest )
221
+ require .NoError (t ,err ,"expected to call 'get_me' tool successfully" )
222
+ require .False (t ,resp .IsError ,fmt .Sprintf ("expected result not to be an error: %+v" ,resp ))
223
+
224
+ require .False (t ,resp .IsError ,"expected result not to be an error" )
225
+ require .Len (t ,resp .Content ,1 ,"expected content to have one item" )
226
+
227
+ textContent ,ok := resp .Content [0 ].(mcp.TextContent )
228
+ require .True (t ,ok ,"expected content to be of type TextContent" )
229
+
230
+ var trimmedGetMeText struct {
231
+ Login string `json:"login"`
232
+ }
233
+ err = json .Unmarshal ([]byte (textContent .Text ),& trimmedGetMeText )
234
+ require .NoError (t ,err ,"expected to unmarshal text content successfully" )
235
+
236
+ currentOwner := trimmedGetMeText .Login
237
+
238
+ // Then create a repository with a README (via autoInit)
239
+ repoName := fmt .Sprintf ("github-mcp-server-e2e-%s-%d" ,t .Name (),time .Now ().UnixMilli ())
240
+ createRepoRequest := mcp.CallToolRequest {}
241
+ createRepoRequest .Params .Name = "create_repository"
242
+ createRepoRequest .Params .Arguments = map [string ]any {
243
+ "name" :repoName ,
244
+ "private" :true ,
245
+ "autoInit" :true ,
246
+ }
247
+
248
+ t .Logf ("Creating repository %s/%s..." ,currentOwner ,repoName )
249
+ _ ,err = mcpClient .CallTool (ctx ,createRepoRequest )
250
+ require .NoError (t ,err ,"expected to call 'get_me' tool successfully" )
251
+ require .False (t ,resp .IsError ,fmt .Sprintf ("expected result not to be an error: %+v" ,resp ))
252
+
253
+ // Cleanup the repository after the test
254
+ t .Cleanup (func () {
255
+ // MCP Server doesn't support deletions, but we can use the GitHub Client
256
+ ghClient := github .NewClient (nil ).WithAuthToken (getE2EToken (t ))
257
+ t .Logf ("Deleting repository %s/%s..." ,currentOwner ,repoName )
258
+ _ ,err := ghClient .Repositories .Delete (context .Background (),currentOwner ,repoName )
259
+ require .NoError (t ,err ,"expected to delete repository successfully" )
260
+ })
261
+
262
+ // Then create a tag
263
+ // MCP Server doesn't support tag creation, but we can use the GitHub Client
264
+ ghClient := github .NewClient (nil ).WithAuthToken (getE2EToken (t ))
265
+ t .Logf ("Creating tag %s/%s:%s..." ,currentOwner ,repoName ,"v0.0.1" )
266
+ ref ,_ ,err := ghClient .Git .GetRef (context .Background (),currentOwner ,repoName ,"refs/heads/main" )
267
+ require .NoError (t ,err ,"expected to get ref successfully" )
268
+
269
+ tagObj ,_ ,err := ghClient .Git .CreateTag (context .Background (),currentOwner ,repoName ,& github.Tag {
270
+ Tag :github .Ptr ("v0.0.1" ),
271
+ Message :github .Ptr ("v0.0.1" ),
272
+ Object :& github.GitObject {
273
+ SHA :ref .Object .SHA ,
274
+ Type :github .Ptr ("commit" ),
275
+ },
276
+ })
277
+ require .NoError (t ,err ,"expected to create tag object successfully" )
278
+
279
+ _ ,_ ,err = ghClient .Git .CreateRef (context .Background (),currentOwner ,repoName ,& github.Reference {
280
+ Ref :github .Ptr ("refs/tags/v0.0.1" ),
281
+ Object :& github.GitObject {
282
+ SHA :tagObj .SHA ,
283
+ },
284
+ })
285
+ require .NoError (t ,err ,"expected to create tag ref successfully" )
286
+
287
+ // List the tags
288
+ listTagsRequest := mcp.CallToolRequest {}
289
+ listTagsRequest .Params .Name = "list_tags"
290
+ listTagsRequest .Params .Arguments = map [string ]any {
291
+ "owner" :currentOwner ,
292
+ "repo" :repoName ,
293
+ }
294
+
295
+ t .Logf ("Listing tags for %s/%s..." ,currentOwner ,repoName )
296
+ resp ,err = mcpClient .CallTool (ctx ,listTagsRequest )
297
+ require .NoError (t ,err ,"expected to call 'list_tags' tool successfully" )
298
+ require .False (t ,resp .IsError ,fmt .Sprintf ("expected result not to be an error: %+v" ,resp ))
299
+
300
+ require .False (t ,resp .IsError ,"expected result not to be an error" )
301
+ require .Len (t ,resp .Content ,1 ,"expected content to have one item" )
302
+
303
+ textContent ,ok = resp .Content [0 ].(mcp.TextContent )
304
+ require .True (t ,ok ,"expected content to be of type TextContent" )
305
+
306
+ var trimmedTags []struct {
307
+ Name string `json:"name"`
308
+ Commit struct {
309
+ SHA string `json:"sha"`
310
+ }`json:"commit"`
311
+ }
312
+ err = json .Unmarshal ([]byte (textContent .Text ),& trimmedTags )
313
+ require .NoError (t ,err ,"expected to unmarshal text content successfully" )
314
+
315
+ require .Len (t ,trimmedTags ,1 ,"expected to find one tag" )
316
+ require .Equal (t ,"v0.0.1" ,trimmedTags [0 ].Name ,"expected tag name to match" )
317
+ require .Equal (t ,* ref .Object .SHA ,trimmedTags [0 ].Commit .SHA ,"expected tag SHA to match" )
318
+
319
+ // And fetch an individual tag
320
+ getTagRequest := mcp.CallToolRequest {}
321
+ getTagRequest .Params .Name = "get_tag"
322
+ getTagRequest .Params .Arguments = map [string ]any {
323
+ "owner" :currentOwner ,
324
+ "repo" :repoName ,
325
+ "tag" :"v0.0.1" ,
326
+ }
327
+
328
+ t .Logf ("Getting tag %s/%s:%s..." ,currentOwner ,repoName ,"v0.0.1" )
329
+ resp ,err = mcpClient .CallTool (ctx ,getTagRequest )
330
+ require .NoError (t ,err ,"expected to call 'get_tag' tool successfully" )
331
+ require .False (t ,resp .IsError ,"expected result not to be an error" )
332
+
333
+ var trimmedTag []struct {// don't understand why this is an array
334
+ Name string `json:"name"`
335
+ Commit struct {
336
+ SHA string `json:"sha"`
337
+ }`json:"commit"`
338
+ }
339
+ err = json .Unmarshal ([]byte (textContent .Text ),& trimmedTag )
340
+ require .NoError (t ,err ,"expected to unmarshal text content successfully" )
341
+ require .Len (t ,trimmedTag ,1 ,"expected to find one tag" )
342
+ require .Equal (t ,"v0.0.1" ,trimmedTag [0 ].Name ,"expected tag name to match" )
343
+ require .Equal (t ,* ref .Object .SHA ,trimmedTag [0 ].Commit .SHA ,"expected tag SHA to match" )
344
+ }