diff --git a/bin/mutalyzer-json-service.wsgi b/bin/mutalyzer-json-service.wsgi
index 052dbbb36111927d5c7ef3853af9610a1181b00f..4e2f98020a74e7c2bf80cbb4d7631c6cfa47cc78 100755
--- a/bin/mutalyzer-json-service.wsgi
+++ b/bin/mutalyzer-json-service.wsgi
@@ -23,7 +23,7 @@ To start the built-in HTTP server on port 8082:
 
 import sys
 from wsgiref.simple_server import make_server
-from rpclib.server.wsgi import WsgiApplication
+from spyne.server.wsgi import WsgiApplication
 from mutalyzer.services import json
 
 
diff --git a/extras/pre-install.sh b/extras/pre-install.sh
index 3641d10eaa55b8ff821fb3be868432fd69e5b9b3..34bb88a3c9ddbec68f87dd3b8e9850dae3c87e2e 100644
--- a/extras/pre-install.sh
+++ b/extras/pre-install.sh
@@ -44,13 +44,12 @@ apt-get install -y \
   python-setuptools \
   git-core
 
-echo -e "${COLOR_INFO}Installing known-working rpclib from git master${COLOR_END}"
+echo -e "${COLOR_INFO}Installing known-working spyne from git${COLOR_END}"
 
-# For now we use a specific known-working version of rpclib. The project has
-# in the meantime been renamed to Spyne and we should update some time.
+# For now we use a specific known-working version of spyne.
 pushd $(mktemp -d)
-git clone https://github.com/martijnvermaat/rpclib.git .
-git checkout mutalyzer
+git clone https://github.com/arskom/spyne.git .
+git checkout -b mutalyzer 065e475fa216837cd714e046e92d01a1799f78c2
 python setup.py install
 popd
 
diff --git a/mutalyzer/__init__.py b/mutalyzer/__init__.py
index 426c8e052daaa03fa46faf50a2aa0075ea008647..a6839ab59a19c0f66eace64cb28ee06930d89931 100644
--- a/mutalyzer/__init__.py
+++ b/mutalyzer/__init__.py
@@ -22,8 +22,8 @@ import os
 
 RELEASE = False
 
-__version_info__ = ('2', '0', 'beta-21', 'dev')
-__date__ = '11 Jul 2012'
+__version_info__ = ('2', '0', 'beta-22', 'dev')
+__date__ = '23 Jul 2012'
 
 
 __version__ = '.'.join(__version_info__)
diff --git a/mutalyzer/models.py b/mutalyzer/models.py
index 0dcc07ec440cc716e679611f825cce7c2e331ca8..5f2c342278f5b6b0663a7b8bea2f3f98a91263a5 100644
--- a/mutalyzer/models.py
+++ b/mutalyzer/models.py
@@ -1,13 +1,13 @@
 """
 Collection of serilizable objects used by the SOAP webservice. They extend
-from the rpclib ClassModel.
+from the spyne ClassModel.
 
-Default attributes for the rpclib ClassModel:
+Default attributes for the spyne ClassModel:
 - nillable = True
 - min_occurs = 0
 - max_occurs = 1
 
-Additional attributes values for the rpclib String model:
+Additional attributes values for the spyne String model:
 - min_len = 0
 - max_len = 'unbounded'
 - pattern = None
@@ -17,21 +17,21 @@ Additional attributes values for the rpclib String model:
 """
 
 
-from rpclib.model.primitive import String, Integer, Boolean, DateTime
-from rpclib.model.complex import ComplexModel, Array
+from spyne.model.primitive import String, Integer, Boolean, DateTime
+from spyne.model.complex import ComplexModel, Array
 
 from mutalyzer import SOAP_NAMESPACE
 
 
 class Mandatory(object):
     """
-    This is rpclib.model.primitive.Mandatory, but without min_length=1 for
+    This is spyne.model.primitive.Mandatory, but without min_length=1 for
     the String model.
     """
-    String = String(min_occurs=1, nillable=False)
-    Integer = Integer(min_occurs=1, nillable=False)
-    Boolean = Boolean(min_occurs=1, nillable=False)
-    DateTime = DateTime(min_occurs=1, nillable=False)
+    String = String(type_name='mandatory_string', min_occurs=1, nillable=False)
+    Integer = Integer(type_name='mandatory_integer', min_occurs=1, nillable=False)
+    Boolean = Boolean(type_name='mandatory_boolean', min_occurs=1, nillable=False)
+    DateTime = DateTime(type_name='mandatory_date_time', min_occurs=1, nillable=False)
 #Mandatory
 
 
