diff --git a/examples/tv-app/android/java/AppImpl.cpp b/examples/tv-app/android/java/AppImpl.cpp
index 57418ebeb6c724..12fce44e3e6bae 100644
--- a/examples/tv-app/android/java/AppImpl.cpp
+++ b/examples/tv-app/android/java/AppImpl.cpp
@@ -403,6 +403,19 @@ Access::Privilege ContentAppFactoryImpl::GetVendorPrivilege(uint16_t vendorId)
     return Access::Privilege::kOperate;
 }
 
+std::list<ClusterId> ContentAppFactoryImpl::GetAllowedClusterListForStaticEndpoint(EndpointId endpointId, uint16_t vendorId,
+                                                                                   uint16_t productId)
+{
+    if (endpointId == kLocalVideoPlayerEndpointId)
+    {
+        return { chip::app::Clusters::Descriptor::Id,      chip::app::Clusters::OnOff::Id,
+                 chip::app::Clusters::WakeOnLan::Id,       chip::app::Clusters::MediaPlayback::Id,
+                 chip::app::Clusters::LowPower::Id,        chip::app::Clusters::KeypadInput::Id,
+                 chip::app::Clusters::ContentLauncher::Id, chip::app::Clusters::AudioOutput::Id };
+    }
+    return {};
+}
+
 } // namespace AppPlatform
 } // namespace chip
 
diff --git a/examples/tv-app/android/java/AppImpl.h b/examples/tv-app/android/java/AppImpl.h
index 70ea36f452ac30..df257e081577dc 100644
--- a/examples/tv-app/android/java/AppImpl.h
+++ b/examples/tv-app/android/java/AppImpl.h
@@ -163,6 +163,11 @@ class DLL_EXPORT ContentAppFactoryImpl : public ContentAppFactory
     // When a vendor has admin privileges, it will get access to all clusters on ep1
     Access::Privilege GetVendorPrivilege(uint16_t vendorId) override;
 
+    // Get the cluster list this vendorId/productId should have on static endpoints such as ep1 for casting video clients.
+    // When a vendor has admin privileges, it will get access to all clusters on ep1
+    std::list<ClusterId> GetAllowedClusterListForStaticEndpoint(EndpointId endpointId, uint16_t vendorId,
+                                                                uint16_t productId) override;
+
     void AddAdminVendorId(uint16_t vendorId);
 
     void setContentAppAttributeDelegate(ContentAppAttributeDelegate * attributeDelegate);
diff --git a/examples/tv-app/android/java/TVApp-JNI.cpp b/examples/tv-app/android/java/TVApp-JNI.cpp
index c59893106a8554..405554e073f950 100644
--- a/examples/tv-app/android/java/TVApp-JNI.cpp
+++ b/examples/tv-app/android/java/TVApp-JNI.cpp
@@ -41,9 +41,11 @@
 #include <lib/support/CHIPJNIError.h>
 #include <lib/support/JniReferences.h>
 #include <lib/support/JniTypeWrappers.h>
+#include <zap-generated/CHIPClusters.h>
 
 using namespace chip;
 using namespace chip::app;
+using namespace chip::app::Clusters;
 using namespace chip::AppPlatform;
 using namespace chip::Credentials;
 
