Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,7 @@ The following sets of tools are available (all are on by default):
- `repo`: Repository name (string, required)

- **get_commit** - Get commit details
- `include_diff`: Whether to include file diffs and stats in the response. Default is true for single commit queries. (boolean, optional)
- `owner`: Repository owner (string, required)
- `page`: Page number for pagination (min 1) (number, optional)
- `perPage`: Results per page for pagination (min 1, max 100) (number, optional)
Expand Down Expand Up @@ -898,6 +899,7 @@ The following sets of tools are available (all are on by default):
- `sort`: Sort field ('indexed' only) (string, optional)

- **search_repositories** - Search repositories
- `minimal_output`: Return minimal repository information (default: true). When false, returns full GitHub API repository objects. (boolean, optional)
- `page`: Page number for pagination (min 1) (number, optional)
- `perPage`: Results per page for pagination (min 1, max 100) (number, optional)
- `query`: Repository search query. Examples: 'machine learning in:name stars:>1000 language:python', 'topic:react', 'user:facebook'. Supports advanced search syntax for precise filtering. (string, required)
Expand Down
4 changes: 4 additions & 0 deletions pkg/github/__toolsnaps__/get_commit.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
"description": "Get details for a commit from a GitHub repository",
"inputSchema": {
"properties": {
"include_diff": {
"description": "Whether to include file diffs and stats in the response. Default is true for single commit queries.",
"type": "boolean"
},
"owner": {
"description": "Repository owner",
"type": "string"
Expand Down
5 changes: 5 additions & 0 deletions pkg/github/__toolsnaps__/search_repositories.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
"description": "Find GitHub repositories by name, description, readme, topics, or other metadata. Perfect for discovering projects, finding examples, or locating specific repositories across GitHub.",
"inputSchema": {
"properties": {
"minimal_output": {
"default": true,
"description": "Return minimal repository information (default: true). When false, returns full GitHub API repository objects.",
"type": "boolean"
},
"page": {
"description": "Page number for pagination (min 1)",
"minimum": 1,
Expand Down
17 changes: 15 additions & 2 deletions pkg/github/gists.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,14 @@ func CreateGist(getClient GetClientFn, t translations.TranslationHelperFunc) (to
return mcp.NewToolResultError(fmt.Sprintf("failed to create gist: %s", string(body))), nil
}

r, err := json.Marshal(createdGist)
minimalResponse := MinimalGistResponse{
URL: createdGist.GetHTMLURL(),
ID: createdGist.GetID(),
Description: createdGist.GetDescription(),
Public: createdGist.GetPublic(),
}

r, err := json.Marshal(minimalResponse)
if err != nil {
return nil, fmt.Errorf("failed to marshal response: %w", err)
}
Expand Down Expand Up @@ -249,7 +256,13 @@ func UpdateGist(getClient GetClientFn, t translations.TranslationHelperFunc) (to
return mcp.NewToolResultError(fmt.Sprintf("failed to update gist: %s", string(body))), nil
}

r, err := json.Marshal(updatedGist)
minimalResponse := MinimalUpdateResponse{
URL: updatedGist.GetHTMLURL(),
Updated: true,
Message: "Gist updated successfully",
}

r, err := json.Marshal(minimalResponse)
if err != nil {
return nil, fmt.Errorf("failed to marshal response: %w", err)
}
Expand Down
37 changes: 9 additions & 28 deletions pkg/github/gists_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,23 +321,13 @@ func Test_CreateGist(t *testing.T) {
// Parse the result and get the text content
textContent := getTextResult(t, result)

// Unmarshal and verify the result
var gist *github.Gist
// Unmarshal and verify the minimal result
var gist MinimalGistResponse
err = json.Unmarshal([]byte(textContent.Text), &gist)
require.NoError(t, err)

assert.Equal(t, *tc.expectedGist.ID, *gist.ID)
assert.Equal(t, *tc.expectedGist.Description, *gist.Description)
assert.Equal(t, *tc.expectedGist.HTMLURL, *gist.HTMLURL)
assert.Equal(t, *tc.expectedGist.Public, *gist.Public)

// Verify file content
for filename, expectedFile := range tc.expectedGist.Files {
actualFile, exists := gist.Files[filename]
assert.True(t, exists)
assert.Equal(t, *expectedFile.Filename, *actualFile.Filename)
assert.Equal(t, *expectedFile.Content, *actualFile.Content)
}
assert.Equal(t, tc.expectedGist.GetID(), gist.ID)
assert.Equal(t, tc.expectedGist.GetHTMLURL(), gist.URL)
})
}
}
Expand Down Expand Up @@ -486,22 +476,13 @@ func Test_UpdateGist(t *testing.T) {
// Parse the result and get the text content
textContent := getTextResult(t, result)

// Unmarshal and verify the result
var gist *github.Gist
err = json.Unmarshal([]byte(textContent.Text), &gist)
// Unmarshal and verify the minimal result
var updateResp MinimalUpdateResponse
err = json.Unmarshal([]byte(textContent.Text), &updateResp)
require.NoError(t, err)

assert.Equal(t, *tc.expectedGist.ID, *gist.ID)
assert.Equal(t, *tc.expectedGist.Description, *gist.Description)
assert.Equal(t, *tc.expectedGist.HTMLURL, *gist.HTMLURL)

// Verify file content
for filename, expectedFile := range tc.expectedGist.Files {
actualFile, exists := gist.Files[filename]
assert.True(t, exists)
assert.Equal(t, *expectedFile.Filename, *actualFile.Filename)
assert.Equal(t, *expectedFile.Content, *actualFile.Content)
}
assert.Equal(t, tc.expectedGist.GetHTMLURL(), updateResp.URL)
assert.Equal(t, true, updateResp.Updated)
})
}
}
19 changes: 17 additions & 2 deletions pkg/github/issues.go
Original file line number Diff line number Diff line change
Expand Up @@ -872,7 +872,15 @@ func CreateIssue(getClient GetClientFn, t translations.TranslationHelperFunc) (t
return mcp.NewToolResultError(fmt.Sprintf("failed to create issue: %s", string(body))), nil
}

