Skip to content

Commit c86d5d6

Browse files
committed
build: upgrade to go-sdk v1.2.0
see https://github.com/modelcontextprotocol/go-sdk/releases/tag/v1.2.0 also, refactor e2e tests: get rid of env vars and properly wait for MCP server to be ready Signed-off-by: Xavier Coulon <xcoulon@redhat.com>
1 parent d423d3e commit c86d5d6

4 files changed

Lines changed: 56 additions & 23 deletions

File tree

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ require (
77
github.com/argoproj/gitops-engine v0.7.1-0.20250905153922-d96c3d51e4c4
88
github.com/google/jsonschema-go v0.3.0
99
github.com/h2non/gock v1.2.0
10-
github.com/modelcontextprotocol/go-sdk v1.1.0
10+
github.com/modelcontextprotocol/go-sdk v1.2.0
1111
github.com/spf13/cobra v1.10.1
1212
github.com/stretchr/testify v1.10.0
1313
k8s.io/apimachinery v0.33.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,8 @@ github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU
239239
github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
240240
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
241241
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
242-
github.com/modelcontextprotocol/go-sdk v1.1.0 h1:Qjayg53dnKC4UZ+792W21e4BpwEZBzwgRW6LrjLWSwA=
243-
github.com/modelcontextprotocol/go-sdk v1.1.0/go.mod h1:6fM3LCm3yV7pAs8isnKLn07oKtB0MP9LHd3DfAcKw10=
242+
github.com/modelcontextprotocol/go-sdk v1.2.0 h1:Y23co09300CEk8iZ/tMxIX1dVmKZkzoSBZOpJwUnc/s=
243+
github.com/modelcontextprotocol/go-sdk v1.2.0/go.mod h1:6fM3LCm3yV7pAs8isnKLn07oKtB0MP9LHd3DfAcKw10=
244244
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
245245
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
246246
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=

test/e2e/argocd-mock/main.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"flag"
45
"fmt"
56
"log/slog"
67
"net/http"
@@ -11,13 +12,18 @@ import (
1112
)
1213

1314
func main() {
14-
listen := os.Getenv("ARGOCD_SERVER_LISTEN")
15-
token := os.Getenv("ARGOCD_SERVER_TOKEN")
16-
debug := os.Getenv("ARGOCD_SERVER_DEBUG")
15+
16+
var listen string
17+
var token string
18+
var debug bool
19+
flag.StringVar(&listen, "listen", "", "listen address")
20+
flag.StringVar(&token, "token", "", "token")
21+
flag.BoolVar(&debug, "debug", false, "debug mode")
22+
flag.Parse()
1723

1824
lvl := new(slog.LevelVar)
1925
lvl.Set(slog.LevelInfo)
20-
if debug == "true" {
26+
if debug {
2127
lvl.Set(slog.LevelDebug)
2228
}
2329
logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{

test/e2e/server_test.go

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/json"
66
"errors"
77
"fmt"
8+
"net/http"
89
"os"
910
"os/exec"
1011
"strconv"
@@ -23,10 +24,18 @@ import (
2324
// Note: make sure you ran `task install` before running this test
2425
// ------------------------------------------------------------------------------------------------
2526

27+
const (
28+
MCPServerListen = "localhost:50081"
29+
MCPServerDebug = true
30+
ArgoCDMockListen = "localhost:50084"
31+
ArgoCDMockToken = "secure-token"
32+
ArgoCDMockDebug = true
33+
)
34+
2635
func TestServer(t *testing.T) {
2736

2837
// start the argocd mock server
29-
cmd := exec.CommandContext(context.Background(), "argocd-mock")
38+
cmd := exec.CommandContext(context.Background(), "argocd-mock", "--listen", ArgoCDMockListen, "--token", ArgoCDMockToken, "--debug", strconv.FormatBool(ArgoCDMockDebug)) //nolint:gosec // (it's ok to use `strconv.FormatBool`)
3039
cmd.Stdout = os.Stdout
3140
cmd.Stderr = os.Stderr
3241
go func() {
@@ -42,23 +51,17 @@ func TestServer(t *testing.T) {
4251
t.Logf("killed the Argo CD mock server: %v", cmd.String())
4352
}()
4453

45-
os.Setenv("MCP_SERVER_LISTEN", "localhost:50081")
46-
os.Setenv("MCP_SERVER_DEBUG", "true")
47-
os.Setenv("ARGOCD_SERVER_LISTEN", "localhost:50084")
48-
os.Setenv("ARGOCD_SERVER_TOKEN", "secure-token")
49-
os.Setenv("ARGOCD_SERVER_DEBUG", "true")
50-
5154
testdata := []struct {
5255
name string
5356
init func(*testing.T) (*mcp.ClientSession, KillMCPServerFunc)
5457
}{
5558
{
5659
name: "stdio",
57-
init: newStdioSession("localhost:50081", true, "http://localhost:50084", "secure-token"),
60+
init: newStdioSession(MCPServerListen, MCPServerDebug, "http://"+ArgoCDMockListen, ArgoCDMockToken),
5861
},
5962
{
6063
name: "http",
61-
init: newHTTPSession("localhost:50081", true, "http://localhost:50084", "secure-token"),
64+
init: newHTTPSession(MCPServerListen, MCPServerDebug, "http://"+ArgoCDMockListen, ArgoCDMockToken),
6265
},
6366
}
6467

@@ -182,11 +185,11 @@ func TestServer(t *testing.T) {
182185
}{
183186
{
184187
name: "stdio",
185-
init: newStdioSession("localhost:50081", true, "http://localhost:50085", "another-token"), // invalid URL and token for the Argo CD server
188+
init: newStdioSession(MCPServerListen, MCPServerDebug, "http://localhost:50085", "another-token"), // invalid URL and token for the Argo CD server
186189
},
187190
{
188191
name: "http",
189-
init: newHTTPSession("localhost:50081", true, "http://localhost:50085", "another-token"), // invalid URL and token for the Argo CD server
192+
init: newHTTPSession(MCPServerListen, MCPServerDebug, "http://localhost:50085", "another-token"), // invalid URL and token for the Argo CD server
190193
},
191194
}
192195

@@ -214,10 +217,10 @@ func TestServer(t *testing.T) {
214217

215218
type KillMCPServerFunc func()
216219

217-
func newStdioSession(mcpServerListen string, mcpServerDebug bool, argocdURL string, argocdToken string) func(*testing.T) (*mcp.ClientSession, KillMCPServerFunc) {
220+
func newStdioSession(mcpServerListenPort string, mcpServerDebug bool, argocdURL string, argocdToken string) func(*testing.T) (*mcp.ClientSession, KillMCPServerFunc) {
218221
return func(t *testing.T) (*mcp.ClientSession, KillMCPServerFunc) {
219222
ctx := context.Background()
220-
cmd := newServerCmd(ctx, "stdio", mcpServerListen, strconv.FormatBool(mcpServerDebug), argocdURL, argocdToken)
223+
cmd := newServerCmd(ctx, "stdio", mcpServerListenPort, strconv.FormatBool(mcpServerDebug), argocdURL, argocdToken)
221224
cl := mcp.NewClient(&mcp.Implementation{Name: "e2e-test-client", Version: "v1.0.0"}, nil)
222225
session, err := cl.Connect(ctx, &mcp.CommandTransport{Command: cmd}, nil)
223226
require.NoError(t, err)
@@ -241,13 +244,17 @@ func newHTTPSession(mcpServerListen string, mcpServerDebug bool, argocdURL strin
241244
}
242245
}
243246
}()
244-
time.Sleep(5 * time.Second)
247+
cmd.Stderr = os.Stdout
248+
t.Logf("waiting for the MCP server to start")
249+
err := waitForMCPServer(mcpServerListen)
250+
require.NoError(t, err, "failed to wait for the MCP server to start")
251+
245252
cl := mcp.NewClient(&mcp.Implementation{Name: "e2e-test-client", Version: "v1.0.0"}, nil)
246253
session, err := cl.Connect(ctx, &mcp.StreamableClientTransport{
247254
MaxRetries: 5,
248-
Endpoint: fmt.Sprintf("http://%s/mcp", os.Getenv("MCP_SERVER_LISTEN")),
255+
Endpoint: fmt.Sprintf("http://%s/mcp", mcpServerListen),
249256
}, nil)
250-
require.NoError(t, err)
257+
require.NoError(t, err, "failed to connect to the MCP server")
251258
return session, func() {
252259
t.Logf("killing the MCP server")
253260
if err := cmd.Process.Kill(); err != nil {
@@ -258,6 +265,26 @@ func newHTTPSession(mcpServerListen string, mcpServerDebug bool, argocdURL strin
258265
}
259266
}
260267

268+
func waitForMCPServer(mcpServerListen string) error {
269+
// wait until the MCP server is ready to accept connections
270+
for {
271+
req, err := http.NewRequestWithContext(context.Background(), "GET", fmt.Sprintf("http://%s/health", mcpServerListen), nil)
272+
if err != nil {
273+
return fmt.Errorf("failed to create request: %w", err)
274+
}
275+
resp, err := http.DefaultClient.Do(req)
276+
if err != nil {
277+
continue
278+
}
279+
defer resp.Body.Close()
280+
if resp.StatusCode == http.StatusOK {
281+
break
282+
}
283+
time.Sleep(1 * time.Second)
284+
}
285+
return nil
286+
}
287+
261288
func newServerCmd(ctx context.Context, transport string, mcpServerListen string, mcpServerDebug string, argocdURL string, argocdToken string) *exec.Cmd {
262289
return exec.CommandContext(ctx,
263290
"argocd-mcp-server",

0 commit comments

Comments
 (0)