@@ -201,9 +203,44 @@ class MyPostCommissioningListener : public PostCommissioningListener
     void CommissioningCompleted(uint16_t vendorId, uint16_t productId, NodeId nodeId, Messaging::ExchangeManager & exchangeMgr,
                                 SessionHandle & sessionHandle) override
     {
+        // read current binding list
+        chip::Controller::BindingCluster cluster(exchangeMgr, sessionHandle, kTargetBindingClusterEndpointId);
 
-        ContentAppPlatform::GetInstance().ManageClientAccess(
-            exchangeMgr, sessionHandle, vendorId, GetDeviceCommissioner()->GetNodeId(), OnSuccessResponse, OnFailureResponse);
+        cacheContext(vendorId, productId, nodeId, exchangeMgr, sessionHandle);
+
+        CHIP_ERROR err =
+            cluster.ReadAttribute<Binding::Attributes::Binding::TypeInfo>(this, OnReadSuccessResponse, OnReadFailureResponse);
+        if (err != CHIP_NO_ERROR)
+        {
+            ChipLogError(Controller, "Failed in reading binding. Error %s", ErrorStr(err));
+            clearContext();
+        }
+    }
+
+    /* Callback when command results in success */
+    static void
+    OnReadSuccessResponse(void * context,
+                          const app::DataModel::DecodableList<Binding::Structs::TargetStruct::DecodableType> & responseData)
+    {
+        ChipLogProgress(Controller, "OnReadSuccessResponse - Binding Read Successfully");
+
+        MyPostCommissioningListener * listener = static_cast<MyPostCommissioningListener *>(context);
+        listener->finishTargetConfiguration(responseData);
+    }
+
+    /* Callback when command results in failure */
+    static void OnReadFailureResponse(void * context, CHIP_ERROR error)
+    {
+        ChipLogProgress(Controller, "OnReadFailureResponse - Binding Read Failed");
+
+        MyPostCommissioningListener * listener = static_cast<MyPostCommissioningListener *>(context);
+        listener->clearContext();
+
+        CommissionerDiscoveryController * cdc = GetCommissionerDiscoveryController();
+        if (cdc != nullptr)
+        {
+            cdc->PostCommissioningFailed(error);
+        }
     }
 
     /* Callback when command results in success */
@@ -227,6 +264,60 @@ class MyPostCommissioningListener : public PostCommissioningListener
             cdc->PostCommissioningFailed(error);
         }
     }
+
+    void
+    finishTargetConfiguration(const app::DataModel::DecodableList<Binding::Structs::TargetStruct::DecodableType> & responseList)
+    {
+        std::vector<app::Clusters::Binding::Structs::TargetStruct::Type> bindings;
+        NodeId localNodeId = GetDeviceCommissioner()->GetNodeId();
+
+        auto iter = responseList.begin();
+        while (iter.Next())
+        {
+            auto & binding = iter.GetValue();
+            ChipLogProgress(Controller, "Binding found nodeId=0x" ChipLogFormatX64 " my nodeId=0x" ChipLogFormatX64,
+                            ChipLogValueX64(binding.node.ValueOr(0)), ChipLogValueX64(localNodeId));
+            if (binding.node.ValueOr(0) != localNodeId)
+            {
+                ChipLogProgress(Controller, "Found a binding for a different node, preserving");
+                bindings.push_back(binding);
+            }
+            else
+            {
+                ChipLogProgress(Controller, "Found a binding for a matching node, dropping");
+            }
+        }
+
+        Optional<SessionHandle> opt   = mSecureSession.Get();
+        SessionHandle & sessionHandle = opt.Value();
+        ContentAppPlatform::GetInstance().ManageClientAccess(*mExchangeMgr, sessionHandle, mVendorId, mProductId, localNodeId,
+                                                             bindings, OnSuccessResponse, OnFailureResponse);
+        clearContext();
+    }
+
+    void cacheContext(uint16_t vendorId, uint16_t productId, NodeId nodeId, Messaging::ExchangeManager & exchangeMgr,
+                      SessionHandle & sessionHandle)
+    {
+        mVendorId    = vendorId;
+        mProductId   = productId;
+        mNodeId      = nodeId;
+        mExchangeMgr = &exchangeMgr;
+        mSecureSession.ShiftToSession(sessionHandle);
+    }
+
+    void clearContext()
+    {
+        mVendorId    = 0;
+        mProductId   = 0;
+        mNodeId      = 0;
+        mExchangeMgr = nullptr;
+        mSecureSession.SessionReleased();
+    }
+    uint16_t mVendorId                        = 0;
+    uint16_t mProductId                       = 0;
+    NodeId mNodeId                            = 0;
+    Messaging::ExchangeManager * mExchangeMgr = nullptr;
+    SessionHolder mSecureSession;
 };
 
 MyPostCommissioningListener gMyPostCommissioningListener;
diff --git a/examples/tv-app/linux/AppImpl.cpp b/examples/tv-app/linux/AppImpl.cpp
index ddfa2dff130bfe..20eff22cef8cdc 100644
--- a/examples/tv-app/linux/AppImpl.cpp
+++ b/examples/tv-app/linux/AppImpl.cpp
@@ -42,9 +42,11 @@
 #include <lib/support/CodeUtils.h>
 #include <lib/support/ZclString.h>
 #include <platform/CHIPDeviceLayer.h>
+#include <zap-generated/CHIPClusters.h>
 
 using namespace chip;
 using namespace chip::AppPlatform;
+using namespace chip::app::Clusters;
 
 #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE
 class MyUserPrompter : public UserPrompter
@@ -89,9 +91,44 @@ class MyPostCommissioningListener : public PostCommissioningListener
     void CommissioningCompleted(uint16_t vendorId, uint16_t productId, NodeId nodeId, Messaging::ExchangeManager & exchangeMgr,
                                 SessionHandle & sessionHandle) override
     {
+        // read current binding list
+        chip::Controller::BindingCluster cluster(exchangeMgr, sessionHandle, kTargetBindingClusterEndpointId);
 
-        ContentAppPlatform::GetInstance().ManageClientAccess(
-            exchangeMgr, sessionHandle, vendorId, GetDeviceCommissioner()->GetNodeId(), OnSuccessResponse, OnFailureResponse);
+        cacheContext(vendorId, productId, nodeId, exchangeMgr, sessionHandle);
+
+        CHIP_ERROR err =
+            cluster.ReadAttribute<Binding::Attributes::Binding::TypeInfo>(this, OnReadSuccessResponse, OnReadFailureResponse);
+        if (err != CHIP_NO_ERROR)
+        {
+            ChipLogError(Controller, "Failed in reading binding. Error %s", ErrorStr(err));
+            clearContext();
+        }
+    }
+
+    /* Callback when command results in success */
+    static void
+    OnReadSuccessResponse(void * context,
+                          const app::DataModel::DecodableList<Binding::Structs::TargetStruct::DecodableType> & responseData)
+    {
+        ChipLogProgress(Controller, "OnReadSuccessResponse - Binding Read Successfully");
+
+        MyPostCommissioningListener * listener = static_cast<MyPostCommissioningListener *>(context);
+        listener->finishTargetConfiguration(responseData);
+    }
+
+    /* Callback when command results in failure */
+    static void OnReadFailureResponse(void * context, CHIP_ERROR error)
+    {
+        ChipLogProgress(Controller, "OnReadFailureResponse - Binding Read Failed");
+
+        MyPostCommissioningListener * listener = static_cast<MyPostCommissioningListener *>(context);
+        listener->clearContext();
+
+        CommissionerDiscoveryController * cdc = GetCommissionerDiscoveryController();
+        if (cdc != nullptr)
+        {
+            cdc->PostCommissioningFailed(error);
+        }
     }
 
     /* Callback when command results in success */
@@ -115,6 +152,60 @@ class MyPostCommissioningListener : public PostCommissioningListener
             cdc->PostCommissioningFailed(error);
         }
     }
