# List customisers (`list_customisers`)

Lists the Store customisers, the configurable sign products shoppers design on the storefront, and returns the integer customiser id every other customiser tool needs. Each row reports the customiser name, pricing model, sign category, product family, styling selection mode and whether it is active on the storefront. Results are paginated and always limited to the Store this connection was authorised for. It requires the customisers:read scope and has no side effects.

- Source URL: https://www.signcustomiser.com/help/mcp/tools/list_customisers/
- Markdown URL: https://www.signcustomiser.com/help/mcp/tools/list_customisers.md
- MCP endpoint: https://web.signcustomiser.com/mcp
- Required scope: `customisers:read`
- Behaviour: read

## Purpose

Discover what a Store sells and obtain the customiser ids the rest of the customiser surface takes.

## Annotations

| Hint | Value |
| --- | --- |
| readOnlyHint | true |
| destructiveHint | false |
| idempotentHint | true |
| openWorldHint | false |

## Prerequisites

- A merchant has connected this store and approved the customisers:read scope.

## Arguments

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `limit` | integer | no | How many customisers to return per page, between 1 and 100. Defaults to 20. |
| `cursor` | string | no | The opaque next_cursor value from the previous page. Omit it for the first page and keep every filter identical between pages. |
| `filter` | object | no | Optional filters. An unknown filter is rejected, never ignored. |
| `filter.active` | boolean | no | Only return customisers that are, or are not, live on the storefront. |
| `filter.pricing_model` | string | no | Only return customisers using this pricing model. One of: `simple_letter`, `advanced_letter`, `frame_fit`. |

## Result

Up to `limit` customiser rows in creation order, oldest first and stable across pages, plus the pagination cursor for the next page.

| Property | Type | Required | Description |
| --- | --- | --- | --- |
| `request_id` | string | yes |  |
| `store` | object | yes |  |
| `store.id` | integer | yes |  |
| `store.name` | string | yes |  |
| `customisers` | array of object | yes | The page of customisers, oldest first. |
| `customisers[].id` | integer | yes |  |
| `customisers[].name` | string or null | no |  |
| `customisers[].active` | boolean | yes |  |
| `customisers[].pricing_model` | string | yes | One of: `simple_letter`, `advanced_letter`, `frame_fit`. |
| `customisers[].pricing_model_display_name` | string | yes |  |
| `customisers[].sign_category` | string or null | no |  |
| `customisers[].product_family` | string or null | no |  |
| `customisers[].selection_mode` | string | yes |  |
| `customisers[].updated_at` | string or null | no |  |
| `pagination` | object | yes |  |
| `pagination.has_more` | boolean | yes |  |
| `pagination.next_cursor` | string or null | no | Send this back as `cursor` with identical filters to read the next page. |

## Error cases

| Code | Recovery |
| --- | --- |
| `insufficient_scope` | The connection was approved without customisers:read. |
| `invalid_cursor` | The cursor was altered or reused with different filters; restart with no cursor. |
| `unsupported_value` | A filter value is not one this API accepts; allowed_values lists the accepted set. |

## Example: First page of the active customisers

Request:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "list_customisers",
    "arguments": {
      "limit": 2,
      "filter": {
        "active": true
      }
    }
  }
}
```

Response:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "structuredContent": {
      "request_id": "req_01jz9x2k7c8f3m5n6p7q8r9s0t",
      "store": {
        "id": 12,
        "name": "Demo Signs"
      },
      "customisers": [
        {
          "id": 42,
          "name": "Neon sign builder",
          "active": true,
          "pricing_model": "simple_letter",
          "pricing_model_display_name": "Simple Letter",
          "sign_category": "neon",
          "product_family": "neon",
          "selection_mode": "single_style",
          "updated_at": "2026-06-01T22:09:41Z"
        }
      ],
      "pagination": {
        "has_more": false,
        "next_cursor": null
      }
    }
  }
}
```

## Example: A pricing model that does not exist (error)

Request:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "list_customisers",
    "arguments": {
      "filter": {
        "pricing_model": "fixed_height"
      }
    }
  }
}
```

Response:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "isError": true,
    "structuredContent": {
      "error": {
        "code": "invalid_parameter",
        "title": "Invalid query parameter",
        "detail": "The filter[pricing_model] value is not a supported pricing model.",
        "recovery": "Correct the parameter named in parameter. Dates are YYYY-MM-DD in UTC and identifiers are integers between 1 and 2147483647.",
        "parameter": "filter[pricing_model]",
        "allowed_values": [
          "simple_letter",
          "advanced_letter",
          "frame_fit"
        ]
      }
    }
  }
}
```
