11package http
22
33import (
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
1618type 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
1821type 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
2649func 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+
64117func 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 )
0 commit comments