diff --git a/mutalyzer/services/json.py b/mutalyzer/services/json.py
index b1f46c313d6724a9f0b8f81d723fe692f1f9ad63..ae94a5032dc537656261aa60080d87f95710ac55 100644
--- a/mutalyzer/services/json.py
+++ b/mutalyzer/services/json.py
@@ -3,15 +3,21 @@ Mutalyzer webservice HTTP/RPC with JSON response payloads.
 """
 
 
-from rpclib.application import Application
-from rpclib.protocol.http import HttpRpc
-from rpclib.protocol.json import JsonObject
+from mutalyzer.util import monkey_patch_spyne; monkey_patch_spyne()
+
+from spyne.application import Application
+from spyne.protocol.http import HttpRpc
+from spyne.protocol.json import JsonObject
 
 import mutalyzer
 from mutalyzer.services import rpc
 
 
 # HTTP/RPC application.
+# Note that we originally provided skip_depth=2 to the JsonObject constructor
+# to get rid of some annoying wrappers around the json results. However, this
+# breaks methods returning a primitive datatype (e.g. just a string). Might
+# file a bug about this on spyne.
 application = Application([rpc.MutalyzerService], tns=mutalyzer.SOAP_NAMESPACE,
-                          in_protocol=HttpRpc(), out_protocol=JsonObject(skip_depth=2),
+                          in_protocol=HttpRpc(), out_protocol=JsonObject(),
                           name='Mutalyzer')
diff --git a/mutalyzer/services/rpc.py b/mutalyzer/services/rpc.py
index 4e4f87767df4797af31fce18bb60b64735d3f3d3..e8e05596bd67e5df73aef286a05e0d7014374936 100644
--- a/mutalyzer/services/rpc.py
+++ b/mutalyzer/services/rpc.py
@@ -8,11 +8,11 @@ Mutalyzer RPC services.
 """
 
 
-from rpclib.decorator import srpc
-from rpclib.service import ServiceBase
-from rpclib.model.primitive import String, Integer, Boolean, DateTime
-from rpclib.model.complex import Array
-from rpclib.model.fault import Fault
+from spyne.decorator import srpc
+from spyne.service import ServiceBase
+from spyne.model.primitive import String, Integer, Boolean, DateTime
+from spyne.model.complex import Array
+from spyne.model.fault import Fault
 import os
 import socket
 from operator import itemgetter, attrgetter
@@ -677,7 +677,7 @@ class MutalyzerService(ServiceBase):
         result.molecule = O.getIndexedOutput('molecule', 0)
 
         # We force the results to strings here, because some results
-        # may be of type Bio.Seq.Seq which rpclib doesn't like.
+        # may be of type Bio.Seq.Seq which spyne doesn't like.
         #
         # todo: We might have to also do this elsewhere.
 
diff --git a/mutalyzer/services/soap.py b/mutalyzer/services/soap.py
index 31bb4e67d99376e8504c26af1a694dce1f19976d..e442b9d0f7b7fd045bdb505d1ac02379f89ba591 100644
--- a/mutalyzer/services/soap.py
+++ b/mutalyzer/services/soap.py
@@ -3,9 +3,9 @@ Mutalyzer SOAP/1.1 webservice.
 """
 
 
-from rpclib.application import Application
-from rpclib.protocol.soap import Soap11
-from rpclib.server.wsgi import WsgiApplication
+from spyne.application import Application
+from spyne.protocol.soap import Soap11
+from spyne.server.wsgi import WsgiApplication
 
 import mutalyzer
 from mutalyzer.services import rpc
@@ -20,6 +20,6 @@ application = Application([rpc.MutalyzerService], tns=mutalyzer.SOAP_NAMESPACE,
 # Below we define WSGI applications for use with e.g. Apache/mod_wsgi.
 # Note: We would like to create the wsgi.Application instance only in the
 #     bin/mutalyzer-webservice.wsgi script, but unfortunately this breaks the
-#     get_interface_document method of rpclib which we use to generate API
+#     get_interface_document method of spyne which we use to generate API
 #     documentation in website.py.
 wsgi_application = WsgiApplication(application)
diff --git a/mutalyzer/util.py b/mutalyzer/util.py
index efca9b86c31d152ebe105e79110af6d41c4852b8..df26186a858043a597458de2e0933dcae2288973 100644
--- a/mutalyzer/util.py
+++ b/mutalyzer/util.py
@@ -861,7 +861,7 @@ def monkey_patch_suds():
     Call this function before importing anything from the suds package. For
     example, start your file with the following:
 
-        import monkey; monkey.monkey_patch_suds()
+        from mutalyzer.util import monkey_patch_suds; monkey_patch_suds()
         from suds.client import Client
     """
     from suds.xsd.sxbasic import Import
