Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Migrate Repository Resources to the Go SDK#1457

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
omgitsads merged 7 commits intoomgitsads/go-sdkfromomgitsads/go-sdk-repo-resources
Nov 20, 2025
Merged
Show file tree
Hide file tree
Changes fromall 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
2 changes: 1 addition & 1 deletiongo.mod
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,7 +53,7 @@ require (
github.com/spf13/cast v1.10.0 // indirect
github.com/spf13/pflag v1.0.10
github.com/subosito/gotenv v1.6.0 // indirect
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
github.com/yosida95/uritemplate/v3 v3.0.2
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sys v0.31.0 // indirect
golang.org/x/text v0.28.0 // indirect
Expand Down
174 changes: 101 additions & 73 deletionspkg/github/repository_resource.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
package github

import (
"bytes"
"context"
"encoding/base64"
"errors"
Expand All@@ -15,107 +16,120 @@ import (
"github.com/github/github-mcp-server/pkg/raw"
"github.com/github/github-mcp-server/pkg/translations"
"github.com/google/go-github/v79/github"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
"github.com/modelcontextprotocol/go-sdk/mcp"
"github.com/yosida95/uritemplate/v3"
)

var (
repositoryResourceContentURITemplate = uritemplate.MustNew("repo://{owner}/{repo}/contents{/path*}")
repositoryResourceBranchContentURITemplate = uritemplate.MustNew("repo://{owner}/{repo}/refs/heads/{branch}/contents{/path*}")
repositoryResourceCommitContentURITemplate = uritemplate.MustNew("repo://{owner}/{repo}/sha/{sha}/contents{/path*}")
repositoryResourceTagContentURITemplate = uritemplate.MustNew("repo://{owner}/{repo}/refs/tags/{tag}/contents{/path*}")
repositoryResourcePrContentURITemplate = uritemplate.MustNew("repo://{owner}/{repo}/refs/pull/{prNumber}/head/contents{/path*}")
)

// GetRepositoryResourceContent defines the resource template and handler for getting repository content.
func GetRepositoryResourceContent(getClient GetClientFn, getRawClient raw.GetRawClientFn, t translations.TranslationHelperFunc) (mcp.ResourceTemplate, server.ResourceTemplateHandlerFunc) {
return mcp.NewResourceTemplate(
"repo://{owner}/{repo}/contents{/path*}", // Resource template
t("RESOURCE_REPOSITORY_CONTENT_DESCRIPTION", "Repository Content"),
),
RepositoryResourceContentsHandler(getClient, getRawClient)
func GetRepositoryResourceContent(getClient GetClientFn, getRawClient raw.GetRawClientFn, t translations.TranslationHelperFunc) (mcp.ResourceTemplate, mcp.ResourceHandler) {
return mcp.ResourceTemplate{
Name: "repository_content",
URITemplate: repositoryResourceContentURITemplate.Raw(), // Resource template
Description: t("RESOURCE_REPOSITORY_CONTENT_DESCRIPTION", "Repository Content"),
},
RepositoryResourceContentsHandler(getClient, getRawClient, repositoryResourceContentURITemplate)
}

// GetRepositoryResourceBranchContent defines the resource template and handler for getting repository content for a branch.
func GetRepositoryResourceBranchContent(getClient GetClientFn, getRawClient raw.GetRawClientFn, t translations.TranslationHelperFunc) (mcp.ResourceTemplate, server.ResourceTemplateHandlerFunc) {
return mcp.NewResourceTemplate(
"repo://{owner}/{repo}/refs/heads/{branch}/contents{/path*}", // Resource template
t("RESOURCE_REPOSITORY_CONTENT_BRANCH_DESCRIPTION", "Repository Content for specific branch"),
),
RepositoryResourceContentsHandler(getClient, getRawClient)
func GetRepositoryResourceBranchContent(getClient GetClientFn, getRawClient raw.GetRawClientFn, t translations.TranslationHelperFunc) (mcp.ResourceTemplate, mcp.ResourceHandler) {
return mcp.ResourceTemplate{
Name: "repository_content_branch",
URITemplate: repositoryResourceBranchContentURITemplate.Raw(), // Resource template
Description: t("RESOURCE_REPOSITORY_CONTENT_BRANCH_DESCRIPTION", "Repository Content for specific branch"),
},
RepositoryResourceContentsHandler(getClient, getRawClient, repositoryResourceBranchContentURITemplate)
}

// GetRepositoryResourceCommitContent defines the resource template and handler for getting repository content for a commit.
func GetRepositoryResourceCommitContent(getClient GetClientFn, getRawClient raw.GetRawClientFn, t translations.TranslationHelperFunc) (mcp.ResourceTemplate, server.ResourceTemplateHandlerFunc) {
return mcp.NewResourceTemplate(
"repo://{owner}/{repo}/sha/{sha}/contents{/path*}", // Resource template
t("RESOURCE_REPOSITORY_CONTENT_COMMIT_DESCRIPTION", "Repository Content for specific commit"),
),
RepositoryResourceContentsHandler(getClient, getRawClient)
func GetRepositoryResourceCommitContent(getClient GetClientFn, getRawClient raw.GetRawClientFn, t translations.TranslationHelperFunc) (mcp.ResourceTemplate, mcp.ResourceHandler) {
return mcp.ResourceTemplate{
Name: "repository_content_commit",
URITemplate: repositoryResourceCommitContentURITemplate.Raw(), // Resource template
Description: t("RESOURCE_REPOSITORY_CONTENT_COMMIT_DESCRIPTION", "Repository Content for specific commit"),
},
RepositoryResourceContentsHandler(getClient, getRawClient, repositoryResourceCommitContentURITemplate)
}

// GetRepositoryResourceTagContent defines the resource template and handler for getting repository content for a tag.
func GetRepositoryResourceTagContent(getClient GetClientFn, getRawClient raw.GetRawClientFn, t translations.TranslationHelperFunc) (mcp.ResourceTemplate, server.ResourceTemplateHandlerFunc) {
return mcp.NewResourceTemplate(
"repo://{owner}/{repo}/refs/tags/{tag}/contents{/path*}", // Resource template
t("RESOURCE_REPOSITORY_CONTENT_TAG_DESCRIPTION", "Repository Content for specific tag"),
),
RepositoryResourceContentsHandler(getClient, getRawClient)
func GetRepositoryResourceTagContent(getClient GetClientFn, getRawClient raw.GetRawClientFn, t translations.TranslationHelperFunc) (mcp.ResourceTemplate, mcp.ResourceHandler) {
return mcp.ResourceTemplate{
Name: "repository_content_tag",
URITemplate: repositoryResourceTagContentURITemplate.Raw(), // Resource template
Description: t("RESOURCE_REPOSITORY_CONTENT_TAG_DESCRIPTION", "Repository Content for specific tag"),
},
RepositoryResourceContentsHandler(getClient, getRawClient, repositoryResourceTagContentURITemplate)
}

// GetRepositoryResourcePrContent defines the resource template and handler for getting repository content for a pull request.
func GetRepositoryResourcePrContent(getClient GetClientFn, getRawClient raw.GetRawClientFn, t translations.TranslationHelperFunc) (mcp.ResourceTemplate, server.ResourceTemplateHandlerFunc) {
return mcp.NewResourceTemplate(
"repo://{owner}/{repo}/refs/pull/{prNumber}/head/contents{/path*}", // Resource template
t("RESOURCE_REPOSITORY_CONTENT_PR_DESCRIPTION", "Repository Content for specific pull request"),
),
RepositoryResourceContentsHandler(getClient, getRawClient)
func GetRepositoryResourcePrContent(getClient GetClientFn, getRawClient raw.GetRawClientFn, t translations.TranslationHelperFunc) (mcp.ResourceTemplate, mcp.ResourceHandler) {
return mcp.ResourceTemplate{
Name: "repository_content_pr",
URITemplate: repositoryResourcePrContentURITemplate.Raw(), // Resource template
Description: t("RESOURCE_REPOSITORY_CONTENT_PR_DESCRIPTION", "Repository Content for specific pull request"),
},
RepositoryResourceContentsHandler(getClient, getRawClient, repositoryResourcePrContentURITemplate)
}

// RepositoryResourceContentsHandler returns a handler function for repository content requests.
func RepositoryResourceContentsHandler(getClient GetClientFn, getRawClient raw.GetRawClientFn) func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
return func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
// the matcher will give []string with one element
// https://github.com/mark3labs/mcp-go/pull/54
o, ok := request.Params.Arguments["owner"].([]string)
if !ok || len(o) == 0 {
func RepositoryResourceContentsHandler(getClient GetClientFn, getRawClient raw.GetRawClientFn, resourceURITemplate *uritemplate.Template) mcp.ResourceHandler {
return func(ctx context.Context, request *mcp.ReadResourceRequest) (*mcp.ReadResourceResult, error) {
// Match the URI to extract parameters
uriValues := resourceURITemplate.Match(request.Params.URI)
if uriValues == nil {
return nil, fmt.Errorf("failed to match URI: %s", request.Params.URI)
}

// Extract required vars
owner := uriValues.Get("owner").String()
repo := uriValues.Get("repo").String()

if owner == "" {
return nil, errors.New("owner is required")
}
owner := o[0]

r, ok := request.Params.Arguments["repo"].([]string)
if !ok || len(r) == 0 {
if repo == "" {
return nil, errors.New("repo is required")
}
repo := r[0]

// path should be a joined list of the path parts
path := ""
p, ok := request.Params.Arguments["path"].([]string)
if ok {
path = strings.Join(p, "/")
}
path := uriValues.Get("path").String()

opts := &github.RepositoryContentGetOptions{}
rawOpts := &raw.ContentOpts{}

sha, ok:=request.Params.Arguments["sha"].([]string)
ifok && len(sha) > 0 {
opts.Ref = sha[0]
rawOpts.SHA = sha[0]
sha:=uriValues.Get("sha").String()
if sha != "" {
opts.Ref = sha
rawOpts.SHA = sha
}

branch, ok:=request.Params.Arguments["branch"].([]string)
ifok && len(branch) > 0 {
opts.Ref = "refs/heads/" + branch[0]
rawOpts.Ref = "refs/heads/" + branch[0]
branch:=uriValues.Get("branch").String()
if branch != "" {
opts.Ref = "refs/heads/" + branch
rawOpts.Ref = "refs/heads/" + branch
}

tag, ok:=request.Params.Arguments["tag"].([]string)
ifok && len(tag) > 0 {
opts.Ref = "refs/tags/" + tag[0]
rawOpts.Ref = "refs/tags/" + tag[0]
tag:=uriValues.Get("tag").String()
if tag != "" {
opts.Ref = "refs/tags/" + tag
rawOpts.Ref = "refs/tags/" + tag
}
prNumber, ok := request.Params.Arguments["prNumber"].([]string)
if ok && len(prNumber) > 0 {

prNumber := uriValues.Get("prNumber").String()
if prNumber != "" {
// fetch the PR from the API to get the latest commit and use SHA
githubClient, err := getClient(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get GitHub client: %w", err)
}
prNum, err := strconv.Atoi(prNumber[0])
prNum, err := strconv.Atoi(prNumber)
if err != nil {
return nil, fmt.Errorf("invalid pull request number: %w", err)
}
Expand DownExpand Up@@ -161,19 +175,33 @@ func RepositoryResourceContentsHandler(getClient GetClientFn, getRawClient raw.G

switch {
case strings.HasPrefix(mimeType, "text"), strings.HasPrefix(mimeType, "application"):
return []mcp.ResourceContents{
mcp.TextResourceContents{
URI: request.Params.URI,
MIMEType: mimeType,
Text: string(content),
return &mcp.ReadResourceResult{
Contents: []*mcp.ResourceContents{
{
URI: request.Params.URI,
MIMEType: mimeType,
Text: string(content),
},
},
}, nil
default:
return []mcp.ResourceContents{
mcp.BlobResourceContents{
URI: request.Params.URI,
MIMEType: mimeType,
Blob: base64.StdEncoding.EncodeToString(content),
var buf bytes.Buffer
base64Encoder := base64.NewEncoder(base64.StdEncoding, &buf)
_, err := base64Encoder.Write(content)
if err != nil {
return nil, fmt.Errorf("failed to base64 encode content: %w", err)
}
if err := base64Encoder.Close(); err != nil {
return nil, fmt.Errorf("failed to close base64 encoder: %w", err)
}

return &mcp.ReadResourceResult{
Contents: []*mcp.ResourceContents{
{
URI: request.Params.URI,
MIMEType: mimeType,
Blob: buf.Bytes(),
},
},
}, nil
}
Expand Down
Loading
Loading

[8]ページ先頭

©2009-2025 Movatter.jp