diff --git a/rust/bt-mcs/Cargo.toml b/rust/bt-mcs/Cargo.toml
index a30afdb..3ada3f7 100644
--- a/rust/bt-mcs/Cargo.toml
+++ b/rust/bt-mcs/Cargo.toml
@@ -9,8 +9,10 @@
 bt-common.workspace = true
 bt-gatt.workspace = true
 futures.workspace = true
+log.workspace = true
 pin-project.workspace = true
 thiserror.workspace = true
 
 [dev-dependencies]
+assert_matches.workspace = true
 bt-gatt = { workspace = true, features = ["test-utils"] }
diff --git a/rust/bt-mcs/src/lib.rs b/rust/bt-mcs/src/lib.rs
index 2ef3b54..3d5520d 100644
--- a/rust/bt-mcs/src/lib.rs
+++ b/rust/bt-mcs/src/lib.rs
@@ -7,4 +7,12 @@
 pub mod types;
 
 pub use crate::error::Error;
-pub use crate::server::{McsServer, McsServerBuilder};
+pub use crate::server::{
+    ControlPointWriteResponder, McsServer, McsServerBuilder, McsServerEvent,
+    SetPlaybackSpeedResponder, SetPlayingOrderResponder, SetTrackPositionResponder,
+    SetValueResponder,
+};
+pub use crate::types::{
+    ControlPointResultCode, MediaControlOpcode, MediaState, PlaybackSpeed, PlayingOrder,
+    SeekingSpeed, SupportedOpcodes, SupportedPlayingOrders, TrackDuration, TrackPosition,
+};
diff --git a/rust/bt-mcs/src/server.rs b/rust/bt-mcs/src/server.rs
index be7e567..25e336c 100644
--- a/rust/bt-mcs/src/server.rs
+++ b/rust/bt-mcs/src/server.rs
@@ -4,18 +4,23 @@
 
 //! Implements the Media Control Service (MCS) server.
 
-use bt_common::Uuid;
+use bt_common::packet_encoding::Decodable;
+use bt_common::{PeerId, Uuid};
 use bt_gatt::server::{
     LocalService, ReadResponder, Server as _, ServiceDefinition, ServiceEvent, ServiceId,
+    WriteResponder,
 };
 use bt_gatt::types::{
     AttributePermissions, CharacteristicProperties, CharacteristicProperty, GattError, Handle,
     SecurityLevels, ServiceKind,
 };
 use bt_gatt::Characteristic;
-use futures::stream::Stream;
+use futures::channel::oneshot;
+use futures::stream::{FuturesUnordered, Stream};
+use futures::FutureExt;
 use pin_project::pin_project;
 use std::future::Future;
+use std::pin::Pin;
 use std::task::{Context, Poll, Waker};
 
 use crate::types::*;
@@ -152,6 +157,12 @@
     fn is_published(&self) -> bool {
         matches!(self, LocalServiceState::Published { .. })
     }
+
+    fn notify(&self, handle: &Handle, data: &[u8], peers: &[PeerId]) {
+        if let LocalServiceState::Published { service, .. } = self {
+            service.notify(handle, data, peers);
+        }
+    }
 }
 
 impl<T: bt_gatt::ServerTypes> Stream for LocalServiceState<T> {
@@ -185,10 +196,9 @@
                             self.as_mut().set(LocalServiceState::Terminated);
                             return Poll::Ready(Some(Err(Error::Gatt(e))));
                         }
-                        None => {
-                            self.as_mut().set(LocalServiceState::Terminated);
-                            return Poll::Ready(None);
-                        }
+                        // Deferred to McsServer to allow draining in-flight control point
+                        // responses.
+                        None => return Poll::Ready(None),
                     }
                 }
             }
@@ -196,6 +206,184 @@
     }
 }
 
+/// Confirms the updated track position to store in local state and notify to
+/// clients.
+/// It is safe to drop without responding to ignore the update or if the value
+/// has not changed.
+pub type SetTrackPositionResponder = SetValueResponder<TrackPosition>;
+
+/// Confirms the updated playback speed to store in local state and notify to
+/// clients.
+/// It is safe to drop without responding to ignore the update or if the value
+/// has not changed.
+pub type SetPlaybackSpeedResponder = SetValueResponder<PlaybackSpeed>;
+
+/// Confirms the updated playing order to store in local state and notify to
+/// clients.
+/// It is safe to drop without responding to ignore the update or if the value
+/// has not changed.
+pub type SetPlayingOrderResponder = SetValueResponder<PlayingOrder>;
+
+/// Confirms the media control command result code to notify to the client.
+/// A response is expected to confirm the result. If no response is provided,
+/// then it is assumed that the Control Point request has failed and
+/// `ControlPointResultCode::CommandCannotBeCompleted` will be sent to the peer.
+pub type ControlPointWriteResponder = SetValueResponder<ControlPointResultCode>;
+
+/// Responder for an asynchronous characteristic write or control point command.
+///
+/// Calling [`send`](Self::send) confirms the new value or command result to
+/// update local state and notify clients. It is safe to drop the responder
+/// without responding to cancel the update (or report command failure).
+pub struct SetValueResponder<T> {
+    response_tx: oneshot::Sender<T>,
+}
+
+impl<T: std::fmt::Debug> SetValueResponder<T> {
+    /// Confirms the value or result code determined by the media player
+    /// application and dispatches the corresponding GATT notification.
+    pub fn send(self, value: T) {
+        if let Err(result) = self.response_tx.send(value) {
+            log::warn!("Failed to send response: server dropped or closed: {result:?}");
+        }
+    }
+}
+
+impl<T> std::fmt::Debug for SetValueResponder<T> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.debug_struct("SetValueResponder").finish_non_exhaustive()
+    }
+}
+
+/// An in-flight handler for a single-value asynchronous write response.
+struct SetValueResponseFut<T> {
+    rx: oneshot::Receiver<T>,
+}
+
+impl<T> SetValueResponseFut<T> {
+    fn create() -> (Self, SetValueResponder<T>) {
+        let (tx, rx) = oneshot::channel();
+        (Self { rx }, SetValueResponder { response_tx: tx })
+    }
+}
+
+impl<T> Future for SetValueResponseFut<T> {
+    type Output = Option<T>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        self.rx.poll_unpin(cx).map(Result::ok)
+    }
+}
+
+/// Responses produced when an in-flight asynchronous write response completes.
+enum PendingWriteResponse {
+    ControlPoint {
+        peer_id: PeerId,
+        opcode: MediaControlOpcode,
+        result_code: ControlPointResultCode,
+    },
+    TrackPosition(TrackPosition),
+    PlaybackSpeed(PlaybackSpeed),
+    PlayingOrder(PlayingOrder),
+}
+
+/// An in-flight asynchronous write response future.
+enum PendingWriteResponseFut {
+    ControlPoint {
+        peer_id: PeerId,
+        opcode: MediaControlOpcode,
+        fut: SetValueResponseFut<ControlPointResultCode>,
+    },
+    TrackPosition(SetValueResponseFut<TrackPosition>),
+    PlaybackSpeed(SetValueResponseFut<PlaybackSpeed>),
+    PlayingOrder(SetValueResponseFut<PlayingOrder>),
+}
+
+impl Future for PendingWriteResponseFut {
+    type Output = Option<PendingWriteResponse>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        match self.as_mut().get_mut() {
+            Self::ControlPoint { peer_id, opcode, fut } => fut.poll_unpin(cx).map(|res| {
+                let code = res.unwrap_or(ControlPointResultCode::CommandCannotBeCompleted);
+                Some(PendingWriteResponse::ControlPoint {
+                    peer_id: *peer_id,
+                    opcode: opcode.clone(),
+                    result_code: code,
+                })
+            }),
+            Self::TrackPosition(fut) => {
+                fut.poll_unpin(cx).map(|res| res.map(PendingWriteResponse::TrackPosition))
+            }
+            Self::PlaybackSpeed(fut) => {
+                fut.poll_unpin(cx).map(|res| res.map(PendingWriteResponse::PlaybackSpeed))
+            }
+            Self::PlayingOrder(fut) => {
+                fut.poll_unpin(cx).map(|res| res.map(PendingWriteResponse::PlayingOrder))
+            }
+        }
+    }
+}
+
+/// Events produced by an [`McsServer`] stream representing client actions that
+/// require additional upper-layer application processing.
+#[derive(Debug)]
+pub enum McsServerEvent {
+    /// Request to set the track playback position.
+    SetTrackPosition {
+        peer_id: PeerId,
+        position: TrackPosition,
+        responder: SetValueResponder<TrackPosition>,
+    },
+    /// Request to set the playback speed.
+    SetPlaybackSpeed {
+        peer_id: PeerId,
+        speed: PlaybackSpeed,
+        responder: SetValueResponder<PlaybackSpeed>,
+    },
+    /// Request to set the playing order.
+    SetPlayingOrder {
+        peer_id: PeerId,
+        order: PlayingOrder,
+        responder: SetValueResponder<PlayingOrder>,
+    },
+    /// Request to execute a media control command.
+    ControlPointCommand {
+        opcode: MediaControlOpcode,
+        responder: SetValueResponder<ControlPointResultCode>,
+    },
+}
+
+/// State of the playing order characteristics when enabled on the server.
+#[derive(Debug, Clone, PartialEq, Eq)]
+struct PlayingOrderState {
+    /// Currently selected playing order.
+    current: PlayingOrder,
+    /// Bitmask of supported playing orders.
+    supported: SupportedPlayingOrders,
+}
+
+impl PlayingOrderState {
+    /// Creates a new `PlayingOrderState` with the default current order
+    /// (`PlayingOrder::InOrderOnce`) and the given supported bitmask.
+    fn new(supported: SupportedPlayingOrders) -> Self {
+        Self { current: PlayingOrder::default(), supported }
+    }
+
+    /// Sets the playing order if it is supported.
+    ///
+    /// Returns `true` if `order` was supported and applied, or `false` if
+    /// ignored because it was unsupported (MCS v1.0.1 Section 3.15.1).
+    fn set_order(&mut self, order: PlayingOrder) -> bool {
+        if self.supported.contains(order.into()) {
+            self.current = order;
+            true
+        } else {
+            false
+        }
+    }
+}
+
 /// Local state of the characteristics in this server.
 #[derive(Debug, Clone, PartialEq, Eq)]
 struct McsLocalState {
@@ -215,10 +403,10 @@
     media_state: MediaState,
     /// URL pointing to media player icon graphic, if supported.
     icon_url: Option<String>,
-    /// Playback speed multiplier (0 = 1.0x normal speed), if supported.
-    playback_speed: Option<i8>,
-    /// Seeking speed factor (0 = not seeking), if supported.
-    seeking_speed: Option<i8>,
+    /// Playback speed multiplier, if supported.
+    playback_speed: Option<PlaybackSpeed>,
+    /// Seeking speed factor, if supported.
+    seeking_speed: Option<SeekingSpeed>,
     /// Playing order and supported playing orders, if supported.
     playing_orders: Option<PlayingOrderState>,
     /// Supported media control point opcodes, if Media Control Point is
@@ -281,10 +469,39 @@
         TrackPosition::FromStart(current)
     }
 
