Skip to content

Commit 740fbff

Browse files
committed
Add a github server factory to HTTPMcpHandler to allow dependency injection in remote
1 parent f13e75d commit 740fbff

File tree

3 files changed

+79
-27
lines changed

3 files changed

+79
-27
lines changed

pkg/github/server.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"encoding/json"
66
"fmt"
77
"log/slog"
8-
"os"
98
"strings"
109
"time"
1110

@@ -100,7 +99,7 @@ func NewMCPServer(cfg *MCPServerConfig, deps ToolDependencies, inventory *invent
10099
ghServer.AddReceivingMiddleware(InjectDepsMiddleware(deps))
101100

102101
if unrecognized := inventory.UnrecognizedToolsets(); len(unrecognized) > 0 {
103-
fmt.Fprintf(os.Stderr, "Warning: unrecognized toolsets ignored: %s\n", strings.Join(unrecognized, ", "))
102+
cfg.Logger.Warn("Warning: unrecognized toolsets ignored", "toolsets", strings.Join(unrecognized, ", "))
104103
}
105104

106105
// Register GitHub tools/resources/prompts from the inventory.

pkg/http/handler.go

Lines changed: 75 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package http
22

33
import (
4+
"context"
45
"log/slog"
56
"net/http"
67
"strings"
@@ -10,44 +11,86 @@ import (
1011
"github.com/github/github-mcp-server/pkg/http/middleware"
1112
"github.com/github/github-mcp-server/pkg/inventory"
1213
"github.com/github/github-mcp-server/pkg/translations"
14+
"github.com/go-chi/chi/v5"
1315
"github.com/modelcontextprotocol/go-sdk/mcp"
1416
)
1517

1618
type InventoryFactoryFunc func(r *http.Request) *inventory.Inventory
19+
type GitHubMCPServerFactoryFunc func(ctx context.Context, r *http.Request, deps github.ToolDependencies, inventory *inventory.Inventory, cfg *github.MCPServerConfig) (*mcp.Server, error)
1720

1821
type HTTPMcpHandler struct {
19-
config *HTTPServerConfig
20-
deps github.ToolDependencies
21-
logger *slog.Logger
22-
t translations.TranslationHelperFunc
23-
inventoryFactoryFunc InventoryFactoryFunc
22+
config *HTTPServerConfig
23+
deps github.ToolDependencies
24+
logger *slog.Logger
25+
t translations.TranslationHelperFunc
26+
githubMcpServerFactory GitHubMCPServerFactoryFunc
27+
inventoryFactoryFunc InventoryFactoryFunc
28+
}
29+
30+
type HTTPMcpHandlerOptions struct {
31+
GitHubMcpServerFactory GitHubMCPServerFactoryFunc
32+
InventoryFactory InventoryFactoryFunc
33+
}
34+
35+
type HTTPMcpHandlerOption func(*HTTPMcpHandlerOptions)
36+
37+
func WithGitHubMCPServerFactory(f GitHubMCPServerFactoryFunc) HTTPMcpHandlerOption {
38+
return func(o *HTTPMcpHandlerOptions) {
39+
o.GitHubMcpServerFactory = f
40+
}
41+
}
42+
43+
func WithInventoryFactory(f InventoryFactoryFunc) HTTPMcpHandlerOption {
44+
return func(o *HTTPMcpHandlerOptions) {
45+
o.InventoryFactory = f
46+
}
2447
}
2548

2649
func NewHTTPMcpHandler(cfg *HTTPServerConfig,
2750
deps github.ToolDependencies,
2851
t translations.TranslationHelperFunc,
2952
logger *slog.Logger,
30-
inventoryFactory InventoryFactoryFunc) *HTTPMcpHandler {
53+
options ...HTTPMcpHandlerOption) *HTTPMcpHandler {
54+
opts := &HTTPMcpHandlerOptions{}
55+
for _, o := range options {
56+
o(opts)
57+
}
58+
59+
githubMcpServerFactory := opts.GitHubMcpServerFactory
60+
if githubMcpServerFactory == nil {
61+
githubMcpServerFactory = DefaultGitHubMCPServerFactory
62+
}
63+
64+
inventoryFactory := opts.InventoryFactory
65+
if inventoryFactory == nil {
66+
inventoryFactory = DefaultInventoryFactory(cfg, t, nil)
67+
}
68+
3169
return &HTTPMcpHandler{
32-
config: cfg,
33-
deps: deps,
34-
logger: logger,
35-
t: t,
36-
inventoryFactoryFunc: inventoryFactory,
70+
config: cfg,
71+
deps: deps,
72+
logger: logger,
73+
t: t,
74+
githubMcpServerFactory: githubMcpServerFactory,
75+
inventoryFactoryFunc: inventoryFactory,
3776
}
3877
}
3978

40-
func (s *HTTPMcpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
41-
inventory := s.inventoryFactoryFunc(r)
42-
43-
ghServer, err := github.NewMCPServer(&github.MCPServerConfig{
44-
Version: s.config.Version,
45-
Host: s.config.Host,
46-
Translator: s.t,
47-
ContentWindowSize: s.config.ContentWindowSize,
48-
Logger: s.logger,
49-
RepoAccessTTL: s.config.RepoAccessCacheTTL,
50-
}, s.deps, inventory)
79+
func (h *HTTPMcpHandler) RegisterRoutes(r chi.Router) {
80+
r.Mount("/", h)
81+
}
82+
83+
func (h *HTTPMcpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
84+
inventory := h.inventoryFactoryFunc(r)
85+
86+
ghServer, err := h.githubMcpServerFactory(r.Context(), r, h.deps, inventory, &github.MCPServerConfig{
87+
Version: h.config.Version,
88+
Translator: h.t,
89+
ContentWindowSize: h.config.ContentWindowSize,
90+
Logger: h.logger,
91+
RepoAccessTTL: h.config.RepoAccessCacheTTL,
92+
})
93+
5194
if err != nil {
5295
w.WriteHeader(http.StatusInternalServerError)
5396
}
@@ -61,6 +104,16 @@ func (s *HTTPMcpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
61104
middleware.ExtractUserToken()(mcpHandler).ServeHTTP(w, r)
62105
}
63106

107+
func DefaultGitHubMCPServerFactory(ctx context.Context, _ *http.Request, deps github.ToolDependencies, inventory *inventory.Inventory, cfg *github.MCPServerConfig) (*mcp.Server, error) {
108+
return github.NewMCPServer(&github.MCPServerConfig{
109+
Version: cfg.Version,
110+
Translator: cfg.Translator,
111+
ContentWindowSize: cfg.ContentWindowSize,
112+
Logger: cfg.Logger,
113+
RepoAccessTTL: cfg.RepoAccessTTL,
114+
}, deps, inventory)
115+
}
116+
64117
func DefaultInventoryFactory(cfg *HTTPServerConfig, t translations.TranslationHelperFunc, staticChecker inventory.FeatureFlagChecker) InventoryFactoryFunc {
65118
return func(r *http.Request) *inventory.Inventory {
66119
b := github.NewInventory(t).WithDeprecatedAliases(github.DeprecatedToolAliases)

pkg/http/server.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,10 @@ func RunHTTPServer(cfg HTTPServerConfig) error {
9595
cfg.ContentWindowSize,
9696
)
9797

98-
handler := NewHTTPMcpHandler(&cfg, deps, t, logger, DefaultInventoryFactory(&cfg, t, nil))
99-
10098
r := chi.NewRouter()
101-
r.Mount("/", handler)
99+
100+
handler := NewHTTPMcpHandler(&cfg, deps, t, logger)
101+
handler.RegisterRoutes(r)
102102

103103
addr := fmt.Sprintf(":%d", cfg.Port)
104104
httpSvr := http.Server{

0 commit comments

Comments
 (0)