diff --git a/indra/lib/python/indra/base/config.py b/indra/lib/python/indra/base/config.py
index d88801aa0d0b7735ae688d0379daf5d3dd1a6cc9..86000cf98d08fa12fdd2182de3de52e93b202239 100644
--- a/indra/lib/python/indra/base/config.py
+++ b/indra/lib/python/indra/base/config.py
@@ -27,16 +27,20 @@ def load(indra_xml_file=None):
         config_file.close()
         #print "loaded config from",indra_xml_file,"into",_g_config_dict
 
-def update(xml_file):
+def update(new_conf):
     """Load an XML file and apply its map as overrides or additions
     to the existing config.  The dataserver does this with indra.xml
     and dataserver.xml."""
     global _g_config_dict
     if _g_config_dict == None:
-        raise Exception("no config loaded before config.update()")
-    config_file = file(xml_file)
-    overrides = llsd.LLSD().parse(config_file.read())
-    config_file.close()
+        _g_config_dict = {}
+    if isinstance(new_conf, dict):
+        overrides = new_conf
+    else:
+        config_file = file(new_conf)
+        overrides = llsd.LLSD().parse(config_file.read())
+        config_file.close()
+        
     _g_config_dict.update(overrides)
 
 def get(key, default = None):
@@ -44,3 +48,7 @@ def get(key, default = None):
     if _g_config_dict == None:
         load()
     return _g_config_dict.get(key, default)
+
+def as_dict():
+    global _g_config_dict
+    return _g_config_dict
diff --git a/indra/lib/python/indra/base/llsd.py b/indra/lib/python/indra/base/llsd.py
index 462a8787ae96b23617014c7a401b6c84e526600b..a03893bfc33a83739d02e48724e1e056d4ee7cd9 100644
--- a/indra/lib/python/indra/base/llsd.py
+++ b/indra/lib/python/indra/base/llsd.py
@@ -136,7 +136,8 @@ def __init__(self):
             list : self.ARRAY,
             tuple : self.ARRAY,
             types.GeneratorType : self.ARRAY,
-            dict : self.MAP
+            dict : self.MAP,
+            LLSD : self.LLSD
         }
 
     def elt(self, name, contents=None):
@@ -148,6 +149,8 @@ def elt(self, name, contents=None):
     def xml_esc(self, v):
         return v.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
 
+    def LLSD(self, v):
+        return self.generate(v.thing)
     def UNDEF(self, v):
         return self.elt('undef')
     def BOOLEAN(self, v):
@@ -212,9 +215,12 @@ def __init__(self):
             list : self.ARRAY,
             tuple : self.ARRAY,
             types.GeneratorType : self.ARRAY,
-            dict : self.MAP
+            dict : self.MAP,
+            LLSD : self.LLSD
         }
 
+    def LLSD(self, v):
+        return self.generate(v.thing)
     def UNDEF(self, v):
         return '!'
     def BOOLEAN(self, v):
@@ -739,6 +745,8 @@ def format_binary(something):
 def _format_binary_recurse(something):
     if something is None:
         return '!'
+    elif isinstance(something, LLSD):
+        return _format_binary_recurse(something.thing)
     elif isinstance(something, bool):
         if something:
             return '1'
@@ -807,3 +815,36 @@ def __str__(self):
 
 undef = LLSD(None)
 
+# register converters for stacked, if stacked is available
+try:
+    from mulib import stacked
+except ImportError, e:
+    print "Not able to import stacked, skipping registering llsd converters."
+    pass  # don't bother with the converters
+else:
+    def llsd_convert_json(llsd_stuff, request):
+        callback = request.get_header('callback')
+        if callback is not None:
+            ## See Yahoo's ajax documentation for information about using this
+            ## callback style of programming
+            ## http://developer.yahoo.com/common/json.html#callbackparam
+            req.write("%s(%s)" % (callback, simplejson.dumps(llsd_stuff)))
+        else:
+            req.write(simplejson.dumps(llsd_stuff))
+
+    def llsd_convert_xml(llsd_stuff, request):
+        request.write(format_xml(llsd_stuff))
+
+    def llsd_convert_binary(llsd_stuff, request):
+        request.write(format_binary(llsd_stuff))
+
+    for typ in [LLSD, dict, list, tuple, str, int, float, bool, unicode, type(None)]:
+        stacked.add_producer(typ, llsd_convert_json, 'application/json')
+
+        stacked.add_producer(typ, llsd_convert_xml, 'application/llsd+xml')
+        stacked.add_producer(typ, llsd_convert_xml, 'application/xml')
+        stacked.add_producer(typ, llsd_convert_xml, 'text/xml')
+
+        stacked.add_producer(typ, llsd_convert_binary, 'application/llsd+binary')
+
+    stacked.add_producer(LLSD, llsd_convert_xml, '*/*')
diff --git a/indra/lib/python/indra/base/lluuid.py b/indra/lib/python/indra/base/lluuid.py
index 62ed365cab9e6c13dbe3959cd2c5880071e85d9f..f07446bba30b9090527b2934cb3e8f66b14e4e23 100644
--- a/indra/lib/python/indra/base/lluuid.py
+++ b/indra/lib/python/indra/base/lluuid.py
@@ -258,11 +258,12 @@ def uuid_bits_to_uuid(bits):
 
 
 try:
