Create SpdmTransport interface to the MCTP library

This implements spdm-lib's SpdmTransport trait object for the OpenPRoT MCTP Client.

The current architecture ties a Requester to a Responder.
diff --git a/Cargo.lock b/Cargo.lock
index e3cfac7..d6fd3b4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -500,10 +500,7 @@
 name = "openprot-mctp-client"
 version = "0.1.0"
 dependencies = [
- "mctp",
- "mctp-lib",
  "openprot-mctp-api",
- "openprot-mctp-server",
 ]
 
 [[package]]
@@ -574,6 +571,7 @@
 version = "0.1.0"
 dependencies = [
  "heapless 0.9.1",
+ "openprot-spdm-transport-mctp",
  "spdm-lib",
 ]
 
@@ -582,6 +580,15 @@
 version = "0.1.0"
 dependencies = [
  "heapless 0.9.1",
+ "openprot-spdm-transport-mctp",
+ "spdm-lib",
+]
+
+[[package]]
+name = "openprot-spdm-transport-mctp"
+version = "0.1.0"
+dependencies = [
+ "openprot-mctp-api",
  "spdm-lib",
 ]
 
diff --git a/Cargo.toml b/Cargo.toml
index 16f3fbd..5e05e37 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -20,6 +20,7 @@
     "services/mctp/client",
     "services/spdm/requester",
     "services/spdm/responder",
+    "services/spdm/transport-mctp",
     "services/telemetry",
     "services/storage",
 ]
diff --git a/services/spdm/requester/BUILD.bazel b/services/spdm/requester/BUILD.bazel
index 21f9159..0362cd5 100644
--- a/services/spdm/requester/BUILD.bazel
+++ b/services/spdm/requester/BUILD.bazel
@@ -9,6 +9,7 @@
     edition = "2024",
     visibility = ["//visibility:public"],
     deps = [
+        "//services/spdm/transport-mctp:spdm_transport_mctp",
         "@rust_crates//:heapless",
         "@rust_crates//:spdm-lib",
     ],
diff --git a/services/spdm/requester/Cargo.toml b/services/spdm/requester/Cargo.toml
index 753b13d..e87282e 100644
--- a/services/spdm/requester/Cargo.toml
+++ b/services/spdm/requester/Cargo.toml
@@ -8,5 +8,6 @@
 license = "Apache-2.0"
 
 [dependencies]
+openprot-spdm-transport-mctp = { path = "../transport-mctp" }
 spdm-lib = { git = "https://github.com/9elements/spdm-lib.git", branch = "buildup" }
 heapless = { workspace = true }
diff --git a/services/spdm/responder/BUILD.bazel b/services/spdm/responder/BUILD.bazel
index 9dd4e83..46cc63f 100644
--- a/services/spdm/responder/BUILD.bazel
+++ b/services/spdm/responder/BUILD.bazel
@@ -9,6 +9,7 @@
     edition = "2024",
     visibility = ["//visibility:public"],
     deps = [
+        "//services/spdm/transport-mctp:spdm_transport_mctp",
         "@rust_crates//:heapless",
         "@rust_crates//:spdm-lib",
     ],
diff --git a/services/spdm/responder/Cargo.toml b/services/spdm/responder/Cargo.toml
index a06a73b..7a20ccd 100644
--- a/services/spdm/responder/Cargo.toml
+++ b/services/spdm/responder/Cargo.toml
@@ -8,5 +8,6 @@
 license = "Apache-2.0"
 
 [dependencies]
+openprot-spdm-transport-mctp = { path = "../transport-mctp" }
 spdm-lib = { git = "https://github.com/9elements/spdm-lib.git", branch = "buildup" }
 heapless = { workspace = true }
