diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py
index 609faf5aad..f3315b9dc2 100644
--- a/openstackclient/compute/v2/server.py
+++ b/openstackclient/compute/v2/server.py
@@ -66,6 +66,28 @@ class PowerStateColumn(cliff_columns.FormattableColumn):
             return 'N/A'
 
 
+class AddressesColumn(cliff_columns.FormattableColumn):
+    """Generate a formatted string of a server's addresses."""
+
+    def human_readable(self):
+        try:
+            return utils.format_dict_of_list({
+                k: [i['addr'] for i in v if 'addr' in i]
+                for k, v in self._value.items()})
+        except Exception:
+            return 'N/A'
+
+
+class HostColumn(cliff_columns.FormattableColumn):
+    """Generate a formatted string of a hostname."""
+
+    def human_readable(self):
+        if self._value is None:
+            return ''
+
+        return self._value
+
+
 def _get_ip_address(addresses, address_type, ip_address_family):
     # Old style addresses
     if address_type in addresses:
@@ -2287,7 +2309,7 @@ class ListServer(command.Lister):
         return parser
 
     def take_action(self, parsed_args):
-        compute_client = self.app.client_manager.compute
+        compute_client = self.app.client_manager.sdk_connection.compute
         identity_client = self.app.client_manager.identity
         image_client = self.app.client_manager.image
 
@@ -2312,10 +2334,11 @@ class ListServer(command.Lister):
         # flavor name is given, map it to ID.
         flavor_id = None
         if parsed_args.flavor:
-            flavor_id = utils.find_resource(
-                compute_client.flavors,
-                parsed_args.flavor,
-            ).id
+            flavor = compute_client.find_flavor(parsed_args.flavor)
+            if flavor is None:
+                msg = _('Unable to find flavor: %s') % parsed_args.flavor
+                raise exceptions.CommandError(msg)
+            flavor_id = flavor.id
 
         # Nova only supports list servers searching by image ID. So if a
         # image name is given, map it to ID.
@@ -2331,19 +2354,21 @@ class ListServer(command.Lister):
             'ip': parsed_args.ip,
             'ip6': parsed_args.ip6,
             'name': parsed_args.name,
-            'instance_name': parsed_args.instance_name,
             'status': parsed_args.status,
             'flavor': flavor_id,
             'image': image_id,
             'host': parsed_args.host,
-            'tenant_id': project_id,
-            'all_tenants': parsed_args.all_projects,
+            'project_id': project_id,
+            'all_projects': parsed_args.all_projects,
             'user_id': user_id,
             'deleted': parsed_args.deleted,
             'changes-before': parsed_args.changes_before,
             'changes-since': parsed_args.changes_since,
         }
 
+        if parsed_args.instance_name is not None:
+            search_opts['instance_name'] = parsed_args.instance_name
+
         if parsed_args.availability_zone:
             search_opts['availability_zone'] = parsed_args.availability_zone
 
@@ -2375,7 +2400,7 @@ class ListServer(command.Lister):
             search_opts['power_state'] = power_state
 
         if parsed_args.tags:
