# Platform tools

Platform tools help your agent find the right data and the right map before any visualization or analysis happens. They return JSON for the agent to reason over; no inline UI is rendered. Use them to enumerate connections, browse the warehouse hierarchically, search for tables by name, inspect column distributions, and locate saved Builder maps.

## Data discovery

### `list_connections`

**Description**

Lists all available data warehouse connections for the account. Returns connection names, provider types, and IDs.

**Example:** An agent asked *"What data do I have access to?"* would call `list_connections` to get a list:

```
[
  { "name": "carto_dw", "provider": "bigquery" },
  { "name": "my_snowflake", "provider": "snowflake" }
]
```

**Input properties:**

*No parameters*

**Output:**

A JSON array of connection objects, each containing the connection name, provider type, and ID.

<details>

<summary>Response example</summary>

```
{
  "status": 200,
  "data": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "name": "carto_dw",
      "provider_id": "bigquery",
      "privacy": "shared",
      "carto_dw": true,
      "created_at": "2024-01-15T10:30:00.000Z",
      "updated_at": "2024-06-20T14:22:00.000Z"
    },
    {
      "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
      "name": "my_snowflake",
      "provider_id": "snowflake",
      "privacy": "shared",
      "carto_dw": false,
      "created_at": "2024-03-10T08:00:00.000Z",
      "updated_at": "2024-03-10T08:00:00.000Z"
    }
  ]
}
```

</details>

**Example**

*"What data do I have access to?"*

The agent calls `list_connections` with no parameters and returns a summary of available connections:

```
list_connections()
```

***

### `list_resources`

**Description**

Browses the contents of a data warehouse connection hierarchically. Returns databases, schemas, tables, and views at the requested level.

The hierarchy varies by provider:

* **BigQuery:** connection > project > dataset > table/view
* **Snowflake:** connection > database > schema > table/view
* **Databricks:** connection > catalog > schema > table/view
* **PostgreSQL / Redshift:** connection > database > schema > table/view

Call with no `fqn` to see the top level, then pass an `fqn` to drill into a specific database or schema. Use `maxDepth=2` to expand one level deeper in a single call (e.g., see schemas AND their tables).

**Input properties**

| Parameter         | Type   | Required | Description                                                                                                             |
| ----------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------------------- |
| `connection_name` | string | Yes      | Name of the connection (from `list_connections`).                                                                       |
| `fqn`             | string | No       | Fully qualified name to browse. Omit for top level. Examples: `"my_database"`, `"my_database.my_schema"`.               |
| `maxDepth`        | number | No       | How many levels deep to expand (1=current level only, 2=include children, 3=include grandchildren). Default: 1, max: 3. |
| `maxItems`        | number | No       | Maximum total items to return across all levels. Default: 30, max: 500.                                                 |

**Output**

A JSON object with a hierarchical structure of resources at the requested level. Each resource includes its name, fully qualified name, type (`database`, `schema`, `table`, or `view`), and any children if expanded.

<details>

<summary>Response example</summary>

```
{
  "status": 200,
  "data": {
    "provider": "bigquery",
    "type": "connection",
    "children": [
      {
        "id": "my_project",
        "name": "my_project",
        "type": "database",
        "children": [
          {
            "id": "my_project.retail_data",
            "name": "retail_data",
            "type": "schema",
            "children": [
              {
                "id": "my_project.retail_data.stores",
                "name": "stores",
                "type": "table"
              },
              {
                "id": "my_project.retail_data.sales_regions",
                "name": "sales_regions",
                "type": "table"
              }
            ],
            "childCount": 2,
            "childrenTruncated": false
          }
        ],
        "childCount": 5,
        "childrenTruncated": true
      }
    ],
    "returnedItems": 8,
    "maxItemsApplied": 30,
    "truncated": false,
    "rootChildrenTruncated": false,
    "totalRootChildren": 1
  }
}
```

</details>

**Example**

*"What tables are in the retail\_data dataset?"*

The agent first discovered the `carto_dw` connection via `list_connections`, then drills into a specific dataset:

```
// First call: list top-level projects
list_resources({ connection_name: "carto_dw" })

// Second call: drill into a dataset and expand tables
list_resources({
  connection_name: "carto_dw",
  fqn: "my_project.retail_data",
  maxDepth: 2
})
```

***

### `search_resources`

**Description**

Searches for tables and views by name across a data warehouse connection. Returns a flat, ranked list of matches (exact match first, then prefix, then contains). Use this instead of `list_resources` when you know part of the table name but not where it lives.

