diff --git a/examples/test_workflow.json b/examples/test_workflow.json
index f0fa936ec307ee749bef6b3e85bb4bdc05303f4e..64e04bbbbe181604dd97217b241c2d1a27c06d11 100644
--- a/examples/test_workflow.json
+++ b/examples/test_workflow.json
@@ -1,9 +1,17 @@
 {
-    "multi_criteria_optimization": {
-        "name": "basic"
+  "multi_criteria_optimizer": {
+    "name": "basic",
+    "model_data": {}
+  },
+  "data_sources": [
+    {
+      "name": "viscosity",
+      "model_data": {}
     },
-    "data_sources": [
-        "viscosity", "price"
-    ]
+    {
+      "name": "price",
+      "model_data": {}
+    }
+  ]
 }
 
diff --git a/force_bdss/core_mco_driver.py b/force_bdss/core_mco_driver.py
index 17fa2b40b892c13764193a4e5ae9167a40f77927..57051c180ce7336c08107185668d2b9b54d2345b 100644
--- a/force_bdss/core_mco_driver.py
+++ b/force_bdss/core_mco_driver.py
@@ -3,9 +3,10 @@ from envisage.plugin import Plugin
 from traits.has_traits import on_trait_change
 from traits.trait_types import List
 
-from force_bdss.data_sources.i_data_source import (
-    IDataSource)
-from force_bdss.mco.i_multi_criteria_optimizers import IMultiCriteriaOptimizer
+from force_bdss.data_sources.i_data_source_bundle import (
+    IDataSourceBundle)
+from force_bdss.mco.i_multi_criteria_optimizer_bundle import (
+    IMultiCriteriaOptimizerBundle)
 
 
 class CoreMCODriver(Plugin):
@@ -20,45 +21,51 @@ class CoreMCODriver(Plugin):
 
     #: A List of the available Multi Criteria Optimizers.
     #: This will be populated by MCO plugins.
-    multi_criteria_optimizers = ExtensionPoint(
-        List(IMultiCriteriaOptimizer),
-        id='force_bdss.multi_criteria_optimizers')
+    mco_bundles = ExtensionPoint(
+        List(IMultiCriteriaOptimizerBundle),
+        id='force.bdss.mco.bundles')
 
     #: A list of the available Key Performance Indicator calculators.
     #: It will be populated by plugins.
-    data_sources = ExtensionPoint(
-        List(IDataSource),
-        id='force_bdss.data_sources')
+    data_source_bundles = ExtensionPoint(
+        List(IDataSourceBundle),
+        id='force.bdss.data_sources.bundles')
 
     @on_trait_change("application:started")
     def application_started(self):
         workflow = self.application.workflow
         if self.application.evaluate:
             for requested_ds in workflow.data_sources:
-                data_source = self._find_data_source_by_computes(requested_ds)
-                if data_source:
-                    data_source.run(self.application)
+                ds_bundle = self._find_data_source_bundle_by_name(
+                    requested_ds.name)
+                if ds_bundle:
+                    ds_model = ds_bundle.create_model(requested_ds.model_data)
+                    data_source = ds_bundle.create_data_source(
+                        self.application, ds_model)
+                    data_source.run()
                 else:
                     raise Exception("Requested data source {} but don't know "
-                                    "to find it.".format(requested_ds))
+                                    "to find it.".format(requested_ds.name))
         else:
-            mco_name = workflow.multi_criteria_optimization.name
-            mco = self._find_mco_by_name(mco_name)
-            if mco:
-                mco.run(self.application)
+            mco_data = workflow.multi_criteria_optimizer
+            mco_bundle = self._find_mco_bundle_by_name(mco_data.name)
+            if mco_bundle:
+                mco_model = mco_bundle.create_model(mco_data.model_data)
+                mco = mco_bundle.create_optimizer(self.application, mco_model)
+                mco.run()
             else:
                 raise Exception("Requested MCO {} but it's not available"
-                                "to compute it.".format(mco_name))
+                                "to compute it.".format(mco_data.name))
 
-    def _find_data_source_by_computes(self, computes):
-        for ds in self.data_sources:
-            if ds.computes == computes:
+    def _find_data_source_bundle_by_name(self, name):
+        for ds in self.data_source_bundles:
+            if ds.name == name:
                 return ds
 
         return None
 
