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

Commit0ca07aa

Browse files
committed
Support breakpoint debugging e2e tests
1 parentafc7a93 commit0ca07aa

File tree

2 files changed

+89
-56
lines changed

2 files changed

+89
-56
lines changed

‎e2e/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ FAIL github.com/github/github-mcp-server/e2e 1.433s
7777
FAIL
7878
```
7979

80+
##Debugging the Tests
81+
82+
It is possible to provide`GITHUB_MCP_SERVER_E2E_DEBUG=true` to run the e2e tests with an in-process version of the MCP server. This has slightly reduced coverage as it doesn't integrate with Docker, or make use of the cobra/viper configuration parsing. However, it allows for placing breakpoints in the MCP Server internals, supporting much better debugging flows than the fully black-box tests.
83+
84+
One might argue that the lack of visibility into failures for the black box tests also indicates a product need, but this solves for the immediate pain point felt as a maintainer.
85+
8086
##Limitations
8187

8288
The current test suite is intentionally very limited in scope. This is because the maintenance costs on e2e tests tend to increase significantly over time. To read about some challenges with GitHub integration tests, see[go-github integration tests README](https://github.com/google/go-github/blob/5b75aa86dba5cf4af2923afa0938774f37fa0a67/test/README.md). We will expand this suite circumspectly!

‎e2e/e2e_test.go

Lines changed: 83 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,15 @@ import (
99
"os"
1010
"os/exec"
1111
"slices"
12+
"strings"
1213
"sync"
1314
"testing"
1415
"time"
1516

16-
"github.com/google/go-github/v69/github"
17+
"github.com/github/github-mcp-server/internal/ghmcp"
18+
"github.com/github/github-mcp-server/pkg/github"
19+
"github.com/github/github-mcp-server/pkg/translations"
20+
gogithub"github.com/google/go-github/v69/github"
1721
mcpClient"github.com/mark3labs/mcp-go/client"
1822
"github.com/mark3labs/mcp-go/mcp"
1923
"github.com/stretchr/testify/require"
@@ -56,68 +60,91 @@ func ensureDockerImageBuilt(t *testing.T) {
5660
require.NoError(t,buildError,"expected to build Docker image successfully")
5761
}
5862

59-
//ClientOpts holds configuration options for the MCP client setup
60-
typeClientOptsstruct {
61-
//Environment variablestoset before startingtheclient
62-
EnvVarsmap[string]string
63+
//clientOpts holds configuration options for the MCP client setup
64+
typeclientOptsstruct {
65+
//Toolsetstoenable intheMCP server
66+
enabledToolsets []string
6367
}
6468

65-
//ClientOption defines a function type for configuring ClientOpts
66-
typeClientOptionfunc(*ClientOpts)
69+
//clientOption defines a function type for configuring ClientOpts
70+
typeclientOptionfunc(*clientOpts)
6771

68-
// WithEnvVars returns an option that adds environment variables to the client options
69-
funcWithEnvVars(envVarsmap[string]string)ClientOption {
70-
returnfunc(opts*ClientOpts) {
71-
opts.EnvVars=envVars
72+
// withToolsets returns an option that either sets an Env Var when executing in docker,
73+
// or sets the toolsets in the MCP server when running in-process.
74+
funcwithToolsets(toolsets []string)clientOption {
75+
returnfunc(opts*clientOpts) {
76+
opts.enabledToolsets=toolsets
7277
}
7378
}
7479

75-
// setupMCPClient sets up the test environment and returns an initialized MCP client
76-
// It handles token retrieval, Docker image building, and applying the provided options
77-
funcsetupMCPClient(t*testing.T,options...ClientOption)*mcpClient.Client {
80+
funcsetupMCPClient(t*testing.T,options...clientOption)*mcpClient.Client {
7881
// Get token and ensure Docker image is built
7982
token:=getE2EToken(t)
80-
ensureDockerImageBuilt(t)
8183

8284
// Create and configure options
83-
opts:=&ClientOpts{
84-
EnvVars:make(map[string]string),
85-
}
85+
opts:=&clientOpts{}
8686

8787
// Apply all options to configure the opts struct
8888
for_,option:=rangeoptions {
8989
option(opts)
9090
}
9191

92-
// Prepare Docker arguments
93-
args:= []string{
94-
"docker",
95-
"run",
96-
"-i",
97-
"--rm",
98-
"-e",
99-
"GITHUB_PERSONAL_ACCESS_TOKEN",// Personal access token is all required
100-
}
92+
// By default, we run the tests including the Docker image, but with DEBUG
93+
// enabled, we run the server in-process, allowing for easier debugging.
94+
varclient*mcpClient.Client
95+
ifos.Getenv("GITHUB_MCP_SERVER_E2E_DEBUG")=="" {
96+
ensureDockerImageBuilt(t)
97+
98+
// Prepare Docker arguments
99+
args:= []string{
100+
"docker",
101+
"run",
102+
"-i",
103+
"--rm",
104+
"-e",
105+
"GITHUB_PERSONAL_ACCESS_TOKEN",// Personal access token is all required
106+
}
101107

102-
// Add all environment variables to the Docker arguments
103-
forkey:=rangeopts.EnvVars {
104-
args=append(args,"-e",key)
105-
}
108+
// Add toolsets environment variable to the Docker arguments
109+
iflen(opts.enabledToolsets)>0 {
110+
args=append(args,"-e","GITHUB_TOOLSETS")
111+
}
112+
113+
// Add the image name
114+
args=append(args,"github/e2e-github-mcp-server")
106115

107-
// Add the image name
108-
args=append(args,"github/e2e-github-mcp-server")
116+
// Construct the env vars for the MCP Client to execute docker with
117+
dockerEnvVars:= []string{
118+
fmt.Sprintf("GITHUB_PERSONAL_ACCESS_TOKEN=%s",token),
119+
fmt.Sprintf("GITHUB_TOOLSETS=%s",strings.Join(opts.enabledToolsets,",")),
120+
}
109121

110-
// Construct the env vars for the MCP Client to execute docker with
111-
dockerEnvVars:=make([]string,0,len(opts.EnvVars)+1)
112-
dockerEnvVars=append(dockerEnvVars,fmt.Sprintf("GITHUB_PERSONAL_ACCESS_TOKEN=%s",token))
113-
forkey,value:=rangeopts.EnvVars {
114-
dockerEnvVars=append(dockerEnvVars,fmt.Sprintf("%s=%s",key,value))
122+
// Create the client
123+
t.Log("Starting Stdio MCP client...")
124+
varerrerror
125+
client,err=mcpClient.NewStdioMCPClient(args[0],dockerEnvVars,args[1:]...)
126+
require.NoError(t,err,"expected to create client successfully")
127+
}else {
128+
// We need this because the fully compiled server has a default for the viper config, which is
129+
// not in scope for using the MCP server directly. This probably indicates that we should refactor
130+
// so that there is a shared setup mechanism, but let's wait till we feel more friction.
131+
enabledToolsets:=opts.enabledToolsets
132+
ifenabledToolsets==nil {
133+
enabledToolsets=github.DefaultTools
134+
}
135+
136+
ghServer,err:=ghmcp.NewMCPServer(ghmcp.MCPServerConfig{
137+
Token:token,
138+
EnabledToolsets:enabledToolsets,
139+
Translator:translations.NullTranslationHelper,
140+
})
141+
require.NoError(t,err,"expected to construct MCP server successfully")
142+
143+
t.Log("Starting In Process MCP client...")
144+
client,err=mcpClient.NewInProcessClient(ghServer)
145+
require.NoError(t,err,"expected to create in-process client successfully")
115146
}
116147

117-
// Create the client
118-
t.Log("Starting Stdio MCP client...")
119-
client,err:=mcpClient.NewStdioMCPClient(args[0],dockerEnvVars,args[1:]...)
120-
require.NoError(t,err,"expected to create client successfully")
121148
t.Cleanup(func() {
122149
require.NoError(t,client.Close(),"expected to close client successfully")
123150
})
@@ -169,7 +196,7 @@ func TestGetMe(t *testing.T) {
169196

170197
// Then the login in the response should match the login obtained via the same
171198
// token using the GitHub API.
172-
ghClient:=github.NewClient(nil).WithAuthToken(getE2EToken(t))
199+
ghClient:=gogithub.NewClient(nil).WithAuthToken(getE2EToken(t))
173200
user,_,err:=ghClient.Users.Get(context.Background(),"")
174201
require.NoError(t,err,"expected to get user successfully")
175202
require.Equal(t,trimmedContent.Login,*user.Login,"expected login to match")
@@ -181,9 +208,7 @@ func TestToolsets(t *testing.T) {
181208

182209
mcpClient:=setupMCPClient(
183210
t,
184-
WithEnvVars(map[string]string{
185-
"GITHUB_TOOLSETS":"repos,issues",
186-
}),
211+
withToolsets([]string{"repos","issues"}),
187212
)
188213

189214
ctx,cancel:=context.WithTimeout(context.Background(),5*time.Second)
@@ -208,6 +233,8 @@ func TestToolsets(t *testing.T) {
208233
}
209234

210235
funcTestTags(t*testing.T) {
236+
t.Parallel()
237+
211238
mcpClient:=setupMCPClient(t)
212239

213240
ctx:=context.Background()
@@ -253,32 +280,32 @@ func TestTags(t *testing.T) {
253280
// Cleanup the repository after the test
254281
t.Cleanup(func() {
255282
// MCP Server doesn't support deletions, but we can use the GitHub Client
256-
ghClient:=github.NewClient(nil).WithAuthToken(getE2EToken(t))
283+
ghClient:=gogithub.NewClient(nil).WithAuthToken(getE2EToken(t))
257284
t.Logf("Deleting repository %s/%s...",currentOwner,repoName)
258285
_,err:=ghClient.Repositories.Delete(context.Background(),currentOwner,repoName)
259286
require.NoError(t,err,"expected to delete repository successfully")
260287
})
261288

262289
// Then create a tag
263290
// MCP Server doesn't support tag creation, but we can use the GitHub Client
264-
ghClient:=github.NewClient(nil).WithAuthToken(getE2EToken(t))
291+
ghClient:=gogithub.NewClient(nil).WithAuthToken(getE2EToken(t))
265292
t.Logf("Creating tag %s/%s:%s...",currentOwner,repoName,"v0.0.1")
266293
ref,_,err:=ghClient.Git.GetRef(context.Background(),currentOwner,repoName,"refs/heads/main")
267294
require.NoError(t,err,"expected to get ref successfully")
268295

269-
tagObj,_,err:=ghClient.Git.CreateTag(context.Background(),currentOwner,repoName,&github.Tag{
270-
Tag:github.Ptr("v0.0.1"),
271-
Message:github.Ptr("v0.0.1"),
272-
Object:&github.GitObject{
296+
tagObj,_,err:=ghClient.Git.CreateTag(context.Background(),currentOwner,repoName,&gogithub.Tag{
297+
Tag:gogithub.Ptr("v0.0.1"),
298+
Message:gogithub.Ptr("v0.0.1"),
299+
Object:&gogithub.GitObject{
273300
SHA:ref.Object.SHA,
274-
Type:github.Ptr("commit"),
301+
Type:gogithub.Ptr("commit"),
275302
},
276303
})
277304
require.NoError(t,err,"expected to create tag object successfully")
278305

279-
_,_,err=ghClient.Git.CreateRef(context.Background(),currentOwner,repoName,&github.Reference{
280-
Ref:github.Ptr("refs/tags/v0.0.1"),
281-
Object:&github.GitObject{
306+
_,_,err=ghClient.Git.CreateRef(context.Background(),currentOwner,repoName,&gogithub.Reference{
307+
Ref:gogithub.Ptr("refs/tags/v0.0.1"),
308+
Object:&gogithub.GitObject{
282309
SHA:tagObj.SHA,
283310
},
284311
})

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp