diff --git a/docs/upgrading.md b/docs/upgrading.md
index e9e17239d50049..8e77cc3afe38ba 100644
--- a/docs/upgrading.md
+++ b/docs/upgrading.md
@@ -107,3 +107,87 @@ To use default attribute persistence, you need to pass in a
 `PersistentStorageDelegate` to `CodegenDataModelProviderInstance`. See example
 changes in [36658](https://github.com/project-chip/connectedhomeip/pull/36658)
 ).
+
+### Decoupling of Command Handler Interface from Ember
+
+#### EnumerateGeneratedCommands
+
+Changed the old callback based iteration, into a ListBuilder based approach for
+the Enumeration of Generated Commands
+
+`CommandHandlerInterface::EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context)`
+becomes
+`CommandHandlerInterface::EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, ListBuilder<CommandId> & builder)`
+
+Changes for implementation
+
+-   old
+
+```cpp
+   for (auto && cmd : { ScanNetworksResponse::Id, NetworkConfigResponse::Id, ConnectNetworkResponse::Id })
+   {
+       VerifyOrExit(callback(cmd, context) == Loop::Continue, /**/);
+   }
+```
+
+-   new
+
+```cpp
+   ReturnErrorOnFailure(
+        builder.AppendElements({ ScanNetworksResponse::Id, NetworkConfigResponse::Id, ConnectNetworkResponse::Id })
+   )
+```
+
+#### EnumerateAcceptedCommands
+
+Expanded `EnumerateAcceptedCommands` Interface to provide the Access Information
+(Attributes and Qualities) using a ListBuilder
+
+`CommandHandlerInterface::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context)`
+becomes
+`CommandHandlerInterface::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, ListBuilder<AcceptedCommandEntry> & builder)`
+
+Changes for implementation:
+
+-   Old
+
+```cpp
+    for (auto && cmd : {
+             Disable::Id,
+             EnableCharging::Id,
+         })
+    {
+        VerifyOrExit(callback(cmd, context) == Loop::Continue, /**/);
+    }
+
+    if (HasFeature(Feature::kV2x))
+    {
+        VerifyOrExit(callback(EnableDischarging::Id, context) == Loop::Continue, /**/);
+    }
+```
+
+-   new
+
+```cpp
+    using QF   = DataModel::CommandQualityFlags;
+    using Priv = Access::Privilege;
+
+    ReturnErrorOnFailure(builder.AppendElements({
+        { Disable::Id,        QF::kTimed, Priv::kOperate },
+        { EnableCharging::Id, QF::kTimed, Priv::kOperate },
+    }));
+
+    if (HasFeature(Feature::kV2x))
+    {
+        ReturnErrorOnFailure(builder.EnsureAppendCapacity(1));
+        ReturnErrorOnFailure(
+            builder.Append({ EnableDischarging::Id, QF::kTimed, Priv::kOperate})
+        );
+    }
+
+```
+
+Important Notes:
+
+Use `EnsureAppendCapacity` before `ListBuilder::Append` to prevent buffer
+overflow when appending a single element, this function never allocates.
diff --git a/src/app/CommandHandlerInterface.h b/src/app/CommandHandlerInterface.h
index 4146556779756c..47cedcc5c8cfdf 100644
--- a/src/app/CommandHandlerInterface.h
+++ b/src/app/CommandHandlerInterface.h
@@ -21,6 +21,8 @@
 #include <app/CommandHandler.h>
 #include <app/ConcreteClusterPath.h>
 #include <app/ConcreteCommandPath.h>
+#include <app/data-model-provider/MetadataList.h>
+#include <app/data-model-provider/MetadataTypes.h>
 #include <app/data-model/Decode.h>
 #include <app/data-model/List.h> // So we can encode lists
 #include <lib/core/DataModelTypes.h>
@@ -28,7 +30,6 @@
 
 namespace chip {
 namespace app {
-
 /*
  * This interface permits applications to register a server-side command handler
  * at run-time for a given cluster. The handler can either be configured to handle all endpoints
@@ -122,7 +123,8 @@ class CommandHandlerInterface
      * This is used by callbacks that just look for a particular value in the
      * list.
      */
-    virtual CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context)
+    virtual CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster,
+                                                 DataModel::ListBuilder<DataModel::AcceptedCommandEntry> & builder)
     {
         return CHIP_ERROR_NOT_IMPLEMENTED;
     }
