Skip to content
Draft
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
2 changes: 1 addition & 1 deletion pkg/github/dependencies.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ func NewToolFromHandler(
requiredScopes []scopes.Scope,
handler func(ctx context.Context, deps ToolDependencies, req *mcp.CallToolRequest) (*mcp.CallToolResult, error),
) inventory.ServerTool {
st := inventory.NewServerToolWithRawContextHandler(tool, toolset, func(ctx context.Context, req *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
st := inventory.NewServerTool(tool, toolset, func(ctx context.Context, req *mcp.CallToolRequest) (*mcp.CallToolResult, error) {
deps := MustDepsFromContext(ctx)
return handler(ctx, deps, req)
})
Expand Down
5 changes: 2 additions & 3 deletions pkg/github/dynamic_tools.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,9 @@ type DynamicToolDependencies struct {

// NewDynamicTool creates a ServerTool with fully-typed DynamicToolDependencies.
// Dynamic tools use a different dependency structure (DynamicToolDependencies) than regular
// tools (ToolDependencies), so they intentionally use the closure pattern.
// tools (ToolDependencies), so they use NewServerToolWithDeps which creates closures.
func NewDynamicTool(toolset inventory.ToolsetMetadata, tool mcp.Tool, handler func(deps DynamicToolDependencies) mcp.ToolHandlerFor[map[string]any, any]) inventory.ServerTool {
//nolint:staticcheck // SA1019: Dynamic tools use a different deps structure, closure pattern is intentional
return inventory.NewServerTool(tool, toolset, func(d any) mcp.ToolHandlerFor[map[string]any, any] {
return inventory.NewServerToolWithDeps(tool, toolset, func(d any) mcp.ToolHandlerFor[map[string]any, any] {
return handler(d.(DynamicToolDependencies))
})
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/inventory/registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func testToolsetMetadataWithDefault(id string, isDefault bool) ToolsetMetadata {

// mockToolWithDefault creates a mock tool with a default toolset flag
func mockToolWithDefault(name string, toolsetID string, readOnly bool, isDefault bool) ServerTool {
return NewServerToolWithRawContextHandler(
return NewServerTool(
mcp.Tool{
Name: name,
Annotations: &mcp.ToolAnnotations{
Expand All @@ -45,7 +45,7 @@ func mockToolWithDefault(name string, toolsetID string, readOnly bool, isDefault

// mockTool creates a minimal ServerTool for testing
func mockTool(name string, toolsetID string, readOnly bool) ServerTool {
return NewServerToolWithRawContextHandler(
return NewServerTool(
mcp.Tool{
Name: name,
Annotations: &mcp.ToolAnnotations{
Expand Down
13 changes: 7 additions & 6 deletions pkg/inventory/server_tool.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,14 @@ func (st *ServerTool) RegisterFunc(s *mcp.Server, deps any) {
s.AddTool(&toolCopy, handler)
}

// NewServerTool creates a ServerTool from a tool definition, toolset metadata, and a typed handler function.
// NewServerToolWithDeps creates a ServerTool from a tool definition, toolset metadata, and a typed handler function.
// The handler function takes dependencies (as any) and returns a typed handler.
// Callers should type-assert deps to their typed dependencies struct.
//
// Deprecated: This creates closures at registration time. For better performance in
// per-request server scenarios, use NewServerToolWithContextHandler instead.
func NewServerTool[In any, Out any](tool mcp.Tool, toolset ToolsetMetadata, handlerFn func(deps any) mcp.ToolHandlerFor[In, Out]) ServerTool {
// This function creates closures at registration time and should only be used for special cases
// where the deps structure differs from the standard ToolDependencies (e.g., dynamic tools).
// For regular tools, use NewServerToolWithContextHandler or NewServerTool instead.
func NewServerToolWithDeps[In any, Out any](tool mcp.Tool, toolset ToolsetMetadata, handlerFn func(deps any) mcp.ToolHandlerFor[In, Out]) ServerTool {
return ServerTool{
Tool: tool,
Toolset: toolset,
Expand Down Expand Up @@ -163,13 +164,13 @@ func NewServerToolWithContextHandler[In any, Out any](tool mcp.Tool, toolset Too
}
}

// NewServerToolWithRawContextHandler creates a ServerTool with a raw handler that receives deps via context.
// NewServerTool creates a ServerTool with a raw handler that receives deps via context.
// This is the preferred approach for tools that use mcp.ToolHandler directly because it doesn't
// create closures at registration time.
//
// The handler function is stored directly without wrapping in a deps closure.
// Dependencies should be injected into context before calling tool handlers.
func NewServerToolWithRawContextHandler(tool mcp.Tool, toolset ToolsetMetadata, handler mcp.ToolHandler) ServerTool {
func NewServerTool(tool mcp.Tool, toolset ToolsetMetadata, handler mcp.ToolHandler) ServerTool {
return ServerTool{
Tool: tool,
Toolset: toolset,
Expand Down