r, err := json.Marshal(issue)
// Return minimal response with just essential information
minimalResponse := MinimalIssueResponse{
URL: issue.GetHTMLURL(),
Number: issue.GetNumber(),
State: issue.GetState(),
Title: issue.GetTitle(),
}

r, err := json.Marshal(minimalResponse)
if err != nil {
return nil, fmt.Errorf("failed to marshal response: %w", err)
}
Expand Down Expand Up @@ -1242,7 +1250,14 @@ func UpdateIssue(getClient GetClientFn, t translations.TranslationHelperFunc) (t
return mcp.NewToolResultError(fmt.Sprintf("failed to update issue: %s", string(body))), nil
}

r, err := json.Marshal(updatedIssue)
// Return minimal response with just essential information
minimalResponse := MinimalUpdateResponse{
URL: updatedIssue.GetHTMLURL(),
Updated: true,
Message: "Issue updated successfully",
}

r, err := json.Marshal(minimalResponse)
if err != nil {
return nil, fmt.Errorf("failed to marshal response: %w", err)
}
Expand Down
78 changes: 11 additions & 67 deletions pkg/github/issues_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -712,39 +712,15 @@ func Test_CreateIssue(t *testing.T) {
require.NoError(t, err)
textContent := getTextResult(t, result)

// Unmarshal and verify the result
var returnedIssue github.Issue
// Unmarshal and verify the minimal result
var returnedIssue MinimalIssueResponse
err = json.Unmarshal([]byte(textContent.Text), &returnedIssue)
require.NoError(t, err)

assert.Equal(t, *tc.expectedIssue.Number, *returnedIssue.Number)
assert.Equal(t, *tc.expectedIssue.Title, *returnedIssue.Title)
assert.Equal(t, *tc.expectedIssue.State, *returnedIssue.State)
assert.Equal(t, *tc.expectedIssue.HTMLURL, *returnedIssue.HTMLURL)

if tc.expectedIssue.Body != nil {
assert.Equal(t, *tc.expectedIssue.Body, *returnedIssue.Body)
}

if tc.expectedIssue.Type != nil {
assert.Equal(t, *tc.expectedIssue.Type.Name, *returnedIssue.Type.Name)
}

// Check assignees if expected
if len(tc.expectedIssue.Assignees) > 0 {
assert.Equal(t, len(tc.expectedIssue.Assignees), len(returnedIssue.Assignees))
for i, assignee := range returnedIssue.Assignees {
assert.Equal(t, *tc.expectedIssue.Assignees[i].Login, *assignee.Login)
}
}

// Check labels if expected
if len(tc.expectedIssue.Labels) > 0 {
assert.Equal(t, len(tc.expectedIssue.Labels), len(returnedIssue.Labels))
for i, label := range returnedIssue.Labels {
assert.Equal(t, *tc.expectedIssue.Labels[i].Name, *label.Name)
}
}
assert.Equal(t, tc.expectedIssue.GetNumber(), returnedIssue.Number)
assert.Equal(t, tc.expectedIssue.GetTitle(), returnedIssue.Title)
assert.Equal(t, tc.expectedIssue.GetState(), returnedIssue.State)
assert.Equal(t, tc.expectedIssue.GetHTMLURL(), returnedIssue.URL)
})
}
}
Expand Down Expand Up @@ -1233,45 +1209,13 @@ func Test_UpdateIssue(t *testing.T) {
// Parse the result and get the text content if no error
textContent := getTextResult(t, result)

// Unmarshal and verify the result
var returnedIssue github.Issue
err = json.Unmarshal([]byte(textContent.Text), &returnedIssue)
// Unmarshal and verify the minimal result
var updateResp MinimalUpdateResponse
err = json.Unmarshal([]byte(textContent.Text), &updateResp)
require.NoError(t, err)

assert.Equal(t, *tc.expectedIssue.Number, *returnedIssue.Number)
assert.Equal(t, *tc.expectedIssue.Title, *returnedIssue.Title)
assert.Equal(t, *tc.expectedIssue.State, *returnedIssue.State)
assert.Equal(t, *tc.expectedIssue.HTMLURL, *returnedIssue.HTMLURL)

if tc.expectedIssue.Body != nil {
assert.Equal(t, *tc.expectedIssue.Body, *returnedIssue.Body)
}

if tc.expectedIssue.Type != nil {
assert.Equal(t, *tc.expectedIssue.Type.Name, *returnedIssue.Type.Name)
}

// Check assignees if expected
if len(tc.expectedIssue.Assignees) > 0 {
assert.Len(t, returnedIssue.Assignees, len(tc.expectedIssue.Assignees))
for i, assignee := range returnedIssue.Assignees {
assert.Equal(t, *tc.expectedIssue.Assignees[i].Login, *assignee.Login)
}
}

// Check labels if expected
if len(tc.expectedIssue.Labels) > 0 {
assert.Len(t, returnedIssue.Labels, len(tc.expectedIssue.Labels))
for i, label := range returnedIssue.Labels {
assert.Equal(t, *tc.expectedIssue.Labels[i].Name, *label.Name)
}
}

// Check milestone if expected
if tc.expectedIssue.Milestone != nil {
assert.NotNil(t, returnedIssue.Milestone)
assert.Equal(t, *tc.expectedIssue.Milestone.Number, *returnedIssue.Milestone.Number)
}
assert.Equal(t, tc.expectedIssue.GetHTMLURL(), updateResp.URL)
assert.Equal(t, true, updateResp.Updated)
})
}
}
Expand Down
Loading
Loading