diff --git a/include/ftl/uuid.hpp b/include/ftl/uuid.hpp
index e5420748e4859cdbbcf8d7f973b401ff0f25994e..06a6adf49786c7aa7bdef9447f0334aa53972b2c 100644
--- a/include/ftl/uuid.hpp
+++ b/include/ftl/uuid.hpp
@@ -6,6 +6,7 @@
 
 #pragma once
 
+#include <cstring>
 #include <ftl/lib/loguru.hpp>
 
 #ifndef WIN32
@@ -19,8 +20,6 @@
 #include <string>
 #include <functional>
 
-#include <msgpack.hpp>
-
 namespace ftl {
 /**
  * C++ Wrapper for libuuid. The default constructor generates a new UUID.
@@ -128,10 +127,7 @@ class UUID {
 */
     }
 
-    /* Allow the UUID to be packed into an RPC message. */
-    MSGPACK_DEFINE(uuid_);
-
- private:
+ protected:
 #ifdef WIN32
     union {
         _GUID guid_;
diff --git a/src/peer.cpp b/src/peer.cpp
index 040f7090d1582a3063e1a916ac49c81406387847..3aac02dcb7633f0bcf8440d0de8230ca9abeb608 100644
--- a/src/peer.cpp
+++ b/src/peer.cpp
@@ -21,6 +21,7 @@
 #include <ftl/uri.hpp>
 #include <ftl/time.hpp>
 #include "peer.hpp"
+#include "uuidMSGPACK.hpp"
 
 #include "protocol/connection.hpp"
 
@@ -77,7 +78,7 @@ void Peer::_send_handshake() {
             << " peer) handshake sent, status: "
             << (isConnected() ? "connected" : "connecting");
 
-    send("__handshake__", ftl::net::kMagic, ftl::net::kVersion, net_->id());
+    send("__handshake__", ftl::net::kMagic, ftl::net::kVersion, ftl::UUIDMSGPACK(net_->id()));
 }
 
 void Peer::_process_handshake(uint64_t magic, uint32_t version, const UUID &pid) {
@@ -113,7 +114,7 @@ void Peer::_process_handshake(uint64_t magic, uint32_t version, const UUID &pid)
 
 void Peer::_bind_rpc() {
     // Install return handshake handler.
-    bind("__handshake__", [this](uint64_t magic, uint32_t version, const UUID &pid) {
+    bind("__handshake__", [this](uint64_t magic, uint32_t version, const ftl::UUIDMSGPACK &pid) {
         _process_handshake(magic, version, pid);
     });
 
diff --git a/src/protocol.hpp b/src/protocol.hpp
index 08065448980f26013e51252134b02f973b83dc9c..c9facb788c3319de669e7c92c493d420232148ef 100644
--- a/src/protocol.hpp
+++ b/src/protocol.hpp
@@ -11,11 +11,12 @@
 #include <ftl/protocol/config.h>
 #include <tuple>
 #include <ftl/uuid.hpp>
+#include "uuidMSGPACK.hpp"
 
 namespace ftl {
 namespace net {
 
-typedef std::tuple<uint64_t, uint32_t, ftl::UUID> Handshake;
+typedef std::tuple<uint64_t, uint32_t, ftl::UUIDMSGPACK> Handshake;
 
 static const uint64_t kMagic = 0x0009340053640912;
 static const uint32_t kVersion = (FTL_VERSION_MAJOR << 16) +
diff --git a/src/self.cpp b/src/self.cpp
index 1c4692a1d31449a7f2084551dc8549ae4936b822..f7a21b8cd1ba541e2b9abc8cbd342f08ebe8b38f 100644
--- a/src/self.cpp
+++ b/src/self.cpp
@@ -9,7 +9,7 @@
 #include "./streams/netstream.hpp"
 #include "./streams/filestream.hpp"
 #include <ftl/lib/nlohmann/json.hpp>
-#include <ftl/uuid.hpp>
+#include "uuidMSGPACK.hpp"
 
 using ftl::protocol::Self;
 using ftl::protocol::FrameID;
@@ -141,7 +141,7 @@ std::vector<std::string> Self::getStreams() {
 }
 
 std::shared_ptr<ftl::protocol::Node> Self::locateStream(const std::string &uri) {
-    auto p = universe_->findOne<ftl::UUID>("find_stream", uri);
+    auto p = universe_->findOne<ftl::UUIDMSGPACK>("find_stream", uri);
 
     if (!p) return nullptr;
     auto peer = universe_->getPeer(*p);
diff --git a/src/streams/netstream.cpp b/src/streams/netstream.cpp
index 10976767644c5b11db4c8ba068f3ccd1e39e38d3..a0442ae993842ca654267853d45e4fab3a3734ff 100644
--- a/src/streams/netstream.cpp
+++ b/src/streams/netstream.cpp
@@ -8,6 +8,7 @@
 #include <string>
 #include "netstream.hpp"
 #include <ftl/time.hpp>
+#include "../uuidMSGPACK.hpp"
 #include "packetMsgpack.hpp"
 
 #define LOGURU_REPLACE_GLOG 1
@@ -48,7 +49,7 @@ static std::list<std::string> net_streams;
 static SHARED_MUTEX stream_mutex;
 
 void Net::installRPC(ftl::net::Universe *net) {
-    net->bind("find_stream", [net](const std::string &uri) -> optional<ftl::UUID> {
+    net->bind("find_stream", [net](const std::string &uri) -> optional<ftl::UUIDMSGPACK> {
         DLOG(INFO) << "Request for stream: " << uri;
 
         ftl::URI u1(uri);
@@ -59,7 +60,8 @@ void Net::installRPC(ftl::net::Universe *net) {
             ftl::URI u2(s);
             // Don't compare query string components.
             if (base == u2.getBaseURI()) {
-                return std::reference_wrapper(net->id());
+                ftl::UUIDMSGPACK mpuuid(net->id());
+                return std::reference_wrapper(mpuuid);
             }
         }
         return {};
@@ -321,7 +323,7 @@ bool Net::_enable(FrameID id) {
 
     // not hosting, try to find peer now
     // First find non-proxy version, then check for proxy version if no match
-    auto p = net_->findOne<ftl::UUID>("find_stream", uri_);
+    auto p = net_->findOne<ftl::UUIDMSGPACK>("find_stream", uri_);
 
     if (p) {
         peer_ = *p;
diff --git a/src/uuidMSGPACK.hpp b/src/uuidMSGPACK.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..3bed536c9a4f575ba490959f3f40aa39ec484924
--- /dev/null
+++ b/src/uuidMSGPACK.hpp
@@ -0,0 +1,21 @@
+/**
+ * @file uuidMSGPACK.hpp
+ * @copyright Copyright (c) 2022 University of Turku, MIT License
+ * @author Nicolas Pope
+ */
+
+#pragma once
+
+#include <ftl/uuid.hpp>
+#include <msgpack.hpp>
+
+namespace ftl {
+
+class UUIDMSGPACK : public ftl::UUID {
+ public:
+    UUIDMSGPACK() : ftl::UUID() {}
+    explicit UUIDMSGPACK(const ftl::UUID &u) : ftl::UUID(u) {}
+    MSGPACK_DEFINE(uuid_);
+};
+
+}
diff --git a/test/mocks/connection.cpp b/test/mocks/connection.cpp
index c47bc7612edb1d77cfdf95188981d6df27dc174e..98de3ef7d0e87e1710cd8b9badebe0746327ff0c 100644
--- a/test/mocks/connection.cpp
+++ b/test/mocks/connection.cpp
@@ -3,6 +3,7 @@
 #include "../../src/socket.hpp"
 #include "../../src/universe.hpp"
 #include "../../src/protocol/connection.hpp"
+#include "../../src/uuidMSGPACK.hpp"
 #include <ftl/protocol/self.hpp>
 #include <chrono>
 
@@ -77,7 +78,7 @@ ftl::net::PeerPtr createMockPeer(int c) {
 
 void send_handshake(ftl::net::Peer &p) {
 	ftl::UUID id;
-	p.send("__handshake__", ftl::net::kMagic, ((8 << 16) + (5 << 8) + 2), id);
+	p.send("__handshake__", ftl::net::kMagic, ((8 << 16) + (5 << 8) + 2), ftl::UUIDMSGPACK(id));
 }
 
 void provideResponses(const ftl::net::PeerPtr &p, int c, const std::vector<std::tuple<bool,std::string,msgpack::object>> &responses) {
diff --git a/test/netstream_unit.cpp b/test/netstream_unit.cpp
index 168b754e4538c3b8486cbcae53ababef97066d6e..71701b084d79fe3661ecfc9da9a7049a3bbff1ae 100644
--- a/test/netstream_unit.cpp
+++ b/test/netstream_unit.cpp
@@ -10,6 +10,7 @@
 
 #include "../src/streams/netstream.hpp"
 #include "../src/streams/packetMsgpack.hpp"
+#include "../src/uuidMSGPACK.hpp"
 #include "mocks/connection.hpp"
 
 using ftl::protocol::FrameID;
@@ -100,7 +101,7 @@ TEST_CASE("Net stream sending requests") {
 		std::thread thr([&p]() {
             auto z = std::make_unique<msgpack::zone>();
             provideResponses(p, 0, {
-                {false, "find_stream", packResponse(*z, p->id())},
+                {false, "find_stream", packResponse(*z, ftl::UUIDMSGPACK(p->id()))},
                 {true, "enable_stream", {}},
             });
 		});