Skip to content

Commit eaf411c

Browse files
CopilotomgitsadsLuluBeatson
authored
Migrate git toolset to modelcontextprotocol/go-sdk (#1432)
* Initial plan * Migrate git toolset to modelcontextprotocol/go-sdk - Remove //go:build ignore tag from git.go - Update imports to use modelcontextprotocol/go-sdk - Convert GetRepositoryTree tool schema to jsonschema format - Update handler signature to use new generics pattern - Update parameter extraction to use args map - Replace mcp.NewToolResult* with utils package helpers - Create dedicated git_test.go with updated test patterns - Update toolsnaps for get_repository_tree Related to #1428 Co-authored-by: omgitsads <4619+omgitsads@users.noreply.github.com> * re-add git toolset --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: omgitsads <4619+omgitsads@users.noreply.github.com> Co-authored-by: LuluBeatson <lulubeatson@github.com>
1 parent ef60ef7 commit eaf411c

File tree

5 files changed

+281
-71
lines changed

5 files changed

+281
-71
lines changed
Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,38 @@
11
{
22
"annotations": {
3-
"title": "Get repository tree",
4-
"readOnlyHint": true
3+
"readOnlyHint": true,
4+
"title": "Get repository tree"
55
},
66
"description": "Get the tree structure (files and directories) of a GitHub repository at a specific ref or SHA",
77
"inputSchema": {
8+
"type": "object",
9+
"required": [
10+
"owner",
11+
"repo"
12+
],
813
"properties": {
914
"owner": {
10-
"description": "Repository owner (username or organization)",
11-
"type": "string"
15+
"type": "string",
16+
"description": "Repository owner (username or organization)"
1217
},
1318
"path_filter": {
14-
"description": "Optional path prefix to filter the tree results (e.g., 'src/' to only show files in the src directory)",
15-
"type": "string"
19+
"type": "string",
20+
"description": "Optional path prefix to filter the tree results (e.g., 'src/' to only show files in the src directory)"
1621
},
1722
"recursive": {
18-
"default": false,
23+
"type": "boolean",
1924
"description": "Setting this parameter to true returns the objects or subtrees referenced by the tree. Default is false",
20-
"type": "boolean"
25+
"default": false
2126
},
2227
"repo": {
23-
"description": "Repository name",
24-
"type": "string"
28+
"type": "string",
29+
"description": "Repository name"
2530
},
2631
"tree_sha": {
27-
"description": "The SHA1 value or ref (branch or tag) name of the tree. Defaults to the repository's default branch",
28-
"type": "string"
32+
"type": "string",
33+
"description": "The SHA1 value or ref (branch or tag) name of the tree. Defaults to the repository's default branch"
2934
}
30-
},
31-
"required": [
32-
"owner",
33-
"repo"
34-
],
35-
"type": "object"
35+
}
3636
},
3737
"name": "get_repository_tree"
3838
}

pkg/github/git.go

Lines changed: 61 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
//go:build ignore
2-
31
package github
42

