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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//! Core middleware trait definitions
use ;
use async_trait;
use SessionView;
/// Core middleware trait for intercepting MCP requests and responses
///
/// Middleware can inspect and modify requests before they reach the dispatcher,
/// and inspect/modify responses before they're sent to the client.
///
/// # Lifecycle
///
/// 1. **Before Dispatch**: Called before the MCP method handler executes
/// - Access to request method, parameters, and metadata
/// - Can inject state into session via `SessionInjection`
/// - Can short-circuit request by returning error
///
/// 2. **After Dispatch**: Called after the MCP method handler completes
/// - Access to the result (success or error)
/// - Can modify the response
/// - Can log, audit, or transform results
///
/// # Transport Agnostic
///
/// Middleware works across all transports (HTTP, Lambda) via normalized `RequestContext`.
///
/// # Examples
///
/// ```rust,no_run
/// use turul_http_mcp_server::middleware::{McpMiddleware, RequestContext, SessionInjection, MiddlewareError};
/// use turul_mcp_session_storage::SessionView;
/// use async_trait::async_trait;
///
/// struct AuthMiddleware {
/// api_key: String,
/// }
///
/// #[async_trait]
/// impl McpMiddleware for AuthMiddleware {
/// async fn before_dispatch(
/// &self,
/// ctx: &mut RequestContext<'_>,
/// session: Option<&dyn SessionView>,
/// injection: &mut SessionInjection,
/// ) -> Result<(), MiddlewareError> {
/// // Extract API key from metadata
/// let provided_key = ctx.metadata()
/// .get("api-key")
/// .and_then(|v| v.as_str())
/// .ok_or_else(|| MiddlewareError::Unauthorized("Missing API key".into()))?;
///
/// // Validate
/// if provided_key != self.api_key {
/// return Err(MiddlewareError::Unauthorized("Invalid API key".into()));
/// }
///
/// // Inject auth metadata into session (if session exists)
/// injection.set_metadata("authenticated", serde_json::json!(true));
///
/// // For initialize (session is None), injection will be applied when session is created
/// // For other methods (session is Some), can also read existing state if needed
/// if let Some(sess) = session {
/// // Can check existing session state for rate limiting, etc.
/// }
///
/// Ok(())
/// }
/// }
/// ```