Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion internal/ghmcp/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,17 @@ func NewMCPServer(cfg MCPServerConfig) (*mcp.Server, error) {
ghServer.AddReceivingMiddleware(addGitHubAPIErrorToContext)
ghServer.AddReceivingMiddleware(addUserAgentsMiddleware(cfg, restClient, gqlHTTPClient))

// Create the dependencies struct for tool handlers
deps := github.ToolDependencies{
GetClient: getClient,
GetGQLClient: getGQLClient,
GetRawClient: getRawClient,
RepoAccessCache: repoAccessCache,
T: cfg.Translator,
Flags: github.FeatureFlags{LockdownMode: cfg.LockdownMode},
ContentWindowSize: cfg.ContentWindowSize,
}

// Create default toolsets
tsg := github.DefaultToolsetGroup(
cfg.ReadOnly,
Expand Down Expand Up @@ -181,7 +192,7 @@ func NewMCPServer(cfg MCPServerConfig) (*mcp.Server, error) {
enabledTools, _ = tsg.ResolveToolAliases(enabledTools)

// Register the specified tools (additive to any toolsets already enabled)
err = tsg.RegisterSpecificTools(ghServer, enabledTools, cfg.ReadOnly)
err = tsg.RegisterSpecificTools(ghServer, enabledTools, cfg.ReadOnly, deps)
if err != nil {
return nil, fmt.Errorf("failed to register tools: %w", err)
}
Expand Down
53 changes: 53 additions & 0 deletions pkg/github/dependencies.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package github

import (
"github.com/github/github-mcp-server/pkg/lockdown"
"github.com/github/github-mcp-server/pkg/raw"
"github.com/github/github-mcp-server/pkg/toolsets"
"github.com/github/github-mcp-server/pkg/translations"
"github.com/modelcontextprotocol/go-sdk/mcp"
)

// ToolDependencies contains all dependencies that tool handlers might need.
// This is a properly-typed struct that lives in pkg/github to avoid circular
// dependencies. The toolsets package uses `any` for deps and tool handlers
// type-assert to this struct.
type ToolDependencies struct {
// GetClient returns a GitHub REST API client
GetClient GetClientFn

// GetGQLClient returns a GitHub GraphQL client
GetGQLClient GetGQLClientFn

// GetRawClient returns a raw HTTP client for GitHub
GetRawClient raw.GetRawClientFn

// RepoAccessCache is the lockdown mode repo access cache
RepoAccessCache *lockdown.RepoAccessCache

// T is the translation helper function
T translations.TranslationHelperFunc

// Flags are feature flags
Flags FeatureFlags

// ContentWindowSize is the size of the content window for log truncation
ContentWindowSize int
}

// NewTool creates a ServerTool with fully-typed ToolDependencies.
// This helper isolates the type assertion from `any` to `ToolDependencies`,
// so tool implementations remain fully typed without assertions scattered throughout.
func NewTool[In, Out any](tool mcp.Tool, handler func(deps ToolDependencies) mcp.ToolHandlerFor[In, Out]) toolsets.ServerTool {
return toolsets.NewServerTool(tool, func(d any) mcp.ToolHandlerFor[In, Out] {
return handler(d.(ToolDependencies))
})
}

// NewToolFromHandler creates a ServerTool with fully-typed ToolDependencies
// for handlers that conform to mcp.ToolHandler directly.
func NewToolFromHandler(tool mcp.Tool, handler func(deps ToolDependencies) mcp.ToolHandler) toolsets.ServerTool {
return toolsets.NewServerToolFromHandler(tool, func(d any) mcp.ToolHandler {
return handler(d.(ToolDependencies))
})
}
4 changes: 1 addition & 3 deletions pkg/github/dynamic_tools.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,7 @@ func EnableToolset(s *mcp.Server, toolsetGroup *toolsets.ToolsetGroup, t transla
//
// Send notification to all initialized sessions
// s.sendNotificationToAllClients("notifications/tools/list_changed", nil)
for _, serverTool := range toolset.GetActiveTools() {
serverTool.RegisterFunc(s)
}
toolset.RegisterTools(s)

return utils.NewToolResultText(fmt.Sprintf("Toolset %s enabled", toolsetName)), nil, nil
})
Expand Down
Loading