diff --git a/force_bdss/api.py b/force_bdss/api.py
index 828570458e60ba2d9b117fc32f9279b2ec28696d..fa2fddd8cf2847e007b6e89f4c410f7011edc862 100644
--- a/force_bdss/api.py
+++ b/force_bdss/api.py
@@ -21,7 +21,7 @@ from .mco.i_mco_factory import IMCOFactory  # noqa
 from .mco.parameters.base_mco_parameter_factory import BaseMCOParameterFactory  # noqa
 from .mco.parameters.base_mco_parameter import BaseMCOParameter  # noqa
 
-from .mco.events import *  # noqa
+from .core_driver_events import *  # noqa
 
 from .notification_listeners.i_notification_listener_factory import INotificationListenerFactory  # noqa
 from .notification_listeners.base_notification_listener import BaseNotificationListener  # noqa
diff --git a/force_bdss/core_driver_events.py b/force_bdss/core_driver_events.py
new file mode 100644
index 0000000000000000000000000000000000000000..d7b10c0026abc89c296769d93219923e40a140c8
--- /dev/null
+++ b/force_bdss/core_driver_events.py
@@ -0,0 +1,23 @@
+from traits.api import HasStrictTraits, Tuple
+
+
+class BaseDriverEvent(HasStrictTraits):
+    """ Base event for the MCO driver."""
+
+
+class MCOStartEvent(BaseDriverEvent):
+    """ The MCO driver should emit this event when the evaluation starts."""
+    input_names = Tuple()
+    output_names = Tuple()
+
+
+class MCOFinishEvent(BaseDriverEvent):
+    """ The MCO driver should emit this event when the evaluation ends."""
+
+
+class MCOProgressEvent(BaseDriverEvent):
+    """ The MCO driver should emit this event for every new evaluation that has
+    been completed. It carries data about the evaluation, specifically the
+    input data (MCO parameter values) and the resulting output (KPIs)."""
+    input = Tuple()
+    output = Tuple()
diff --git a/force_bdss/core_mco_driver.py b/force_bdss/core_mco_driver.py
index e2678daee1837df4cf8595ee4618008a988c47d3..fb4171427dadcf58e98b7342fef214b6fd375df4 100644
--- a/force_bdss/core_mco_driver.py
+++ b/force_bdss/core_mco_driver.py
@@ -14,6 +14,7 @@ from .io.workflow_reader import (
     InvalidVersionException,
     InvalidFileException
 )
+from .core_driver_events import MCOStartEvent, MCOFinishEvent, MCOProgressEvent
 
 log = logging.getLogger(__name__)
 CORE_MCO_DRIVER_ID = plugin_id("core", "CoreMCODriver")
@@ -50,8 +51,27 @@ class CoreMCODriver(BaseCoreDriver):
         mco_factory = mco_model.factory
         return mco_factory.create_optimizer()
 
-    @on_trait_change("mco:event")
-    def _handle_mco_event(self, event):
+    @on_trait_change("mco:started")
+    def _deliver_start_event(self):
+        output_names = []
+        for kpi in self.workflow.kpi_calculators:
+            output_names.extend(kpi.output_slot_names)
+
+        self._deliver_event(MCOStartEvent(
+            input_names=tuple(p.name for p in self.workflow.mco.parameters),
+            output_names=tuple(output_names)
+        ))
+
+    @on_trait_change("mco:finished")
+    def _deliver_finished_event(self):
+        self._deliver_event(MCOFinishEvent())
+
+    @on_trait_change("mco:new_data")
+    def _deliver_mco_progress_event(self, data):
+        self._deliver_event(MCOProgressEvent(**data))
+
+    def _deliver_event(self, event):
+        """ Delivers an event to the listeners """
         for listener in self.listeners[:]:
             try:
                 listener.deliver(event)
diff --git a/force_bdss/core_plugins/dummy/dummy_dakota/dakota_optimizer.py b/force_bdss/core_plugins/dummy/dummy_dakota/dakota_optimizer.py
index 9f9de5d87192fa818b1bd4e9ae49a510b3489827..96d5fe70a617c0401f72df5e62555c0d602cd7f6 100644
--- a/force_bdss/core_plugins/dummy/dummy_dakota/dakota_optimizer.py
+++ b/force_bdss/core_plugins/dummy/dummy_dakota/dakota_optimizer.py
@@ -4,8 +4,6 @@ import itertools
 import collections
 
 from force_bdss.api import BaseMCO
-from force_bdss.mco.events import MCOStartEvent, MCOFinishEvent, \
-    MCOProgressEvent
 
 
 def rotated_range(start, stop, starting_value):
@@ -18,8 +16,6 @@ def rotated_range(start, stop, starting_value):
 
 class DummyDakotaOptimizer(BaseMCO):
     def run(self, model):
-        self.notify_event(MCOStartEvent())
-
         parameters = model.parameters
 
         values = []
@@ -34,6 +30,7 @@ class DummyDakotaOptimizer(BaseMCO):
 
         application = self.factory.plugin.application
 