For faster results, pass a `scopeFqn` to narrow the search to a specific database or schema. Without a scope, multi-database providers (Snowflake, BigQuery, Databricks) search the first 10 databases/datasets alphabetically. The response includes `searchedContainers`/`totalContainers` so you know if the search was partial.

**Input properties**

| Parameter         | Type   | Required | Description                                                                                                                                   |
| ----------------- | ------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `connection_name` | string | Yes      | Name of the connection (from `list_connections`).                                                                                             |
| `query`           | string | Yes      | Search string to match against table/view names (case-insensitive).                                                                           |
| `type`            | string | No       | Filter results to only `"table"` or only `"view"`.                                                                                            |
| `limit`           | number | No       | Max results to return (1–100). Default: 20.                                                                                                   |
| `scopeFqn`        | string | No       | Narrow search to a specific database, schema, or dataset. Makes the search much faster. Examples: `"my_database"`, `"my_database.my_schema"`. |

**Output**

A JSON object containing a flat array of matching resources. Results are ranked by match quality (exact, then prefix, then contains). The `searchedContainers` and `totalContainers` fields indicate whether the search covered all databases/datasets or was partial.

<details>

<summary>Response example</summary>

```
{
  "status": 200,
  "data": {
    "provider": "bigquery",
    "results": [
      {
        "id": "my_project.retail_data.stores",
        "name": "stores",
        "type": "table",
        "database": "my_project",
        "schema": "retail_data",
        "fqn": "my_project.retail_data.stores",
        "_links": {
          "resources": "/connections/carto_dw/resources/my_project.retail_data.stores"
        }
      },
      {
        "id": "my_project.geo_data.stores_backup",
        "name": "stores_backup",
        "type": "table",
        "database": "my_project",
        "schema": "geo_data",
        "fqn": "my_project.geo_data.stores_backup",
        "_links": {
          "resources": "/connections/carto_dw/resources/my_project.geo_data.stores_backup"
        }
      }
    ],
    "returnedResults": 2,
    "truncated": false,
    "query": "stores",
    "scopeFqn": "my_project.retail_data",
    "searchedContainers": 1,
    "totalContainers": 1
  }
}
```

</details>

**Example**

*"Do we have any table with store locations?"*

The agent searches across the connection for tables matching "stores":

```
search_resources({
  connection_name: "carto_dw",
  query: "stores",
  scopeFqn: "my_project.retail_data"
})
```

***

### `describe`

**Description**

Inspects a table or a SQL query — returns the column schema (and geometry column, geometry type, row count when available) or, when a `column` is provided, distribution statistics for that column. One tool, four modes:

| Mode                  | Required parameters                      | Returns                                             |
| --------------------- | ---------------------------------------- | --------------------------------------------------- |
| Table schema          | `connection_name`, `table_fqn`           | Columns + `geomField` / `geometryType` / `rowCount` |
| Query schema          | `connection_name`, `query`               | Columns + `geomField` / `geometryType` / `rowCount` |
| Column stats on table | `connection_name`, `table_fqn`, `column` | Stats for that column                               |
| Column stats on query | `connection_name`, `query`, `column`     | Stats for that column                               |

