diff --git a/force_bdss/base_extension_plugin.py b/force_bdss/base_extension_plugin.py
index 4a9915b0b5fa395d5cefbb742b26a9cc4943a9f1..86c69916b235d93560271bc6275ca20c4d4b1785 100644
--- a/force_bdss/base_extension_plugin.py
+++ b/force_bdss/base_extension_plugin.py
@@ -17,7 +17,7 @@ class BaseExtensionPlugin(Plugin):
     specific trait you want to populate. For example::
 
         class MyPlugin(BaseExtensionPlugin):
-            def _data_source_bundles(self):
+            def _data_source_bundles_default(self):
                 return [MyDataSourceBundle1(),
                         MyDataSourceBundle2()]
     """
@@ -39,3 +39,8 @@ class BaseExtensionPlugin(Plugin):
         IKPICalculatorBundle,
         contributes_to=ExtensionPointID.KPI_CALCULATOR_BUNDLES
     )
+
+    notification_listener_bundles = List(
+        INotificationListenerBundle,
+        contributes_to=ExtensionPointID.NOTIFICATION_LISTENER_BUNDLES
+    )
diff --git a/force_bdss/bundle_registry_plugin.py b/force_bdss/bundle_registry_plugin.py
index 44e7d4808f6e58429dc1efa566b90d3fd0afa90e..e3a1176697ef5b86e76a437e1512b246bc25585d 100644
--- a/force_bdss/bundle_registry_plugin.py
+++ b/force_bdss/bundle_registry_plugin.py
@@ -3,6 +3,8 @@ from envisage.plugin import Plugin
 from traits.api import List
 
 from force_bdss.ids import ExtensionPointID
+from force_bdss.notification_listeners.i_notification_listener_bundle import \
+    INotificationListenerBundle
 from .data_sources.i_data_source_bundle import (
     IDataSourceBundle)
 from .kpi.i_kpi_calculator_bundle import IKPICalculatorBundle
@@ -43,6 +45,11 @@ class BundleRegistryPlugin(Plugin):
         List(IKPICalculatorBundle),
         id=ExtensionPointID.KPI_CALCULATOR_BUNDLES)
 
+    notification_listener_bundles = ExtensionPoint(
+        List(INotificationListenerBundle),
+        id=ExtensionPointID.NOTIFICATION_LISTENER_BUNDLE
+    )
+
     def data_source_bundle_by_id(self, id):
         """Finds a given data source bundle by means of its id.
         The ID is as obtained by the function bundle_id() in the
@@ -136,3 +143,25 @@ class BundleRegistryPlugin(Plugin):
 
         raise KeyError("Requested MCO parameter {}:{} but don't know"
                        " how to find it.".format(mco_id, parameter_id))
+
+    def notification_listener_bundle_by_id(self, id):
+        """Finds a given notification listener by means of its id.
+        The ID is as obtained by the function bundle_id() in the
+        plugin api.
+
+        Parameters
+        ----------
+        id: str
+            The identifier returned by the bundle_id() function.
+
+        Raises
+        ------
+        KeyError: if the entry is not found.
+        """
+        for nl in self.notification_listener_bundles:
+            if nl.id == id:
+                return nl
+
+        raise KeyError(
+            "Requested notification listener {} but don't know how "
+            "to find it.".format(id))
diff --git a/force_bdss/core_mco_driver.py b/force_bdss/core_mco_driver.py
index da740f9d99e0e6083247b36568c56a866b28227d..ea6b4ca0e7e0cc782b2bce2519446a2a127ea7bb 100644
--- a/force_bdss/core_mco_driver.py
+++ b/force_bdss/core_mco_driver.py
@@ -2,8 +2,9 @@ from __future__ import print_function
 
 import sys
 
-from traits.api import on_trait_change
+from traits.api import on_trait_change, Instance
 
+from force_bdss.mco.base_mco import BaseMCO
 from .ids import plugin_id
 from .base_core_driver import BaseCoreDriver
 from .io.workflow_reader import (
@@ -20,6 +21,10 @@ class CoreMCODriver(BaseCoreDriver):
     """
     id = CORE_MCO_DRIVER_ID
 
+    mco = Instance(BaseMCO, allow_none=True)
+
+    listeners = Instance(BaseNotificationListener)
+
     @on_trait_change("application:started")
     def application_started(self):
         try:
@@ -30,5 +35,6 @@ class CoreMCODriver(BaseCoreDriver):
 
         mco_model = workflow.mco
         mco_bundle = mco_model.bundle
-        mco = mco_bundle.create_optimizer()
-        mco.run(mco_model)
+        self.mco = mco_bundle.create_optimizer()
+        self.mco.run(mco_model)
+
diff --git a/force_bdss/core_plugins/dummy/ui_notification_listener/__init__.py b/force_bdss/core_plugins/dummy/ui_notification_listener/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/force_bdss/mco/base_mco.py b/force_bdss/mco/base_mco.py
index d2afbec85a54984a41b2fecd733b775d8ff5b14a..893c6b2fceef94d811359adb0a2dcb69e30f98ed 100644
--- a/force_bdss/mco/base_mco.py
+++ b/force_bdss/mco/base_mco.py
@@ -1,6 +1,6 @@
 import abc
 
-from traits.api import ABCHasStrictTraits, Instance
+from traits.api import ABCHasStrictTraits, Instance, Event
 
 from .i_mco_bundle import IMCOBundle
 
@@ -13,6 +13,12 @@ class BaseMCO(ABCHasStrictTraits):
     #: A reference to the bundle
     bundle = Instance(IMCOBundle)
 
+    started = Event()
+
+    finished = Event()
+
+    progress = Event()
+
     def __init__(self, bundle, *args, **kwargs):
         """Initializes the MCO.
 
diff --git a/force_bdss/notification_listeners/__init__.py b/force_bdss/notification_listeners/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/force_bdss/notification_listeners/i_notification_listener_bundle.py b/force_bdss/notification_listeners/i_notification_listener_bundle.py
new file mode 100644
index 0000000000000000000000000000000000000000..2693dec9cbd4fea31233d57708e82212be0f94c3
--- /dev/null
+++ b/force_bdss/notification_listeners/i_notification_listener_bundle.py
@@ -0,0 +1,21 @@
+from traits.api import Interface, String, Instance
+from envisage.plugin import Plugin
+
+
+class INotificationListenerBundle(Interface):
+    """Envisage required interface for the BaseNotificationListenerBundle.
+    You should not need to use this directly.
+
+    Refer to the BaseNotificationListenerBundle for documentation.
+    """
+    id = String()
+
+    name = String()
+
+    plugin = Instance(Plugin)
+
+    def create_object(self):
+        """"""
+
+    def create_model(self, model_data=None):
+        """"""