-            if compute_client.api_version < api_versions.APIVersion('2.26'):
+            if not sdk_utils.supports_microversion(compute_client, '2.26'):
                 msg = _(
                     '--os-compute-api-version 2.26 or greater is required to '
                     'support the --tag option'
@@ -2385,7 +2410,7 @@ class ListServer(command.Lister):
             search_opts['tags'] = ','.join(parsed_args.tags)
 
         if parsed_args.not_tags:
-            if compute_client.api_version < api_versions.APIVersion('2.26'):
+            if not sdk_utils.supports_microversion(compute_client, '2.26'):
                 msg = _(
                     '--os-compute-api-version 2.26 or greater is required to '
                     'support the --not-tag option'
@@ -2395,7 +2420,7 @@ class ListServer(command.Lister):
             search_opts['not-tags'] = ','.join(parsed_args.not_tags)
 
         if parsed_args.locked:
-            if compute_client.api_version < api_versions.APIVersion('2.73'):
+            if not sdk_utils.supports_microversion(compute_client, '2.73'):
                 msg = _(
                     '--os-compute-api-version 2.73 or greater is required to '
                     'support the --locked option'
@@ -2404,7 +2429,7 @@ class ListServer(command.Lister):
 
             search_opts['locked'] = True
         elif parsed_args.unlocked:
-            if compute_client.api_version < api_versions.APIVersion('2.73'):
+            if not sdk_utils.supports_microversion(compute_client, '2.73'):
                 msg = _(
                     '--os-compute-api-version 2.73 or greater is required to '
                     'support the --unlocked option'
@@ -2413,10 +2438,14 @@ class ListServer(command.Lister):
 
             search_opts['locked'] = False
 
+        if parsed_args.limit is not None:
+            search_opts['limit'] = parsed_args.limit
+            search_opts['paginated'] = False
+
         LOG.debug('search options: %s', search_opts)
 
         if search_opts['changes-before']:
-            if compute_client.api_version < api_versions.APIVersion('2.66'):
+            if not sdk_utils.supports_microversion(compute_client, '2.66'):
                 msg = _('--os-compute-api-version 2.66 or later is required')
                 raise exceptions.CommandError(msg)
 
@@ -2450,15 +2479,15 @@ class ListServer(command.Lister):
 
         if parsed_args.long:
             columns += (
-                'OS-EXT-STS:task_state',
-                'OS-EXT-STS:power_state',
+                'task_state',
+                'power_state',
             )
             column_headers += (
                 'Task State',
                 'Power State',
             )
 
-        columns += ('networks',)
+        columns += ('addresses',)
         column_headers += ('Networks',)
 
         if parsed_args.long:
@@ -2480,7 +2509,7 @@ class ListServer(command.Lister):
         # microversion 2.47 puts the embedded flavor into the server response
         # body but omits the id, so if not present we just expose the original
         # flavor name in the output
-        if compute_client.api_version >= api_versions.APIVersion('2.47'):
+        if sdk_utils.supports_microversion(compute_client, '2.47'):
             columns += ('flavor_name',)
             column_headers += ('Flavor',)
         else:
@@ -2502,8 +2531,8 @@ class ListServer(command.Lister):
 
         if parsed_args.long:
             columns += (
-                'OS-EXT-AZ:availability_zone',
-                'OS-EXT-SRV-ATTR:host',
+                'availability_zone',
+                'hypervisor_hostname',
                 'metadata',
             )
             column_headers += (
@@ -2512,40 +2541,38 @@ class ListServer(command.Lister):
                 'Properties',
             )
 
-        marker_id = None
-
         # support for additional columns
         if parsed_args.columns:
             for c in parsed_args.columns:
                 if c in ('Project ID', 'project_id'):
-                    columns += ('tenant_id',)
+                    columns += ('project_id',)
                     column_headers += ('Project ID',)
                 if c in ('User ID', 'user_id'):
                     columns += ('user_id',)
                     column_headers += ('User ID',)
                 if c in ('Created At', 'created_at'):
-                    columns += ('created',)
+                    columns += ('created_at',)
                     column_headers += ('Created At',)
                 if c in ('Security Groups', 'security_groups'):
                     columns += ('security_groups_name',)
                     column_headers += ('Security Groups',)
                 if c in ("Task State", "task_state"):
-                    columns += ('OS-EXT-STS:task_state',)
+                    columns += ('task_state',)
                     column_headers += ('Task State',)
                 if c in ("Power State", "power_state"):
-                    columns += ('OS-EXT-STS:power_state',)
+                    columns += ('power_state',)
                     column_headers += ('Power State',)
                 if c in ("Image ID", "image_id"):
                     columns += ('Image ID',)
                     column_headers += ('Image ID',)
                 if c in ("Flavor ID", "flavor_id"):
-                    columns += ('Flavor ID',)
+                    columns += ('flavor_id',)
                     column_headers += ('Flavor ID',)
                 if c in ('Availability Zone', "availability_zone"):
-                    columns += ('OS-EXT-AZ:availability_zone',)
+                    columns += ('availability_zone',)
                     column_headers += ('Availability Zone',)
                 if c in ('Host', "host"):
-                    columns += ('OS-EXT-SRV-ATTR:host',)
+                    columns += ('hypervisor_hostname',)
                     column_headers += ('Host',)
                 if c in ('Properties', "properties"):
                     columns += ('Metadata',)
@@ -2555,7 +2582,7 @@ class ListServer(command.Lister):
             column_headers = tuple(column_headers)
             columns = tuple(columns)
 
-        if parsed_args.marker:
+        if parsed_args.marker is not None:
             # Check if both "--marker" and "--deleted" are used.
             # In that scenario a lookup is not needed as the marker
             # needs to be an ID, because find_resource does not
@@ -2563,16 +2590,10 @@ class ListServer(command.Lister):
             if parsed_args.deleted:
                 marker_id = parsed_args.marker
             else:
-                marker_id = utils.find_resource(
-                    compute_client.servers,
-                    parsed_args.marker,
-                ).id
+                marker_id = compute_client.find_server(parsed_args.marker).id
+            search_opts['marker'] = marker_id
 
-        data = compute_client.servers.list(
-            search_opts=search_opts,
-            marker=marker_id,
-            limit=parsed_args.limit,
-        )
+        data = list(compute_client.servers(**search_opts))
 
         images = {}
         flavors = {}
@@ -2627,12 +2648,12 @@ class ListServer(command.Lister):
                     # "Flavor Name" is not crucial, so we swallow any
                     # exceptions
                     try:
-                        flavors[f_id] = compute_client.flavors.get(f_id)
+                        flavors[f_id] = compute_client.find_flavor(f_id)
                     except Exception:
                         pass
             else:
                 try:
-                    flavors_list = compute_client.flavors.list(is_public=None)
+                    flavors_list = compute_client.flavors(is_public=None)
                     for i in flavors_list:
                         flavors[i.id] = i
                 except Exception:
@@ -2641,7 +2662,7 @@ class ListServer(command.Lister):
         # Populate image_name, image_id, flavor_name and flavor_id attributes
         # of server objects so that we can display those columns.
         for s in data:
-            if compute_client.api_version >= api_versions.APIVersion('2.69'):
+            if sdk_utils.supports_microversion(compute_client, '2.69'):
                 # NOTE(tssurya): From 2.69, we will have the keys 'flavor'
                 # and 'image' missing in the server response during
                 # infrastructure failure situations.
@@ -2650,7 +2671,7 @@ class ListServer(command.Lister):
                 if not hasattr(s, 'image') or not hasattr(s, 'flavor'):
                     continue
 
-            if 'id' in s.image:
+            if 'id' in s.image and s.image.id is not None:
                 image = images.get(s.image['id'])
                 if image:
                     s.image_name = image.name
@@ -2663,7 +2684,7 @@ class ListServer(command.Lister):
                 s.image_name = IMAGE_STRING_FOR_BFV
                 s.image_id = IMAGE_STRING_FOR_BFV
 
-            if compute_client.api_version < api_versions.APIVersion('2.47'):
+            if not sdk_utils.supports_microversion(compute_client, '2.47'):
                 flavor = flavors.get(s.flavor['id'])
                 if flavor:
                     s.flavor_name = flavor.name
@@ -2673,7 +2694,7 @@ class ListServer(command.Lister):
 
         # Add a list with security group name as attribute
         for s in data:
-            if hasattr(s, 'security_groups'):
+            if hasattr(s, 'security_groups') and s.security_groups is not None:
                 s.security_groups_name = [x["name"] for x in s.security_groups]
             else:
                 s.security_groups_name = []
@@ -2686,10 +2707,10 @@ class ListServer(command.Lister):
         # it's on, providing useful information to a user in this
         # situation.
         if (
-            compute_client.api_version >= api_versions.APIVersion('2.16') and
+            sdk_utils.supports_microversion(compute_client, '2.16') and
             parsed_args.long
         ):
-            if any([hasattr(s, 'host_status') for s in data]):
+            if any([s.host_status is not None for s in data]):
                 columns += ('Host Status',)
                 column_headers += ('Host Status',)
 
@@ -2699,16 +2720,17 @@ class ListServer(command.Lister):
                 utils.get_item_properties(
                     s, columns,
                     mixed_case_fields=(
-                        'OS-EXT-STS:task_state',
-                        'OS-EXT-STS:power_state',
-                        'OS-EXT-AZ:availability_zone',
-                        'OS-EXT-SRV-ATTR:host',
+                        'task_state',
+                        'power_state',
+                        'availability_zone',
+                        'host',
                     ),
                     formatters={
-                        'OS-EXT-STS:power_state': PowerStateColumn,
-                        'networks': format_columns.DictListColumn,
+                        'power_state': PowerStateColumn,
+                        'addresses': AddressesColumn,
                         'metadata': format_columns.DictColumn,
                         'security_groups_name': format_columns.ListColumn,
+                        'hypervisor_hostname': HostColumn,
                     },
                 ) for s in data
             ),
diff --git a/openstackclient/tests/functional/compute/v2/test_server.py b/openstackclient/tests/functional/compute/v2/test_server.py
index 0558ef6213..8c62fa9d45 100644
--- a/openstackclient/tests/functional/compute/v2/test_server.py
+++ b/openstackclient/tests/functional/compute/v2/test_server.py
@@ -105,7 +105,7 @@ class ServerTests(common.ComputeTestCase):
                 'server list -f json --deleted --marker ' + name2
             ))
         except exceptions.CommandFailed as e:
-            self.assertIn('marker [%s] not found (HTTP 400)' % (name2),
+            self.assertIn('marker [%s] not found' % (name2),
                           e.stderr.decode('utf-8'))
 
     def test_server_list_with_changes_before(self):
diff --git a/openstackclient/tests/unit/compute/v2/test_server.py b/openstackclient/tests/unit/compute/v2/test_server.py
index f59c954a3b..45aff6a370 100644
--- a/openstackclient/tests/unit/compute/v2/test_server.py
+++ b/openstackclient/tests/unit/compute/v2/test_server.py
@@ -117,6 +117,21 @@ class TestServer(compute_fakes.TestComputev2):
         # Set object methods to be tested. Could be overwritten in subclass.
         self.methods = {}
 
+        patcher = mock.patch.object(
+            sdk_utils, 'supports_microversion', return_value=True)
+        self.addCleanup(patcher.stop)
+        self.supports_microversion_mock = patcher.start()
+        self._set_mock_microversion(
+            self.app.client_manager.compute.api_version.get_string())
+
+    def _set_mock_microversion(self, mock_v):
+        """Set a specific microversion for the mock supports_microversion()."""
+        self.supports_microversion_mock.reset_mock(return_value=True)
+
+        self.supports_microversion_mock.side_effect = (
+            lambda _, v:
+            api_versions.APIVersion(v) <= api_versions.APIVersion(mock_v))
+
     def setup_servers_mock(self, count):
         # If we are creating more than one server, make one of them
         # boot-from-volume
@@ -4448,32 +4463,25 @@ class _TestServerList(TestServer):
     def setUp(self):
         super(_TestServerList, self).setUp()
 
-        self.search_opts = {
+        # Default params of the core function of the command in the case of no
+        # commandline option specified.
+        self.kwargs = {
             'reservation_id': None,
             'ip': None,
             'ip6': None,
             'name': None,
-            'instance_name': None,
             'status': None,
             'flavor': None,
             'image': None,
             'host': None,
-            'tenant_id': None,
-            'all_tenants': False,
+            'project_id': None,
+            'all_projects': False,
             'user_id': None,
             'deleted': False,
             'changes-since': None,
             'changes-before': None,
         }
 
-        # Default params of the core function of the command in the case of no
-        # commandline option specified.
-        self.kwargs = {
-            'search_opts': self.search_opts,
-            'marker': None,
-            'limit': None,
-        }
-
         # The fake servers' attributes. Use the original attributes names in
         # nova, not the ones printed by "server list" command.
         self.attrs = {
@@ -4488,10 +4496,6 @@ class _TestServerList(TestServer):
             'Metadata': format_columns.DictColumn({}),
         }
 
-        # The servers to be listed.
-        self.servers = self.setup_servers_mock(3)
-        self.servers_mock.list.return_value = self.servers
-
         self.image = image_fakes.create_one_image()
 
         # self.images_mock.return_value = [self.image]
@@ -4499,7 +4503,12 @@ class _TestServerList(TestServer):
         self.get_image_mock.return_value = self.image
 
         self.flavor = compute_fakes.FakeFlavor.create_one_flavor()
-        self.flavors_mock.get.return_value = self.flavor
+        self.sdk_client.find_flavor.return_value = self.flavor
+        self.attrs['flavor'] = {'original_name': self.flavor.name}
+
+        # The servers to be listed.
+        self.servers = self.setup_sdk_servers_mock(3)
+        self.sdk_client.servers.return_value = self.servers
 
         # Get the command object to test
         self.cmd = server.ListServer(self.app, None)
@@ -4518,7 +4527,7 @@ class TestServerList(_TestServerList):
         ]
 
         Flavor = collections.namedtuple('Flavor', 'id name')
-        self.flavors_mock.list.return_value = [
+        self.sdk_client.flavors.return_value = [
             Flavor(id=s.flavor['id'], name=self.flavor.name)
             for s in self.servers
         ]
@@ -4528,7 +4537,7 @@ class TestServerList(_TestServerList):
                 s.id,
                 s.name,
                 s.status,
-                format_columns.DictListColumn(s.networks),
+                server.AddressesColumn(s.addresses),
                 # Image will be an empty string if boot-from-volume
                 self.image.name if s.image else server.IMAGE_STRING_FOR_BFV,
                 self.flavor.name,
@@ -4547,9 +4556,9 @@ class TestServerList(_TestServerList):
 
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
         self.images_mock.assert_called()
-        self.flavors_mock.list.assert_called()
+        self.sdk_client.flavors.assert_called()
         # we did not pass image or flavor, so gets on those must be absent
         self.assertFalse(self.flavors_mock.get.call_count)
         self.assertFalse(self.get_image_mock.call_count)
@@ -4564,14 +4573,14 @@ class TestServerList(_TestServerList):
             ('deleted', False),
         ]
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
-        self.servers_mock.list.return_value = []
+        self.sdk_client.servers.return_value = []
         self.data = ()
 
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
         self.images_mock.assert_not_called()
-        self.flavors_mock.list.assert_not_called()
+        self.sdk_client.flavors.assert_not_called()
         self.assertEqual(self.columns, columns)
         self.assertEqual(self.data, tuple(data))
 
@@ -4581,19 +4590,19 @@ class TestServerList(_TestServerList):
                 s.id,
                 s.name,
                 s.status,
-                getattr(s, 'OS-EXT-STS:task_state'),
+                getattr(s, 'task_state'),
                 server.PowerStateColumn(
-                    getattr(s, 'OS-EXT-STS:power_state')
+                    getattr(s, 'power_state')
                 ),
-                format_columns.DictListColumn(s.networks),
+                server.AddressesColumn(s.addresses),
                 # Image will be an empty string if boot-from-volume
                 self.image.name if s.image else server.IMAGE_STRING_FOR_BFV,
                 s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV,
                 self.flavor.name,
                 s.flavor['id'],
-                getattr(s, 'OS-EXT-AZ:availability_zone'),
-                getattr(s, 'OS-EXT-SRV-ATTR:host'),
-                s.Metadata,
+                getattr(s, 'availability_zone'),
+                server.HostColumn(getattr(s, 'hypervisor_hostname')),
+                format_columns.DictColumn(s.metadata),
             ) for s in self.servers
         )
         arglist = [
@@ -4606,12 +4615,12 @@ class TestServerList(_TestServerList):
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
 
         columns, data = self.cmd.take_action(parsed_args)
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
         image_ids = {s.image['id'] for s in self.servers if s.image}
         self.images_mock.assert_called_once_with(
             id=f'in:{",".join(image_ids)}',
         )
-        self.flavors_mock.list.assert_called_once_with(is_public=None)
+        self.sdk_client.flavors.assert_called_once_with(is_public=None)
         self.assertEqual(self.columns_long, columns)
         self.assertEqual(self.data, tuple(data))
 
@@ -4637,7 +4646,7 @@ class TestServerList(_TestServerList):
 
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
         self.assertIn('Project ID', columns)
         self.assertIn('User ID', columns)
         self.assertIn('Created At', columns)
@@ -4656,7 +4665,7 @@ class TestServerList(_TestServerList):
                 s.id,
                 s.name,
                 s.status,
-                format_columns.DictListColumn(s.networks),
+                server.AddressesColumn(s.addresses),
                 # Image will be an empty string if boot-from-volume
                 s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV,
                 s.flavor['id']
@@ -4674,9 +4683,9 @@ class TestServerList(_TestServerList):
 
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
         self.images_mock.assert_not_called()
-        self.flavors_mock.list.assert_not_called()
+        self.sdk_client.flavors.assert_not_called()
         self.assertEqual(self.columns, columns)
         self.assertEqual(self.data, tuple(data))
 
@@ -4686,7 +4695,7 @@ class TestServerList(_TestServerList):
                 s.id,
                 s.name,
                 s.status,
-                format_columns.DictListColumn(s.networks),
+                server.AddressesColumn(s.addresses),
                 # Image will be an empty string if boot-from-volume
                 s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV,
                 s.flavor['id']
@@ -4704,9 +4713,9 @@ class TestServerList(_TestServerList):
 
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
         self.images_mock.assert_not_called()
-        self.flavors_mock.list.assert_not_called()
+        self.sdk_client.flavors.assert_not_called()
         self.assertEqual(self.columns, columns)
         self.assertEqual(self.data, tuple(data))
 
@@ -4723,11 +4732,11 @@ class TestServerList(_TestServerList):
 
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
         self.images_mock.assert_not_called()
-        self.flavors_mock.list.assert_not_called()
+        self.sdk_client.flavors.assert_not_called()
         self.get_image_mock.assert_called()
-        self.flavors_mock.get.assert_called()
+        self.sdk_client.find_flavor.assert_called()
 
         self.assertEqual(self.columns, columns)
         self.assertEqual(self.data, tuple(data))
@@ -4747,10 +4756,10 @@ class TestServerList(_TestServerList):
         self.find_image_mock.assert_called_with(self.image.id,
                                                 ignore_missing=False)
 
-        self.search_opts['image'] = self.image.id
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.kwargs['image'] = self.image.id
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
         self.images_mock.assert_not_called()
-        self.flavors_mock.list.assert_called_once()
+        self.sdk_client.flavors.assert_called_once()
 
         self.assertEqual(self.columns, columns)
         self.assertEqual(self.data, tuple(data))
@@ -4767,12 +4776,13 @@ class TestServerList(_TestServerList):
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.flavors_mock.get.assert_has_calls([mock.call(self.flavor.id)])
+        self.sdk_client.find_flavor.assert_has_calls(
+            [mock.call(self.flavor.id)])
 
-        self.search_opts['flavor'] = self.flavor.id
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.kwargs['flavor'] = self.flavor.id
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
         self.images_mock.assert_called_once()
-        self.flavors_mock.list.assert_not_called()
+        self.sdk_client.flavors.assert_not_called()
 
         self.assertEqual(self.columns, columns)
         self.assertEqual(self.data, tuple(data))
@@ -4791,9 +4801,9 @@ class TestServerList(_TestServerList):
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.search_opts['changes-since'] = '2016-03-04T06:27:59Z'
-        self.search_opts['deleted'] = True
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.kwargs['changes-since'] = '2016-03-04T06:27:59Z'
+        self.kwargs['deleted'] = True
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
 
         self.assertEqual(self.columns, columns)
         self.assertEqual(self.data, tuple(data))
@@ -4820,8 +4830,7 @@ class TestServerList(_TestServerList):
         )
 
     def test_server_list_with_tag(self):
-        self.app.client_manager.compute.api_version = api_versions.APIVersion(
-            '2.26')
+        self._set_mock_microversion('2.26')
 
         arglist = [
             '--tag', 'tag1',
@@ -4834,16 +4843,15 @@ class TestServerList(_TestServerList):
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.search_opts['tags'] = 'tag1,tag2'
+        self.kwargs['tags'] = 'tag1,tag2'
 
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
 
         self.assertEqual(self.columns, columns)
         self.assertEqual(self.data, tuple(data))
 
     def test_server_list_with_tag_pre_v225(self):
-        self.app.client_manager.compute.api_version = api_versions.APIVersion(
-            '2.25')
+        self._set_mock_microversion('2.25')
 
         arglist = [
             '--tag', 'tag1',
@@ -4863,9 +4871,7 @@ class TestServerList(_TestServerList):
             str(ex))
 
     def test_server_list_with_not_tag(self):
-        self.app.client_manager.compute.api_version = api_versions.APIVersion(
-            '2.26')
-
+        self._set_mock_microversion('2.26')
         arglist = [
             '--not-tag', 'tag1',
             '--not-tag', 'tag2',
@@ -4877,16 +4883,15 @@ class TestServerList(_TestServerList):
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.search_opts['not-tags'] = 'tag1,tag2'
+        self.kwargs['not-tags'] = 'tag1,tag2'
 
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
 
         self.assertEqual(self.columns, columns)
         self.assertEqual(self.data, tuple(data))
 
     def test_server_list_with_not_tag_pre_v226(self):
-        self.app.client_manager.compute.api_version = api_versions.APIVersion(
-            '2.25')
+        self._set_mock_microversion('2.25')
 
         arglist = [
             '--not-tag', 'tag1',
@@ -4916,8 +4921,8 @@ class TestServerList(_TestServerList):
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.search_opts['availability_zone'] = 'test-az'
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.kwargs['availability_zone'] = 'test-az'
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
         self.assertEqual(self.columns, columns)
         self.assertEqual(tuple(self.data), tuple(data))
 
@@ -4932,8 +4937,8 @@ class TestServerList(_TestServerList):
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.search_opts['key_name'] = 'test-key'
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.kwargs['key_name'] = 'test-key'
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
         self.assertEqual(self.columns, columns)
         self.assertEqual(tuple(self.data), tuple(data))
 
@@ -4948,8 +4953,8 @@ class TestServerList(_TestServerList):
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.search_opts['config_drive'] = True
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.kwargs['config_drive'] = True
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
         self.assertEqual(self.columns, columns)
         self.assertEqual(tuple(self.data), tuple(data))
 
@@ -4964,8 +4969,8 @@ class TestServerList(_TestServerList):
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.search_opts['config_drive'] = False
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.kwargs['config_drive'] = False
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
         self.assertEqual(self.columns, columns)
         self.assertEqual(tuple(self.data), tuple(data))
 
@@ -4980,8 +4985,8 @@ class TestServerList(_TestServerList):
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.search_opts['progress'] = '100'
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.kwargs['progress'] = '100'
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
         self.assertEqual(self.columns, columns)
         self.assertEqual(tuple(self.data), tuple(data))
 
@@ -5005,8 +5010,8 @@ class TestServerList(_TestServerList):
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.search_opts['vm_state'] = 'active'
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.kwargs['vm_state'] = 'active'
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
         self.assertEqual(self.columns, columns)
         self.assertEqual(tuple(self.data), tuple(data))
 
@@ -5021,8 +5026,8 @@ class TestServerList(_TestServerList):
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.search_opts['task_state'] = 'deleting'
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.kwargs['task_state'] = 'deleting'
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
         self.assertEqual(self.columns, columns)
         self.assertEqual(tuple(self.data), tuple(data))
 
@@ -5037,33 +5042,31 @@ class TestServerList(_TestServerList):
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.search_opts['power_state'] = 1
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.kwargs['power_state'] = 1
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
         self.assertEqual(self.columns, columns)
         self.assertEqual(tuple(self.data), tuple(data))
 
     def test_server_list_long_with_host_status_v216(self):
-        self.app.client_manager.compute.api_version = \
-            api_versions.APIVersion('2.16')
-
+        self._set_mock_microversion('2.16')
         self.data1 = tuple(
             (
                 s.id,
                 s.name,
                 s.status,
-                getattr(s, 'OS-EXT-STS:task_state'),
+                getattr(s, 'task_state'),
                 server.PowerStateColumn(
-                    getattr(s, 'OS-EXT-STS:power_state')
+                    getattr(s, 'power_state')
                 ),
-                format_columns.DictListColumn(s.networks),
+                server.AddressesColumn(s.addresses),
                 # Image will be an empty string if boot-from-volume
                 self.image.name if s.image else server.IMAGE_STRING_FOR_BFV,
                 s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV,
                 self.flavor.name,
                 s.flavor['id'],
-                getattr(s, 'OS-EXT-AZ:availability_zone'),
-                getattr(s, 'OS-EXT-SRV-ATTR:host'),
-                s.Metadata,
+                getattr(s, 'availability_zone'),
+                server.HostColumn(getattr(s, 'hypervisor_hostname')),
+                format_columns.DictColumn(s.metadata),
             ) for s in self.servers)
 
         arglist = [
@@ -5078,18 +5081,18 @@ class TestServerList(_TestServerList):
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
 
         self.assertEqual(self.columns_long, columns)
         self.assertEqual(tuple(self.data1), tuple(data))
 
         # Next test with host_status in the data -- the column should be
         # present in this case.
-        self.servers_mock.reset_mock()
+        self.sdk_client.servers.reset_mock()
 
         self.attrs['host_status'] = 'UP'
-        servers = self.setup_servers_mock(3)
-        self.servers_mock.list.return_value = servers
+        servers = self.setup_sdk_servers_mock(3)
+        self.sdk_client.servers.return_value = servers
 
         # Make sure the returned image and flavor IDs match the servers.
         Image = collections.namedtuple('Image', 'id name')
@@ -5099,12 +5102,6 @@ class TestServerList(_TestServerList):
             for s in servers if s.image
         ]
 
-        Flavor = collections.namedtuple('Flavor', 'id name')
-        self.flavors_mock.list.return_value = [
-            Flavor(id=s.flavor['id'], name=self.flavor.name)
-            for s in servers
-        ]
-
         # Add the expected host_status column and data.
         columns_long = self.columns_long + ('Host Status',)
         self.data2 = tuple(
@@ -5112,25 +5109,25 @@ class TestServerList(_TestServerList):
                 s.id,
                 s.name,
                 s.status,
-                getattr(s, 'OS-EXT-STS:task_state'),
+                getattr(s, 'task_state'),
                 server.PowerStateColumn(
-                    getattr(s, 'OS-EXT-STS:power_state')
+                    getattr(s, 'power_state')
                 ),
-                format_columns.DictListColumn(s.networks),
+                server.AddressesColumn(s.addresses),
                 # Image will be an empty string if boot-from-volume
                 self.image.name if s.image else server.IMAGE_STRING_FOR_BFV,
                 s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV,
                 self.flavor.name,
                 s.flavor['id'],
-                getattr(s, 'OS-EXT-AZ:availability_zone'),
-                getattr(s, 'OS-EXT-SRV-ATTR:host'),
-                s.Metadata,
+                getattr(s, 'availability_zone'),
+                server.HostColumn(getattr(s, 'hypervisor_hostname')),
+                format_columns.DictColumn(s.metadata),
                 s.host_status,
             ) for s in servers)
 
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
 
         self.assertEqual(columns_long, columns)
         self.assertEqual(tuple(self.data2), tuple(data))
@@ -5178,8 +5175,8 @@ class TestServerListV273(_TestServerList):
         }
 
         # The servers to be listed.
-        self.servers = self.setup_servers_mock(3)
-        self.servers_mock.list.return_value = self.servers
+        self.servers = self.setup_sdk_servers_mock(3)
+        self.sdk_client.servers.return_value = self.servers
 
         Image = collections.namedtuple('Image', 'id name')
         self.images_mock.return_value = [
@@ -5190,14 +5187,14 @@ class TestServerListV273(_TestServerList):
 
         # The flavor information is embedded, so now reason for this to be
         # called
-        self.flavors_mock.list = mock.NonCallableMock()
+        self.sdk_client.flavors = mock.NonCallableMock()
 
         self.data = tuple(
             (
                 s.id,
                 s.name,
                 s.status,
-                format_columns.DictListColumn(s.networks),
+                server.AddressesColumn(s.addresses),
                 # Image will be an empty string if boot-from-volume
                 self.image.name if s.image else server.IMAGE_STRING_FOR_BFV,
                 self.flavor.name,
@@ -5221,8 +5218,7 @@ class TestServerListV273(_TestServerList):
 
     def test_server_list_with_locked(self):
 
-        self.app.client_manager.compute.api_version = \
-            api_versions.APIVersion('2.73')
+        self._set_mock_microversion('2.73')
         arglist = [
             '--locked'
         ]
@@ -5233,16 +5229,15 @@ class TestServerListV273(_TestServerList):
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.search_opts['locked'] = True
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.kwargs['locked'] = True
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
 
         self.assertCountEqual(self.columns, columns)
         self.assertCountEqual(self.data, tuple(data))
 
     def test_server_list_with_unlocked_v273(self):
+        self._set_mock_microversion('2.73')
 
-        self.app.client_manager.compute.api_version = \
-            api_versions.APIVersion('2.73')
         arglist = [
             '--unlocked'
         ]
@@ -5253,16 +5248,15 @@ class TestServerListV273(_TestServerList):
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.search_opts['locked'] = False
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.kwargs['locked'] = False
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
 
         self.assertCountEqual(self.columns, columns)
         self.assertCountEqual(self.data, tuple(data))
 
     def test_server_list_with_locked_and_unlocked(self):
 
-        self.app.client_manager.compute.api_version = \
-            api_versions.APIVersion('2.73')
+        self._set_mock_microversion('2.73')
         arglist = [
             '--locked',
             '--unlocked'
@@ -5278,8 +5272,7 @@ class TestServerListV273(_TestServerList):
         self.assertIn('Argument parse failed', str(ex))
 
     def test_server_list_with_changes_before(self):
-        self.app.client_manager.compute.api_version = (
-            api_versions.APIVersion('2.66'))
+        self._set_mock_microversion('2.66')
         arglist = [
             '--changes-before', '2016-03-05T06:27:59Z',
             '--deleted'
@@ -5292,10 +5285,10 @@ class TestServerListV273(_TestServerList):
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
         columns, data = self.cmd.take_action(parsed_args)
 
-        self.search_opts['changes-before'] = '2016-03-05T06:27:59Z'
-        self.search_opts['deleted'] = True
+        self.kwargs['changes-before'] = '2016-03-05T06:27:59Z'
+        self.kwargs['deleted'] = True
 
-        self.servers_mock.list.assert_called_with(**self.kwargs)
+        self.sdk_client.servers.assert_called_with(**self.kwargs)
 
         self.assertCountEqual(self.columns, columns)
         self.assertCountEqual(self.data, tuple(data))
@@ -5303,9 +5296,7 @@ class TestServerListV273(_TestServerList):
     @mock.patch.object(iso8601, 'parse_date', side_effect=iso8601.ParseError)
     def test_server_list_with_invalid_changes_before(
             self, mock_parse_isotime):
-        self.app.client_manager.compute.api_version = (
-            api_versions.APIVersion('2.66'))
-
+        self._set_mock_microversion('2.66')
         arglist = [
             '--changes-before', 'Invalid time value',
         ]
@@ -5325,8 +5316,7 @@ class TestServerListV273(_TestServerList):
         )
 
     def test_server_with_changes_before_pre_v266(self):
-        self.app.client_manager.compute.api_version = (
-            api_versions.APIVersion('2.65'))
+        self._set_mock_microversion('2.65')
 
         arglist = [
             '--changes-before', '2016-03-05T06:27:59Z',
@@ -5344,8 +5334,7 @@ class TestServerListV273(_TestServerList):
                           parsed_args)
 
     def test_server_list_v269_with_partial_constructs(self):
-        self.app.client_manager.compute.api_version = \
-            api_versions.APIVersion('2.69')
+        self._set_mock_microversion('2.69')
         arglist = []
         verifylist = []
         parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@@ -5371,10 +5360,10 @@ class TestServerListV273(_TestServerList):
             # it will fail at formatting the networks info later on.
             "networks": {}
         }
-        server = compute_fakes.fakes.FakeResource(
+        fake_server = compute_fakes.fakes.FakeResource(
             info=server_dict,
         )
-        self.servers.append(server)
+        self.servers.append(fake_server)
         columns, data = self.cmd.take_action(parsed_args)
         # get the first three servers out since our interest is in the partial
         # server.
@@ -5384,7 +5373,7 @@ class TestServerListV273(_TestServerList):
         partial_server = next(data)
         expected_row = (
             'server-id-95a56bfc4xxxxxx28d7e418bfd97813a', '',
-            'UNKNOWN', format_columns.DictListColumn({}), '', '')
+            'UNKNOWN', server.AddressesColumn(''), '', '')
         self.assertEqual(expected_row, partial_server)
 
 
diff --git a/releasenotes/notes/nova-gaps-server-list-to-sdk-88c8bfc10a9e3032.yaml b/releasenotes/notes/nova-gaps-server-list-to-sdk-88c8bfc10a9e3032.yaml
new file mode 100644
index 0000000000..01d690e3e9
--- /dev/null
+++ b/releasenotes/notes/nova-gaps-server-list-to-sdk-88c8bfc10a9e3032.yaml
@@ -0,0 +1,5 @@
+---
+features:
+  - |
+    The ``server list`` command now uses the OpenStack SDK instead of the
+    Python nova bindings.