Use schema mode to discover what columns a table or query has before styling. Use stats mode in declarative [`view_map`](/carto-for-agents/mcp-server/tools-reference/interactive-tools.md#view_map) flows to drive data-aware styling:

* For `colorBins`: use the returned quantiles to derive thresholds (e.g., quartiles → 4-bucket scale).
* For `colorContinuous`: use `min` and `max` for the domain.
* For `colorCategories`: use the returned categories.

Query mode lets the agent inspect the columns of an arbitrary SQL query without running it against the warehouse. Pass the same SQL string that goes in the source's `sqlQuery` so schema/stats are computed over the same rows the map renders.

{% hint style="info" %}
`describe` only covers tables, views, and SQL queries. **Tilesets and rasters** are pre-baked formats whose schema isn't exposed by this endpoint — fall back to `list_resources`, which also surfaces per-band raster metadata (`colorinterp`, `colortable`, `nodata`, `minresolution`).
{% endhint %}

**Input properties**

| Parameter             | Type   | Required | Description                                                                                                             |
| --------------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------------------- |
| `connection_name`     | string | Yes      | Name of the connection (from `list_connections`).                                                                       |
| `table_fqn`           | string | No\*     | Fully qualified table name (e.g., `"db.schema.table"`). Provide this OR `query`, not both.                              |
| `query`               | string | No\*     | SQL query to inspect. Provide this OR `table_fqn`, not both.                                                            |
| `query_parameters`    | object | No       | Parameter bindings for `query`. Only valid when `query` is set.                                                         |
| `column`              | string | No       | Column to compute statistics for. When present, switches from schema mode to stats mode.                                |
| `max_categories`      | number | No       | Stats mode only. Max categories returned for string/boolean columns. Default 20.                                        |
| `categories_order_by` | string | No       | Stats mode only. Order categories by: `frequency_asc` \| `frequency_desc` \| `alphabetical_asc` \| `alphabetical_desc`. |
| `spatial_data_type`   | string | No       | Stats mode only, for geometry columns: `h3` \| `h3int` \| `quadbin` \| `geo`.                                           |

\* Exactly one of `table_fqn` or `query` is required.

**Output**

Schema mode:

```
{
  "source":       { "type": "table", "fqn": "..." },     // or { "type": "query", "sql": "..." }
  "schema":       [{ "name": "pop_max", "type": "Number" }, ...],
  "geomField":    "geom",          // optional — present when the source has a geometry column
  "geometryType": "Point",         // optional — "Point" | "LineString" | "Polygon"
  "rowCount":     12345            // optional
}
```

Stats mode (discriminated by `type`):

* `Number` → `{ type, min, max, avg, sum, quantiles: { 3: [...], 4: [...], …, 20: [...] } }` — `quantiles[N]` is an array of N+1 numbers `[min, t1, t2, …, t(N-1), max]`.
* `String` / `Boolean` → `{ type, categories: [{ category, frequency }, …] }`.
* `Timestamp` → `{ type, min, max }` as ISO 8601 strings (or `null` when empty).
* `Geometry` → `{ type, extent: { xmin, ymin, xmax, ymax } | null }`.

**Examples**

*"What columns does this table have?"*

```
describe({
  connection_name: "carto_dw",
  table_fqn: "carto-demo-data.demo_tables.populated_places"
})
// → { source, schema: [...], geomField: "geom", geometryType: "Point", rowCount: 7322 }
```

*"Color the population layer by quartiles"*

```
describe({
  connection_name: "carto_dw",
  table_fqn: "carto-demo-data.demo_tables.populated_places",
  column: "pop_max"
})
// → { type: "Number", min: 0, max: 30000000, quantiles: { 4: [0, 5000, 50000, 250000, 30000000] } }

// Drop the first and last (natural extremes); use the inner three as colorBins domain.
```

*"What columns does this SQL query produce?"*

```
describe({
  connection_name: "carto_dw",
  query: "SELECT name, COUNT(*) AS n FROM carto-demo-data.demo_tables.populated_places GROUP BY name"
})
// → { source: { type: "query", sql: "..." }, schema: [{ name: "name", type: "String" }, { name: "n", type: "Number" }] }
```

## Saved maps

### `list_maps`

**Description**

Lists the user's saved CARTO Builder maps. Returns paginated entries with id, name, privacy, owner, thumbnail, and timestamps. The returned id is the input for [`load_builder_map`](/carto-for-agents/mcp-server/tools-reference/interactive-tools.md#load_builder_map).

Common usage:

* Call without arguments for the most recent maps the user can access (owned + shared with them).
* Use `search` to filter by name when the user mentions a specific map by title.
* Use `mine_only=true` when the user explicitly asks for "my maps" (filters out maps shared with them by others).
* Default sort is `updated_at desc` — most recently edited first. Override with `order_by` / `order_direction` if needed.

**Input properties**

| Parameter         | Type    | Required | Description                                                                                     |
| ----------------- | ------- | -------- | ----------------------------------------------------------------------------------------------- |
| `search`          | string  | No       | Free-text search by map name (case-insensitive substring match).                                |
| `page`            | number  | No       | 1-indexed page number. Default 1.                                                               |
| `page_size`       | number  | No       | Items per page. Default 20, max 100.                                                            |
| `order_by`        | string  | No       | Sort field: `title` \| `created_at` \| `updated_at` \| `views` \| `demo`. Default `updated_at`. |
| `order_direction` | string  | No       | `asc` or `desc`. Default `desc`.                                                                |
| `privacy`         | string  | No       | Filter by privacy: `private` \| `shared` \| `public`.                                           |
| `mine_only`       | boolean | No       | When true, only maps owned by the calling user. Default false (includes maps shared with them). |

**Output**

A JSON object with a paginated array of map entries. Each entry includes the map id, name, privacy, owner, thumbnail URL, and timestamps.

**Example**

*"What are my recent maps?"*

```
list_maps({ mine_only: true, page_size: 5 })
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.carto.com/carto-for-agents/mcp-server/tools-reference/platform-tools.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