53
import (
@@ -10,9 +8,10 @@ import (
108

119
ghErrors "github.com/github/github-mcp-server/pkg/errors"
1210
"github.com/github/github-mcp-server/pkg/translations"
11+
"github.com/github/github-mcp-server/pkg/utils"
1312
"github.com/google/go-github/v79/github"
14-
"github.com/mark3labs/mcp-go/mcp"
15-
"github.com/mark3labs/mcp-go/server"
13+
"github.com/google/jsonschema-go/jsonschema"
14+
"github.com/modelcontextprotocol/go-sdk/mcp"
1615
)
1716

1817
// TreeEntryResponse represents a single entry in a Git tree.
@@ -38,57 +37,69 @@ type TreeResponse struct {
3837
}
3938

4039
// GetRepositoryTree creates a tool to get the tree structure of a GitHub repository.
41-
func GetRepositoryTree(getClient GetClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler server.ToolHandlerFunc) {
42-
return mcp.NewTool("get_repository_tree",
43-
mcp.WithDescription(t("TOOL_GET_REPOSITORY_TREE_DESCRIPTION", "Get the tree structure (files and directories) of a GitHub repository at a specific ref or SHA")),
44-
mcp.WithToolAnnotation(mcp.ToolAnnotation{
45-
Title: t("TOOL_GET_REPOSITORY_TREE_USER_TITLE", "Get repository tree"),
46-
ReadOnlyHint: ToBoolPtr(true),
47-
}),
48-
mcp.WithString("owner",
49-
mcp.Required(),
50-
mcp.Description("Repository owner (username or organization)"),
51-
),
52-
mcp.WithString("repo",
53-
mcp.Required(),
54-
mcp.Description("Repository name"),
55-
),
56-
mcp.WithString("tree_sha",
57-
mcp.Description("The SHA1 value or ref (branch or tag) name of the tree. Defaults to the repository's default branch"),
58-
),
59-
mcp.WithBoolean("recursive",
60-
mcp.Description("Setting this parameter to true returns the objects or subtrees referenced by the tree. Default is false"),
61-
mcp.DefaultBool(false),
62-
),
63-
mcp.WithString("path_filter",
64-
mcp.Description("Optional path prefix to filter the tree results (e.g., 'src/' to only show files in the src directory)"),
65-
),
66-
),
67-
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
68-
owner, err := RequiredParam[string](request, "owner")
40+
func GetRepositoryTree(getClient GetClientFn, t translations.TranslationHelperFunc) (mcp.Tool, mcp.ToolHandlerFor[map[string]any, any]) {
41+
tool := mcp.Tool{
42+
Name: "get_repository_tree",
43+
Description: t("TOOL_GET_REPOSITORY_TREE_DESCRIPTION", "Get the tree structure (files and directories) of a GitHub repository at a specific ref or SHA"),
44+
Annotations: &mcp.ToolAnnotations{
45+
Title: t("TOOL_GET_REPOSITORY_TREE_USER_TITLE", "Get repository tree"),
46+
ReadOnlyHint: true,
47+
},
48+
InputSchema: &jsonschema.Schema{
49+
Type: "object",
50+
Properties: map[string]*jsonschema.Schema{
51+
"owner": {
52+
Type: "string",
53+
Description: "Repository owner (username or organization)",
54+
},
55+
"repo": {
56+
Type: "string",
57+
Description: "Repository name",
58+
},
59+
"tree_sha": {
60+
Type: "string",
61+
Description: "The SHA1 value or ref (branch or tag) name of the tree. Defaults to the repository's default branch",
62+
},
63+
"recursive": {
64+
Type: "boolean",
65+
Description: "Setting this parameter to true returns the objects or subtrees referenced by the tree. Default is false",
66+
Default: json.RawMessage(`false`),
67+
},
68+
"path_filter": {
69+
Type: "string",
70+
Description: "Optional path prefix to filter the tree results (e.g., 'src/' to only show files in the src directory)",
71+
},
72+
},
73+
Required: []string{"owner", "repo"},
74+
},
75+
}
76+
77+
handler := mcp.ToolHandlerFor[map[string]any, any](
78+
func(ctx context.Context, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) {
79+
owner, err := RequiredParam[string](args, "owner")
6980
if err != nil {
70-
return mcp.NewToolResultError(err.Error()), nil
81+
return utils.NewToolResultError(err.Error()), nil, nil
7182
}
72-
repo, err := RequiredParam[string](request, "repo")
83+
repo, err := RequiredParam[string](args, "repo")
7384
if err != nil {
74-
return mcp.NewToolResultError(err.Error()), nil
85+
return utils.NewToolResultError(err.Error()), nil, nil
7586
}
76-
treeSHA, err := OptionalParam[string](request, "tree_sha")
87+
treeSHA, err := OptionalParam[string](args, "tree_sha")
7788
if err != nil {
78-
return mcp.NewToolResultError(err.Error()), nil
89+
return utils.NewToolResultError(err.Error()), nil, nil
7990
}
80-
recursive, err := OptionalBoolParamWithDefault(request, "recursive", false)
91+
recursive, err := OptionalBoolParamWithDefault(args, "recursive", false)
8192
if err != nil {
82-
return mcp.NewToolResultError(err.Error()), nil
93+
return utils.NewToolResultError(err.Error()), nil, nil
8394
}
84-
pathFilter, err := OptionalParam[string](request, "path_filter")
95+
pathFilter, err := OptionalParam[string](args, "path_filter")
8596
if err != nil {
86-
return mcp.NewToolResultError(err.Error()), nil
97+
return utils.NewToolResultError(err.Error()), nil, nil
8798
}
8899

89100
client, err := getClient(ctx)
90101
if err != nil {
91-
return mcp.NewToolResultError("failed to get GitHub client"), nil
102+
return utils.NewToolResultError("failed to get GitHub client"), nil, nil
92103
}
93104

94105
// If no tree_sha is provided, use the repository's default branch
@@ -99,7 +110,7 @@ func GetRepositoryTree(getClient GetClientFn, t translations.TranslationHelperFu
99110
"failed to get repository info",
100111
repoResp,
101112
err,
102-
), nil
113+
), nil, nil
103114
}
104115
treeSHA = *repoInfo.DefaultBranch
105116
}
@@ -111,7 +122,7 @@ func GetRepositoryTree(getClient GetClientFn, t translations.TranslationHelperFu
111122
"failed to get repository tree",
112123
resp,
113124
err,
114-
), nil
125+
), nil, nil
115126
}
116127
defer func() { _ = resp.Body.Close() }()
117128

@@ -154,9 +165,12 @@ func GetRepositoryTree(getClient GetClientFn, t translations.TranslationHelperFu
154165

155166
r, err := json.Marshal(response)
156167
if err != nil {
157-
return nil, fmt.Errorf("failed to marshal response: %w", err)
168+
return nil, nil, fmt.Errorf("failed to marshal response: %w", err)
158169
}
159170

160-
return mcp.NewToolResultText(string(r)), nil
161-
}
171+
return utils.NewToolResultText(string(r)), nil, nil
172+
},
173+
)
174+
175+
return tool, handler
162176
}

0 commit comments

Comments
 (0)