+    /// Sets the track position and records the update timestamp.
+    fn set_track_position(&mut self, position: TrackPosition) {
+        self.track_position = position;
+        self.position_updated_at = Some(std::time::Instant::now());
+    }
+
+    /// Sets the playback speed.
+    fn set_playback_speed(&mut self, speed: PlaybackSpeed) {
+        self.playback_speed = Some(speed);
+    }
+
+    /// Sets the playing order if playing order is supported.
+    fn set_playing_order(&mut self, order: PlayingOrder) {
+        if let Some(ref mut orders) = self.playing_orders {
+            let _ = orders.set_order(order);
+        }
+    }
+
+    #[cfg(test)]
+    pub(crate) fn set_media_state(&mut self, state: MediaState) {
+        self.media_state = state;
+    }
+
+    #[cfg(test)]
+    pub(crate) fn set_supported_opcodes(&mut self, opcodes: SupportedOpcodes) {
+        self.supported_opcodes = Some(opcodes);
+    }
+
     /// Reads the characteristic bytes for `handle` at `offset`.
     fn handle_read(&self, handle: Handle, offset: usize) -> Result<Vec<u8>, GattError> {
         let read_at_offset =
             |bytes: &[u8]| bytes.get(offset..).map(Vec::from).ok_or(GattError::InvalidOffset);
+
         match handle {
             // Track Changed and Media Control Point are not readable per MCS v1.0.1 Section 3,
             // Table 3.1.
@@ -303,11 +520,11 @@
             }
             PLAYBACK_SPEED_HANDLE => {
                 let speed = self.playback_speed.ok_or(GattError::InvalidHandle)?;
-                read_at_offset(&[speed as u8])
+                read_at_offset(&[speed.into()])
             }
             SEEKING_SPEED_HANDLE => {
                 let speed = self.seeking_speed.ok_or(GattError::InvalidHandle)?;
-                read_at_offset(&[speed as u8])
+                read_at_offset(&[speed.into()])
             }
             PLAYING_ORDER_HANDLE => {
                 let orders = self.playing_orders.as_ref().ok_or(GattError::InvalidHandle)?;
@@ -359,8 +576,8 @@
 
     /// Enables playback and seeking speed support with default speeds.
     pub fn with_player_speeds(mut self) -> Self {
-        self.state.playback_speed = Some(0);
-        self.state.seeking_speed = Some(0);
+        self.state.playback_speed = Some(PlaybackSpeed::NORMAL);
+        self.state.seeking_speed = Some(SeekingSpeed::NOT_SEEKING);
         self
     }
 
@@ -446,22 +663,33 @@
     /// Builds an [`McsServer`] configured with this builder.
     pub fn build<T: bt_gatt::ServerTypes>(self) -> Result<McsServer<T>, Error> {
         let service_def = self.build_service_definition()?;
-        Ok(McsServer { service_def, local_service: Default::default(), state: self.state })
+        Ok(McsServer::new(service_def, self.state))
     }
 }
 
 /// An instance of a Media Control Service (MCS) or Generic Media Control
 /// Service (GMCS) GATT server.
-#[pin_project]
+#[pin_project(project = McsServerProj)]
 pub struct McsServer<T: bt_gatt::ServerTypes> {
     service_def: ServiceDefinition,
     #[pin]
     local_service: LocalServiceState<T>,
     /// Local state of the characteristics in this server.
     state: McsLocalState,
+    #[pin]
+    pending_write_responses: FuturesUnordered<PendingWriteResponseFut>,
 }
 
 impl<T: bt_gatt::ServerTypes> McsServer<T> {
+    fn new(service_def: ServiceDefinition, state: McsLocalState) -> Self {
+        Self {
+            service_def,
+            local_service: Default::default(),
+            state,
+            pending_write_responses: FuturesUnordered::new(),
+        }
+    }
+
     /// Returns true if this server is a GMCS server.
     pub fn is_generic_service(&self) -> bool {
         self.service_def.uuid() == GENERIC_MEDIA_CONTROL_SERVICE_UUID
@@ -489,33 +717,251 @@
         Ok(())
     }
 
+    #[cfg(test)]
+    pub(crate) fn set_media_state(&mut self, state: MediaState) {
+        self.state.set_media_state(state);
+    }
+
+    #[cfg(test)]
+    pub(crate) fn set_supported_opcodes(&mut self, opcodes: SupportedOpcodes) {
+        self.state.set_supported_opcodes(opcodes);
+    }
+}
+
+impl<'a, T: bt_gatt::ServerTypes> McsServerProj<'a, T> {
     fn handle_read<R: ReadResponder>(&self, handle: Handle, offset: usize, responder: R) {
         match self.state.handle_read(handle, offset) {
             Ok(bytes) => responder.respond(&bytes),
             Err(err) => responder.error(err),
         }
     }
+
+    fn handle_write<W: WriteResponder>(
+        &mut self,
+        peer_id: PeerId,
+        handle: Handle,
+        offset: u32,
+        value: &[u8],
+        responder: W,
+    ) -> Option<McsServerEvent> {
+        // Reject non-zero offsets as MCS writable characteristics do not support
+        // long writes.
+        if offset != 0 {
+            responder.error(GattError::InvalidOffset);
+            return None;
+        }
+
+        match handle {
+            MEDIA_CONTROL_POINT_HANDLE => {
+                self.handle_control_point_write(peer_id, value, responder)
+            }
+            TRACK_POSITION_HANDLE => {
+                if value.len() != 4 {
+                    responder.error(GattError::InvalidAttributeValueLength);
+                    return None;
+                }
+                let raw = i32::from_le_bytes(value.try_into().unwrap());
+                let position = TrackPosition::from_raw_10ms(raw);
+                responder.acknowledge();
+                let (fut, resp) = SetValueResponseFut::create();
+                self.pending_write_responses.push(PendingWriteResponseFut::TrackPosition(fut));
+                Some(McsServerEvent::SetTrackPosition { peer_id, position, responder: resp })
+            }
+            PLAYBACK_SPEED_HANDLE => {
+                if self.state.playback_speed.is_none() {
+                    responder.error(GattError::InvalidHandle);
+                    return None;
+                }
+                if value.len() != 1 {
+                    responder.error(GattError::InvalidAttributeValueLength);
+                    return None;
+                }
+                let speed = PlaybackSpeed::from(value[0] as i8);
+                responder.acknowledge();
+                let (fut, resp) = SetValueResponseFut::create();
+                self.pending_write_responses.push(PendingWriteResponseFut::PlaybackSpeed(fut));
+                Some(McsServerEvent::SetPlaybackSpeed { peer_id, speed, responder: resp })
+            }
+            PLAYING_ORDER_HANDLE => {
+                let Some(ref playing_orders) = self.state.playing_orders else {
+                    responder.error(GattError::InvalidHandle);
+                    return None;
+                };
+                if value.len() != 1 {
+                    responder.error(GattError::InvalidAttributeValueLength);
+                    return None;
+                }
+                let Ok(order) = PlayingOrder::try_from(value[0]) else {
+                    // Invalid playing order values (MCS v1.0.1 Section 3.15.1).
+                    responder.acknowledge();
+                    return None;
+                };
+                if !playing_orders.supported.contains(order.into()) {
+                    // Unsupported playing order is ignored per MCS v1.0.1 Section 3.15.1.
+                    responder.acknowledge();
+                    return None;
+                }
+                responder.acknowledge();
+                let (fut, resp) = SetValueResponseFut::create();
+                self.pending_write_responses.push(PendingWriteResponseFut::PlayingOrder(fut));
+                Some(McsServerEvent::SetPlayingOrder { peer_id, order, responder: resp })
+            }
+            // Read-only characteristics cannot be written to.
+            MEDIA_PLAYER_NAME_HANDLE
+            | TRACK_CHANGED_HANDLE
+            | TRACK_TITLE_HANDLE
+            | TRACK_DURATION_HANDLE
+            | MEDIA_PLAYER_ICON_URL_HANDLE
+            | SEEKING_SPEED_HANDLE
+            | PLAYING_ORDERS_SUPPORTED_HANDLE
+            | MEDIA_STATE_HANDLE
+            | MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_HANDLE
+            | CONTENT_CONTROL_ID_HANDLE => {
+                responder.error(GattError::WriteNotPermitted);
+                None
+            }
+            // TODO(b/549911651): Add support for optional characteristics (e.g. Search Control
+            // Point and OTS object IDs).
+            _ => {
+                responder.error(GattError::InvalidHandle);
+                None
+            }
+        }
+    }
+
+    fn handle_control_point_write<W: WriteResponder>(
+        &mut self,
+        peer_id: PeerId,
+        value: &[u8],
+        responder: W,
+    ) -> Option<McsServerEvent> {
+        // The Media Control Point characteristic is optional - reject all requests if
+        // it is not enabled on this server.
+        let Some(supported_opcodes) = self.state.supported_opcodes else {
+            responder.error(GattError::InvalidHandle);
+            return None;
+        };
+
+        let Some(&raw_opcode) = value.first() else {
+            responder.error(GattError::InvalidAttributeValueLength);
+            return None;
+        };
+
+        let notify_error = |responder: W, result_code: ControlPointResultCode| {
+            responder.acknowledge();
+            self.local_service.notify(
+                &MEDIA_CONTROL_POINT_HANDLE,
+                &[raw_opcode, result_code.into()],
+                &[peer_id],
+            );
+            None
+        };
+
+        // Validate opcode decoding and server opcode support (see MCS v1.0.1 Section
+        // 3.18.2).
+        let opcode = match MediaControlOpcode::decode(value) {
+            (Ok(opcode), _) if supported_opcodes.contains((&opcode).into()) => opcode,
+            _ => return notify_error(responder, ControlPointResultCode::OpcodeNotSupported),
+        };
+
+        // Reject commands if the media player is inactive.
+        // TODO(b/540400364): The spec also technically allows the handling of the
+        // command if the media player supports it with no active track. Revisit
+        // this if needed.
+        if self.state.media_state == MediaState::Inactive {
+            return notify_error(responder, ControlPointResultCode::MediaPlayerInactive);
+        }
+
+        // Acknowledge the GATT write and produce a new event for the request.
+        responder.acknowledge();
+        let (fut, responder) = SetValueResponseFut::create();
+        self.pending_write_responses.push(PendingWriteResponseFut::ControlPoint {
+            peer_id,
+            opcode: opcode.clone(),
+            fut,
+        });
+        Some(McsServerEvent::ControlPointCommand { opcode, responder })
+    }
+
+    /// Attempts to handle a pending write response from the upper layer
+    /// application.
+    fn handle_pending_write_response(&mut self, response: PendingWriteResponse) {
+        match response {
+            PendingWriteResponse::ControlPoint { peer_id, opcode, result_code } => {
+                // Dispatches a Media Control Point GATT notification containing
+                // [opcode, result_code] to the peer per MCS v1.0.1 Section 3.18.2.
+                self.local_service.notify(
+                    &MEDIA_CONTROL_POINT_HANDLE,
+                    &[opcode.raw_opcode(), result_code.into()],
+                    &[peer_id],
+                );
+            }
+            PendingWriteResponse::TrackPosition(position) => {
+                self.state.set_track_position(position);
+                self.local_service.notify(
+                    &TRACK_POSITION_HANDLE,
+                    &position.raw_10ms().to_le_bytes(),
+                    &[],
+                );
+            }
+            PendingWriteResponse::PlaybackSpeed(speed) => {
+                self.state.set_playback_speed(speed);
+                self.local_service.notify(&PLAYBACK_SPEED_HANDLE, &[speed.into()], &[]);
+            }
+            PendingWriteResponse::PlayingOrder(order) => {
+                self.state.set_playing_order(order);
+                self.local_service.notify(&PLAYING_ORDER_HANDLE, &[order.into()], &[]);
+            }
+        }
+    }
 }
 
 impl<T: bt_gatt::ServerTypes> Stream for McsServer<T> {
-    type Item = Result<(), Error>;
+    type Item = Result<McsServerEvent, Error>;
 
     fn poll_next(
         mut self: std::pin::Pin<&mut Self>,
         cx: &mut Context<'_>,
     ) -> Poll<Option<Self::Item>> {
         loop {
-            let gatt_event =
-                match futures::ready!(self.as_mut().project().local_service.poll_next(cx)) {
-                    None => return Poll::Ready(None),
-                    Some(Err(e)) => return Poll::Ready(Some(Err(e))),
-                    Some(Ok(event)) => event,
-                };
+            let mut this = self.as_mut().project();
+            // Drain any completed asynchronous write responses before processing new
+            // GATT events.
+            if let Poll::Ready(Some(response)) = this.pending_write_responses.as_mut().poll_next(cx)
+            {
+                if let Some(response) = response {
+                    this.handle_pending_write_response(response);
+                }
+                continue;
+            }
+
+            let gatt_event = match futures::ready!(this.local_service.as_mut().poll_next(cx)) {
+                None => {
+                    // Continue polling until all in-flight responses have been drained before
+                    // terminating the stream.
+                    if this.pending_write_responses.is_empty() {
+                        this.local_service.as_mut().set(LocalServiceState::Terminated);
+                        return Poll::Ready(None);
+                    } else {
+                        return Poll::Pending;
+                    }
+                }
+                Some(Err(e)) => return Poll::Ready(Some(Err(e))),
+                Some(Ok(event)) => event,
+            };
+
             match gatt_event {
                 ServiceEvent::Read { peer_id: _, handle, offset, responder } => {
-                    self.handle_read(handle, offset as usize, responder);
+                    this.handle_read(handle, offset as usize, responder);
                 }
-                // TODO(b/540400364): Add support for characteristic writes
+                ServiceEvent::Write { peer_id, handle, offset, value, responder } => {
+                    let value_bytes = value.to_owned();
+                    if let Some(event) =
+                        this.handle_write(peer_id, handle, offset, &value_bytes, responder)
+                    {
+                        return Poll::Ready(Some(Ok(event)));
+                    }
+                }
                 _ => continue,
             }
         }
@@ -526,17 +972,15 @@
 mod tests {
     use super::*;
 
-    use bt_common::PeerId;
+    use assert_matches::assert_matches;
     use bt_gatt::test_utils::{FakeServer, FakeServerEvent, FakeTypes};
-    use bt_gatt::types::GattError;
-    use futures::{FutureExt, StreamExt};
+    use futures::StreamExt;
 
     #[test]
     fn builder_generic_service_definition() {
         let builder = McsServerBuilder::generic(0x42, "Test Generic Player");
-        let service_def = builder
-            .build_service_definition()
-            .expect("generic service definition builds successfully");
+        let service_def =
+            builder.build_service_definition().expect("service definition builds successfully");
         assert_eq!(service_def.uuid(), GENERIC_MEDIA_CONTROL_SERVICE_UUID);
         assert_eq!(service_def.id(), ServiceId::new(0x42));
         assert_eq!(service_def.kind(), ServiceKind::Primary);
@@ -656,12 +1100,15 @@
     #[test]
     fn service_id_tracks_ccid() {
         let builder1 = McsServerBuilder::instance(0x05, "Player 1");
-        let builder2 = McsServerBuilder::instance(0x05, "Player 2");
+        let builder2 = McsServerBuilder::generic(0x05, "Player 2");
         let builder3 = McsServerBuilder::instance(0x06, "Player 3");
 
-        let def1 = builder1.build_service_definition().expect("valid definition");
-        let def2 = builder2.build_service_definition().expect("valid definition");
-        let def3 = builder3.build_service_definition().expect("valid definition");
+        let def1 =
+            builder1.build_service_definition().expect("service definition builds successfully");
+        let def2 =
+            builder2.build_service_definition().expect("service definition builds successfully");
+        let def3 =
+            builder3.build_service_definition().expect("service definition builds successfully");
 
         assert_eq!(def1.id(), def2.id());
         assert_eq!(def1.id(), ServiceId::new(5));
@@ -718,7 +1165,7 @@
 
         server.publish(fake_gatt_server.clone()).expect("initial publish succeeds");
         let err = server.publish(fake_gatt_server);
-        assert!(matches!(err, Err(Error::AlreadyPublished)));
+        assert_matches!(err, Err(Error::AlreadyPublished));
     }
 
     #[test]
@@ -745,10 +1192,10 @@
         )));
         server2.publish(fake_gatt_server).expect("server2 publish call succeeds");
         let poll_result = server2.next().poll_unpin(&mut noop_cx);
-        assert!(matches!(
+        assert_matches!(
             poll_result,
             Poll::Ready(Some(Err(Error::Gatt(bt_gatt::types::Error::AlreadyPublished(_)))))
-        ));
+        );
     }
 
     #[test]
@@ -782,11 +1229,11 @@
 
         // Polling the server returns None indicating the stream has terminated.
         let poll_result = server.next().poll_unpin(&mut noop_cx);
-        assert!(matches!(poll_result, Poll::Ready(None)));
+        assert_matches!(poll_result, Poll::Ready(None));
 
         // Subsequent polls on terminated state also return None.
         let poll_result = server.next().poll_unpin(&mut noop_cx);
-        assert!(matches!(poll_result, Poll::Ready(None)));
+        assert_matches!(poll_result, Poll::Ready(None));
     }
 
     fn setup_test_server(
@@ -805,6 +1252,30 @@
         (server, fake_gatt_server, event_receiver)
     }
 
