@@ -48,9 +48,10 @@ type ToolFilterFunc func(ctx context.Context, tools []mcp.Tool) []mcp.Tool
48
48
49
49
// dynamicTools holds configuration for dynamic tool generation
50
50
type dynamicTools struct {
51
- enabled bool
52
- listFunc func (ctx context.Context , request mcp.ListToolsRequest ) ([]mcp.Tool , error )
53
- handlerFunc func (ctx context.Context , request mcp.CallToolRequest ) (* mcp.CallToolResult , error )
51
+ enabled bool
52
+ listFunc func (ctx context.Context , request mcp.ListToolsRequest ) ([]mcp.Tool , error )
53
+ handlerFunc func (ctx context.Context , request mcp.CallToolRequest ) (* mcp.CallToolResult , error )
54
+ validateFunc func (ctx context.Context , toolName string ) bool
54
55
}
55
56
56
57
// ServerTool combines a Tool with its ToolHandlerFunc.
@@ -300,12 +301,24 @@ func WithDynamicTools(
300
301
enabled bool ,
301
302
listFunc func (ctx context.Context , request mcp.ListToolsRequest ) ([]mcp.Tool , error ),
302
303
handlerFunc func (ctx context.Context , request mcp.CallToolRequest ) (* mcp.CallToolResult , error ),
304
+ validateFunc func (ctx context.Context , toolName string ) bool ,
303
305
) ServerOption {
304
306
return func (s * MCPServer ) {
307
+ // If enabled, all functions must be non-nil
308
+ if enabled && (listFunc == nil || handlerFunc == nil || validateFunc == nil ) {
309
+ panic ("WithDynamicTools: when enabled=true, all functions (listFunc, handlerFunc, validateFunc) must be non-nil" )
310
+ }
311
+
305
312
s .dynamicTools = & dynamicTools {
306
- enabled : enabled ,
307
- listFunc : listFunc ,
308
- handlerFunc : handlerFunc ,
313
+ enabled : enabled ,
314
+ listFunc : listFunc ,
315
+ handlerFunc : handlerFunc ,
316
+ validateFunc : validateFunc ,
317
+ }
318
+
319
+ // Ensure capabilities.tool is not nil so that clients know tools exist
320
+ if enabled {
321
+ s .implicitlyRegisterToolCapabilities ()
309
322
}
310
323
}
311
324
}
@@ -967,7 +980,7 @@ func (s *MCPServer) handleListTools(
967
980
}
968
981
969
982
// Add dynamic tools if enabled
970
- if s .dynamicTools != nil && s .dynamicTools .enabled && s . dynamicTools . listFunc != nil {
983
+ if s .dynamicTools != nil && s .dynamicTools .enabled {
971
984
dynamicTools , err := s .dynamicTools .listFunc (ctx , request )
972
985
if err != nil {
973
986
return nil , & requestError {
@@ -1067,12 +1080,15 @@ func (s *MCPServer) handleToolCall(
1067
1080
}
1068
1081
1069
1082
// If still not found, try dynamic tool handler
1070
- if ! ok && s .dynamicTools != nil && s .dynamicTools .enabled && s .dynamicTools .handlerFunc != nil {
1071
- // Create a ServerTool with the dynamic handler
1072
- tool = ServerTool {
1073
- Handler : s .dynamicTools .handlerFunc ,
1083
+ if ! ok && s .dynamicTools != nil && s .dynamicTools .enabled {
1084
+ // Check if this tool is valid using the validation function
1085
+ if s .dynamicTools .validateFunc (ctx , request .Params .Name ) {
1086
+ // Create a ServerTool with the dynamic handler
1087
+ tool = ServerTool {
1088
+ Handler : s .dynamicTools .handlerFunc ,
1089
+ }
1090
+ ok = true
1074
1091
}
1075
- ok = true
1076
1092
}
1077
1093
1078
1094
if ! ok {
0 commit comments