diff --git a/reco/mq/CbmDevUnpack.cxx b/reco/mq/CbmDevUnpack.cxx
index a3bb6edfe284467546983985bfd98fc65d5eaafc..7f015c7f09384b98c1e56bd9d257efa335df6c2d 100644
--- a/reco/mq/CbmDevUnpack.cxx
+++ b/reco/mq/CbmDevUnpack.cxx
@@ -39,6 +39,8 @@ struct InitTaskError : std::runtime_error {
 };
 
 using namespace std;
+using cbm::algo::UnpackMuchElinkPar;
+using cbm::algo::UnpackMuchPar;
 using cbm::algo::UnpackStsElinkPar;
 using cbm::algo::UnpackStsPar;
 
@@ -59,16 +61,16 @@ catch (InitTaskError& e) {
 
 Bool_t CbmDevUnpack::InitAlgos()
 {
-  // --- Common parameters for all components
-  uint32_t numChansPerAsic   = 128;  // R/O channels per ASIC
-  uint32_t numAsicsPerModule = 16;   // Number of ASICs per module
+  // --- Common parameters for all components for STS
+  uint32_t numChansPerAsicSts   = 128;  // R/O channels per ASIC for STS
+  uint32_t numAsicsPerModuleSts = 16;   // Number of ASICs per module for STS
 
-  // Create one algorithm per component and configure it with parameters
-  auto equipIds = fStsConfig.GetEquipmentIds();
-  for (auto& equip : equipIds) {
+  // Create one algorithm per component for STS and configure it with parameters
+  auto equipIdsSts = fStsConfig.GetEquipmentIds();
+  for (auto& equip : equipIdsSts) {
     std::unique_ptr<UnpackStsPar> par(new UnpackStsPar());
-    par->fNumChansPerAsic   = numChansPerAsic;
-    par->fNumAsicsPerModule = numAsicsPerModule;
+    par->fNumChansPerAsic   = numChansPerAsicSts;
+    par->fNumAsicsPerModule = numAsicsPerModuleSts;
     const size_t numElinks  = fStsConfig.GetNumElinks(equip);
     for (size_t elink = 0; elink < numElinks; elink++) {
       UnpackStsElinkPar elinkPar;
@@ -90,6 +92,25 @@ Bool_t CbmDevUnpack::InitAlgos()
   LOG(info) << "==================================================";
   std::cout << std::endl;
 
+  // Create one algorithm per component for MUCH and configure it with parameters
+  auto equipIdsMuch = fMuchConfig.GetEquipmentIds();
+  for (auto& equip : equipIdsMuch) {
+    std::unique_ptr<UnpackMuchPar> par(new UnpackMuchPar());
+    const size_t numElinks = fMuchConfig.GetNumElinks(equip);
+    for (size_t elink = 0; elink < numElinks; elink++) {
+      UnpackMuchElinkPar elinkPar;
+      elinkPar.fAddress    = fMuchConfig.Map(equip, elink);  // Vector of MUCH addresses for this elink
+      elinkPar.fTimeOffset = 0.;
+      par->fElinkParams.push_back(elinkPar);
+    }
+    fAlgoMuch[equip].SetParams(std::move(par));
+    LOG(info) << "--- Configured equipment " << equip << " with " << numElinks << " elinks";
+  }
+
+  LOG(info) << "--- Configured " << fAlgoMuch.size() << " unpacker algorithms for MUCH.";
+  LOG(info) << "==================================================";
+  std::cout << std::endl;
+
   return true;
 }
 
@@ -197,26 +218,34 @@ CbmDigiTimeslice CbmDevUnpack::DoUnpack(const fles::Timeslice& timeslice)
   // Output digi timeslice
   CbmDigiTimeslice digiTs;
 
-  // --- Timer
-  TStopwatch timer;
-  TStopwatch compTimer;
-  timer.Start();
-
   // --- Timeslice properties
   const uint64_t tsIndex = timeslice.index();
   const uint64_t tsTime  = timeslice.start_time();
   const uint64_t numComp = timeslice.num_components();
-  uint64_t numCompUsed   = 0;
+
+  // --- Timer
+  TStopwatch timer;
+  timer.Start();
 
   // --- Counters
-  size_t numMs    = 0;
-  size_t numBytes = 0;
-  size_t numDigis = 0;
+  size_t numMs         = 0;
+  size_t numBytes      = 0;
+  size_t numDigis      = 0;
+  uint64_t numCompUsed = 0;
 
   // ---  Component loop
   for (uint64_t comp = 0; comp < numComp; comp++) {
 
+    // --- Component log
+    size_t numBytesInComp = 0;
+    size_t numDigisInComp = 0;
+    uint64_t numMsInComp  = 0;
+
+    TStopwatch compTimer;
+    compTimer.Start();
+
     auto systemId = static_cast<fles::SubsystemIdentifier>(timeslice.descriptor(comp, 0).sys_id);
+
     if (systemId == fles::SubsystemIdentifier::STS) {
       const uint16_t equipmentId = timeslice.descriptor(comp, 0).eq_id;
       const auto algoIt          = fAlgoSts.find(equipmentId);
@@ -228,13 +257,8 @@ CbmDigiTimeslice CbmDevUnpack::DoUnpack(const fles::Timeslice& timeslice)
       // algorithms depending on the version.
       assert(timeslice.descriptor(comp, 0).sys_ver == 0x20);
 
-      // --- Component log
-      size_t numBytesInComp = 0;
-      size_t numDigisInComp = 0;
-      compTimer.Start();
-
       // --- Microslice loop
-      uint64_t numMsInComp = timeslice.num_microslices(comp);
+      numMsInComp = timeslice.num_microslices(comp);
       for (uint64_t mslice = 0; mslice < numMsInComp; mslice++) {
         const auto msDescriptor = timeslice.descriptor(comp, mslice);
         const auto msContent    = timeslice.content(comp, mslice);
@@ -249,22 +273,54 @@ CbmDigiTimeslice CbmDevUnpack::DoUnpack(const fles::Timeslice& timeslice)
         digiTs.fData.fSts.fDigis.insert(it, result.first.begin(), result.first.end());
         numDigisInComp += result.first.size();
       }
+      numCompUsed++;
+    }  // system STS
 
-      compTimer.Stop();
-      LOG(debug) << "CbmDevUnpack::DoUnpack(): Component " << comp << ", microslices " << numMsInComp << " input size "
-                 << numBytesInComp << " bytes, "
-                 << ", digis " << numDigisInComp << ", CPU time " << compTimer.CpuTime() * 1000. << " ms";
+    if (systemId == fles::SubsystemIdentifier::MUCH) {
+      const uint16_t equipmentId = timeslice.descriptor(comp, 0).eq_id;
+      const auto algoIt          = fAlgoMuch.find(equipmentId);
+      assert(algoIt != fAlgoMuch.end());
+
+      // The current algorithm works for the MUCH data format version 0x20 used in 2021.
+      // Other versions are not yet supported.
+      // In the future, different data formats will be supported by instantiating different
+      // algorithms depending on the version.
+      assert(timeslice.descriptor(comp, 0).sys_ver == 0x20);
+
+      // --- Microslice loop
+      numMsInComp = timeslice.num_microslices(comp);
+      for (uint64_t mslice = 0; mslice < numMsInComp; mslice++) {
+        const auto msDescriptor = timeslice.descriptor(comp, mslice);
+        const auto msContent    = timeslice.content(comp, mslice);
+        numBytesInComp += msDescriptor.size;
+        auto result = (algoIt->second)(msContent, msDescriptor, tsTime);
+        LOG(debug1) << "CbmDevUnpack::DoUnpack(): Component " << comp << ", microslice " << mslice << ", digis "
+                    << result.first.size() << ", errors " << result.second.fNumNonHitOrTsbMessage << " | "
+                    << result.second.fNumErrElinkOutOfRange << " | " << result.second.fNumErrInvalidFirstMessage
+                    << " | " << result.second.fNumErrInvalidMsSize << " | " << result.second.fNumErrTimestampOverflow
+                    << " | ";
+        const auto it = digiTs.fData.fMuch.fDigis.end();
+        digiTs.fData.fMuch.fDigis.insert(it, result.first.begin(), result.first.end());
+        numDigisInComp += result.first.size();
+      }
       numCompUsed++;
-      numBytes += numBytesInComp;
-      numDigis += numDigisInComp;
-      numMs += numMsInComp;
-    }
+    }  // system MUCH
+
 
+    compTimer.Stop();
+    LOG(debug) << "CbmDevUnpack::DoUnpack(): Component " << comp << ", microslices " << numMsInComp << " input size "
+               << numBytesInComp << " bytes, "
+               << ", digis " << numDigisInComp << ", CPU time " << compTimer.CpuTime() * 1000. << " ms";
+    numBytes += numBytesInComp;
+    numDigis += numDigisInComp;
+    numMs += numMsInComp;
   }  //# component
 
   // --- Sorting of output digis. Is required by both digi trigger and event builder.
   std::sort(digiTs.fData.fSts.fDigis.begin(), digiTs.fData.fSts.fDigis.end(),
             [](CbmStsDigi digi1, CbmStsDigi digi2) { return digi1.GetTime() < digi2.GetTime(); });
+  std::sort(digiTs.fData.fMuch.fDigis.begin(), digiTs.fData.fMuch.fDigis.end(),
+            [](CbmMuchDigi digi1, CbmMuchDigi digi2) { return digi1.GetTime() < digi2.GetTime(); });
 
   // --- Timeslice log
   timer.Stop();
diff --git a/reco/mq/CbmDevUnpack.h b/reco/mq/CbmDevUnpack.h
index af5a996e045e8d7f11c32e10ff0a7eb81f67a2e9..454dd139644cdb33c9baa674c332afe772513c37 100644
--- a/reco/mq/CbmDevUnpack.h
+++ b/reco/mq/CbmDevUnpack.h
@@ -26,7 +26,9 @@
 #include <map>
 #include <vector>
 
+#include "MuchReadoutConfig.h"
 #include "StsReadoutConfig.h"
+#include "UnpackMuch.h"
 #include "UnpackSts.h"
 
 class TimesliceMetaData;
@@ -41,6 +43,9 @@ private:
   std::map<uint16_t, cbm::algo::UnpackSts> fAlgoSts = {};
   cbm::algo::StsReadoutConfig fStsConfig {};
 
+  std::map<uint16_t, cbm::algo::UnpackMuch> fAlgoMuch = {};
+  cbm::algo::MuchReadoutConfig fMuchConfig {};
+
   /// message queues
   std::string fsChannelNameDataInput  = "ts-request";
   std::string fsChannelNameDataOutput = "unpts_0";