-    from mulib import mu
+    from mulib import stacked
 except ImportError:
     print "Couldn't import mulib, not registering UUID converter"
 else:
-    def convertUUID(req, uuid):
-        return str(uuid)
+    def convertUUID(uuid, req):
+        req.write(str(uuid))
 
-    mu.registerConverter(UUID, convertUUID)
+    stacked.add_producer(UUID, convertUUID, "*/*")
+    stacked.add_producer(UUID, convertUUID, "text/html")
diff --git a/indra/lib/python/indra/ipc/llsdhttp.py b/indra/lib/python/indra/ipc/llsdhttp.py
index cffff6b24b6d54221f076e9f5dd1c9f6f713b8b1..b5c15d1c2b1f16b3602b47d19b22af8a3f919afb 100644
--- a/indra/lib/python/indra/ipc/llsdhttp.py
+++ b/indra/lib/python/indra/ipc/llsdhttp.py
@@ -10,251 +10,55 @@
 import os
 import urlparse
 
-
-from eventlet import httpc as httputil
-
-
-
 from indra.base import llsd
-LLSD = llsd.LLSD()
-
-
-class ConnectionError(Exception):
-    def __init__(self, method, host, port, path, status, reason, body):
-        self.method = method
-        self.host = host
-        self.port = port
-        self.path = path
-        self.status = status
-        self.reason = reason
-        self.body = body
-        Exception.__init__(self)
-
-    def __str__(self):
-        return "%s(%r, %r, %r, %r, %r, %r, %r)" % (
-            self.__class__.__name__,
-            self.method, self.host, self.port,
-            self.path, self.status, self.reason, self.body)
-
-
-class NotFound(ConnectionError):
-    pass
-
-class Forbidden(ConnectionError):
-    pass
-
-class MalformedResponse(ConnectionError):
-    pass
-
-class NotImplemented(ConnectionError):
-    pass
-
-def runConnection(connection, raise_parse_errors=True):
-    response = connection.getresponse()
-    if (response.status not in [200, 201, 204]):
-        klass = {404:NotFound,
-                 403:Forbidden,
-                 501:NotImplemented}.get(response.status, ConnectionError)
-        raise klass(
-            connection.method, connection.host, connection.port,
-            connection.path, response.status, response.reason, response.read())
-    content_length = response.getheader('content-length')
-
-    if content_length: # Check to see whether it is not None
-        content_length = int(content_length)
-
-    if content_length: # Check to see whether the length is not 0
-        body = response.read(content_length)
-    else:
-        body = ''
-
-    if not body.strip():
-        #print "No body:", `body`
-        return None
-    try:
-        return LLSD.parse(body)
-    except Exception, e:
-        if raise_parse_errors:
-            print "Exception: %s, Could not parse LLSD: " % (e), body
-            raise MalformedResponse(
-            connection.method, connection.host, connection.port,
-            connection.path, response.status, response.reason, body)
-        else:
-            return None
-
-class FileScheme(object):
-    """Retarded scheme to local file wrapper."""
-    host = '<file>'
-    port = '<file>'
-    reason = '<none>'
-
-    def __init__(self, location):
-        pass
 
-    def request(self, method, fullpath, body='', headers=None):
-        self.status = 200
-        self.path = fullpath.split('?')[0]
-        self.method = method = method.lower()
-        assert method in ('get', 'put', 'delete')
-        if method == 'delete':
-            try:
-                os.remove(self.path)
-            except OSError:
-                pass  # don't complain if already deleted
-        elif method == 'put':
-            try:
-                f = file(self.path, 'w')
-                f.write(body)
-                f.close()
-            except IOError, e:
-                self.status = 500
-                self.raise_connection_error()
-        elif method == 'get':
-            if not os.path.exists(self.path):
-                self.status = 404
-                self.raise_connection_error(NotFound)
+from eventlet import httpc
 
-    def connect(self):
-        pass
 
-    def getresponse(self):
-        return self
+get, put, delete, post = httpc.make_suite(
+    llsd.format_xml, llsd.parse, 'application/xml+llsd')
 