@@ -146,7 +148,7 @@ class CommandHandlerInterface
      * This is used by callbacks that just look for a particular value in the
      * list.
      */
-    virtual CHIP_ERROR EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context)
+    virtual CHIP_ERROR EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, DataModel::ListBuilder<CommandId> & builder)
     {
         return CHIP_ERROR_NOT_IMPLEMENTED;
     }
diff --git a/src/app/clusters/device-energy-management-server/device-energy-management-server.cpp b/src/app/clusters/device-energy-management-server/device-energy-management-server.cpp
index 0b7205dd83a33a..8791a842676711 100644
--- a/src/app/clusters/device-energy-management-server/device-energy-management-server.cpp
+++ b/src/app/clusters/device-energy-management-server/device-energy-management-server.cpp
@@ -104,49 +104,51 @@ CHIP_ERROR Instance::Read(const ConcreteReadAttributePath & aPath, AttributeValu
 }
 
 // CommandHandlerInterface
-CHIP_ERROR Instance::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context)
+CHIP_ERROR Instance::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster,
+                                               DataModel::ListBuilder<DataModel::AcceptedCommandEntry> & builder)
 {
     using namespace Commands;
+    using Priv = Access::Privilege;
+
+    ReturnErrorOnFailure(builder.EnsureAppendCapacity(8)); // Ensure we have capacity for all possible commands
 
     if (HasFeature(Feature::kPowerAdjustment))
     {
-        for (auto && cmd : {
-                 PowerAdjustRequest::Id,
-                 CancelPowerAdjustRequest::Id,
-             })
-        {
-            VerifyOrExit(callback(cmd, context) == Loop::Continue, /**/);
-        }
+        ReturnErrorOnFailure(builder.AppendElements({
+            { PowerAdjustRequest::Id, {}, Priv::kOperate },      //
+            { CancelPowerAdjustRequest::Id, {}, Priv::kOperate } //
+        }));
     }
 
     if (HasFeature(Feature::kStartTimeAdjustment))
     {
-        VerifyOrExit(callback(StartTimeAdjustRequest::Id, context) == Loop::Continue, /**/);
+        ReturnErrorOnFailure(builder.Append({ StartTimeAdjustRequest::Id, {}, Priv::kOperate }));
     }
 
     if (HasFeature(Feature::kPausable))
     {
-        VerifyOrExit(callback(PauseRequest::Id, context) == Loop::Continue, /**/);
-        VerifyOrExit(callback(ResumeRequest::Id, context) == Loop::Continue, /**/);
+        ReturnErrorOnFailure(builder.AppendElements({
+            { PauseRequest::Id, {}, Priv::kOperate }, //
+            { ResumeRequest::Id, {}, Priv::kOperate } //
+        }));
     }
 
     if (HasFeature(Feature::kForecastAdjustment))
     {
-        VerifyOrExit(callback(ModifyForecastRequest::Id, context) == Loop::Continue, /**/);
+        ReturnErrorOnFailure(builder.Append({ ModifyForecastRequest::Id, {}, Priv::kOperate }));
     }
 
     if (HasFeature(Feature::kConstraintBasedAdjustment))
     {
-        VerifyOrExit(callback(RequestConstraintBasedForecast::Id, context) == Loop::Continue, /**/);
+        ReturnErrorOnFailure(builder.Append({ RequestConstraintBasedForecast::Id, {}, Priv::kOperate }));
     }
 
     if (HasFeature(Feature::kStartTimeAdjustment) || HasFeature(Feature::kForecastAdjustment) ||
         HasFeature(Feature::kConstraintBasedAdjustment))
     {
-        VerifyOrExit(callback(CancelRequest::Id, context) == Loop::Continue, /**/);
+        ReturnErrorOnFailure(builder.Append({ CancelRequest::Id, {}, Priv::kOperate }));
     }
 
-exit:
     return CHIP_NO_ERROR;
 }
 
diff --git a/src/app/clusters/device-energy-management-server/device-energy-management-server.h b/src/app/clusters/device-energy-management-server/device-energy-management-server.h
index c58e5c5a73743a..069f1c1b1965e4 100644
--- a/src/app/clusters/device-energy-management-server/device-energy-management-server.h
+++ b/src/app/clusters/device-energy-management-server/device-energy-management-server.h
@@ -235,7 +235,8 @@ class Instance : public AttributeAccessInterface, public CommandHandlerInterface
 
     // CommandHandlerInterface
     void InvokeCommand(HandlerContext & handlerContext) override;
