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

Commit39ff840

Browse files
committed
add experimental get_latest_version tool
1 parent973fb5d commit39ff840

File tree

3 files changed

+175
-0
lines changed

3 files changed

+175
-0
lines changed

‎README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,12 @@ export GITHUB_MCP_TOOL_ADD_ISSUE_COMMENT_DESCRIPTION="an alternative description
382382
-`state`: Alert state (string, optional)
383383
-`severity`: Alert severity (string, optional)
384384

385+
###Version
386+
387+
-**get_latest_version** - Get the latest version of the GitHub MCP server to see if you are up to date
388+
389+
- No parameters required for this tool
390+
385391
##Resources
386392

387393
###Repository Content

‎pkg/github/server.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"fmt"
88
"io"
99
"net/http"
10+
"time"
1011

1112
"github.com/github/github-mcp-server/pkg/translations"
1213
"github.com/google/go-github/v69/github"
@@ -77,6 +78,10 @@ func NewServer(client *github.Client, version string, readOnly bool, t translati
7778
// Add GitHub tools - Code Scanning
7879
s.AddTool(getCodeScanningAlert(client,t))
7980
s.AddTool(listCodeScanningAlerts(client,t))
81+
82+
// Add GitHub tools - latest version
83+
s.AddTool(getLatestVersion(client,version,t))
84+
8085
returns
8186
}
8287

@@ -112,6 +117,54 @@ func getMe(client *github.Client, t translations.TranslationHelperFunc) (tool mc
112117
}
113118
}
114119