-    def getheader(self, header):
-        if header == 'content-length':
-            try:
-                return os.path.getsize(self.path)
-            except OSError:
-                return 0
 
-    def read(self, howmuch=None):
-        if self.method == 'get':
-            try:
-                return file(self.path, 'r').read(howmuch)
-            except IOError:
-                self.status = 500
-                self.raise_connection_error()
-        return ''
+for x in (httpc.ConnectionError, httpc.NotFound, httpc.Forbidden):
+    globals()[x.__name__] = x
 
-    def raise_connection_error(self, klass=ConnectionError):
-        raise klass(
-            self.method, self.host, self.port,
-            self.path, self.status, self.reason, '')
 
-scheme_to_factory_map = {
-    'http': httputil.HttpClient,
-    'https': httputil.HttpsClient,
-    'file': FileScheme,
-}
-
-def makeConnection(scheme, location, use_proxy):
-    if use_proxy:
-        if "http_proxy" in os.environ:
-            location = os.environ["http_proxy"]
-        elif "ALL_PROXY" in os.environ:
-            location = os.environ["ALL_PROXY"]
-        else:
-            location = "localhost:3128" #default to local squid
-        if location.startswith("http://"):
-            location = location[len("http://"):]
-    return scheme_to_factory_map[scheme](location)
-
-
-def get(url, headers=None, use_proxy=False):
-    if headers is None:
-        headers = {}
-    scheme, location, path, params, query, id = urlparse.urlparse(url)
-    connection = makeConnection(scheme, location, use_proxy=use_proxy)
-    fullpath = path
-    if query:
-        fullpath += "?"+query
-    connection.connect()
-    if headers is None:
-        headers=dict()
-    if use_proxy:
-        headers.update({ "Host" : location })
-        connection.request("GET", url, headers=headers)
-    else:
-        connection.request("GET", fullpath, headers=headers)
-
-    return runConnection(connection)
-
-def put(url, data, headers=None):
-    body = LLSD.toXML(data)
-    scheme, location, path, params, query, id = urlparse.urlparse(url)
-    connection = makeConnection(scheme, location, use_proxy=False)
-    if headers is None:
-        headers = {}
-    headers.update({'Content-Type': 'application/xml'})
-    fullpath = path
-    if query:
-        fullpath += "?"+query
-    connection.request("PUT", fullpath, body, headers)
-    return runConnection(connection, raise_parse_errors=False)
-
-def delete(url):
-    scheme, location, path, params, query, id = urlparse.urlparse(url)
-    connection = makeConnection(scheme, location, use_proxy=False)
-    connection.request("DELETE", path+"?"+query)
-    return runConnection(connection, raise_parse_errors=False)
-
-def post(url, data=None):
-    body = LLSD.toXML(data)
-    scheme, location, path, params, query, id = urlparse.urlparse(url)
-    connection = makeConnection(scheme, location, use_proxy=False)
-    connection.request("POST", path+"?"+query, body, {'Content-Type': 'application/xml'})
-    return runConnection(connection)
-
-def postFile(url, filename):
+def postFile(url, filename, verbose=False):
     f = open(filename)
     body = f.read()
     f.close()
-    scheme, location, path, params, query, id = urlparse.urlparse(url)
-    connection = makeConnection(scheme, location, use_proxy=False)
-    connection.request("POST", path+"?"+query, body, {'Content-Type': 'application/octet-stream'})
-    return runConnection(connection)
+    llsd_body = llsd.parse(bodY)
+    return post(url, llsd_body, verbose=verbose)
+
 
 def getStatus(url, use_proxy=False):
-    scheme, location, path, params, query, id = urlparse.urlparse(url)
-    connection = makeConnection(scheme, location, use_proxy=use_proxy)
-    if use_proxy:
-        connection.request("GET", url, headers={ "Host" : location })
-    else:
-        connection.request("GET", path+"?"+query)
-    return connection.getresponse().status
+    status, _headers, _body = get(url, use_proxy=use_proxy, verbose=True)
+    return status
+
 
 def putStatus(url, data):
-    body = LLSD.toXML(data)
-    scheme, location, path, params, query, id = urlparse.urlparse(url)
-    connection = makeConnection(scheme, location, use_proxy=False)
-    connection.request("PUT", path+"?"+query, body, {'Content-Type': 'application/xml'})
-    return connection.getresponse().status
+    status, _headers, _body = put(url, data, verbose=True)
+    return status
+
 
 def deleteStatus(url):
-    scheme, location, path, params, query, id = urlparse.urlparse(url)
-    connection = makeConnection(scheme, location, use_proxy=False)
-    connection.request("DELETE", path+"?"+query)
-    return connection.getresponse().status
+    status, _headers, _body = delete(url, verbose=True)
+    return status
+
 
 def postStatus(url, data):
