fastmcp_server/middleware.rs
1//! Middleware hooks for request/response interception.
2//!
3//! This provides a minimal, synchronous middleware system for MCP requests.
4//! Middleware can short-circuit requests, transform responses, and rewrite errors.
5//!
6//! # Ordering Semantics
7//!
8//! - `on_request` runs **in registration order** (first registered, first called).
9//! - `on_response` runs **in reverse order** for middleware whose `on_request` ran.
10//! - `on_error` runs **in reverse order** for middleware whose `on_request` ran.
11//!
12//! If a middleware returns `Respond` from `on_request`, the response is still
13//! passed through `on_response` for the already-entered middleware stack.
14//! If any `on_request` or `on_response` returns an error, `on_error` is invoked
15//! for the entered middleware stack to allow error rewriting.
16
17use fastmcp_core::{McpContext, McpError, McpResult};
18use fastmcp_protocol::JsonRpcRequest;
19
20/// Result of middleware request interception.
21#[derive(Debug, Clone)]
22pub enum MiddlewareDecision {
23 /// Continue normal dispatch.
24 Continue,
25 /// Short-circuit dispatch and return this JSON value as the result.
26 Respond(serde_json::Value),
27}
28
29/// Middleware hook trait for request/response interception.
30///
31/// This is intentionally minimal: synchronous hooks only, with simple
32/// short-circuit and response transform capabilities. See the module-level
33/// documentation for ordering semantics.
34pub trait Middleware: Send + Sync {
35 /// Invoked before routing the request.
36 ///
37 /// Return `Respond` to skip normal dispatch and return a custom result.
38 fn on_request(
39 &self,
40 _ctx: &McpContext,
41 _request: &JsonRpcRequest,
42 ) -> McpResult<MiddlewareDecision> {
43 Ok(MiddlewareDecision::Continue)
44 }
45
46 /// Invoked after a successful handler result is produced.
47 ///
48 /// Middleware can transform the response value (or return an error).
49 fn on_response(
50 &self,
51 _ctx: &McpContext,
52 _request: &JsonRpcRequest,
53 response: serde_json::Value,
54 ) -> McpResult<serde_json::Value> {
55 Ok(response)
56 }
57
58 /// Invoked when a handler or middleware returns an error.
59 ///
60 /// Middleware may rewrite the error before it is sent to the client.
61 fn on_error(&self, _ctx: &McpContext, _request: &JsonRpcRequest, error: McpError) -> McpError {
62 error
63 }
64}