120+
// getLatestVersion creates a tool to get the latest version of the server.
121+
// getMe creates a tool to get details of the authenticated user.
122+
funcgetLatestVersion(client*github.Client,currentVersionstring,t translations.TranslationHelperFunc) (tool mcp.Tool,handler server.ToolHandlerFunc) {
123+
returnmcp.NewTool("get_latest_version",
124+
mcp.WithDescription(t("TOOL_GET_ME_DESCRIPTION","Checks the latest available version of the GitHub MCP server to see if it is up to date.")),
125+
mcp.WithString("reason",
126+
mcp.Description("Optional: reason the session was created"),
127+
),
128+
),
129+
func(ctx context.Context,_ mcp.CallToolRequest) (*mcp.CallToolResult,error) {
130+
// Get the latest release from GitHub API
131+
release,resp,err:=client.Repositories.GetLatestRelease(ctx,"github","github-mcp-server")
132+
iferr!=nil {
133+
returnnil,fmt.Errorf("failed to get latest release: %w",err)
134+
}
135+
deferfunc() {_=resp.Body.Close() }()
136+
137+
ifresp.StatusCode!=http.StatusOK {
138+
body,err:=io.ReadAll(resp.Body)
139+
iferr!=nil {
140+
returnnil,fmt.Errorf("failed to read response body: %w",err)
141+
}
142+
returnmcp.NewToolResultError(fmt.Sprintf("failed to get latest release: %s",string(body))),nil
143+
}
144+
145+
latestVersion:=release.GetTagName()
146+
iflatestVersion=="" {
147+
latestVersion=release.GetName()
148+
}
149+
150+
// Compare versions and create response
151+
result:=map[string]interface{}{
152+
"current_version":currentVersion,
153+
"latest_version":latestVersion,
154+
"up_to_date":currentVersion==latestVersion,
155+
"release_url":release.GetHTMLURL(),
156+
"published_at":release.GetPublishedAt().Format(time.RFC3339),
157+
}
158+
159+
r,err:=json.Marshal(result)
160+
iferr!=nil {
161+
returnnil,fmt.Errorf("failed to marshal result: %w",err)
162+
}
163+
164+
returnmcp.NewToolResultText(string(r)),nil
165+
}
166+
}
167+
115168
// isAcceptedError checks if the error is an accepted error.
116169
funcisAcceptedError(errerror)bool {
117170
varacceptedError*github.AcceptedError

‎pkg/github/server_test.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,3 +634,119 @@ func TestOptionalPaginationParams(t *testing.T) {
634634
})
635635
}
636636
}
637+
638+
funcTest_GetLatestVersion(t*testing.T) {
639+
// Verify tool definition
640+
mockClient:=github.NewClient(nil)
641+
tool,_:=getLatestVersion(mockClient,"v1.0.0",translations.NullTranslationHelper)
642+
643+
assert.Equal(t,"get_latest_version",tool.Name)
644+
assert.NotEmpty(t,tool.Description)
645+
646+
// Setup mock release response
647+
mockRelease:=&github.RepositoryRelease{
648+
TagName:github.Ptr("v1.1.0"),
649+
Name:github.Ptr("Release v1.1.0"),
650+
HTMLURL:github.Ptr("https://github.com/github/github-mcp-server/releases/tag/v1.1.0"),
651+
PublishedAt:&github.Timestamp{Time:time.Now().Add(-24*time.Hour)},
652+
}
653+
654+
tests:= []struct {
655+
namestring
656+
mockedClient*http.Client
657+
currentVersionstring
658+
expectErrorbool
659+
expectedResultmap[string]interface{}
660+
expectedErrMsgstring
661+
}{
662+
{
663+
name:"successful get latest version - up to date",
664+
mockedClient:mock.NewMockedHTTPClient(
665+
mock.WithRequestMatchHandler(
666+
mock.GetReposReleasesLatestByOwnerByRepo,
667+
mockResponse(t,http.StatusOK,mockRelease),
668+
),
669+
),
670+
currentVersion:"v1.1.0",
671+
expectError:false,
672+
expectedResult:map[string]interface{}{
673+
"current_version":"v1.1.0",
674+
"latest_version":"v1.1.0",
675+
"up_to_date":true,
676+
"release_url":"https://github.com/github/github-mcp-server/releases/tag/v1.1.0",
677+
// We can't test exact published_at since it's dynamic
678+
},
679+
},
680+
{
681+
name:"successful get latest version - outdated",
682+
mockedClient:mock.NewMockedHTTPClient(
683+
mock.WithRequestMatchHandler(
684+
mock.GetReposReleasesLatestByOwnerByRepo,
685+
mockResponse(t,http.StatusOK,mockRelease),
686+
),
687+
),
688+
currentVersion:"v1.0.0",
689+
expectError:false,
690+
expectedResult:map[string]interface{}{
691+
"current_version":"v1.0.0",
692+
"latest_version":"v1.1.0",
693+
"up_to_date":false,
694+
"release_url":"https://github.com/github/github-mcp-server/releases/tag/v1.1.0",
695+
// We can't test exact published_at since it's dynamic
696+
},
697+
},
698+
{
699+
name:"API request fails",
700+
mockedClient:mock.NewMockedHTTPClient(
701+
mock.WithRequestMatchHandler(
702+
mock.GetReposReleasesLatestByOwnerByRepo,
703+
http.HandlerFunc(func(w http.ResponseWriter,_*http.Request) {
704+
w.WriteHeader(http.StatusNotFound)
705+
_,_=w.Write([]byte(`{"message": "Not Found"}`))
706+
}),
707+
),
708+
),
709+
currentVersion:"v1.0.0",
710+
expectError:true,
711+
expectedErrMsg:"failed to get latest release",
712+
},
713+
}
714+
715+
for_,tc:=rangetests {
716+
t.Run(tc.name,func(t*testing.T) {
717+
// Setup client with mock
718+
client:=github.NewClient(tc.mockedClient)
719+
_,handler:=getLatestVersion(client,tc.currentVersion,translations.NullTranslationHelper)
720+
721+
// Create call request with empty parameters (none needed for this API)
722+
request:=createMCPRequest(map[string]interface{}{})
723+
724+
// Call handler
725+
result,err:=handler(context.Background(),request)
726+
727+
// Verify results
728+
iftc.expectError {
729+
require.Error(t,err)
730+
assert.Contains(t,err.Error(),tc.expectedErrMsg)
731+
return
732+
}
733+
734+
require.NoError(t,err)
735+
736+
// Parse result and get text content
737+
textContent:=getTextResult(t,result)
738+
739+
// Unmarshal and verify the result
740+
varresultMapmap[string]interface{}
741+
err=json.Unmarshal([]byte(textContent.Text),&resultMap)
742+
require.NoError(t,err)
743+
744+
// Verify expected fields
745+
assert.Equal(t,tc.expectedResult["current_version"],resultMap["current_version"])
746+
assert.Equal(t,tc.expectedResult["latest_version"],resultMap["latest_version"])
747+
assert.Equal(t,tc.expectedResult["up_to_date"],resultMap["up_to_date"])
748+
assert.Equal(t,tc.expectedResult["release_url"],resultMap["release_url"])
749+
assert.NotEmpty(t,resultMap["published_at"])
750+
})
751+
}
752+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp