diff --git a/homeassistant/components/mqtt/debug_info.py b/homeassistant/components/mqtt/debug_info.py
index 3bf07db183238c656de2a1bea2d15971418a5faf..17dbc27f0c4ba0b8dae35e5a52c40a6b7a9e8ac7 100644
--- a/homeassistant/components/mqtt/debug_info.py
+++ b/homeassistant/components/mqtt/debug_info.py
@@ -154,7 +154,81 @@ def update_trigger_discovery_data(hass, discovery_hash, discovery_payload):
 
 def remove_trigger_discovery_data(hass, discovery_hash):
     """Remove discovery data."""
-    hass.data[DATA_MQTT_DEBUG_INFO]["triggers"][discovery_hash]["discovery_data"] = None
+    hass.data[DATA_MQTT_DEBUG_INFO]["triggers"].pop(discovery_hash)
+
+
+def _info_for_entity(hass: HomeAssistant, entity_id: str) -> dict[str, Any]:
+    mqtt_debug_info = hass.data[DATA_MQTT_DEBUG_INFO]
+    entity_info = mqtt_debug_info["entities"][entity_id]
+    subscriptions = [
+        {
+            "topic": topic,
+            "messages": [
+                {
+                    "payload": str(msg.payload),
+                    "qos": msg.qos,
+                    "retain": msg.retain,
+                    "time": msg.timestamp,
+                    "topic": msg.topic,
+                }
+                for msg in subscription["messages"]
+            ],
+        }
+        for topic, subscription in entity_info["subscriptions"].items()
+    ]
+    transmitted = [
+        {
+            "topic": topic,
+            "messages": [
+                {
+                    "payload": str(msg.payload),
+                    "qos": msg.qos,
+                    "retain": msg.retain,
+                    "time": msg.timestamp,
+                    "topic": msg.topic,
+                }
+                for msg in subscription["messages"]
+            ],
+        }
+        for topic, subscription in entity_info["transmitted"].items()
+    ]
+    discovery_data = {
+        "topic": entity_info["discovery_data"].get(ATTR_DISCOVERY_TOPIC, ""),
+        "payload": entity_info["discovery_data"].get(ATTR_DISCOVERY_PAYLOAD, ""),
+    }
+
+    return {
+        "entity_id": entity_id,
+        "subscriptions": subscriptions,
+        "discovery_data": discovery_data,
+        "transmitted": transmitted,
+    }
+
+
+def _info_for_trigger(hass: HomeAssistant, trigger_key: str) -> dict[str, Any]:
+    mqtt_debug_info = hass.data[DATA_MQTT_DEBUG_INFO]
+    trigger = mqtt_debug_info["triggers"][trigger_key]
+    discovery_data = None
+    if trigger["discovery_data"] is not None:
+        discovery_data = {
+            "topic": trigger["discovery_data"][ATTR_DISCOVERY_TOPIC],
+            "payload": trigger["discovery_data"][ATTR_DISCOVERY_PAYLOAD],
+        }
+    return {"discovery_data": discovery_data, "trigger_key": trigger_key}
+
+
+def info_for_config_entry(hass):
+    """Get debug info for all entities and triggers."""
+    mqtt_info = {"entities": [], "triggers": []}
+    mqtt_debug_info = hass.data[DATA_MQTT_DEBUG_INFO]
+
+    for entity_id in mqtt_debug_info["entities"]:
+        mqtt_info["entities"].append(_info_for_entity(hass, entity_id))
+
+    for trigger_key in mqtt_debug_info["triggers"]:
+        mqtt_info["triggers"].append(_info_for_trigger(hass, trigger_key))
+
+    return mqtt_info
 
 
 def info_for_device(hass, device_id):
@@ -170,60 +244,12 @@ def info_for_device(hass, device_id):
         if entry.entity_id not in mqtt_debug_info["entities"]:
             continue
 
