Skip to content

Commit b66c4e9

Browse files
feat: logging plugin extended for mcp requests
1 parent 5ced4fe commit b66c4e9

File tree

32 files changed

+3044
-55
lines changed

32 files changed

+3044
-55
lines changed

core/bifrost.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,7 @@ func (bifrost *Bifrost) ChatCompletionRequest(ctx *schemas.BifrostContext, req *
681681
req,
682682
response,
683683
bifrost.makeChatCompletionRequest,
684+
bifrost.executeMCPToolWithHooks,
684685
)
685686
}
686687

@@ -777,6 +778,7 @@ func (bifrost *Bifrost) ResponsesRequest(ctx *schemas.BifrostContext, req *schem
777778
req,
778779
response,
779780
bifrost.makeResponsesRequest,
781+
bifrost.executeMCPToolWithHooks,
780782
)
781783
}
782784

@@ -3776,6 +3778,38 @@ func (bifrost *Bifrost) handleMCPToolExecution(ctx *schemas.BifrostContext, mcpR
37763778
return finalResp, nil
37773779
}
37783780

3781+
// executeMCPToolWithHooks is a wrapper around handleMCPToolExecution that matches the signature
3782+
// expected by the agent's executeToolFunc parameter. It runs MCP plugin hooks before and after
3783+
// tool execution to enable logging, telemetry, and other plugin functionality.
3784+
func (bifrost *Bifrost) executeMCPToolWithHooks(ctx *schemas.BifrostContext, request *schemas.BifrostMCPRequest) (*schemas.BifrostMCPResponse, error) {
3785+
// Defensive check: context must be non-nil to prevent panics in plugin hooks
3786+
if ctx == nil {
3787+
return nil, fmt.Errorf("context cannot be nil")
3788+
}
3789+
3790+
if request == nil {
3791+
return nil, fmt.Errorf("request cannot be nil")
3792+
}
3793+
3794+
// Determine request type from the MCP request - explicitly handle all known types
3795+
var requestType schemas.RequestType
3796+
switch request.RequestType {
3797+
case schemas.MCPRequestTypeChatToolCall:
3798+
requestType = schemas.ChatCompletionRequest
3799+
case schemas.MCPRequestTypeResponsesToolCall:
3800+
requestType = schemas.ResponsesRequest
3801+
default:
3802+
// Return error for unknown/unsupported request types instead of silently defaulting
3803+
return nil, fmt.Errorf("unsupported MCP request type: %s", request.RequestType)
3804+
}
3805+
3806+
resp, bifrostErr := bifrost.handleMCPToolExecution(ctx, request, requestType)
3807+
if bifrostErr != nil {
3808+
return nil, fmt.Errorf("%s", GetErrorMessage(bifrostErr))
3809+
}
3810+
return resp, nil
3811+
}
3812+
37793813
// PLUGIN MANAGEMENT
37803814

37813815
// RunPreHooks executes PreHooks in order, tracks how many ran, and returns the final request, any short-circuit decision, and the count.

