Skip to content

Commit 187a8b6

Browse files
Wire ToolDependencies through toolsets
- Move ToolDependencies to pkg/github/dependencies.go with proper types - Use 'any' in toolsets package to avoid circular dependencies - Add NewTool/NewToolFromHandler helpers that isolate type assertion - Tool implementations will be fully typed with no assertions scattered - Infrastructure ready for incremental tool migration
1 parent 09ecc66 commit 187a8b6

File tree

6 files changed

+216
-143
lines changed

6 files changed

+216
-143
lines changed

internal/ghmcp/server.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"github.com/github/github-mcp-server/pkg/lockdown"
1919
mcplog "github.com/github/github-mcp-server/pkg/log"
2020
"github.com/github/github-mcp-server/pkg/raw"
21-
"github.com/github/github-mcp-server/pkg/toolsets"
2221
"github.com/github/github-mcp-server/pkg/translations"
2322
gogithub "github.com/google/go-github/v79/github"
2423
"github.com/modelcontextprotocol/go-sdk/mcp"
@@ -152,6 +151,17 @@ func NewMCPServer(cfg MCPServerConfig) (*mcp.Server, error) {
152151
ghServer.AddReceivingMiddleware(addGitHubAPIErrorToContext)
153152
ghServer.AddReceivingMiddleware(addUserAgentsMiddleware(cfg, restClient, gqlHTTPClient))
154153

154+
// Create the dependencies struct for tool handlers
155+
deps := github.ToolDependencies{
156+
GetClient: getClient,
157+
GetGQLClient: getGQLClient,
158+
GetRawClient: getRawClient,
159+
RepoAccessCache: repoAccessCache,
160+
T: cfg.Translator,
161+
Flags: github.FeatureFlags{LockdownMode: cfg.LockdownMode},
162+
ContentWindowSize: cfg.ContentWindowSize,
163+
}
164+
155165
// Create default toolsets
156166
tsg := github.DefaultToolsetGroup(
157167
cfg.ReadOnly,
@@ -182,7 +192,7 @@ func NewMCPServer(cfg MCPServerConfig) (*mcp.Server, error) {
182192
enabledTools, _ = tsg.ResolveToolAliases(enabledTools)
183193

184194
// Register the specified tools (additive to any toolsets already enabled)
185-
err = tsg.RegisterSpecificTools(ghServer, enabledTools, cfg.ReadOnly, toolsets.ToolDependencies{})
195+
err = tsg.RegisterSpecificTools(ghServer, enabledTools, cfg.ReadOnly, deps)
186196
if err != nil {
187197
return nil, fmt.Errorf("failed to register tools: %w", err)
188198
}

pkg/github/dependencies.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package github
2+
3+
import (
4+
"github.com/github/github-mcp-server/pkg/lockdown"
5+
"github.com/github/github-mcp-server/pkg/raw"
6+
"github.com/github/github-mcp-server/pkg/toolsets"
7+
"github.com/github/github-mcp-server/pkg/translations"
8+
"github.com/modelcontextprotocol/go-sdk/mcp"
9+
)
10+
11+
// ToolDependencies contains all dependencies that tool handlers might need.
12+
// This is a properly-typed struct that lives in pkg/github to avoid circular
13+
// dependencies. The toolsets package uses `any` for deps and tool handlers
14+
// type-assert to this struct.
15+
type ToolDependencies struct {
16+
// GetClient returns a GitHub REST API client
17+
GetClient GetClientFn
18+
19+
// GetGQLClient returns a GitHub GraphQL client
20+
GetGQLClient GetGQLClientFn
21+
22+
// GetRawClient returns a raw HTTP client for GitHub
23+
GetRawClient raw.GetRawClientFn
24+
25+
// RepoAccessCache is the lockdown mode repo access cache
26+
RepoAccessCache *lockdown.RepoAccessCache
27+
28+
// T is the translation helper function
29+
T translations.TranslationHelperFunc
30+
31+
// Flags are feature flags
32+
Flags FeatureFlags
33+
34+
// ContentWindowSize is the size of the content window for log truncation
35+
ContentWindowSize int
36+
}
37+
38+
// NewTool creates a ServerTool with fully-typed ToolDependencies.
39+
// This helper isolates the type assertion from `any` to `ToolDependencies`,
40+
// so tool implementations remain fully typed without assertions scattered throughout.
41+
func NewTool[In, Out any](tool mcp.Tool, handler func(deps ToolDependencies) mcp.ToolHandlerFor[In, Out]) toolsets.ServerTool {
42+
return toolsets.NewServerTool(tool, func(d any) mcp.ToolHandlerFor[In, Out] {
43+
return handler(d.(ToolDependencies))
44+
})
45+
}
46+
47+
// NewToolFromHandler creates a ServerTool with fully-typed ToolDependencies
48+
// for handlers that conform to mcp.ToolHandler directly.
49+
func NewToolFromHandler(tool mcp.Tool, handler func(deps ToolDependencies) mcp.ToolHandler) toolsets.ServerTool {
50+
return toolsets.NewServerToolFromHandler(tool, func(d any) mcp.ToolHandler {
51+
return handler(d.(ToolDependencies))
52+
})
53+
}

0 commit comments

Comments
 (0)