-        entity_info = mqtt_debug_info["entities"][entry.entity_id]
-        subscriptions = [
-            {
-                "topic": topic,
-                "messages": [
-                    {
-                        "payload": str(msg.payload),
-                        "qos": msg.qos,
-                        "retain": msg.retain,
-                        "time": msg.timestamp,
-                        "topic": msg.topic,
-                    }
-                    for msg in list(subscription["messages"])
-                ],
-            }
-            for topic, subscription in entity_info["subscriptions"].items()
-        ]
-        transmitted = [
-            {
-                "topic": topic,
-                "messages": [
-                    {
-                        "payload": str(msg.payload),
-                        "qos": msg.qos,
-                        "retain": msg.retain,
-                        "time": msg.timestamp,
-                        "topic": msg.topic,
-                    }
-                    for msg in list(subscription["messages"])
-                ],
-            }
-            for topic, subscription in entity_info["transmitted"].items()
-        ]
-        discovery_data = {
-            "topic": entity_info["discovery_data"].get(ATTR_DISCOVERY_TOPIC, ""),
-            "payload": entity_info["discovery_data"].get(ATTR_DISCOVERY_PAYLOAD, ""),
-        }
-        mqtt_info["entities"].append(
-            {
-                "entity_id": entry.entity_id,
-                "subscriptions": subscriptions,
-                "discovery_data": discovery_data,
-                "transmitted": transmitted,
-            }
-        )
+        mqtt_info["entities"].append(_info_for_entity(hass, entry.entity_id))
 
-    for trigger in mqtt_debug_info["triggers"].values():
-        if trigger["device_id"] != device_id or trigger["discovery_data"] is None:
+    for trigger_key, trigger in mqtt_debug_info["triggers"].items():
+        if trigger["device_id"] != device_id:
             continue
 
-        discovery_data = {
-            "topic": trigger["discovery_data"][ATTR_DISCOVERY_TOPIC],
-            "payload": trigger["discovery_data"][ATTR_DISCOVERY_PAYLOAD],
-        }
-        mqtt_info["triggers"].append({"discovery_data": discovery_data})
+        mqtt_info["triggers"].append(_info_for_trigger(hass, trigger_key))
 
     return mqtt_info
