forked from ClickHouse/mcp-clickhouse
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexample_middleware.py
More file actions
87 lines (63 loc) · 2.79 KB
/
Copy pathexample_middleware.py
File metadata and controls
87 lines (63 loc) · 2.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
"""
Example middleware module for mcp-clickhouse.
This module demonstrates how to create custom middleware that can be loaded
into the MCP server without modifying the source code.
To use this middleware, set the MCP_MIDDLEWARE_MODULE environment variable:
MCP_MIDDLEWARE_MODULE=example_middleware
Or in your Claude Desktop config:
"env": {
"MCP_MIDDLEWARE_MODULE": "example_middleware",
...
}
"""
import logging
from fastmcp.server.middleware import Middleware, MiddlewareContext, CallNext
logger = logging.getLogger("example-middleware")
class LoggingMiddleware(Middleware):
"""Example middleware that logs all MCP requests."""
async def on_request(self, context: MiddlewareContext, call_next: CallNext) -> any:
"""Log all incoming requests."""
logger.info(f"Incoming MCP request: method={context.method}, type={context.type}")
result = await call_next(context)
logger.info(f"Request completed: method={context.method}")
return result
class ToolCallLoggingMiddleware(Middleware):
"""Example middleware that specifically logs tool calls."""
async def on_call_tool(self, context: MiddlewareContext, call_next: CallNext) -> any:
"""Log tool execution details."""
tool_name = context.message.name if hasattr(context.message, 'name') else 'unknown'
logger.info(f"Executing tool: {tool_name}")
try:
result = await call_next(context)
logger.info(f"Tool {tool_name} completed successfully")
return result
except Exception as e:
logger.error(f"Tool {tool_name} failed with error: {e}")
raise
class TimingMiddleware(Middleware):
"""Example middleware that measures request processing time."""
async def on_message(self, context: MiddlewareContext, call_next: CallNext) -> any:
"""Measure processing time for all messages."""
import time
start_time = time.time()
result = await call_next(context)
elapsed = time.time() - start_time
logger.info(f"Request {context.method} took {elapsed:.4f} seconds")
return result
def setup_middleware(mcp):
"""
Setup function called by the MCP server to register middleware.
Args:
mcp: The FastMCP instance
"""
logger.info("Setting up example middleware")
# Add logging middleware
mcp.add_middleware(LoggingMiddleware())
logger.info("Added LoggingMiddleware")
# Add tool-specific logging
mcp.add_middleware(ToolCallLoggingMiddleware())
logger.info("Added ToolCallLoggingMiddleware")
# Add timing middleware
mcp.add_middleware(TimingMiddleware())
logger.info("Added TimingMiddleware")
logger.info("Example middleware setup complete")