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/basic_bundle.py b/force_bdss/mco/basic_bundle.py
new file mode 100644
index 0000000000000000000000000000000000000000..86139561ad1de0e4a8814fa132e1605440629be5
--- /dev/null
+++ b/force_bdss/mco/basic_bundle.py
@@ -0,0 +1,17 @@
+from traits.has_traits import HasStrictTraits, provides
+
+from .i_multi_criteria_optimizer_bundle import IMultiCriteriaOptimizerBundle
+from .basic_model import BasicModel
+from .basic_optimizer import BasicOptimizer
+
+
+@provides(IMultiCriteriaOptimizerBundle)
+class BasicBundle(HasStrictTraits):
+    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/mco/basic_model.py b/force_bdss/mco/basic_model.py
new file mode 100644
index 0000000000000000000000000000000000000000..3139ad7e106b74e776637f9cb92b560da04f7587
--- /dev/null
+++ b/force_bdss/mco/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/mco/basic_optimizer.py b/force_bdss/mco/basic_optimizer.py
new file mode 100644
index 0000000000000000000000000000000000000000..cc7477a8f4a253db1fd3e3a709796d325588e6b6
--- /dev/null
+++ b/force_bdss/mco/basic_optimizer.py
@@ -0,0 +1,12 @@
+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/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/dakota_bundle.py b/force_bdss/mco/dakota_bundle.py
new file mode 100644
index 0000000000000000000000000000000000000000..a33c5efafe5051779c26fd773f38bce01ee0d86d
--- /dev/null
+++ b/force_bdss/mco/dakota_bundle.py
@@ -0,0 +1,17 @@
+from traits.has_traits import HasStrictTraits, provides
+
+from force_bdss.mco.dakota_optimizer import DakotaOptimizer
+from force_bdss.mco.dakota_model import DakotaModel
+from .i_multi_criteria_optimizer_bundle import IMultiCriteriaOptimizerBundle
+
+
+@provides(IMultiCriteriaOptimizerBundle)
+class DakotaBundle(HasStrictTraits):
+    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/mco/dakota_model.py b/force_bdss/mco/dakota_model.py
new file mode 100644
index 0000000000000000000000000000000000000000..76b572f07a393d4b8b8ed93c0ce101c0927338cf
--- /dev/null
+++ b/force_bdss/mco/dakota_model.py
@@ -0,0 +1,7 @@
+from traits.has_traits import HasStrictTraits
+
+
+class DakotaModel(HasStrictTraits):
+    @classmethod
+    def from_json(cls, model_data):
+        return cls()
diff --git a/force_bdss/mco/dakota_optimizer.py b/force_bdss/mco/dakota_optimizer.py
new file mode 100644
index 0000000000000000000000000000000000000000..dc805322137ed238dbae885e28d634944469198f
--- /dev/null
+++ b/force_bdss/mco/dakota_optimizer.py
@@ -0,0 +1,13 @@
+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/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
index 79e3f3066fc1d589543de3ac384d221c2b7b0dba..55095a26a273597731fb8790f95539058602e492 100644
--- a/force_bdss/mco/multi_criteria_optimizers_plugin.py
+++ b/force_bdss/mco/multi_criteria_optimizers_plugin.py
@@ -1,18 +1,19 @@
 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
+from .i_multi_criteria_optimizer_bundle import (
+    IMultiCriteriaOptimizerBundle)
+from .dakota_bundle import DakotaBundle
+from .basic_bundle import BasicBundle
 
 
 class MultiCriteriaOptimizersPlugin(Plugin):
-    id = "force_bdss.multi_criteria_optimizers_plugin"
+    id = "force.bdss.mco.plugins.multi_criteria_optimizers_plugin"
 
     multi_criteria_optimizers = List(
-        IMultiCriteriaOptimizer,
-        contributes_to='force_bdss.multi_criteria_optimizers'
+        IMultiCriteriaOptimizerBundle,
+        contributes_to='force.bdss.mco.bundles'
     )
 
     def _multi_criteria_optimizers_default(self):
-        return [Basic(), Dakota()]
+        return [BasicBundle(), DakotaBundle()]