@@ -879,3 +879,29 @@ def monkey_patch_suds():
     Import.open = _import_open_patched
     Import.MUTALYZER_MONKEY_PATCHED = True
 #monkey_patch_suds
+
+
+def monkey_patch_spyne():
+    """
+    Apply our monkey-patch for the spyne package.
+
+    Fault objects cannot be serialized by the JsonObject output protocol,
+    this fixes it.
+
+    Call this function before importing anything from the spyne package. For
+    example, start your file with the following:
+
+        from mutalyzer.util import monkey_patch_spyne; monkey_patch_spyne()
+        from spyne.protocol.json import JsonObject
+    """
+    from spyne.model.fault import Fault
+
+    if hasattr(Fault, '_to_dict'):
+        return
+
+    def _to_dict(self, *args, **kwargs):
+        return dict(Fault=dict(faultcode=self.faultcode,
+                               faultstring=self.faultstring))
+
+    Fault._to_dict = _to_dict
+#monkey_patch_spyne
diff --git a/mutalyzer/website.py b/mutalyzer/website.py
index c738a6731bace7a6ffffb8147d89a6a814abb22e..4dc460404d30297424cfb49d4b707377e478e7c2 100644
--- a/mutalyzer/website.py
+++ b/mutalyzer/website.py
@@ -29,7 +29,7 @@ from lxml import etree
 from cStringIO import StringIO
 from simpletal import simpleTALES
 from simpletal import simpleTAL
-from rpclib.interface.wsdl import Wsdl11
+from spyne.interface.wsdl import Wsdl11
 
 import mutalyzer
 from mutalyzer import util
diff --git a/tests/test_services_json.py b/tests/test_services_json.py
index 6055a185aee5447062c14f7050b5f3ad907b4f76..f235adbf34a538b979e1c0a8603d1521e453b575 100644
--- a/tests/test_services_json.py
+++ b/tests/test_services_json.py
@@ -30,7 +30,7 @@ class TestServicesJson():
         Running checkSyntax with a valid variant name should return True.
         """
         r = call('checkSyntax', variant='AB026906.1:c.274G>T')
-        assert_equal(r['CheckSyntaxOutput']['valid'], True)
+        assert_equal(r['checkSyntaxResponse']['checkSyntaxResult']['valid'], True)
 
     def test_checksyntax_invalid(self):
         """
@@ -38,8 +38,8 @@ class TestServicesJson():
         and give at least one error message.
         """
         r = call('checkSyntax', variant='0:abcd')
-        assert_equal(r['CheckSyntaxOutput']['valid'], False)
-        assert len(r['CheckSyntaxOutput']['messages']['SoapMessage']) >= 1
+        assert_equal(r['checkSyntaxResponse']['checkSyntaxResult']['valid'], False)
+        assert len(r['checkSyntaxResponse']['checkSyntaxResult']['messages']['SoapMessage']) >= 1
 
     def test_checksyntax_empty(self):
         """
@@ -55,14 +55,14 @@ class TestServicesJson():
         """
         r = call('transcriptInfo', LOVD_ver='123', build='hg19',
                  accNo='NM_002001.2')
-        assert_equal(r['Transcript']['trans_start'], -99)
-        assert_equal(r['Transcript']['trans_stop'], 1066)
-        assert_equal(r['Transcript']['CDS_stop'], 774)
+        assert_equal(r['transcriptInfoResponse']['transcriptInfoResult']['trans_start'], -99)
+        assert_equal(r['transcriptInfoResponse']['transcriptInfoResult']['trans_stop'], 1066)
+        assert_equal(r['transcriptInfoResponse']['transcriptInfoResult']['CDS_stop'], 774)
 
     def test_info(self):
         """
         Running the info method should give us some version information.
         """
         r = call('info')
-        assert_equal(type(r['InfoOutput']['versionParts']['string']), list)
-        assert_equal(r['InfoOutput']['version'], mutalyzer.__version__)
+        assert_equal(type(r['infoResponse']['infoResult']['versionParts']['string']), list)
+        assert_equal(r['infoResponse']['infoResult']['version'], mutalyzer.__version__)