+    fn setup_test_server_with_control_point(
+        peer: PeerId,
+    ) -> (
+        McsServer<FakeTypes>,
+        FakeServer,
+        futures::channel::mpsc::UnboundedReceiver<FakeServerEvent>,
+        Context<'static>,
+    ) {
+        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
+        let (mut server, fake_gatt_server, mut event_receiver) = setup_test_server(
+            McsServerBuilder::generic(0x42, "Test Player")
+                .with_supported_operations(SupportedOpcodes::all()),
+        );
+        fake_gatt_server.incoming_client_configuration(
+            peer,
+            server.service_def.id(),
+            MEDIA_CONTROL_POINT_HANDLE,
+            bt_gatt::server::NotificationType::Notify,
+        );
+        let _ = server.next().poll_unpin(&mut noop_cx);
+        let _ = event_receiver.try_recv();
+        (server, fake_gatt_server, event_receiver, noop_cx)
+    }
+
     fn assert_read_characteristic(
         server: &mut McsServer<FakeTypes>,
         fake_gatt_server: &FakeServer,
@@ -981,8 +1452,9 @@
             else {
                 panic!("expected ReadResponded for handle {:?}", handle);
             };
-            assert!(
-                matches!(value.unwrap_err(), bt_gatt::types::Error::Gatt(GattError::InvalidHandle)),
+            assert_matches!(
+                value.unwrap_err(),
+                bt_gatt::types::Error::Gatt(GattError::InvalidHandle),
                 "handle {:?} should return InvalidHandle when unconfigured",
                 handle
             );
@@ -990,6 +1462,40 @@
     }
 
     #[test]
+    fn write_unconfigured_optional_characteristics_returns_invalid_handle() {
+        let (mut server, fake_gatt_server, mut event_receiver) =
+            setup_test_server(McsServerBuilder::generic(0x42, "Mandatory Only Player"));
+
+        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
+        let peer = PeerId(1);
+        let service_id = server.service_def.id();
+
+        let unconfigured_writes = [
+            (PLAYBACK_SPEED_HANDLE, vec![0x00]),
+            (PLAYING_ORDER_HANDLE, vec![PlayingOrder::SingleOnce.into()]),
+            (MEDIA_CONTROL_POINT_HANDLE, vec![MediaControlOpcode::Play.raw_opcode()]),
+        ];
+
+        for (handle, value) in unconfigured_writes {
+            fake_gatt_server.incoming_write(peer, service_id, handle, 0, value);
+            let poll_result = server.next().poll_unpin(&mut noop_cx);
+            // Must NOT emit any McsServerEvent.
+            assert_matches!(poll_result, Poll::Pending);
+            let bt_gatt::test_utils::FakeServerEvent::WriteResponded { value, .. } =
+                event_receiver.try_recv().unwrap()
+            else {
+                panic!("expected WriteResponded for handle {:?}", handle);
+            };
+            assert_matches!(
+                value.unwrap_err(),
+                bt_gatt::types::Error::Gatt(GattError::InvalidHandle),
+                "handle {:?} should return InvalidHandle on write when unconfigured",
+                handle
+            );
+        }
+    }
+
+    #[test]
     fn read_string_characteristics_with_offset() {
         let (mut server, fake_gatt_server, mut event_receiver) = setup_test_server(
             McsServerBuilder::generic(0x42, "Long Player Name")
@@ -1043,10 +1549,7 @@
         else {
             panic!("expected ReadResponded");
         };
-        assert!(matches!(
-            value.unwrap_err(),
-            bt_gatt::types::Error::Gatt(GattError::InvalidOffset)
-        ));
+        assert_matches!(value.unwrap_err(), bt_gatt::types::Error::Gatt(GattError::InvalidOffset));
 
         // Out-of-bounds offset on Icon URL returns InvalidOffset
         fake_gatt_server.incoming_read(peer, service_id, MEDIA_PLAYER_ICON_URL_HANDLE, 100);
@@ -1056,10 +1559,7 @@
         else {
             panic!("expected ReadResponded");
         };
-        assert!(matches!(
-            value.unwrap_err(),
-            bt_gatt::types::Error::Gatt(GattError::InvalidOffset)
-        ));
+        assert_matches!(value.unwrap_err(), bt_gatt::types::Error::Gatt(GattError::InvalidOffset));
     }
 
     #[test]
@@ -1081,10 +1581,10 @@
         else {
             panic!("expected ReadResponded");
         };
-        assert!(matches!(
+        assert_matches!(
             value.unwrap_err(),
             bt_gatt::types::Error::Gatt(GattError::ReadNotPermitted)
-        ));
+        );
 
         // Media Control Point is write/notify-only
         fake_gatt_server.incoming_read(peer, service_id, MEDIA_CONTROL_POINT_HANDLE, 0);
@@ -1094,10 +1594,10 @@
         else {
             panic!("expected ReadResponded");
         };
-        assert!(matches!(
+        assert_matches!(
             value.unwrap_err(),
             bt_gatt::types::Error::Gatt(GattError::ReadNotPermitted)
-        ));
+        );
 
         // Unknown handle returns InvalidHandle
         fake_gatt_server.incoming_read(peer, service_id, Handle(999), 0);
@@ -1107,10 +1607,1129 @@
         else {
             panic!("expected ReadResponded");
         };
-        assert!(matches!(
+        assert_matches!(value.unwrap_err(), bt_gatt::types::Error::Gatt(GattError::InvalidHandle));
+    }
+
+    #[test]
+    fn write_track_position_success() {
+        let (mut server, fake_gatt_server, mut event_receiver) =
+            setup_test_server(McsServerBuilder::generic(0x42, "Test Player"));
+        server.state.media_state = MediaState::Paused;
+        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
+
+        let peer = PeerId(1);
+        let service_id = ServiceId::new(0x42);
+
+        fake_gatt_server.incoming_client_configuration(
+            peer,
+            service_id,
+            TRACK_POSITION_HANDLE,
+            bt_gatt::server::NotificationType::Notify,
+        );
+        let _ = server.next().poll_unpin(&mut noop_cx);
+        let _ = event_receiver.try_recv();
+
+        fake_gatt_server.incoming_write(
+            peer,
+            service_id,
+            TRACK_POSITION_HANDLE,
+            0,
+            4200i32.to_le_bytes().to_vec(),
+        );
+
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        let Poll::Ready(Some(Ok(McsServerEvent::SetTrackPosition {
+            peer_id,
+            position,
+            responder,
+        }))) = poll_result
+        else {
+            panic!("expected SetTrackPosition event, got {poll_result:?}");
+        };
+        assert_eq!(peer_id, peer);
+        assert_eq!(position, TrackPosition::from_raw_10ms(4200));
+
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert!(value.is_ok());
+
+        // Upper layer confirms the set track position.
+        responder.send(position);
+
+        // Server processes the confirmation, updates state, and sends notification.
+        let _ = server.next().poll_unpin(&mut noop_cx);
+
+        let FakeServerEvent::Notified { handle, value, peers, .. } =
+            event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected Notified");
+        };
+        assert_eq!(handle, TRACK_POSITION_HANDLE);
+        assert_eq!(peers, vec![peer]);
+        assert_eq!(value, 4200i32.to_le_bytes().to_vec());
+
+        // Subsequent read reflects the updated track position
+        fake_gatt_server.incoming_read(peer, service_id, TRACK_POSITION_HANDLE, 0);
+        let _ = server.next().poll_unpin(&mut noop_cx);
+        let FakeServerEvent::ReadResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected ReadResponded");
+        };
+        assert_eq!(value.unwrap(), 4200i32.to_le_bytes());
+    }
+
+    #[test]
+    fn write_track_position_invalid_length_or_offset() {
+        let (mut server, fake_gatt_server, mut event_receiver) =
+            setup_test_server(McsServerBuilder::generic(0x42, "Test Player"));
+        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
+
+        let peer = PeerId(1);
+        let service_id = ServiceId::new(0x42);
+
+        // Invalid offset (non-zero)
+        fake_gatt_server.incoming_write(
+            peer,
+            service_id,
+            TRACK_POSITION_HANDLE,
+            1,
+            4200i32.to_le_bytes().to_vec(),
+        );
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        assert_matches!(poll_result, Poll::Pending);
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert_matches!(value.unwrap_err(), bt_gatt::types::Error::Gatt(GattError::InvalidOffset));
+
+        // Invalid value length (3 bytes instead of 4)
+        fake_gatt_server.incoming_write(
+            peer,
+            service_id,
+            TRACK_POSITION_HANDLE,
+            0,
+            vec![0x01, 0x02, 0x03],
+        );
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        assert_matches!(poll_result, Poll::Pending);
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert_matches!(
             value.unwrap_err(),
-            bt_gatt::types::Error::Gatt(GattError::InvalidHandle)
-        ));
+            bt_gatt::types::Error::Gatt(GattError::InvalidAttributeValueLength)
+        );
+    }
+
+    #[test]
+    fn write_playback_speed_success() {
+        let (mut server, fake_gatt_server, mut event_receiver) =
+            setup_test_server(McsServerBuilder::generic(0x42, "Test Player").with_player_speeds());
+        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
+
+        let peer = PeerId(1);
+        let service_id = ServiceId::new(0x42);
+
+        fake_gatt_server.incoming_client_configuration(
+            peer,
+            service_id,
+            PLAYBACK_SPEED_HANDLE,
+            bt_gatt::server::NotificationType::Notify,
+        );
+        let _ = server.next().poll_unpin(&mut noop_cx);
+        let _ = event_receiver.try_recv();
+
+        fake_gatt_server.incoming_write(
+            peer,
+            service_id,
+            PLAYBACK_SPEED_HANDLE,
+            0,
+            vec![-64i8 as u8],
+        );
+
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        let Poll::Ready(Some(Ok(McsServerEvent::SetPlaybackSpeed { peer_id, speed, responder }))) =
+            poll_result
+        else {
+            panic!("expected SetPlaybackSpeed event, got {poll_result:?}");
+        };
+        assert_eq!(peer_id, peer);
+        assert_eq!(speed, PlaybackSpeed::HALF);
+
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert!(value.is_ok());
+
+        // Upper layer confirms playback speed
+        responder.send(speed);
+        let _ = server.next().poll_unpin(&mut noop_cx);
+
+        let FakeServerEvent::Notified { handle, value, peers, .. } =
+            event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected Notified");
+        };
+        assert_eq!(handle, PLAYBACK_SPEED_HANDLE);
+        assert_eq!(peers, vec![peer]);
+        assert_eq!(value, vec![-64i8 as u8]);
+
+        // Subsequent read reflects the updated playback speed
+        fake_gatt_server.incoming_read(peer, service_id, PLAYBACK_SPEED_HANDLE, 0);
+        let _ = server.next().poll_unpin(&mut noop_cx);
+        let FakeServerEvent::ReadResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected ReadResponded");
+        };
+        assert_eq!(value.unwrap(), vec![-64i8 as u8]);
+    }
+
+    #[test]
+    fn write_playback_speed_invalid_length_or_offset() {
+        let (mut server, fake_gatt_server, mut event_receiver) =
+            setup_test_server(McsServerBuilder::generic(0x42, "Test Player").with_player_speeds());
+        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
+
+        let peer = PeerId(1);
+        let service_id = ServiceId::new(0x42);
+
+        // Invalid offset (non-zero)
+        fake_gatt_server.incoming_write(peer, service_id, PLAYBACK_SPEED_HANDLE, 1, vec![0x00]);
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        assert_matches!(poll_result, Poll::Pending);
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert_matches!(value.unwrap_err(), bt_gatt::types::Error::Gatt(GattError::InvalidOffset));
+
+        // Invalid value length (2 bytes instead of 1)
+        fake_gatt_server.incoming_write(
+            peer,
+            service_id,
+            PLAYBACK_SPEED_HANDLE,
+            0,
+            vec![0x00, 0x01],
+        );
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        assert_matches!(poll_result, Poll::Pending);
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert_matches!(
+            value.unwrap_err(),
+            bt_gatt::types::Error::Gatt(GattError::InvalidAttributeValueLength)
+        );
+    }
+
+    #[test]
+    fn write_playing_order_supported() {
+        let (mut server, fake_gatt_server, mut event_receiver) = setup_test_server(
+            McsServerBuilder::generic(0x42, "Test Player")
+                .with_playing_orders(SupportedPlayingOrders::all()),
+        );
+        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
+
+        let peer = PeerId(1);
+        let service_id = ServiceId::new(0x42);
+
+        fake_gatt_server.incoming_client_configuration(
+            peer,
+            service_id,
+            PLAYING_ORDER_HANDLE,
+            bt_gatt::server::NotificationType::Notify,
+        );
+        let _ = server.next().poll_unpin(&mut noop_cx);
+        let _ = event_receiver.try_recv();
+
+        fake_gatt_server.incoming_write(
+            peer,
+            service_id,
+            PLAYING_ORDER_HANDLE,
+            0,
+            vec![PlayingOrder::ShuffleOnce.into()],
+        );
+
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        let Poll::Ready(Some(Ok(McsServerEvent::SetPlayingOrder { peer_id, order, responder }))) =
+            poll_result
+        else {
+            panic!("expected SetPlayingOrder event, got {poll_result:?}");
+        };
+        assert_eq!(peer_id, peer);
+        assert_eq!(order, PlayingOrder::ShuffleOnce);
+
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert!(value.is_ok());
+
+        // Upper layer confirms playing order
+        responder.send(order);
+        let _ = server.next().poll_unpin(&mut noop_cx);
+
+        let FakeServerEvent::Notified { handle, value, peers, .. } =
+            event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected Notified");
+        };
+        assert_eq!(handle, PLAYING_ORDER_HANDLE);
+        assert_eq!(peers, vec![peer]);
+        assert_eq!(value, vec![PlayingOrder::ShuffleOnce.into()]);
+
+        // Subsequent read reflects the updated playing order
+        fake_gatt_server.incoming_read(peer, service_id, PLAYING_ORDER_HANDLE, 0);
+        let _ = server.next().poll_unpin(&mut noop_cx);
+        let FakeServerEvent::ReadResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected ReadResponded");
+        };
+        assert_eq!(value.unwrap(), vec![PlayingOrder::ShuffleOnce.into()]);
+    }
+
+    #[test]
+    fn write_playing_order_unsupported_is_ignored() {
+        let (mut server, fake_gatt_server, mut event_receiver) = setup_test_server(
+            McsServerBuilder::generic(0x42, "Test Player")
+                .with_playing_orders(SupportedPlayingOrders::IN_ORDER_ONCE),
+        );
+        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
+
+        let peer = PeerId(1);
+        let service_id = ServiceId::new(0x42);
+
+        // Writing ShuffleOnce when only InOrderOnce is supported is ignored per MCS
+        // v1.0.1 Section 3.15.1
+        fake_gatt_server.incoming_write(
+            peer,
+            service_id,
+            PLAYING_ORDER_HANDLE,
+            0,
+            vec![PlayingOrder::ShuffleOnce.into()],
+        );
+
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        assert_matches!(poll_result, Poll::Pending);
+
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert!(value.is_ok());
+
+        // Value remains unchanged (InOrderOnce)
+        fake_gatt_server.incoming_read(peer, service_id, PLAYING_ORDER_HANDLE, 0);
+        let _ = server.next().poll_unpin(&mut noop_cx);
+        let FakeServerEvent::ReadResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected ReadResponded");
+        };
+        assert_eq!(value.unwrap(), vec![PlayingOrder::InOrderOnce.into()]);
+    }
+
+    #[test]
+    fn write_read_only_characteristic_returns_error() {
+        let (mut server, fake_gatt_server, mut event_receiver) =
+            setup_test_server(McsServerBuilder::generic(0x42, "Test Player"));
+        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
+
+        let peer = PeerId(1);
+        let service_id = ServiceId::new(0x42);
+
+        let read_only_writes = [
+            (MEDIA_PLAYER_NAME_HANDLE, b"New Name".to_vec()),
+            (TRACK_CHANGED_HANDLE, vec![]),
+            (TRACK_TITLE_HANDLE, b"New Title".to_vec()),
+            (TRACK_DURATION_HANDLE, 1000i32.to_le_bytes().to_vec()),
+            (MEDIA_PLAYER_ICON_URL_HANDLE, b"https://example.com".to_vec()),
+            (SEEKING_SPEED_HANDLE, vec![0x00]),
+            (PLAYING_ORDERS_SUPPORTED_HANDLE, vec![0x01, 0x00]),
+            (MEDIA_STATE_HANDLE, vec![0x01]),
+            (MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_HANDLE, vec![0x01, 0x00, 0x00, 0x00]),
+            (CONTENT_CONTROL_ID_HANDLE, vec![0x99]),
+        ];
+
+        for (handle, value) in read_only_writes {
+            fake_gatt_server.incoming_write(peer, service_id, handle, 0, value);
+            let poll_result = server.next().poll_unpin(&mut noop_cx);
+            assert_matches!(poll_result, Poll::Pending);
+            let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+            else {
+                panic!("expected WriteResponded for handle {:?}", handle);
+            };
+            assert_matches!(
+                value.unwrap_err(),
+                bt_gatt::types::Error::Gatt(GattError::WriteNotPermitted),
+                "handle {:?} should return WriteNotPermitted on write",
+                handle
+            );
+        }
+    }
+
+    #[test]
+    fn control_point_unsupported_opcode_immediate_notification() {
+        let peer = PeerId(1);
+        let service_id = ServiceId::new(0x42);
+        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
+            setup_test_server_with_control_point(peer);
+
+        // Write an unsupported/RFU opcode (0xEE)
+        fake_gatt_server.incoming_write(
+            peer,
+            service_id,
+            MEDIA_CONTROL_POINT_HANDLE,
+            0,
+            vec![0xEE],
+        );
+
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        assert_matches!(poll_result, Poll::Pending);
+
+        // ATT write is acknowledged
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert!(value.is_ok());
+
+        // Immediate Media Control Point Notification sent with OPCODE_NOT_SUPPORTED
+        // (0x02)
+        let FakeServerEvent::Notified { handle, value, peers, .. } =
+            event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected Notified");
+        };
+        assert_eq!(handle, MEDIA_CONTROL_POINT_HANDLE);
+        assert_eq!(peers, vec![peer]);
+        assert_eq!(value, vec![0xEE, ControlPointResultCode::OpcodeNotSupported.into()]);
+    }
+
+    #[test]
+    fn control_point_inactive_player_immediate_notification() {
+        let peer = PeerId(1);
+        let service_id = ServiceId::new(0x42);
+        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
+            setup_test_server_with_control_point(peer);
+
+        // Write Play opcode (0x01) while player is Inactive
+        fake_gatt_server.incoming_write(
+            peer,
+            service_id,
+            MEDIA_CONTROL_POINT_HANDLE,
+            0,
+            vec![0x01],
+        );
+
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        assert_matches!(poll_result, Poll::Pending);
+
+        // ATT write is acknowledged
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert!(value.is_ok());
+
+        // Immediate Media Control Point Notification sent with MEDIA_PLAYER_INACTIVE
+        // (0x03)
+        let FakeServerEvent::Notified { handle, value, peers, .. } =
+            event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected Notified");
+        };
+        assert_eq!(handle, MEDIA_CONTROL_POINT_HANDLE);
+        assert_eq!(peers, vec![peer]);
+        assert_eq!(value, vec![0x01, ControlPointResultCode::MediaPlayerInactive.into()]);
+    }
+
+    #[test]
+    fn control_point_valid_command_success() {
+        let peer = PeerId(1);
+        let service_id = ServiceId::new(0x42);
+        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
+            setup_test_server_with_control_point(peer);
+        server.set_media_state(MediaState::Playing);
+
+        // Write Pause opcode (0x02)
+        fake_gatt_server.incoming_write(
+            peer,
+            service_id,
+            MEDIA_CONTROL_POINT_HANDLE,
+            0,
+            vec![0x02],
+        );
+
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        let Poll::Ready(Some(Ok(McsServerEvent::ControlPointCommand { opcode, responder }))) =
+            poll_result
+        else {
+            panic!("expected ControlPointCommand event, got {poll_result:?}");
+        };
+        assert_eq!(opcode, MediaControlOpcode::Pause);
+
+        // ATT write is acknowledged
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert!(value.is_ok());
+
+        // Upper layer executes command and responds with Success
+        responder.send(ControlPointResultCode::Success);
+
+        // Polling the server dispatches the notification
+        let _ = server.next().poll_unpin(&mut noop_cx);
+
+        let FakeServerEvent::Notified { handle, value, peers, .. } =
+            event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected Notified");
+        };
+        assert_eq!(handle, MEDIA_CONTROL_POINT_HANDLE);
+        assert_eq!(peers, vec![peer]);
+        assert_eq!(value, vec![0x02, ControlPointResultCode::Success.into()]);
+    }
+
+    #[test]
+    fn control_point_parameterized_command_success() {
+        let peer = PeerId(1);
+        let service_id = ServiceId::new(0x42);
+        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
+            setup_test_server_with_control_point(peer);
+        server.set_media_state(MediaState::Playing);
+
+        // MoveRelative opcode with 4-byte offset parameter
+        let opcode = MediaControlOpcode::MoveRelative(1500);
+        let mut write_val = vec![opcode.raw_opcode()];
+        write_val.extend_from_slice(&1500i32.to_le_bytes());
+
+        fake_gatt_server.incoming_write(peer, service_id, MEDIA_CONTROL_POINT_HANDLE, 0, write_val);
+
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        let Poll::Ready(Some(Ok(McsServerEvent::ControlPointCommand {
+            opcode: rx_opcode,
+            responder,
+        }))) = poll_result
+        else {
+            panic!("expected ControlPointCommand event, got {poll_result:?}");
+        };
+        assert_eq!(rx_opcode, opcode);
+
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert!(value.is_ok());
+
+        responder.send(ControlPointResultCode::Success);
+        let _ = server.next().poll_unpin(&mut noop_cx);
+
+        let FakeServerEvent::Notified { handle, value, peers, .. } =
+            event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected Notified");
+        };
+        assert_eq!(handle, MEDIA_CONTROL_POINT_HANDLE);
+        assert_eq!(peers, vec![peer]);
+        assert_eq!(value, vec![opcode.raw_opcode(), ControlPointResultCode::Success.into()]);
+    }
+
+    #[test]
+    fn control_point_truncated_parameter_sends_opcode_not_supported() {
+        let peer = PeerId(1);
+        let service_id = ServiceId::new(0x42);
+        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
+            setup_test_server_with_control_point(peer);
+        server.set_media_state(MediaState::Playing);
+
+        // MoveRelative requires 5 octets; provide only 2 octets
+        let raw_op = MediaControlOpcode::MoveRelative(0).raw_opcode();
+        fake_gatt_server.incoming_write(
+            peer,
+            service_id,
+            MEDIA_CONTROL_POINT_HANDLE,
+            0,
+            vec![raw_op, 0x01],
+        );
+
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        assert_matches!(poll_result, Poll::Pending);
+
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert!(value.is_ok());
+
+        let FakeServerEvent::Notified { handle, value, peers, .. } =
+            event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected Notified");
+        };
+        assert_eq!(handle, MEDIA_CONTROL_POINT_HANDLE);
+        assert_eq!(peers, vec![peer]);
+        assert_eq!(value, vec![raw_op, ControlPointResultCode::OpcodeNotSupported.into()]);
+    }
+
+    #[test]
+    fn control_point_empty_value_or_invalid_offset_returns_gatt_error() {
+        let peer = PeerId(1);
+        let service_id = ServiceId::new(0x42);
+        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
+            setup_test_server_with_control_point(peer);
+
+        // Non-zero offset returns InvalidOffset
+        fake_gatt_server.incoming_write(
+            peer,
+            service_id,
+            MEDIA_CONTROL_POINT_HANDLE,
+            1,
+            vec![0x01],
+        );
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        assert_matches!(poll_result, Poll::Pending);
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert_matches!(value.unwrap_err(), bt_gatt::types::Error::Gatt(GattError::InvalidOffset));
+
+        // Empty value returns InvalidAttributeValueLength
+        fake_gatt_server.incoming_write(peer, service_id, MEDIA_CONTROL_POINT_HANDLE, 0, vec![]);
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        assert_matches!(poll_result, Poll::Pending);
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert_matches!(
+            value.unwrap_err(),
+            bt_gatt::types::Error::Gatt(GattError::InvalidAttributeValueLength)
+        );
+    }
+
+    #[test]
+    fn control_point_unsupported_opcode_on_active_player_returns_opcode_not_supported() {
+        let peer = PeerId(1);
+        let service_id = ServiceId::new(0x42);
+        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
+            setup_test_server_with_control_point(peer);
+        server.set_media_state(MediaState::Playing);
+        server.set_supported_opcodes(SupportedOpcodes::PLAY);
+
+        // Pause is valid in spec, but not in supported_opcodes for this server instance
+        fake_gatt_server.incoming_write(
+            peer,
+            service_id,
+            MEDIA_CONTROL_POINT_HANDLE,
+            0,
+            vec![MediaControlOpcode::Pause.raw_opcode()],
+        );
+
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        assert_matches!(poll_result, Poll::Pending);
+
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert!(value.is_ok());
+
+        let FakeServerEvent::Notified { handle, value, peers, .. } =
+            event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected Notified");
+        };
+        assert_eq!(handle, MEDIA_CONTROL_POINT_HANDLE);
+        assert_eq!(peers, vec![peer]);
+        assert_eq!(
+            value,
+            vec![
+                MediaControlOpcode::Pause.raw_opcode(),
+                ControlPointResultCode::OpcodeNotSupported.into()
+            ]
+        );
+    }
+
+    #[test]
+    fn control_point_dropped_responder_sends_cannot_be_completed() {
+        let peer = PeerId(1);
+        let service_id = ServiceId::new(0x42);
+        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
+            setup_test_server_with_control_point(peer);
+        server.set_media_state(MediaState::Playing);
+
+        // Write Stop opcode (0x05)
+        fake_gatt_server.incoming_write(
+            peer,
+            service_id,
+            MEDIA_CONTROL_POINT_HANDLE,
+            0,
+            vec![0x05],
+        );
+
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        let Poll::Ready(Some(Ok(McsServerEvent::ControlPointCommand { opcode, responder }))) =
+            poll_result
+        else {
+            panic!("expected ControlPointCommand event, got {poll_result:?}");
+        };
+        assert_eq!(opcode, MediaControlOpcode::Stop);
+
+        // ATT write is acknowledged
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert!(value.is_ok());
+
+        // Responder is dropped without calling send
+        drop(responder);
+
+        // Polling the server dispatches the fallback notification
+        let _ = server.next().poll_unpin(&mut noop_cx);
+
+        let FakeServerEvent::Notified { handle, value, peers, .. } =
+            event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected Notified");
+        };
+        assert_eq!(handle, MEDIA_CONTROL_POINT_HANDLE);
+        assert_eq!(peers, vec![peer]);
+        assert_eq!(value, vec![0x05, ControlPointResultCode::CommandCannotBeCompleted.into()]);
+    }
+
+    #[test]
+    fn control_point_multiple_consecutive_notifications() {
+        let peer1 = PeerId(1);
+        let peer2 = PeerId(2);
+        let service_id = ServiceId::new(0x42);
+        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
+            setup_test_server_with_control_point(peer1);
+        server.set_media_state(MediaState::Playing);
+
+        // Also configure notifications for peer2
+        fake_gatt_server.incoming_client_configuration(
+            peer2,
+            server.service_def.id(),
+            MEDIA_CONTROL_POINT_HANDLE,
+            bt_gatt::server::NotificationType::Notify,
+        );
+        let _ = server.next().poll_unpin(&mut noop_cx);
+        let _ = event_receiver.try_recv();
+
+        // Issue 1st command (Play from peer1)
+        fake_gatt_server.incoming_write(
+            peer1,
+            service_id,
+            MEDIA_CONTROL_POINT_HANDLE,
+            0,
+            vec![MediaControlOpcode::Play.raw_opcode()],
+        );
+
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        let Poll::Ready(Some(Ok(McsServerEvent::ControlPointCommand {
+            opcode: op1,
+            responder: resp1,
+        }))) = poll_result
+        else {
+            panic!("expected 1st ControlPointCommand event, got {poll_result:?}");
+        };
+        assert_eq!(op1, MediaControlOpcode::Play);
+
+        // Issue 2nd command (NextTrack from peer2)
+        fake_gatt_server.incoming_write(
+            peer2,
+            service_id,
+            MEDIA_CONTROL_POINT_HANDLE,
+            0,
+            vec![MediaControlOpcode::NextTrack.raw_opcode()],
+        );
+
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        let Poll::Ready(Some(Ok(McsServerEvent::ControlPointCommand {
+            opcode: op2,
+            responder: resp2,
+        }))) = poll_result
+        else {
+            panic!("expected 2nd ControlPointCommand event, got {poll_result:?}");
+        };
+        assert_eq!(op2, MediaControlOpcode::NextTrack);
+
+        // Drain write acknowledgements
+        let FakeServerEvent::WriteResponded { value: val1, .. } =
+            event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected 1st WriteResponded");
+        };
+        assert!(val1.is_ok());
+
+        let FakeServerEvent::WriteResponded { value: val2, .. } =
+            event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected 2nd WriteResponded");
+        };
+        assert!(val2.is_ok());
+
+        // Respond to both commands in a row before polling the stream
+        resp1.send(ControlPointResultCode::Success);
+        resp2.send(ControlPointResultCode::CommandCannotBeCompleted);
+
+        // Polling the server stream drains both pending control point responses and
+        // issues two local service notifications in a single poll_next invocation.
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        assert_matches!(poll_result, Poll::Pending);
+
+        let n1 = event_receiver.try_recv().unwrap();
+        let n2 = event_receiver.try_recv().unwrap();
+
+        let mut received = Vec::new();
+        for event in [n1, n2] {
+            let FakeServerEvent::Notified { handle, value, peers, .. } = event else {
+                panic!("expected Notified event, got {event:?}");
+            };
+            assert_eq!(handle, MEDIA_CONTROL_POINT_HANDLE);
+            received.push((peers, value));
+        }
+
+        assert!(received.contains(&(
+            vec![peer1],
+            vec![MediaControlOpcode::Play.raw_opcode(), ControlPointResultCode::Success.into()]
+        )));
+        assert!(received.contains(&(
+            vec![peer2],
+            vec![
+                MediaControlOpcode::NextTrack.raw_opcode(),
+                ControlPointResultCode::CommandCannotBeCompleted.into()
+            ]
+        )));
+
+        // No further events pending
+        assert_matches!(event_receiver.try_recv(), Err(_));
+    }
+
+    #[test]
+    fn server_stream_drains_pending_control_point_responses_before_terminating() {
+        let peer = PeerId(1);
+        let service_id = ServiceId::new(0x42);
+        let (mut server, fake_gatt_server, mut event_receiver, mut noop_cx) =
+            setup_test_server_with_control_point(peer);
+        server.set_media_state(MediaState::Playing);
+
+        // Write Pause opcode (0x02)
+        fake_gatt_server.incoming_write(
+            peer,
+            service_id,
+            MEDIA_CONTROL_POINT_HANDLE,
+            0,
+            vec![0x02],
+        );
+
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        let Poll::Ready(Some(Ok(McsServerEvent::ControlPointCommand { opcode, responder }))) =
+            poll_result
+        else {
+            panic!("expected ControlPointCommand event, got {poll_result:?}");
+        };
+        assert_eq!(opcode, MediaControlOpcode::Pause);
+
+        // ATT write is acknowledged
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert!(value.is_ok());
+
+        // Replace local_service events stream with a custom channel and close it.
+        let (sender, receiver) = futures::channel::mpsc::unbounded();
+        let LocalServiceState::Published { service, .. } =
+            std::mem::replace(&mut server.local_service, LocalServiceState::Terminated)
+        else {
+            panic!("Expected server to be in Published state");
+        };
+        server.local_service = LocalServiceState::Published { service, events: receiver };
+        drop(sender);
+
+        // Polling the server returns Pending because there is still an in-flight
+        // responder
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        assert_matches!(poll_result, Poll::Pending);
+
+        // Upper layer executes command and responds with Success
+        responder.send(ControlPointResultCode::Success);
+
+        // Polling the server dispatches the notification and drains the in-flight
+        // response, then terminates the stream as the GATT service event stream
+        // has closed.
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        assert_matches!(poll_result, Poll::Ready(None));
+
+        let FakeServerEvent::Notified { handle, value, peers, .. } =
+            event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected Notified");
+        };
+        assert_eq!(handle, MEDIA_CONTROL_POINT_HANDLE);
+        assert_eq!(peers, vec![peer]);
+        assert_eq!(value, vec![0x02, ControlPointResultCode::Success.into()]);
+    }
+
+    #[test]
+    fn write_negative_track_position_success() {
+        let (mut server, fake_gatt_server, mut event_receiver) =
+            setup_test_server(McsServerBuilder::generic(0x42, "Test Player"));
+        server.state.media_state = MediaState::Paused;
+        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
+
+        let peer = PeerId(1);
+        let service_id = ServiceId::new(0x42);
+
+        fake_gatt_server.incoming_client_configuration(
+            peer,
+            service_id,
+            TRACK_POSITION_HANDLE,
+            bt_gatt::server::NotificationType::Notify,
+        );
+        let _ = server.next().poll_unpin(&mut noop_cx);
+        let _ = event_receiver.try_recv();
+
+        // Negative value represents offset from end of track per MCS v1.0.1 Section
+        // 3.7.1
+        fake_gatt_server.incoming_write(
+            peer,
+            service_id,
+            TRACK_POSITION_HANDLE,
+            0,
+            (-500i32).to_le_bytes().to_vec(),
+        );
+
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        let Poll::Ready(Some(Ok(McsServerEvent::SetTrackPosition {
+            peer_id,
+            position,
+            responder,
+        }))) = poll_result
+        else {
+            panic!("expected SetTrackPosition event, got {poll_result:?}");
+        };
+        assert_eq!(peer_id, peer);
+        assert_eq!(position, TrackPosition::from_raw_10ms(-500));
+
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert!(value.is_ok());
+
+        // Upper layer confirms the updated track position
+        responder.send(position);
+        let _ = server.next().poll_unpin(&mut noop_cx);
+
+        let FakeServerEvent::Notified { handle, value, peers, .. } =
+            event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected Notified");
+        };
+        assert_eq!(handle, TRACK_POSITION_HANDLE);
+        assert_eq!(peers, vec![peer]);
+        assert_eq!(value, (-500i32).to_le_bytes().to_vec());
+
+        // Subsequent read reflects the updated track position
+        fake_gatt_server.incoming_read(peer, service_id, TRACK_POSITION_HANDLE, 0);
+        let _ = server.next().poll_unpin(&mut noop_cx);
+        let FakeServerEvent::ReadResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected ReadResponded");
+        };
+        assert_eq!(value.unwrap(), (-500i32).to_le_bytes());
+    }
+
+    #[test]
+    fn write_responder_dropped_without_send_does_not_notify_or_mutate() {
+        let (mut server, fake_gatt_server, mut event_receiver) = setup_test_server(
+            McsServerBuilder::generic(0x42, "Test Player")
+                .with_player_speeds()
+                .with_playing_orders(SupportedPlayingOrders::all()),
+        );
+        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
+
+        let peer = PeerId(1);
+        let service_id = ServiceId::new(0x42);
+
+        // 1. Playback speed write
+        fake_gatt_server.incoming_write(peer, service_id, PLAYBACK_SPEED_HANDLE, 0, vec![0x40]);
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        let Poll::Ready(Some(Ok(McsServerEvent::SetPlaybackSpeed { responder, .. }))) = poll_result
+        else {
+            panic!("expected SetPlaybackSpeed event, got {poll_result:?}");
+        };
+        // ATT write is acknowledged
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert!(value.is_ok());
+
+        // Drop responder without calling send
+        drop(responder);
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        assert_matches!(poll_result, Poll::Pending);
+        // No notification should be emitted
+        assert_matches!(event_receiver.try_recv(), Err(_));
+
+        // Playback speed remains unchanged
+        fake_gatt_server.incoming_read(peer, service_id, PLAYBACK_SPEED_HANDLE, 0);
+        let _ = server.next().poll_unpin(&mut noop_cx);
+        let FakeServerEvent::ReadResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected ReadResponded");
+        };
+        assert_eq!(value.unwrap(), vec![PlaybackSpeed::NORMAL.into()]);
+
+        // 2. Track position write
+        fake_gatt_server.incoming_write(
+            peer,
+            service_id,
+            TRACK_POSITION_HANDLE,
+            0,
+            500i32.to_le_bytes().to_vec(),
+        );
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        let Poll::Ready(Some(Ok(McsServerEvent::SetTrackPosition { responder, .. }))) = poll_result
+        else {
+            panic!("expected SetTrackPosition event, got {poll_result:?}");
+        };
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert!(value.is_ok());
+
+        drop(responder);
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        assert_matches!(poll_result, Poll::Pending);
+        assert_matches!(event_receiver.try_recv(), Err(_));
+
+        // Track position remains unavailable
+        fake_gatt_server.incoming_read(peer, service_id, TRACK_POSITION_HANDLE, 0);
+        let _ = server.next().poll_unpin(&mut noop_cx);
+        let FakeServerEvent::ReadResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected ReadResponded");
+        };
+        assert_eq!(value.unwrap(), TrackPosition::Unavailable.raw_10ms().to_le_bytes());
+
+        // 3. Playing order write
+        fake_gatt_server.incoming_write(
+            peer,
+            service_id,
+            PLAYING_ORDER_HANDLE,
+            0,
+            vec![PlayingOrder::ShuffleOnce.into()],
+        );
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        let Poll::Ready(Some(Ok(McsServerEvent::SetPlayingOrder { responder, .. }))) = poll_result
+        else {
+            panic!("expected SetPlayingOrder event, got {poll_result:?}");
+        };
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert!(value.is_ok());
+
+        drop(responder);
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        assert_matches!(poll_result, Poll::Pending);
+        assert_matches!(event_receiver.try_recv(), Err(_));
+
+        // Playing order remains default InOrderOnce
+        fake_gatt_server.incoming_read(peer, service_id, PLAYING_ORDER_HANDLE, 0);
+        let _ = server.next().poll_unpin(&mut noop_cx);
+        let FakeServerEvent::ReadResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected ReadResponded");
+        };
+        assert_eq!(value.unwrap(), vec![PlayingOrder::InOrderOnce.into()]);
+    }
+
+    #[test]
+    fn write_playing_order_invalid_value_is_ignored() {
+        let (mut server, fake_gatt_server, mut event_receiver) = setup_test_server(
+            McsServerBuilder::generic(0x42, "Test Player")
+                .with_playing_orders(SupportedPlayingOrders::all()),
+        );
+        let mut noop_cx = Context::from_waker(futures::task::noop_waker_ref());
+
+        let peer = PeerId(1);
+        let service_id = ServiceId::new(0x42);
+
+        // Write an out-of-range RFU value (0xFF)
+        fake_gatt_server.incoming_write(peer, service_id, PLAYING_ORDER_HANDLE, 0, vec![0xFF]);
+
+        let poll_result = server.next().poll_unpin(&mut noop_cx);
+        assert_matches!(poll_result, Poll::Pending);
+
+        let FakeServerEvent::WriteResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected WriteResponded");
+        };
+        assert!(value.is_ok());
+
+        // Value remains unchanged (default InOrderOnce)
+        fake_gatt_server.incoming_read(peer, service_id, PLAYING_ORDER_HANDLE, 0);
+        let _ = server.next().poll_unpin(&mut noop_cx);
+        let FakeServerEvent::ReadResponded { value, .. } = event_receiver.try_recv().unwrap()
+        else {
+            panic!("expected ReadResponded");
+        };
+        assert_eq!(value.unwrap(), vec![PlayingOrder::InOrderOnce.into()]);
+    }
+
+    #[test]
+    fn local_state_handle_read() {
+        let mut state = McsLocalState::new(0x01, "Player");
+        state.media_state = MediaState::Paused;
+        state.playback_speed = Some(PlaybackSpeed::NORMAL);
+        state.playing_orders = Some(PlayingOrderState::new(SupportedPlayingOrders::all()));
+
+        // Track Position
+        assert_eq!(
+            state.handle_read(TRACK_POSITION_HANDLE, 0),
+            Ok(TrackPosition::Unavailable.raw_10ms().to_le_bytes().to_vec())
+        );
+
+        // Playback Speed
+        assert_eq!(state.handle_read(PLAYBACK_SPEED_HANDLE, 0), Ok(vec![0x00]));
+
+        // Playing Order
+        assert_eq!(
+            state.handle_read(PLAYING_ORDER_HANDLE, 0),
+            Ok(vec![PlayingOrder::InOrderOnce.into()])
+        );
+    }
+
+    #[test]
+    fn playing_order_state_helpers() {
+        let mut state = PlayingOrderState::new(SupportedPlayingOrders::IN_ORDER_ONCE);
+        assert_eq!(state.current, PlayingOrder::InOrderOnce);
+        assert_eq!(state.supported, SupportedPlayingOrders::IN_ORDER_ONCE);
+        assert!(!state.set_order(PlayingOrder::SingleOnce));
+        assert_eq!(state.current, PlayingOrder::InOrderOnce);
+        assert!(state.set_order(PlayingOrder::InOrderOnce));
+
+        let mut all_state = PlayingOrderState::new(SupportedPlayingOrders::all());
+        assert_eq!(all_state.current, PlayingOrder::InOrderOnce);
+        assert_eq!(all_state.supported, SupportedPlayingOrders::all());
+        assert!(all_state.set_order(PlayingOrder::ShuffleRepeat));
+        assert_eq!(all_state.current, PlayingOrder::ShuffleRepeat);
     }
 
     #[test]
