diff --git a/reco/L1/CMakeLists.txt b/reco/L1/CMakeLists.txt
index 4eda3f60ecda8dd6fb5b241c19a559238a692824..a87c6542bc3bf59b40a85dad13865caa64c349d1 100644
--- a/reco/L1/CMakeLists.txt
+++ b/reco/L1/CMakeLists.txt
@@ -34,6 +34,7 @@ Set(INCLUDE_DIRECTORIES
 
   ${CBMROOT_SOURCE_DIR}/reco/L1
   ${CBMROOT_SOURCE_DIR}/reco/L1/L1Algo
+  ${CBMROOT_SOURCE_DIR}/reco/L1/catools
   ${CBMROOT_SOURCE_DIR}/reco/L1/OffLineInterface
   ${CBMROOT_SOURCE_DIR}/reco/L1/ParticleFinder
   ${CBMROOT_SOURCE_DIR}/reco/L1/qa
@@ -128,6 +129,7 @@ set(SRCS
   L1Algo/L1Grid.cxx
   CbmL1Performance.cxx
   CbmL1ReadEvent.cxx
+  CbmCaPerformance.cxx
   L1Algo/L1Station.cxx
   L1Algo/L1TrackParFit.cxx
   L1Algo/L1Event.cxx
@@ -152,7 +154,9 @@ set(SRCS
   L1Algo/utils/L1AlgoDraw.cxx
   L1Algo/utils/L1AlgoEfficiencyPerformance.cxx
   L1Algo/utils/L1AlgoPulls.cxx
-
+  catools/CaToolsMcData.cxx
+  catools/CaToolsMcDataManager.cxx
+  catools/CaToolsPerformance.cxx
   ParticleFinder/CbmL1PFFitter.cxx
   ParticleFinder/CbmL1PFMCParticle.cxx
 
@@ -196,6 +200,10 @@ set(HEADERS
   # OffLineInterface / CbmL1SttTrack.h
   L1Algo/L1Def.h
   L1Algo/L1Vector.h
+  CbmCaPerformance.h
+  catools/CaToolsMcData.h
+  catools/CaToolsMcDataManager.h
+  catools/CaToolsPerformance.h
   qa/CbmTrackerInputQaTrd.h
   qa/CbmTrackerInputQaTof.h
   qa/CbmTrackingInputQaSts.h
diff --git a/reco/L1/CbmCaPerformance.cxx b/reco/L1/CbmCaPerformance.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..d630c1b5c00630e5b7f74b467c598e7c7a0bdd0e
--- /dev/null
+++ b/reco/L1/CbmCaPerformance.cxx
@@ -0,0 +1,143 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergey Gorbunov, Sergei Zharko [committer] */
+
+/// \file   CbmCaPerformance.cxx
+/// \brief  CA Tracking performance interface for CBM (implementation)
+/// \since  23.09.2022
+/// \author S.Zharko <s.zharko@gsi.de>
+
+#include "CbmCaPerformance.h"
+
+#include "CbmEvent.h"
+#include "CbmL1.h"  // for L1DetectorID
+#include "CbmMCDataManager.h"
+
+#include "FairLogger.h"
+#include "FairRootManager.h"
+
+#include <cassert>
+#include <stdexcept>  // for std::logic_error
+
+
+// *********************************
+// ** Action definition functions **
+// *********************************
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+bool CbmCaPerformance::Init()
+try {
+  LOG(info) << "Initializing CA tracking Monte-Carlo module... ";
+
+  auto fairManager = FairRootManager::Instance();
+  assert(fairManager);
+
+  auto mcManager = dynamic_cast<CbmMCDataManager*>(fairManager->GetObject("MCDataManager"));
+  assert(mcManager);
+
+  fpMvdPoints  = nullptr;
+  fpStsPoints  = nullptr;
+  fpMuchPoints = nullptr;
+  fpTrdPoints  = nullptr;
+  fpTofPoints  = nullptr;
+
+  if (fbUseMvd) {
+    LOG(info) << "CA MC Module: initializing branches for MVD";
+    fpMvdPoints = mcManager->InitBranch("MvdPoint");
+  }
+
+  if (fbUseSts) {
+    LOG(info) << "CA MC Module: initializing branches for STS";
+    fpStsPoints = mcManager->InitBranch("StsPoint");
+  }
+
+  if (fbUseMuch) {
+    LOG(info) << "CA MC Module: initializing branches for MuCh";
+    fpMuchPoints = mcManager->InitBranch("MuchPoint");
+  }
+
+  if (fbUseTrd) {
+    LOG(info) << "CA MC Module: initializing branches for TRD";
+    fpTrdPoints = mcManager->InitBranch("TrdPoint");
+  }
+
+  if (fbUseTof) {
+    LOG(info) << "CA MC Module: initializing branches for TOF";
+    fpTofPoints = mcManager->InitBranch("TofPoint");
+  }
+
+  // Check initialization
+  this->CheckInit();
+
+  LOG(info) << "Initializing CA tracking Monte-Carlo module... \033[1;32mDone!\033[0m";
+  return true;
+}
+catch (const std::logic_error& error) {
+  LOG(info) << "Initializing CA tracking Monte-Carlo module... \033[1;31mFailed\033[0m\nReason: " << error.what();
+  return false;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void CbmCaPerformance::ProcessEvent(CbmEvent* pEvent)
+{
+  assert(pEvent);
+  std::cout << "\033[1;32mProcessing performance event\033[0m\n";
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void CbmCaPerformance::Finish() { std::cout << "\033[1;32mFinishing performance\033[0m\n"; }
+
+
+// ***********************
+// **     Accessors     **
+// ***********************
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void CbmCaPerformance::SetDetector(L1DetectorID detID, bool flag)
+{
+  switch (detID) {
+    case L1DetectorID::kMvd: fbUseMvd = flag; break;
+    case L1DetectorID::kSts: fbUseSts = flag; break;
+    case L1DetectorID::kMuch: fbUseMuch = flag; break;
+    case L1DetectorID::kTrd: fbUseTrd = flag; break;
+    case L1DetectorID::kTof: fbUseTof = flag; break;
+  }
+}
+
+
+// *******************************
+// **     Utility functions     **
+// *******************************
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void CbmCaPerformance::CheckInit() const
+{
+  // Check parameters
+  if (!fpParameters) { throw std::logic_error("Tracking parameters object was not defined"); }
+
+  // Check detectors initialization
+  if (fbUseMvd) {
+    if (fpMvdPoints) { throw std::logic_error("MC points unavailable for MVD"); }
+  }
+
+  if (fbUseSts) {
+    if (fpStsPoints) { throw std::logic_error("MC points unavailable for STS"); }
+  }
+
+  if (fbUseMuch) {
+    if (fpMuchPoints) { throw std::logic_error("MC points unavailable for MuCh"); }
+  }
+
+  if (fbUseTrd) {
+    if (fpTrdPoints) { throw std::logic_error("MC points unavailable for TRD"); }
+  }
+
+  if (fbUseTof) {
+    if (fpTofPoints) { throw std::logic_error("MC points unavailable for TOF"); }
+  }
+}
diff --git a/reco/L1/CbmCaPerformance.h b/reco/L1/CbmCaPerformance.h
new file mode 100644
index 0000000000000000000000000000000000000000..8dd5f579cd6685b0fdc476655b057639f55685da
--- /dev/null
+++ b/reco/L1/CbmCaPerformance.h
@@ -0,0 +1,123 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergey Gorbunov, Sergei Zharko [committer] */
+
+/// \file   CbmCaPerformance.h
+/// \brief  CA Tracking performance interface for CBM (header)
+/// \since  23.09.2022
+/// \author S.Zharko <s.zharko@gsi.de>
+
+#ifndef CbmCaPerformance_h
+#define CbmCaPerformance_h 1
+
+#include "CaToolsMcDataManager.h"
+#include "CaToolsPerformance.h"
+
+
+class CbmEvent;
+class CbmMCDataObject;
+class CbmMCDataArray;
+class CbmMCEventList;
+enum class L1DetectorID;
+
+
+/// Class CbmCaPerformcance is an interface to communicate between
+class CbmCaPerformance {
+public:
+  // *****************************************
+  // **     Constructors and destructor     **
+  // *****************************************
+
+  /// Default constructor
+  CbmCaPerformance() = default;
+
+  /// Destructor
+  ~CbmCaPerformance() = default;
+
+  /// Copy constructor
+  CbmCaPerformance(const CbmCaPerformance&) = delete;
+
+  /// Move constructor
+  CbmCaPerformance(CbmCaPerformance&&) = delete;
+
+  /// Copy assignment operator
+  CbmCaPerformance& operator=(const CbmCaPerformance&) = delete;
+
+  /// Move assignment operator
+  CbmCaPerformance& operator=(CbmCaPerformance&&) = delete;
+
+
+  // *****************************************
+  // **     Action definition functions     **
+  // *****************************************
+
+  /// Defines performance action in the beginning of the run
+  /// \return Success flag
+  bool Init();
+
+  /// Defines performance action in each event or timeslice
+  /// \param  pEvent Pointer to a current CbmEvent
+  void ProcessEvent(CbmEvent* pEvent);
+
+  /// Defines performance action in the end of the run
+  void Finish();
+
+
+  // ***********************
+  // **     Accessors     **
+  // ***********************
+
+  /// Registers pointer to the tracking parameters object
+  void SetParameters(const L1Parameters* pParameters) { fpParameters = pParameters; }
+
+  /// Sets used detector subsystems
+  /// \param  detID  Id of detector
+  /// \param  flag   Flag: true - detector is used
+  void SetDetector(L1DetectorID detID, bool flag);
+
+
+private:
+  // *******************************
+  // **     Utility functions     **
+  // *******************************
+
+  /// Checks class initialization. Throws std::logic_error, if initialization is incomplete at initialization call
+  void CheckInit() const;
+
+
+  // *******************************
+  // **     Utility variables     **
+  // *******************************
+
+  ca::tools::Performance fPerformance     = {};       ///< Instance of the internal performance object
+  ca::tools::McDataManager fMcDataManager = {};       ///< Instance of the MC data manager
+  const L1Parameters* fpParameters        = nullptr;  ///< Pointer to tracking parameters object
+
+  bool fbUseMvd  = false;
+  bool fbUseSts  = false;
+  bool fbUseMuch = false;
+  bool fbUseTrd  = false;
+  bool fbUseTof  = false;
+
+
+  // *********************************
+  // **     Input data branches     **
+  // *********************************
+
+  // Mc-event
+  const CbmMCEventList* fpEventList      = nullptr;  ///< MC event list
+  const CbmMCDataObject* fpMcEventHeader = nullptr;  ///< MC event header
+  const CbmMCDataArray* fpMcTracks       = nullptr;  ///< MC tracks
+
+  // Mc-points
+  const CbmMCDataArray* fpMvdPoints  = nullptr;  ///< MVD MC-points container
+  const CbmMCDataArray* fpStsPoints  = nullptr;  ///< STS MC-points container
+  const CbmMCDataArray* fpMuchPoints = nullptr;  ///< MuCh MC-points container
+  const CbmMCDataArray* fpTrdPoints  = nullptr;  ///< TRD MC-points container
+  const CbmMCDataArray* fpTofPoints  = nullptr;  ///< TOF MC-points container
+
+
+  // Matching information
+};
+
+#endif  // CbmCaPerformance_h
diff --git a/reco/L1/CbmL1.h b/reco/L1/CbmL1.h
index 00f4b16b20d1807c72a6779121f2d1ccd4b23d0e..e8a7ff2345e4554262c09ab508daf284fd656a06 100644
--- a/reco/L1/CbmL1.h
+++ b/reco/L1/CbmL1.h
@@ -376,9 +376,16 @@ private:
    * Input Performance
    */
 
+  /// Matches hit with MC point
+  /// \tparam  DetId Detector ID
+  /// \param   iHit  External index of hit
+  /// \return  tuple of MC point index in fvMCPoints array
+  template<L1DetectorID DetId>
+  int MatchHitWithMc(int iHit) const;
+
   /// Procedure for match hits and MCPoints.
   /// Reads information about correspondence between hits and MC-points and fill CbmL1MCPoint::hitIds and CbmL1Hit::mcPointIds arrays
-  /// should be called after fill of algo
+  /// should be called after reading the event
   void HitMatch();
 
   void FieldApproxCheck();    // Build histograms with difference between Field map and approximated field
@@ -469,7 +476,11 @@ public:
 private:
   static CbmL1* fpInstance;  ///< Instance of CbmL1
 
-  int nMvdPoints = 0;  // TODO: Should be removed (S.Zharko)
+  int fNpointsMvd  = 0;  ///< Number of MC points for MVD
+  int fNpointsSts  = 0;  ///< Number of MC points for STS
+  int fNpointsMuch = 0;  ///< Number of MC points for MuCh
+  int fNpointsTrd  = 0;  ///< Number of MC points for TRD
+  int fNpointsTof  = 0;  ///< Number of MC points for TOF
 
   L1Vector<CbmL1MCPoint> fvMCPoints = {"CbmL1::fvMCPoints"};          ///< Container of MC points
   L1Vector<int> fvMCPointIndexesTs  = {"CbmL1::fvMCPointIndexesTs"};  ///< Indexes of MC points in TS
@@ -518,11 +529,14 @@ private:
   Double_t fMomentumCutOff = 0.1;   // currently not used
   Bool_t fGhostSuppression = true;  // currently not used
 
-  /// TODO: change to bool
-  Int_t fStsUseMcHit  = -1;  ///< if STS data should be processed
-  Int_t fMuchUseMcHit = -1;  ///< if Much data should be processed
-  Int_t fTrdUseMcHit  = -1;  ///< if Trd data should be processed
-  Int_t fTofUseMcHit  = -1;  ///< if Tof data should be processed
+  /// Flags to adjust hits with MC information
+  /// 1: Position of a reconstructed hit is taken from matched MC point and smeared (optionally) with the position
+  ///    resolution
+  /// 2: A set of hits is created from the set of MC points
+  Int_t fStsUseMcHit  = -1;  ///< MC info flag for STS hits
+  Int_t fMuchUseMcHit = -1;  ///< MC info flag for MuCh hits
+  Int_t fTrdUseMcHit  = -1;  ///< MC info flag for TRD hits
+  Int_t fTofUseMcHit  = -1;  ///< MC info flag for TOF hits
 
   bool fUseMVD  = false;  ///< if Mvd data should be processed
   bool fUseSTS  = false;  ///< if Mvd data should be processed
diff --git a/reco/L1/CbmL1ReadEvent.cxx b/reco/L1/CbmL1ReadEvent.cxx
index d6d081f62dce67713685d550e68c951e33ed786b..24b1bf60550b0084712973c4d4b8ad784c20d835 100644
--- a/reco/L1/CbmL1ReadEvent.cxx
+++ b/reco/L1/CbmL1ReadEvent.cxx
@@ -172,6 +172,145 @@ struct TmpHit {
   }
 };
 
+
+// *****************************************
+// **     Hits and MC-points matching     **
+// *****************************************
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+template<>
+int CbmL1::MatchHitWithMc<L1DetectorID::kMvd>(int iHit) const
+{
+  int iPoint = -1;
+  if (fpMvdHitMatches) {
+    int iHitExt          = -(1 + iHit);  // TODO: SZh 28.08.2022: this should be replaced with iHitExt = hit.extIdex
+    const auto* hitMatch = dynamic_cast<CbmMatch*>(fpMvdHitMatches->At(iHitExt));
+    assert(hitMatch);
+    if (hitMatch->GetNofLinks() > 0 && hitMatch->GetLink(0).GetIndex() < fNpointsMvd) {
+      iPoint = hitMatch->GetLink(0).GetIndex();
+    }
+  }
+  return iPoint;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+template<>
+int CbmL1::MatchHitWithMc<L1DetectorID::kSts>(int iHit) const
+{
+  int iPoint     = -1;
+  const auto* sh = dynamic_cast<CbmStsHit*>(fpStsHits->At(iHit));
+
+  // Match MC point
+  if (fpStsClusterMatches) {
+    const auto* clusterMatchF = static_cast<const CbmMatch*>(fpStsClusterMatches->At(sh->GetFrontClusterId()));
+    const auto* clusterMatchB = static_cast<const CbmMatch*>(fpStsClusterMatches->At(sh->GetBackClusterId()));
+    CbmMatch hitMatch;
+    for (int iLinkF = 0; iLinkF < clusterMatchF->GetNofLinks(); ++iLinkF) {
+      const auto& linkF = clusterMatchF->GetLink(iLinkF);
+      for (int iLinkB = 0; iLinkB < clusterMatchB->GetNofLinks(); ++iLinkB) {
+        const auto& linkB = clusterMatchB->GetLink(iLinkB);
+        if (linkF == linkB) {
+          hitMatch.AddLink(linkF);
+          hitMatch.AddLink(linkB);
+        }
+      }
+    }
+    float bestWeight = 0.f;
+    for (int iLink = 0; iLink < hitMatch.GetNofLinks(); ++iLink) {
+      const CbmLink& link = hitMatch.GetLink(iLink);
+      int iFile           = link.GetFile();
+      int iEvent          = link.GetEntry();
+      int iIndex          = link.GetIndex();
+
+      if (fLegacyEventMode) {
+        iFile  = fvFileEvent.begin()->first;
+        iEvent = fvFileEvent.begin()->second;
+      }
+
+      auto itPoint = fmMCPointsLinksMap.find(CbmL1LinkKey(iIndex + fNpointsMvd, iEvent, iFile));
+      assert(itPoint != fmMCPointsLinksMap.cend());
+
+      if (link.GetWeight() > bestWeight) {
+        bestWeight = link.GetWeight();
+        iPoint     = itPoint->second;
+      }
+    }
+  }  // Match MC point
+  return iPoint;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+template<>
+int CbmL1::MatchHitWithMc<L1DetectorID::kMuch>(int iHit) const
+{
+  int iPoint               = -1;
+  const auto* hitMatchMuch = dynamic_cast<CbmMatch*>(fpMuchHitMatches->At(iHit));
+  if (hitMatchMuch) {
+    for (int iLink = 0; iLink < hitMatchMuch->GetNofLinks(); ++iLink) {
+      if (hitMatchMuch->GetLink(iLink).GetIndex() < fNpointsMuch) {
+        int iMc    = hitMatchMuch->GetLink(iLink).GetIndex();
+        int iIndex = iMc + fNpointsMvd + fNpointsSts;
+        int iFile  = hitMatchMuch->GetLink(0).GetFile();
+        int iEvent = hitMatchMuch->GetLink(0).GetEntry();
+
+        auto itPoint = fmMCPointsLinksMap.find(CbmL1LinkKey(iIndex, iEvent, iFile));
+        if (itPoint == fmMCPointsLinksMap.cend()) continue;
+        iPoint = itPoint->second;
+      }
+    }
+  }
+  return iPoint;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+template<>
+int CbmL1::MatchHitWithMc<L1DetectorID::kTrd>(int iHit) const
+{
+  int iPoint           = -1;
+  const auto* hitMatch = dynamic_cast<const CbmMatch*>(fpTrdHitMatches->At(iHit));
+  if (hitMatch) {
+    int iMC = -1;
+    if (hitMatch->GetNofLinks() > 0) {
+      iMC = hitMatch->GetLink(0).GetIndex();
+      assert(iMC >= 0 && iMC < fNpointsTrd);
+      iPoint = iMC + fNpointsMvd + fNpointsSts + fNpointsMuch;
+    }
+  }
+  return iPoint;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+template<>
+int CbmL1::MatchHitWithMc<L1DetectorID::kTof>(int iHit) const
+{
+  int iPoint           = -1;
+  const auto* hitMatch = dynamic_cast<const CbmMatch*>(fpTofHitMatches->At(iHit));
+  if (hitMatch) {
+    for (int iLink = 0; iLink < hitMatch->GetNofLinks(); ++iLink) {
+      int iFile    = hitMatch->GetLink(iLink).GetFile();
+      int iEvent   = hitMatch->GetLink(iLink).GetEntry();
+      int iMc      = hitMatch->GetLink(iLink).GetIndex();
+      int iIndex   = iMc + fNpointsMvd + fNpointsSts + fNpointsMuch + fNpointsTrd;
+      auto itPoint = fmMCPointsLinksMap.find(CbmL1LinkKey(iIndex, iEvent, iFile));
+      if (itPoint == fmMCPointsLinksMap.cend()) { continue; }
+      iPoint = itPoint->second;
+    }
+  }
+  return iPoint;
+}
+
+
+// **************************
+// **     Event reader     **
+// **************************
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
 void CbmL1::ReadEvent(float& TsStart, float& TsLength, float& /*TsOverlap*/, int& FstHitinTs, bool& areDataLeft,
                       CbmEvent* event)
 {
@@ -216,19 +355,18 @@ void CbmL1::ReadEvent(float& TsStart, float& TsLength, float& /*TsOverlap*/, int
     tmpHits.reserve(nHitsTotal);
   }
 
-  nMvdPoints      = 0;
-  int nStsPoints  = 0;
-  int nTrdPoints  = 0;
-  int nMuchPoints = 0;
-  int nTofPoints  = 0;
+  fNpointsMvd  = 0;
+  fNpointsSts  = 0;
+  fNpointsTrd  = 0;
+  fNpointsMuch = 0;
+  fNpointsTof  = 0;
 
   // get MVD hits
-  Int_t nMvdHits  = 0;
-  Int_t nMuchHits = 0;
-  Int_t nTrdHits  = 0;
-  Int_t nTofHits  = 0;
-  // get STS hits
+  int nMvdHits  = 0;
   int nStsHits = 0;
+  int nMuchHits = 0;
+  int nTrdHits  = 0;
+  int nTofHits  = 0;
 
   int firstTrdPoint  = 0;
   int firstStsPoint  = 0;
@@ -257,9 +395,9 @@ void CbmL1::ReadEvent(float& TsStart, float& TsLength, float& /*TsOverlap*/, int
       Int_t iEvent = set_it->second;
 
       if (fUseMVD && fpMvdPoints) {
-        Int_t nMvdPointsInEvent = fpMvdPoints->Size(iFile, iEvent);
+        Int_t fNpointsMvdInEvent = fpMvdPoints->Size(iFile, iEvent);
         double maxDeviation     = 0;
-        for (Int_t iMC = 0; iMC < nMvdPointsInEvent; iMC++) {
+        for (Int_t iMC = 0; iMC < fNpointsMvdInEvent; iMC++) {
           CbmL1MCPoint MC;
           if (!ReadMCPoint(&MC, iMC, iFile, iEvent, 1)) {
             MC.iStation          = -1;
@@ -285,7 +423,7 @@ void CbmL1::ReadEvent(float& TsStart, float& TsLength, float& /*TsOverlap*/, int
             fmMCPointsLinksMap[CbmL1LinkKey(iMC, iEvent, iFile)] = fvMCPoints.size();
             fvMCPoints.push_back(MC);
             fvMCPointIndexesTs.push_back(0);
-            nMvdPoints++;
+            fNpointsMvd++;
           }
         }
         if (fVerbose > 2) { LOG(info) << "CbmL1ReadEvent: max deviation of Mvd points " << maxDeviation; }
@@ -320,10 +458,10 @@ void CbmL1::ReadEvent(float& TsStart, float& TsLength, float& /*TsOverlap*/, int
             assert(itTrack != fmMCTracksLinksMap.cend());
             MC.ID = itTrack->second;
             fvMCTracks[MC.ID].Points.push_back_no_warning(fvMCPoints.size());
-            fmMCPointsLinksMap[CbmL1LinkKey(iMC + nMvdPoints, iEvent, iFile)] = fvMCPoints.size();
+            fmMCPointsLinksMap[CbmL1LinkKey(iMC + fNpointsMvd, iEvent, iFile)] = fvMCPoints.size();
             fvMCPoints.push_back(MC);
             fvMCPointIndexesTs.push_back(0);
-            nStsPoints++;
+            fNpointsSts++;
           }
         }
         if (fVerbose > 2) { LOG(info) << "CbmL1ReadEvent: max deviation of Sts points " << maxDeviation; }
@@ -349,10 +487,10 @@ void CbmL1::ReadEvent(float& TsStart, float& TsLength, float& /*TsOverlap*/, int
             assert(itTrack != fmMCTracksLinksMap.cend());
             MC.ID = itTrack->second;
             fvMCTracks[MC.ID].Points.push_back_no_warning(fvMCPoints.size());
-            fmMCPointsLinksMap[CbmL1LinkKey(iMC + nMvdPoints + nStsPoints, iEvent, iFile)] = fvMCPoints.size();
+            fmMCPointsLinksMap[CbmL1LinkKey(iMC + fNpointsMvd + fNpointsSts, iEvent, iFile)] = fvMCPoints.size();
             fvMCPoints.push_back(MC);
             fvMCPointIndexesTs.push_back(0);
-            nMuchPoints++;
+            fNpointsMuch++;
           }
         }
       }  // fpMuchPoints
@@ -376,11 +514,11 @@ void CbmL1::ReadEvent(float& TsStart, float& TsLength, float& /*TsOverlap*/, int
             assert(itTrack != fmMCTracksLinksMap.cend());
             MC.ID = itTrack->second;
             fvMCTracks[MC.ID].Points.push_back_no_warning(fvMCPoints.size());
-            fmMCPointsLinksMap[CbmL1LinkKey(iMC + nMvdPoints + nStsPoints + nMuchPoints, iEvent, iFile)] =
+            fmMCPointsLinksMap[CbmL1LinkKey(iMC + fNpointsMvd + fNpointsSts + fNpointsMuch, iEvent, iFile)] =
               fvMCPoints.size();
             fvMCPoints.push_back(MC);
             fvMCPointIndexesTs.push_back(0);
-            nTrdPoints++;
+            fNpointsTrd++;
           }
         }
       }  // fpTrdPoints
@@ -465,11 +603,11 @@ void CbmL1::ReadEvent(float& TsStart, float& TsLength, float& /*TsOverlap*/, int
 
               MC.ID = iTrack;
 
-              int iMC = fTofPointToTrack[iTofSta][iTrack] + nMvdPoints + nStsPoints + nMuchPoints + nTrdPoints;
+              int iMC = fTofPointToTrack[iTofSta][iTrack] + fNpointsMvd + fNpointsSts + fNpointsMuch + fNpointsTrd;
               fmMCPointsLinksMap[CbmL1LinkKey(iMC, iEvent, iFile)] = fvMCPoints.size();
               fvMCPoints.push_back(MC);
               fvMCPointIndexesTs.push_back(0);
-              nTofPoints++;
+              fNpointsTof++;
             }
           }
       }
@@ -547,14 +685,16 @@ void CbmL1::ReadEvent(float& TsStart, float& TsLength, float& /*TsOverlap*/, int
         th.v                = th.x * st.backInfo.cos_phi[0] + th.y * st.backInfo.sin_phi[0];
       }
       th.Det = 0;
-      th.iMC = -1;
-      if (fPerformance) {
-        if (fpMvdHitMatches) {
-          CbmMatch* mvdHitMatch = L1_DYNAMIC_CAST<CbmMatch*>(fpMvdHitMatches->At(j));
-          if (mvdHitMatch->GetNofLinks() > 0)
-            if (mvdHitMatch->GetLink(0).GetIndex() < nMvdPoints) { th.iMC = mvdHitMatch->GetLink(0).GetIndex(); }
-        }
-      }
+      th.iMC = fPerformance ? MatchHitWithMc<L1DetectorID::kMvd>(th.ExtIndex) : -1;
+      //if (fPerformance) {
+      //  if (fpMvdHitMatches) {
+      //    CbmMatch* mvdHitMatch = L1_DYNAMIC_CAST<CbmMatch*>(fpMvdHitMatches->At(j));
+      //    if (mvdHitMatch->GetNofLinks() > 0)
+      //      if (mvdHitMatch->GetLink(0).GetIndex() < fNpointsMvd) {
+      //        th.iMC = mvdHitMatch->GetLink(0).GetIndex();
+      //      }
+      //  }
+      //}
       //if(  h.MC_Point >=0 ) // DEBUG !!!!
       {
         tmpHits.push_back(th);
@@ -566,7 +706,7 @@ void CbmL1::ReadEvent(float& TsStart, float& TsLength, float& /*TsOverlap*/, int
 
   if (fUseSTS && (2 == fStsUseMcHit)) {  // create hits from points
 
-    for (int ip = firstStsPoint; ip < firstStsPoint + nStsPoints; ip++) {
+    for (int ip = firstStsPoint; ip < firstStsPoint + fNpointsSts; ip++) {
       const CbmL1MCPoint& p = fvMCPoints[ip];
       //       int mcTrack           = p.ID;
       //       if (mcTrack < 0) continue;
@@ -659,7 +799,7 @@ void CbmL1::ReadEvent(float& TsStart, float& TsLength, float& /*TsOverlap*/, int
         th.u                = th.x * st.frontInfo.cos_phi[0] + th.y * st.frontInfo.sin_phi[0];
         th.v                = th.x * st.backInfo.cos_phi[0] + th.y * st.backInfo.sin_phi[0];
       }
-      th.iMC = -1;
+      th.iMC = fPerformance ? MatchHitWithMc<L1DetectorID::kSts>(hitIndexSort) : -1;
 
       tmpHits.push_back(th);
       nStsHits++;
@@ -672,7 +812,7 @@ void CbmL1::ReadEvent(float& TsStart, float& TsLength, float& /*TsOverlap*/, int
   //
   if ((2 == fMuchUseMcHit) && fUseMUCH) {  // create hits from points
 
-    for (int ip = firstMuchPoint; ip < firstMuchPoint + nMuchPoints; ip++) {
+    for (int ip = firstMuchPoint; ip < firstMuchPoint + fNpointsMuch; ip++) {
       const CbmL1MCPoint& p = fvMCPoints[ip];
 
       //       int mcTrack = p.ID;
@@ -742,32 +882,33 @@ void CbmL1::ReadEvent(float& TsStart, float& TsLength, float& /*TsOverlap*/, int
         th.u                = th.x * st.frontInfo.cos_phi[0] + th.y * st.frontInfo.sin_phi[0];
         th.v                = th.x * st.backInfo.cos_phi[0] + th.y * st.backInfo.sin_phi[0];
       }
-      th.iMC  = -1;
-      int iMC = -1;
-
-
-      if (fPerformance) {
-        if (fpMuchHitMatches) {
-          CbmMatch* matchHitMatch = L1_DYNAMIC_CAST<CbmMatch*>(fpMuchHitMatches->At(j));
-
-
-          for (Int_t iLink = 0; iLink < matchHitMatch->GetNofLinks(); iLink++) {
-            if (matchHitMatch->GetLink(iLink).GetIndex() < nMuchPoints) {
-              iMC          = matchHitMatch->GetLink(iLink).GetIndex();
-              Int_t iIndex = iMC + nMvdPoints + nStsPoints;
-
-              Int_t iFile  = matchHitMatch->GetLink(0).GetFile();
-              Int_t iEvent = matchHitMatch->GetLink(0).GetEntry();
-
-              auto itPoint = fmMCPointsLinksMap.find(CbmL1LinkKey(iIndex, iEvent, iFile));
-              if (itPoint == fmMCPointsLinksMap.cend()) continue;
-              th.iMC = itPoint->second;
-              if ((1 == fMuchUseMcHit) && (th.iMC > -1))
-                th.SetHitFromPoint(fvMCPoints[th.iMC], fpAlgo->GetParameters()->GetStation(th.iStation));
-            }
-          }
-        }
+      th.iMC = fPerformance ? MatchHitWithMc<L1DetectorID::kMuch>(j) : -1;
+      if (1 == fMuchUseMcHit && th.iMC > -1) {
+        th.SetHitFromPoint(fvMCPoints[th.iMC], fpAlgo->GetParameters()->GetStation(th.iStation));
       }
+      //int iMC = -1;
+      //if (fPerformance) {
+      //  if (fpMuchHitMatches) {
+      //    CbmMatch* matchHitMatch = L1_DYNAMIC_CAST<CbmMatch*>(fpMuchHitMatches->At(j));
+
+
+      //    for (Int_t iLink = 0; iLink < matchHitMatch->GetNofLinks(); iLink++) {
+      //      if (matchHitMatch->GetLink(iLink).GetIndex() < fNpointsMuch) {
+      //        iMC          = matchHitMatch->GetLink(iLink).GetIndex();
+      //        Int_t iIndex = iMC + fNpointsMvd + fNpointsSts;
+
+      //        Int_t iFile  = matchHitMatch->GetLink(0).GetFile();
+      //        Int_t iEvent = matchHitMatch->GetLink(0).GetEntry();
+
+      //        auto itPoint = fmMCPointsLinksMap.find(CbmL1LinkKey(iIndex, iEvent, iFile));
+      //        if (itPoint == fmMCPointsLinksMap.cend()) continue;
+      //        th.iMC = itPoint->second;
+      //        if ((1 == fMuchUseMcHit) && (th.iMC > -1))
+      //          th.SetHitFromPoint(fvMCPoints[th.iMC], fpAlgo->GetParameters()->GetStation(th.iStation));
+      //      }
+      //    }
+      //  }
+      //}
 
       tmpHits.push_back(th);
       nMuchHits++;
@@ -782,7 +923,7 @@ void CbmL1::ReadEvent(float& TsStart, float& TsLength, float& /*TsOverlap*/, int
   if (fUseTRD) {
 
     if (2 == fTrdUseMcHit) {  // create hits from MC points
-      for (int ip = firstTrdPoint; ip < firstTrdPoint + nTrdPoints; ip++) {
+      for (int ip = firstTrdPoint; ip < firstTrdPoint + fNpointsTrd; ip++) {
         const CbmL1MCPoint& p = fvMCPoints[ip];
         //       int mcTrack = p.ID;
         //       if (mcTrack < 0) continue;
@@ -798,7 +939,7 @@ void CbmL1::ReadEvent(float& TsStart, float& TsLength, float& /*TsOverlap*/, int
 
       assert(fpTrdHits);
 
-      vector<bool> mcUsed(nTrdPoints, 0);
+      vector<bool> mcUsed(fNpointsTrd, 0);
 
       Int_t nEntTrd = (event ? event->GetNofData(ECbmDataType::kTrdHit) : fpTrdHits->GetEntriesFast());
 
@@ -856,24 +997,26 @@ void CbmL1::ReadEvent(float& TsStart, float& TsLength, float& /*TsOverlap*/, int
 
         std::tie(th.u, th.v) = st.ConvXYtoUV<double>(th.x, th.y);
 
-        th.iMC     = -1;
-        th.track   = -1;
-        int iMcTrd = -1;
-        if (fPerformance && fpTrdHitMatches) {
-          CbmMatch* trdHitMatch = L1_DYNAMIC_CAST<CbmMatch*>(fpTrdHitMatches->At(iHit));
-          if (trdHitMatch->GetNofLinks() > 0) {
-            iMcTrd = trdHitMatch->GetLink(0).GetIndex();
-            assert(iMcTrd >= 0 && iMcTrd < nTrdPoints);
-            th.iMC   = iMcTrd + nMvdPoints + nStsPoints + nMuchPoints;
-            th.track = fvMCPoints[th.iMC].ID;
-          }
-        }
+        th.iMC   = fPerformance ? MatchHitWithMc<L1DetectorID::kTrd>(iHit) : -1;
+        th.track = (th.iMC > -1) ? fvMCPoints[th.iMC].ID : -1;
+        //int iMcTrd = -1;
+        //if (fPerformance && fpTrdHitMatches) {
+        //  CbmMatch* trdHitMatch = L1_DYNAMIC_CAST<CbmMatch*>(fpTrdHitMatches->At(iHit));
+        //  if (trdHitMatch->GetNofLinks() > 0) {
+        //    iMcTrd = trdHitMatch->GetLink(0).GetIndex();
+        //    assert(iMcTrd >= 0 && iMcTrd < fNpointsTrd);
+        //    th.iMC   = iMcTrd + fNpointsMvd + fNpointsSts + fNpointsMuch;
+        //    th.track = fvMCPoints[th.iMC].ID;
+        //  }
+        //}
 
         if (1 == fTrdUseMcHit) {  // replace hit by MC points
 
           assert(fPerformance && fpTrdHitMatches);
 
           if (th.iMC < 0) continue;      // skip noise hits
+          int iMcTrd = th.iMC - fNpointsMvd - fNpointsSts - fNpointsMuch;
+          assert(iMcTrd >= 0 && iMcTrd < fNpointsTrd);
           if (mcUsed[iMcTrd]) continue;  // one hit per MC point
           bool doSmear = true;
           if (0) {  // SGtrd2d!! debug: artificial errors
@@ -906,7 +1049,7 @@ void CbmL1::ReadEvent(float& TsStart, float& TsLength, float& /*TsOverlap*/, int
   // Get ToF hits
   //
   if ((2 == fTofUseMcHit) && fUseTOF) {  // create hits from points
-    for (int ip = firstTofPoint; ip < firstTofPoint + nTofPoints; ip++) {
+    for (int ip = firstTofPoint; ip < firstTofPoint + fNpointsTof; ip++) {
       const CbmL1MCPoint& p = fvMCPoints[ip];
 
       //       int mcTrack = p.ID;
@@ -985,32 +1128,35 @@ void CbmL1::ReadEvent(float& TsStart, float& TsLength, float& /*TsOverlap*/, int
       th.u                = th.x * st.frontInfo.cos_phi[0] + th.y * st.frontInfo.sin_phi[0];
       th.v                = th.x * st.backInfo.cos_phi[0] + th.y * st.backInfo.sin_phi[0];
 
+      th.iMC = fPerformance ? MatchHitWithMc<L1DetectorID::kTof>(j) : -1;
 
-      th.iMC = -1;
+      if (1 == fTofUseMcHit && th.iMC > -1) {
+        th.SetHitFromPoint(fvMCPoints[th.iMC], fpAlgo->GetParameters()->GetStation(th.iStation));
+      }
       //      int iMC = -1;
 
 
-      if (fPerformance) {
+      //if (fPerformance) {
 
-        CbmMatch* matchHitMatch = L1_DYNAMIC_CAST<CbmMatch*>(fpTofHitMatches->At(j));
+      //  CbmMatch* matchHitMatch = L1_DYNAMIC_CAST<CbmMatch*>(fpTofHitMatches->At(j));
 
-        for (int iLink = 0; iLink < matchHitMatch->GetNofLinks(); iLink++)  //matchHitMatch->GetNofLinks(); k++)
-        {
-          Int_t iMC    = matchHitMatch->GetLink(iLink).GetIndex();
-          Int_t iFile  = matchHitMatch->GetLink(iLink).GetFile();
-          Int_t iEvent = matchHitMatch->GetLink(iLink).GetEntry();
+      //  for (int iLink = 0; iLink < matchHitMatch->GetNofLinks(); iLink++)  //matchHitMatch->GetNofLinks(); k++)
+      //  {
+      //    Int_t iMC    = matchHitMatch->GetLink(iLink).GetIndex();
+      //    Int_t iFile  = matchHitMatch->GetLink(iLink).GetFile();
+      //    Int_t iEvent = matchHitMatch->GetLink(iLink).GetEntry();
 
-          Int_t iIndex = iMC + nMvdPoints + nStsPoints + nMuchPoints + nTrdPoints;
+      //    Int_t iIndex = iMC + fNpointsMvd + fNpointsSts + fNpointsMuch + fNpointsTrd;
 
-          //CbmTofPoint* pt = L1_DYNAMIC_CAST<CbmTofPoint*>(fTofPoints->Get(iFile, iEvent, iMC));
-          // pt->GetTrackID();
-          auto itPoint = fmMCPointsLinksMap.find(CbmL1LinkKey(iIndex, iEvent, iFile));
-          if (itPoint == fmMCPointsLinksMap.cend()) continue;
-          th.iMC = itPoint->second;
-          if ((1 == fTofUseMcHit) && (th.iMC > -1))
-            th.SetHitFromPoint(fvMCPoints[th.iMC], fpAlgo->GetParameters()->GetStation(th.iStation));
-        }
-      }
+      //    //CbmTofPoint* pt = L1_DYNAMIC_CAST<CbmTofPoint*>(fTofPoints->Get(iFile, iEvent, iMC));
+      //    // pt->GetTrackID();
+      //    auto itPoint = fmMCPointsLinksMap.find(CbmL1LinkKey(iIndex, iEvent, iFile));
+      //    if (itPoint == fmMCPointsLinksMap.cend()) continue;
+      //    th.iMC = itPoint->second;
+      //    if ((1 == fTofUseMcHit) && (th.iMC > -1))
+      //      th.SetHitFromPoint(fvMCPoints[th.iMC], fpAlgo->GetParameters()->GetStation(th.iStation));
+      //  }
+      //}
 
       tmpHits.push_back(th);
       nTofHits++;
@@ -1372,67 +1518,10 @@ void CbmL1::HitMatch()
   for (int iH = 0; iH < NHits; iH++) {
     CbmL1Hit& hit = fvExternalHits[iH];
 
-    if ((hit.Det == 1) && (2 != fStsUseMcHit)) {
-      CbmStsHit* sh = L1_DYNAMIC_CAST<CbmStsHit*>(fpStsHits->At(fvExternalHits[iH].extIndex));
-
-      int iP = -1;
-
-      if (fpStsClusterMatches) {
-
-        const CbmMatch* frontClusterMatch =
-          static_cast<const CbmMatch*>(fpStsClusterMatches->At(sh->GetFrontClusterId()));
-        const CbmMatch* backClusterMatch =
-          static_cast<const CbmMatch*>(fpStsClusterMatches->At(sh->GetBackClusterId()));
-        CbmMatch stsHitMatch;
-
-        for (Int_t iFrontLink = 0; iFrontLink < frontClusterMatch->GetNofLinks(); iFrontLink++) {
-          const CbmLink& frontLink = frontClusterMatch->GetLink(iFrontLink);
-          for (Int_t iBackLink = 0; iBackLink < backClusterMatch->GetNofLinks(); iBackLink++) {
-            const CbmLink& backLink = backClusterMatch->GetLink(iBackLink);
-            if (frontLink == backLink) {
-              stsHitMatch.AddLink(frontLink);
-              stsHitMatch.AddLink(backLink);
-            }
-          }
-        }
-
-        Float_t bestWeight = 0.f;
-        for (Int_t iLink = 0; iLink < stsHitMatch.GetNofLinks(); iLink++) {
-          const CbmLink& link = stsHitMatch.GetLink(iLink);
-          Int_t iFile         = link.GetFile();
-          Int_t iEvent        = link.GetEntry();
-          Int_t iIndex        = link.GetIndex();
-
-
-          if (fLegacyEventMode) {
-            iFile  = fvFileEvent.begin()->first;
-            iEvent = fvFileEvent.begin()->second;
-          }
-
-          auto itPoint = fmMCPointsLinksMap.find(CbmL1LinkKey(iIndex + nMvdPoints, iEvent, iFile));
-          assert(itPoint != fmMCPointsLinksMap.cend());
-
-          if (link.GetWeight() > bestWeight) {
-            bestWeight = link.GetWeight();
-            iP         = itPoint->second;
-          }
-        }
-      }  //mach cluster
-
-      if (iP >= 0) {
-        hit.mcPointIds.push_back_no_warning(iP);
-        fvMCPoints[iP].hitIds.push_back_no_warning(iH);
-      }
-
-      fvHitPointIndexes[iH] = iP;
-    }
-
-    if ((hit.Det != 1) || (2 == fStsUseMcHit)) {  // the hit is not from STS
-      int iP = fvHitPointIndexes[iH];
-      if (iP >= 0) {
-        hit.mcPointIds.push_back_no_warning(iP);
-        fvMCPoints[iP].hitIds.push_back_no_warning(iH);
-      }
+    int iP = fvHitPointIndexes[iH];
+    if (iP >= 0) {
+      hit.mcPointIds.push_back_no_warning(iP);
+      fvMCPoints[iP].hitIds.push_back_no_warning(iH);
     }
 
   }  // for hits
diff --git a/reco/L1/catools/CaToolsMcData.cxx b/reco/L1/catools/CaToolsMcData.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..9b534c2ba0a8ff129ae7102d6697df74d179f1a3
--- /dev/null
+++ b/reco/L1/catools/CaToolsMcData.cxx
@@ -0,0 +1,49 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergey Gorbunov, Sergei Zharko [committer] */
+
+/// \file   CaToolsMcData.cxx
+/// \brief  Data structure for internal tracking MC-information (implementation)
+/// \since  23.09.2022
+/// \author S.Zharko <s.zharko@gsi.de>
+
+#include "CaToolsMcData.h"
+
+#include <utility>  // for std::move
+
+using namespace ca::tools;
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+McData::McData() {}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+McData::McData(const McData& /*other*/) {}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+McData::McData(McData&& other) noexcept { this->Swap(other); }
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+McData& McData::operator=(const McData& other)
+{
+  if (this != &other) { McData(other).Swap(*this); }
+  return *this;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+McData& McData::operator=(McData&& other) noexcept
+{
+  if (this != &other) {
+    McData tmp(std::move(other));
+    this->Swap(tmp);
+  }
+  return *this;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void McData::Swap(McData& /*other*/) noexcept {}
diff --git a/reco/L1/catools/CaToolsMcData.h b/reco/L1/catools/CaToolsMcData.h
new file mode 100644
index 0000000000000000000000000000000000000000..c677e72a773d632b5c5301c86b75835d3ad57242
--- /dev/null
+++ b/reco/L1/catools/CaToolsMcData.h
@@ -0,0 +1,57 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergey Gorbunov, Sergei Zharko [committer] */
+
+/// \file   CaToolsMcData.h
+/// \brief  Data structure for internal tracking MC-information (header)
+/// \since  23.09.2022
+/// \author S.Zharko <s.zharko@gsi.de>
+
+#ifndef CaToolsMcData_h
+#define CaToolsMcData_h 1
+
+namespace ca
+{
+  namespace tools
+  {
+    class McData {
+    public:
+      // *********************************
+      // ** Constructors and destructor **
+      // *********************************
+
+      /// Default constructor
+      McData();
+
+      /// Destructor
+      ~McData() = default;
+
+      /// Copy constructor
+      McData(const McData& other);
+
+      /// Move constructor
+      McData(McData&& other) noexcept;
+
+      /// Copy assignment operator
+      McData& operator=(const McData& other);
+
+      /// Move assignment operator
+      McData& operator=(McData&& other) noexcept;
+
+      /// Swap method
+      void Swap(McData& other) noexcept;
+
+
+      // **********************
+      // ** Access functions **
+      // **********************
+
+    private:
+      // **********************
+      // ** Member variables **
+      // **********************
+    };
+  }  // namespace tools
+}  // namespace ca
+
+#endif  // CaToolsMcData_h
diff --git a/reco/L1/catools/CaToolsMcDataManager.cxx b/reco/L1/catools/CaToolsMcDataManager.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..3fae609bb4a6289077b67c7f735a9adce764f7af
--- /dev/null
+++ b/reco/L1/catools/CaToolsMcDataManager.cxx
@@ -0,0 +1,26 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergey Gorbunov, Sergei Zharko [committer] */
+
+/// \file   CaToolsMcDataManager.cxx
+/// \brief  Manager class for handling McData structure (implementation)
+/// \since  23.09.2022
+/// \author S.Zharko <s.zharko@gsi.de>
+
+#include "CaToolsMcDataManager.h"
+
+#include <cassert>
+#include <utility>
+
+#include "CaToolsPerformance.h"
+
+using namespace ca::tools;
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+bool McDataManager::SendMcData(Performance* pPerformance)
+{
+  assert(pPerformance);
+  pPerformance->ReceiveMcData(std::move(fMcData));
+  return true;
+}
diff --git a/reco/L1/catools/CaToolsMcDataManager.h b/reco/L1/catools/CaToolsMcDataManager.h
new file mode 100644
index 0000000000000000000000000000000000000000..0e6cb9ebf604c9ee4272b65788f625c97e42b2f5
--- /dev/null
+++ b/reco/L1/catools/CaToolsMcDataManager.h
@@ -0,0 +1,58 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergey Gorbunov, Sergei Zharko [committer] */
+
+/// \file   CaToolsMcDataManager.h
+/// \brief  Manager class for handling McData structure (header)
+/// \since  23.09.2022
+/// \author S.Zharko <s.zharko@gsi.de>
+
+#ifndef CaToolsMcDataManager_h
+#define CaToolsMcDataManager_h 1
+
+#include "CaToolsMcData.h"
+
+namespace ca
+{
+  namespace tools
+  {
+    class Performance;
+    class McDataManager {
+    public:
+      // *********************************
+      // ** Constructors and destructor **
+      // *********************************
+
+      /// Default constructor
+      McDataManager() {}
+
+      /// Destructor
+      ~McDataManager() = default;
+
+      /// Copy constructor
+      McDataManager(const McDataManager&) = delete;
+
+      /// Move constructor
+      McDataManager(McDataManager&&) = delete;
+
+      /// Copy assignment operator
+      McDataManager& operator=(const McDataManager&) = delete;
+
+      /// Move assignment operator
+      McDataManager& operator=(McDataManager&&) = delete;
+
+      /// Sends (moves) MC data object to the destination Performance instance
+      /// \param  pPerformance Pointer to the destination Performance instance
+      /// \return Success flag
+      bool SendMcData(Performance* pPerformance);
+
+    private:
+      // **********************
+      // ** Member variables **
+      // **********************
+      McData fMcData {};  ///< Object with internal MC data
+    };
+  }  // namespace tools
+}  // namespace ca
+
+#endif  // CaToolsMcDataManager_h
diff --git a/reco/L1/catools/CaToolsPerformance.cxx b/reco/L1/catools/CaToolsPerformance.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..37fc72ebee3144345880339736901868b8d3690a
--- /dev/null
+++ b/reco/L1/catools/CaToolsPerformance.cxx
@@ -0,0 +1,21 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergey Gorbunov, Sergei Zharko [committer] */
+
+/// \file   CaToolsPerformance.h
+/// \brief  Tracking performance class (implementation)
+/// \since  23.09.2022
+/// \author S.Zharko <s.zharko@gsi.de>
+
+#include "CaToolsPerformance.h"
+
+#include <utility>  // for std::move
+
+using namespace ca::tools;
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void Performance::ReceiveMcData(McData&& mcData) { fMcData = std::move(mcData); }
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
diff --git a/reco/L1/catools/CaToolsPerformance.h b/reco/L1/catools/CaToolsPerformance.h
new file mode 100644
index 0000000000000000000000000000000000000000..05d660bbc52451a2451a2941247b0320a30ab726
--- /dev/null
+++ b/reco/L1/catools/CaToolsPerformance.h
@@ -0,0 +1,64 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergey Gorbunov, Sergei Zharko [committer] */
+
+/// \file   CaToolsPerformance.h
+/// \brief  Tracking performance class (header)
+/// \since  23.09.2022
+/// \author S.Zharko <s.zharko@gsi.de>
+
+#ifndef CaToolsPerformance_h
+#define CaToolsPerformance_h 1
+
+#include "CaToolsMcData.h"
+
+class L1Parameters;
+
+namespace ca
+{
+  namespace tools
+  {
+    /// Class ca::tools::Performance defines CA tracking internal performance measurement
+    ///
+    class Performance {
+    public:
+      // *****************************************
+      // **     Constructors and destructor     **
+      // *****************************************
+
+
+      /// Default constructor
+      Performance() = default;
+
+      /// Destructor
+      ~Performance() = default;
+
+      /// Copy constructor
+      Performance(const Performance& other) = delete;
+
+      /// Move constructor
+      Performance(Performance&& other) = delete;
+
+      /// Copy assignment operator
+      Performance& operator=(const Performance& other) = delete;
+
+      /// Move assignment operator
+      Performance& operator=(Performance&& other) = delete;
+
+
+      // ***********************
+      // **     Accessors     **
+      // ***********************
+
+      /// Receives MC data object from McDataManager
+      void ReceiveMcData(McData&& mcData);
+
+
+    private:
+      const L1Parameters* fpParameters = nullptr;  ///< Instance of the tracking core class parameters
+      McData fMcData                   = {};       ///< Object of MC data
+    };
+  }  // namespace tools
+}  // namespace ca
+
+#endif  // CaToolsPerformance_h