Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
210 changes: 210 additions & 0 deletions test/e2e/fetch_mcp_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"net/http"
"os"
"strings"
"time"

Expand Down Expand Up @@ -110,6 +111,215 @@ var _ = Describe("FetchMcpServer", Label("mcp", "e2e"), func() {
})
})

Context("when starting the server from registry with tools override", Label("override"), func() {
var (
toolsOverrideFile string
tempDir string
)

BeforeEach(func() {
// Create temporary directory for tool override files
tempDir = GinkgoT().TempDir()
})

It("should start with valid tool override and show overridden tool names", func() {
By("Creating a valid tool override JSON file")
toolsOverrideContent := `{
"toolsOverride": {
"fetch": {
"name": "custom_fetch_tool",
"description": "A customized fetch tool with overridden name and description"
}
}
}`
toolsOverrideFile = tempDir + "/tools_override.json"
err := os.WriteFile(toolsOverrideFile, []byte(toolsOverrideContent), 0644)
Expect(err).ToNot(HaveOccurred(), "Should be able to create tool override file")

By("Starting the fetch MCP server with tool override")
stdout, stderr := e2e.NewTHVCommand(config, "run", "--name", serverName, "fetch", "--tools-override", toolsOverrideFile).ExpectSuccess()

// The command should indicate success
Expect(stdout+stderr).To(ContainSubstring("fetch"), "Output should mention the fetch server")

By("Waiting for the server to be running")
err = e2e.WaitForMCPServer(config, serverName, 60*time.Second)
Expect(err).ToNot(HaveOccurred(), "Server should be running within 60 seconds")

By("Verifying the server appears in the list")
stdout, _ = e2e.NewTHVCommand(config, "list").ExpectSuccess()
Expect(stdout).To(ContainSubstring(serverName), "Server should appear in the list")
Expect(stdout).To(ContainSubstring("running"), "Server should be in running state")

By("Verifying tool override is applied by listing tools")
stdout, _ = e2e.NewTHVCommand(config, "mcp", "list", "tools", "--server", serverName, "--timeout", "60s").ExpectSuccess()
Expect(stdout).To(ContainSubstring("custom_fetch_tool"), "Should show overridden tool name")
Expect(stdout).To(ContainSubstring("customized fetch tool"), "Should show overridden tool description")
})

It("should start with tool override that only changes description", func() {
By("Creating a tool override JSON file with only description override")
toolsOverrideContent := `{
"toolsOverride": {
"fetch": {
"description": "An enhanced fetch tool with custom description only"
}
}
}`
toolsOverrideFile = tempDir + "/tools_override_desc_only.json"
err := os.WriteFile(toolsOverrideFile, []byte(toolsOverrideContent), 0644)
Expect(err).ToNot(HaveOccurred(), "Should be able to create tool override file")

By("Starting the fetch MCP server with description-only tool override")
stdout, stderr := e2e.NewTHVCommand(config, "run", "--name", serverName, "fetch", "--tools-override", toolsOverrideFile).ExpectSuccess()

// The command should indicate success
Expect(stdout+stderr).To(ContainSubstring("fetch"), "Output should mention the fetch server")

By("Waiting for the server to be running")
err = e2e.WaitForMCPServer(config, serverName, 60*time.Second)
Expect(err).ToNot(HaveOccurred(), "Server should be running within 60 seconds")

By("Verifying tool override is applied by listing tools")
stdout, _ = e2e.NewTHVCommand(config, "mcp", "list", "tools", "--server", serverName, "--timeout", "60s").ExpectSuccess()
Expect(stdout).To(ContainSubstring("fetch"), "Should still show original tool name")
Expect(stdout).To(ContainSubstring("enhanced fetch tool"), "Should show overridden tool description")
})

It("should start with tool override that only changes name", func() {
By("Creating a tool override JSON file with only name override")
toolsOverrideContent := `{
"toolsOverride": {
"fetch": {
"name": "renamed_fetch"
}
}
}`
toolsOverrideFile = tempDir + "/tools_override_name_only.json"
err := os.WriteFile(toolsOverrideFile, []byte(toolsOverrideContent), 0644)
Expect(err).ToNot(HaveOccurred(), "Should be able to create tool override file")

By("Starting the fetch MCP server with name-only tool override")
stdout, stderr := e2e.NewTHVCommand(config, "run", "--name", serverName, "fetch", "--tools-override", toolsOverrideFile).ExpectSuccess()

// The command should indicate success
Expect(stdout+stderr).To(ContainSubstring("fetch"), "Output should mention the fetch server")

By("Waiting for the server to be running")
err = e2e.WaitForMCPServer(config, serverName, 60*time.Second)
Expect(err).ToNot(HaveOccurred(), "Server should be running within 60 seconds")

By("Verifying tool override is applied by listing tools")
stdout, _ = e2e.NewTHVCommand(config, "mcp", "list", "tools", "--server", serverName, "--timeout", "60s").ExpectSuccess()
Expect(stdout).To(ContainSubstring("renamed_fetch"), "Should show overridden tool name")
})

It("should fail when tool override file has invalid JSON", func() {
By("Creating an invalid tool override JSON file")
toolsOverrideContent := `{
"toolsOverride": {
"fetch": {
"name": "invalid_json"
}
// Missing closing brace
}`
toolsOverrideFile = tempDir + "/invalid_tools_override.json"
err := os.WriteFile(toolsOverrideFile, []byte(toolsOverrideContent), 0644)
Expect(err).ToNot(HaveOccurred(), "Should be able to create invalid tool override file")

By("Attempting to start the fetch MCP server with invalid tool override")
_, _, err = e2e.NewTHVCommand(config, "run", "--name", serverName, "fetch", "--tools-override", toolsOverrideFile).ExpectFailure()
Expect(err).To(HaveOccurred(), "Should fail with invalid JSON")
})

It("should fail when tool override file does not exist", func() {
By("Attempting to start the fetch MCP server with non-existent tool override file")
_, _, err := e2e.NewTHVCommand(config, "run", "--name", serverName, "fetch", "--tools-override", "/non/existent/file.json").ExpectFailure()
Expect(err).To(HaveOccurred(), "Should fail with non-existent file")
})

It("should fail when tool override has empty name and description", func() {
By("Creating a tool override JSON file with empty override")
toolsOverrideContent := `{
"toolsOverride": {
"fetch": {
"name": "",
"description": ""
}
}
}`
toolsOverrideFile = tempDir + "/empty_tools_override.json"
err := os.WriteFile(toolsOverrideFile, []byte(toolsOverrideContent), 0644)
Expect(err).ToNot(HaveOccurred(), "Should be able to create empty tool override file")

By("Attempting to start the fetch MCP server with empty tool override")
_, _, err = e2e.NewTHVCommand(config, "run", "--name", serverName, "fetch", "--tools-override", toolsOverrideFile).ExpectFailure()
Expect(err).To(HaveOccurred(), "Should fail with empty tool override")
})
})