-    CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override;
+    CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster,
+                                         DataModel::ListBuilder<DataModel::AcceptedCommandEntry> & builder) override;
 
     Protocols::InteractionModel::Status CheckOptOutAllowsRequest(AdjustmentCauseEnum adjustmentCause);
     void HandlePowerAdjustRequest(HandlerContext & ctx, const Commands::PowerAdjustRequest::DecodableType & commandData);
diff --git a/src/app/clusters/energy-evse-server/energy-evse-server.cpp b/src/app/clusters/energy-evse-server/energy-evse-server.cpp
index d4ae59307cfea1..a598bf7428da4c 100644
--- a/src/app/clusters/energy-evse-server/energy-evse-server.cpp
+++ b/src/app/clusters/energy-evse-server/energy-evse-server.cpp
@@ -182,41 +182,37 @@ CHIP_ERROR Instance::Write(const ConcreteDataAttributePath & aPath, AttributeVal
 }
 
 // CommandHandlerInterface
-CHIP_ERROR Instance::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context)
+CHIP_ERROR Instance::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster,
+                                               DataModel::ListBuilder<DataModel::AcceptedCommandEntry> & builder)
 {
     using namespace Commands;
+    using QF   = DataModel::CommandQualityFlags;
+    using Priv = Access::Privilege;
+    ReturnErrorOnFailure(builder.EnsureAppendCapacity(7));
 
-    for (auto && cmd : {
-             Disable::Id,
-             EnableCharging::Id,
-         })
-    {
-        VerifyOrExit(callback(cmd, context) == Loop::Continue, /**/);
-    }
+    ReturnErrorOnFailure(builder.AppendElements({
+        { Disable::Id, QF::kTimed, Priv::kOperate },        //
+        { EnableCharging::Id, QF::kTimed, Priv::kOperate }, //
+    }));
 
     if (HasFeature(Feature::kV2x))
     {
-        VerifyOrExit(callback(EnableDischarging::Id, context) == Loop::Continue, /**/);
+        ReturnErrorOnFailure(builder.Append({ EnableDischarging::Id, QF::kTimed, Priv::kOperate }));
     }
 
     if (HasFeature(Feature::kChargingPreferences))
     {
-        for (auto && cmd : {
-                 SetTargets::Id,
-                 GetTargets::Id,
-                 ClearTargets::Id,
-             })
-        {
-            VerifyOrExit(callback(cmd, context) == Loop::Continue, /**/);
-        }
+        ReturnErrorOnFailure(builder.AppendElements({
+            { SetTargets::Id, QF::kTimed, Priv::kOperate },   //
+            { GetTargets::Id, QF::kTimed, Priv::kOperate },   //
+            { ClearTargets::Id, QF::kTimed, Priv::kOperate }, //
+        }));
     }
 
     if (SupportsOptCmd(OptionalCommands::kSupportsStartDiagnostics))
     {
-        callback(StartDiagnostics::Id, context);
+        ReturnErrorOnFailure(builder.Append({ StartDiagnostics::Id, QF::kTimed, Priv::kOperate }));
     }
-
-exit:
     return CHIP_NO_ERROR;
 }
 
diff --git a/src/app/clusters/energy-evse-server/energy-evse-server.h b/src/app/clusters/energy-evse-server/energy-evse-server.h
index 979e44c040a17b..6031eb8ac76a5a 100644
--- a/src/app/clusters/energy-evse-server/energy-evse-server.h
+++ b/src/app/clusters/energy-evse-server/energy-evse-server.h
@@ -200,7 +200,8 @@ class Instance : public AttributeAccessInterface, public CommandHandlerInterface
 
     // CommandHandlerInterface
     void InvokeCommand(HandlerContext & handlerContext) override;
-    CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override;
+    CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster,
+                                         DataModel::ListBuilder<DataModel::AcceptedCommandEntry> & builder) override;
 
     void HandleDisable(HandlerContext & ctx, const Commands::Disable::DecodableType & commandData);
     void HandleEnableCharging(HandlerContext & ctx, const Commands::EnableCharging::DecodableType & commandData);
