@@ -20,7 +20,7 @@ import (
20
20
var (
21
21
// Shared variables and sync.Once instances to ensure one-time execution
22
22
getTokenOnce sync.Once
23
- e2eToken string
23
+ token string
24
24
25
25
buildOnce sync.Once
26
26
buildError error
@@ -29,12 +29,12 @@ var (
29
29
// getE2EToken ensures the environment variable is checked only once and returns the token
30
30
func getE2EToken (t * testing.T ) string {
31
31
getTokenOnce .Do (func () {
32
- e2eToken = os .Getenv ("GITHUB_MCP_SERVER_E2E_TOKEN" )
33
- if e2eToken == "" {
32
+ token = os .Getenv ("GITHUB_MCP_SERVER_E2E_TOKEN" )
33
+ if token == "" {
34
34
t .Fatalf ("GITHUB_MCP_SERVER_E2E_TOKEN environment variable is not set" )
35
35
}
36
36
})
37
- return e2eToken
37
+ return token
38
38
}
39
39
40
40
// ensureDockerImageBuilt makes sure the Docker image is built only once across all tests
@@ -54,25 +54,79 @@ func ensureDockerImageBuilt(t *testing.T) {
54
54
require .NoError (t , buildError , "expected to build Docker image successfully" )
55
55
}
56
56
57
- func TestE2E (t * testing.T ) {
57
+ // ClientOpts holds configuration options for the MCP client setup
58
+ type ClientOpts struct {
59
+ // Environment variables to set before starting the client
60
+ EnvVars map [string ]string
61
+ // Whether to initialize the client after creation
62
+ ShouldInitialize bool
63
+ }
64
+
65
+ // ClientOption defines a function type for configuring ClientOpts
66
+ type ClientOption func (* ClientOpts )
67
+
68
+ // WithEnvVars returns an option that adds environment variables to the client options
69
+ func WithEnvVars (envVars map [string ]string ) ClientOption {
70
+ return func (opts * ClientOpts ) {
71
+ opts .EnvVars = envVars
72
+ }
73
+ }
74
+
75
+ // WithInitialize returns an option that configures the client to be initialized
76
+ func WithInitialize () ClientOption {
77
+ return func (opts * ClientOpts ) {
78
+ opts .ShouldInitialize = true
79
+ }
80
+ }
81
+
82
+ // setupMCPClient sets up the test environment and returns an initialized MCP client
83
+ // It handles token retrieval, Docker image building, and applying the provided options
84
+ func setupMCPClient (t * testing.T , options ... ClientOption ) * mcpClient.Client {
85
+ // Get token and ensure Docker image is built
58
86
token := getE2EToken (t )
59
87
ensureDockerImageBuilt (t )
60
88
61
- t .Setenv ("GITHUB_PERSONAL_ACCESS_TOKEN" , token ) // The MCP Client merges the existing environment.
89
+ // Create and configure options
90
+ opts := & ClientOpts {
91
+ EnvVars : make (map [string ]string ),
92
+ }
93
+
94
+ // Apply all options to configure the opts struct
95
+ for _ , option := range options {
96
+ option (opts )
97
+ }
98
+
99
+ // Set the GitHub token and other environment variables
100
+ t .Setenv ("GITHUB_PERSONAL_ACCESS_TOKEN" , token )
101
+ for key , value := range opts .EnvVars {
102
+ t .Setenv (key , value )
103
+ }
104
+
105
+ // Prepare Docker arguments
62
106
args := []string {
63
107
"docker" ,
64
108
"run" ,
65
109
"-i" ,
66
110
"--rm" ,
67
111
"-e" ,
68
112
"GITHUB_PERSONAL_ACCESS_TOKEN" ,
69
- "github/e2e-github-mcp-server" ,
70
113
}
114
+
115
+ // Add all environment variables to the Docker arguments
116
+ for key := range opts .EnvVars {
117
+ args = append (args , "-e" , key )
118
+ }
119
+
120
+ // Add the image name
121
+ args = append (args , "github/e2e-github-mcp-server" )
122
+
123
+ // Create the client
71
124
t .Log ("Starting Stdio MCP client..." )
72
125
client , err := mcpClient .NewStdioMCPClient (args [0 ], []string {}, args [1 :]... )
73
126
require .NoError (t , err , "expected to create client successfully" )
74
127
75
- t .Run ("Initialize" , func (t * testing.T ) {
128
+ // Initialize the client if configured to do so
129
+ if opts .ShouldInitialize {
76
130
ctx , cancel := context .WithTimeout (context .Background (), 5 * time .Second )
77
131
defer cancel ()
78
132
@@ -84,10 +138,16 @@ func TestE2E(t *testing.T) {
84
138
}
85
139
86
140
result , err := client .Initialize (ctx , request )
87
- require .NoError (t , err , "expected to initialize successfully" )
141
+ require .NoError (t , err , "failed to initialize client" )
142
+ require .Equal (t , "github-mcp-server" , result .ServerInfo .Name , "unexpected server name" )
143
+ }
88
144
89
- require .Equal (t , "github-mcp-server" , result .ServerInfo .Name )
90
- })
145
+ return client
146
+ }
147
+
148
+ func TestE2E (t * testing.T ) {
149
+ // Setup the MCP client with initialization
150
+ client := setupMCPClient (t , WithInitialize ())
91
151
92
152
t .Run ("CallTool get_me" , func (t * testing.T ) {
93
153
ctx , cancel := context .WithTimeout (context .Background (), 5 * time .Second )
@@ -114,7 +174,7 @@ func TestE2E(t *testing.T) {
114
174
115
175
// Then the login in the response should match the login obtained via the same
116
176
// token using the GitHub API.
117
- client := github .NewClient (nil ).WithAuthToken (token )
177
+ client := github .NewClient (nil ).WithAuthToken (getE2EToken ( t ) )
118
178
user , _ , err := client .Users .Get (context .Background (), "" )
119
179
require .NoError (t , err , "expected to get user successfully" )
120
180
require .Equal (t , trimmedContent .Login , * user .Login , "expected login to match" )
0 commit comments