Commit c5ab415
Changed files (1)
test
integration
test/integration/main_test.go
@@ -97,24 +97,24 @@ type MCPServer struct {
// NewMCPServer creates and starts a new MCP server for testing
func NewMCPServer(binaryPath string, args ...string) (*MCPServer, error) {
cmd := exec.Command(binaryPath, args...)
-
+
stdin, err := cmd.StdinPipe()
if err != nil {
return nil, fmt.Errorf("failed to create stdin pipe: %w", err)
}
-
+
stdout, err := cmd.StdoutPipe()
if err != nil {
stdin.Close()
return nil, fmt.Errorf("failed to create stdout pipe: %w", err)
}
-
+
if err := cmd.Start(); err != nil {
stdin.Close()
stdout.Close()
return nil, fmt.Errorf("failed to start server: %w", err)
}
-
+
return &MCPServer{
cmd: cmd,
stdin: stdin,
@@ -129,18 +129,18 @@ func (s *MCPServer) SendRequest(req JSONRPCRequest) (*JSONRPCResponse, error) {
if err != nil {
return nil, fmt.Errorf("failed to marshal request: %w", err)
}
-
+
// Send request
_, err = s.stdin.Write(append(reqBytes, '\n'))
if err != nil {
return nil, fmt.Errorf("failed to write request: %w", err)
}
-
+
// Read response with timeout
scanner := bufio.NewScanner(s.stdout)
responseChan := make(chan string, 1)
errorChan := make(chan error, 1)
-
+
go func() {
if scanner.Scan() {
responseChan <- scanner.Text()
@@ -150,7 +150,7 @@ func (s *MCPServer) SendRequest(req JSONRPCRequest) (*JSONRPCResponse, error) {
errorChan <- fmt.Errorf("EOF")
}
}()
-
+
select {
case responseText := <-responseChan:
var resp JSONRPCResponse
@@ -174,16 +174,16 @@ func (s *MCPServer) Close() error {
Method: "shutdown",
}
s.SendRequest(shutdownReq)
-
+
s.stdin.Close()
s.stdout.Close()
-
+
// Wait for process to exit or kill it
done := make(chan error, 1)
go func() {
done <- s.cmd.Wait()
}()
-
+
select {
case <-done:
return nil
@@ -217,7 +217,7 @@ func getBinaryPath(binaryName string) string {
func TestAllServers(t *testing.T) {
// Create temp directories for testing
tempDir := t.TempDir()
-
+
servers := []ServerTestConfig{
{
BinaryName: "mcp-filesystem",
@@ -275,8 +275,15 @@ func TestAllServers(t *testing.T) {
ExpectedServers: "imap",
MinResources: 0, // No static resources (connection fails gracefully)
},
+ {
+ BinaryName: "mcp-bash",
+ Args: []string{},
+ ExpectedTools: []string{"bash_exec", "system_info", "get_env"},
+ ExpectedServers: "bash",
+ MinResources: 0, // Bash server has resources but they're dynamically registered
+ },
}
-
+
for _, config := range servers {
t.Run(config.BinaryName, func(t *testing.T) {
testServer(t, config)
@@ -287,19 +294,19 @@ func TestAllServers(t *testing.T) {
// testServer tests a single MCP server
func testServer(t *testing.T, config ServerTestConfig) {
binaryPath := getBinaryPath(config.BinaryName)
-
+
// Check if binary exists
if _, err := os.Stat(binaryPath); os.IsNotExist(err) {
t.Fatalf("Binary not found: %s (run 'make build' first)", binaryPath)
}
-
+
// Start server
server, err := NewMCPServer(binaryPath, config.Args...)
if err != nil {
t.Fatalf("Failed to start server: %v", err)
}
defer server.Close()
-
+
// Test initialization
initReq := JSONRPCRequest{
JSONRPC: "2.0",
@@ -314,87 +321,87 @@ func testServer(t *testing.T, config ServerTestConfig) {
},
},
}
-
+
resp, err := server.SendRequest(initReq)
if err != nil {
t.Fatalf("Failed to send initialize request: %v", err)
}
-
+
if resp.Error != nil {
t.Fatalf("Initialize request failed: %v", resp.Error)
}
-
+
var initResult InitializeResult
if err := json.Unmarshal(resp.Result, &initResult); err != nil {
t.Fatalf("Failed to parse initialize response: %v", err)
}
-
+
if initResult.ProtocolVersion != "2024-11-05" {
t.Errorf("Expected protocol version 2024-11-05, got %s", initResult.ProtocolVersion)
}
-
+
if initResult.ServerInfo.Name != config.ExpectedServers {
t.Errorf("Expected server name %s, got %s", config.ExpectedServers, initResult.ServerInfo.Name)
}
-
+
// Test tools/list
toolsReq := JSONRPCRequest{
JSONRPC: "2.0",
ID: 2,
Method: "tools/list",
}
-
+
resp, err = server.SendRequest(toolsReq)
if err != nil {
t.Fatalf("Failed to send tools/list request: %v", err)
}
-
+
if resp.Error != nil {
t.Fatalf("Tools/list request failed: %v", resp.Error)
}
-
+
var toolsResult ListToolsResult
if err := json.Unmarshal(resp.Result, &toolsResult); err != nil {
t.Fatalf("Failed to parse tools/list response: %v", err)
}
-
+
// Check that expected tools are present
toolNames := make(map[string]bool)
for _, tool := range toolsResult.Tools {
toolNames[tool.Name] = true
}
-
+
for _, expectedTool := range config.ExpectedTools {
if !toolNames[expectedTool] {
t.Errorf("Expected tool %s not found in tools list", expectedTool)
}
}
-
+
// Test resources/list
resourcesReq := JSONRPCRequest{
JSONRPC: "2.0",
ID: 3,
Method: "resources/list",
}
-
+
resp, err = server.SendRequest(resourcesReq)
if err != nil {
t.Fatalf("Failed to send resources/list request: %v", err)
}
-
+
if resp.Error != nil {
t.Fatalf("Resources/list request failed: %v", resp.Error)
}
-
+
var resourcesResult ListResourcesResult
if err := json.Unmarshal(resp.Result, &resourcesResult); err != nil {
t.Fatalf("Failed to parse resources/list response: %v", err)
}
-
+
if len(resourcesResult.Resources) < config.MinResources {
t.Errorf("Expected at least %d resources, got %d", config.MinResources, len(resourcesResult.Resources))
}
-
+
// Validate that resources have required fields
for _, resource := range resourcesResult.Resources {
if resource.URI == "" {
@@ -407,35 +414,36 @@ func testServer(t *testing.T, config ServerTestConfig) {
t.Errorf("Resource URI should contain scheme: %s", resource.URI)
}
}
-
+
t.Logf("✅ %s: %d tools, %d resources", config.BinaryName, len(toolsResult.Tools), len(resourcesResult.Resources))
}
// TestServerStartupPerformance tests that servers start quickly
func TestServerStartupPerformance(t *testing.T) {
tempDir := t.TempDir()
-
+
servers := []string{
"mcp-filesystem",
- "mcp-git",
+ "mcp-git",
"mcp-memory",
"mcp-fetch",
"mcp-time",
"mcp-sequential-thinking",
"mcp-maildir",
"mcp-imap",
+ "mcp-bash",
}
-
+
for _, serverName := range servers {
t.Run(serverName, func(t *testing.T) {
binaryPath := getBinaryPath(serverName)
-
+
if _, err := os.Stat(binaryPath); os.IsNotExist(err) {
t.Skip("Binary not found")
}
-
+
start := time.Now()
-
+
var args []string
switch serverName {
case "mcp-filesystem":
@@ -447,13 +455,13 @@ func TestServerStartupPerformance(t *testing.T) {
case "mcp-imap":
args = []string{"--server", "example.com", "--username", "test", "--password", "test"}
}
-
+
server, err := NewMCPServer(binaryPath, args...)
if err != nil {
t.Fatalf("Failed to start server: %v", err)
}
defer server.Close()
-
+
// Send initialize request to confirm server is ready
initReq := JSONRPCRequest{
JSONRPC: "2.0",
@@ -465,14 +473,14 @@ func TestServerStartupPerformance(t *testing.T) {
ClientInfo: ClientInfo{Name: "test", Version: "1.0.0"},
},
}
-
+
_, err = server.SendRequest(initReq)
if err != nil {
t.Fatalf("Server not responding: %v", err)
}
-
+
duration := time.Since(start)
-
+
// Servers should start and respond within 500ms for good performance
if duration > 500*time.Millisecond {
t.Errorf("Server %s took %v to start, expected < 500ms", serverName, duration)
@@ -481,4 +489,4 @@ func TestServerStartupPerformance(t *testing.T) {
}
})
}
-}
\ No newline at end of file
+}