Skip to content
Merged
Show file tree
Hide file tree
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
27 changes: 27 additions & 0 deletions test/e2e/images/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,33 @@ const (
// Provides ~64 PagerDuty incident management tools (incidents, services, schedules, etc.).
PagerDutyMCPServerImage = pagerdutyMCPServerImageURL + ":" + pagerdutyMCPServerImageTag

timeMCPServerImageURL = "ghcr.io/stacklok/dockyard/uvx/mcp-server-time"
timeMCPServerImageTag = "2026.7.10"
// timeMCPServerImageDigest pins the 2026-07-27 build of tag 2026.7.10.
//
// Same failure mode as idaProMCPServerImageDigest above, different symptom:
// the tag is mutable, dockyard rebuilds it and resolves Python dependencies
// fresh, and the 2026-07-31 rebuild picked up the mcp Python SDK 2.0.0
// released 2026-07-28. mcp-server-time imports McpError from
// mcp.shared.exceptions, which 2.x moved, so the container now exits on
// startup with "ImportError: cannot import name 'McpError' from
// 'mcp.shared.exceptions'". The proxy suites then fail with
// "timeout waiting for MCP server to be ready".
//
// Pin the last build that resolved a 1.x mcp until upstream caps the
// constraint or adopts the 2.x API. Verified by driving both builds over
// stdio: the pinned digest answers initialize, tag 2026.7.10 does not.
timeMCPServerImageDigest = "sha256:5cca77dec3fefbacad35e3008ab1660f8725ef246213afb24231504fc73c999d"
// TimeMCPServerImage is the stdio backend used by the proxy e2e suites
// (proxy_stdio_test.go, stdio_proxy_over_streamable_http_mcp_server_test.go).
// Provides get_current_time / convert_time.
//
// These suites reference this constant rather than the "time" registry entry
// so a mutable upstream tag cannot break CI: the registry resolves "time" to
// the moving :2026.7.10 tag, which is currently broken. Registry-name
// resolution itself is still covered by the suites that run "osv".
TimeMCPServerImage = timeMCPServerImageURL + ":" + timeMCPServerImageTag + "@" + timeMCPServerImageDigest

redisImageURL = "redis"
redisImageTag = "7-alpine"
// RedisImage is used for Redis-backed session storage in scaling tests.
Expand Down
5 changes: 3 additions & 2 deletions test/e2e/proxy_stdio_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (

"github.com/stacklok/toolhive/pkg/transport/types"
"github.com/stacklok/toolhive/test/e2e"
"github.com/stacklok/toolhive/test/e2e/images"
)

const (
Expand Down Expand Up @@ -183,7 +184,7 @@ var _ = Describe("Proxy Stdio E2E", Label("proxy", "stdio", "e2e"), Serial, func
BeforeEach(func() {
transportType = types.TransportTypeStdio
proxyMode = "sse"
mcpServerName = "time"
mcpServerName = images.TimeMCPServerImage
})
It("should proxy MCP requests successfully", func() {
By("Getting time server URL")
Expand Down Expand Up @@ -234,7 +235,7 @@ var _ = Describe("Proxy Stdio E2E", Label("proxy", "stdio", "e2e"), Serial, func
BeforeEach(func() {
transportType = types.TransportTypeStdio
proxyMode = "streamable-http"
mcpServerName = "time"
mcpServerName = images.TimeMCPServerImage
})
It("should proxy MCP requests successfully", func() {
By("Getting time server URL")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
. "github.com/onsi/gomega"

"github.com/stacklok/toolhive/test/e2e"
"github.com/stacklok/toolhive/test/e2e/images"
)

var _ = Describe("TimeStreamableHttpMcpServer", Label("proxy", "streamable-http", "e2e"), Serial, func() {
Expand Down Expand Up @@ -44,8 +45,9 @@ var _ = Describe("TimeStreamableHttpMcpServer", Label("proxy", "streamable-http"
By("Starting the time MCP server with streamable-http proxy")
e2e.NewTHVCommand(config, "run",
"--name", serverName,
"--transport", "stdio",
"--proxy-mode", "streamable-http",
"time").ExpectSuccess()
images.TimeMCPServerImage).ExpectSuccess()

By("Waiting for the server to be running")
err := e2e.WaitForMCPServer(config, serverName, 60*time.Second)
Expand Down
Loading