+        self.started = True
         for value in value_iterator:
             ps = subprocess.Popen(
                 [sys.argv[0],
@@ -45,9 +42,9 @@ class DummyDakotaOptimizer(BaseMCO):
             out = ps.communicate(
                 " ".join([str(v) for v in value]).encode("utf-8"))
             out_data = out[0].decode("utf-8").split()
-            self.notify_event(MCOProgressEvent(
-                input=tuple(value),
-                output=tuple(out_data),
-            ))
+            self.new_data = {
+                'input': tuple(value),
+                'output': tuple(out_data)
+            }
 
-        self.notify_event(MCOFinishEvent())
+        self.finished = True
diff --git a/force_bdss/mco/base_mco.py b/force_bdss/mco/base_mco.py
index ae9d89b72092c962ebc7f6415d3fa8166613711e..91918c6bf2fd262eed4eecab8d5c42c213c5c5bc 100644
--- a/force_bdss/mco/base_mco.py
+++ b/force_bdss/mco/base_mco.py
@@ -1,8 +1,7 @@
 import abc
 
-from traits.api import ABCHasStrictTraits, Instance, Event
+from traits.api import ABCHasStrictTraits, Instance, Event, Dict, Str, Tuple
 
-from force_bdss.mco.events import BaseMCOEvent
 from .i_mco_factory import IMCOFactory
 
 
@@ -14,8 +13,14 @@ class BaseMCO(ABCHasStrictTraits):
     #: A reference to the factory
     factory = Instance(IMCOFactory)
 
-    #: Triggered when an event occurs.
-    event = Event(BaseMCOEvent)
+    #: Triggered when the evaluation started.
+    started = Event()
+
+    #: Triggered when the evaluation finished
+    finished = Event()
+
+    # Event triggered when the mco wants to send new data to listeners
+    new_data = Event(Dict(Str(), Tuple()))
 
     def __init__(self, factory, *args, **kwargs):
         """Initializes the MCO.
@@ -39,18 +44,3 @@ class BaseMCO(ABCHasStrictTraits):
             An instance of the model information, as created from
             create_model()
         """
-
-    def notify_event(self, event):
-        """Method based interface to deliver an event, instead of
-        assignment to traits.
-
-        Sends the event, synchronously. When the routine returns,
-        listeners have been fully informed (they might, however, handle
-        the event asynchronously at their convenience)
-
-        Parameters
-        ----------
-        event: BaseMCOEvent
-            The event to deliver.
-        """
-        self.event = event
diff --git a/force_bdss/mco/events.py b/force_bdss/mco/events.py
deleted file mode 100644
index 216e1effa30d7b1e81e0a8f82312310bb3fae583..0000000000000000000000000000000000000000
--- a/force_bdss/mco/events.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from traits.api import HasStrictTraits, Tuple
-
-
-class BaseMCOEvent(HasStrictTraits):
-    """Base event for the MCO"""
-
-
-class MCOStartEvent(BaseMCOEvent):
-    """MCO should emit this event when the evaluation starts."""
-
-
-class MCOFinishEvent(BaseMCOEvent):
-    """MCO should emit this event when the evaluation ends."""
-
-
-class MCOProgressEvent(BaseMCOEvent):
-    """MCO should emit this event for every new evaluation that has been
-    completed. It carries data about the evaluation, specifically the
-    input data (MCO parameter values) and the resulting output (KPIs)."""
-    input = Tuple()
-    output = Tuple()
diff --git a/force_bdss/tests/test_core_mco_driver.py b/force_bdss/tests/test_core_mco_driver.py
index 688f7944604416e69ec586053d44d63005e7f807..3a4b33f2d9f15205bf9ebb8debafe85ec088c534 100644
--- a/force_bdss/tests/test_core_mco_driver.py
+++ b/force_bdss/tests/test_core_mco_driver.py
@@ -1,7 +1,8 @@
 import unittest
 from testfixtures import LogCapture
 
-from force_bdss.mco.events import MCOStartEvent
+from force_bdss.core_driver_events import (
+    MCOStartEvent, MCOFinishEvent, MCOProgressEvent)
 from force_bdss.notification_listeners.base_notification_listener import \
     BaseNotificationListener
 from force_bdss.tests import fixtures
@@ -47,16 +48,37 @@ class TestCoreMCODriver(unittest.TestCase):
         )
         self.assertEqual(len(driver.listeners), 1)
 
-    def test_event_handling(self):
+    def test_start_event_handling(self):
         driver = CoreMCODriver(
             application=self.mock_application,
         )
         listener = driver.listeners[0]
         mock_deliver = mock.Mock()
         listener.__dict__["deliver"] = mock_deliver
-        event = MCOStartEvent()
-        driver.mco.event = event
-        self.assertTrue(mock_deliver.call_args[0][0], event)
+        driver.mco.started = True
+        self.assertIsInstance(mock_deliver.call_args[0][0], MCOStartEvent)
+
+    def test_finished_event_handling(self):
+        driver = CoreMCODriver(
+            application=self.mock_application,
+        )
+        listener = driver.listeners[0]
+        mock_deliver = mock.Mock()
+        listener.__dict__["deliver"] = mock_deliver
+        driver.mco.finished = True
+        self.assertIsInstance(mock_deliver.call_args[0][0], MCOFinishEvent)
+
+    def test_progress_event_handling(self):
+        driver = CoreMCODriver(
+            application=self.mock_application,
+        )
+        listener = driver.listeners[0]
+        mock_deliver = mock.Mock()
+        listener.__dict__["deliver"] = mock_deliver
+        driver.mco.new_data = {'input': (1, 2), 'output': (3, 4)}
+        self.assertIsInstance(mock_deliver.call_args[0][0], MCOProgressEvent)
+        self.assertEqual(mock_deliver.call_args[0][0].input, (1, 2))
+        self.assertEqual(mock_deliver.call_args[0][0].output, (3, 4))
 
     def test_listener_init_exception(self):
         driver = CoreMCODriver(
@@ -90,7 +112,7 @@ class TestCoreMCODriver(unittest.TestCase):
         listener.__dict__["deliver"] = mock_deliver
         mock_deliver.side_effect = Exception()
         with LogCapture() as capture:
-            driver.mco.event = MCOStartEvent()
+            driver.mco.started = True
             self.assertTrue(mock_deliver.called)
 
             capture.check(