diff --git a/homeassistant/components/mqtt/diagnostics.py b/homeassistant/components/mqtt/diagnostics.py
new file mode 100644
index 0000000000000000000000000000000000000000..ea490783fc09f1b9b7b35f44ae46a5fb2b82fa76
--- /dev/null
+++ b/homeassistant/components/mqtt/diagnostics.py
@@ -0,0 +1,126 @@
+"""Diagnostics support for MQTT."""
+from __future__ import annotations
+
+from typing import Any
+
+from homeassistant.components import device_tracker
+from homeassistant.components.diagnostics import async_redact_data
+from homeassistant.config_entries import ConfigEntry
+from homeassistant.const import (
+    ATTR_LATITUDE,
+    ATTR_LONGITUDE,
+    CONF_PASSWORD,
+    CONF_USERNAME,
+)
+from homeassistant.core import HomeAssistant, callback, split_entity_id
+from homeassistant.helpers import device_registry as dr, entity_registry as er
+from homeassistant.helpers.device_registry import DeviceEntry
+
+from . import DATA_MQTT, MQTT, debug_info, is_connected
+
+REDACT_CONFIG = {CONF_PASSWORD, CONF_USERNAME}
+REDACT_STATE_DEVICE_TRACKER = {ATTR_LATITUDE, ATTR_LONGITUDE}
+
+
+async def async_get_config_entry_diagnostics(
+    hass: HomeAssistant, entry: ConfigEntry
+) -> dict[str, Any]:
+    """Return diagnostics for a config entry."""
+    return _async_get_diagnostics(hass, entry)
+
+
+async def async_get_device_diagnostics(
+    hass: HomeAssistant, entry: ConfigEntry, device: DeviceEntry
+) -> dict[str, Any]:
+    """Return diagnostics for a device entry."""
+    return _async_get_diagnostics(hass, entry, device)
+
+
+@callback
+def _async_get_diagnostics(
+    hass: HomeAssistant,
+    entry: ConfigEntry,
+    device: DeviceEntry | None = None,
+) -> dict[str, Any]:
+    """Return diagnostics for a config entry."""
+    mqtt_instance: MQTT = hass.data[DATA_MQTT]
+
+    redacted_config = async_redact_data(mqtt_instance.conf, REDACT_CONFIG)
+
+    data = {
+        "connected": is_connected(hass),
+        "mqtt_config": redacted_config,
+    }
+
+    if device:
+        data["device"] = _async_device_as_dict(hass, device)
+        data["mqtt_debug_info"] = debug_info.info_for_device(hass, device.id)
+    else:
+        device_registry = dr.async_get(hass)
+        data.update(
+            devices=[
+                _async_device_as_dict(hass, device)
+                for device in dr.async_entries_for_config_entry(
+                    device_registry, entry.entry_id
+                )
+            ],
+            mqtt_debug_info=debug_info.info_for_config_entry(hass),
+        )
+
+    return data
+
+
+@callback
+def _async_device_as_dict(hass: HomeAssistant, device: DeviceEntry) -> dict[str, Any]:
+    """Represent an MQTT device as a dictionary."""
+
+    # Gather information how this MQTT device is represented in Home Assistant
+    entity_registry = er.async_get(hass)
+    data: dict[str, Any] = {
+        "id": device.id,
+        "name": device.name,
+        "name_by_user": device.name_by_user,
+        "disabled": device.disabled,
+        "disabled_by": device.disabled_by,
+        "entities": [],
+    }
+
+    entities = er.async_entries_for_device(
+        entity_registry,
+        device_id=device.id,
+        include_disabled_entities=True,
+    )
+
+    for entity_entry in entities:
+        state = hass.states.get(entity_entry.entity_id)
+        state_dict = None
+        if state:
+            state_dict = dict(state.as_dict())
+
+            # The context doesn't provide useful information in this case.
+            state_dict.pop("context", None)
+
+            entity_domain = split_entity_id(state.entity_id)[0]
+
+            # Retract some sensitive state attributes
+            if entity_domain == device_tracker.DOMAIN:
+                state_dict["attributes"] = async_redact_data(
+                    state_dict["attributes"], REDACT_STATE_DEVICE_TRACKER
+                )
+
+        data["entities"].append(
+            {
+                "device_class": entity_entry.device_class,
+                "disabled_by": entity_entry.disabled_by,
+                "disabled": entity_entry.disabled,
+                "entity_category": entity_entry.entity_category,
+                "entity_id": entity_entry.entity_id,
+                "icon": entity_entry.icon,
+                "original_device_class": entity_entry.original_device_class,
+                "original_icon": entity_entry.original_icon,
+                "state": state_dict,
+                "unit_of_measurement": entity_entry.unit_of_measurement,
+            }
+        )
+
+    return data
diff --git a/tests/components/mqtt/test_diagnostics.py b/tests/components/mqtt/test_diagnostics.py
new file mode 100644
index 0000000000000000000000000000000000000000..bbd42a20c87be2ea8e15a34e77fa9b33ab14c3b3
--- /dev/null
+++ b/tests/components/mqtt/test_diagnostics.py
@@ -0,0 +1,263 @@
+"""Test MQTT diagnostics."""
+
+import json
+from unittest.mock import ANY
+
+import pytest
+
+from homeassistant.components import mqtt
+
+from tests.common import async_fire_mqtt_message, mock_device_registry
+from tests.components.diagnostics import (
+    get_diagnostics_for_config_entry,
+    get_diagnostics_for_device,
+)
+
+default_config = {
+    "birth_message": {},
+    "broker": "mock-broker",
+    "discovery": True,
+    "discovery_prefix": "homeassistant",
+    "keepalive": 60,
+    "port": 1883,
+    "protocol": "3.1.1",
+    "tls_version": "auto",
+    "will_message": {
+        "payload": "offline",
+        "qos": 0,
+        "retain": False,
+        "topic": "homeassistant/status",
+    },
+}
+
+
+@pytest.fixture
+def device_reg(hass):
+    """Return an empty, loaded, registry."""
+    return mock_device_registry(hass)
+
+
+async def test_entry_diagnostics(hass, device_reg, hass_client, mqtt_mock):
+    """Test config entry diagnostics."""
+    config_entry = hass.config_entries.async_entries(mqtt.DOMAIN)[0]
+    mqtt_mock.connected = True
+
+    assert await get_diagnostics_for_config_entry(hass, hass_client, config_entry) == {
+        "connected": True,
+        "devices": [],
+        "mqtt_config": default_config,
+        "mqtt_debug_info": {"entities": [], "triggers": []},
+    }
+
+    # Discover a device with an entity and a trigger
+    config_sensor = {
+        "device": {"identifiers": ["0AFFD2"]},
+        "platform": "mqtt",
+        "state_topic": "foobar/sensor",
+        "unique_id": "unique",
+    }
+    config_trigger = {
+        "automation_type": "trigger",
+        "device": {"identifiers": ["0AFFD2"]},
+        "platform": "mqtt",
+        "topic": "test-topic1",
+        "type": "foo",
+        "subtype": "bar",
+    }
+    data_sensor = json.dumps(config_sensor)
+    data_trigger = json.dumps(config_trigger)
+
+    async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data_sensor)
+    async_fire_mqtt_message(
+        hass, "homeassistant/device_automation/bla/config", data_trigger
+    )
+    await hass.async_block_till_done()
+
+    device_entry = device_reg.async_get_device({("mqtt", "0AFFD2")})
+
+    expected_debug_info = {
+        "entities": [
+            {
+                "entity_id": "sensor.mqtt_sensor",
+                "subscriptions": [{"topic": "foobar/sensor", "messages": []}],
+                "discovery_data": {
+                    "payload": config_sensor,
+                    "topic": "homeassistant/sensor/bla/config",
+                },
+                "transmitted": [],
+            }
+        ],
+        "triggers": [
+            {
+                "discovery_data": {
+                    "payload": config_trigger,
+                    "topic": "homeassistant/device_automation/bla/config",
+                },
+                "trigger_key": ["device_automation", "bla"],
+            }
+        ],
+    }
+
+    expected_device = {
+        "disabled": False,
+        "disabled_by": None,
+        "entities": [
+            {
+                "device_class": None,
+                "disabled": False,
+                "disabled_by": None,
+                "entity_category": None,
+                "entity_id": "sensor.mqtt_sensor",
+                "icon": None,
+                "original_device_class": None,
+                "original_icon": None,
+                "state": {
+                    "attributes": {"friendly_name": "MQTT Sensor"},
+                    "entity_id": "sensor.mqtt_sensor",
+                    "last_changed": ANY,
+                    "last_updated": ANY,
+                    "state": "unknown",
+                },
+                "unit_of_measurement": None,
+            }
+        ],
+        "id": device_entry.id,
+        "name": None,
+        "name_by_user": None,
+    }
+
+    assert await get_diagnostics_for_config_entry(hass, hass_client, config_entry) == {
+        "connected": True,
+        "devices": [expected_device],
+        "mqtt_config": default_config,
+        "mqtt_debug_info": expected_debug_info,
+    }
+
+    assert await get_diagnostics_for_device(
+        hass, hass_client, config_entry, device_entry
+    ) == {
+        "connected": True,
+        "device": expected_device,
+        "mqtt_config": default_config,
+        "mqtt_debug_info": expected_debug_info,
+    }
+
+
+@pytest.mark.parametrize(
+    "mqtt_config",
+    [
+        {
+            mqtt.CONF_BROKER: "mock-broker",
+            mqtt.CONF_BIRTH_MESSAGE: {},
+            mqtt.CONF_PASSWORD: "hunter2",
+            mqtt.CONF_USERNAME: "my_user",
+        }
+    ],
+)
+async def test_redact_diagnostics(hass, device_reg, hass_client, mqtt_mock):
+    """Test redacting diagnostics."""
+    expected_config = dict(default_config)
+    expected_config["password"] = "**REDACTED**"
+    expected_config["username"] = "**REDACTED**"
+
+    config_entry = hass.config_entries.async_entries(mqtt.DOMAIN)[0]
+    mqtt_mock.connected = True
+
+    # Discover a device with a device tracker
+    config_tracker = {
+        "device": {"identifiers": ["0AFFD2"]},
+        "platform": "mqtt",
+        "state_topic": "foobar/device_tracker",
+        "json_attributes_topic": "attributes-topic",
+        "unique_id": "unique",
+    }
+    data_tracker = json.dumps(config_tracker)
+
+    async_fire_mqtt_message(
+        hass, "homeassistant/device_tracker/bla/config", data_tracker
+    )
+    await hass.async_block_till_done()
+
+    location_data = '{"latitude":32.87336,"longitude": -117.22743, "gps_accuracy":1.5}'
+    async_fire_mqtt_message(hass, "attributes-topic", location_data)
+    await hass.async_block_till_done()
+
+    device_entry = device_reg.async_get_device({("mqtt", "0AFFD2")})
+
+    expected_debug_info = {
+        "entities": [
+            {
+                "entity_id": "device_tracker.mqtt_unique",
+                "subscriptions": [
+                    {
+                        "topic": "attributes-topic",
+                        "messages": [
+                            {
+                                "payload": location_data,
+                                "qos": 0,
+                                "retain": False,
+                                "time": ANY,
+                                "topic": "attributes-topic",
+                            }
+                        ],
+                    },
+                    {"topic": "foobar/device_tracker", "messages": []},
+                ],
+                "discovery_data": {
+                    "payload": config_tracker,
+                    "topic": "homeassistant/device_tracker/bla/config",
+                },
+                "transmitted": [],
+            }
+        ],
+        "triggers": [],
+    }
+
+    expected_device = {
+        "disabled": False,
+        "disabled_by": None,
+        "entities": [
+            {
+                "device_class": None,
+                "disabled": False,
+                "disabled_by": None,
+                "entity_category": None,
+                "entity_id": "device_tracker.mqtt_unique",
+                "icon": None,
+                "original_device_class": None,
+                "original_icon": None,
+                "state": {
+                    "attributes": {
+                        "gps_accuracy": 1.5,
+                        "latitude": "**REDACTED**",
+                        "longitude": "**REDACTED**",
+                        "source_type": None,
+                    },
+                    "entity_id": "device_tracker.mqtt_unique",
+                    "last_changed": ANY,
+                    "last_updated": ANY,
+                    "state": "home",
+                },
+                "unit_of_measurement": None,
+            }
+        ],
+        "id": device_entry.id,
+        "name": None,
+        "name_by_user": None,
+    }
+
+    assert await get_diagnostics_for_config_entry(hass, hass_client, config_entry) == {
+        "connected": True,
+        "devices": [expected_device],
+        "mqtt_config": expected_config,
+        "mqtt_debug_info": expected_debug_info,
+    }
+
+    assert await get_diagnostics_for_device(
+        hass, hass_client, config_entry, device_entry
+    ) == {
+        "connected": True,
+        "device": expected_device,
+        "mqtt_config": expected_config,
+        "mqtt_debug_info": expected_debug_info,
+    }
diff --git a/tests/components/mqtt/test_init.py b/tests/components/mqtt/test_init.py
index 92884dcef93fe385b6151d00bdba71ad0937ccc6..a9a96df4f8fdff8141e0ff946dcacbe971f53ae4 100644
--- a/tests/components/mqtt/test_init.py
+++ b/tests/components/mqtt/test_init.py
@@ -1529,15 +1529,27 @@ async def test_mqtt_ws_get_device_debug_info(
     hass, device_reg, hass_ws_client, mqtt_mock
 ):
     """Test MQTT websocket device debug info."""
