diff --git a/pkg/github/server.go b/pkg/github/server.go index 06c12575d..16ba6c951 100644 --- a/pkg/github/server.go +++ b/pkg/github/server.go @@ -101,7 +101,7 @@ func NewMCPServer(ctx context.Context, cfg *MCPServerConfig, deps ToolDependenci } } - ghServer := NewServer(cfg.Version, serverOpts) + ghServer := NewServer(cfg.Version, cfg.Translator("SERVER_NAME", "github-mcp-server"), cfg.Translator("SERVER_TITLE", "GitHub MCP Server"), serverOpts) // Add middlewares. Order matters - for example, the error context middleware should be applied last so that it runs FIRST (closest to the handler) to ensure all errors are captured, // and any middleware that needs to read or modify the context should be before it. @@ -177,15 +177,22 @@ func addGitHubAPIErrorToContext(next mcp.MethodHandler) mcp.MethodHandler { } // NewServer creates a new GitHub MCP server with the specified GH client and logger. -func NewServer(version string, opts *mcp.ServerOptions) *mcp.Server { +func NewServer(version, name, title string, opts *mcp.ServerOptions) *mcp.Server { if opts == nil { opts = &mcp.ServerOptions{} } + if name == "" { + name = "github-mcp-server" + } + if title == "" { + title = "GitHub MCP Server" + } + // Create a new MCP server s := mcp.NewServer(&mcp.Implementation{ - Name: "github-mcp-server", - Title: "GitHub MCP Server", + Name: name, + Title: title, Version: version, Icons: octicons.Icons("mark-github"), }, opts) diff --git a/pkg/github/server_test.go b/pkg/github/server_test.go index 2b99cab12..c815d5fa0 100644 --- a/pkg/github/server_test.go +++ b/pkg/github/server_test.go @@ -13,6 +13,7 @@ import ( "github.com/github/github-mcp-server/pkg/raw" "github.com/github/github-mcp-server/pkg/translations" gogithub "github.com/google/go-github/v82/github" + "github.com/modelcontextprotocol/go-sdk/mcp" "github.com/shurcooL/githubv4" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -150,6 +151,91 @@ func TestNewMCPServer_CreatesSuccessfully(t *testing.T) { // is already tested in pkg/github/*_test.go. } +// TestNewServer_NameAndTitleViaTranslation verifies that server name and title +// can be overridden via the translation helper (GITHUB_MCP_SERVER_NAME / +// GITHUB_MCP_SERVER_TITLE env vars or github-mcp-server-config.json) and +// fall back to sensible defaults when not overridden. +func TestNewServer_NameAndTitleViaTranslation(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + translator translations.TranslationHelperFunc + expectedName string + expectedTitle string + }{ + { + name: "defaults when using NullTranslationHelper", + translator: translations.NullTranslationHelper, + expectedName: "github-mcp-server", + expectedTitle: "GitHub MCP Server", + }, + { + name: "custom name and title via translator", + translator: func(key, defaultValue string) string { + switch key { + case "SERVER_NAME": + return "my-github-server" + case "SERVER_TITLE": + return "My GitHub MCP Server" + default: + return defaultValue + } + }, + expectedName: "my-github-server", + expectedTitle: "My GitHub MCP Server", + }, + { + name: "custom name only via translator", + translator: func(key, defaultValue string) string { + if key == "SERVER_NAME" { + return "ghes-server" + } + return defaultValue + }, + expectedName: "ghes-server", + expectedTitle: "GitHub MCP Server", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + srv := NewServer("v1.0.0", tt.translator("SERVER_NAME", "github-mcp-server"), tt.translator("SERVER_TITLE", "GitHub MCP Server"), nil) + require.NotNil(t, srv) + + // Connect a client to retrieve the initialize result and verify ServerInfo. + st, ct := mcp.NewInMemoryTransports() + client := mcp.NewClient(&mcp.Implementation{Name: "test-client"}, nil) + + type clientResult struct { + result *mcp.InitializeResult + err error + } + clientResultCh := make(chan clientResult, 1) + go func() { + cs, err := client.Connect(context.Background(), ct, nil) + if err != nil { + clientResultCh <- clientResult{err: err} + return + } + clientResultCh <- clientResult{result: cs.InitializeResult()} + }() + + _, err := srv.Connect(context.Background(), st, nil) + require.NoError(t, err) + + got := <-clientResultCh + require.NoError(t, got.err) + require.NotNil(t, got.result) + require.NotNil(t, got.result.ServerInfo) + assert.Equal(t, tt.expectedName, got.result.ServerInfo.Name) + assert.Equal(t, tt.expectedTitle, got.result.ServerInfo.Title) + }) + } +} + // TestResolveEnabledToolsets verifies the toolset resolution logic. func TestResolveEnabledToolsets(t *testing.T) { t.Parallel()