diff --git a/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp b/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp
index 5d823d0cafe3cb..1fa83ffbf43ac2 100644
--- a/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp
+++ b/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp
@@ -16,7 +16,6 @@
  *
  */
 
-#include "app/data-model-provider/MetadataList.h"
 #include <app-common/zap-generated/attributes/Accessors.h>
 #include <app/AttributeAccessInterfaceRegistry.h>
 #include <app/CommandHandlerInterfaceRegistry.h>
@@ -24,6 +23,7 @@
 #include <app/InteractionModelEngine.h>
 #include <app/clusters/microwave-oven-control-server/microwave-oven-control-server.h>
 #include <app/clusters/mode-base-server/mode-base-server.h>
+#include <app/data-model-provider/MetadataList.h>
 #include <app/data-model-provider/MetadataTypes.h>
 #include <app/reporting/reporting.h>
 #include <app/util/attribute-storage.h>
diff --git a/src/app/clusters/network-commissioning/network-commissioning.cpp b/src/app/clusters/network-commissioning/network-commissioning.cpp
index ea73b8ff23d9eb..4fa6d541b4709b 100644
--- a/src/app/clusters/network-commissioning/network-commissioning.cpp
+++ b/src/app/clusters/network-commissioning/network-commissioning.cpp
@@ -1360,64 +1360,56 @@ void Instance::OnFailSafeTimerExpired()
     }
 }
 
-CHIP_ERROR Instance::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context)
+CHIP_ERROR Instance::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster,
+                                               DataModel::ListBuilder<DataModel::AcceptedCommandEntry> & builder)
 {
     using namespace Clusters::NetworkCommissioning::Commands;
+    using Priv = Access::Privilege;
 
-    if (mFeatureFlags.Has(Feature::kThreadNetworkInterface))
-    {
-        for (auto && cmd : {
-                 ScanNetworks::Id,
-                 AddOrUpdateThreadNetwork::Id,
-                 RemoveNetwork::Id,
-                 ConnectNetwork::Id,
-                 ReorderNetwork::Id,
-             })
-        {
-            VerifyOrExit(callback(cmd, context) == Loop::Continue, /**/);
-        }
-    }
-    else if (mFeatureFlags.Has(Feature::kWiFiNetworkInterface))
+    static constexpr size_t kNetworkCommands = 7; // Count of max possible commands assuming all features
+    ReturnErrorOnFailure(builder.EnsureAppendCapacity(kNetworkCommands));
+
+    bool hasThread = mFeatureFlags.Has(Feature::kThreadNetworkInterface);
+    bool hasWifi   = mFeatureFlags.Has(Feature::kWiFiNetworkInterface);
+
+    if (hasThread || hasWifi)
     {
-        for (auto && cmd : {
-                 ScanNetworks::Id,
-                 AddOrUpdateWiFiNetwork::Id,
-                 RemoveNetwork::Id,
-                 ConnectNetwork::Id,
-                 ReorderNetwork::Id,
-             })
-        {
-            VerifyOrExit(callback(cmd, context) == Loop::Continue, /**/);
-        }
+        ReturnErrorOnFailure(builder.AppendElements({
+            { ScanNetworks::Id, {}, Priv::kAdminister },   //
+            { RemoveNetwork::Id, {}, Priv::kAdminister },  //
+            { ConnectNetwork::Id, {}, Priv::kAdminister }, //
+            { ReorderNetwork::Id, {}, Priv::kAdminister }, //
+        }));
+        ReturnErrorOnFailure(
+            builder.Append({ hasThread ? AddOrUpdateThreadNetwork::Id : AddOrUpdateWiFiNetwork::Id, {}, Priv::kAdminister }));
     }
 
     if (mFeatureFlags.Has(Feature::kPerDeviceCredentials))
     {
-        VerifyOrExit(callback(QueryIdentity::Id, context) == Loop::Continue, /**/);
+        ReturnErrorOnFailure(builder.Append({ QueryIdentity::Id, {}, Priv::kAdminister }));
     }
 
-exit:
     return CHIP_NO_ERROR;
 }
 
