diff --git a/src/ami.js/ctx.js b/src/ami.js/ctx.js
index 4aba53f..6356ed9 100644
--- a/src/ami.js/ctx.js
+++ b/src/ami.js/ctx.js
@@ -6,7 +6,6 @@
 #include messages.jsx
 #include notify.js
 #include reconnect.jsx
-#include servers.js
 #include settings.js
 #include sockchat.js
 #include sound.js
@@ -175,10 +174,9 @@ var AmiContext = function(title, auth, flashii, loading) {
     var emoticons = new AmiEmoticons;
     pub.emoticons = emoticons;
 
-    pub.servers = new AmiServers;
     pub.windowTitle = new AmiWindowTitle(title);
 
-    var sockChat = new AmiSockChat(auth);
+    var sockChat = new AmiSockChat(auth, flashii);
     pub.sockChat = sockChat;
 
     var chat = new AmiChat(pub, title, document.body);
diff --git a/src/ami.js/flashii.js b/src/ami.js/flashii.js
index 367c10f..a3428c3 100644
--- a/src/ami.js/flashii.js
+++ b/src/ami.js/flashii.js
@@ -94,6 +94,14 @@ const Flashii = function(baseUrl) {
 
     fii.v1 = {};
 
+    const verifyChatServerId = id => {
+        if(typeof id === 'number')
+            id = id.toString();
+        if(/^([^0-9]+)$/gu.test(id))
+            throw new Error('id argument is not an acceptable chat server id.');
+        return id;
+    };
+
     fii.v1.chat = {};
     fii.v1.chat.login = function({ redirect=null, assign=true }) {
         return new Commitment(success => {
@@ -111,6 +119,73 @@ const Flashii = function(baseUrl) {
                 success(url);
         });
     };
+    fii.v1.chat.servers = function({ proto=null, secure=null, fields=null, fresh=false }) {
+        return new Commitment((success, fail) => {
+            const params = {};
+
+            if(proto !== null && typeof proto !== 'string')
+                throw new Error('proto must be a string or null');
+            params['proto'] = proto;
+
+            if(secure !== null)
+                params['secure'] = secure ? '1' : '0';
+
+            send({ method: 'GET', path: '/v1/chat/servers', fields, fresh, params })
+                .success(({ status, body }) => {
+                    if(status === 400)
+                        throw new Error('An argument contains an unsupported value.');
+                    if(status > 299)
+                        throw new Error(`Failed to fetch chat server list with error code ${status}.`);
+
+                    success(body);
+                })
+                .fail(fail)
+                .run();
+        });
+    };
+    fii.v1.chat.servers.server = function({ id, fields=null, fresh=false }) {
+        return new Commitment((success, fail) => {
+            id = verifyChatServerId(id);
+
+            send({ method: 'GET', path: `/v1/chat/servers/${id}`, fields, fresh })
+                .success(({ status, body }) => {
+                    if(status === 400)
+                        throw new Error('Fields argument contains unsupported value.');
+                    if(status === 404)
+                        throw new Error('No chat server with that id could be found.');
+                    if(status > 299)
+                        throw new Error(`Failed to fetch chat server with error code ${status}.`);
+
+                    success(body);
+                })
+                .fail(fail)
+                .run();
+        });
+    };
+    fii.v1.chat.servers.recommended = function({ proto, secure=null, fields=null, fresh=false }) {
+        return new Commitment((success, fail) => {
+            if(typeof proto !== 'string')
+                throw new Error('proto must be a string');
+
+            const params = { proto };
+            if(secure !== null)
+                params['secure'] = secure ? '1' : '0';
+
+            send({ method: 'GET', path: '/v1/chat/servers/recommended', fields, fresh, params })
+                .success(({ status, body }) => {
+                    if(status === 400)
+                        throw new Error('An argument contains an unsupported value.');
+                    if(status === 404)
+                        throw new Error('Was unable to determine a server based on the requested parameters.');
+                    if(status > 299)
+                        throw new Error(`Failed to fetch recommended chat server with error code ${status}.`);
+
+                    success(body);
+                })
+                .fail(fail)
+                .run();
+        });
+    };
     fii.v1.chat.token = function() {
         return new Commitment((success, fail) => {
             send({ method: 'GET', path: '/v1/chat/token', authed: true, fresh: true })
diff --git a/src/ami.js/servers.js b/src/ami.js/servers.js
deleted file mode 100644
index 0321340..0000000
--- a/src/ami.js/servers.js
+++ /dev/null
@@ -1,21 +0,0 @@
-#include common.js
-
-var AmiServers = function() {
-    var servers = futami.get('servers').slice(0),
-        index = 0xFFFF;
-
-    $arrayShuffle(servers);
-
-    return {
-        getServer: function(callback) {
-            if(++index >= servers.length)
-                index = 0;
-
-            var server = servers[index];
-            if(server.indexOf('//') >= 0)
-                server = location.protocol.replace('http', 'ws') + server;
-
-            callback(server);
-        },
-    };
-};
diff --git a/src/ami.js/sockchat.js b/src/ami.js/sockchat.js
index de06b0b..e4ae00e 100644
--- a/src/ami.js/sockchat.js
+++ b/src/ami.js/sockchat.js
@@ -1,8 +1,7 @@
 #include auth.js
-#include servers.js
 #include watcher.js
 
-var AmiSockChat = function(auth) {
+var AmiSockChat = function(auth, flashii) {
     if(!AmiIsAuth(auth))
         throw new Error('auth param is not acceptable');
 
@@ -119,13 +118,16 @@ var AmiSockChat = function(auth) {
             wasConnected: wasConnected,
         }]);
 
-        ami.servers.getServer(function(server) {
-            sock = new WebSocket(server);
-            sock.addEventListener('open', onOpen);
-            sock.addEventListener('close', onClose);
-            sock.addEventListener('error', onError);
-            sock.addEventListener('message', onMessage);
-        }.bind(this));
+        flashii.v1.chat.servers.recommended({ proto: 'sockchat' })
+            .success(({ uri }) => {
+                sock = new WebSocket(uri);
+                sock.addEventListener('open', onOpen);
+                sock.addEventListener('close', onClose);
+                sock.addEventListener('error', onError);
+                sock.addEventListener('message', onMessage);
+            })
+            .fail(ex => { onError(ex); })
+            .run();
     };
 
     var formatBotMsg = function(type, args, isError) {