diff --git a/apack.json b/apack.json
index 173939f22ae373f8127bc4340f3bc7149cf824e4..582c061556e895f031139ed955329c1e06012a19 100644
--- a/apack.json
+++ b/apack.json
@@ -4,7 +4,7 @@
   "description": "Graphical configuration tool for application and libraries based on Zigbee Cluster Library.",
   "path": [".", "node_modules/.bin/", "ZAP.app/Contents/MacOS"],
   "requiredFeatureLevel": "apack.core:9",
-  "featureLevel": 94,
+  "featureLevel": 95,
   "uc.triggerExtension": "zap",
   "executable": {
     "zap:win32.x86_64": {
diff --git a/src-electron/db/db-mapping.js b/src-electron/db/db-mapping.js
index 874c6749e967e836320069a8a62533d686bc48dc..363c47ca061809b1e1167232321a24b3e2e719ac 100644
--- a/src-electron/db/db-mapping.js
+++ b/src-electron/db/db-mapping.js
@@ -179,9 +179,13 @@ exports.map = {
       argPresentIf: x.ARG_PRESENT_IF,
       argCountArg: x.ARG_COUNT_ARG,
       commandArgCount: x.COMMAND_ARGUMENT_COUNT,
+      requiredCommandArgCount: x.REQUIRED_COMMAND_ARGUMENT_COUNT,
+      hasArguments: x.COMMAND_ARGUMENT_COUNT > 0,
+      commandHasRequiredField: x.REQUIRED_COMMAND_ARGUMENT_COUNT > 0,
       argIsNullable: x.ARG_IS_NULLABLE,
       responseRef: x.RESPONSE_REF,
       responseName: x.RESPONSE_NAME,
+      hasSpecificResponse: dbApi.toDbBool(x.RESPONSE_REF),
       isIncoming: x.INCOMING,
       isOutgoing: x.OUTGOING,
       isDefaultResponseEnabled: x.IS_DEFAULT_RESPONSE_ENABLED,
diff --git a/src-electron/db/query-command.js b/src-electron/db/query-command.js
index af5fb1c3dccef7ba479e31641b5296966a181985..2b139a38617bd14ca92c231dd30fc40dbd9598f1 100644
--- a/src-electron/db/query-command.js
+++ b/src-electron/db/query-command.js
@@ -121,7 +121,8 @@ async function selectAllAvailableClusterCommandDetailsFromEndpointTypes(
   let endpointTypeIds = endpointTypes.map((ep) => ep.endpointTypeId).toString()
   let mapFunction = (x) => {
     return {
-      id: x.CLUSTER_ID,
+      clusterId: x.CLUSTER_ID,
+      id: x.COMMAND_ID,
       clusterName: x.CLUSTER_NAME,
       clusterCode: x.CLUSTER_CODE,
       commandMfgCode: x.COMMAND_MANUFACTURER_CODE,
@@ -132,6 +133,9 @@ async function selectAllAvailableClusterCommandDetailsFromEndpointTypes(
       commandName: x.COMMAND_NAME,
       commandSource: x.COMMAND_SOURCE,
       commandCode: x.COMMAND_CODE,
+      code: x.COMMAND_CODE,
+      name: x.COMMAND_NAME,
+      source: x.COMMAND_SOURCE,
       incoming: x.INCOMING,
       outgoing: x.OUTGOING,
       mfgCommandCount: x.MANUFACTURING_SPECIFIC_COMMAND_COUNT,
@@ -153,6 +157,7 @@ SELECT
   ENDPOINT_TYPE_CLUSTER.ENABLED AS CLUSTER_ENABLED,
   COUNT(*) OVER (PARTITION BY CLUSTER.MANUFACTURER_CODE, CLUSTER.NAME, COMMAND.MANUFACTURER_CODE, COMMAND.NAME) AS NO_OF_CLUSTER_SIDES_ENABLED,
   COMMAND.NAME AS COMMAND_NAME,
+  COMMAND.COMMAND_ID,
   COMMAND.SOURCE AS COMMAND_SOURCE,
   COMMAND.CODE AS COMMAND_CODE,
   ENDPOINT_TYPE_COMMAND.INCOMING AS INCOMING,
@@ -921,7 +926,8 @@ SELECT
   COMMAND.RESPONSE_REF,
   COMMAND.RESPONSE_NAME,
   COMMAND.IS_DEFAULT_RESPONSE_ENABLED,
-  COUNT(COMMAND_ARG.COMMAND_REF) AS COMMAND_ARGUMENT_COUNT
+  COUNT(COMMAND_ARG.COMMAND_REF) AS COMMAND_ARGUMENT_COUNT,
+  COUNT(COMMAND_ARG.COMMAND_REF) FILTER (WHERE COMMAND_ARG.IS_OPTIONAL = 0) AS REQUIRED_COMMAND_ARGUMENT_COUNT
 FROM COMMAND
 LEFT JOIN
   COMMAND_ARG
diff --git a/src-electron/db/query-endpoint-type.js b/src-electron/db/query-endpoint-type.js
index f8a7ea2feac69c5bbf77cf0629c291d4beb2d2e2..bd8b0cbbd280d72ca30128d048a8339fe09709b0 100644
--- a/src-electron/db/query-endpoint-type.js
+++ b/src-electron/db/query-endpoint-type.js
@@ -162,7 +162,17 @@ async function selectEndpointType(db, id) {
  * @param {*} endpointTypes
  * @returns Promise that resolves with the data that should go into the external form.
  */
-async function selectAllClustersDetailsFromEndpointTypes(db, endpointTypes) {
+async function selectAllClustersDetailsFromEndpointTypes(
+  db,
+  endpointTypes,
+  options = null
+) {
+  let side = null
+  let endpointClusterSideFilter = 'ENDPOINT_TYPE_CLUSTER.SIDE IS NOT ""'
+  if (options && options.hash.side) {
+    side = options.hash.side.toLowerCase()
+    endpointClusterSideFilter = "ENDPOINT_TYPE_CLUSTER.SIDE = '" + side + "'"
+  }
   let endpointTypeIds = endpointTypes.map((ep) => ep.endpointTypeId).toString()
   let mapFunction = (x) => {
     return {
@@ -205,7 +215,7 @@ ON
 WHERE
   ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_REF IN (${endpointTypeIds})
 AND
-  ENDPOINT_TYPE_CLUSTER.SIDE IS NOT "" AND ENDPOINT_TYPE_CLUSTER.ENABLED = 1
+${endpointClusterSideFilter} AND ENDPOINT_TYPE_CLUSTER.ENABLED = 1
 GROUP BY
   NAME, SIDE
 ${
diff --git a/src-electron/generator/helper-session.js b/src-electron/generator/helper-session.js
index 67efb6b1f114c868fa74ef532c6078153a45db74..f57f3cc6c320be8e183eb002f9342c0fb0850b61 100644
--- a/src-electron/generator/helper-session.js
+++ b/src-electron/generator/helper-session.js
@@ -451,7 +451,8 @@ async function all_user_clusters(options) {
   let clusters =
     await queryEndpointType.selectAllClustersDetailsFromEndpointTypes(
       this.global.db,
-      endpointTypes
+      endpointTypes,
+      options
     )
 
   return templateUtil.collectBlocks(clusters, options, this)
diff --git a/src-electron/generator/helper-zcl.js b/src-electron/generator/helper-zcl.js
index 364cf14234a07fcdf3020925251d73a5556370ad..396e0807af98a0ee3a9018764b699492426e9248 100644
--- a/src-electron/generator/helper-zcl.js
+++ b/src-electron/generator/helper-zcl.js
@@ -405,6 +405,38 @@ function zcl_commands(options) {
   return templateUtil.templatePromise(this.global, promise)
 }
 
+/**
+ * Returns all commands which are command responses.
+ * For eg, If the xml has the following:
+ * <command source="client" code="0x00" name="newCmd" response="newCmdResponse">
+ * then newCmdResponse will be included in the list of commands returned here.
+ *
+ * There are two modes of this helper:
+ * - when used in a global context, it iterates over ALL command responses in
+ * the database.
+ * - when used inside a `zcl_cluster` block helper, it iterates only over the
+ * commands responses for that cluster.
+ * @param {*} options
+ * @returns all command responses
+ */
+async function zcl_command_responses(options) {
+  let packageIds = await templateUtil.ensureZclPackageIds(this)
+  let cmds = null
+  if ('id' in this) {
+    cmds = await queryCommand.selectCommandsByClusterId(
+      this.global.db,
+      this.id,
+      packageIds
+    )
+  } else {
+    cmds = await queryCommand.selectAllCommands(this.global.db, packageIds)
+  }
+  let commandResponses = cmds.map((cmd) => cmd.responseName)
+  let res = cmds.filter((cmd) => commandResponses.includes(cmd.name))
+  let promise = templateUtil.collectBlocks(res, options, this)
+  return templateUtil.templatePromise(this.global, promise)
+}
+
 /**
  * Block helper iterating over all commands with cluster information.
  * Note: Similar to zcl_commands but has cluster information as well.
@@ -2954,3 +2986,4 @@ exports.as_zcl_type_size = as_zcl_type_size
 exports.if_compare = if_compare
 exports.if_is_data_type_signed = if_is_data_type_signed
 exports.as_zcl_data_type_size = as_zcl_data_type_size
+exports.zcl_command_responses = zcl_command_responses
diff --git a/src-electron/generator/matter/app/zap-templates/templates/chip/helper.js b/src-electron/generator/matter/app/zap-templates/templates/chip/helper.js
index 19f3db722c4aab6dfba17932dd4681208df8312e..fdd419b6365e4b35bb6ccb737984a49fdd50b6bb 100644
--- a/src-electron/generator/matter/app/zap-templates/templates/chip/helper.js
+++ b/src-electron/generator/matter/app/zap-templates/templates/chip/helper.js
@@ -752,16 +752,27 @@ const dep = templateUtil.deprecatedHelper;
 //
 exports.chip_clusters = chip_clusters;
 exports.chip_has_clusters = chip_has_clusters;
-exports.chip_client_clusters = chip_client_clusters;
+exports.chip_client_clusters = dep(
+  chip_client_clusters,
+  'chip_client_clusters has been deprecated. Use all_user_clusters with the \
+  side option as client'
+);
 exports.chip_has_client_clusters = chip_has_client_clusters;
 exports.chip_server_clusters = chip_server_clusters;
 exports.chip_has_server_clusters = chip_has_server_clusters;
-exports.chip_cluster_commands = chip_cluster_commands;
-exports.chip_cluster_command_arguments = chip_cluster_command_arguments;
+exports.chip_cluster_commands = dep(
+  chip_cluster_commands,
+  'chip_cluster_commands has been deprecated. Use zcl_commands with source attribute as client'
+);
+exports.chip_cluster_command_arguments = dep(chip_cluster_command_arguments, {
+  to: 'zcl_command_arguments',
+});
 exports.chip_cluster_command_arguments_with_structs_expanded =
   chip_cluster_command_arguments_with_structs_expanded;
 exports.chip_server_global_responses = chip_server_global_responses;
-exports.chip_cluster_responses = chip_cluster_responses;
+exports.chip_cluster_responses = dep(chip_cluster_responses, {
+  to: 'zcl_command_responses',
+});
 exports.chip_cluster_response_arguments = chip_cluster_response_arguments;
 exports.chip_attribute_list_entryTypes = chip_attribute_list_entryTypes;
 exports.chip_server_cluster_attributes = dep(
diff --git a/src-electron/generator/matter/controller/java/templates/helper.js b/src-electron/generator/matter/controller/java/templates/helper.js
index 66c2fed7414978065cd2996288f3b315a7f3b895..50ccf9a600f708043c9f7c56186ccfa2b0392a90 100644
--- a/src-electron/generator/matter/controller/java/templates/helper.js
+++ b/src-electron/generator/matter/controller/java/templates/helper.js
@@ -193,8 +193,7 @@ function convertAttributeCallbackTypeToJavaName(cType) {
 }
 
 /**
- * Note: This helper needs to be used under a block helper which has a
- * reference to clusterId.
+ * Note: This is a util function
  * Available options:
  * - isBoxedJavaType: 0/1 to return string types in different ways
  * - All other options passed to this helper are considered as overrides for
@@ -206,7 +205,12 @@ function convertAttributeCallbackTypeToJavaName(cType) {
  * @param {*} options
  * @returns The corresponding java data type for a zcl data type.
  */
-async function as_underlying_java_zcl_type(type, clusterId, options) {
+async function as_underlying_java_zcl_type_util(
+  type,
+  clusterId,
+  options,
+  context
+) {
   let hash = options.hash;
   // Overwrite any type with the one coming from the template options
   // Eg: {{as_underlying_java_zcl_type type [clusterId] boolean='Boolean'}}
@@ -216,9 +220,9 @@ async function as_underlying_java_zcl_type(type, clusterId, options) {
   }
 
   // Get ZCL Data Type from the db
-  const packageIds = await templateUtil.ensureZclPackageIds(this);
+  const packageIds = await templateUtil.ensureZclPackageIds(context);
   let dataType = await queryZcl.selectDataTypeByNameAndClusterId(
-    this.global.db,
+    context.global.db,
     type,
     clusterId,
     packageIds
@@ -247,7 +251,7 @@ async function as_underlying_java_zcl_type(type, clusterId, options) {
         dataType,
         clusterId,
         packageIds,
-        this
+        context
       );
       if (sizeAndSign.size >= 3) {
         return 'Long';
@@ -268,6 +272,24 @@ async function as_underlying_java_zcl_type(type, clusterId, options) {
   }
 }
 
+/**
+ * Note: This helper needs to be used under a block helper which has a
+ * reference to clusterId.
+ * Available options:
+ * - isBoxedJavaType: 0/1 to return string types in different ways
+ * - All other options passed to this helper are considered as overrides for
+ * zcl types
+ * for eg: (as_underlying_java_zcl_type type clusterId boolean='Boolean')
+ * will return "Boolean" for "boolean" type
+ * @param {*} type
+ * @param {*} clusterId
+ * @param {*} options
+ * @returns The corresponding java data type for a zcl data type.
+ */
+async function as_underlying_java_zcl_type(type, clusterId, options) {
+  return as_underlying_java_zcl_type_util(type, clusterId, options, this);
+}
+
 async function asUnderlyingBasicType(type) {
   const options = { hash: {} };
   let zclType = await zclHelper.asUnderlyingZclType.call(this, type, options);
@@ -295,7 +317,16 @@ async function asJavaType(type, zclType, cluster, options) {
       cluster
     )}Cluster${appHelper.asUpperCamelCase(type)}`;
   } else {
-    classType += asJavaBoxedType(type, zclType);
+    let javaBoxedType = asJavaBoxedType(type, zclType);
+    if (javaBoxedType == 'Object' && options.hash.clusterId) {
+      javaBoxedType = await as_underlying_java_zcl_type_util(
+        type,
+        options.hash.clusterId,
+        options,
+        this
+      );
+    }
+    classType += javaBoxedType;
   }
 
   if (!options.hash.underlyingType) {
diff --git a/src-electron/generator/matter/controller/python/templates/helper.js b/src-electron/generator/matter/controller/python/templates/helper.js
index 1b06f53d8c01e006107b29c996e4fea121de92d4..de12a955c8f0f6f9c46ea76cc0cc9448df975880 100644
--- a/src-electron/generator/matter/controller/python/templates/helper.js
+++ b/src-electron/generator/matter/controller/python/templates/helper.js
@@ -79,7 +79,7 @@ async function as_underlying_python_zcl_type(type, clusterId, options) {
     clusterId,
     packageIds
   );
-  if (type == 'boolean') {
+  if (type && type.toLowerCase() == 'boolean') {
     return 'bool';
   } else if (
     dataType.discriminatorName.toLowerCase() == dbEnum.zclType.bitmap ||