-CHIP_ERROR Instance::EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context)
+CHIP_ERROR Instance::EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, DataModel::ListBuilder<CommandId> & builder)
 {
     using namespace Clusters::NetworkCommissioning::Commands;
 
+    static constexpr size_t kCommands = 4; // Count of max possible commands assuming all features
+    ReturnErrorOnFailure(builder.EnsureAppendCapacity(kCommands));
+
     if (mFeatureFlags.HasAny(Feature::kWiFiNetworkInterface, Feature::kThreadNetworkInterface))
     {
-        for (auto && cmd : { ScanNetworksResponse::Id, NetworkConfigResponse::Id, ConnectNetworkResponse::Id })
-        {
-            VerifyOrExit(callback(cmd, context) == Loop::Continue, /**/);
-        }
+        ReturnErrorOnFailure(
+            builder.AppendElements({ ScanNetworksResponse::Id, NetworkConfigResponse::Id, ConnectNetworkResponse::Id }));
     }
 
     if (mFeatureFlags.Has(Feature::kPerDeviceCredentials))
     {
-        VerifyOrExit(callback(QueryIdentityResponse::Id, context) == Loop::Continue, /**/);
+        ReturnErrorOnFailure(builder.Append(QueryIdentityResponse::Id));
     }
 
-exit:
     return CHIP_NO_ERROR;
 }
 
diff --git a/src/app/clusters/network-commissioning/network-commissioning.h b/src/app/clusters/network-commissioning/network-commissioning.h
index d727c9b6c2beb9..a3c82bb79105f8 100644
--- a/src/app/clusters/network-commissioning/network-commissioning.h
+++ b/src/app/clusters/network-commissioning/network-commissioning.h
@@ -59,8 +59,10 @@ class Instance : public CommandHandlerInterface,
 
     // CommandHandlerInterface
     void InvokeCommand(HandlerContext & ctx) override;
-    CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override;
-    CHIP_ERROR EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override;
+    CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster,
+                                         DataModel::ListBuilder<DataModel::AcceptedCommandEntry> & builder) override;
+    CHIP_ERROR EnumerateGeneratedCommands(const ConcreteClusterPath & cluster,
+                                          DataModel::ListBuilder<CommandId> & builder) override;
 
     // AttributeAccessInterface
     CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override;
diff --git a/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp b/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp
index 6c581ff72a9e19..6fe79a538fc748 100644
--- a/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp
+++ b/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp
@@ -188,12 +188,16 @@ void Instance::InvokeCommand(HandlerContext & handlerContext)
 
 // List the commands supported by this instance.
 CHIP_ERROR Instance::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster,
-                                               CommandHandlerInterface::CommandIdCallback callback, void * context)
+                                               DataModel::ListBuilder<DataModel::AcceptedCommandEntry> & builder)
 {
+    using namespace ResourceMonitoring::Commands;
+    using Priv = Access::Privilege;
+
     ChipLogDetail(Zcl, "resourcemonitoring: EnumerateAcceptedCommands");
     if (mResetConditionCommandSupported)
     {
-        callback(ResourceMonitoring::Commands::ResetCondition::Id, context);
+        ReturnErrorOnFailure(builder.EnsureAppendCapacity(1));
+        return builder.Append({ ResetCondition::Id, {}, Priv::kOperate });
     }
 
     return CHIP_NO_ERROR;
diff --git a/src/app/clusters/resource-monitoring-server/resource-monitoring-server.h b/src/app/clusters/resource-monitoring-server/resource-monitoring-server.h
index 45c96c39f30074..a43fa4262d2329 100644
--- a/src/app/clusters/resource-monitoring-server/resource-monitoring-server.h
+++ b/src/app/clusters/resource-monitoring-server/resource-monitoring-server.h
@@ -132,7 +132,8 @@ class Instance : public CommandHandlerInterface, public AttributeAccessInterface
 
     // CommandHandlerInterface
     void InvokeCommand(HandlerContext & ctx) override;
-    CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override;
+    CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster,
+                                         DataModel::ListBuilder<DataModel::AcceptedCommandEntry> & builder) override;
 
     // AttributeAccessInterface
     CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override;
diff --git a/src/app/clusters/software-diagnostics-server/software-diagnostics-server.cpp b/src/app/clusters/software-diagnostics-server/software-diagnostics-server.cpp
index 6d78a13d4f6560..9dbcc1af4e0163 100644
--- a/src/app/clusters/software-diagnostics-server/software-diagnostics-server.cpp
+++ b/src/app/clusters/software-diagnostics-server/software-diagnostics-server.cpp
@@ -62,7 +62,8 @@ class SoftwareDiagnosticsCommandHandler : public CommandHandlerInterface
 
     void InvokeCommand(HandlerContext & handlerContext) override;
 
