# Flexlists MCP server — guide for AI agents

Flexlists is a no-code database: **lists** (tables) with **rows**, **fields** (columns) and **views**
(Table, Kanban, Calendar, Gallery, Timeline, Gantt, Map, Chart, Mind map, Checklist).
This MCP server lets you read and change a user's lists with the rights of their API key or OAuth grant.

- Endpoint: `https://flexlists.com/mcp` (Streamable HTTP, MCP 2025-06-18; stateless, JSON responses)
- Auth: `Authorization: Bearer <API key>` (Integrations → API keys / AI agents (MCP)), or OAuth 2.1
  (discovery: `https://flexlists.com/.well-known/oauth-protected-resource/mcp`)
- Human docs: https://flexlists.com/docs/mcp

## How to work

1. Call `whoami`: who the key belongs to, its scope (whole account, one workspace, specific lists,
   or an API access configuration) and whether it is read-only.
2. `list_lists` → pick a `listId`. Every list tool takes this number.
3. `get_list_schema` before writing: rows are keyed by field **name**; Choice fields only take their options.
4. Read with `search_rows` (filter, full-text, sort, cursor) or `get_view_rows` (a view's own filters and sort).
5. Write with `create_rows` / `update_rows` (max 100 rows per call).
6. Destructive tools (`delete_rows`, `delete_list`, `delete_field`, `unshare`, `delete_group`,
   `remove_group_member`, `delete_webhook`) need `"confirm": true`. First tell the user exactly what
   goes, and only confirm after they agreed.

## Values

| Field type | Read | Write |
|---|---|---|
| Text, LongText, Markdown | string | string |
| Integer, Decimal, … | number | number |
| Boolean | true / false | true / false |
| Date | "2024-05-01" | "2024-05-01" |
| DateTime | ISO 8601 | ISO 8601 or epoch ms |
| Choice | label | label (case-insensitive) |
| MultiChoice | [labels] | [labels] |
| User | { id, name } | email or user id |
| Lookup (relation) | { id, label } | related row id, { "id": 12 } or its label ("Acme") |
| Sublist | [{ id, label }] | [row ids] |
| File, Image | [{ name, url, size }] (url valid 1 h) | attach_file_to_row |

`null` clears a field. Unknown field names are refused with the list of valid names.

## Filters (`where`)

The syntax of `POST /api/v1/lists/{listId}/rows/search`: an object of conditions that must all hold.

```json
{ "Status": "Open", "Due": { "op": "lt", "value": "2024-06-01" }, "Name": { "op": "contains", "value": "acme" } }
```

ops: `eq`, `neq`, `contains`, `gt`, `gte`, `lt`, `lte`, `empty`, `notEmpty`. Keys may also be `id`,
`createdAt`, `updatedAt`. `query` adds a full-text "contains" over the text fields.

## Paging and size

- `search_rows` / `get_view_rows`: max 200 rows per call; when `nextCursor` is not null, call again
  with `cursor` (and the same sort / filter).
- Every result stays under 1 MB. A bigger page comes back shorter with a `note`; continue with the cursor
  or ask for fewer `fields`.
- `aggregate_rows` (count / sum / avg / min / max, grouped by a field; dates by day…year) and
  `count_rows` answer "how many / how much" without reading rows.

## Files

- `attach_file_to_row`: from a public http(s) URL (max 25 MB, no private / internal addresses) or base64 (max 5 MB).
- `get_file`: short-lived download links (1 hour), never the bytes.
- `read_spreadsheet`, `import_spreadsheet_rows`, `create_list_from_spreadsheet`: CSV / XLSX by URL or fileId.

## Permissions

- A key never sees lists outside its scope. A read-only key gets a tool error on write tools.
- Writes need the same role as in the app (e.g. AddOnly may only add rows; schema changes need full access).
- API access configuration keys only reach their own lists, with their own permission per list and endpoint allowlist.
- Rate limit: 600 requests per minute per key (HTTP 429 + Retry-After).

## Tools

| Tool | Kind | What it does |
|---|---|---|
| `whoami` | read | The Flexlists user this key belongs to, the workspaces it can see, and what the key may do: its scope (user = the whole account, workspace = one workspace, tables = specific lists, config = an API access configuration), read-only or read & write, and when it expires. |
| `list_workspaces` | read | The workspaces this key can see (id, name, whether the user owns it). |
| `list_lists` | read | The lists (tables) this key can read: listId, name, workspace and folder. |
| `get_list_schema` | read | The fields (columns) of a list: name, type, required, read-only, the options of Choice fields, and for relation fields (Lookup / Sublist) the related list and its label field. |
| `create_list` | write | Create a new list with fields and optional first rows. |
| `rename_list` | write | Rename a list and/or change its description. |
| `delete_list` | write, destructive (confirm) | Delete a list with all its rows and views. |
| `list_folders` | read | The folders of My Lists and My Views (one tree, paths like "Sales/Q4") with the lists and views in each. |
| `create_folder` | write | Make a folder for lists and views, optionally inside another of your folders. |
| `move_to_folder` | write | Move lists (listIds) and/or views (viewIds) into one of your folders, or to the root (folder "" or "root"). |
| `list_templates` | read | Templates to start from. |
| `create_from_template` | write | Make a list (or a list + view) from a template of list_templates, with its demo rows unless demo_data is false. |
| `add_field` | write | Add a field (column) to a list. |
| `update_field` | write | Rename a field, make it required or not, change its description, or set the options of a Choice field (the full new list; existing options keep their colour, renamed ones are new options). |
| `delete_field` | write, destructive (confirm) | Delete a field and its values in every row. |
| `search_rows` | read | Read rows of a list: filter (where), full-text search (query), sort, only some fields, paged with a cursor (max 200 rows per call). |
| `get_row` | read | One row by id, keyed by field name (files as short-lived download links, relations as { id, label }). |
| `create_rows` | write | Add 1 to 100 rows. |
| `update_rows` | write | Change 1 to 100 rows: each { "id": 17, "fields": { "Field name": value } } — only the given fields change. |
| `delete_rows` | write, destructive (confirm) | Delete 1 to 100 rows by id. |
| `count_rows` | read | How many rows match a filter (where / query); no filter = all rows. |
| `aggregate_rows` | read | Totals of a list, optionally grouped by a field (like a chart): count, sum, avg, min, max of number fields. |
| `list_views` | read | The views of a list (Table, Kanban, Calendar, Gallery, Timeline, Gantt, Map, Chart, Mind map, Checklist, …): viewId, name, type. |
| `list_view_types` | read | The view types Flexlists can make, what each is good for, and the fields ("slots") each needs with the field types they accept — use it before create_view. |
| `create_view` | write | Add a view to an existing list: KanBan, Calendar, TimeLine, Gantt, Map, Gallery, Chart, MindMap, Spreadsheet or List (table). |
| `get_view_rows` | read | The rows of a view as the view shows them: its own filters and sort, its visible fields only. |
| `create_checklist` | write | Build a CHECKLIST (an inspection, opening routine, onboarding, audit…): three linked lists (items, runs, results) and the Checklist view. |
| `list_comments` | read | The comments (row chat) on a row, oldest first: author, text, time. |
| `add_comment` | write | Add a comment to a row (its row chat), as the key's user. |
| `get_row_history` | read | When a row was created and last changed, and its recent edits (who, when, which fields from → to) from the change log, which keeps edits for 7 days. |
| `attach_file_to_row` | write | Store a file in a File or Image field of a row (added to the files it has): from a URL (Flexlists downloads it, max 25 MB, public http/https addresses only) or as base64 content (max 5 MB, give fileName). |
| `get_file` | read | The files in a File / Image field of a row: name, size, fileId and a download link that works for 1 hour without login (the bytes are never sent inline). |
| `read_spreadsheet` | read | Look into a CSV / XLSX file (by URL or fileId): sheet names, column headers with guessed types, row count and the first rows. |
| `create_list_from_spreadsheet` | write | Make a new list from a CSV / XLSX file (by URL or fileId) and import ALL its rows on the server. |
| `import_spreadsheet_rows` | write | Append the rows of a CSV / XLSX file (by URL or fileId) to an existing list. |
| `get_sharing` | read | Who has access to a list: people (name, email, role, pending invites) and groups (name, role). |
| `share_list` | write | Give people access to a list by email. |
| `share_list_with_group` | write | Give one of your groups access to a list (everyone in it, also people added later). |
| `set_share_role` | write | Change the role of a person (email) or a group on a list. |
| `unshare` | write, destructive (confirm) | Take away a person's (email; also cancels a pending invite) or a group's access to a list. |
| `list_groups` | read | Your groups (named sets of people) with their members, pending invites and the lists each group can open. |
| `create_group` | write | Create a group and optionally add members by email. |
| `update_group` | write | Rename a group or change its description. |
| `delete_group` | write, destructive (confirm) | Delete one of your groups: its members lose the access they had through it. |
| `add_group_members` | write | Add people to a group by email (unknown addresses get an invitation). |
| `remove_group_member` | write, destructive (confirm) | Remove a person (email) from a group, or cancel their invitation. |
| `list_forms` | read | Your public forms: id, name, on/off, public link and number of submissions. |
| `get_form` | read | One form: its public URL, steps and questions, which lists it writes to (with what visitors may do there), settings and submission count. |
| `create_form` | write | Build a public FORM with AI (planned and built like the form builder does): a shareable page where visitors fill in answers that land in your lists (missing lists are created). |
| `list_form_submissions` | read | The latest submissions of one of your forms (newest first): time, answers, the rows they created, and errors. |
| `set_form_enabled` | write | Turn one of your forms on (visitors can submit) or off. |
| `list_automations` | read | Your integrations and workflows (automations): id, name, kind, on/off, trigger, last run. |
| `create_automation` | write | Start a new integration (connect a list to another service: email, Slack, a CRM, …) or workflow (automate your own data on a schedule or when rows change). |
| `set_automation_enabled` | write | Switch one of your automations on or off (switching on fails while secrets are missing). |
| `run_automation` | write | Run one of your automations now (a test run with a sample row for table-triggered ones). |
| `list_applications` | read | The applications (multi-page apps on your lists) you own or maintain, with their links, and their solutions. |
| `create_application` | write | Start a new multi-page application (a portal, a customer or employee app, …) on your lists. |
| `list_webhooks` | read | Your row-change webhooks on lists in this key's scope: id, list, events, target URL, on/off. |
| `create_webhook` | changes settings | Send row changes of a list to a URL (HTTPS POST, signed with the returned secret, shown only now). |
| `delete_webhook` | changes settings, destructive (confirm) | Remove one of your webhooks (by id from list_webhooks). |
| `explain_item` | read | Explain one of your automations, forms, applications or view templates: what it does, how to use it, which secrets it needs and whether they are set, how to change it. |
| `contact_support` | changes settings | File a ticket with the Flexlists support team (humans), who reply by email. |

## Resources and prompts

- Resources: `flexlists://lists` (index), `flexlists://list/{listId}/schema`, `flexlists://docs/llm` (this guide).
- Prompts: `analyze_list`, `build_tracker`, `import_data`.
