# Include only specific clientscurl -X POST http://localhost:8080/v1/chat/completions \ -H "x-bf-mcp-include-clients: filesystem,web_search" \ -d '...'# Include only specific toolscurl -X POST http://localhost:8080/v1/chat/completions \ -H "x-bf-mcp-include-tools: filesystem-read_file,web_search-search" \ -d '...'# Include all tools from one client, specific tools from anothercurl -X POST http://localhost:8080/v1/chat/completions \ -H "x-bf-mcp-include-tools: filesystem-*,web_search-search" \ -d '...'# Include internal tools registered via RegisterTool()curl -X POST http://localhost:8080/v1/chat/completions \ -H "x-bf-mcp-include-tools: bifrostInternal-echo,bifrostInternal-calculator" \ -d '...'# Empty clients filter blocks ALL tools - no tools available to LLMcurl -X POST http://localhost:8080/v1/chat/completions \ -H "x-bf-mcp-include-clients:" \ -d '...'# Result: No MCP tools available (deny-all)# Empty tools filter also blocks ALL toolscurl -X POST http://localhost:8080/v1/chat/completions \ -H "x-bf-mcp-include-tools:" \ -d '...'# Result: No MCP tools available (deny-all)
// Include only specific clientsctx := context.WithValue(context.Background(), schemas.BifrostContextKey("mcp-include-clients"), []string{"filesystem", "web_search"})// Include only specific toolsctx = context.WithValue(ctx, schemas.BifrostContextKey("mcp-include-tools"), []string{"filesystem-read_file", "web_search-search"})// Wildcard for all tools from a clientctx = context.WithValue(ctx, schemas.BifrostContextKey("mcp-include-tools"), []string{"filesystem-*", "web_search-search"})// Include all internal tools (registered via RegisterTool)ctx = context.WithValue(ctx, schemas.BifrostContextKey("mcp-include-tools"), []string{"bifrostInternal-*"})response, err := client.ChatCompletionRequest(schemas.NewBifrostContext(ctx, schemas.NoDeadline), request)// Empty include-clients blocks ALL tools - no tools availablectx = context.WithValue(context.Background(), schemas.BifrostContextKey("mcp-include-clients"), []string{}) // Empty slice = deny-all// Result: No MCP tools available to LLM// Empty include-tools also blocks ALL toolsctx = context.WithValue(context.Background(), schemas.BifrostContextKey("mcp-include-tools"), []string{}) // Empty slice = deny-all// Result: No MCP tools available to LLM
These tools are registered via RegisterTool() in the SDK
This consistent naming convention ensures clear separation between tools from different clients and prevents naming conflicts across all MCP client types.
Virtual Keys can have their own MCP tool access configuration, which takes precedence over request-level headers.
When a Virtual Key has no MCP configurations, no MCP tools are available (deny-by-default). You must explicitly add MCP client configurations to allow tools. When a Virtual Key has MCP configurations, it generates the x-bf-mcp-include-tools header automatically, overriding any manually sent header.
import ( "context" "github.com/maximhq/bifrost/core/schemas")// Filter to specific clientsctx := context.WithValue( context.Background(), schemas.BifrostContextKey("mcp-include-clients"), []string{"filesystem", "web_search"},)// Or filter to specific toolsctx = context.WithValue( ctx, schemas.BifrostContextKey("mcp-include-tools"), []string{"filesystem-read_file", "web_search-search"},)// Request will only see filtered toolsresponse, _ := client.ChatCompletionRequest(schemas.NewBifrostContext(ctx, schemas.NoDeadline), request)
The tools included in a chat request depend on all active filters. To see what tools are available for a specific request, check the request body sent to the LLM provider in your logs or observability platform.