core/mcp/mcp.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ func (m *MCPManager) CheckAndExecuteAgentForChatRequest(
182182
req *schemas.BifrostChatRequest,
183183
response *schemas.BifrostChatResponse,
184184
makeReq func(ctx *schemas.BifrostContext, req *schemas.BifrostChatRequest) (*schemas.BifrostChatResponse, *schemas.BifrostError),
185+
executeTool func(ctx *schemas.BifrostContext, request *schemas.BifrostMCPRequest) (*schemas.BifrostMCPResponse, error),
185186
) (*schemas.BifrostChatResponse, *schemas.BifrostError) {
186187
if makeReq == nil {
187188
return nil, &schemas.BifrostError{
@@ -197,7 +198,7 @@ func (m *MCPManager) CheckAndExecuteAgentForChatRequest(
197198
return response, nil
198199
}
199200
// Execute agent mode
200-
return m.toolsManager.ExecuteAgentForChatRequest(ctx, req, response, makeReq)
201+
return m.toolsManager.ExecuteAgentForChatRequest(ctx, req, response, makeReq, executeTool)
201202
}
202203

203204
// CheckAndExecuteAgentForResponsesRequest checks if the responses response contains tool calls,
@@ -233,6 +234,7 @@ func (m *MCPManager) CheckAndExecuteAgentForResponsesRequest(
233234
req *schemas.BifrostResponsesRequest,
234235
response *schemas.BifrostResponsesResponse,
235236
makeReq func(ctx *schemas.BifrostContext, req *schemas.BifrostResponsesRequest) (*schemas.BifrostResponsesResponse, *schemas.BifrostError),
237+
executeTool func(ctx *schemas.BifrostContext, request *schemas.BifrostMCPRequest) (*schemas.BifrostMCPResponse, error),
236238
) (*schemas.BifrostResponsesResponse, *schemas.BifrostError) {
237239
if makeReq == nil {
238240
return nil, &schemas.BifrostError{
@@ -248,7 +250,7 @@ func (m *MCPManager) CheckAndExecuteAgentForResponsesRequest(
248250
return response, nil
249251
}
250252
// Execute agent mode
251-
return m.toolsManager.ExecuteAgentForResponsesRequest(ctx, req, response, makeReq)
253+
return m.toolsManager.ExecuteAgentForResponsesRequest(ctx, req, response, makeReq, executeTool)
252254
}
253255

254256
// Cleanup performs cleanup of all MCP resources including clients and local server.

core/mcp/toolmanager.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -517,15 +517,21 @@ func (m *ToolsManager) ExecuteAgentForChatRequest(
517517
req *schemas.BifrostChatRequest,
518518
resp *schemas.BifrostChatResponse,
519519
makeReq func(ctx *schemas.BifrostContext, req *schemas.BifrostChatRequest) (*schemas.BifrostChatResponse, *schemas.BifrostError),
520+
executeTool func(ctx *schemas.BifrostContext, request *schemas.BifrostMCPRequest) (*schemas.BifrostMCPResponse, error),
520521
) (*schemas.BifrostChatResponse, *schemas.BifrostError) {
522+
// Use provided executeTool function, or fall back to internal ExecuteTool
523+
executeToolFunc := executeTool
524+
if executeToolFunc == nil {
525+
executeToolFunc = m.ExecuteTool
526+
}
521527
return ExecuteAgentForChatRequest(
522528
ctx,
523529
int(m.maxAgentDepth.Load()),
524530
req,
525531
resp,
526532
makeReq,
527533
m.fetchNewRequestIDFunc,
528-
m.ExecuteTool,
534+
executeToolFunc,
529535
m.clientManager,
530536
)
531537
}
@@ -548,15 +554,21 @@ func (m *ToolsManager) ExecuteAgentForResponsesRequest(
548554
req *schemas.BifrostResponsesRequest,
549555
resp *schemas.BifrostResponsesResponse,
550556
makeReq func(ctx *schemas.BifrostContext, req *schemas.BifrostResponsesRequest) (*schemas.BifrostResponsesResponse, *schemas.BifrostError),
557+
executeTool func(ctx *schemas.BifrostContext, request *schemas.BifrostMCPRequest) (*schemas.BifrostMCPResponse, error),
551558
) (*schemas.BifrostResponsesResponse, *schemas.BifrostError) {
559+
// Use provided executeTool function, or fall back to internal ExecuteTool
560+
executeToolFunc := executeTool
561+
if executeToolFunc == nil {
562+
executeToolFunc = m.ExecuteTool
563+
}
552564
return ExecuteAgentForResponsesRequest(
553565
ctx,
554566
int(m.maxAgentDepth.Load()),
555567
req,
556568
resp,
557569
makeReq,
558570
m.fetchNewRequestIDFunc,
559-
m.ExecuteTool,
571+
executeToolFunc,
560572
m.clientManager,
561573
)
562574
}

core/mcp/utils.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,15 @@ func (m *MCPManager) GetToolPerClient(ctx context.Context) map[string][]schemas.
6464
continue
6565
}
6666

67-
logger.Debug(fmt.Sprintf("Checking tools for MCP client %s with tools to execute: %v", clientName, client.ExecutionConfig.ToolsToExecute))
68-
6967
// Add all tools from this client
7068
for toolName, tool := range client.ToolMap {
7169
// Check if tool should be skipped based on client configuration
7270
if shouldSkipToolForConfig(toolName, client.ExecutionConfig) {
73-
logger.Debug(fmt.Sprintf("%s Skipping MCP tool %s: not in tools to execute list", MCPLogPrefix, toolName))
7471
continue
7572
}
7673

7774
// Check if tool should be skipped based on request context
7875
if shouldSkipToolForRequest(ctx, clientName, toolName) {
79-
logger.Debug(fmt.Sprintf("%s Skipping MCP tool %s: not in include tools list", MCPLogPrefix, toolName))
8076
continue
8177
}
8278

core/schemas/bifrost.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ const (
113113
FileDeleteRequest RequestType = "file_delete"
114114
FileContentRequest RequestType = "file_content"
115115
CountTokensRequest RequestType = "count_tokens"
116+
MCPToolExecutionRequest RequestType = "mcp_tool_execution"
116117
UnknownRequest RequestType = "unknown"
117118
)
118119

@@ -154,7 +155,7 @@ const (
154155
BifrostContextKeyAccumulatorID BifrostContextKey = "bifrost-accumulator-id" // string (ID for streaming accumulator lookup - set by tracer for accumulator operations)
155156
BifrostContextKeySkipDBUpdate BifrostContextKey = "bifrost-skip-db-update" // bool (set by bifrost - DO NOT SET THIS MANUALLY))
156157
BifrostContextKeyGovernancePluginName BifrostContextKey = "governance-plugin-name" // string (name of the governance plugin that processed the request - set by bifrost)
157-
BifrostContextKeyIsEnterprise BifrostContextKey = "is-enterprise" // bool (set by bifrost - DO NOT SET THIS MANUALLY))
158+
BifrostContextKeyIsEnterprise BifrostContextKey = "is-enterprise" // bool (set by bifrost - DO NOT SET THIS MANUALLY))
158159
)
159160

160161
// NOTE: for custom plugin implementation dealing with streaming short circuit,

docs/openapi/openapi.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,14 @@ paths:
527527
/api/logs/recalculate-cost:
528528
$ref: './paths/management/logging.yaml#/logs-recalculate-cost'
529529

530+
# MCP Logs
531+
/api/mcp-logs:
532+
$ref: './paths/management/logging.yaml#/mcp-logs'
533+
/api/mcp-logs/stats:
534+
$ref: './paths/management/logging.yaml#/mcp-logs-stats'
535+
/api/mcp-logs/filterdata:
536+
$ref: './paths/management/logging.yaml#/mcp-logs-filterdata'
537+
530538
# Cache
531539
/api/cache/clear/{requestId}:
532540
$ref: './paths/management/cache.yaml#/clear-by-request-id'
@@ -832,6 +840,20 @@ components:
832840
RecalculateCostResponse:
833841
$ref: './schemas/management/logging.yaml#/RecalculateCostResponse'
834842

843+
# MCP Logs
844+
MCPToolLogEntry:
845+
$ref: './schemas/management/logging.yaml#/MCPToolLogEntry'
846+
MCPToolLogSearchFilters:
847+
$ref: './schemas/management/logging.yaml#/MCPToolLogSearchFilters'
848+
MCPToolLogStats:
849+
$ref: './schemas/management/logging.yaml#/MCPToolLogStats'
850+
SearchMCPLogsResponse:
851+
$ref: './schemas/management/logging.yaml#/SearchMCPLogsResponse'
852+
MCPLogsFilterDataResponse:
853+
$ref: './schemas/management/logging.yaml#/MCPLogsFilterDataResponse'
854+
DeleteMCPLogsRequest:
855+
$ref: './schemas/management/logging.yaml#/DeleteMCPLogsRequest'
856+
835857
# Cache
836858
ClearCacheResponse:
837859
$ref: './schemas/management/cache.yaml#/ClearCacheResponse'

0 commit comments

Comments
 (0)