Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 173 additions & 0 deletions e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1447,6 +1447,179 @@ func TestPullRequestReviewCommentSubmit(t *testing.T) {
require.Equal(t, 3, len(comments), "expected to find three review comments")
}

func TestListIssues(t *testing.T) {
t.Parallel()

mcpClient := setupMCPClient(t)

ctx := context.Background()

// First, who am I
getMeRequest := mcp.CallToolRequest{}
getMeRequest.Params.Name = "get_me"

t.Log("Getting current user...")
resp, err := mcpClient.CallTool(ctx, getMeRequest)
require.NoError(t, err, "expected to call 'get_me' tool successfully")
require.False(t, resp.IsError, fmt.Sprintf("expected result not to be an error: %+v", resp))

require.False(t, resp.IsError, "expected result not to be an error")
require.Len(t, resp.Content, 1, "expected content to have one item")

textContent, ok := resp.Content[0].(mcp.TextContent)
require.True(t, ok, "expected content to be of type TextContent")

var trimmedGetMeText struct {
Login string `json:"login"`
}
err = json.Unmarshal([]byte(textContent.Text), &trimmedGetMeText)
require.NoError(t, err, "expected to unmarshal text content successfully")

currentOwner := trimmedGetMeText.Login

// Then create a repository with a README (via autoInit)
repoName := fmt.Sprintf("github-mcp-server-e2e-%s-%d", t.Name(), time.Now().UnixMilli())
createRepoRequest := mcp.CallToolRequest{}
createRepoRequest.Params.Name = "create_repository"
createRepoRequest.Params.Arguments = map[string]any{
"name": repoName,
"private": true,
"autoInit": true,
}

t.Logf("Creating repository %s/%s...", currentOwner, repoName)
_, err = mcpClient.CallTool(ctx, createRepoRequest)
Copy link

Copilot AI Jun 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test ignores the response from create_repository but then asserts on resp.IsError, which is stale. Change this line to resp, err = mcpClient.CallTool(...) so you capture the actual tool response before asserting.

Suggested change
_, err = mcpClient.CallTool(ctx, createRepoRequest)
resp, err := mcpClient.CallTool(ctx, createRepoRequest)

Copilot uses AI. Check for mistakes.
require.NoError(t, err, "expected to call 'create_repository' tool successfully")
require.False(t, resp.IsError, fmt.Sprintf("expected result not to be an error: %+v", resp))

// Cleanup the repository after the test
t.Cleanup(func() {
// MCP Server doesn't support deletions, but we can use the GitHub Client
ghClient := getRESTClient(t)
t.Logf("Deleting repository %s/%s...", currentOwner, repoName)
ghClient.Repositories.Delete(context.Background(), currentOwner, repoName)
// require.NoError(t, err, "expected to delete repository successfully")
})

// Create a branch on which to create a new commit
createBranchRequest := mcp.CallToolRequest{}
createBranchRequest.Params.Name = "create_branch"
createBranchRequest.Params.Arguments = map[string]any{
"owner": currentOwner,
"repo": repoName,
"branch": "test-branch",
"from_branch": "main",
}

t.Logf("Creating branch in %s/%s...", currentOwner, repoName)
resp, err = mcpClient.CallTool(ctx, createBranchRequest)
require.NoError(t, err, "expected to call 'create_branch' tool successfully")
require.False(t, resp.IsError, fmt.Sprintf("expected result not to be an error: %+v", resp))

// Create a commit with a new file
commitRequest := mcp.CallToolRequest{}
commitRequest.Params.Name = "create_or_update_file"
commitRequest.Params.Arguments = map[string]any{
"owner": currentOwner,
"repo": repoName,
"path": "test-file.txt",
"content": fmt.Sprintf("Created by e2e test %s\nwith multiple lines", t.Name()),
"message": "Add test file",
"branch": "test-branch",
}

t.Logf("Creating commit with new file in %s/%s...", currentOwner, repoName)
resp, err = mcpClient.CallTool(ctx, commitRequest)
require.NoError(t, err, "expected to call 'create_or_update_file' tool successfully")
require.False(t, resp.IsError, fmt.Sprintf("expected result not to be an error: %+v", resp))

textContent, ok = resp.Content[0].(mcp.TextContent)
require.True(t, ok, "expected content to be of type TextContent")

var trimmedCommitText struct {
Commit struct {
SHA string `json:"sha"`
} `json:"commit"`
}
err = json.Unmarshal([]byte(textContent.Text), &trimmedCommitText)
require.NoError(t, err, "expected to unmarshal text content successfully")

// Create a pull request
prRequest := mcp.CallToolRequest{}
prRequest.Params.Name = "create_pull_request"
prRequest.Params.Arguments = map[string]any{
"owner": currentOwner,
"repo": repoName,
"title": "Test PR",
"body": "This is a test PR",
"head": "test-branch",
"base": "main",
}

t.Logf("Creating pull request in %s/%s...", currentOwner, repoName)
resp, err = mcpClient.CallTool(ctx, prRequest)
require.NoError(t, err, "expected to call 'create_pull_request' tool successfully")
require.False(t, resp.IsError, fmt.Sprintf("expected result not to be an error: %+v", resp))

// Create a review for the pull request, but we can't approve it
// because the current owner also owns the PR.
createPendingPullRequestReviewRequest := mcp.CallToolRequest{}
createPendingPullRequestReviewRequest.Params.Name = "create_pending_pull_request_review"
createPendingPullRequestReviewRequest.Params.Arguments = map[string]any{
"owner": currentOwner,
"repo": repoName,
"pullNumber": 1,
}

t.Logf("Creating pending review for pull request in %s/%s...", currentOwner, repoName)
resp, err = mcpClient.CallTool(ctx, createPendingPullRequestReviewRequest)
require.NoError(t, err, "expected to call 'create_pending_pull_request_review' tool successfully")
require.False(t, resp.IsError, fmt.Sprintf("expected result not to be an error: %+v", resp))

textContent, ok = resp.Content[0].(mcp.TextContent)
require.True(t, ok, "expected content to be of type TextContent")
require.Equal(t, "pending pull request created", textContent.Text)

t.Logf("Creating an issue in %s/%s...", currentOwner, repoName)
createIssueRequest := mcp.CallToolRequest{}
createIssueRequest.Params.Name = "create_issue"
createIssueRequest.Params.Arguments = map[string]any{
"owner": currentOwner,
"repo": repoName,
"title": "Test Issue",
"body": "This is a test issue",
}
resp, err = mcpClient.CallTool(ctx, createIssueRequest)
require.NoError(t, err, "expected to call 'create_issue' tool successfully")
require.False(t, resp.IsError, fmt.Sprintf("expected result not to be an error: %+v", resp))

// List issues in the repository
listIssuesRequest := mcp.CallToolRequest{}
listIssuesRequest.Params.Name = "list_issues"
listIssuesRequest.Params.Arguments = map[string]any{
"owner": currentOwner,
"repo": repoName,
}

t.Logf("Listing issues in %s/%s...", currentOwner, repoName)
resp, err = mcpClient.CallTool(ctx, listIssuesRequest)
require.NoError(t, err, "expected to call 'list_issues' tool successfully")
require.False(t, resp.IsError, fmt.Sprintf("expected result not to be an error: %+v", resp))

textContent, ok = resp.Content[0].(mcp.TextContent)
require.True(t, ok, "expected content to be of type TextContent")

var issues []struct {
ID int `json:"id"`
Number int `json:"number"`
Title string `json:"title"`
Body string `json:"body"`
}
err = json.Unmarshal([]byte(textContent.Text), &issues)
require.NoError(t, err, "expected to unmarshal text content successfully")
require.Len(t, issues, 1, "expected to find one issue")
}

func TestPullRequestReviewDeletion(t *testing.T) {
t.Parallel()

Expand Down
3 changes: 3 additions & 0 deletions pkg/github/issues.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ func SearchIssues(getClient GetClientFn, t translations.TranslationHelperFunc) (
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
if !strings.Contains(query, "is:issue") {
query += " is:issue"
}
sort, err := OptionalParam[string](request, "sort")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
Expand Down