Skip to content

Commit 24c2868

Browse files
committed
feat: Add support for git tag operations
Add git tag functionality including: - List repository tags - Get tag details - Support for tag-based content access This enables basic read-only tag management through the MCP server API.
1 parent 4e26dce commit 24c2868

File tree

3 files changed

+400
-0
lines changed

3 files changed

+400
-0
lines changed

pkg/github/repositories.go

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,3 +796,147 @@ func PushFiles(getClient GetClientFn, t translations.TranslationHelperFunc) (too
796796
return mcp.NewToolResultText(string(r)), nil
797797
}
798798
}
799+
800+
// ListTags creates a tool to list tags in a GitHub repository.
801+
func ListTags(getClient GetClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler server.ToolHandlerFunc) {
802+
return mcp.NewTool("list_tags",
803+
mcp.WithDescription(t("TOOL_LIST_TAGS_DESCRIPTION", "List tags in a GitHub repository")),
804+
mcp.WithToolAnnotation(mcp.ToolAnnotation{
805+
Title: t("TOOL_LIST_TAGS_USER_TITLE", "List tags"),
806+
ReadOnlyHint: true,
807+
}),
808+
mcp.WithString("owner",
809+
mcp.Required(),
810+
mcp.Description("Repository owner"),
811+
),
812+
mcp.WithString("repo",
813+
mcp.Required(),
814+
mcp.Description("Repository name"),
815+
),
816+
WithPagination(),
817+
),
818+
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
819+
owner, err := requiredParam[string](request, "owner")
820+
if err != nil {
821+
return mcp.NewToolResultError(err.Error()), nil
822+
}
823+
repo, err := requiredParam[string](request, "repo")
824+
if err != nil {
825+
return mcp.NewToolResultError(err.Error()), nil
826+
}
827+
pagination, err := OptionalPaginationParams(request)
828+
if err != nil {
829+
return mcp.NewToolResultError(err.Error()), nil
830+
}
831+
832+
opts := &github.ListOptions{
833+
Page: pagination.page,
834+
PerPage: pagination.perPage,
835+
}
836+
837+
client, err := getClient(ctx)
838+
if err != nil {
839+
return nil, fmt.Errorf("failed to get GitHub client: %w", err)
840+
}
841+
842+
tags, resp, err := client.Repositories.ListTags(ctx, owner, repo, opts)
843+
if err != nil {
844+
return nil, fmt.Errorf("failed to list tags: %w", err)
845+
}
846+
defer func() { _ = resp.Body.Close() }()
847+
848+
if resp.StatusCode != http.StatusOK {
849+
body, err := io.ReadAll(resp.Body)
850+
if err != nil {
851+
return nil, fmt.Errorf("failed to read response body: %w", err)
852+
}
853+
return mcp.NewToolResultError(fmt.Sprintf("failed to list tags: %s", string(body))), nil
854+
}
855+
856+
r, err := json.Marshal(tags)
857+
if err != nil {
858+
return nil, fmt.Errorf("failed to marshal response: %w", err)
859+
}
860+
861+
return mcp.NewToolResultText(string(r)), nil
862+
}
863+
}
864+
865+
// GetTag creates a tool to get details about a specific tag in a GitHub repository.
866+
func GetTag(getClient GetClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler server.ToolHandlerFunc) {
867+
return mcp.NewTool("get_tag",
868+
mcp.WithDescription(t("TOOL_GET_TAG_DESCRIPTION", "Get details about a specific tag in a GitHub repository")),
869+
mcp.WithToolAnnotation(mcp.ToolAnnotation{
870+
Title: t("TOOL_GET_TAG_USER_TITLE", "Get tag details"),
871+
ReadOnlyHint: true,
872+
}),
873+
mcp.WithString("owner",
874+
mcp.Required(),
875+
mcp.Description("Repository owner"),
876+
),
877+
mcp.WithString("repo",
878+
mcp.Required(),
879+
mcp.Description("Repository name"),
880+
),
881+
mcp.WithString("tag",
882+
mcp.Required(),
883+
mcp.Description("Tag name"),
884+
),
885+
),
886+
func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
887+
owner, err := requiredParam[string](request, "owner")
888+
if err != nil {
889+
return mcp.NewToolResultError(err.Error()), nil
890+
}
891+
repo, err := requiredParam[string](request, "repo")
892+
if err != nil {
893+
return mcp.NewToolResultError(err.Error()), nil
894+
}
895+
tag, err := requiredParam[string](request, "tag")
896+
if err != nil {
897+
return mcp.NewToolResultError(err.Error()), nil
898+
}
899+
900+
client, err := getClient(ctx)
901+
if err != nil {
902+
return nil, fmt.Errorf("failed to get GitHub client: %w", err)
903+
}
904+
905+
// First get the tag reference
906+
ref, resp, err := client.Git.GetRef(ctx, owner, repo, "refs/tags/"+tag)
907+
if err != nil {
908+
return nil, fmt.Errorf("failed to get tag reference: %w", err)
909+
}
910+
defer func() { _ = resp.Body.Close() }()
911+
912+
if resp.StatusCode != http.StatusOK {
913+
body, err := io.ReadAll(resp.Body)
914+
if err != nil {
915+
return nil, fmt.Errorf("failed to read response body: %w", err)
916+
}
917+
return mcp.NewToolResultError(fmt.Sprintf("failed to get tag reference: %s", string(body))), nil
918+
}
919+
920+
// Then get the tag object
921+
tagObj, resp, err := client.Git.GetTag(ctx, owner, repo, *ref.Object.SHA)
922+
if err != nil {
923+
return nil, fmt.Errorf("failed to get tag object: %w", err)
924+
}
925+
defer func() { _ = resp.Body.Close() }()
926+
927+
if resp.StatusCode != http.StatusOK {
928+
body, err := io.ReadAll(resp.Body)
929+
if err != nil {
930+
return nil, fmt.Errorf("failed to read response body: %w", err)
931+
}
932+
return mcp.NewToolResultError(fmt.Sprintf("failed to get tag object: %s", string(body))), nil
933+
}
934+
935+
r, err := json.Marshal(tagObj)
936+
if err != nil {
937+
return nil, fmt.Errorf("failed to marshal response: %w", err)
938+
}
939+
940+
return mcp.NewToolResultText(string(r)), nil
941+
}
942+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy