diff --git a/pw_rpc/public/pw_rpc/method_info.h b/pw_rpc/public/pw_rpc/method_info.h
index 4caddf2051..714c7d3ccf 100644
--- a/pw_rpc/public/pw_rpc/method_info.h
+++ b/pw_rpc/public/pw_rpc/method_info.h
@@ -48,4 +48,9 @@ using MethodRequestType = typename internal::MethodInfo<kMethod>::Request;
 template <auto kMethod>
 using MethodResponseType = typename internal::MethodInfo<kMethod>::Response;
 
+// Function which returns a serializer for given kMethod.
+// For e.g. `pwpb` methods, this returns a `const PwpbMethodSerde&`.
+template <auto kMethod>
+using MethodSerde = typename internal::MethodInfo<kMethod>::serde;
+
 }  // namespace pw::rpc
diff --git a/pw_rpc/pwpb/BUILD.bazel b/pw_rpc/pwpb/BUILD.bazel
index ae13ccb203..786b03cd0f 100644
--- a/pw_rpc/pwpb/BUILD.bazel
+++ b/pw_rpc/pwpb/BUILD.bazel
@@ -58,6 +58,7 @@ pw_cc_library(
     name = "common",
     hdrs = [
         "public/pw_rpc/pwpb/internal/common.h",
+        "public/pw_rpc/pwpb/serde.h",
         "public/pw_rpc/pwpb/server_reader_writer.h",
     ],
     includes = ["public"],
diff --git a/pw_rpc/pwpb/BUILD.gn b/pw_rpc/pwpb/BUILD.gn
index 8a4342b698..0f862a55d6 100644
--- a/pw_rpc/pwpb/BUILD.gn
+++ b/pw_rpc/pwpb/BUILD.gn
@@ -71,7 +71,10 @@ pw_source_set("common") {
     dir_pw_log,
     dir_pw_stream,
   ]
-  public = [ "public/pw_rpc/pwpb/internal/common.h" ]
+  public = [
+    "public/pw_rpc/pwpb/internal/common.h",
+    "public/pw_rpc/pwpb/serde.h",
+  ]
 }
 
 pw_source_set("test_method_context") {
diff --git a/pw_rpc/pwpb/public/pw_rpc/pwpb/client_reader_writer.h b/pw_rpc/pwpb/public/pw_rpc/pwpb/client_reader_writer.h
index ec590446fd..2071e5975d 100644
--- a/pw_rpc/pwpb/public/pw_rpc/pwpb/client_reader_writer.h
+++ b/pw_rpc/pwpb/public/pw_rpc/pwpb/client_reader_writer.h
@@ -328,7 +328,7 @@ class PwpbClientReaderWriter
                          uint32_t channel_id_v,
                          uint32_t service_id,
                          uint32_t method_id,
-                         const internal::PwpbMethodSerde& serde)
+                         const PwpbMethodSerde& serde)
       PW_EXCLUSIVE_LOCKS_REQUIRED(internal::rpc_lock())
       : internal::PwpbStreamResponseClientCall<Response>(
             client,
@@ -372,7 +372,7 @@ class PwpbClientReader
                    uint32_t channel_id_v,
                    uint32_t service_id,
                    uint32_t method_id,
-                   const internal::PwpbMethodSerde& serde)
+                   const PwpbMethodSerde& serde)
       PW_EXCLUSIVE_LOCKS_REQUIRED(internal::rpc_lock())
       : internal::PwpbStreamResponseClientCall<Response>(
             client,
@@ -429,7 +429,7 @@ class PwpbClientWriter
                    uint32_t channel_id_v,
                    uint32_t service_id,
                    uint32_t method_id,
-                   const internal::PwpbMethodSerde& serde)
+                   const PwpbMethodSerde& serde)
       PW_EXCLUSIVE_LOCKS_REQUIRED(internal::rpc_lock())
 
       : internal::PwpbUnaryResponseClientCall<Response>(
@@ -473,7 +473,7 @@ class PwpbUnaryReceiver
                     uint32_t channel_id_v,
                     uint32_t service_id,
                     uint32_t method_id,
-                    const internal::PwpbMethodSerde& serde)
+                    const PwpbMethodSerde& serde)
       PW_EXCLUSIVE_LOCKS_REQUIRED(internal::rpc_lock())
       : internal::PwpbUnaryResponseClientCall<Response>(client,
                                                         channel_id_v,
diff --git a/pw_rpc/pwpb/public/pw_rpc/pwpb/fake_channel_output.h b/pw_rpc/pwpb/public/pw_rpc/pwpb/fake_channel_output.h
index 27e0ca4a66..d26994198c 100644
--- a/pw_rpc/pwpb/public/pw_rpc/pwpb/fake_channel_output.h
+++ b/pw_rpc/pwpb/public/pw_rpc/pwpb/fake_channel_output.h
@@ -64,13 +64,12 @@ class PwpbPayloadsView {
    private:
     friend class PwpbPayloadsView;
 
-    constexpr iterator(const PayloadsView::iterator& it,
-                       const internal::PwpbSerde& serde)
+    constexpr iterator(const PayloadsView::iterator& it, const PwpbSerde& serde)
         : containers::
               WrappedIterator<iterator, PayloadsView::iterator, Payload>(it),
           serde_(serde) {}
 
-    internal::PwpbSerde serde_;
+    PwpbSerde serde_;
   };
 
   Payload operator[](size_t index) const {
@@ -94,11 +93,11 @@ class PwpbPayloadsView {
   friend class PwpbFakeChannelOutput;
 
   template <typename... Args>
-  PwpbPayloadsView(const internal::PwpbSerde& serde, Args&&... args)
+  PwpbPayloadsView(const PwpbSerde& serde, Args&&... args)
       : view_(args...), serde_(serde) {}
 
   PayloadsView view_;
-  internal::PwpbSerde serde_;
+  PwpbSerde serde_;
 };
 
 // A ChannelOutput implementation that stores the outgoing payloads and status.
@@ -191,7 +190,7 @@ class PwpbFakeChannelOutput final
   // synchronized! The PwpbPayloadsView is immediately invalidated if any
   // thread accesses the FakeChannelOutput.
   template <typename T>
-  PwpbPayloadsView<T> payload_structs(const internal::PwpbSerde& serde,
+  PwpbPayloadsView<T> payload_structs(const PwpbSerde& serde,
                                       MethodType type,
                                       uint32_t channel_id,
                                       uint32_t service_id,
diff --git a/pw_rpc/pwpb/public/pw_rpc/pwpb/internal/common.h b/pw_rpc/pwpb/public/pw_rpc/pwpb/internal/common.h
index 16f284743b..18a0052a3f 100644
--- a/pw_rpc/pwpb/public/pw_rpc/pwpb/internal/common.h
+++ b/pw_rpc/pwpb/public/pw_rpc/pwpb/internal/common.h
@@ -20,105 +20,13 @@
 #include "pw_protobuf/stream_decoder.h"
 #include "pw_rpc/internal/client_call.h"
 #include "pw_rpc/internal/server_call.h"
+#include "pw_rpc/pwpb/serde.h"
 #include "pw_span/span.h"
 #include "pw_status/status.h"
 #include "pw_status/status_with_size.h"
 
 namespace pw::rpc::internal {
 
-using PwpbMessageDescriptor =
-    const span<const protobuf::internal::MessageField>*;
-
-// Serializer/deserializer for a pw_protobuf message.
-class PwpbSerde {
- public:
-  explicit constexpr PwpbSerde(PwpbMessageDescriptor table) : table_(table) {}
-
-  PwpbSerde(const PwpbSerde&) = default;
-  PwpbSerde& operator=(const PwpbSerde&) = default;
-
-  // Encodes a pw_protobuf struct to the serialized wire format.
-  template <typename Message>
-  StatusWithSize Encode(const Message& message, ByteSpan buffer) const {
-    return Encoder(buffer).Write(as_bytes(span(&message, 1)), table_);
-  }
-
-  // Decodes a serialized protobuf into a pw_protobuf message struct.
-  template <typename Message>
-  Status Decode(ConstByteSpan buffer, Message& message) const {
-    return Decoder(buffer).Read(as_writable_bytes(span(&message, 1)), table_);
-  }
-
- private:
-  class Encoder : public protobuf::MemoryEncoder {
-   public:
-    constexpr Encoder(ByteSpan buffer) : protobuf::MemoryEncoder(buffer) {}
-
-    StatusWithSize Write(ConstByteSpan message, PwpbMessageDescriptor table) {
-      const auto status = protobuf::MemoryEncoder::Write(message, *table);
-      return StatusWithSize(status, size());
-    }
-  };
-
-  class Decoder : public protobuf::StreamDecoder {
-   public:
-    constexpr Decoder(ConstByteSpan buffer)
-        : protobuf::StreamDecoder(reader_), reader_(buffer) {}
-
-    Status Read(ByteSpan message, PwpbMessageDescriptor table) {
-      return protobuf::StreamDecoder::Read(message, *table);
-    }
-
-   private:
-    stream::MemoryReader reader_;
-  };
-
-  PwpbMessageDescriptor table_;
-};
-
-// Serializer/deserializer for pw_protobuf request and response message structs
-// within an RPC method.
-class PwpbMethodSerde {
- public:
-  constexpr PwpbMethodSerde(PwpbMessageDescriptor request_table,
-                            PwpbMessageDescriptor response_table)
-      : request_serde_(request_table), response_serde_(response_table) {}
-
-  PwpbMethodSerde(const PwpbMethodSerde&) = delete;
-  PwpbMethodSerde& operator=(const PwpbMethodSerde&) = delete;
-
-  // Encodes the pw_protobuf request struct to the serialized wire format.
-  template <typename Request>
-  StatusWithSize EncodeRequest(const Request& request, ByteSpan buffer) const {
-    return request_serde_.Encode(request, buffer);
-  }
-
-  // Encodes the pw_protobuf response struct to the serialized wire format.
-  template <typename Response>
-  StatusWithSize EncodeResponse(const Response& response,
-                                ByteSpan buffer) const {
-    return response_serde_.Encode(response, buffer);
-  }
-  // Decodes a serialized protobuf into the pw_protobuf request struct.
-  template <typename Request>
-  Status DecodeRequest(ConstByteSpan buffer, Request& request) const {
-    return request_serde_.Decode(buffer, request);
-  }
-
-  // Decodes a serialized protobuf into the pw_protobuf response struct.
-  template <typename Response>
-  Status DecodeResponse(ConstByteSpan buffer, Response& response) const {
-    return response_serde_.Decode(buffer, response);
-  }
-
-  const PwpbSerde& request() const { return request_serde_; }
-  const PwpbSerde& response() const { return response_serde_; }
-
- private:
-  PwpbSerde request_serde_;
-  PwpbSerde response_serde_;
-};
-
 // Defines per-message struct type instance of the serializer/deserializer.
 template <PwpbMessageDescriptor kRequest, PwpbMessageDescriptor kResponse>
 constexpr PwpbMethodSerde kPwpbMethodSerde(kRequest, kResponse);
diff --git a/pw_rpc/pwpb/public/pw_rpc/pwpb/serde.h b/pw_rpc/pwpb/public/pw_rpc/pwpb/serde.h
new file mode 100644
index 0000000000..74ed63d8b8
--- /dev/null
+++ b/pw_rpc/pwpb/public/pw_rpc/pwpb/serde.h
@@ -0,0 +1,116 @@
+// Copyright 2022 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+#pragma once
+
+#include "pw_protobuf/encoder.h"
+#include "pw_protobuf/internal/codegen.h"
+#include "pw_protobuf/stream_decoder.h"
+#include "pw_span/span.h"
+
+namespace pw::rpc {
+
+using PwpbMessageDescriptor =
+    const span<const protobuf::internal::MessageField>*;
+
+// Serializer/deserializer for a pw_protobuf message.
+class PwpbSerde {
+ public:
+  explicit constexpr PwpbSerde(PwpbMessageDescriptor table) : table_(table) {}
+
+  PwpbSerde(const PwpbSerde&) = default;
+  PwpbSerde& operator=(const PwpbSerde&) = default;
+
+  // Encodes a pw_protobuf struct to the serialized wire format.
+  template <typename Message>
+  StatusWithSize Encode(const Message& message, ByteSpan buffer) const {
+    return Encoder(buffer).Write(as_bytes(span(&message, 1)), table_);
+  }
+
+  // Decodes a serialized protobuf into a pw_protobuf message struct.
+  template <typename Message>
+  Status Decode(ConstByteSpan buffer, Message& message) const {
+    return Decoder(buffer).Read(as_writable_bytes(span(&message, 1)), table_);
+  }
+
+ private:
+  class Encoder : public protobuf::MemoryEncoder {
+   public:
+    constexpr Encoder(ByteSpan buffer) : protobuf::MemoryEncoder(buffer) {}
+
+    StatusWithSize Write(ConstByteSpan message, PwpbMessageDescriptor table) {
+      const auto status = protobuf::MemoryEncoder::Write(message, *table);
+      return StatusWithSize(status, size());
+    }
+  };
+
+  class Decoder : public protobuf::StreamDecoder {
+   public:
+    constexpr Decoder(ConstByteSpan buffer)
+        : protobuf::StreamDecoder(reader_), reader_(buffer) {}
+
+    Status Read(ByteSpan message, PwpbMessageDescriptor table) {
+      return protobuf::StreamDecoder::Read(message, *table);
+    }
+
+   private:
+    stream::MemoryReader reader_;
+  };
+
+  PwpbMessageDescriptor table_;
+};
+
+// Serializer/deserializer for pw_protobuf request and response message structs
+// within an RPC method.
+class PwpbMethodSerde {
+ public:
+  constexpr PwpbMethodSerde(PwpbMessageDescriptor request_table,
+                            PwpbMessageDescriptor response_table)
+      : request_serde_(request_table), response_serde_(response_table) {}
+
+  PwpbMethodSerde(const PwpbMethodSerde&) = delete;
+  PwpbMethodSerde& operator=(const PwpbMethodSerde&) = delete;
+
+  // Encodes the pw_protobuf request struct to the serialized wire format.
+  template <typename Request>
+  StatusWithSize EncodeRequest(const Request& request, ByteSpan buffer) const {
+    return request_serde_.Encode(request, buffer);
+  }
+
+  // Encodes the pw_protobuf response struct to the serialized wire format.
+  template <typename Response>
+  StatusWithSize EncodeResponse(const Response& response,
+                                ByteSpan buffer) const {
+    return response_serde_.Encode(response, buffer);
+  }
+  // Decodes a serialized protobuf into the pw_protobuf request struct.
+  template <typename Request>
+  Status DecodeRequest(ConstByteSpan buffer, Request& request) const {
+    return request_serde_.Decode(buffer, request);
+  }
+
+  // Decodes a serialized protobuf into the pw_protobuf response struct.
+  template <typename Response>
+  Status DecodeResponse(ConstByteSpan buffer, Response& response) const {
+    return response_serde_.Decode(buffer, response);
+  }
+
+  const PwpbSerde& request() const { return request_serde_; }
+  const PwpbSerde& response() const { return response_serde_; }
+
+ private:
+  PwpbSerde request_serde_;
+  PwpbSerde response_serde_;
+};
+
+}  // namespace pw::rpc
diff --git a/pw_rpc/py/pw_rpc/codegen_pwpb.py b/pw_rpc/py/pw_rpc/codegen_pwpb.py
index df17090b06..0dc753bcf2 100644
--- a/pw_rpc/py/pw_rpc/codegen_pwpb.py
+++ b/pw_rpc/py/pw_rpc/codegen_pwpb.py
@@ -186,7 +186,7 @@ def method_info_specialization(self, method: ProtoServiceMethod) -> None:
         self.line(f'using Request = {method.request_type().pwpb_struct()};')
         self.line(f'using Response = {method.response_type().pwpb_struct()};')
         self.line()
-        self.line(f'static constexpr const {RPC_NAMESPACE}::internal::'
+        self.line(f'static constexpr const {RPC_NAMESPACE}::'
                   'PwpbMethodSerde& serde() {')
         with self.indent():
             self.line(f'return {_serde(method)};')