-    CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override;
+    CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster,
+                                         DataModel::ListBuilder<DataModel::AcceptedCommandEntry> & builder) override;
 };
 
 SoftwareDiagnosticsAttrAccess gAttrAccess;
@@ -168,18 +169,19 @@ void SoftwareDiagnosticsCommandHandler::InvokeCommand(HandlerContext & handlerCo
     handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, status);
 }
 
-CHIP_ERROR SoftwareDiagnosticsCommandHandler::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster,
-                                                                        CommandIdCallback callback, void * context)
+CHIP_ERROR
+SoftwareDiagnosticsCommandHandler::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster,
+                                                             DataModel::ListBuilder<DataModel::AcceptedCommandEntry> & builder)
 {
+    using namespace Commands;
+    using Priv = Access::Privilege;
     if (!DeviceLayer::GetDiagnosticDataProvider().SupportsWatermarks())
     {
         // No commmands.
         return CHIP_NO_ERROR;
     }
-
-    callback(Commands::ResetWatermarks::Id, context);
-
-    return CHIP_NO_ERROR;
+    ReturnErrorOnFailure(builder.EnsureAppendCapacity(1));
+    return builder.Append({ ResetWatermarks::Id, {}, Priv::kManage });
 }
 
 } // anonymous namespace
diff --git a/src/app/data-model-provider/MetadataList.h b/src/app/data-model-provider/MetadataList.h
index 24a34c8223f655..569459a929a39a 100644
--- a/src/app/data-model-provider/MetadataList.h
+++ b/src/app/data-model-provider/MetadataList.h
@@ -178,6 +178,12 @@ class ListBuilder : public detail::GenericAppendOnlyBuffer
     /// via `Take`)
     CHIP_ERROR AppendElements(SpanType span) { return AppendElementArrayRaw(span.data(), span.size()); }
 
+    /// Append always attempts to append/extend existing memory.
+    ///
+    /// Automatically attempts to allocate sufficient space to fulfill the element
+    /// requirements.
+    CHIP_ERROR AppendElements(std::initializer_list<T> span) { return AppendElementArrayRaw(span.begin(), span.size()); }
+
     /// Append a single element.
     /// Sufficent append capacity MUST exist.
     CHIP_ERROR Append(const T & value) { return AppendSingleElementRaw(&value); }
diff --git a/src/controller/tests/TestServerCommandDispatch.cpp b/src/controller/tests/TestServerCommandDispatch.cpp
index 17acaa5887c14b..f7f739203aef33 100644
--- a/src/controller/tests/TestServerCommandDispatch.cpp
+++ b/src/controller/tests/TestServerCommandDispatch.cpp
@@ -69,7 +69,8 @@ class TestClusterCommandHandler : public chip::app::CommandHandlerInterface
 
 private:
     void InvokeCommand(chip::app::CommandHandlerInterface::HandlerContext & handlerContext) final;
-    CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) final;
+    CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster,
+                                         DataModel::ListBuilder<DataModel::AcceptedCommandEntry> & builder) final;
 
     bool mOverrideAcceptedCommands = false;
     bool mClaimNoCommands          = false;
@@ -105,8 +106,11 @@ void TestClusterCommandHandler::InvokeCommand(chip::app::CommandHandlerInterface
 }
 
 CHIP_ERROR TestClusterCommandHandler::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster,
-                                                                CommandHandlerInterface::CommandIdCallback callback, void * context)
+                                                                DataModel::ListBuilder<DataModel::AcceptedCommandEntry> & builder)
 {
+    using namespace Clusters::UnitTesting::Commands;
+    using Priv = Access::Privilege;
+
     if (!mOverrideAcceptedCommands)
     {
         return CHIP_ERROR_NOT_IMPLEMENTED;
@@ -117,9 +121,8 @@ CHIP_ERROR TestClusterCommandHandler::EnumerateAcceptedCommands(const ConcreteCl
         return CHIP_NO_ERROR;
     }
 
-    // We just have one command id.
-    callback(Clusters::UnitTesting::Commands::TestSimpleArgumentRequest::Id, context);
-    return CHIP_NO_ERROR;
+    static constexpr DataModel::AcceptedCommandEntry entries[] = { { TestSimpleArgumentRequest::Id, {}, Priv::kOperate } };
+    return builder.ReferenceExisting({ entries, std::size(entries) });
 }
 
 } // namespace
