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

Commiteca853b

Browse files
williammartinSamMorrowDrums
authored andcommitted
Split PR review creation, commenting, submission and deletion
1 parent50043c3 commiteca853b

19 files changed

+2936
-946
lines changed

‎e2e/e2e_test.go

Lines changed: 633 additions & 25 deletions
Large diffs are not rendered by default.

‎go.mod

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ require (
1515
require (
1616
github.com/davecgh/go-spewv1.1.2-0.20180830191138-d8f796af33cc// indirect
1717
github.com/fsnotify/fsnotifyv1.8.0// indirect
18-
github.com/go-viper/mapstructure/v2v2.2.1// indirect
18+
github.com/go-viper/mapstructure/v2v2.2.1
1919
github.com/google/go-github/v71v71.0.0// indirect
2020
github.com/google/go-querystringv1.1.0// indirect
2121
github.com/google/uuidv1.6.0// indirect
@@ -25,13 +25,16 @@ require (
2525
github.com/pmezard/go-difflibv1.0.1-0.20181226105442-5d4384ee4fb2// indirect
2626
github.com/rogpeppe/go-internalv1.13.1// indirect
2727
github.com/sagikazarmark/locaferov0.9.0// indirect
28+
github.com/shurcooL/githubv4v0.0.0-20240727222349-48295856cce7
29+
github.com/shurcooL/graphqlv0.0.0-20230722043721-ed46e5a46466
2830
github.com/sourcegraph/concv0.3.0// indirect
2931
github.com/spf13/aferov1.14.0// indirect
3032
github.com/spf13/castv1.7.1// indirect
3133
github.com/spf13/pflagv1.0.6// indirect
3234
github.com/subosito/gotenvv1.6.0// indirect
3335
github.com/yosida95/uritemplate/v3v3.0.2// indirect
3436
go.uber.org/multierrv1.11.0// indirect
37+
golang.org/x/oauth2v0.29.0// indirect
3538
golang.org/x/sysv0.31.0// indirect
3639
golang.org/x/textv0.23.0// indirect
3740
golang.org/x/timev0.5.0// indirect

‎go.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWN
4545
github.com/russross/blackfriday/v2v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
4646
github.com/sagikazarmark/locaferov0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k=
4747
github.com/sagikazarmark/locaferov0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk=
48+
github.com/shurcooL/githubv4v0.0.0-20240727222349-48295856cce7 h1:cYCy18SHPKRkvclm+pWm1Lk4YrREb4IOIb/YdFO0p2M=
49+
github.com/shurcooL/githubv4v0.0.0-20240727222349-48295856cce7/go.mod h1:zqMwyHmnN/eDOZOdiTohqIUKUrTFX62PNlu7IJdu0q8=
50+
github.com/shurcooL/graphqlv0.0.0-20230722043721-ed46e5a46466 h1:17JxqqJY66GmZVHkmAsGEkcIu0oCe3AM420QDgGwZx0=
51+
github.com/shurcooL/graphqlv0.0.0-20230722043721-ed46e5a46466/go.mod h1:9dIRpgIY7hVhoqfe0/FcYp0bpInZaT7dc3BYOprrIUE=
4852
github.com/sirupsen/logrusv1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
4953
github.com/sirupsen/logrusv1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
5054
github.com/sourcegraph/concv0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
@@ -69,6 +73,8 @@ github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zI
6973
github.com/yosida95/uritemplate/v3v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
7074
go.uber.org/multierrv1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
7175
go.uber.org/multierrv1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
76+
golang.org/x/oauth2v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
77+
golang.org/x/oauth2v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
7278
golang.org/x/sysv0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
7379
golang.org/x/sysv0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
7480
golang.org/x/sysv0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=

‎internal/ghmcp/server.go

Lines changed: 176 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ import (
55
"fmt"
66
"io"
77
"log"
8+
"net/http"
9+
"net/url"
810
"os"
911
"os/signal"
12+
"strings"
1013
"syscall"
1114

1215
"github.com/github/github-mcp-server/pkg/github"
@@ -15,6 +18,7 @@ import (
1518
gogithub"github.com/google/go-github/v69/github"
1619
"github.com/mark3labs/mcp-go/mcp"
1720
"github.com/mark3labs/mcp-go/server"
21+
"github.com/shurcooL/githubv4"
1822
"github.com/sirupsen/logrus"
1923
)
2024

@@ -44,25 +48,43 @@ type MCPServerConfig struct {
4448
}
4549

4650
funcNewMCPServer(cfgMCPServerConfig) (*server.MCPServer,error) {
47-
ghClient:=gogithub.NewClient(nil).WithAuthToken(cfg.Token)
48-
ghClient.UserAgent=fmt.Sprintf("github-mcp-server/%s",cfg.Version)
49-
50-
ifcfg.Host!="" {
51-
varerrerror
52-
ghClient,err=ghClient.WithEnterpriseURLs(cfg.Host,cfg.Host)
53-
iferr!=nil {
54-
returnnil,fmt.Errorf("failed to create GitHub client with host: %w",err)
55-
}
51+
apiHost,err:=parseAPIHost(cfg.Host)
52+
iferr!=nil {
53+
returnnil,fmt.Errorf("failed to parse API host: %w",err)
5654
}
5755

56+
// Construct our REST client
57+
restClient:=gogithub.NewClient(nil).WithAuthToken(cfg.Token)
58+
restClient.UserAgent=fmt.Sprintf("github-mcp-server/%s",cfg.Version)
59+
restClient.BaseURL=apiHost.baseRESTURL
60+
restClient.UploadURL=apiHost.uploadURL
61+
62+
// Construct our GraphQL client
63+
// We're using NewEnterpriseClient here unconditionally as opposed to NewClient because we already
64+
// did the necessary API host parsing so that github.com will return the correct URL anyway.
65+
gqlHTTPClient:=&http.Client{
66+
Transport:&bearerAuthTransport{
67+
transport:http.DefaultTransport,
68+
token:cfg.Token,
69+
},
70+
}// We're going to wrap the Transport later in beforeInit
71+
gqlClient:=githubv4.NewEnterpriseClient(apiHost.graphqlURL.String(),gqlHTTPClient)
72+
5873
// When a client send an initialize request, update the user agent to include the client info.
5974
beforeInit:=func(_ context.Context,_any,message*mcp.InitializeRequest) {
60-
ghClient.UserAgent=fmt.Sprintf(
75+
userAgent:=fmt.Sprintf(
6176
"github-mcp-server/%s (%s/%s)",
6277
cfg.Version,
6378
message.Params.ClientInfo.Name,
6479
message.Params.ClientInfo.Version,
6580
)
81+
82+
restClient.UserAgent=userAgent
83+
84+
gqlHTTPClient.Transport=&userAgentTransport{
85+
transport:gqlHTTPClient.Transport,
86+
agent:userAgent,
87+
}
6688
}
6789

6890
hooks:=&server.Hooks{
@@ -83,14 +105,19 @@ func NewMCPServer(cfg MCPServerConfig) (*server.MCPServer, error) {
83105
}
84106

85107
getClient:=func(_ context.Context) (*gogithub.Client,error) {
86-
returnghClient,nil// closing over client
108+
returnrestClient,nil// closing over client
109+
}
110+
111+
getGQLClient:=func(_ context.Context) (*githubv4.Client,error) {
112+
returngqlClient,nil// closing over client
87113
}
88114

89115
// Create default toolsets
90116
toolsets,err:=github.InitToolsets(
91117
enabledToolsets,
92118
cfg.ReadOnly,
93119
getClient,
120+
getGQLClient,
94121
cfg.Translator,
95122
)
96123
iferr!=nil {
@@ -213,3 +240,141 @@ func RunStdioServer(cfg StdioServerConfig) error {
213240

214241
returnnil
215242
}
243+
244+
typeapiHoststruct {
245+
baseRESTURL*url.URL
246+
graphqlURL*url.URL
247+
uploadURL*url.URL
248+
}
249+
250+
funcnewDotcomHost() (apiHost,error) {
251+
baseRestURL,err:=url.Parse("https://api.github.com/")
252+
iferr!=nil {
253+
returnapiHost{},fmt.Errorf("failed to parse dotcom REST URL: %w",err)
254+
}
255+
256+
gqlURL,err:=url.Parse("https://api.github.com/graphql")
257+
iferr!=nil {
258+
returnapiHost{},fmt.Errorf("failed to parse dotcom GraphQL URL: %w",err)
259+
}
260+
261+
uploadURL,err:=url.Parse("https://uploads.github.com")
262+
iferr!=nil {
263+
returnapiHost{},fmt.Errorf("failed to parse dotcom Upload URL: %w",err)
264+
}
265+
266+
returnapiHost{
267+
baseRESTURL:baseRestURL,
268+
graphqlURL:gqlURL,
269+
uploadURL:uploadURL,
270+
},nil
271+
}
272+
273+
funcnewGHECHost(hostnamestring) (apiHost,error) {
274+
u,err:=url.Parse(hostname)
275+
iferr!=nil {
276+
returnapiHost{},fmt.Errorf("failed to parse GHEC URL: %w",err)
277+
}
278+
279+
// Unsecured GHEC would be an error
280+
ifu.Scheme=="http" {
281+
returnapiHost{},fmt.Errorf("GHEC URL must be HTTPS")
282+
}
283+
284+
restURL,err:=url.Parse(fmt.Sprintf("https://api.%s/",u.Hostname()))
285+
iferr!=nil {
286+
returnapiHost{},fmt.Errorf("failed to parse GHEC REST URL: %w",err)
287+
}
288+
289+
gqlURL,err:=url.Parse(fmt.Sprintf("https://api.%s/graphql",u.Hostname()))
290+
iferr!=nil {
291+
returnapiHost{},fmt.Errorf("failed to parse GHEC GraphQL URL: %w",err)
292+
}
293+
294+
uploadURL,err:=url.Parse(fmt.Sprintf("https://uploads.%s",u.Hostname()))
295+
iferr!=nil {
296+
returnapiHost{},fmt.Errorf("failed to parse GHEC Upload URL: %w",err)
297+
}
298+
299+
returnapiHost{
300+
baseRESTURL:restURL,
301+
graphqlURL:gqlURL,
302+
uploadURL:uploadURL,
303+
},nil
304+
}
305+
306+
funcnewGHESHost(hostnamestring) (apiHost,error) {
307+
u,err:=url.Parse(hostname)
308+
iferr!=nil {
309+
returnapiHost{},fmt.Errorf("failed to parse GHES URL: %w",err)
310+
}
311+
312+
restURL,err:=url.Parse(fmt.Sprintf("%s://%s/api/v3/",u.Scheme,u.Hostname()))
313+
iferr!=nil {
314+
returnapiHost{},fmt.Errorf("failed to parse GHES REST URL: %w",err)
315+
}
316+
317+
gqlURL,err:=url.Parse(fmt.Sprintf("%s://%s/api/graphql",u.Scheme,u.Hostname()))
318+
iferr!=nil {
319+
returnapiHost{},fmt.Errorf("failed to parse GHES GraphQL URL: %w",err)
320+
}
321+
322+
uploadURL,err:=url.Parse(fmt.Sprintf("%s://%s/api/uploads/",u.Scheme,u.Hostname()))
323+
iferr!=nil {
324+
returnapiHost{},fmt.Errorf("failed to parse GHES Upload URL: %w",err)
325+
}
326+
327+
returnapiHost{
328+
baseRESTURL:restURL,
329+
graphqlURL:gqlURL,
330+
uploadURL:uploadURL,
331+
},nil
332+
}
333+
334+
// Note that this does not handle ports yet, so development environments are out.
335+
funcparseAPIHost(sstring) (apiHost,error) {
336+
ifs=="" {
337+
returnnewDotcomHost()
338+
}
339+
340+
u,err:=url.Parse(s)
341+
iferr!=nil {
342+
returnapiHost{},fmt.Errorf("could not parse host as URL: %s",s)
343+
}
344+
345+
ifu.Scheme=="" {
346+
returnapiHost{},fmt.Errorf("host must have a scheme (http or https): %s",s)
347+
}
348+
349+
ifstrings.HasSuffix(u.Hostname(),"github.com") {
350+
returnnewDotcomHost()
351+
}
352+
353+
ifstrings.HasSuffix(u.Hostname(),"ghe.com") {
354+
returnnewGHECHost(s)
355+
}
356+
357+
returnnewGHESHost(s)
358+
}
359+
360+
typeuserAgentTransportstruct {
361+
transport http.RoundTripper
362+
agentstring
363+
}
364+
365+
func (t*userAgentTransport)RoundTrip(req*http.Request) (*http.Response,error) {
366+
req=req.Clone(req.Context())
367+
req.Header.Set("User-Agent",t.agent)
368+
returnt.transport.RoundTrip(req)
369+
}
370+
371+
typebearerAuthTransportstruct {
372+
transport http.RoundTripper
373+
tokenstring
374+
}
375+
376+
func (t*bearerAuthTransport)RoundTrip(req*http.Request) (*http.Response,error) {
377+
req=req.Clone(req.Context())
378+
req.Header.Set("Authorization","Bearer "+t.token)
379+
returnt.transport.RoundTrip(req)
380+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp