list_connections
List the warehouse connections you can author against. The ten fields it returns, why it takes no arguments, errors and scope.
Lists the warehouse data connections you can build a refreshable dashboard
against, so you can find the connection id to pass to
introspect_schema,
validate_cube_sql, or a
source_config.connection.
Warehouse connections are created and managed in the Dashies web app, never through MCP.
Behaviour hints for clients: read-only, not open-world.
Parameters
This tool takes no parameters. Its input schema declares no properties at all, and that is deliberate: which connections you see is decided by how the MCP connection was authorized, not by an argument. See Scope below.
Returns
Ten fields per connection, every one of them always present. Seven describe how the connection was configured, and three describe what actually happened to it:
| Field | Meaning |
|---|---|
id | The connection id you pass as connection. |
kind | Always warehouse here. |
label | The name you gave it in the web app. |
engine | postgres, bigquery, snowflake, redshift, databricks or mssql. |
status | pending, active, error or disabled. Only active can author. |
last_verified_at | When a Test last succeeded. |
last_error | A classified token such as connection_auth, never raw driver text. |
health_state | What real refreshes observed. null until something has observed it. |
health_error | The classified reason behind health_state. |
health_source | What made that observation. |
No password, secret, Vault reference or internal object name is ever included: the projection is an allowlist, not a filter.
status and health_state are independent, not two views of one thing
status is what a Test concluded. health_state is what a real refresh
observed. status: active beside health_state: failing is a normal and
meaningful reading, not a contradiction: the connection is configured and
enabled, and the last refresh failed at the connection level. Never collapse
them.
Your personal warehouse connections (2):
- Analytics Postgres [7a1e...-...] | engine: postgres | status: active | last verified: 2026-07-29T04:12:09Z
- Snowflake Prod [0c22...-...] | engine: snowflake | status: error | last verified: 2026-07-20T11:03:44Z | last error: connection_auth | last observed: failing (connection_auth)
Pass a connection's id as the `connection` argument to introspect_schema / validate_cube_sql, or as source_config.connection in publish_dashboard, to author a dashboard that refreshes from that warehouse. Only 'active' connections can be used. These are personal-scoped: a WORKSPACE dashboard can only bind a connection created in that workspace, so if you are publishing into a workspace, add the warehouse from inside that workspace first.
BEGIN_JSON
{"count":2,"connections":[{"id":"...","kind":"warehouse","label":"Analytics Postgres","engine":"postgres","status":"active","last_verified_at":"...","last_error":null,"health_state":null,"health_error":null,"health_source":null}]}
END_JSON
The | last observed: <state> segment appears only when something has
actually observed the connection, so one that has never refreshed prints nothing
there. With a classified reason it renders last observed: failing (connection_auth).
The header names the space, and the word is load-bearing
A personal listing heads Your personal warehouse connections (N):. The word
personal is there deliberately: the bare form reads as "all of yours", and an
author on an older authorization who read it that way built against a connection
and was refused at the binding call by a message that is intentionally ambiguous
and therefore cannot be diagnosed. That personal header is also the branch whose
guidance paragraph carries the extra scope sentence quoted above.
A workspace listing heads Warehouse connections in the "acme-co" workspace (2):
and omits that trailing sentence, because in that branch there is no
personal-versus-workspace trap to warn about.
Empty states
Personal, both lines:
You have no warehouse connections.
Connect a warehouse from the Dashies web app (Connections) to author dashboards that refresh from your own database. The built-in 'self' connection (Dashies' own no-PII metrics) is always available without a connection id.
Workspace, both lines:
There are no warehouse connections in the "acme-co" workspace.
Connect a warehouse from the Dashies web app (Connections) with the "acme-co" workspace as the active space to author dashboards that refresh from it. The built-in 'self' connection (Dashies' own no-PII metrics) is always available without a connection id.
An authorization locked to a workspace whose slug is unavailable says
this workspace wherever those lines say the "acme-co" workspace.
self is never listed
The built-in self connection is always available and never appears here. Use it
by passing connection: "self" or by omitting the argument entirely. An empty
list therefore means "no warehouses", not "nothing to author against".
Errors
| Condition | Text |
|---|---|
| The read failed | Could not list your connections: <err> |
Scope
The read space comes from the grant alone. A personal authorization lists your personal connections; a workspace authorization lists that workspace's, whoever on the team created them. The two sets are disjoint.
A connection belongs permanently to the space it was created in and cannot be moved, so a connection you can see in one space is simply absent from the other. Inside a workspace, any member can use a connection to author, but only the member who added it and workspace admins can rename, re-test, rotate or delete it.
Check it worked
If the list is empty but you expect entries, check which space you authorized for: re-authorizing and choosing the workspace is what switches the read space, and there is no argument that overrides it. The header tells you which space you got, so read it rather than inferring from the contents.
If an entry shows status: error, test the connection in the web app before
authoring against it, since an inactive connection is refused at the point of use
rather than here. If it shows status: active with last observed: failing,
the configuration is fine and the last real refresh was not: read
get_refresh_status on a dashboard
bound to it for the run that failed.