-    def _find_mco_by_name(self, name):
-        for mco in self.multi_criteria_optimizers:
+    def _find_mco_bundle_by_name(self, name):
+        for mco in self.mco_bundles:
             if mco.name == name:
                 return mco
 
diff --git a/force_bdss/core_plugins/__init__.py b/force_bdss/core_plugins/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/force_bdss/core_plugins/test_data_sources/__init__.py b/force_bdss/core_plugins/test_data_sources/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/force_bdss/core_plugins/test_data_sources/basic/__init__.py b/force_bdss/core_plugins/test_data_sources/basic/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/force_bdss/core_plugins/test_data_sources/basic/basic_bundle.py b/force_bdss/core_plugins/test_data_sources/basic/basic_bundle.py
new file mode 100644
index 0000000000000000000000000000000000000000..8a99792da4ba9ef207841b5aa2c39e9d4b918e5b
--- /dev/null
+++ b/force_bdss/core_plugins/test_data_sources/basic/basic_bundle.py
@@ -0,0 +1,20 @@
+from traits.api import provides, HasStrictTraits, String
+
+from force_bdss.data_sources.i_data_source_bundle import IDataSourceBundle
+
+from .basic_model import BasicModel
+from .basic_data_source import BasicDataSource
+
+
+@provides(IDataSourceBundle)
+class BasicBundle(HasStrictTraits):
+    name = String("basic")
+
+    def create_model(self, model_data):
+        return BasicModel.from_json(model_data)
+
+    def create_ui(self):
+        pass
+
+    def create_data_source(self, application, model):
+        return BasicDataSource(self, application, model)
diff --git a/force_bdss/core_plugins/test_data_sources/basic/basic_data_source.py b/force_bdss/core_plugins/test_data_sources/basic/basic_data_source.py
new file mode 100644
index 0000000000000000000000000000000000000000..6705515570052b6516ec7cbca76cd234b13cbb99
--- /dev/null
+++ b/force_bdss/core_plugins/test_data_sources/basic/basic_data_source.py
@@ -0,0 +1,6 @@
+from force_bdss.data_sources.base_data_source import BaseDataSource
+
+
+class BasicDataSource(BaseDataSource):
+    def run(self):
+        print("Computing basic key performance indicator")
diff --git a/force_bdss/core_plugins/test_data_sources/basic/basic_model.py b/force_bdss/core_plugins/test_data_sources/basic/basic_model.py
new file mode 100644
index 0000000000000000000000000000000000000000..3139ad7e106b74e776637f9cb92b560da04f7587
--- /dev/null
+++ b/force_bdss/core_plugins/test_data_sources/basic/basic_model.py
@@ -0,0 +1,7 @@
+from traits.has_traits import HasStrictTraits
+
+
+class BasicModel(HasStrictTraits):
+    @classmethod
+    def from_json(cls, model_data):
+        return cls()
diff --git a/force_bdss/core_plugins/test_data_sources/data_sources_plugin.py b/force_bdss/core_plugins/test_data_sources/data_sources_plugin.py
new file mode 100644
index 0000000000000000000000000000000000000000..9960da34aeea3f79a2987c20401d0c1d9c0b712e
--- /dev/null
+++ b/force_bdss/core_plugins/test_data_sources/data_sources_plugin.py
@@ -0,0 +1,22 @@
+from envisage.plugin import Plugin
+from traits.api import List
+
+from force_bdss.data_sources.i_data_source_bundle import IDataSourceBundle
+
+from .basic.basic_bundle import BasicBundle
+from .price.price_bundle import PriceBundle
+from .viscosity.viscosity_bundle import ViscosityBundle
+
+
+class DataSourcesPlugin(Plugin):
+    id = "force_bdss.data_sources_plugin"
+
+    data_sources = List(
+        IDataSourceBundle,
+        contributes_to='force.bdss.data_sources.bundles'
+    )
+
+    def _data_sources_default(self):
+        return [BasicBundle(),
+                ViscosityBundle(),
+                PriceBundle()]
diff --git a/force_bdss/core_plugins/test_data_sources/price/__init__.py b/force_bdss/core_plugins/test_data_sources/price/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/force_bdss/core_plugins/test_data_sources/price/price_bundle.py b/force_bdss/core_plugins/test_data_sources/price/price_bundle.py
new file mode 100644
index 0000000000000000000000000000000000000000..2721ee27bf5aa836adaa22b864eff4ec99b3ac51
--- /dev/null
+++ b/force_bdss/core_plugins/test_data_sources/price/price_bundle.py
@@ -0,0 +1,21 @@
+from traits.api import provides, HasStrictTraits
+from traits.trait_types import String
+
+from force_bdss.data_sources.i_data_source_bundle import IDataSourceBundle
+
+from .price_model import PriceModel
+from .price_data_source import PriceDataSource
+
+
+@provides(IDataSourceBundle)
+class PriceBundle(HasStrictTraits):
+    name = String("price")
+
+    def create_model(self, model_data):
+        return PriceModel.from_json(model_data)
+
+    def create_ui(self):
+        pass
+
+    def create_data_source(self, application, model):
+        return PriceDataSource(self, application, model)
diff --git a/force_bdss/core_plugins/test_data_sources/price/price_data_source.py b/force_bdss/core_plugins/test_data_sources/price/price_data_source.py
new file mode 100644
index 0000000000000000000000000000000000000000..62ec8d1738e1020b1cba6de43020d64dc30ee86f
--- /dev/null
+++ b/force_bdss/core_plugins/test_data_sources/price/price_data_source.py
@@ -0,0 +1,6 @@
+from force_bdss.data_sources.base_data_source import BaseDataSource
+
+
+class PriceDataSource(BaseDataSource):
+    def run(self):
+        print("Computing price")
diff --git a/force_bdss/core_plugins/test_data_sources/price/price_model.py b/force_bdss/core_plugins/test_data_sources/price/price_model.py
new file mode 100644
index 0000000000000000000000000000000000000000..f98449a2e2791f35b1f035e9f1772e15fe1f0930
--- /dev/null
+++ b/force_bdss/core_plugins/test_data_sources/price/price_model.py
@@ -0,0 +1,7 @@
+from traits.has_traits import HasStrictTraits
+
+
+class PriceModel(HasStrictTraits):
+    @classmethod
+    def from_json(cls, model_data):
+        return cls()
diff --git a/force_bdss/core_plugins/test_data_sources/viscosity/__init__.py b/force_bdss/core_plugins/test_data_sources/viscosity/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/force_bdss/core_plugins/test_data_sources/viscosity/viscosity_bundle.py b/force_bdss/core_plugins/test_data_sources/viscosity/viscosity_bundle.py
new file mode 100644
index 0000000000000000000000000000000000000000..6b05b062b6f1d7ad9e54cc515a665d5c26ba24cf
--- /dev/null
+++ b/force_bdss/core_plugins/test_data_sources/viscosity/viscosity_bundle.py
@@ -0,0 +1,20 @@
+from traits.api import provides, HasStrictTraits, String
+
+from force_bdss.data_sources.i_data_source_bundle import IDataSourceBundle
+
+from .viscosity_data_source import ViscosityDataSource
+from .viscosity_model import ViscosityModel
+
+
+@provides(IDataSourceBundle)
+class ViscosityBundle(HasStrictTraits):
+    name = String("viscosity")
+
+    def create_model(self, model_data):
+        return ViscosityModel.from_json(model_data)
+
+    def create_ui(self):
+        pass
+
+    def create_data_source(self, application, model):
+        return ViscosityDataSource(self, application, model)
diff --git a/force_bdss/core_plugins/test_data_sources/viscosity/viscosity_data_source.py b/force_bdss/core_plugins/test_data_sources/viscosity/viscosity_data_source.py
new file mode 100644
index 0000000000000000000000000000000000000000..3ebd04733aab4a01a365913d290a61d2683aec95
--- /dev/null
+++ b/force_bdss/core_plugins/test_data_sources/viscosity/viscosity_data_source.py
@@ -0,0 +1,6 @@
+from force_bdss.data_sources.base_data_source import BaseDataSource
+
+
+class ViscosityDataSource(BaseDataSource):
+    def run(self):
+        print("Computing viscosity")
diff --git a/force_bdss/core_plugins/test_data_sources/viscosity/viscosity_model.py b/force_bdss/core_plugins/test_data_sources/viscosity/viscosity_model.py
new file mode 100644
index 0000000000000000000000000000000000000000..8168c45e58666ecf7ae35687ffcf69aa69be014f
--- /dev/null
+++ b/force_bdss/core_plugins/test_data_sources/viscosity/viscosity_model.py
@@ -0,0 +1,7 @@
+from traits.api import HasStrictTraits
+
+
+class ViscosityModel(HasStrictTraits):
+    @classmethod
+    def from_json(cls, model_data):
+        return cls()
diff --git a/force_bdss/core_plugins/test_mco/__init__.py b/force_bdss/core_plugins/test_mco/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/force_bdss/core_plugins/test_mco/basic/__init__.py b/force_bdss/core_plugins/test_mco/basic/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/force_bdss/core_plugins/test_mco/basic/basic_bundle.py b/force_bdss/core_plugins/test_mco/basic/basic_bundle.py
new file mode 100644
index 0000000000000000000000000000000000000000..a8aa0bd25fa6fd42e27ba8547f4bb906693e8c3f
--- /dev/null
+++ b/force_bdss/core_plugins/test_mco/basic/basic_bundle.py
@@ -0,0 +1,21 @@
+from traits.has_traits import HasStrictTraits, provides
+from traits.trait_types import String
+
+from force_bdss.mco.i_multi_criteria_optimizer_bundle import (
+    IMultiCriteriaOptimizerBundle)
+from .basic_model import BasicModel
+from .basic_optimizer import BasicOptimizer
+
+
+@provides(IMultiCriteriaOptimizerBundle)
+class BasicBundle(HasStrictTraits):
+    name = String("basic")
+
+    def create_model(self, model_data):
+        return BasicModel.from_json(model_data)
+
+    def create_ui(self):
+        pass
+
+    def create_optimizer(self, application, model):
+        return BasicOptimizer(self, application, model)
diff --git a/force_bdss/core_plugins/test_mco/basic/basic_model.py b/force_bdss/core_plugins/test_mco/basic/basic_model.py
new file mode 100644
index 0000000000000000000000000000000000000000..3139ad7e106b74e776637f9cb92b560da04f7587
--- /dev/null
+++ b/force_bdss/core_plugins/test_mco/basic/basic_model.py
@@ -0,0 +1,7 @@
+from traits.has_traits import HasStrictTraits
+
+
+class BasicModel(HasStrictTraits):
+    @classmethod
+    def from_json(cls, model_data):
+        return cls()
diff --git a/force_bdss/core_plugins/test_mco/basic/basic_optimizer.py b/force_bdss/core_plugins/test_mco/basic/basic_optimizer.py
new file mode 100644
index 0000000000000000000000000000000000000000..7a4f1ed27c11b3db0a9a56b1e1a8a0c222610913
--- /dev/null
+++ b/force_bdss/core_plugins/test_mco/basic/basic_optimizer.py
@@ -0,0 +1,13 @@
+import subprocess
+import sys
+
+from force_bdss.mco.base_multi_criteria_optimizer import (
+    BaseMultiCriteriaOptimizer
+)
+
+
+class BasicOptimizer(BaseMultiCriteriaOptimizer):
+    def run(self):
+        print("Running Basic optimizer")
+        subprocess.check_call([sys.argv[0], "--evaluate",
+                               self.application.workflow_filepath])
diff --git a/force_bdss/core_plugins/test_mco/dakota/__init__.py b/force_bdss/core_plugins/test_mco/dakota/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/force_bdss/core_plugins/test_mco/dakota/dakota_bundle.py b/force_bdss/core_plugins/test_mco/dakota/dakota_bundle.py
new file mode 100644
index 0000000000000000000000000000000000000000..dd0ef08d38b7daafdf8ff552af3348fab81ae44d
--- /dev/null
+++ b/force_bdss/core_plugins/test_mco/dakota/dakota_bundle.py
@@ -0,0 +1,22 @@
+from traits.has_traits import HasStrictTraits, provides
+from traits.trait_types import String
+
+from force_bdss.mco.i_multi_criteria_optimizer_bundle import (
+    IMultiCriteriaOptimizerBundle)
+
+from .dakota_model import DakotaModel
+from .dakota_optimizer import DakotaOptimizer
+
+
+@provides(IMultiCriteriaOptimizerBundle)
+class DakotaBundle(HasStrictTraits):
+    name = String("dakota")
+
+    def create_model(self, model_data):
+        return DakotaModel.from_json(model_data)
+
+    def create_ui(self):
+        pass
+
+    def create_optimizer(self, application, model):
+        return DakotaOptimizer(self, application, model)
diff --git a/force_bdss/core_plugins/test_mco/dakota/dakota_model.py b/force_bdss/core_plugins/test_mco/dakota/dakota_model.py
new file mode 100644
index 0000000000000000000000000000000000000000..ed6ff342dfdd8c2ee8742ba32f86808cb8f82582
--- /dev/null
+++ b/force_bdss/core_plugins/test_mco/dakota/dakota_model.py
@@ -0,0 +1,7 @@
+from traits.api import HasStrictTraits
+
+
+class DakotaModel(HasStrictTraits):
+    @classmethod
+    def from_json(cls, model_data):
+        return cls()
diff --git a/force_bdss/core_plugins/test_mco/dakota/dakota_optimizer.py b/force_bdss/core_plugins/test_mco/dakota/dakota_optimizer.py
new file mode 100644
index 0000000000000000000000000000000000000000..0f8f064cc985e2afdb6fc99765f42596ae49cece
--- /dev/null
+++ b/force_bdss/core_plugins/test_mco/dakota/dakota_optimizer.py
@@ -0,0 +1,14 @@
+import subprocess
+
+import sys
+
+from force_bdss.mco.base_multi_criteria_optimizer import (
+    BaseMultiCriteriaOptimizer
+)
+
+
+class DakotaOptimizer(BaseMultiCriteriaOptimizer):
+    def run(self):
+        print("Running dakota optimizer")
+        subprocess.check_call([sys.argv[0], "--evaluate",
+                               self.application.workflow_filepath])
diff --git a/force_bdss/core_plugins/test_mco/multi_criteria_optimizers_plugin.py b/force_bdss/core_plugins/test_mco/multi_criteria_optimizers_plugin.py
new file mode 100644
index 0000000000000000000000000000000000000000..6976cdb7a9009361b2f3f9d97dd7fc2c4b4c3865
--- /dev/null
+++ b/force_bdss/core_plugins/test_mco/multi_criteria_optimizers_plugin.py
@@ -0,0 +1,20 @@
+from envisage.plugin import Plugin
+from traits.api import List
+
+from force_bdss.mco.i_multi_criteria_optimizer_bundle import (
+    IMultiCriteriaOptimizerBundle)
+
+from .basic.basic_bundle import BasicBundle
+from .dakota.dakota_bundle import DakotaBundle
+
+
+class MultiCriteriaOptimizersPlugin(Plugin):
+    id = "force.bdss.mco.plugins.multi_criteria_optimizers_plugin"
+
+    multi_criteria_optimizers = List(
+        IMultiCriteriaOptimizerBundle,
+        contributes_to='force.bdss.mco.bundles'
+    )
+
+    def _multi_criteria_optimizers_default(self):
+        return [BasicBundle(), DakotaBundle()]
diff --git a/force_bdss/data_sources/base_data_source.py b/force_bdss/data_sources/base_data_source.py
new file mode 100644
index 0000000000000000000000000000000000000000..f3b12d62f0f02a0d72e0e74b7cdb5848f8f80830
--- /dev/null
+++ b/force_bdss/data_sources/base_data_source.py
@@ -0,0 +1,15 @@
+import abc
+
+
+class BaseDataSource(metaclass=abc.ABCMeta):
+    def __init__(self, bundle, application, model):
+        self.bundle = bundle
+        self.application = application
+        self.model = model
+
+    @property
+    def name(self):
+        return self.bundle.name
+
+    def run(self):
+        pass
diff --git a/force_bdss/data_sources/basic.py b/force_bdss/data_sources/basic.py
deleted file mode 100644
index 5fe2f3cee8737ca51c38c2e2653b7219464237a9..0000000000000000000000000000000000000000
--- a/force_bdss/data_sources/basic.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from traits.api import provides, HasStrictTraits, String
-
-from force_bdss.data_sources.i_data_source import (
-    IDataSource)
-
-
-@provides(IDataSource)
-class Basic(HasStrictTraits):
-    computes = String("basic")
-
-    def run(self, workflow):
-        print("Computing basic key performance indicator, {}".format(workflow))
diff --git a/force_bdss/data_sources/data_sources_plugin.py b/force_bdss/data_sources/data_sources_plugin.py
deleted file mode 100644
index 2bd94d88418648f6dbb36eef508bd6b48da07e7a..0000000000000000000000000000000000000000
--- a/force_bdss/data_sources/data_sources_plugin.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from envisage.plugin import Plugin
-from traits.api import List
-
-from force_bdss.data_sources.i_data_source import (
-    IDataSource)
-
-from force_bdss.data_sources.basic import Basic
-from force_bdss.data_sources.price import Price
-from force_bdss.data_sources.viscosity import Viscosity
-
-
-class DataSourcesPlugin(Plugin):
-
-    id = "force_bdss.data_sources_plugin"
-
-    data_sources = List(
-        IDataSource,
-        contributes_to='force_bdss.data_sources'
-    )
-
-    def _data_sources_default(self):
-        return [Basic(), Viscosity(), Price()]
diff --git a/force_bdss/data_sources/i_data_source.py b/force_bdss/data_sources/i_data_source.py
deleted file mode 100644
index e86f0c76a5587585322312b0ec6df4246e224f6a..0000000000000000000000000000000000000000
--- a/force_bdss/data_sources/i_data_source.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from traits.api import Interface, String
-
-
-class IDataSource(Interface):
-    computes = String()
-
-    def run(self):
-        pass
diff --git a/force_bdss/data_sources/i_data_source_bundle.py b/force_bdss/data_sources/i_data_source_bundle.py
new file mode 100644
index 0000000000000000000000000000000000000000..f277caedbd43319478a3605f9b2e815fd0725324
--- /dev/null
+++ b/force_bdss/data_sources/i_data_source_bundle.py
@@ -0,0 +1,14 @@
+from traits.api import Interface, String
+
+
+class IDataSourceBundle(Interface):
+    name = String()
+
+    def create_ui(self):
+        pass
+
+    def create_data_source(self, application, model):
+        pass
+
+    def create_model(self, model_data):
+        pass
diff --git a/force_bdss/data_sources/price.py b/force_bdss/data_sources/price.py
deleted file mode 100644
index 30fbaf78418fa5dfecf721f0714c572a1fcd1faa..0000000000000000000000000000000000000000
--- a/force_bdss/data_sources/price.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from traits.api import provides, HasStrictTraits, String
-
-from force_bdss.data_sources.i_data_source import (
-    IDataSource)
-
-
-@provides(IDataSource)
-class Price(HasStrictTraits):
-    computes = String("price")
-
-    def run(self, workflow):
-        print("Computing price")
diff --git a/force_bdss/data_sources/viscosity.py b/force_bdss/data_sources/viscosity.py
deleted file mode 100644
index 1c207f438268f1db67d29fe16602be7998040611..0000000000000000000000000000000000000000
--- a/force_bdss/data_sources/viscosity.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from traits.api import provides, HasStrictTraits, String
-
-from force_bdss.data_sources.i_data_source import (
-    IDataSource)
-
-
-@provides(IDataSource)
-class Viscosity(HasStrictTraits):
-    computes = String("viscosity")
-
-    def run(self, workflow):
-        print("Computing viscosity")
diff --git a/force_bdss/mco/base_multi_criteria_optimizer.py b/force_bdss/mco/base_multi_criteria_optimizer.py
new file mode 100644
index 0000000000000000000000000000000000000000..eb530d5dfdf7760377e1b2b4b8aade740a28e55f
--- /dev/null
+++ b/force_bdss/mco/base_multi_criteria_optimizer.py
@@ -0,0 +1,16 @@
+import abc
+
+
+class BaseMultiCriteriaOptimizer(metaclass=abc.ABCMeta):
+    def __init__(self, bundle, application, model):
+        self.bundle = bundle
+        self.application = application
+        self.model = model
+
+    @property
+    def name(self):
+        return self.bundle.name
+
+    @abc.abstractmethod
+    def run(self):
+        pass
diff --git a/force_bdss/mco/basic.py b/force_bdss/mco/basic.py
deleted file mode 100644
index 2e29c3bc233236dd41de6edad6f3e605c372b893..0000000000000000000000000000000000000000
--- a/force_bdss/mco/basic.py
+++ /dev/null
@@ -1,16 +0,0 @@
-import subprocess
-import sys
-
-from traits.api import provides, HasStrictTraits, String
-
-from force_bdss.mco.i_multi_criteria_optimizers import IMultiCriteriaOptimizer
-
-
-@provides(IMultiCriteriaOptimizer)
-class Basic(HasStrictTraits):
-    name = String("basic")
-
-    def run(self, application):
-        print("Running Basic optimizer")
-        subprocess.check_call([sys.argv[0], "--evaluate",
-                               application.workflow_filepath])
diff --git a/force_bdss/mco/dakota.py b/force_bdss/mco/dakota.py
deleted file mode 100644
index b046b11f3cd407015593c92dc6e187695bee9b39..0000000000000000000000000000000000000000
--- a/force_bdss/mco/dakota.py
+++ /dev/null
@@ -1,17 +0,0 @@
-import subprocess
-
-import sys
-
-from traits.api import provides, HasStrictTraits, String
-
-from force_bdss.mco.i_multi_criteria_optimizers import IMultiCriteriaOptimizer
-
-
-@provides(IMultiCriteriaOptimizer)
-class Dakota(HasStrictTraits):
-    name = String("dakota")
-
-    def run(self, application):
-        print("Running dakota optimizer")
-        subprocess.check_call([sys.argv[0], "--evaluate",
-                               application.workflow_filepath])
diff --git a/force_bdss/mco/i_multi_criteria_optimizer_bundle.py b/force_bdss/mco/i_multi_criteria_optimizer_bundle.py
new file mode 100644
index 0000000000000000000000000000000000000000..3a584c4103fa11b71c648e03791f3a205188db33
--- /dev/null
+++ b/force_bdss/mco/i_multi_criteria_optimizer_bundle.py
@@ -0,0 +1,14 @@
+from traits.api import Interface, String
+
+
+class IMultiCriteriaOptimizerBundle(Interface):
+    name = String()
+
+    def create_optimizer(self, application, model):
+        pass
+
+    def create_ui(self):
+        pass
+
+    def create_model(self, model_data):
+        pass
diff --git a/force_bdss/mco/i_multi_criteria_optimizers.py b/force_bdss/mco/i_multi_criteria_optimizers.py
deleted file mode 100644
index 93c6b25dca4f73afc08caa0d348c59b9a2e195eb..0000000000000000000000000000000000000000
--- a/force_bdss/mco/i_multi_criteria_optimizers.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from traits.api import Interface, String
-
-
-class IMultiCriteriaOptimizer(Interface):
-    name = String()
-
-    def run(self, application):
-        pass
diff --git a/force_bdss/mco/multi_criteria_optimizers_plugin.py b/force_bdss/mco/multi_criteria_optimizers_plugin.py
deleted file mode 100644
index 79e3f3066fc1d589543de3ac384d221c2b7b0dba..0000000000000000000000000000000000000000
--- a/force_bdss/mco/multi_criteria_optimizers_plugin.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from envisage.plugin import Plugin
-from traits.api import List
-
-from force_bdss.mco.basic import Basic
-from force_bdss.mco.dakota import Dakota
-from force_bdss.mco.i_multi_criteria_optimizers import IMultiCriteriaOptimizer
-
-
-class MultiCriteriaOptimizersPlugin(Plugin):
-    id = "force_bdss.multi_criteria_optimizers_plugin"
-
-    multi_criteria_optimizers = List(
-        IMultiCriteriaOptimizer,
-        contributes_to='force_bdss.multi_criteria_optimizers'
-    )
-
-    def _multi_criteria_optimizers_default(self):
-        return [Basic(), Dakota()]
diff --git a/force_bdss/workspecs/data_source.py b/force_bdss/workspecs/data_source.py
new file mode 100644
index 0000000000000000000000000000000000000000..944e41ce68b6fa60fd9be2c77a6f651df2832b00
--- /dev/null
+++ b/force_bdss/workspecs/data_source.py
@@ -0,0 +1,16 @@
+from traits.has_traits import HasStrictTraits
+from traits.trait_types import String, Dict
+
+
+class DataSource(HasStrictTraits):
+    name = String()
+    model_data = Dict()
+
+    @classmethod
+    def from_json(cls, json_data):
+        self = cls(
+            name=json_data["name"],
+            model_data=json_data["model_data"]
+        )
+
+        return self
diff --git a/force_bdss/workspecs/multi_criteria_optimization.py b/force_bdss/workspecs/multi_criteria_optimization.py
deleted file mode 100644
index 9e5e3152e68a168d0de2d2e5f0ff8d2031c1b25d..0000000000000000000000000000000000000000
--- a/force_bdss/workspecs/multi_criteria_optimization.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from traits.api import HasStrictTraits, String
-
-
-class MultiCriteriaOptimization(HasStrictTraits):
-    name = String()
-
-    @classmethod
-    def from_json(cls, json_data):
-        self = cls(
-            name=json_data["name"]
-        )
-
-        return self
diff --git a/force_bdss/workspecs/multi_criteria_optimizer.py b/force_bdss/workspecs/multi_criteria_optimizer.py
new file mode 100644
index 0000000000000000000000000000000000000000..72a2fa6b264fb3f5cd0be4fc9af9fb284a6fca96
--- /dev/null
+++ b/force_bdss/workspecs/multi_criteria_optimizer.py
@@ -0,0 +1,15 @@
+from traits.api import HasStrictTraits, String, Dict
+
+
+class MultiCriteriaOptimizer(HasStrictTraits):
+    name = String()
+    model_data = Dict()
+
+    @classmethod
+    def from_json(cls, json_data):
+        self = cls(
+            name=json_data["name"],
+            model_data=json_data["model_data"]
+        )
+
+        return self
diff --git a/force_bdss/workspecs/workflow.py b/force_bdss/workspecs/workflow.py
index 871e9b7d1acab73292e017903a632d3d174cfb2f..88e5b60203bec836fbad4ef3c2bd7c3dae1b42e0 100644
--- a/force_bdss/workspecs/workflow.py
+++ b/force_bdss/workspecs/workflow.py
@@ -1,20 +1,24 @@
 from traits.api import HasStrictTraits, Instance, String, List
 
