listMaterializedViews
List PostgreSQL materialized views, with name search and optional definitions
List materialized views in the public schema of a PostgreSQL database. Unlike regular views, materialized views store their results physically and must be refreshed explicitly. Regular views and system-schema matviews are excluded. Results are paginated — see Cursor Pagination for the protocol. PostgreSQL only — not available for MySQL, MariaDB, or SQLite.
The tool accepts these optional parameters:
cursor— opaque pagination token; pass back the prior response'snextCursorto fetch the next page.search— a case-insensitive substring filter on materialized view name:ordersmatchesorders,mv_orders, andorders_daily. The value is wrapped as%orders%in aLIKE/ILIKEpattern, so%and_inside it still act as wildcards (_matches any single character). SQL meta-characters (',;,--) are bound as parameter values and never interpolated. Thesearchvalue must remain identical across paginated calls for cursor continuity.detailed— whentrue, the response includes per-matview metadata (schema,owner,description,definition,populated,indexed) so a single call enumerates matviews and inspects them. Defaults tofalse.
In brief mode (default) the response is a sorted JSON array of matview-name strings. Matview names are unique per schema, so no duplicates appear:
{
"entries": ["mv_archived_orders", "mv_orders_by_region", "mv_recent_orders"]
}In detailed mode the response is keyed by bare matview name — matviews cannot overload, so no signature suffix is needed. The matview name is the map key only; it is not repeated inside the value. Brief and detailed pages share the same matviewname row order, so a client can switch detailed mid-pagination without losing position:
{
"entries": {
"mv_orders_by_region": {
"schema": "public",
"owner": "app_user",
"description": "Orders rolled up by region for the BI dashboard.",
"definition": " WITH paid_orders AS (\n SELECT orders.id, orders.customer_id, orders.total\n FROM orders\n WHERE orders.status = 'paid'\n )\n SELECT customer_id AS region, count(*) AS order_count, sum(total) AS gross\n FROM paid_orders\n GROUP BY customer_id;",
"populated": true,
"indexed": true
}
}
}Per-entry fields (sourced from pg_matviews joined to pg_class for the OID needed by obj_description):
schema— schema name (always"public"in this build).owner— owning role's name frompg_matviews.matviewowner.description—COMMENT ON MATERIALIZED VIEWtext, ornullwhen no comment.definition— the SELECT body verbatim frompg_matviews.definition, with noCREATE MATERIALIZED VIEWwrapper.populated—trueonce the matview has been refreshed at least once.falsefor matviews createdWITH NO DATAand never refreshed; querying such a matview returns zero rows untilREFRESH MATERIALIZED VIEWruns.indexed—truewhen at least one index exists on the matview.REFRESH MATERIALIZED VIEW CONCURRENTLYadditionally requires a unique index; this tool reports the broader has-any-index signal.
Detailed mode deliberately omits column metadata, tablespace, storage parameters, and unique-index detection. Column shape is recoverable from the definition text or via listTables(detailed=true) since Postgres exposes matviews in pg_class. Unique-index detection requires a pg_index join — advanced callers can readQuery pg_indexes for that.