Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.25.0

require (
github.com/BurntSushi/toml v1.6.0
github.com/modelcontextprotocol/go-sdk v1.4.1
github.com/modelcontextprotocol/go-sdk v1.5.0
github.com/spf13/cobra v1.10.2
golang.org/x/term v0.41.0
)
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY=
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
Expand All @@ -34,8 +34,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/modelcontextprotocol/go-sdk v1.4.1 h1:M4x9GyIPj+HoIlHNGpK2hq5o3BFhC+78PkEaldQRphc=
github.com/modelcontextprotocol/go-sdk v1.4.1/go.mod h1:Bo/mS87hPQqHSRkMv4dQq1XCu6zv4INdXnFZabkNU6s=
github.com/modelcontextprotocol/go-sdk v1.5.0 h1:CHU0FIX9kpueNkxuYtfYQn1Z0slhFzBZuq+x6IiblIU=
github.com/modelcontextprotocol/go-sdk v1.5.0/go.mod h1:gggDIhoemhWs3BGkGwd1umzEXCEMMvAnhTrnbXJKKKA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
Expand Down
8 changes: 4 additions & 4 deletions internal/mcp/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,10 +248,10 @@ func NewHTTPConnection(ctx context.Context, serverID, url string, headers map[st
conn, err = trySSETransport(ctx, cancel, serverID, url, headers, headerClient, keepAlive)
if err == nil {
logger.LogWarn("backend", "⚠️ MCP over SSE has been deprecated. Connected using SSE transport for url=%s. Please migrate to streamable HTTP transport (2025-03-26 spec).", url)
log.Printf("⚠️ WARNING: MCP over SSE (2024-11-05 spec) has been DEPRECATED")
log.Printf("⚠️ The server at %s is using the deprecated SSE transport", url)
log.Printf("⚠️ Please migrate to streamable HTTP transport (2025-03-26 spec)")
log.Printf("Configured HTTP MCP server with SSE transport: %s", url)
logger.LogWarn("backend", "⚠️ WARNING: MCP over SSE (2024-11-05 spec) has been DEPRECATED")
logger.LogWarn("backend", "⚠️ The server at %s is using the deprecated SSE transport", url)
logger.LogWarn("backend", "⚠️ Please migrate to streamable HTTP transport (2025-03-26 spec)")
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logConn.Printf is DEBUG-gated (and logs at debug level to the file logger), so this message will no longer be visible by default (unlike the previous log.Printf) and may not land in mcp-gateway.log at WARN/INFO. If this line is intended as part of the SSE deprecation/operator visibility, route it through the structured logger too (e.g., logger.LogWarn/LogInfo) for consistency with the other deprecation messages.

Suggested change
logger.LogWarn("backend", "⚠️ Please migrate to streamable HTTP transport (2025-03-26 spec)")
logger.LogWarn("backend", "⚠️ Please migrate to streamable HTTP transport (2025-03-26 spec)")
logger.LogWarn("backend", "Configured HTTP MCP server with SSE transport: %s", url)

Copilot uses AI. Check for mistakes.
logConn.Printf("Configured HTTP MCP server with SSE transport: %s", url)
return conn, nil
}
logConn.Printf("SSE transport failed: %v", err)
Expand Down
7 changes: 6 additions & 1 deletion internal/mcp/http_transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,17 @@ func isHTTPConnectionError(err error) bool {
return false
}

// isSessionNotFoundError checks if an error message indicates a backend MCP session has expired
// isSessionNotFoundError checks if an error indicates a backend MCP session has expired
// or is not found. This is used to detect when automatic reconnection to the backend is needed.
// It uses errors.Is to check for sdk.ErrSessionMissing (the typed sentinel introduced in v1.5.0),
// and also falls back to string-matching for non-SDK transports that return plain error messages.
func isSessionNotFoundError(err error) bool {
if err == nil {
return false
}
if errors.Is(err, sdk.ErrSessionMissing) {
return true
}
Comment on lines 74 to +80
Copy link

Copilot AI Apr 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new errors.Is(err, sdk.ErrSessionMissing) branch isn’t covered by the existing TestIsSessionNotFoundError cases (which only exercise string matching). Add a test that passes sdk.ErrSessionMissing (and ideally a wrapped %w form) so this typed-sentinel detection is validated and won’t silently regress on future SDK upgrades.

Copilot uses AI. Check for mistakes.
return strings.Contains(strings.ToLower(err.Error()), "session not found")
}

Expand Down
9 changes: 6 additions & 3 deletions internal/server/tool_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,12 @@ type launchResult struct {
// The wrapper in this function adapts the three-argument form back to the SDK's two-argument
// form when registering with the SDK server.
//
// NOTE: The Server.AddTool method (used here) skips JSON Schema validation whereas the
// sdk.AddTool function validates the schema. This distinction relies on internal SDK
// behaviour and must be re-verified on every SDK upgrade.
// NOTE: The Server.AddTool method (used here) does not validate tool arguments against the
// input schema at call time, whereas the package-level sdk.AddTool function does. The method
// does require that InputSchema is non-nil and has type "object" (enforced since v1.5.0), but
// it does not validate the argument values — that responsibility belongs to the caller.
// This distinction relies on internal SDK behaviour and must be re-verified on every SDK upgrade.
// Verified correct for go-sdk v1.5.0 (see server.go:Server.AddTool vs AddTool[In,Out]).
func registerToolWithoutValidation(server *sdk.Server, tool *sdk.Tool, handler func(context.Context, *sdk.CallToolRequest, interface{}) (*sdk.CallToolResult, interface{}, error)) {
server.AddTool(tool, func(ctx context.Context, req *sdk.CallToolRequest) (*sdk.CallToolResult, error) {
result, _, err := handler(ctx, req, nil)
Expand Down
Loading