-    body = LLSD.toXML(data)
-    scheme, location, path, params, query, id = urlparse.urlparse(url)
-    connection = makeConnection(scheme, location, use_proxy=False)
-    connection.request("POST", path+"?"+query, body)
-    return connection.getresponse().status
+    status, _headers, _body = post(url, data, verbose=True)
+    return status
+
 
 def postFileStatus(url, filename):
-    f = open(filename)
-    body = f.read()
-    f.close()
-    scheme, location, path, params, query, id = urlparse.urlparse(url)
-    connection = makeConnection(scheme, location, use_proxy=False)
-    connection.request("POST", path+"?"+query, body, {'Content-Type': 'application/octet-stream'})
-    response = connection.getresponse()
-    return response.status, response.read()
+    status, _headers, body = postFile(url, filename, verbose=True)
+    return status, body
+
 
 def getFromSimulator(path, use_proxy=False):
     return get('http://' + simulatorHostAndPort + path, use_proxy=use_proxy)
 
+
 def postToSimulator(path, data=None):
     return post('http://' + simulatorHostAndPort + path, data)
diff --git a/indra/lib/python/indra/ipc/servicebuilder.py b/indra/lib/python/indra/ipc/servicebuilder.py
index 05de1ee5c5c35257a964c736322e817d4c8d9a7a..289b9589d2c1635797fb22da7947c68deedeb78c 100644
--- a/indra/lib/python/indra/ipc/servicebuilder.py
+++ b/indra/lib/python/indra/ipc/servicebuilder.py
@@ -11,15 +11,28 @@
 from indra.ipc import llsdhttp
 from indra.ipc import russ
 
+# *NOTE: agent presence relies on this variable existing and being current, it is a huge hack
 services_config = {}
 try:
     services_config = llsdhttp.get(config.get('services-config'))
 except:
     pass
 
-# convenience method for when you can't be arsed to make your own object (i.e. all the time)
 _g_builder = None
-def build(name, context):
+def build(name, context={}, **kwargs):
+    """ Convenience method for using a global, singleton, service builder.  Pass arguments either via a dict or via python keyword arguments, or both!
+
+    Example use:
+     > context = {'channel':'Second Life Release', 'version':'1.18.2.0'}
+     > servicebuilder.build('version-manager-version', context)
+       'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.2.0'
+     > servicebuilder.build('version-manager-version', channel='Second Life Release', version='1.18.2.0')
+       'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.2.0'
+     > servicebuilder.build('version-manager-version', context, version='1.18.1.2')
+       'http://int.util.vaak.lindenlab.com/channel/Second%20Life%20Release/1.18.1.2'
+    """
+    context = context.copy()  # shouldn't modify the caller's dictionary
+    context.update(kwargs)
     global _g_builder
     if _g_builder is None:
         _g_builder = ServiceBuilder()
diff --git a/indra/lib/python/indra/ipc/xml_rpc.py b/indra/lib/python/indra/ipc/xml_rpc.py
index 66375b4ac35745c9185e08d10d59e1d87ce4e953..c5b5bcd5670b5c5ed2dc210ada2c8e4980a161d2 100644
--- a/indra/lib/python/indra/ipc/xml_rpc.py
+++ b/indra/lib/python/indra/ipc/xml_rpc.py
@@ -189,19 +189,19 @@ def handle(yielder):
     return result
 
 
-VALUE = mu.tagFactory('value')
-BOOLEAN = mu.tagFactory('boolean')
-INT = mu.tagFactory('int')
-STRUCT = mu.tagFactory('struct')
-MEMBER = mu.tagFactory('member')
-NAME = mu.tagFactory('name')
-ARRAY = mu.tagFactory('array')
-DATA = mu.tagFactory('data')
-STRING = mu.tagFactory('string')
-DOUBLE = mu.tagFactory('double')
-METHODRESPONSE = mu.tagFactory('methodResponse')
-PARAMS = mu.tagFactory('params')
-PARAM = mu.tagFactory('param')
+VALUE = mu.tag_factory('value')
+BOOLEAN = mu.tag_factory('boolean')
+INT = mu.tag_factory('int')
+STRUCT = mu.tag_factory('struct')
+MEMBER = mu.tag_factory('member')
+NAME = mu.tag_factory('name')
+ARRAY = mu.tag_factory('array')
+DATA = mu.tag_factory('data')
+STRING = mu.tag_factory('string')
+DOUBLE = mu.tag_factory('double')
+METHODRESPONSE = mu.tag_factory('methodResponse')
+PARAMS = mu.tag_factory('params')
+PARAM = mu.tag_factory('param')
 
 mu.inline_elements['string'] = True
 mu.inline_elements['boolean'] = True