diff --git a/services/spdm/transport-mctp/BUILD.bazel b/services/spdm/transport-mctp/BUILD.bazel
new file mode 100644
index 0000000..d44ad13
--- /dev/null
+++ b/services/spdm/transport-mctp/BUILD.bazel
@@ -0,0 +1,20 @@
+# Licensed under the Apache-2.0 license
+
+load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test")
+
+rust_library(
+    name = "spdm_transport_mctp",
+    srcs = glob(["src/**/*.rs"]),
+    crate_name = "openprot_spdm_transport_mctp",
+    edition = "2024",
+    visibility = ["//visibility:public"],
+    deps = [
+        "//services/mctp/api:mctp_api",
+        "@rust_crates//:spdm-lib",
+    ],
+)
+
+rust_test(
+    name = "spdm_transport_mctp_test",
+    crate = ":spdm_transport_mctp",
+)
diff --git a/services/spdm/transport-mctp/Cargo.toml b/services/spdm/transport-mctp/Cargo.toml
new file mode 100644
index 0000000..36a77c0
--- /dev/null
+++ b/services/spdm/transport-mctp/Cargo.toml
@@ -0,0 +1,12 @@
+# Licensed under the Apache-2.0 license
+
+[package]
+name = "openprot-spdm-transport-mctp"
+version = "0.1.0"
+edition = "2021"
+description = "MCTP transport implementation for SPDM"
+license = "Apache-2.0"
+
+[dependencies]
+openprot-mctp-api = { path = "../../mctp/api" }
+spdm-lib = { git = "https://github.com/9elements/spdm-lib.git", branch = "buildup" }
diff --git a/services/spdm/transport-mctp/README.md b/services/spdm/transport-mctp/README.md
new file mode 100644
index 0000000..7b19d9e
--- /dev/null
+++ b/services/spdm/transport-mctp/README.md
@@ -0,0 +1,51 @@
+# openprot-spdm-transport-mctp
+
+MCTP transport layer for SPDM protocol communication.
+
+## Overview
+
+This crate implements the `SpdmTransport` trait from `spdm-lib` using MCTP as the underlying transport mechanism. It bridges the SPDM protocol layer with the MCTP messaging infrastructure.
+
+## MCTP Binding
+
+- **Message Type**: 0x05 (SPDM, per DMTF DSP0236 §4.2.1)
+- **Max Message Size**: 2048 bytes
+- **Fragmentation**: Handled by MCTP layer
+- **Tag Correlation**: MCTP tags used for request/response matching
+
+## Modes
+
+### Requester Mode
+Used by SPDM requesters (clients) that initiate attestation operations:
+```rust
+let transport = MctpSpdmTransport::new_requester(mctp_client, remote_eid);
+```
+
+### Responder Mode
+Used by SPDM responders (servers) that handle attestation requests:
+```rust
+let transport = MctpSpdmTransport::new_responder(mctp_client);
+```
+
+## Transport Lifecycle
+
+1. **Initialize**: `init_sequence()` establishes MCTP handles
+   - Requester: Creates request handle to remote EID
+   - Responder: Registers listener for SPDM messages
+
+2. **Communication**:
+   - Requester: `send_request()` → `receive_response()`
+   - Responder: `receive_request()` → `send_response()`
+
+3. **Cleanup**: Automatically releases MCTP handles on drop
+
+## Dependencies
+
+- `openprot-mctp-api` — MCTP client trait and types
+- `spdm-lib` — SPDM protocol library with transport trait
+
+## Usage
+
+This crate is used by both:
+- `openprot-spdm-requester` — SPDM client implementation
+- `openprot-spdm-responder` — SPDM server implementation
diff --git a/services/spdm/transport-mctp/src/lib.rs b/services/spdm/transport-mctp/src/lib.rs
new file mode 100644
index 0000000..d1a3d26
--- /dev/null
+++ b/services/spdm/transport-mctp/src/lib.rs
@@ -0,0 +1,241 @@
+// Licensed under the Apache-2.0 license
+
+//! MCTP-based SPDM Transport
+//!
+//! This module provides an implementation of the `SpdmTransport` trait from
+//! spdm-lib that uses MCTP as the underlying transport layer.
+//!
+//! ## MCTP Binding
+//!
+//! SPDM messages are carried over MCTP using message type 0x05 (SPDM).
+//! The transport handles:
+//! - MCTP session management (handles for req/listener)
+//! - Message fragmentation (via MCTP layer)
+//! - Request/response correlation (via MCTP tags)
+
+#![no_std]
+#![warn(missing_docs)]
+
+use openprot_mctp_api::{Handle, MctpClient, RecvMetadata};
+use spdm_lib::codec::MessageBuf;
+use spdm_lib::platform::transport::{SpdmTransport, TransportError, TransportResult};
+
+/// MCTP message type for SPDM (DMTF DSP0236 §4.2.1)
+const MCTP_MSG_TYPE_SPDM: u8 = 0x05;
+
+/// Maximum SPDM message size over MCTP
+const MAX_SPDM_MESSAGE_SIZE: usize = 2048;
+
+/// MCTP transport layer header size (none for SPDM over MCTP)
+const MCTP_HEADER_SIZE: usize = 0;
+
+/// SPDM transport implementation using MCTP as the underlying transport.
+///
+/// This transport can operate in two modes:
+/// - **Requester mode**: Sends requests to a remote EID and receives responses
+/// - **Responder mode**: Listens for incoming requests and sends responses
+pub struct MctpSpdmTransport<C: MctpClient> {
+    /// MCTP client for transport operations
+    client: C,
+
+    /// MCTP handle for requester mode (outbound requests)
+    req_handle: Option<Handle>,
+
+    /// MCTP handle for responder mode (incoming requests)
+    listener_handle: Option<Handle>,
+
+    /// Remote endpoint ID (for requester mode)
+    remote_eid: Option<u8>,
+
+    /// Last received message metadata (for response correlation)
+    last_request_meta: Option<RecvMetadata>,
+}
+
+impl<C: MctpClient> MctpSpdmTransport<C> {
+    /// Create a new MCTP SPDM transport in requester mode.
+    ///
+    /// This will establish an MCTP request handle to the given remote EID.
+    pub fn new_requester(client: C, remote_eid: u8) -> Self {
+        Self {
+            client,
+            req_handle: None,
+            listener_handle: None,
+            remote_eid: Some(remote_eid),
+            last_request_meta: None,
+        }
+    }
+
+    /// Create a new MCTP SPDM transport in responder mode.
+    ///
+    /// This will register an MCTP listener for SPDM message type.
+    pub fn new_responder(client: C) -> Self {
+        Self {
+            client,
+            req_handle: None,
+            listener_handle: None,
+            remote_eid: None,
+            last_request_meta: None,
+        }
+    }
+}
+
+impl<C: MctpClient> SpdmTransport for MctpSpdmTransport<C> {
+    /// Initialize the MCTP transport session.
+    ///
+    /// For **requester mode**:
+    /// - Establishes an MCTP request handle targeting the remote EID
+    ///
+    /// For **responder mode**:
+    /// - Registers an MCTP listener for SPDM message type (0x05)
+    ///
+    /// # Errors
+    ///
+    /// Returns `TransportError::DriverError` if MCTP handle allocation fails.
+    fn init_sequence(&mut self) -> TransportResult<()> {
+        if let Some(remote_eid) = self.remote_eid {
+            // Requester mode: get request handle for remote EID
+            self.req_handle = Some(
+                self.client
+                    .req(remote_eid)
+                    .map_err(|_| TransportError::DriverError)?,
+            );
+        } else {
+            // Responder mode: register listener for SPDM messages
+            self.listener_handle = Some(
+                self.client
+                    .listener(MCTP_MSG_TYPE_SPDM)
+                    .map_err(|_| TransportError::DriverError)?,
+            );
+        }
+
+        Ok(())
+    }
+
+    fn send_request<'a>(&mut self, dest_eid: u8, req: &mut MessageBuf<'a>) -> TransportResult<()> {
+        // Get the request handle (should be set by init_sequence)
+        let handle = self.req_handle.ok_or(TransportError::NoRequestInFlight)?;
+
+        // Get the message data from MessageBuf
+        let msg_len = req.data_len();
+        let msg_data = req.data(msg_len).map_err(|_| TransportError::SendError)?;
+
+        // Send via MCTP
+        self.client
+            .send(
+                Some(handle),
+                MCTP_MSG_TYPE_SPDM,
+                Some(dest_eid),
+                None, // Let MCTP allocate tag
+                false, // No integrity check for SPDM
+                msg_data,
+            )
+            .map_err(|_| TransportError::SendError)?;
+
+        Ok(())
+    }
+
+    fn receive_response<'a>(&mut self, rsp: &mut MessageBuf<'a>) -> TransportResult<()> {
+        // Get the request handle
+        let handle = self.req_handle.ok_or(TransportError::ResponseNotExpected)?;
+
+        // Allocate receive buffer
+        let mut recv_buf = [0u8; MAX_SPDM_MESSAGE_SIZE];
+
+        // Receive via MCTP (blocking with no timeout)
+        let meta = self.client
+            .recv(handle, 0, &mut recv_buf)
+            .map_err(|_| TransportError::ReceiveError)?;
+
+        // Verify message type
+        if meta.msg_type != MCTP_MSG_TYPE_SPDM {
+            return Err(TransportError::UnexpectedMessageType);
+        }
+
+        // Copy payload into MessageBuf
+        let payload = &recv_buf[..meta.payload_size];
+        rsp.reserve(MCTP_HEADER_SIZE).map_err(|_| TransportError::BufferTooSmall)?;
+        rsp.put_data(meta.payload_size).map_err(|_| TransportError::BufferTooSmall)?;
+
+        let rsp_buf = rsp.data_mut(meta.payload_size).map_err(|_| TransportError::BufferTooSmall)?;
+        rsp_buf.copy_from_slice(payload);
+
+        Ok(())
+    }
+
+    fn receive_request<'a>(&mut self, req: &mut MessageBuf<'a>) -> TransportResult<()> {
+        // Get the listener handle
+        let handle = self.listener_handle.ok_or(TransportError::DriverError)?;
+
+        // Allocate receive buffer
+        let mut recv_buf = [0u8; MAX_SPDM_MESSAGE_SIZE];
+
+        // Receive via MCTP (blocking with no timeout)
+        let meta = self.client
+            .recv(handle, 0, &mut recv_buf)
+            .map_err(|_| TransportError::ReceiveError)?;
+
+        // Verify message type
+        if meta.msg_type != MCTP_MSG_TYPE_SPDM {
+            return Err(TransportError::UnexpectedMessageType);
+        }
+
+        // Store metadata for response correlation
+        self.last_request_meta = Some(meta);
+
+        // Copy payload into MessageBuf
+        let payload = &recv_buf[..meta.payload_size];
+        req.reserve(MCTP_HEADER_SIZE).map_err(|_| TransportError::BufferTooSmall)?;
+        req.put_data(meta.payload_size).map_err(|_| TransportError::BufferTooSmall)?;
+
+        let req_buf = req.data_mut(meta.payload_size).map_err(|_| TransportError::BufferTooSmall)?;
+        req_buf.copy_from_slice(payload);
+
+        Ok(())
+    }
+
+    fn send_response<'a>(&mut self, resp: &mut MessageBuf<'a>) -> TransportResult<()> {
+        // Get metadata from last received request
+        let meta = self.last_request_meta.ok_or(TransportError::NoRequestInFlight)?;
+
+        // Get the response data from MessageBuf
+        let msg_len = resp.data_len();
+        let msg_data = resp.data(msg_len).map_err(|_| TransportError::SendError)?;
+
+        // Send response back to requester
+        self.client
+            .send(
+                None, // No handle for responses
+                MCTP_MSG_TYPE_SPDM,
+                Some(meta.remote_eid), // Back to requester
+                Some(meta.msg_tag),    // Use same tag for correlation
+                meta.msg_ic,           // Match integrity check
+                msg_data,
+            )
+            .map_err(|_| TransportError::SendError)?;
+
+        // Clear request metadata
+        self.last_request_meta = None;
+
+        Ok(())
+    }
+
+    fn max_message_size(&self) -> TransportResult<usize> {
+        Ok(MAX_SPDM_MESSAGE_SIZE)
+    }
+
+    fn header_size(&self) -> usize {
+        MCTP_HEADER_SIZE
+    }
+}
+
+impl<C: MctpClient> Drop for MctpSpdmTransport<C> {
+    fn drop(&mut self) {
+        // Clean up MCTP handles
+        if let Some(handle) = self.req_handle {
+            self.client.drop_handle(handle);
+        }
+        if let Some(handle) = self.listener_handle {
+            self.client.drop_handle(handle);
+        }
+    }
+}