Context("when combining tools filter with tools override", Label("override", "filter"), func() {
var (
toolsOverrideFile string
tempDir string
)

BeforeEach(func() {
// Create temporary directory for tool override files
tempDir = GinkgoT().TempDir()
})

It("should apply both filter and override correctly", func() {
By("Creating a tool override JSON file")
toolsOverrideContent := `{
"toolsOverride": {
"fetch": {
"name": "filtered_and_overridden_fetch",
"description": "A fetch tool that is both filtered and overridden"
}
}
}`
toolsOverrideFile = tempDir + "/combined_tools_override.json"
err := os.WriteFile(toolsOverrideFile, []byte(toolsOverrideContent), 0644)
Expect(err).ToNot(HaveOccurred(), "Should be able to create tool override file")

By("Starting the fetch MCP server with both tools filter and override")
stdout, stderr := e2e.NewTHVCommand(
config, "run", "--name", serverName, "fetch", "--tools", "filtered_and_overridden_fetch", "--tools-override", toolsOverrideFile).ExpectSuccess()

// The command should indicate success
Expect(stdout+stderr).To(ContainSubstring("fetch"), "Output should mention the fetch server")

By("Waiting for the server to be running")
err = e2e.WaitForMCPServer(config, serverName, 60*time.Second)
Expect(err).ToNot(HaveOccurred(), "Server should be running within 60 seconds")

By("Verifying both filter and override are applied by listing tools")
stdout, _ = e2e.NewTHVCommand(config, "mcp", "list", "tools", "--server", serverName, "--timeout", "60s").ExpectSuccess()
Expect(stdout).To(ContainSubstring("filtered_and_overridden_fetch"), "Should show overridden tool name")
Expect(stdout).To(ContainSubstring("filtered and overridden"), "Should show overridden tool description")
})

It("should fail when filtering out a tool that has an override", func() {
By("Creating a tool override JSON file for a tool that will be filtered out")
toolsOverrideContent := `{
"toolsOverride": {
"fetch": {
"name": "overridden_but_filtered_out",
"description": "This tool will be filtered out despite having an override"
}
}
}`
toolsOverrideFile = tempDir + "/filtered_out_override.json"
err := os.WriteFile(toolsOverrideFile, []byte(toolsOverrideContent), 0644)
Expect(err).ToNot(HaveOccurred(), "Should be able to create tool override file")

By("Attempting to start server with tool filter that excludes the overridden tool")
_, _, err = e2e.NewTHVCommand(config, "run", "--name", serverName, "fetch", "--tools", "non-existent-tool", "--tools-override", toolsOverrideFile).ExpectFailure()
Expect(err).To(HaveOccurred(), "Should fail when filtering out overridden tool")
})
})

Context("when managing the server lifecycle", func() {
BeforeEach(func() {
// Start a server for lifecycle tests
Expand Down
Loading