processed
diff --git a/services/mctp/server/src/dispatch.rs b/services/mctp/server/src/dispatch.rs
index 00436a5..127ccfe 100644
--- a/services/mctp/server/src/dispatch.rs
+++ b/services/mctp/server/src/dispatch.rs
@@ -60,7 +60,7 @@
                         .unwrap_or_else(|_| encode_error(response, ResponseCode::InternalError))
                 }
                 Err(e) => {
-                    pw_log::error!("dispatch: Req(eid={}) failed: ResponseCode={}", header.eid as u32, e.code as u8);
+                    pw_log::error!("dispatch: Req(eid={}) failed: ResponseCode={}", header.eid as u32, e.code as u32);
                     encode_error(response, e.code)
                 }
             }
diff --git a/services/mctp/server/src/main.rs b/services/mctp/server/src/main.rs
index 125a92e..b6d8171 100644
--- a/services/mctp/server/src/main.rs
+++ b/services/mctp/server/src/main.rs
@@ -326,27 +326,54 @@
         match i2c.wait_for_messages(BusIndex::BUS_2, &mut msgs, None) {
             Ok(n) => {
                 for msg in msgs.get(..n).unwrap_or(&[]) {
-                    // Log the raw I2C frame before decode so we can confirm
-                    // the hardware actually delivered a well-formed SMBus frame.
-                    // Format: dest_addr cmd byte_count src_addr | MCTP hdr[0..3]
                     let raw = msg.data();
-                    if raw.len() >= 8 {
+
+                    // WORKAROUND: Manually prepend destination address to I2C frame.
+                    // The I2C hardware currently does NOT prepend the destination address,
+                    // but mctp-lib's I2C decoder expects it. This will be fixed when the
+                    // I2C driver is updated to prepend the destination address automatically.
+                    // TODO: Remove this workaround once I2C driver change is in place.
+                    let mut frame_with_dest = [0u8; 256];
+                    if raw.len() + 1 > frame_with_dest.len() {
+                        pw_log::warn!(
+                            "I2C frame too large ({} bytes), skipping",
+                            raw.len() as u32,
+                        );
+                        continue;
+                    }
+
+                    // Prepend destination address (OWN_I2C_ADDR << 1 | 0 for write)
+                    frame_with_dest[0] = OWN_I2C_ADDR << 1;
+                    frame_with_dest[1..raw.len() + 1].copy_from_slice(raw);
+                    let frame_len = raw.len() + 1;
+
+                    // Log the frame AFTER prepending destination
+                    // Format: dest_addr cmd byte_count src_addr | MCTP hdr[0..3]
+                    if frame_len >= 9 {
                         pw_log::info!(
-                            "I2C frame raw: dest=0x{:02x} cmd=0x{:02x} bc={} src=0x{:02x} \
+                            "I2C frame (with prepended dest): dest=0x{:02x} cmd=0x{:02x} bc={} src=0x{:02x} \
                             | mctp: ver=0x{:02x} deid=0x{:02x} seid=0x{:02x} flags=0x{:02x} \
                             len={}",
-                            raw[0] as u32, raw[1] as u32, raw[2] as u32, raw[3] as u32,
-                            raw[4] as u32, raw[5] as u32, raw[6] as u32, raw[7] as u32,
-                            raw.len() as u32,
+                            frame_with_dest[0] as u32, frame_with_dest[1] as u32,
+                            frame_with_dest[2] as u32, frame_with_dest[3] as u32,
+                            frame_with_dest[4] as u32, frame_with_dest[5] as u32,
+                            frame_with_dest[6] as u32, frame_with_dest[7] as u32,
+                            frame_len as u32,
                         );
                     } else {
                         pw_log::warn!(
                             "I2C frame too short ({} bytes) to contain MCTP header",
-                            raw.len() as u32,
+                            frame_len as u32,
                         );
                     }
 
-                    match receiver.decode(msg) {
+                    // Create temporary TargetMessage with prepended destination
+                    let msg_with_dest = i2c_api::TargetMessage::from_data(
+                        msg.source_address,
+                        &frame_with_dest[..frame_len]
+                    );
+
+                    match receiver.decode(&msg_with_dest) {
                         Ok((pkt, src_addr)) => {
                             i2c_pkt = i2c_pkt.wrapping_add(1);
                             // Log MCTP packet fields: SOM/EOM from flags byte (pkt[3])
@@ -355,23 +382,37 @@
                             let seq = pkt.get(3).map_or(0u8, |b| (b >> 4) & 0x3);
                             let msg_type = pkt.get(4).map_or(0u8, |b| b & 0x7f);
                             pw_log::info!(
-                                "MCTP pkt #{}: src_i2c=0x{:02x} len={} \
+                                "MCTP pkt #{}: src_i2c=0x{:02x} dest_i2c=0x{:02x} bc={} len={} \
                                 SOM={} EOM={} seq={} msg_type=0x{:02x}",
                                 i2c_pkt as u32,
-                                src_addr as u32,
+                                src_addr.source as u32,
+                                src_addr.dest as u32,
+                                src_addr.byte_count as u32,
                                 pkt.len() as u32,
                                 som as u32, eom as u32, seq as u32, msg_type as u32,
                             );
-                            if let Err(e) = server.borrow_mut().inbound(pkt) {
-                                inbound_err = inbound_err.wrapping_add(1);
-                                if inbound_err == 1 || inbound_err & 0xf == 0 {
-                                    pw_log::error!(
-                                        "MCTP server: inbound() error code={} \
-                                        total_inbound_errors={}",
-                                        e.code as u32,
-                                        inbound_err as u32,
+                            match server.borrow_mut().inbound(pkt) {
+                                Ok(Some(cookie)) => {
+                                    pw_log::debug!(
+                                        "MCTP pkt #{} associated with cookie {}",
+                                        i2c_pkt as u32,
+                                        cookie.0 as u32,
                                     );
                                 }
+                                Ok(None) => {
+                                    pw_log::debug!("MCTP pkt #{} discarded (no matching handler)", i2c_pkt as u32);
+                                }
+                                Err(e) => {
+                                    inbound_err = inbound_err.wrapping_add(1);
+                                    if inbound_err == 1 || inbound_err & 0xf == 0 {
+                                        pw_log::error!(
+                                            "MCTP server: inbound() error code={} \
+                                            total_inbound_errors={}",
+                                            e.code as u32,
+                                            inbound_err as u32,
+                                        );
+                                    }
+                                }
                             }
                         }
                         Err(_) => {
@@ -506,6 +547,7 @@
             if let Ok(n) = i2c_notify.get_pending_messages(BusIndex::BUS_2, &mut msgs) {
                 for msg in &msgs[..n] {
                     if let Ok((pkt, _src_addr)) = receiver.decode(msg) {
+                        // Feed packet to server; ignore result (no detailed logging in this path)
                         let _ = server.inbound(pkt);
                     }
                 }
diff --git a/services/mctp/server/src/server.rs b/services/mctp/server/src/server.rs
index 8a336a5..181d589 100644
--- a/services/mctp/server/src/server.rs
+++ b/services/mctp/server/src/server.rs
@@ -73,7 +73,7 @@
     pub fn req(&mut self, eid: u8) -> Result<Handle, MctpError> {
         self.stack.req(Eid(eid)).map(|cookie| Handle(cookie.0 as u32)).map_err(|e| {
             let err = mctp_error_to_server_error(e);
-            pw_log::error!("server: req(eid={}) ResponseCode={}", eid as u32, err.code as u8);
+            pw_log::error!("server: req(eid={}) ResponseCode={}", eid as u32, err.code as u32);
             err
         })
     }
@@ -82,7 +82,7 @@
     pub fn listener(&mut self, typ: u8) -> Result<Handle, MctpError> {
         self.stack.listener(MsgType(typ)).map(|cookie| Handle(cookie.0 as u32)).map_err(|e| {
             let err = mctp_error_to_server_error(e);
-            pw_log::error!("server: listener(typ={}) ResponseCode={}", typ as u32, err.code as u8);
+            pw_log::error!("server: listener(typ={}) ResponseCode={}", typ as u32, err.code as u32);
             err
         })
     }
@@ -264,7 +264,10 @@
     /// The platform layer calls this when data arrives from a transport
     /// binding. The packet should be a raw MCTP packet without transport
     /// headers (the transport binding strips those).
-    pub fn inbound(&mut self, pkt: &[u8]) -> Result<(), MctpError> {
+    ///
+    /// Returns `Ok(Some(AppCookie))` if the message was associated with a
+    /// listener or request handle, or `Ok(None)` if it was discarded.
+    pub fn inbound(&mut self, pkt: &[u8]) -> Result<Option<AppCookie>, MctpError> {
         self.stack
             .inbound(pkt)
             .map_err(mctp_error_to_server_error)
diff --git a/services/mctp/server/tests/common/mod.rs b/services/mctp/server/tests/common/mod.rs
index 19ad95e..848199b 100644
--- a/services/mctp/server/tests/common/mod.rs
+++ b/services/mctp/server/tests/common/mod.rs
@@ -40,6 +40,7 @@
 impl Sender for BufferSender<'_> {
     fn send_vectored(
         &mut self,
+        _eid: Eid,
         mut fragmenter: Fragmenter,
         payload: &[&[u8]],
     ) -> mctp::Result<Tag> {
@@ -73,6 +74,7 @@
 impl Sender for SmallMtuBufferSender<'_> {
     fn send_vectored(
         &mut self,
+        _eid: Eid,
         mut fragmenter: Fragmenter,
         payload: &[&[u8]],
     ) -> mctp::Result<Tag> {
@@ -106,6 +108,7 @@
 impl Sender for DroppingBufferSender {
     fn send_vectored(
         &mut self,
+        _eid: Eid,
         mut fragmenter: Fragmenter,
         payload: &[&[u8]],
     ) -> mctp::Result<Tag> {
@@ -139,7 +142,7 @@
 ) {
     let pkts = packets.borrow();
     for pkt in pkts.iter() {
-        dest.inbound(pkt).unwrap();
+        let _ = dest.inbound(pkt).unwrap();
     }
 }
 
diff --git a/services/mctp/transport-loopback/src/lib.rs b/services/mctp/transport-loopback/src/lib.rs
index a3a977e..11f4a3d 100644
--- a/services/mctp/transport-loopback/src/lib.rs
+++ b/services/mctp/transport-loopback/src/lib.rs
@@ -175,6 +175,7 @@
 impl Sender for BufferSender<'_> {
     fn send_vectored(
         &mut self,
+        _eid: Eid,
         mut fragmenter: Fragmenter,
         payload: &[&[u8]],
     ) -> mctp::Result<mctp::Tag> {
diff --git a/target/ast1060-evb/spdm-req-resp-test/mctp_loopback_server.rs b/target/ast1060-evb/spdm-req-resp-test/mctp_loopback_server.rs
index 691da34..5879246 100644
--- a/target/ast1060-evb/spdm-req-resp-test/mctp_loopback_server.rs
+++ b/target/ast1060-evb/spdm-req-resp-test/mctp_loopback_server.rs
@@ -82,8 +82,16 @@
     let pkts = packets.borrow();
     pw_log::debug!("transfer_and_clear: {} packet(s)", pkts.len() as u32);
     for pkt in pkts.iter() {
-        if let Err(e) = dest.inbound(pkt) {
-            pw_log::error!("transfer_and_clear: inbound failed: {}", e.code as u32);
+        match dest.inbound(pkt) {
+            Ok(Some(cookie)) => {
+                pw_log::debug!("transfer_and_clear: pkt delivered to cookie {}", cookie.0 as u32);
+            }
+            Ok(None) => {
+                pw_log::debug!("transfer_and_clear: pkt discarded (no handler)");
+            }
+            Err(e) => {
+                pw_log::error!("transfer_and_clear: inbound failed: {}", e.code as u32);
+            }
         }
     }
     drop(pkts);