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

Commitb863da9

Browse files
Migrate context_tools to new ServerTool pattern
Convert GetMe, GetTeams, and GetTeamMembers to use the new typeddependency injection pattern:- Functions now take only translations helper, return toolsets.ServerTool- Handler is generated lazily via deps.GetClient/deps.GetGQLClient- Tests updated to use serverTool.Handler(deps) pattern- Fixed error return pattern to return nil for Go error (via result.IsError)Co-authored-by: Adam Holt <omgitsads@users.noreply.github.com>
1 parentb29546e commitb863da9

File tree

3 files changed

+204
-168
lines changed

3 files changed

+204
-168
lines changed

‎pkg/github/context_tools.go‎

Lines changed: 159 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"time"
77

88
ghErrors"github.com/github/github-mcp-server/pkg/errors"
9+
"github.com/github/github-mcp-server/pkg/toolsets"
910
"github.com/github/github-mcp-server/pkg/translations"
1011
"github.com/github/github-mcp-server/pkg/utils"
1112
"github.com/google/jsonschema-go/jsonschema"
@@ -36,8 +37,9 @@ type UserDetails struct {
3637
}
3738

3839
// GetMe creates a tool to get details of the authenticated user.
39-
funcGetMe(getClientGetClientFn,t translations.TranslationHelperFunc) (mcp.Tool, mcp.ToolHandlerFor[map[string]any,any]) {
40-
return mcp.Tool{
40+
funcGetMe(t translations.TranslationHelperFunc) toolsets.ServerTool {
41+
returnNewTool(
42+
mcp.Tool{
4143
Name:"get_me",
4244
Description:t("TOOL_GET_ME_DESCRIPTION","Get details of the authenticated GitHub user. Use this when a request is about the user's own profile for GitHub. Or when information is missing to build other tool calls."),
4345
Annotations:&mcp.ToolAnnotations{
@@ -48,50 +50,53 @@ func GetMe(getClient GetClientFn, t translations.TranslationHelperFunc) (mcp.Too
4850
// OpenAI strict mode requires the properties field to be present.
4951
InputSchema:json.RawMessage(`{"type":"object","properties":{}}`),
5052
},
51-
mcp.ToolHandlerFor[map[string]any,any](func(ctx context.Context,_*mcp.CallToolRequest,_map[string]any) (*mcp.CallToolResult,any,error) {
52-
client,err:=getClient(ctx)
53-
iferr!=nil {
54-
returnutils.NewToolResultErrorFromErr("failed to get GitHub client",err),nil,nil
55-
}
53+
func(depsToolDependencies) mcp.ToolHandlerFor[map[string]any,any] {
54+
returnfunc(ctx context.Context,_*mcp.CallToolRequest,_map[string]any) (*mcp.CallToolResult,any,error) {
55+
client,err:=deps.GetClient(ctx)
56+
iferr!=nil {
57+
returnutils.NewToolResultErrorFromErr("failed to get GitHub client",err),nil,nil
58+
}
5659

57-
user,res,err:=client.Users.Get(ctx,"")
58-
iferr!=nil {
59-
returnghErrors.NewGitHubAPIErrorResponse(ctx,
60-
"failed to get user",
61-
res,
62-
err,
63-
),nil,err
64-
}
60+
user,res,err:=client.Users.Get(ctx,"")
61+
iferr!=nil {
62+
returnghErrors.NewGitHubAPIErrorResponse(ctx,
63+
"failed to get user",
64+
res,
65+
err,
66+
),nil,nil
67+
}
6568

66-
// Create minimal user representation instead of returning full user object
67-
minimalUser:=MinimalUser{
68-
Login:user.GetLogin(),
69-
ID:user.GetID(),
70-
ProfileURL:user.GetHTMLURL(),
71-
AvatarURL:user.GetAvatarURL(),
72-
Details:&UserDetails{
73-
Name:user.GetName(),
74-
Company:user.GetCompany(),
75-
Blog:user.GetBlog(),
76-
Location:user.GetLocation(),
77-
Email:user.GetEmail(),
78-
Hireable:user.GetHireable(),
79-
Bio:user.GetBio(),
80-
TwitterUsername:user.GetTwitterUsername(),
81-
PublicRepos:user.GetPublicRepos(),
82-
PublicGists:user.GetPublicGists(),
83-
Followers:user.GetFollowers(),
84-
Following:user.GetFollowing(),
85-
CreatedAt:user.GetCreatedAt().Time,
86-
UpdatedAt:user.GetUpdatedAt().Time,
87-
PrivateGists:user.GetPrivateGists(),
88-
TotalPrivateRepos:user.GetTotalPrivateRepos(),
89-
OwnedPrivateRepos:user.GetOwnedPrivateRepos(),
90-
},
91-
}
69+
// Create minimal user representation instead of returning full user object
70+
minimalUser:=MinimalUser{
71+
Login:user.GetLogin(),
72+
ID:user.GetID(),
73+
ProfileURL:user.GetHTMLURL(),
74+
AvatarURL:user.GetAvatarURL(),
75+
Details:&UserDetails{
76+
Name:user.GetName(),
77+
Company:user.GetCompany(),
78+
Blog:user.GetBlog(),
79+
Location:user.GetLocation(),
80+
Email:user.GetEmail(),
81+
Hireable:user.GetHireable(),
82+
Bio:user.GetBio(),
83+
TwitterUsername:user.GetTwitterUsername(),
84+
PublicRepos:user.GetPublicRepos(),
85+
PublicGists:user.GetPublicGists(),
86+
Followers:user.GetFollowers(),
87+
Following:user.GetFollowing(),
88+
CreatedAt:user.GetCreatedAt().Time,
89+
UpdatedAt:user.GetUpdatedAt().Time,
90+
PrivateGists:user.GetPrivateGists(),
91+
TotalPrivateRepos:user.GetTotalPrivateRepos(),
92+
OwnedPrivateRepos:user.GetOwnedPrivateRepos(),
93+
},
94+
}
9295

93-
returnMarshalledTextResult(minimalUser),nil,nil
94-
})
96+
returnMarshalledTextResult(minimalUser),nil,nil
97+
}
98+
},
99+
)
95100
}
96101

97102
typeTeamInfostruct {
@@ -105,8 +110,9 @@ type OrganizationTeams struct {
105110
Teams []TeamInfo`json:"teams"`
106111
}
107112

108-
funcGetTeams(getClientGetClientFn,getGQLClientGetGQLClientFn,t translations.TranslationHelperFunc) (mcp.Tool, mcp.ToolHandlerFor[map[string]any,any]) {
109-
return mcp.Tool{
113+
funcGetTeams(t translations.TranslationHelperFunc) toolsets.ServerTool {
114+
returnNewTool(
115+
mcp.Tool{
110116
Name:"get_teams",
111117
Description:t("TOOL_GET_TEAMS_DESCRIPTION","Get details of the teams the user is a member of. Limited to organizations accessible with current credentials"),
112118
Annotations:&mcp.ToolAnnotations{
@@ -123,84 +129,88 @@ func GetTeams(getClient GetClientFn, getGQLClient GetGQLClientFn, t translations
123129
},
124130
},
125131
},
126-
func(ctx context.Context,_*mcp.CallToolRequest,argsmap[string]any) (*mcp.CallToolResult,any,error) {
127-
user,err:=OptionalParam[string](args,"user")
128-
iferr!=nil {
129-
returnutils.NewToolResultError(err.Error()),nil,nil
130-
}
131-
132-
varusernamestring
133-
ifuser!="" {
134-
username=user
135-
}else {
136-
client,err:=getClient(ctx)
132+
func(depsToolDependencies) mcp.ToolHandlerFor[map[string]any,any] {
133+
returnfunc(ctx context.Context,_*mcp.CallToolRequest,argsmap[string]any) (*mcp.CallToolResult,any,error) {
134+
user,err:=OptionalParam[string](args,"user")
137135
iferr!=nil {
138-
returnutils.NewToolResultErrorFromErr("failed to get GitHub client",err),nil,nil
136+
returnutils.NewToolResultError(err.Error()),nil,nil
139137
}
140138

141-
userResp,res,err:=client.Users.Get(ctx,"")
139+
varusernamestring
140+
ifuser!="" {
141+
username=user
142+
}else {
143+
client,err:=deps.GetClient(ctx)
144+
iferr!=nil {
145+
returnutils.NewToolResultErrorFromErr("failed to get GitHub client",err),nil,nil
146+
}
147+
148+
userResp,res,err:=client.Users.Get(ctx,"")
149+
iferr!=nil {
150+
returnghErrors.NewGitHubAPIErrorResponse(ctx,
151+
"failed to get user",
152+
res,
153+
err,
154+
),nil,nil
155+
}
156+
username=userResp.GetLogin()
157+
}
158+
159+
gqlClient,err:=deps.GetGQLClient(ctx)
142160
iferr!=nil {
143-
returnghErrors.NewGitHubAPIErrorResponse(ctx,
144-
"failed to get user",
145-
res,
146-
err,
147-
),nil,nil
161+
returnutils.NewToolResultErrorFromErr("failed to get GitHub GQL client",err),nil,nil
148162
}
149-
username=userResp.GetLogin()
150-
}
151163

152-
gqlClient,err:=getGQLClient(ctx)
153-
iferr!=nil {
154-
returnutils.NewToolResultErrorFromErr("failed to get GitHub GQL client",err),nil,nil
155-
}
164+
varqstruct {
165+
Userstruct {
166+
Organizationsstruct {
167+
Nodes []struct {
168+
Login githubv4.String
169+
Teamsstruct {
170+
Nodes []struct {
171+
Name githubv4.String
172+
Slug githubv4.String
173+
Description githubv4.String
174+
}
175+
}`graphql:"teams(first: 100, userLogins: [$login])"`
176+
}
177+
}`graphql:"organizations(first: 100)"`
178+
}`graphql:"user(login: $login)"`
179+
}
180+
vars:=map[string]interface{}{
181+
"login":githubv4.String(username),
182+
}
183+
iferr:=gqlClient.Query(ctx,&q,vars);err!=nil {
184+
returnghErrors.NewGitHubGraphQLErrorResponse(ctx,"Failed to find teams",err),nil,nil
185+
}
156186

157-
varqstruct {
158-
Userstruct {
159-
Organizationsstruct {
160-
Nodes []struct {
161-
Login githubv4.String
162-
Teamsstruct {
163-
Nodes []struct {
164-
Name githubv4.String
165-
Slug githubv4.String
166-
Description githubv4.String
167-
}
168-
}`graphql:"teams(first: 100, userLogins: [$login])"`
169-
}
170-
}`graphql:"organizations(first: 100)"`
171-
}`graphql:"user(login: $login)"`
172-
}
173-
vars:=map[string]interface{}{
174-
"login":githubv4.String(username),
175-
}
176-
iferr:=gqlClient.Query(ctx,&q,vars);err!=nil {
177-
returnghErrors.NewGitHubGraphQLErrorResponse(ctx,"Failed to find teams",err),nil,nil
178-
}
187+
varorganizations []OrganizationTeams
188+
for_,org:=rangeq.User.Organizations.Nodes {
189+
orgTeams:=OrganizationTeams{
190+
Org:string(org.Login),
191+
Teams:make([]TeamInfo,0,len(org.Teams.Nodes)),
192+
}
179193

180-
varorganizations []OrganizationTeams
181-
for_,org:=rangeq.User.Organizations.Nodes {
182-
orgTeams:=OrganizationTeams{
183-
Org:string(org.Login),
184-
Teams:make([]TeamInfo,0,len(org.Teams.Nodes)),
185-
}
194+
for_,team:=rangeorg.Teams.Nodes {
195+
orgTeams.Teams=append(orgTeams.Teams,TeamInfo{
196+
Name:string(team.Name),
197+
Slug:string(team.Slug),
198+
Description:string(team.Description),
199+
})
200+
}
186201

187-
for_,team:=rangeorg.Teams.Nodes {
188-
orgTeams.Teams=append(orgTeams.Teams,TeamInfo{
189-
Name:string(team.Name),
190-
Slug:string(team.Slug),
191-
Description:string(team.Description),
192-
})
202+
organizations=append(organizations,orgTeams)
193203
}
194204

195-
organizations=append(organizations,orgTeams)
205+
returnMarshalledTextResult(organizations),nil,nil
196206
}
197-
198-
returnMarshalledTextResult(organizations),nil,nil
199-
}
207+
},
208+
)
200209
}
201210

202-
funcGetTeamMembers(getGQLClientGetGQLClientFn,t translations.TranslationHelperFunc) (mcp.Tool, mcp.ToolHandlerFor[map[string]any,any]) {
203-
return mcp.Tool{
211+
funcGetTeamMembers(t translations.TranslationHelperFunc) toolsets.ServerTool {
212+
returnNewTool(
213+
mcp.Tool{
204214
Name:"get_team_members",
205215
Description:t("TOOL_GET_TEAM_MEMBERS_DESCRIPTION","Get member usernames of a specific team in an organization. Limited to organizations accessible with current credentials"),
206216
Annotations:&mcp.ToolAnnotations{
@@ -222,46 +232,49 @@ func GetTeamMembers(getGQLClient GetGQLClientFn, t translations.TranslationHelpe
222232
Required: []string{"org","team_slug"},
223233
},
224234
},
225-
func(ctx context.Context,_*mcp.CallToolRequest,argsmap[string]any) (*mcp.CallToolResult,any,error) {
226-
org,err:=RequiredParam[string](args,"org")
227-
iferr!=nil {
228-
returnutils.NewToolResultError(err.Error()),nil,nil
229-
}
235+
func(depsToolDependencies) mcp.ToolHandlerFor[map[string]any,any] {
236+
returnfunc(ctx context.Context,_*mcp.CallToolRequest,argsmap[string]any) (*mcp.CallToolResult,any,error) {
237+
org,err:=RequiredParam[string](args,"org")
238+
iferr!=nil {
239+
returnutils.NewToolResultError(err.Error()),nil,nil
240+
}
230241

231-
teamSlug,err:=RequiredParam[string](args,"team_slug")
232-
iferr!=nil {
233-
returnutils.NewToolResultError(err.Error()),nil,nil
234-
}
242+
teamSlug,err:=RequiredParam[string](args,"team_slug")
243+
iferr!=nil {
244+
returnutils.NewToolResultError(err.Error()),nil,nil
245+
}
235246

236-
gqlClient,err:=getGQLClient(ctx)
237-
iferr!=nil {
238-
returnutils.NewToolResultErrorFromErr("failed to get GitHub GQL client",err),nil,nil
239-
}
247+
gqlClient,err:=deps.GetGQLClient(ctx)
248+
iferr!=nil {
249+
returnutils.NewToolResultErrorFromErr("failed to get GitHub GQL client",err),nil,nil
250+
}
240251

241-
varqstruct {
242-
Organizationstruct {
243-
Teamstruct {
244-
Membersstruct {
245-
Nodes []struct {
246-
Login githubv4.String
247-
}
248-
}`graphql:"members(first: 100)"`
249-
}`graphql:"team(slug: $teamSlug)"`
250-
}`graphql:"organization(login: $org)"`
251-
}
252-
vars:=map[string]interface{}{
253-
"org":githubv4.String(org),
254-
"teamSlug":githubv4.String(teamSlug),
255-
}
256-
iferr:=gqlClient.Query(ctx,&q,vars);err!=nil {
257-
returnghErrors.NewGitHubGraphQLErrorResponse(ctx,"Failed to get team members",err),nil,nil
258-
}
252+
varqstruct {
253+
Organizationstruct {
254+
Teamstruct {
255+
Membersstruct {
256+
Nodes []struct {
257+
Login githubv4.String
258+
}
259+
}`graphql:"members(first: 100)"`
260+
}`graphql:"team(slug: $teamSlug)"`
261+
}`graphql:"organization(login: $org)"`
262+
}
263+
vars:=map[string]interface{}{
264+
"org":githubv4.String(org),
265+
"teamSlug":githubv4.String(teamSlug),
266+
}
267+
iferr:=gqlClient.Query(ctx,&q,vars);err!=nil {
268+
returnghErrors.NewGitHubGraphQLErrorResponse(ctx,"Failed to get team members",err),nil,nil
269+
}
259270

260-
varmembers []string
261-
for_,member:=rangeq.Organization.Team.Members.Nodes {
262-
members=append(members,string(member.Login))
263-
}
271+
varmembers []string
272+
for_,member:=rangeq.Organization.Team.Members.Nodes {
273+
members=append(members,string(member.Login))
274+
}
264275

265-
returnMarshalledTextResult(members),nil,nil
266-
}
276+
returnMarshalledTextResult(members),nil,nil
277+
}
278+
},
279+
)
267280
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp