diff --git a/.gitignore b/.gitignore
index af96cd52f..388af07eb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,4 @@
 *~
 *.pyc
 ve3/
+.quality_assurance_status
diff --git a/continuous_integration b/continuous_integration
new file mode 100755
index 000000000..208f02262
--- /dev/null
+++ b/continuous_integration
@@ -0,0 +1,88 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+"""
+Continuous integration toolkit. The purpose of this script is to generate
+everything which is needed for the CI environment.
+
+List of responsibilities:
+    * terminate execution if any of internal scenarios fails
+    * creates the report file that is needed by the Jenkins plugin
+      to post the status on Phabricator. (.quality_assurance_status)
+"""
+
+import os
+import sys
+import json
+import logging
+
+log = logging.getLogger(__name__)
+
+# constants
+memgraph_suite = "memgraph_V1"
+opencypher_suite = "openCypher_M05"
+results_folder = os.path.join("tck_engine", "results")
+memgraph_suffix = "memgraph-%s.json" % memgraph_suite
+opencypher_suffix = "memgraph-%s.json" % opencypher_suite
+qa_status_path = ".quality_assurance_status"
+
+
+def get_newest_path(folder, suffix):
+    """
+    :param folder: Scanned folder.
+    :param suffix: File suffix.
+
+    :return: Path to the newest file in the folder with the specified suffix.
+    """
+    name_list = sorted(filter(lambda x: x.endswith(suffix),
+                       os.listdir(folder)))
+    if len(name_list) <= 0:
+        sys.exit("Unable to find any file with suffix %s in folder %s!" %
+                 (suffix, folder))
+    return os.path.join(folder, name_list.pop())
+
+
+def generate_status(suite, f):
+    """
+    :param suite: Test suite name.
+    :param f: Json file with status report.
+
+    :return: Status string.
+    """
+    result = json.load(f)
+    total = result["total"]
+    passed = result["passed"]
+    return ("SUITE: %s, PASSED SCENARIOS: %s, TOTAL SCENARIOS: %s (%.2f%%)" %
+            (suite, passed, total, 100.0 * passed / total)), passed, total
+
+
+if __name__ == "__main__":
+    # logger config
+    logging.basicConfig(level=logging.INFO)
+
+    # get data files (memgraph internal test + openCypher TCK test results)
+    memgraph_result_path = get_newest_path(results_folder, memgraph_suffix)
+    log.info("Memgraph result path is %s" % memgraph_result_path)
+    opencypher_result_path = get_newest_path(results_folder, opencypher_suffix)
+    log.info("openCypher result path is %s" % opencypher_result_path)
+
+    # read internal scenarios
+    with open(memgraph_result_path) as f:
+        memgraph_status, memgraph_passed, memgraph_total \
+            = generate_status(memgraph_suite, f)
+
+    # read opencypher scenarios
+    with open(opencypher_result_path) as f:
+        opencypher_status, _, _ = generate_status(opencypher_suite, f)
+
+    # create the report file
+    with open(qa_status_path, "w") as f:
+        f.write("Quality Assurance Status\n")
+        f.write("%s\n" % memgraph_status)
+        f.write("%s\n" % opencypher_status)
+
+    log.info("Status is generated in %s" % qa_status_path)
+
+    if memgraph_total != memgraph_passed:
+        sys.exit("There is a problem with internal scenarios! %s"
+                 % memgraph_status)