diff --git a/rust/bt-mcs/src/types.rs b/rust/bt-mcs/src/types.rs
index 1d9d8d0..35594c4 100644
--- a/rust/bt-mcs/src/types.rs
+++ b/rust/bt-mcs/src/types.rs
@@ -706,6 +706,205 @@
     }
 }
 
+/// Playback speed of the media player (MCS v1.0.1 Section 3.8).
+/// Expressed as a power of 2 with a scale factor of 64: multiplier = 2^(speed /
+/// 64).
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct PlaybackSpeed(i8);
+
+impl PlaybackSpeed {
+    /// Minimum supported playback speed.
+    pub const MIN: Self = Self(-128);
+    /// Quarter (0.25x) playback speed.
+    pub const QUARTER: Self = Self(-128);
+    /// Half (0.50x) playback speed.
+    pub const HALF: Self = Self(-64);
+    /// Normal (1.00x) playback speed.
+    pub const NORMAL: Self = Self(0);
+    /// Double (2.00x) playback speed.
+    pub const DOUBLE: Self = Self(64);
+    /// Maximum supported playback speed.
+    pub const MAX: Self = Self(127);
+
+    /// Calculates the floating-point speed multiplier (e.g., 1.0 for normal,
+    /// 0.5 for half speed).
+    pub fn as_multiplier(&self) -> f64 {
+        2.0f64.powf(self.0 as f64 / 64.0)
+    }
+
+    /// Constructs a `PlaybackSpeed` from a floating-point multiplier, clamping
+    /// to the supported range.
+    pub fn from_multiplier(multiplier: f64) -> Self {
+        if multiplier <= 0.0 {
+            return Self::MIN;
+        }
+        let p = (64.0 * multiplier.log2()).round();
+        let clamped = p.clamp(i8::MIN as f64, i8::MAX as f64) as i8;
+        Self(clamped)
+    }
+}
+
+impl Default for PlaybackSpeed {
+    fn default() -> Self {
+        Self::NORMAL
+    }
+}
+
+impl From<i8> for PlaybackSpeed {
+    fn from(raw: i8) -> Self {
+        Self(raw)
+    }
+}
+
+impl From<PlaybackSpeed> for i8 {
+    fn from(speed: PlaybackSpeed) -> Self {
+        speed.0
+    }
+}
+
+impl From<PlaybackSpeed> for u8 {
+    fn from(speed: PlaybackSpeed) -> Self {
+        speed.0 as u8
+    }
+}
+
+impl TryFrom<&[u8]> for PlaybackSpeed {
+    type Error = PacketError;
+
+    fn try_from(buf: &[u8]) -> Result<Self, Self::Error> {
+        if buf.len() != 1 {
+            return Err(PacketError::UnexpectedDataLength);
+        }
+        Ok(Self(buf[0] as i8))
+    }
+}
+
+impl Encodable for PlaybackSpeed {
+    type Error = PacketError;
+
+    fn encoded_len(&self) -> usize {
+        1
+    }
+
+    fn encode(&self, buf: &mut [u8]) -> Result<(), Self::Error> {
+        if buf.is_empty() {
+            return Err(PacketError::BufferTooSmall);
+        }
+        buf[0] = self.0 as u8;
+        Ok(())
+    }
+}
+
+impl Decodable for PlaybackSpeed {
+    type Error = PacketError;
+
+    fn decode(buf: &[u8]) -> (Result<Self, Self::Error>, usize) {
+        if buf.is_empty() {
+            return (Err(PacketError::UnexpectedDataLength), 0);
+        }
+        (Ok(Self(buf[0] as i8)), 1)
+    }
+}
+
+/// Seeking speed factor of the media player (MCS v1.0.1 Section 3.9).
+/// A signed integer representing the multiplier factor during fast-forwarding
+/// or fast-rewinding.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct SeekingSpeed(i8);
+
+impl SeekingSpeed {
+    /// Not seeking.
+    pub const NOT_SEEKING: Self = Self(0);
+
+    /// Constructs a `SeekingSpeed` from the signed speed factor.
+    pub const fn new(factor: i8) -> Self {
+        Self(factor)
+    }
+
+    /// Returns the signed seeking factor.
+    pub const fn factor(&self) -> i8 {
+        self.0
+    }
+
+    /// Returns `true` if the media player is currently fast-forwarding or
+    /// rewinding.
+    pub const fn is_seeking(&self) -> bool {
+        self.0 != 0
+    }
+
+    /// Returns `true` if the media player is fast-forwarding.
+    pub const fn is_fast_forwarding(&self) -> bool {
+        self.0 > 0
+    }
+
+    /// Returns `true` if the media player is fast-rewinding.
+    pub const fn is_fast_rewinding(&self) -> bool {
+        self.0 < 0
+    }
+}
+
+impl Default for SeekingSpeed {
+    fn default() -> Self {
+        Self::NOT_SEEKING
+    }
+}
+
+impl From<i8> for SeekingSpeed {
+    fn from(raw: i8) -> Self {
+        Self(raw)
+    }
+}
+
+impl From<SeekingSpeed> for i8 {
+    fn from(speed: SeekingSpeed) -> Self {
+        speed.0
+    }
+}
+
+impl From<SeekingSpeed> for u8 {
+    fn from(speed: SeekingSpeed) -> Self {
+        speed.0 as u8
+    }
+}
+
+impl TryFrom<&[u8]> for SeekingSpeed {
+    type Error = PacketError;
+
+    fn try_from(buf: &[u8]) -> Result<Self, Self::Error> {
+        if buf.len() != 1 {
+            return Err(PacketError::UnexpectedDataLength);
+        }
+        Ok(Self(buf[0] as i8))
+    }
+}
+
+impl Encodable for SeekingSpeed {
+    type Error = PacketError;
+
+    fn encoded_len(&self) -> usize {
+        1
+    }
+
+    fn encode(&self, buf: &mut [u8]) -> Result<(), Self::Error> {
+        if buf.is_empty() {
+            return Err(PacketError::BufferTooSmall);
+        }
+        buf[0] = self.0 as u8;
+        Ok(())
+    }
+}
+
+impl Decodable for SeekingSpeed {
+    type Error = PacketError;
+
+    fn decode(buf: &[u8]) -> (Result<Self, Self::Error>, usize) {
+        if buf.is_empty() {
+            return (Err(PacketError::UnexpectedDataLength), 0);
+        }
+        (Ok(Self(buf[0] as i8)), 1)
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -1146,4 +1345,91 @@
         assert_eq!(consumed, 0);
         assert_eq!(err.unwrap_err(), PacketError::UnexpectedDataLength);
     }
+
+    #[test]
+    fn playback_speed_helpers_and_encoding() {
+        assert_eq!(i8::from(PlaybackSpeed::NORMAL), 0);
+        assert_eq!(i8::from(PlaybackSpeed::QUARTER), -128);
+        assert_eq!(i8::from(PlaybackSpeed::HALF), -64);
+        assert_eq!(i8::from(PlaybackSpeed::DOUBLE), 64);
+        assert_eq!(i8::from(PlaybackSpeed::MAX), 127);
+
+        assert!((PlaybackSpeed::NORMAL.as_multiplier() - 1.0).abs() < 1e-6);
+        assert!((PlaybackSpeed::QUARTER.as_multiplier() - 0.25).abs() < 1e-6);
+        assert!((PlaybackSpeed::HALF.as_multiplier() - 0.5).abs() < 1e-6);
+        assert!((PlaybackSpeed::DOUBLE.as_multiplier() - 2.0).abs() < 1e-6);
+
+        assert_eq!(PlaybackSpeed::from_multiplier(1.0), PlaybackSpeed::NORMAL);
+        assert_eq!(PlaybackSpeed::from_multiplier(0.25), PlaybackSpeed::QUARTER);
+        assert_eq!(PlaybackSpeed::from_multiplier(0.5), PlaybackSpeed::HALF);
+        assert_eq!(PlaybackSpeed::from_multiplier(2.0), PlaybackSpeed::DOUBLE);
+        assert_eq!(PlaybackSpeed::from_multiplier(0.0), PlaybackSpeed::MIN);
+        assert_eq!(PlaybackSpeed::from_multiplier(100.0), PlaybackSpeed::MAX);
+
+        let speed = PlaybackSpeed::DOUBLE;
+        let mut buf = [0u8; 1];
+        assert!(speed.encode(&mut buf).is_ok());
+        assert_eq!(buf[0], 64);
+
+        let (decoded, consumed) = PlaybackSpeed::decode(&buf);
+        assert_eq!(consumed, 1);
+        assert_eq!(decoded.unwrap(), speed);
+
+        assert_eq!(PlaybackSpeed::try_from(&buf[..]).unwrap(), speed);
+        assert_eq!(
+            PlaybackSpeed::try_from(&[][..]).unwrap_err(),
+            PacketError::UnexpectedDataLength
+        );
+        assert_eq!(
+            PlaybackSpeed::try_from(&[1, 2][..]).unwrap_err(),
+            PacketError::UnexpectedDataLength
+        );
+
+        let mut empty = [0u8; 0];
+        assert_eq!(speed.encode(&mut empty).unwrap_err(), PacketError::BufferTooSmall);
+        let (err, consumed) = PlaybackSpeed::decode(&[]);
+        assert_eq!(consumed, 0);
+        assert_eq!(err.unwrap_err(), PacketError::UnexpectedDataLength);
+    }
+
+    #[test]
+    fn seeking_speed_helpers_and_encoding() {
+        assert_eq!(SeekingSpeed::NOT_SEEKING.factor(), 0);
+        assert!(!SeekingSpeed::NOT_SEEKING.is_seeking());
+        assert!(!SeekingSpeed::NOT_SEEKING.is_fast_forwarding());
+        assert!(!SeekingSpeed::NOT_SEEKING.is_fast_rewinding());
+
+        let fast_forward = SeekingSpeed::new(4);
+        assert_eq!(fast_forward.factor(), 4);
+        assert!(fast_forward.is_seeking());
+        assert!(fast_forward.is_fast_forwarding());
+        assert!(!fast_forward.is_fast_rewinding());
+
+        let fast_rewind = SeekingSpeed::new(-4);
+        assert_eq!(fast_rewind.factor(), -4);
+        assert!(fast_rewind.is_seeking());
+        assert!(!fast_rewind.is_fast_forwarding());
+        assert!(fast_rewind.is_fast_rewinding());
+
+        let mut buf = [0u8; 1];
+        assert!(fast_forward.encode(&mut buf).is_ok());
+        assert_eq!(buf[0], 4);
+
+        let (decoded, consumed) = SeekingSpeed::decode(&buf);
+        assert_eq!(consumed, 1);
+        assert_eq!(decoded.unwrap(), fast_forward);
+
+        assert_eq!(SeekingSpeed::try_from(&buf[..]).unwrap(), fast_forward);
+        assert_eq!(SeekingSpeed::try_from(&[][..]).unwrap_err(), PacketError::UnexpectedDataLength);
+        assert_eq!(
+            SeekingSpeed::try_from(&[1, 2][..]).unwrap_err(),
+            PacketError::UnexpectedDataLength
+        );
+
+        let mut empty = [0u8; 0];
+        assert_eq!(fast_forward.encode(&mut empty).unwrap_err(), PacketError::BufferTooSmall);
+        let (err, consumed) = SeekingSpeed::decode(&[]);
+        assert_eq!(consumed, 0);
+        assert_eq!(err.unwrap_err(), PacketError::UnexpectedDataLength);
+    }
 }
