Skip to content

Commit c0e794d

Browse files
authored
Merge branch 'main' into patch-1
2 parents 22e0f54 + b1575ed commit c0e794d

File tree

5 files changed

+133
-7
lines changed

5 files changed

+133
-7
lines changed

.github/workflows/docker-publish.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ jobs:
7070
# https://github.com/docker/metadata-action
7171
- name: Extract Docker metadata
7272
id: meta
73-
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
73+
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6.0.0
7474
with:
7575
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
7676
tags: |
@@ -106,7 +106,7 @@ jobs:
106106
# https://github.com/docker/build-push-action
107107
- name: Build and push Docker image
108108
id: build-and-push
109-
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
109+
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
110110
with:
111111
context: .
112112
push: ${{ github.event_name != 'pull_request' }}

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,6 +1537,34 @@ set the following environment variable:
15371537
export GITHUB_MCP_TOOL_ADD_ISSUE_COMMENT_DESCRIPTION="an alternative description"
15381538
```
15391539

1540+
### Overriding Server Name and Title
1541+
1542+
The same override mechanism can be used to customize the MCP server's `name` and
1543+
`title` fields in the initialization response. This is useful when running
1544+
multiple GitHub MCP Server instances (e.g., one for github.com and one for
1545+
GitHub Enterprise Server) so that agents can distinguish between them.
1546+
1547+
| Key | Environment Variable | Default |
1548+
|-----|---------------------|---------|
1549+
| `SERVER_NAME` | `GITHUB_MCP_SERVER_NAME` | `github-mcp-server` |
1550+
| `SERVER_TITLE` | `GITHUB_MCP_SERVER_TITLE` | `GitHub MCP Server` |
1551+
1552+
For example, to configure a server instance for GitHub Enterprise Server:
1553+
1554+
```json
1555+
{
1556+
"SERVER_NAME": "ghes-mcp-server",
1557+
"SERVER_TITLE": "GHES MCP Server"
1558+
}
1559+
```
1560+
1561+
Or using environment variables:
1562+
1563+
```sh
1564+
export GITHUB_MCP_SERVER_NAME="ghes-mcp-server"
1565+
export GITHUB_MCP_SERVER_TITLE="GHES MCP Server"
1566+
```
1567+
15401568
## Library Usage
15411569

15421570
The exported Go API of this module should currently be considered unstable, and subject to breaking changes. In the future, we may offer stability; please file an issue if there is a use case where this would be valuable.

docs/server-configuration.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ We currently support the following ways in which the GitHub MCP Server can be co
1515
| Lockdown Mode | `X-MCP-Lockdown` header | `--lockdown-mode` flag or `GITHUB_LOCKDOWN_MODE` env var |
1616
| Insiders Mode | `X-MCP-Insiders` header or `/insiders` URL | `--insiders` flag or `GITHUB_INSIDERS` env var |
1717
| Scope Filtering | Always enabled | Always enabled |
18+
| Server Name/Title | Not available | `GITHUB_MCP_SERVER_NAME` / `GITHUB_MCP_SERVER_TITLE` env vars or `github-mcp-server-config.json` |
1819

1920
> **Default behavior:** If you don't specify any configuration, the server uses the **default toolsets**: `context`, `issues`, `pull_requests`, `repos`, `users`.
2021

pkg/github/server.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ func NewMCPServer(ctx context.Context, cfg *MCPServerConfig, deps ToolDependenci
101101
}
102102
}
103103

104-
ghServer := NewServer(cfg.Version, serverOpts)
104+
ghServer := NewServer(cfg.Version, cfg.Translator("SERVER_NAME", "github-mcp-server"), cfg.Translator("SERVER_TITLE", "GitHub MCP Server"), serverOpts)
105105

106106
// 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,
107107
// and any middleware that needs to read or modify the context should be before it.
@@ -176,16 +176,25 @@ func addGitHubAPIErrorToContext(next mcp.MethodHandler) mcp.MethodHandler {
176176
}
177177
}
178178

179-
// NewServer creates a new GitHub MCP server with the specified GH client and logger.
180-
func NewServer(version string, opts *mcp.ServerOptions) *mcp.Server {
179+
// NewServer creates a new GitHub MCP server with the given version, server
180+
// name, display title, and options. If name or title are empty the defaults
181+
// "github-mcp-server" and "GitHub MCP Server" are used.
182+
func NewServer(version, name, title string, opts *mcp.ServerOptions) *mcp.Server {
181183
if opts == nil {
182184
opts = &mcp.ServerOptions{}
183185
}
184186

187+
if name == "" {
188+
name = "github-mcp-server"
189+
}
190+
if title == "" {
191+
title = "GitHub MCP Server"
192+
}
193+
185194
// Create a new MCP server
186195
s := mcp.NewServer(&mcp.Implementation{
187-
Name: "github-mcp-server",
188-
Title: "GitHub MCP Server",
196+
Name: name,
197+
Title: title,
189198
Version: version,
190199
Icons: octicons.Icons("mark-github"),
191200
}, opts)

pkg/github/server_test.go

Lines changed: 88 additions & 0 deletions
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,6 +151,93 @@ func TestNewMCPServer_CreatesSuccessfully(t *testing.T) {
150151
// is already tested in pkg/github/*_test.go.
151152
}
152153

154+
// TestNewServer_NameAndTitleViaTranslation verifies that server name and title
155+
// can be overridden via the translation helper (GITHUB_MCP_SERVER_NAME /
156+
// GITHUB_MCP_SERVER_TITLE env vars or github-mcp-server-config.json) and
157+
// fall back to sensible defaults when not overridden.
158+
func TestNewServer_NameAndTitleViaTranslation(t *testing.T) {
159+
t.Parallel()
160+
161+
tests := []struct {
162+
name string
163+
translator translations.TranslationHelperFunc
164+
expectedName string
165+
expectedTitle string
166+
}{
167+
{
168+
name: "defaults when using NullTranslationHelper",
169+
translator: translations.NullTranslationHelper,
170+
expectedName: "github-mcp-server",
171+
expectedTitle: "GitHub MCP Server",
172+
},
173+
{
174+
name: "custom name and title via translator",
175+
translator: func(key, defaultValue string) string {
176+
switch key {
177+
case "SERVER_NAME":
178+
return "my-github-server"
179+
case "SERVER_TITLE":
180+
return "My GitHub MCP Server"
181+
default:
182+
return defaultValue
183+
}
184+
},
185+
expectedName: "my-github-server",
186+
expectedTitle: "My GitHub MCP Server",
187+
},
188+
{
189+
name: "custom name only via translator",
190+
translator: func(key, defaultValue string) string {
191+
if key == "SERVER_NAME" {
192+
return "ghes-server"
193+
}
194+
return defaultValue
195+
},
196+
expectedName: "ghes-server",
197+
expectedTitle: "GitHub MCP Server",
198+
},
199+
}
200+
201+
for _, tt := range tests {
202+
t.Run(tt.name, func(t *testing.T) {
203+
t.Parallel()
204+
205+
srv := NewServer("v1.0.0", tt.translator("SERVER_NAME", "github-mcp-server"), tt.translator("SERVER_TITLE", "GitHub MCP Server"), nil)
206+
require.NotNil(t, srv)
207+
208+
// Connect a client to retrieve the initialize result and verify ServerInfo.
209+
st, ct := mcp.NewInMemoryTransports()
210+
client := mcp.NewClient(&mcp.Implementation{Name: "test-client"}, nil)
211+
212+
type clientResult struct {
213+
result *mcp.InitializeResult
214+
err error
215+
}
216+
clientResultCh := make(chan clientResult, 1)
217+
go func() {
218+
cs, err := client.Connect(context.Background(), ct, nil)
219+
if err != nil {
220+
clientResultCh <- clientResult{err: err}
221+
return
222+
}
223+
t.Cleanup(func() { _ = cs.Close() })
224+
clientResultCh <- clientResult{result: cs.InitializeResult()}
225+
}()
226+
227+
ss, err := srv.Connect(context.Background(), st, nil)
228+
require.NoError(t, err)
229+
t.Cleanup(func() { _ = ss.Close() })
230+
231+
got := <-clientResultCh
232+
require.NoError(t, got.err)
233+
require.NotNil(t, got.result)
234+
require.NotNil(t, got.result.ServerInfo)
235+
assert.Equal(t, tt.expectedName, got.result.ServerInfo.Name)
236+
assert.Equal(t, tt.expectedTitle, got.result.ServerInfo.Title)
237+
})
238+
}
239+
}
240+
153241
// TestResolveEnabledToolsets verifies the toolset resolution logic.
154242
func TestResolveEnabledToolsets(t *testing.T) {
155243
t.Parallel()

0 commit comments

Comments
 (0)