Skip to content

Commit d1b6c32

Browse files
committed
revert GraphQL
1 parent db04b21 commit d1b6c32

File tree

3 files changed

+20
-84
lines changed

3 files changed

+20
-84
lines changed

pkg/github/repositories.go

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import (
1616
"github.com/google/go-github/v73/github"
1717
"github.com/mark3labs/mcp-go/mcp"
1818
"github.com/mark3labs/mcp-go/server"
19-
"github.com/shurcooL/githubv4"
2019
)
2120

2221
func GetCommit(getClient GetClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler server.ToolHandlerFunc) {
@@ -447,7 +446,7 @@ func CreateRepository(getClient GetClientFn, t translations.TranslationHelperFun
447446
}
448447

449448
// GetFileContents creates a tool to get the contents of a file or directory from a GitHub repository.
450-
func GetFileContents(getClient GetClientFn, getRawClient raw.GetRawClientFn, getGQLClient GetGQLClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler server.ToolHandlerFunc) {
449+
func GetFileContents(getClient GetClientFn, getRawClient raw.GetRawClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler server.ToolHandlerFunc) {
451450
return mcp.NewTool("get_file_contents",
452451
mcp.WithDescription(t("TOOL_GET_FILE_CONTENTS_DESCRIPTION", "Get the contents of a file or directory from a GitHub repository")),
453452
mcp.WithToolAnnotation(mcp.ToolAnnotation{
@@ -508,14 +507,24 @@ func GetFileContents(getClient GetClientFn, getRawClient raw.GetRawClientFn, get
508507
// If the path is (most likely) not to be a directory, we will
509508
// first try to get the raw content from the GitHub raw content API.
510509
if path != "" && !strings.HasSuffix(path, "/") {
511-
gqlClient, err := getGQLClient(ctx)
512-
if err != nil {
513-
return mcp.NewToolResultError("failed to get GitHub GraphQL client"), nil
510+
// First, get file info from Contents API to retrieve SHA
511+
var fileSHA string
512+
opts := &github.RepositoryContentGetOptions{Ref: ref}
513+
fileContent, _, respContents, err := client.Repositories.GetContents(ctx, owner, repo, path, opts)
514+
if respContents != nil {
515+
defer func() { _ = respContents.Body.Close() }()
514516
}
515-
fileSHA, err := getFileSHA(ctx, gqlClient, owner, repo, path, rawOpts)
516517
if err != nil {
517-
return mcp.NewToolResultError(fmt.Sprintf("failed to get file SHA: %s", err)), nil
518+
return ghErrors.NewGitHubAPIErrorResponse(ctx,
519+
"failed to get file SHA",
520+
respContents,
521+
err,
522+
), nil
523+
}
524+
if fileContent == nil || fileContent.SHA == nil {
525+
return mcp.NewToolResultError("file content SHA is nil"), nil
518526
}
527+
fileSHA = *fileContent.SHA
519528

520529
rawClient, err := getRawClient(ctx)
521530
if err != nil {
@@ -1382,34 +1391,3 @@ func resolveGitReference(ctx context.Context, githubClient *github.Client, owner
13821391
// Use provided ref, or it will be empty which defaults to the default branch
13831392
return &raw.ContentOpts{Ref: ref, SHA: sha}, nil
13841393
}
1385-
1386-
// getFileSHA retrieves the Blob SHA of a file.
1387-
func getFileSHA(ctx context.Context, client *githubv4.Client, owner, repo, path string, opts *raw.ContentOpts) (string, error) {
1388-
var query struct {
1389-
Repository struct {
1390-
Object struct {
1391-
Blob struct {
1392-
OID string
1393-
} `graphql:"... on Blob"`
1394-
} `graphql:"object(expression: $expression)"`
1395-
} `graphql:"repository(owner: $owner, name: $repo)"`
1396-
}
1397-
1398-
// Prepare the expression based on the provided options
1399-
expression := githubv4.String(path)
1400-
if opts != nil && opts.SHA != "" {
1401-
expression = githubv4.String(fmt.Sprintf("%s:%s", opts.SHA, path))
1402-
} else if opts != nil && opts.Ref != "" {
1403-
expression = githubv4.String(fmt.Sprintf("%s:%s", opts.Ref, path))
1404-
}
1405-
1406-
variables := map[string]interface{}{
1407-
"owner": githubv4.String(owner),
1408-
"repo": githubv4.String(repo),
1409-
"expression": expression,
1410-
}
1411-
if err := client.Query(ctx, &query, variables); err != nil {
1412-
return "", fmt.Errorf("failed to query file SHA: %w", err)
1413-
}
1414-
return query.Repository.Object.Blob.OID, nil
1415-
}

pkg/github/repositories_test.go

Lines changed: 3 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -9,59 +9,21 @@ import (
99
"testing"
1010
"time"
1111

12-
"github.com/github/github-mcp-server/internal/githubv4mock"
1312
"github.com/github/github-mcp-server/internal/toolsnaps"
1413
"github.com/github/github-mcp-server/pkg/raw"
1514
"github.com/github/github-mcp-server/pkg/translations"
1615
"github.com/google/go-github/v73/github"
1716
"github.com/mark3labs/mcp-go/mcp"
1817
"github.com/migueleliasweb/go-github-mock/src/mock"
19-
"github.com/shurcooL/githubv4"
2018
"github.com/stretchr/testify/assert"
2119
"github.com/stretchr/testify/require"
2220
)
2321

24-
func mockGQLClientFileSHA(owner, repo, expression, expectedSHA string) *githubv4.Client {
25-
// Create the query structure that matches getFileSHA function
26-
query := struct {
27-
Repository struct {
28-
Object struct {
29-
Blob struct {
30-
OID string
31-
} `graphql:"... on Blob"`
32-
} `graphql:"object(expression: $expression)"`
33-
} `graphql:"repository(owner: $owner, name: $repo)"`
34-
}{}
35-
36-
// Match any variables, we don't care about the exact values in this test
37-
variables := map[string]interface{}{
38-
"owner": githubv4.String(owner),
39-
"repo": githubv4.String(repo),
40-
"expression": githubv4.String(expression),
41-
}
42-
43-
// Create the mock response with the expected SHA
44-
mockResponse := githubv4mock.DataResponse(map[string]any{
45-
"repository": map[string]any{
46-
"object": map[string]any{
47-
"oid": expectedSHA,
48-
},
49-
},
50-
})
51-
52-
// Create the matcher and mock client
53-
matcher := githubv4mock.NewQueryMatcher(query, variables, mockResponse)
54-
httpClient := githubv4mock.NewMockedHTTPClient(matcher)
55-
56-
return githubv4.NewClient(httpClient)
57-
}
58-
5922
func Test_GetFileContents(t *testing.T) {
6023
// Verify tool definition once
6124
mockClient := github.NewClient(nil)
6225
mockRawClient := raw.NewClient(mockClient, &url.URL{Scheme: "https", Host: "raw.githubusercontent.com", Path: "/"})
63-
mockGQLClient := githubv4.NewClient(nil)
64-
tool, _ := GetFileContents(stubGetClientFn(mockClient), stubGetRawClientFn(mockRawClient), stubGetGQLClientFn(mockGQLClient), translations.NullTranslationHelper)
26+
tool, _ := GetFileContents(stubGetClientFn(mockClient), stubGetRawClientFn(mockRawClient), translations.NullTranslationHelper)
6527
require.NoError(t, toolsnaps.Test(tool.Name, tool))
6628

6729
assert.Equal(t, "get_file_contents", tool.Name)
@@ -94,10 +56,10 @@ func Test_GetFileContents(t *testing.T) {
9456
HTMLURL: github.Ptr("https://github.com/owner/repo/tree/main/src"),
9557
},
9658
}
59+
9760
tests := []struct {
9861
name string
9962
mockedClient *http.Client
100-
mockGQLClient *githubv4.Client
10163
requestArgs map[string]interface{}
10264
expectError bool
10365
expectedResult interface{}
@@ -136,7 +98,6 @@ func Test_GetFileContents(t *testing.T) {
13698
}),
13799
),
138100
),
139-
mockGQLClient: mockGQLClientFileSHA("owner", "repo", "refs/heads/main:README.md", "abc123"),
140101
requestArgs: map[string]interface{}{
141102
"owner": "owner",
142103
"repo": "repo",
@@ -182,7 +143,6 @@ func Test_GetFileContents(t *testing.T) {
182143
}),
183144
),
184145
),
185-
mockGQLClient: mockGQLClientFileSHA("owner", "repo", "refs/heads/main:test.png", "def456"),
186146
requestArgs: map[string]interface{}{
187147
"owner": "owner",
188148
"repo": "repo",
@@ -228,7 +188,6 @@ func Test_GetFileContents(t *testing.T) {
228188
),
229189
),
230190
),
231-
mockGQLClient: nil,
232191
requestArgs: map[string]interface{}{
233192
"owner": "owner",
234193
"repo": "repo",
@@ -262,7 +221,6 @@ func Test_GetFileContents(t *testing.T) {
262221
}),
263222
),
264223
),
265-
mockGQLClient: mockGQLClientFileSHA("owner", "repo", "refs/heads/main:nonexistent.md", ""),
266224
requestArgs: map[string]interface{}{
267225
"owner": "owner",
268226
"repo": "repo",
@@ -279,7 +237,7 @@ func Test_GetFileContents(t *testing.T) {
279237
// Setup client with mock
280238
client := github.NewClient(tc.mockedClient)
281239
mockRawClient := raw.NewClient(client, &url.URL{Scheme: "https", Host: "raw.example.com", Path: "/"})
282-
_, handler := GetFileContents(stubGetClientFn(client), stubGetRawClientFn(mockRawClient), stubGetGQLClientFn(tc.mockGQLClient), translations.NullTranslationHelper)
240+
_, handler := GetFileContents(stubGetClientFn(client), stubGetRawClientFn(mockRawClient), translations.NullTranslationHelper)
283241

284242
// Create call request
285243
request := createMCPRequest(tc.requestArgs)

pkg/github/tools.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG
2424
repos := toolsets.NewToolset("repos", "GitHub Repository related tools").
2525
AddReadTools(
2626
toolsets.NewServerTool(SearchRepositories(getClient, t)),
27-
toolsets.NewServerTool(GetFileContents(getClient, getRawClient, getGQLClient, t)),
27+
toolsets.NewServerTool(GetFileContents(getClient, getRawClient, t)),
2828
toolsets.NewServerTool(ListCommits(getClient, t)),
2929
toolsets.NewServerTool(SearchCode(getClient, t)),
3030
toolsets.NewServerTool(GetCommit(getClient, t)),

0 commit comments

Comments
 (0)