-    config = {
+    config_sensor = {
         "device": {"identifiers": ["0AFFD2"]},
         "platform": "mqtt",
         "state_topic": "foobar/sensor",
         "unique_id": "unique",
     }
-    data = json.dumps(config)
+    config_trigger = {
+        "automation_type": "trigger",
+        "device": {"identifiers": ["0AFFD2"]},
+        "platform": "mqtt",
+        "topic": "test-topic1",
+        "type": "foo",
+        "subtype": "bar",
+    }
+    data_sensor = json.dumps(config_sensor)
+    data_trigger = json.dumps(config_trigger)
 
-    async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data)
+    async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data_sensor)
+    async_fire_mqtt_message(
+        hass, "homeassistant/device_automation/bla/config", data_trigger
+    )
     await hass.async_block_till_done()
 
     # Verify device entry is created
@@ -1556,13 +1568,21 @@ async def test_mqtt_ws_get_device_debug_info(
                 "entity_id": "sensor.mqtt_sensor",
                 "subscriptions": [{"topic": "foobar/sensor", "messages": []}],
                 "discovery_data": {
-                    "payload": config,
+                    "payload": config_sensor,
                     "topic": "homeassistant/sensor/bla/config",
                 },
                 "transmitted": [],
             }
         ],
-        "triggers": [],
+        "triggers": [
+            {
+                "discovery_data": {
+                    "payload": config_trigger,
+                    "topic": "homeassistant/device_automation/bla/config",
+                },
+                "trigger_key": ["device_automation", "bla"],
+            }
+        ],
     }
     assert response["result"] == expected_result
 
diff --git a/tests/conftest.py b/tests/conftest.py
index 564480a0e91386119ebefad26d478400d48e2bfa..baac9ac19eed9584187680c984663c24972ce0e7 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -609,6 +609,7 @@ async def mqtt_mock(hass, mqtt_client_mock, mqtt_config):
         spec_set=hass.data["mqtt"],
         wraps=hass.data["mqtt"],
     )
+    mqtt_component_mock.conf = hass.data["mqtt"].conf  # For diagnostics
     mqtt_component_mock._mqttc = mqtt_client_mock
 
     hass.data["mqtt"] = mqtt_component_mock