+
+    void
+    finishTargetConfiguration(const app::DataModel::DecodableList<Binding::Structs::TargetStruct::DecodableType> & responseList)
+    {
+        std::vector<app::Clusters::Binding::Structs::TargetStruct::Type> bindings;
+        NodeId localNodeId = GetDeviceCommissioner()->GetNodeId();
+
+        auto iter = responseList.begin();
+        while (iter.Next())
+        {
+            auto & binding = iter.GetValue();
+            ChipLogProgress(Controller, "Binding found nodeId=0x" ChipLogFormatX64 " my nodeId=0x" ChipLogFormatX64,
+                            ChipLogValueX64(binding.node.ValueOr(0)), ChipLogValueX64(localNodeId));
+            if (binding.node.ValueOr(0) != localNodeId)
+            {
+                ChipLogProgress(Controller, "Found a binding for a different node, preserving");
+                bindings.push_back(binding);
+            }
+            else
+            {
+                ChipLogProgress(Controller, "Found a binding for a matching node, dropping");
+            }
+        }
+
+        Optional<SessionHandle> opt   = mSecureSession.Get();
+        SessionHandle & sessionHandle = opt.Value();
+        ContentAppPlatform::GetInstance().ManageClientAccess(*mExchangeMgr, sessionHandle, mVendorId, mProductId, localNodeId,
+                                                             bindings, OnSuccessResponse, OnFailureResponse);
+        clearContext();
+    }
+
+    void cacheContext(uint16_t vendorId, uint16_t productId, NodeId nodeId, Messaging::ExchangeManager & exchangeMgr,
+                      SessionHandle & sessionHandle)
+    {
+        mVendorId    = vendorId;
+        mProductId   = productId;
+        mNodeId      = nodeId;
+        mExchangeMgr = &exchangeMgr;
+        mSecureSession.ShiftToSession(sessionHandle);
+    }
+
+    void clearContext()
+    {
+        mVendorId    = 0;
+        mProductId   = 0;
+        mNodeId      = 0;
+        mExchangeMgr = nullptr;
+        mSecureSession.SessionReleased();
+    }
+    uint16_t mVendorId                        = 0;
+    uint16_t mProductId                       = 0;
+    NodeId mNodeId                            = 0;
+    Messaging::ExchangeManager * mExchangeMgr = nullptr;
+    SessionHolder mSecureSession;
 };
 
 MyPostCommissioningListener gMyPostCommissioningListener;
@@ -407,6 +498,19 @@ Access::Privilege ContentAppFactoryImpl::GetVendorPrivilege(uint16_t vendorId)
     return Access::Privilege::kOperate;
 }
 
+std::list<ClusterId> ContentAppFactoryImpl::GetAllowedClusterListForStaticEndpoint(EndpointId endpointId, uint16_t vendorId,
+                                                                                   uint16_t productId)
+{
+    if (endpointId == kLocalVideoPlayerEndpointId)
+    {
+        return { chip::app::Clusters::Descriptor::Id,      chip::app::Clusters::OnOff::Id,
+                 chip::app::Clusters::WakeOnLan::Id,       chip::app::Clusters::MediaPlayback::Id,
+                 chip::app::Clusters::LowPower::Id,        chip::app::Clusters::KeypadInput::Id,
+                 chip::app::Clusters::ContentLauncher::Id, chip::app::Clusters::AudioOutput::Id };
+    }
+    return {};
+}
+
 } // namespace AppPlatform
 } // namespace chip
 
diff --git a/examples/tv-app/linux/AppImpl.h b/examples/tv-app/linux/AppImpl.h
index 68c96d135e0630..46cdb650bd38c8 100644
--- a/examples/tv-app/linux/AppImpl.h
+++ b/examples/tv-app/linux/AppImpl.h
@@ -131,6 +131,11 @@ class DLL_EXPORT ContentAppFactoryImpl : public ContentAppFactory
     // When a vendor has admin privileges, it will get access to all clusters on ep1
     Access::Privilege GetVendorPrivilege(uint16_t vendorId) override;
 
+    // Get the cluster list this vendorId/productId should have on static endpoints such as ep1 for casting video clients.
+    // When a vendor has admin privileges, it will get access to all clusters on ep1
+    std::list<ClusterId> GetAllowedClusterListForStaticEndpoint(EndpointId endpointId, uint16_t vendorId,
+                                                                uint16_t productId) override;
+
     void AddAdminVendorId(uint16_t vendorId);
 
 protected:
diff --git a/src/app/app-platform/ContentAppPlatform.cpp b/src/app/app-platform/ContentAppPlatform.cpp
index 6555e55b04aaba..736cf164fdfede 100644
--- a/src/app/app-platform/ContentAppPlatform.cpp
+++ b/src/app/app-platform/ContentAppPlatform.cpp
@@ -510,27 +510,11 @@ CHIP_ERROR ContentAppPlatform::GetACLEntryIndex(size_t * foundIndex, FabricIndex
     return CHIP_ERROR_NOT_FOUND;
 }
 
