mcp: example middleware wrapping ToolHandler (#351)

Add to the middleware example to show how to wrap a ToolHandler.

This middleware is very close to, but not the same as, wrapping a
ToolHandler directly. The only difference is that the middleware wraps
Server.callTool, which looks up the tool by name in the server's list
and then calls the handler. That lookup (plus other intervening
middleware, of course) is all that distinguishes this way of wrapping
from a more direct wrapping.
This commit is contained in:
Jonathan Amsterdam 2025-08-22 11:05:03 -04:00 • committed by GitHub
commit b891d95361
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -40,13 +40,16 @@ func Example_loggingMiddleware() {
"session_id", req.GetSession().ID(),
"has_params", req.GetParams() != nil,
)
// Log more for tool calls.
if ctr, ok := req.(*mcp.CallToolRequest); ok {
logger.Info("Calling tool",
"name", ctr.Params.Name,
"args", ctr.Params.Arguments)
}
start := time.Now()
result, err := next(ctx, method, req)
duration := time.Since(start)
if err != nil {
logger.Error("MCP method failed",
"method", method,
@ -62,7 +65,6 @@ func Example_loggingMiddleware() {
"has_result", result != nil,
)
}
return result, err
}
}
@ -134,6 +136,7 @@ func Example_loggingMiddleware() {
// time=2025-01-01T00:00:00Z level=INFO msg="MCP method started" method=notifications/initialized session_id="" has_params=true
// time=2025-01-01T00:00:00Z level=INFO msg="MCP method completed" method=notifications/initialized session_id="" duration_ms=0 has_result=false
// time=2025-01-01T00:00:00Z level=INFO msg="MCP method started" method=tools/call session_id="" has_params=true
// time=2025-01-01T00:00:00Z level=INFO msg="Calling tool" name=greet args="{\"name\":\"World\"}"
// time=2025-01-01T00:00:00Z level=INFO msg="MCP method completed" method=tools/call session_id="" duration_ms=0 has_result=true
// Tool result: Hello, World!
}