diff --git a/actix-server/CHANGES.md b/actix-server/CHANGES.md
index 1147dcbd..6985fcaa 100644
--- a/actix-server/CHANGES.md
+++ b/actix-server/CHANGES.md
@@ -2,6 +2,7 @@
 
 ## Unreleased - 2023-xx-xx
 
+- ServerBuilder: add support for MPTCP (optional).
 - Minimum supported Rust version (MSRV) is now 1.60.
 
 ## 2.2.0 - 2022-12-21
diff --git a/actix-server/Cargo.toml b/actix-server/Cargo.toml
index ade711f4..58f2bba6 100755
--- a/actix-server/Cargo.toml
+++ b/actix-server/Cargo.toml
@@ -28,7 +28,7 @@ futures-core = { version = "0.3.17", default-features = false, features = ["allo
 futures-util = { version = "0.3.17", default-features = false, features = ["alloc"] }
 mio = { version = "0.8", features = ["os-poll", "net"] }
 num_cpus = "1.13"
-socket2 = "0.4.2" # TODO(MSRV 1.64) update to 0.5
+socket2 = "0.5"
 tokio = { version = "1.23.1", features = ["sync"] }
 tracing = { version = "0.1.30", default-features = false, features = ["log"] }
 
diff --git a/actix-server/src/builder.rs b/actix-server/src/builder.rs
index b6646081..6e80f64f 100644
--- a/actix-server/src/builder.rs
+++ b/actix-server/src/builder.rs
@@ -14,6 +14,13 @@ use crate::{
     Server,
 };
 
+#[derive(PartialEq, Eq, Copy, Clone)]
+pub enum MPTCP {
+    Disabled,
+    TcpFallback,
+    NoFallback,
+}
+
 /// [Server] builder.
 pub struct ServerBuilder {
     pub(crate) threads: usize,
@@ -21,6 +28,7 @@ pub struct ServerBuilder {
     pub(crate) backlog: u32,
     pub(crate) factories: Vec<Box<dyn InternalServiceFactory>>,
     pub(crate) sockets: Vec<(usize, String, MioListener)>,
+    pub(crate) mptcp: MPTCP,
     pub(crate) exit: bool,
     pub(crate) listen_os_signals: bool,
     pub(crate) cmd_tx: UnboundedSender<ServerCommand>,
@@ -45,6 +53,7 @@ impl ServerBuilder {
             factories: Vec::new(),
             sockets: Vec::new(),
             backlog: 2048,
+            mptcp: MPTCP::Disabled,
             exit: false,
             listen_os_signals: true,
             cmd_tx,
@@ -98,6 +107,25 @@ impl ServerBuilder {
         self
     }
 
+    /// Enable the MPTCP protocol at the socket level.
+    ///
+    /// This enable the Multiple Path TCP protocol at the socket level. This means it's managed
+    /// by the kernel and the application (userspace) doesn't have to deal with path management.
+    ///
+    /// Only available in Linux Kernel >= 5.6. If you try to set it on a Windows machine or on
+    /// an older Linux machine, this will fail with a panic.
+    ///
+    /// In Addition to a recent Linux Kernel, you also need to enable the sysctl (if it's not on
+    /// by default):
+    /// `sysctl sysctl net.mptcp.enabled=1`
+    ///
+    /// This method will have no effect if called after a `bind()`.
+    #[cfg(target_os = "linux")]
+    pub fn mptcp(mut self, mptcp_enabled: MPTCP) -> Self {
+        self.mptcp = mptcp_enabled;
+        self
+    }
+
     /// Sets the maximum per-worker number of concurrent connections.
     ///
     /// All socket listeners will stop accepting connections when this limit is reached for
@@ -146,7 +174,7 @@ impl ServerBuilder {
         U: ToSocketAddrs,
         N: AsRef<str>,
     {
-        let sockets = bind_addr(addr, self.backlog)?;
+        let sockets = bind_addr(addr, self.backlog, &self.mptcp)?;
 
         trace!("binding server to: {:?}", &sockets);
 
@@ -263,13 +291,14 @@ impl ServerBuilder {
 pub(super) fn bind_addr<S: ToSocketAddrs>(
     addr: S,
     backlog: u32,
+    mptcp: &MPTCP,
 ) -> io::Result<Vec<MioTcpListener>> {
     let mut opt_err = None;
     let mut success = false;
     let mut sockets = Vec::new();
 
     for addr in addr.to_socket_addrs()? {
-        match create_mio_tcp_listener(addr, backlog) {
+        match create_mio_tcp_listener(addr, backlog, mptcp) {
             Ok(lst) => {
                 success = true;
                 sockets.push(lst);
diff --git a/actix-server/src/lib.rs b/actix-server/src/lib.rs
index 532313b6..bec561e1 100644
--- a/actix-server/src/lib.rs
+++ b/actix-server/src/lib.rs
@@ -19,6 +19,7 @@ mod waker_queue;
 mod worker;
 
 pub use self::builder::ServerBuilder;
+pub use self::builder::MPTCP;
 pub use self::handle::ServerHandle;
 pub use self::server::Server;
 pub use self::service::ServerServiceFactory;
diff --git a/actix-server/src/socket.rs b/actix-server/src/socket.rs
index 8d2ffe8f..2ef97050 100644
--- a/actix-server/src/socket.rs
+++ b/actix-server/src/socket.rs
@@ -12,6 +12,8 @@ pub(crate) use {
     std::os::unix::net::UnixListener as StdUnixListener,
 };
 
+use crate::builder::MPTCP;
+
 pub(crate) enum MioListener {
     Tcp(MioTcpListener),
     #[cfg(unix)]
@@ -224,10 +226,29 @@ mod unix_impl {
 pub(crate) fn create_mio_tcp_listener(
     addr: StdSocketAddr,
     backlog: u32,
+    mptcp: &MPTCP,
 ) -> io::Result<MioTcpListener> {
     use socket2::{Domain, Protocol, Socket, Type};
 
-    let socket = Socket::new(Domain::for_address(addr), Type::STREAM, Some(Protocol::TCP))?;
+    #[cfg(not(target_os = "linux"))]
+    let protocol = Protocol::TCP;
+    #[cfg(target_os = "linux")]
+    let protocol = if mptcp == &MPTCP::Disabled {
+        Protocol::TCP
+    } else {
+        Protocol::MPTCP
+    };
+
+    let socket = match Socket::new(Domain::for_address(addr), Type::STREAM, Some(protocol)) {
+        Ok(sock) => sock,
+        Err(err) => {
+            if mptcp == &MPTCP::TcpFallback {
+                Socket::new(Domain::for_address(addr), Type::STREAM, Some(Protocol::TCP))?
+            } else {
+                return Err(err);
+            }
+        }
+    };
 
     socket.set_reuse_address(true)?;
     socket.set_nonblocking(true)?;
@@ -248,7 +269,7 @@ mod tests {
         assert_eq!(format!("{}", addr), "127.0.0.1:8080");
 
         let addr: StdSocketAddr = "127.0.0.1:0".parse().unwrap();
-        let lst = create_mio_tcp_listener(addr, 128).unwrap();
+        let lst = create_mio_tcp_listener(addr, 128, &MPTCP::Disabled).unwrap();
         let lst = MioListener::Tcp(lst);
         assert!(format!("{:?}", lst).contains("TcpListener"));
         assert!(format!("{}", lst).contains("127.0.0.1"));