diff --git a/src/data-model-providers/codegen/CodegenDataModelProvider.cpp b/src/data-model-providers/codegen/CodegenDataModelProvider.cpp
index 6913214ac803cc..2e8b51807695c1 100644
--- a/src/data-model-providers/codegen/CodegenDataModelProvider.cpp
+++ b/src/data-model-providers/codegen/CodegenDataModelProvider.cpp
@@ -361,52 +361,9 @@ CHIP_ERROR CodegenDataModelProvider::AcceptedCommands(const ConcreteClusterPath
         CommandHandlerInterfaceRegistry::Instance().GetCommandHandler(path.mEndpointId, path.mClusterId);
     if (interface != nullptr)
     {
-        size_t commandCount = 0;
-
-        CHIP_ERROR err = interface->EnumerateAcceptedCommands(
-            path,
-            [](CommandId id, void * context) -> Loop {
-                *reinterpret_cast<size_t *>(context) += 1;
-                return Loop::Continue;
-            },
-            reinterpret_cast<void *>(&commandCount));
-
-        if (err == CHIP_NO_ERROR)
-        {
-            using EnumerationData = struct
-            {
-                ConcreteCommandPath commandPath;
-                DataModel::ListBuilder<DataModel::AcceptedCommandEntry> * acceptedCommandList;
-                CHIP_ERROR processingError;
-            };
-
-            EnumerationData enumerationData;
-            enumerationData.commandPath         = ConcreteCommandPath(path.mEndpointId, path.mClusterId, kInvalidCommandId);
-            enumerationData.processingError     = CHIP_NO_ERROR;
-            enumerationData.acceptedCommandList = &builder;
-
-            ReturnErrorOnFailure(builder.EnsureAppendCapacity(commandCount));
-
-            ReturnErrorOnFailure(interface->EnumerateAcceptedCommands(
-                path,
-                [](CommandId commandId, void * context) -> Loop {
-                    auto input                    = reinterpret_cast<EnumerationData *>(context);
-                    input->commandPath.mCommandId = commandId;
-                    CHIP_ERROR appendError        = input->acceptedCommandList->Append(AcceptedCommandEntryFor(input->commandPath));
-                    if (appendError != CHIP_NO_ERROR)
-                    {
-                        input->processingError = appendError;
-                        return Loop::Break;
-                    }
-                    return Loop::Continue;
-                },
-                reinterpret_cast<void *>(&enumerationData)));
-            ReturnErrorOnFailure(enumerationData.processingError);
-
-            // the two invocations MUST return the same sizes.
-            VerifyOrReturnError(builder.Size() == commandCount, CHIP_ERROR_INTERNAL);
-            return CHIP_NO_ERROR;
-        }
+        CHIP_ERROR err = interface->EnumerateAcceptedCommands(path, builder);
+        // if enumeration returns CHIP_ERROR_NOT_IMPLEMENTED then continue with normal procesing
+        // otherwise we finished
         VerifyOrReturnError(err == CHIP_ERROR_NOT_IMPLEMENTED, err);
     }
 
@@ -445,49 +402,9 @@ CHIP_ERROR CodegenDataModelProvider::GeneratedCommands(const ConcreteClusterPath
         CommandHandlerInterfaceRegistry::Instance().GetCommandHandler(path.mEndpointId, path.mClusterId);
     if (interface != nullptr)
     {
-        size_t commandCount = 0;
-
-        CHIP_ERROR err = interface->EnumerateGeneratedCommands(
-            path,
-            [](CommandId id, void * context) -> Loop {
-                *reinterpret_cast<size_t *>(context) += 1;
-                return Loop::Continue;
-            },
-            reinterpret_cast<void *>(&commandCount));
-
-        if (err == CHIP_NO_ERROR)
-        {
-            ReturnErrorOnFailure(builder.EnsureAppendCapacity(commandCount));
-
-            using EnumerationData = struct
-            {
-                DataModel::ListBuilder<CommandId> * generatedCommandList;
-                CHIP_ERROR processingError;
-            };
-            EnumerationData enumerationData;
-            enumerationData.processingError      = CHIP_NO_ERROR;
-            enumerationData.generatedCommandList = &builder;
-
-            ReturnErrorOnFailure(interface->EnumerateGeneratedCommands(
-                path,
-                [](CommandId id, void * context) -> Loop {
-                    auto input = reinterpret_cast<EnumerationData *>(context);
-
-                    CHIP_ERROR appendError = input->generatedCommandList->Append(id);
-                    if (appendError != CHIP_NO_ERROR)
-                    {
-                        input->processingError = appendError;
-                        return Loop::Break;
-                    }
-                    return Loop::Continue;
-                },
-                reinterpret_cast<void *>(&enumerationData)));
-            ReturnErrorOnFailure(enumerationData.processingError);
-
-            // the two invocations MUST return the same sizes.
-            VerifyOrReturnError(builder.Size() == commandCount, CHIP_ERROR_INTERNAL);
-            return CHIP_NO_ERROR;
-        }
+        CHIP_ERROR err = interface->EnumerateGeneratedCommands(path, builder);
+        // If enumeration returns CHIP_ERROR_NOT_IMPLEMENTED then continue with normal procesing
+        // otherwise we finished
         VerifyOrReturnError(err == CHIP_ERROR_NOT_IMPLEMENTED, err);
     }
 
diff --git a/src/data-model-providers/codegen/tests/TestCodegenModelViaMocks.cpp b/src/data-model-providers/codegen/tests/TestCodegenModelViaMocks.cpp
index bcd9d64d88d86d..ad503fcb9b2860 100644
--- a/src/data-model-providers/codegen/tests/TestCodegenModelViaMocks.cpp
+++ b/src/data-model-providers/codegen/tests/TestCodegenModelViaMocks.cpp
@@ -282,38 +282,22 @@ class CustomListCommandHandler : public CommandHandlerInterface
 
     void SetHandleCommands(bool handle) { mHandleCommand = handle; }
 
-    CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override
+    CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster,
+                                         DataModel::ListBuilder<DataModel::AcceptedCommandEntry> & builder) override
     {
-        VerifyOrReturnError(mOverrideAccepted, CHIP_ERROR_NOT_IMPLEMENTED);
-
-        for (auto id : mAccepted)
-        {
-            if (callback(id, context) != Loop::Continue)
-            {
-                break;
-            }
-        }
-        return CHIP_NO_ERROR;
+        return builder.ReferenceExisting({ mAccepted.data(), mAccepted.size() });
     }
 
-    CHIP_ERROR EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override
+    CHIP_ERROR EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, DataModel::ListBuilder<CommandId> & builder) override
     {
         VerifyOrReturnError(mOverrideGenerated, CHIP_ERROR_NOT_IMPLEMENTED);
-
-        for (auto id : mGenerated)
-        {
-            if (callback(id, context) != Loop::Continue)
-            {
-                break;
-            }
-        }
-        return CHIP_NO_ERROR;
+        return builder.AppendElements({ mGenerated.data(), mGenerated.size() });
     }
 
     void SetOverrideAccepted(bool o) { mOverrideAccepted = o; }
     void SetOverrideGenerated(bool o) { mOverrideGenerated = o; }
 
-    std::vector<CommandId> & AcceptedVec() { return mAccepted; }
+    std::vector<AcceptedCommandEntry> & AcceptedVec() { return mAccepted; }
     std::vector<CommandId> & GeneratedVec() { return mGenerated; }
 
 private:
@@ -321,7 +305,7 @@ class CustomListCommandHandler : public CommandHandlerInterface
     bool mOverrideGenerated = false;
     bool mHandleCommand     = false;
 
-    std::vector<CommandId> mAccepted;
+    std::vector<AcceptedCommandEntry> mAccepted;
     std::vector<CommandId> mGenerated;
 };
 
@@ -1283,8 +1267,8 @@ TEST_F(TestCodegenModelViaMocks, CommandHandlerInterfaceCommandHandling)
     ASSERT_TRUE(acceptedBuilder.IsEmpty());
 
     // set some overrides
-    handler.AcceptedVec().push_back(1234);
-    handler.AcceptedVec().push_back(999);
+    handler.AcceptedVec().push_back({ 1234, {} });
+    handler.AcceptedVec().push_back({ 999, {} });
 
     handler.GeneratedVec().push_back(33);