-from .multi_criteria_optimization import MultiCriteriaOptimization
+from force_bdss.workspecs.data_source import DataSource
+from .multi_criteria_optimizer import MultiCriteriaOptimizer
 
 
 class Workflow(HasStrictTraits):
     name = String()
-    multi_criteria_optimization = Instance(MultiCriteriaOptimization)
-    data_sources = List(String)
+    multi_criteria_optimizer = Instance(MultiCriteriaOptimizer)
+    data_sources = List(DataSource)
 
     @classmethod
     def from_json(cls, json_data):
+
         self = cls(
-            multi_criteria_optimization=MultiCriteriaOptimization.from_json(
-                    json_data["multi_criteria_optimization"]
+            multi_criteria_optimizer=MultiCriteriaOptimizer.from_json(
+                    json_data["multi_criteria_optimizer"]
             ),
-            data_sources=json_data["data_sources"]
+            data_sources=[
+                DataSource.from_json(data_source_data)
+                for data_source_data in json_data["data_sources"]]
             )
 
         return self
diff --git a/setup.py b/setup.py
index 3105683964a7547fbc519e7653da1a57fcd63855..aa6f85129dbbdc940f079ad46a06ac0089d26c72 100644
--- a/setup.py
+++ b/setup.py
@@ -10,10 +10,10 @@ setup(
             'force_bdss = force_bdss.cli.force_bdss:run',
         ],
         "force.bdss.extensions": [
-            "mco = force_bdss.mco.multi_criteria_optimizers_plugin:"
-            "MultiCriteriaOptimizersPlugin",
-            "data_source = force_bdss.data_sources.data_sources_plugin:"
-            "DataSourcesPlugin",
+            "mco = force_bdss.core_plugins.test_mco."
+            "multi_criteria_optimizers_plugin:MultiCriteriaOptimizersPlugin",
+            "data_source = force_bdss.core_plugins.test_data_sources."
+            "data_sources_plugin:DataSourcesPlugin",
         ]
     },
     packages=find_packages(),