Skip to content

Commit 644fda6

Browse files
Add configurable server name and title via env/flag
Allows users running multiple GitHub MCP Server instances (e.g., for github.com and GitHub Enterprise Server) to override the server name and title in the MCP initialization response. - Add --server-name / GITHUB_SERVER_NAME flag+env to override name - Add --server-title / GITHUB_SERVER_TITLE flag+env to override title - Defaults remain "github-mcp-server" and "GitHub MCP Server" - Applies to both stdio and HTTP server modes - Add tests for default and custom name/title Co-authored-by: SamMorrowDrums <4811358+SamMorrowDrums@users.noreply.github.com>
1 parent 0f52067 commit 644fda6

File tree

6 files changed

+115
-5
lines changed

6 files changed

+115
-5
lines changed

cmd/github-mcp-server/main.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ var (
8080
ttl := viper.GetDuration("repo-access-cache-ttl")
8181
stdioServerConfig := ghmcp.StdioServerConfig{
8282
Version: version,
83+
Name: viper.GetString("server-name"),
84+
Title: viper.GetString("server-title"),
8385
Host: viper.GetString("host"),
8486
Token: token,
8587
EnabledToolsets: enabledToolsets,
@@ -108,6 +110,8 @@ var (
108110
ttl := viper.GetDuration("repo-access-cache-ttl")
109111
httpConfig := ghhttp.ServerConfig{
110112
Version: version,
113+
Name: viper.GetString("server-name"),
114+
Title: viper.GetString("server-title"),
111115
Host: viper.GetString("host"),
112116
Port: viper.GetInt("port"),
113117
BaseURL: viper.GetString("base-url"),
@@ -133,6 +137,8 @@ func init() {
133137
rootCmd.SetVersionTemplate("{{.Short}}\n{{.Version}}\n")
134138

135139
// Add global flags that will be shared by all commands
140+
rootCmd.PersistentFlags().String("server-name", "", "Override the server name in the MCP initialization response")
141+
rootCmd.PersistentFlags().String("server-title", "", "Override the server title in the MCP initialization response")
136142
rootCmd.PersistentFlags().StringSlice("toolsets", nil, github.GenerateToolsetsHelp())
137143
rootCmd.PersistentFlags().StringSlice("tools", nil, "Comma-separated list of specific tools to enable")
138144
rootCmd.PersistentFlags().StringSlice("exclude-tools", nil, "Comma-separated list of tool names to disable regardless of other settings")
@@ -155,6 +161,8 @@ func init() {
155161
httpCmd.Flags().Bool("scope-challenge", false, "Enable OAuth scope challenge responses")
156162

157163
// Bind flag to viper
164+
_ = viper.BindPFlag("server-name", rootCmd.PersistentFlags().Lookup("server-name"))
165+
_ = viper.BindPFlag("server-title", rootCmd.PersistentFlags().Lookup("server-title"))
158166
_ = viper.BindPFlag("toolsets", rootCmd.PersistentFlags().Lookup("toolsets"))
159167
_ = viper.BindPFlag("tools", rootCmd.PersistentFlags().Lookup("tools"))
160168
_ = viper.BindPFlag("exclude_tools", rootCmd.PersistentFlags().Lookup("exclude-tools"))

internal/ghmcp/server.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,14 @@ type StdioServerConfig struct {
171171
// Version of the server
172172
Version string
173173

174+
// Name overrides the server name in the MCP initialization response.
175+
// If empty, defaults to "github-mcp-server".
176+
Name string
177+
178+
// Title overrides the server title in the MCP initialization response.
179+
// If empty, defaults to "GitHub MCP Server".
180+
Title string
181+
174182
// GitHub Host to target for API requests (e.g. github.com or github.enterprise.com)
175183
Host string
176184

@@ -266,6 +274,8 @@ func RunStdioServer(cfg StdioServerConfig) error {
266274

267275
ghServer, err := NewStdioMCPServer(ctx, github.MCPServerConfig{
268276
Version: cfg.Version,
277+
Name: cfg.Name,
278+
Title: cfg.Title,
269279
Host: cfg.Host,
270280
Token: cfg.Token,
271281
EnabledToolsets: cfg.EnabledToolsets,

pkg/github/server.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ type MCPServerConfig struct {
2020
// Version of the server
2121
Version string
2222

23+
// Name overrides the server name in the MCP initialization response.
24+
// If empty, defaults to "github-mcp-server".
25+
Name string
26+
27+
// Title overrides the server title in the MCP initialization response.
28+
// If empty, defaults to "GitHub MCP Server".
29+
Title string
30+
2331
// GitHub Host to target for API requests (e.g. github.com or github.enterprise.com)
2432
Host string
2533

@@ -101,7 +109,7 @@ func NewMCPServer(ctx context.Context, cfg *MCPServerConfig, deps ToolDependenci
101109
}
102110
}
103111

104-
ghServer := NewServer(cfg.Version, serverOpts)
112+
ghServer := NewServer(cfg.Version, cfg.Name, cfg.Title, serverOpts)
105113

106114
// 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,
107115
// and any middleware that needs to read or modify the context should be before it.
@@ -177,15 +185,22 @@ func addGitHubAPIErrorToContext(next mcp.MethodHandler) mcp.MethodHandler {
177185
}
178186

179187
// NewServer creates a new GitHub MCP server with the specified GH client and logger.
180-
func NewServer(version string, opts *mcp.ServerOptions) *mcp.Server {
188+
func NewServer(version, name, title string, opts *mcp.ServerOptions) *mcp.Server {
181189
if opts == nil {
182190
opts = &mcp.ServerOptions{}
183191
}
184192

193+
if name == "" {
194+
name = "github-mcp-server"
195+
}
196+
if title == "" {
197+
title = "GitHub MCP Server"
198+
}
199+
185200
// Create a new MCP server
186201
s := mcp.NewServer(&mcp.Implementation{
187-
Name: "github-mcp-server",
188-
Title: "GitHub MCP Server",
202+
Name: name,
203+
Title: title,
189204
Version: version,
190205
Icons: octicons.Icons("mark-github"),
191206
}, opts)

pkg/github/server_test.go

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/github/github-mcp-server/pkg/raw"
1414
"github.com/github/github-mcp-server/pkg/translations"
1515
gogithub "github.com/google/go-github/v82/github"
16+
"github.com/modelcontextprotocol/go-sdk/mcp"
1617
"github.com/shurcooL/githubv4"
1718
"github.com/stretchr/testify/assert"
1819
"github.com/stretchr/testify/require"
@@ -150,7 +151,73 @@ func TestNewMCPServer_CreatesSuccessfully(t *testing.T) {
150151
// is already tested in pkg/github/*_test.go.
151152
}
152153

153-
// TestResolveEnabledToolsets verifies the toolset resolution logic.
154+
// TestNewServer_NameAndTitle verifies that the server name and title can be
155+
// overridden and fall back to sensible defaults when empty.
156+
func TestNewServer_NameAndTitle(t *testing.T) {
157+
t.Parallel()
158+
159+
tests := []struct {
160+
name string
161+
serverName string
162+
serverTitle string
163+
expectedName string
164+
expectedTitle string
165+
}{
166+
{
167+
name: "defaults when empty",
168+
serverName: "",
169+
serverTitle: "",
170+
expectedName: "github-mcp-server",
171+
expectedTitle: "GitHub MCP Server",
172+
},
173+
{
174+
name: "custom name and title",
175+
serverName: "my-github-server",
176+
serverTitle: "My GitHub MCP Server",
177+
expectedName: "my-github-server",
178+
expectedTitle: "My GitHub MCP Server",
179+
},
180+
{
181+
name: "custom name only",
182+
serverName: "ghes-server",
183+
serverTitle: "",
184+
expectedName: "ghes-server",
185+
expectedTitle: "GitHub MCP Server",
186+
},
187+
}
188+
189+
for _, tt := range tests {
190+
t.Run(tt.name, func(t *testing.T) {
191+
t.Parallel()
192+
193+
srv := NewServer("v1.0.0", tt.serverName, tt.serverTitle, nil)
194+
require.NotNil(t, srv)
195+
196+
// Connect a client to retrieve the initialize result and verify ServerInfo.
197+
st, ct := mcp.NewInMemoryTransports()
198+
client := mcp.NewClient(&mcp.Implementation{Name: "test-client"}, nil)
199+
200+
var initResult *mcp.InitializeResult
201+
go func() {
202+
cs, err := client.Connect(context.Background(), ct, nil)
203+
if err == nil {
204+
initResult = cs.InitializeResult()
205+
}
206+
}()
207+
208+
_, err := srv.Connect(context.Background(), st, nil)
209+
require.NoError(t, err)
210+
211+
// Give the goroutine time to complete
212+
// (In-memory transport is synchronous, so this is safe)
213+
require.Eventually(t, func() bool { return initResult != nil }, time.Second, 10*time.Millisecond)
214+
require.NotNil(t, initResult.ServerInfo)
215+
assert.Equal(t, tt.expectedName, initResult.ServerInfo.Name)
216+
assert.Equal(t, tt.expectedTitle, initResult.ServerInfo.Title)
217+
})
218+
}
219+
}
220+
154221
func TestResolveEnabledToolsets(t *testing.T) {
155222
t.Parallel()
156223

pkg/http/handler.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
201201

202202
ghServer, err := h.githubMcpServerFactory(r, h.deps, invToUse, &github.MCPServerConfig{
203203
Version: h.config.Version,
204+
Name: h.config.Name,
205+
Title: h.config.Title,
204206
Translator: h.t,
205207
ContentWindowSize: h.config.ContentWindowSize,
206208
Logger: h.logger,

pkg/http/server.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ type ServerConfig struct {
3131
// Version of the server
3232
Version string
3333

34+
// Name overrides the server name in the MCP initialization response.
35+
// If empty, defaults to "github-mcp-server".
36+
Name string
37+
38+
// Title overrides the server title in the MCP initialization response.
39+
// If empty, defaults to "GitHub MCP Server".
40+
Title string
41+
3442
// GitHub Host to target for API requests (e.g. github.com or github.enterprise.com)
3543
Host string
3644

0 commit comments

Comments
 (0)