-constexpr EndpointId kTargetBindingClusterEndpointId = 0;
-constexpr EndpointId kLocalVideoPlayerEndpointId     = 1;
-constexpr EndpointId kLocalSpeakerEndpointId         = 2;
-constexpr ClusterId kClusterIdDescriptor             = 0x001d;
-constexpr ClusterId kClusterIdOnOff                  = 0x0006;
-constexpr ClusterId kClusterIdWakeOnLAN              = 0x0503;
-// constexpr ClusterId kClusterIdChannel             = 0x0504;
-// constexpr ClusterId kClusterIdTargetNavigator     = 0x0505;
-constexpr ClusterId kClusterIdMediaPlayback = 0x0506;
-// constexpr ClusterId kClusterIdMediaInput          = 0x0507;
-constexpr ClusterId kClusterIdLowPower        = 0x0508;
-constexpr ClusterId kClusterIdKeypadInput     = 0x0509;
-constexpr ClusterId kClusterIdContentLauncher = 0x050a;
-constexpr ClusterId kClusterIdAudioOutput     = 0x050b;
-// constexpr ClusterId kClusterIdApplicationLauncher = 0x050c;
-// constexpr ClusterId kClusterIdAccountLogin        = 0x050e;
-
 // Add ACLs on this device for the given client,
 // and create bindings on the given client so that it knows what it has access to.
 CHIP_ERROR ContentAppPlatform::ManageClientAccess(Messaging::ExchangeManager & exchangeMgr, SessionHandle & sessionHandle,
-                                                  uint16_t targetVendorId, NodeId localNodeId,
+                                                  uint16_t targetVendorId, uint16_t targetProductId, NodeId localNodeId,
+                                                  std::vector<Binding::Structs::TargetStruct::Type> bindings,
                                                   Controller::WriteResponseSuccessCallback successCb,
                                                   Controller::WriteResponseFailureCallback failureCb)
 {
@@ -564,8 +548,6 @@ CHIP_ERROR ContentAppPlatform::ManageClientAccess(Messaging::ExchangeManager & e
     ReturnErrorOnFailure(entry.SetPrivilege(vendorPrivilege));
     ReturnErrorOnFailure(entry.AddSubject(nullptr, subjectNodeId));
 
-    std::vector<Binding::Structs::TargetStruct::Type> bindings;
-
     /**
      * Here we are creating a single ACL entry containing:
      * a) selection of clusters on video player endpoint (8 targets)
@@ -588,6 +570,7 @@ CHIP_ERROR ContentAppPlatform::ManageClientAccess(Messaging::ExchangeManager & e
 
     ChipLogProgress(Controller, "Create video player endpoint ACL and binding");
     {
+        bool hasClusterAccess = false;
         if (vendorPrivilege == Access::Privilege::kAdminister)
         {
             ChipLogProgress(Controller, "ContentAppPlatform::ManageClientAccess Admin privilege granted");
@@ -595,14 +578,14 @@ CHIP_ERROR ContentAppPlatform::ManageClientAccess(Messaging::ExchangeManager & e
             Access::AccessControl::Entry::Target target = { .flags    = Access::AccessControl::Entry::Target::kEndpoint,
                                                             .endpoint = kLocalVideoPlayerEndpointId };
             ReturnErrorOnFailure(entry.AddTarget(nullptr, target));
+            hasClusterAccess = true;
         }
         else
         {
             ChipLogProgress(Controller, "ContentAppPlatform::ManageClientAccess non-Admin privilege granted");
             // a vendor with non-admin privilege gets access to select clusters on ep1
-            std::list<ClusterId> allowedClusterList = { kClusterIdDescriptor,      kClusterIdOnOff,      kClusterIdWakeOnLAN,
-                                                        kClusterIdMediaPlayback,   kClusterIdLowPower,   kClusterIdKeypadInput,
-                                                        kClusterIdContentLauncher, kClusterIdAudioOutput };
+            std::list<ClusterId> allowedClusterList = mContentAppFactory->GetAllowedClusterListForStaticEndpoint(
+                kLocalVideoPlayerEndpointId, targetVendorId, targetProductId);
 
             for (const auto & clusterId : allowedClusterList)
             {
@@ -611,16 +594,21 @@ CHIP_ERROR ContentAppPlatform::ManageClientAccess(Messaging::ExchangeManager & e
                                                                 .cluster  = clusterId,
                                                                 .endpoint = kLocalVideoPlayerEndpointId };
                 ReturnErrorOnFailure(entry.AddTarget(nullptr, target));
+                hasClusterAccess = true;
             }
         }
 
-        bindings.push_back(Binding::Structs::TargetStruct::Type{
-            .node        = MakeOptional(localNodeId),
-            .group       = NullOptional,
-            .endpoint    = MakeOptional(kLocalVideoPlayerEndpointId),
-            .cluster     = NullOptional,
-            .fabricIndex = kUndefinedFabricIndex,
-        });
+        if (hasClusterAccess)
+        {
+            ChipLogProgress(Controller, "ContentAppPlatform::ManageClientAccess adding a binding on ep1");
+            bindings.push_back(Binding::Structs::TargetStruct::Type{
+                .node        = MakeOptional(localNodeId),
+                .group       = NullOptional,
+                .endpoint    = MakeOptional(kLocalVideoPlayerEndpointId),
+                .cluster     = NullOptional,
+                .fabricIndex = kUndefinedFabricIndex,
+            });
+        }
     }
 
     ChipLogProgress(Controller, "Create speaker endpoint ACL and binding");
diff --git a/src/app/app-platform/ContentAppPlatform.h b/src/app/app-platform/ContentAppPlatform.h
index 3744a0fa0edf1d..69248cd431e3c7 100644
--- a/src/app/app-platform/ContentAppPlatform.h
+++ b/src/app/app-platform/ContentAppPlatform.h
@@ -38,6 +38,10 @@ using BindingListType = chip::app::Clusters::Binding::Attributes::Binding::TypeI
 namespace chip {
 namespace AppPlatform {
 
+constexpr EndpointId kTargetBindingClusterEndpointId = 0;
+constexpr EndpointId kLocalVideoPlayerEndpointId     = 1;
+constexpr EndpointId kLocalSpeakerEndpointId         = 2;
+
 class DLL_EXPORT ContentAppFactory
 {
 public:
@@ -63,6 +67,11 @@ class DLL_EXPORT ContentAppFactory
     // and for voice agents, this may be Access::Privilege::kAdminister
     // When a vendor has admin privileges, it will get access to all clusters on ep1
     virtual Access::Privilege GetVendorPrivilege(uint16_t vendorId) = 0;
+
+    // Get the cluster list this vendorId/productId should have on static endpoints such as ep1 for casting video clients.
+    // When a vendor has admin privileges, it will get access to all clusters on ep1
+    virtual std::list<ClusterId> GetAllowedClusterListForStaticEndpoint(EndpointId endpointId, uint16_t vendorId,
+                                                                        uint16_t productId) = 0;
 };
 
 class DLL_EXPORT ContentAppPlatform
@@ -146,14 +155,18 @@ class DLL_EXPORT ContentAppPlatform
      * @param[in] exchangeMgr     Exchange manager to be used to get an exchange context.
      * @param[in] sessionHandle   Reference to an established session.
      * @param[in] targetVendorId  Vendor ID for the target device.
+     * @param[in] targetProductId Product ID for the target device.
      * @param[in] localNodeId     The NodeId for the local device.
+     * @param[in] bindings        Any additional bindings to include. This may include current bindings.
      * @param[in] successCb       The function to be called on success of adding the binding.
      * @param[in] failureCb       The function to be called on failure of adding the binding.
      *
      * @return CHIP_ERROR         CHIP_NO_ERROR on success, or corresponding error
      */
     CHIP_ERROR ManageClientAccess(Messaging::ExchangeManager & exchangeMgr, SessionHandle & sessionHandle, uint16_t targetVendorId,
-                                  NodeId localNodeId, Controller::WriteResponseSuccessCallback successCb,
+                                  uint16_t targetProductId, NodeId localNodeId,
+                                  std::vector<app::Clusters::Binding::Structs::TargetStruct::Type> bindings,
+                                  Controller::WriteResponseSuccessCallback successCb,
                                   Controller::WriteResponseFailureCallback failureCb);
 
 protected: