diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py
index bf345e658e..480759af74 100644
--- a/openstackclient/compute/v2/server.py
+++ b/openstackclient/compute/v2/server.py
@@ -77,6 +77,10 @@ class AddressesColumn(cliff_columns.FormattableColumn):
         except Exception:
             return 'N/A'
 
+    def machine_readable(self):
+        return {k: [i['addr'] for i in v if 'addr' in i]
+                for k, v in self._value.items()}
+
 
 class HostColumn(cliff_columns.FormattableColumn):
     """Generate a formatted string of a hostname."""
@@ -133,14 +137,61 @@ def _prep_server_detail(compute_client, image_client, server, refresh=True):
                     the latest details of a server after creating it.
     :rtype: a dict of server details
     """
+    # Note: Some callers of this routine pass a novaclient server, and others
+    # pass an SDK server. Column names may be different across those cases.
     info = server.to_dict()
     if refresh:
         server = utils.find_resource(compute_client.servers, info['id'])
         info.update(server.to_dict())
 
+    # Some commands using this routine were originally implemented with the
+    # nova python wrappers, and were later migrated to use the SDK. Map the
+    # SDK's property names to the original property names to maintain backward
+    # compatibility for existing users. Data is duplicated under both the old
+    # and new name so users can consume the data by either name.
+    column_map = {
+        'access_ipv4': 'accessIPv4',
+        'access_ipv6': 'accessIPv6',
+        'admin_password': 'adminPass',
+        'admin_password': 'adminPass',
+        'volumes': 'os-extended-volumes:volumes_attached',
+        'availability_zone': 'OS-EXT-AZ:availability_zone',
+        'block_device_mapping': 'block_device_mapping_v2',
+        'compute_host': 'OS-EXT-SRV-ATTR:host',
+        'created_at': 'created',
+        'disk_config': 'OS-DCF:diskConfig',
+        'flavor_id': 'flavorRef',
+        'has_config_drive': 'config_drive',
+        'host_id': 'hostId',
+        'fault': 'fault',
+        'hostname': 'OS-EXT-SRV-ATTR:hostname',
+        'hypervisor_hostname': 'OS-EXT-SRV-ATTR:hypervisor_hostname',
+        'image_id': 'imageRef',
+        'instance_name': 'OS-EXT-SRV-ATTR:instance_name',
+        'is_locked': 'locked',
+        'kernel_id': 'OS-EXT-SRV-ATTR:kernel_id',
+        'launch_index': 'OS-EXT-SRV-ATTR:launch_index',
+        'launched_at': 'OS-SRV-USG:launched_at',
+        'power_state': 'OS-EXT-STS:power_state',
+        'project_id': 'tenant_id',
+        'ramdisk_id': 'OS-EXT-SRV-ATTR:ramdisk_id',
+        'reservation_id': 'OS-EXT-SRV-ATTR:reservation_id',
+        'root_device_name': 'OS-EXT-SRV-ATTR:root_device_name',
+        'scheduler_hints': 'OS-SCH-HNT:scheduler_hints',
+        'task_state': 'OS-EXT-STS:task_state',
+        'terminated_at': 'OS-SRV-USG:terminated_at',
+        'updated_at': 'updated',
+        'user_data': 'OS-EXT-SRV-ATTR:user_data',
+        'vm_state': 'OS-EXT-STS:vm_state',
+    }
+
+    info.update({
+        column_map[column]: data for column, data in info.items()
+        if column in column_map})
+
     # Convert the image blob to a name
     image_info = info.get('image', {})
-    if image_info:
+    if image_info and any(image_info.values()):
         image_id = image_info.get('id', '')
         try:
             image = image_client.get_image(image_id)
@@ -188,7 +239,9 @@ def _prep_server_detail(compute_client, image_client, server, refresh=True):
 
     # NOTE(dtroyer): novaclient splits these into separate entries...
     # Format addresses in a useful way
-    info['addresses'] = format_columns.DictListColumn(server.networks)
+    info['addresses'] = (
+        AddressesColumn(info['addresses']) if 'addresses' in info
+        else format_columns.DictListColumn(info.get('networks')))
 
     # Map 'metadata' field to 'properties'
     info['properties'] = format_columns.DictColumn(info.pop('metadata'))
@@ -4327,32 +4380,34 @@ class ShowServer(command.ShowOne):
         return parser
 
     def take_action(self, parsed_args):
-        compute_client = self.app.client_manager.compute
-        server = utils.find_resource(
-            compute_client.servers, parsed_args.server)
+        compute_client = self.app.client_manager.sdk_connection.compute
+
+        # Find by name or ID, then get the full details of the server
+        server = compute_client.find_server(
+            parsed_args.server, ignore_missing=False)
+        server = compute_client.get_server(server)
 
         if parsed_args.diagnostics:
-            (resp, data) = server.diagnostics()
-            if not resp.status_code == 200:
-                self.app.stderr.write(_(
-                    "Error retrieving diagnostics data\n"
-                ))
-                return ({}, {})
+            data = compute_client.get_server_diagnostics(server)
             return zip(*sorted(data.items()))
 
         topology = None
         if parsed_args.topology:
-            if compute_client.api_version < api_versions.APIVersion('2.78'):
+            if not sdk_utils.supports_microversion(compute_client, '2.78'):
                 msg = _(
                     '--os-compute-api-version 2.78 or greater is required to '
                     'support the --topology option'
                 )
                 raise exceptions.CommandError(msg)
 
-            topology = server.topology()
+            topology = server.fetch_topology(compute_client)
 
         data = _prep_server_detail(
-            compute_client, self.app.client_manager.image, server,
+            # TODO(dannosliwcd): Replace these clients with SDK clients after
+            # all callers of _prep_server_detail() are using the SDK.
+            self.app.client_manager.compute,
+            self.app.client_manager.image,
+            server,
             refresh=False)
 
         if topology:
diff --git a/openstackclient/tests/functional/compute/v2/test_server.py b/openstackclient/tests/functional/compute/v2/test_server.py
index 6a6afa7c48..b1afe8755b 100644
--- a/openstackclient/tests/functional/compute/v2/test_server.py
+++ b/openstackclient/tests/functional/compute/v2/test_server.py
@@ -11,6 +11,7 @@
 #    under the License.
 
 import itertools
+import json
 import time
 import uuid
 
@@ -288,6 +289,33 @@ class ServerTests(common.ComputeTestCase):
         )
         self.assertOutput("", raw_output)
 
+    def test_server_show(self):
+        """Test server show"""
+        cmd_output = self.server_create()
+        name = cmd_output['name']
+
+        # Simple show
+        cmd_output = json.loads(self.openstack(
+            f'server show -f json {name}'
+        ))
+        self.assertEqual(
+            name,
+            cmd_output["name"],
+        )
+
+        # Show diagnostics
+        cmd_output = json.loads(self.openstack(
+            f'server show -f json {name} --diagnostics'
+        ))
+        self.assertIn('driver', cmd_output)
+
+        # Show topology
+        cmd_output = json.loads(self.openstack(
+            f'server show -f json {name} --topology '
+            f'--os-compute-api-version 2.78'
+        ))
+        self.assertIn('topology', cmd_output)
+
     def test_server_actions(self):
         """Test server action pairs
 
diff --git a/openstackclient/tests/unit/compute/v2/test_server.py b/openstackclient/tests/unit/compute/v2/test_server.py
index 846ad8cdca..fc8dcd4fcd 100644
--- a/openstackclient/tests/unit/compute/v2/test_server.py
+++ b/openstackclient/tests/unit/compute/v2/test_server.py
@@ -7931,20 +7931,15 @@ class TestServerShow(TestServer):
             'tenant_id': 'tenant-id-xxx',
             'networks': {'public': ['10.20.30.40', '2001:db8::f']},
         }
-        # Fake the server.diagnostics() method. The return value contains http
-        # response and data. The data is a dict. Sincce this method itself is
-        # faked, we don't need to fake everything of the return value exactly.
-        resp = mock.Mock()
-        resp.status_code = 200
+        self.sdk_client.get_server_diagnostics.return_value = {'test': 'test'}
         server_method = {
-            'diagnostics': (resp, {'test': 'test'}),
-            'topology': self.topology,
+            'fetch_topology': self.topology,
         }
         self.server = compute_fakes.FakeServer.create_one_server(
             attrs=server_info, methods=server_method)
 
         # This is the return value for utils.find_resource()
-        self.servers_mock.get.return_value = self.server
+        self.sdk_client.get_server.return_value = self.server
         self.get_image_mock.return_value = self.image
         self.flavors_mock.get.return_value = self.flavor
 
@@ -8045,8 +8040,7 @@ class TestServerShow(TestServer):
         self.assertEqual(('test',), data)
 
     def test_show_topology(self):
-        self.app.client_manager.compute.api_version = \
-            api_versions.APIVersion('2.78')
+        self._set_mock_microversion('2.78')
 
         arglist = [
             '--topology',
@@ -8068,8 +8062,7 @@ class TestServerShow(TestServer):
         self.assertCountEqual(self.data, data)
 
     def test_show_topology_pre_v278(self):
-        self.app.client_manager.compute.api_version = \
-            api_versions.APIVersion('2.77')
+        self._set_mock_microversion('2.77')
 
         arglist = [
             '--topology',
diff --git a/releasenotes/notes/switch-server-show-to-sdk-44a614aebf2c6da6.yaml b/releasenotes/notes/switch-server-show-to-sdk-44a614aebf2c6da6.yaml
new file mode 100644
index 0000000000..c116f6e0cb
--- /dev/null
+++ b/releasenotes/notes/switch-server-show-to-sdk-44a614aebf2c6da6.yaml
@@ -0,0 +1,7 @@
+---
+features:
+  - |
+    The ``server show`` command now uses the OpenStack SDK instead of the
+    Python nova bindings. The command prints data fields both by their
+    novaclient names used in previous releases as well as the names used in the
+    SDK.