# Tools

Every tool the Roma MCP server offers, as a client sees it over `tools/list`. 29 tools, in 7 groups. Each one acts as the signed-in person, on their own workspace only, and returns both a text and a structured result.

This page is generated from the server's live registration. What you read here is what your client's model reads.

## At a glance

- **Context**: [`get_context`](#get_context)
- **Tasks**: [`list_tasks`](#list_tasks), [`get_task_context`](#get_task_context), [`create_task`](#create_task), [`update_task`](#update_task), [`delete_task`](#delete_task)
- **Projects**: [`list_projects`](#list_projects), [`create_project`](#create_project), [`update_project`](#update_project)
- **Notes and search**: [`search`](#search), [`list_notes`](#list_notes), [`get_note`](#get_note), [`create_note`](#create_note), [`update_note`](#update_note), [`delete_note`](#delete_note)
- **Collections**: [`list_collections`](#list_collections), [`get_collection_items`](#get_collection_items), [`create_collection`](#create_collection), [`update_collection`](#update_collection), [`delete_collection`](#delete_collection), [`add_collection_items`](#add_collection_items), [`update_collection_items`](#update_collection_items), [`delete_collection_items`](#delete_collection_items), [`create_image_upload`](#create_image_upload)
- **Trash**: [`list_deleted`](#list_deleted), [`restore_deleted`](#restore_deleted)
- **Automations**: [`list_automations`](#list_automations), [`get_automation_runs`](#get_automation_runs), [`run_automation`](#run_automation)

**Reading the badges.** `Read-only` tools change nothing and a client can run them without asking. `Adds data` tools create something new and never touch what exists. `Updates or removes existing data` tools update or delete, and clients ask before each call by default. `Safe to retry` marks a call that lands once however often it is repeated. `Reaches outside Roma` marks a tool that touches something beyond the workspace: `run_automation` can act through the person's connected apps, and the two row tools download images from public URLs you name.

**Ids.** Every task, note, project, list, row and automation has a UUID. Tools that take an id answer "not found" for an id that belongs to someone else. Get ids from `get_context`, the list tools or `search`; never guess one.

**Time.** Instants are ISO 8601 with a zone. A window such as `createdAfter` and `createdBefore` includes its lower bound and excludes its upper bound. The person's timezone and today's date come from `get_context`.

**Errors.** A failed call returns `isError: true` with one sentence that says what to change. Nothing is thrown.

## Context

One call that orients a conversation: who the user is, what is due, recent notes, lists, automations and what they asked Roma to remember.

### get_context

**Get workspace context** · `Read-only`

Use this at the start of a conversation that involves the user's Roma workspace, or when you need an overview of it. Returns, in one call: how Roma works; the user (name, timezone, today's date and local time); what they asked the AI to remember about them; their projects; overdue, due-today, in-progress and upcoming tasks; unsorted tasks; recently touched notes; their collections with columns; their automations with the last run; and the last few days of activity. Everything comes with ids for follow-up calls. It is an overview, not the full data: use search, list_tasks, get_note or get_collection_items for depth. Pass focusProjectId to scope the task sections to one project.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `focusProjectId` | `string` | no | Optional project UUID. Scopes the task sections to that project; the rest stays workspace-wide. |

**Returns**

- `about` (`string[]`)
- `user` (`object`)
- `unavailable` (`string[]`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "get_context",
    "arguments": {}
  }
}
```

## Tasks

The to-do list. Create, list, read, update, move and delete tasks, each scoped to a project or left unsorted.

### list_tasks

**List tasks** · `Read-only`

List, filter, and search the user's tasks — the way to find work to pick up. Returns tasks ordered by due date, then priority. Scope to the whole workspace, unsorted tasks only, or a single project. By default completed tasks are excluded.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `scope` | `string` | no | "all" (default) for everything, "inbox" for unsorted items only (no project — the value keeps its legacy name), or a project UUID for that project. |
| `query` | `string` | no | Free-text search across title and description. |
| `taskStatus` | `"todo" \| "inProgress" \| "completed"[]` | no | Filter to these statuses. Omit to use the default active set (excludes completed). |
| `dueAfter` | `string` | no | ISO 8601 instant — only tasks due on/after this (inclusive). |
| `dueBefore` | `string` | no | ISO 8601 instant — only tasks due before this (exclusive). Today = dueAfter today 00:00 local, dueBefore tomorrow 00:00 local; overdue = dueBefore today 00:00 alone. |
| `createdAfter` | `string` | no | ISO 8601 instant — only tasks created on/after this. |
| `createdBefore` | `string` | no | ISO 8601 instant — only tasks created before this (exclusive). |
| `updatedAfter` | `string` | no | ISO 8601 instant — only tasks last changed on/after this. |
| `updatedBefore` | `string` | no | ISO 8601 instant — only tasks last changed before this (exclusive). |
| `completedAfter` | `string` | no | ISO 8601 instant — only tasks completed on/after this. Implies completed tasks unless taskStatus says otherwise. |
| `completedBefore` | `string` | no | ISO 8601 instant — only tasks completed before this (exclusive). |
| `sort` | `"due" \| "created" \| "updated" \| "completed"` | no | Row order. Default 'due' (due date, then priority); a timestamp sort returns newest first. |
| `limit` | `integer` | no | Max results (default 50). (1 to 200) |

**Returns**

- `count` (`number`)
- `tasks` (`object[]`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "list_tasks",
    "arguments": {}
  }
}
```

### get_task_context

**Get task context** · `Read-only`

Fetch one task with everything needed to start working on it: the full task row (description, status, priority, due date) and the project it belongs to. The equivalent of opening an issue.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `artifactId` | `string` | yes | The task's UUID. |

**Returns**

- `task` (`object`)
- `project` (`object | null`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "get_task_context",
    "arguments": {
      "artifactId": "<artifactId>"
    }
  }
}
```

### create_task

**Create task** · `Adds data`

Create a task. Omit projectId to leave it unsorted (no project); set projectId to file it under a project. The task is enriched by AI in the background after creation, so enriched fields may appear on a subsequent read. Returns the created task.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `title` | `string` | yes | Short, clear task title. |
| `description` | `string` | no | Optional longer details. |
| `projectId` | `string` | no | Project UUID. Omit to leave it unsorted (no project). |
| `priority` | `"low" \| "medium" \| "high"` | no |  |
| `taskStatus` | `"todo" \| "inProgress" \| "completed"` | no | Defaults to 'todo'. |
| `dueAt` | `string` | no | ISO 8601 due timestamp. |

**Returns**

- `id` (`string`)
- `title` (`string | null`)
- `description` (`string | null`)
- `taskStatus` (`string | null`)
- `priority` (`string | null`)
- `dueAt` (`string | null`)
- `projectId` (`string | null`)
- `createdAt` (`string | null`)
- `updatedAt` (`string | null`)
- `editedAt` (`string | null`)
- `completedAt` (`string | null`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "create_task",
    "arguments": {
      "title": "<title>"
    }
  }
}
```

### update_task

**Update task** · `Updates or removes existing data` · `Safe to retry`

Update fields on an existing task — title, body, status, priority, due date, or which project it is in (projectId; null moves it out to unsorted). Use status transitions to report progress (e.g. todo → inProgress → completed). Only the fields you pass are changed. The body merge mode controls how `description` combines with the existing body — adding text appends/prepends; it never replaces unless you explicitly ask it to.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `taskId` | `string` | yes | The task's UUID. |
| `title` | `string` | no |  |
| `description` | `string \| null` | no | Body text to merge in per `mode`. Omit to leave the body unchanged; null to clear it. |
| `mode` | `"prepend" \| "append" \| "replace" \| "insertAfter"` | no | How `description` merges: 'append' (default, at the bottom), 'prepend' (at the top), 'insertAfter' (right after the line named in `anchor`), or 'replace' (swap the whole body — only when the user explicitly asked to rewrite it; never to add content; requires confirmReplace: true). |
| `confirmReplace` | `boolean` | no | Required (true) for mode 'replace': confirms the user explicitly asked to swap the WHOLE body, deleting everything in it. Never pass it on the user's behalf without that explicit ask. |
| `anchor` | `string` | no | For mode 'insertAfter' only: a verbatim snippet of the existing line to insert after. Errors if not found. |
| `taskStatus` | `"todo" \| "inProgress" \| "completed"` | no |  |
| `priority` | `"low" \| "medium" \| "high" \| null` | no |  |
| `dueAt` | `string \| null` | no | ISO 8601 timestamp, or null to clear. |
| `projectId` | `string \| null` | no | Move the task: a project UUID (from list_projects or get_context) files it there; null moves it out to unsorted. Omit to leave it where it is. |

**Returns**

- `id` (`string`)
- `title` (`string | null`)
- `description` (`string | null`)
- `taskStatus` (`string | null`)
- `priority` (`string | null`)
- `dueAt` (`string | null`)
- `projectId` (`string | null`)
- `createdAt` (`string | null`)
- `updatedAt` (`string | null`)
- `editedAt` (`string | null`)
- `completedAt` (`string | null`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "update_task",
    "arguments": {
      "taskId": "<taskId>"
    }
  }
}
```

### delete_task

**Delete task** · `Updates or removes existing data` · `Safe to retry`

Delete a task (or subtask) by id. This is a SOFT delete — the task is recoverable for ~30 days before it is purged. Deleting a task also removes it from search. Deletes one task per call so each delete is confirmed individually.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `artifactId` | `string` | yes | The task's UUID. |

**Returns**

- `deleted` (`boolean`)
- `id` (`string`)
- `title` (`string | null`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "delete_task",
    "arguments": {
      "artifactId": "<artifactId>"
    }
  }
}
```

## Projects

Containers for tasks, notes and lists. Resolve names to ids before filing anything.

### list_projects

**List projects** · `Read-only`

List all of the user's projects. Use this to resolve a project name to its UUID before creating or filing a task, or to understand the workspace structure.

**Parameters**

This tool takes no parameters.

**Returns**

- `count` (`number`)
- `projects` (`object[]`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "list_projects",
    "arguments": {}
  }
}
```

### create_project

**Create project** · `Adds data`

Create a project — a folder that groups the user's tasks and notes. Use it when the user wants a new project, or to give work a home that has none; check list_projects or get_context first so an existing project is not duplicated. Returns the project with its id, ready for create_task / update_task projectId.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `name` | `string` | yes | Project name, in the user's own words. |
| `emoji` | `string` | no | Optional single emoji for the project. |

**Returns**

- `id` (`string`)
- `name` (`string | null`)
- `emoji` (`string | null`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "create_project",
    "arguments": {
      "name": "<name>"
    }
  }
}
```

### update_project

**Update project** · `Updates or removes existing data` · `Safe to retry`

Rename a project or change its emoji. Only the fields you pass change; emoji null removes it. Does not move or change the project's tasks.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `projectId` | `string` | yes | The project's UUID (from list_projects or get_context). |
| `name` | `string` | no | New name. |
| `emoji` | `string \| null` | no | New emoji, or null to remove it. |

**Returns**

- `id` (`string`)
- `name` (`string | null`)
- `emoji` (`string | null`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "update_project",
    "arguments": {
      "projectId": "<projectId>"
    }
  }
}
```

## Notes and search

Prose the user keeps. Search finds notes, tasks and list rows by meaning or keyword; notes are read and written as Markdown.

### search

**Search notes & tasks** · `Read-only`

Search the user's Roma workspace — their notes, tasks, typed lists and the rows inside them — by meaning or keyword (hybrid semantic + keyword retrieval). Use this when the user asks about their own information, plans or anything they may have saved, and before adding something that may already exist. Their wording often won't match their notes' wording; the semantic arm bridges that gap (and across languages). Returns the best-matching passage per item; get_note returns a note's full text. An empty result means nothing relevant is saved. Not for general web knowledge.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `query` | `string` | yes | Natural-language query — what the user is trying to find, in their words. |
| `limit` | `integer` | no | Max results (default 10). (1 to 20) |
| `after` | `string` | no | Only items CREATED on/after this ISO 8601 timestamp. Use when scoping by when it was saved ("last week", "in March"). |
| `before` | `string` | no | Only items CREATED before this ISO 8601 timestamp (exclusive). Pair with `after` to bound a window. |

**Returns**

- `count` (`number`)
- `results` (`object[]`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "search",
    "arguments": {
      "query": "<query>"
    }
  }
}
```

### list_notes

**List notes** · `Read-only`

List the user's notes, newest first. Scope to the whole workspace, unsorted notes only, or a single project. Returns a snippet of each body; use get_note for the full text. This is browse-by-container — use search to find by topic.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `scope` | `string` | no | "all" (default) for everything, "inbox" for unsorted items only (no project — the value keeps its legacy name), or a project UUID for that project. |
| `createdAfter` | `string` | no | ISO 8601 instant — only notes created on/after this. |
| `createdBefore` | `string` | no | ISO 8601 instant — only notes created before this (exclusive). |
| `updatedAfter` | `string` | no | ISO 8601 instant — only notes last changed on/after this. |
| `updatedBefore` | `string` | no | ISO 8601 instant — only notes last changed before this (exclusive). |
| `sort` | `"created" \| "updated"` | no | Row order, newest first on that stamp. Default created. |
| `limit` | `integer` | no | Max results (default 50). (1 to 200) |

**Returns**

- `count` (`number`)
- `docs` (`object[]`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "list_notes",
    "arguments": {}
  }
}
```

### get_note

**Get note** · `Read-only`

Read one note in full by its id — the companion to search: search returns the matched passage, this pulls the whole document when you need more than the snippet. Returns the note's title and full body as Markdown, and, for a note a meeting was recorded into, the attributed transcript once its recording is done.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `docId` | `string` | yes | The note's UUID (from a search result). |

**Returns**

- `id` (`string`)
- `title` (`string`)
- `content` (`string`)
- `projectId` (`string | null`)
- `createdAt` (`string | null`)
- `transcript` (`string`)
- `recording` (`object`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "get_note",
    "arguments": {
      "docId": "<docId>"
    }
  }
}
```

### create_note

**Create note** · `Adds data`

Capture a note for the user. Omit projectId to leave it unsorted (no project); set projectId to file it under a project. The body is stored as authored within the editor's supported Markdown subset (unsupported constructs degrade to plain text) — no AI cleanup or reclassification runs — and indexed for search. Returns the created note.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `content` | `string` | yes | The note body, as Markdown (headings `#`, lists, task lists `- [ ]`, bold, links — the editor's supported subset). Rendered to rich text; author real Markdown, not literal markers. |
| `title` | `string` | no | Short title. Omit to let the body speak for itself. |
| `projectId` | `string` | no | Project UUID. Omit to leave it unsorted (no project). |

**Returns**

- `id` (`string`)
- `title` (`string | null`)
- `content` (`string`)
- `projectId` (`string | null`)
- `createdAt` (`string | null`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "create_note",
    "arguments": {
      "content": "<content>"
    }
  }
}
```

### update_note

**Update note** · `Updates or removes existing data`

Edit an existing note — its title, body, or which project it's in. Only the fields you pass change. The body merge mode controls how `content` combines with the existing body. Re-indexes for search automatically.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `docId` | `string` | yes | The note's UUID. |
| `title` | `string` | no | New title. Omit to leave unchanged. |
| `content` | `string` | no | Markdown body to merge in (headings, lists, bold, links). Omit for a title/project-only edit. |
| `mode` | `"prepend" \| "append" \| "replace" \| "insertAfter"` | no | How `content` merges: 'append' (default, at the bottom), 'prepend' (at the top), 'replace' (swap the whole body — only when the user explicitly asked to rewrite it; never to add content; requires confirmReplace: true), or 'insertAfter' (place it right after the line named in `anchor`, matching that line's formatting). |
| `confirmReplace` | `boolean` | no | Required (true) for mode 'replace': confirms the user explicitly asked to swap the WHOLE body, deleting everything in it. Never pass it on the user's behalf without that explicit ask. |
| `anchor` | `string` | no | For mode 'insertAfter' only: a verbatim snippet of the existing line to insert after. Errors if not found. |
| `projectId` | `string` | no | Project UUID to move the note into, or "inbox" to clear its project (unsorted — the value keeps its legacy name). Omit to leave it where it is. |

**Returns**

- `id` (`string`)
- `title` (`string | null`)
- `content` (`string`)
- `projectId` (`string | null`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "update_note",
    "arguments": {
      "docId": "<docId>"
    }
  }
}
```

### delete_note

**Delete note** · `Updates or removes existing data` · `Safe to retry`

Delete a note by id. This is a SOFT delete — the note is recoverable for ~30 days before it is purged. Deleting a note also removes it from search. Deletes one note per call so each delete is confirmed individually.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `docId` | `string` | yes | The note's UUID. |

**Returns**

- `deleted` (`boolean`)
- `id` (`string`)
- `title` (`string | null`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "delete_note",
    "arguments": {
      "docId": "<docId>"
    }
  }
}
```

## Collections

Typed lists: a table with named columns, one row per thing. Rows go in and are corrected many at a time.

### list_collections

**List collections** · `Read-only`

List the user's collections (typed lists — a reading list, a watchlist, an expenses tracker). Returns each list's id, name, standing instructions, row count, and its COLUMNS with their stable ids — the ids add_collection_items and update_collection_items take. Use it before writing to a collection whose columns you have not read yet. Pass suppressOptions: true when you only need names/counts — select columns can carry hundreds of options (you don't need them to write: a select value may be sent as its label).

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `suppressOptions` | `boolean` | no | true replaces each select column's option list with an optionCount — much smaller payload. |

**Returns**

- `count` (`number`)
- `collections` (`object[]`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "list_collections",
    "arguments": {}
  }
}
```

### get_collection_items

**Get collection rows** · `Read-only`

Read the rows of one collection. Values are keyed by COLUMN ID (see list_collections); a select column's value is an option id, a multiSelect column's an array of option ids. Each row also lists its image attachments (so you can verify an import's images actually landed); pass includeImageUrls: true for short-lived viewable links. Paginated: the result carries totalCount and hasMore — keep calling with offset until hasMore is false to read a large list completely. Archived rows are left out unless includeArchived: true. Use to check what a list already holds before adding to it.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `collectionId` | `string` | yes | The collection's UUID (from list_collections). |
| `includeArchived` | `boolean` | no | true also returns archived rows (hidden from every list by default) so one can be brought back with update_collection_items; each row then says whether it is archived. |
| `limit` | `integer` | no | Max rows per page (default 50, newest first). (1 to 200) |
| `offset` | `integer` | no | Rows to skip — page through a big list with offset + limit until hasMore is false. (0 to 9007199254740991) |
| `includeImageUrls` | `boolean` | no | true additionally returns a short-lived signed `url` per attachment so the images can be viewed. Off by default. |
| `createdAfter` | `string` | no | ISO 8601 instant — only rows added on/after this. |
| `createdBefore` | `string` | no | ISO 8601 instant — only rows added before this (exclusive). |
| `updatedAfter` | `string` | no | ISO 8601 instant — only rows last changed on/after this. |
| `updatedBefore` | `string` | no | ISO 8601 instant — only rows last changed before this (exclusive). |

**Returns**

- `count` (`number`)
- `totalCount` (`number`)
- `offset` (`number`)
- `hasMore` (`boolean`)
- `items` (`object[]`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "get_collection_items",
    "arguments": {
      "collectionId": "<collectionId>"
    }
  }
}
```

### create_collection

**Create collection** · `Adds data`

Create a typed list with its columns. Every column is equal — declare the ones the list actually needs, including a name column if rows have names (a list of measurements or dates may have none). Returns the created list WITH the stable column ids to use when adding rows.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `name` | `string` | yes | The list's name. |
| `instructions` | `string` | no | Standing rules for how entries should be handled, one rule per line. Max 500 characters — they ride in the prompt on every turn. (up to 500 characters) |
| `properties` | `object[]` | no | The columns. Omit to start with one default text column the user can rename, retype or delete. |

**Returns**

- `id` (`string`)
- `name` (`string`)
- `columns` (`object[]`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "create_collection",
    "arguments": {
      "name": "<name>"
    }
  }
}
```

### update_collection

**Update collection** · `Updates or removes existing data` · `Safe to retry`

Rename a collection or edit its standing instructions. `instructions` REPLACES the existing text — read the current value first (list_collections) and carry forward anything still true; null clears them. Column (schema) editing is not available over MCP — new select options mint automatically when adding or updating rows.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `collectionId` | `string` | yes | The collection's UUID (from list_collections). |
| `name` | `string` | no | New list name. |
| `instructions` | `string \| null` | no | REPLACES the standing rules (max 500 characters — they ride the prompt every turn); null clears them. |

**Returns**

- `id` (`string`)
- `name` (`string`)
- `instructions` (`string | null`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "update_collection",
    "arguments": {
      "collectionId": "<collectionId>"
    }
  }
}
```

### delete_collection

**Delete collection** · `Updates or removes existing data` · `Safe to retry`

Delete a collection (typed list) by id. Deleting the list also deletes ALL its rows. SOFT delete — the list and its rows are recoverable for ~30 days via restore_deleted (type "collection"), which brings the rows deleted with it back too. When the list still holds rows the call refuses unless confirmDeleteItems is true, so the blast radius is always named before it happens.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `collectionId` | `string` | yes | The collection's UUID (from list_collections). |
| `confirmDeleteItems` | `boolean` | no | Required (true) when the list holds rows: confirms deleting the list AND every row in it. Confirm with the user first. |

**Returns**

- `deleted` (`boolean`)
- `id` (`string`)
- `name` (`string`)
- `itemsDeleted` (`number`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "delete_collection",
    "arguments": {
      "collectionId": "<collectionId>"
    }
  }
}
```

### add_collection_items

**Add collection rows** · `Adds data` · `Reaches outside Roma`

Add rows to a collection, many in one call (the import path). Values are keyed by column id or name; a select value may be its label or option id, a multiSelect value is an ARRAY of them, and unknown labels become new options. Keys that match no column come back in `unknownKeys`. Images that could not be stored come back in `imageFailures` with the reason; create_image_upload is the reliable path for images. Every row is inserted unless `matchOn` names columns to match on; a matched row keeps every filled cell and only gains what it lacks (empty cells, notes, images), so nothing is overwritten. To change a filled cell use update_collection_items (re-adding without matchOn creates a duplicate).

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `collectionId` | `string` | yes | The collection's UUID (from list_collections). |
| `matchOn` | `string[]` | no | Column ids or names that identify an existing row. When given, a row whose listed cells all match an existing row is not added again: the existing row gains the incoming row's empty-cell values, notes and images and keeps every cell it already had; matching is exact. Omit to always insert — no column is a natural key, so there is no default dedup. |
| `items` | `object[]` | yes | Every row to add, in one call. (up to 200 items) |

**Returns**

- `added` (`number`)
- `itemIds` (`string[]`)
- `unknownKeys` (`string[]`)
- `imagesAttached` (`number`)
- `imageFailures` (`object[]`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "add_collection_items",
    "arguments": {
      "collectionId": "<collectionId>",
      "items": [
        {}
      ]
    }
  }
}
```

### update_collection_items

**Update collection rows** · `Updates or removes existing data` · `Safe to retry` · `Reaches outside Roma`

Update existing rows of ONE collection, many in one call; pass only what changes. `values` MERGE into the row (only the keys sent change; "" clears a cell), `body` replaces the notes, `imageUrls` add images (clearImages: true drops the old ones first), `archived` sets a row aside or brings it back. A key matching no column is an error; rows earlier in the batch stay updated and are named, so re-send only the rest. Read row ids and current values with get_collection_items first.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `collectionId` | `string` | yes | The collection's UUID (from list_collections). |
| `items` | `object[]` | yes | Every row to update, in one call. (up to 200 items) |

**Returns**

- `updated` (`number`)
- `itemIds` (`string[]`)
- `imagesAttached` (`number`)
- `imageFailures` (`object[]`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "update_collection_items",
    "arguments": {
      "collectionId": "<collectionId>",
      "items": [
        {
          "itemId": "<itemId>"
        }
      ]
    }
  }
}
```

### delete_collection_items

**Delete collection rows** · `Updates or removes existing data` · `Safe to retry`

Delete rows from collections by id — up to 50 per call. SOFT delete: every row stays recoverable for ~30 days via restore_deleted (type "collectionItem") before it is purged, and drops out of search. Returns a per-id result — ids that don't resolve are reported and the rest still delete.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `itemIds` | `string[]` | yes | The rows' UUIDs (from get_collection_items). Up to 50 per call. (up to 50 items) |

**Returns**

- `deleted` (`number`)
- `results` (`object[]`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "delete_collection_items",
    "arguments": {
      "itemIds": [
        "<itemIds>"
      ]
    }
  }
}
```

### create_image_upload

**Create image upload** · `Adds data`

Get pre-signed URLs to upload images DIRECTLY into Roma storage — the reliable alternative to passing third-party links in imageUrls (those must stay fetchable until the server downloads them; short-lived signed links often expire first). For each slot: HTTP PUT the raw image bytes to uploadUrl with the matching Content-Type header (valid ~2 hours), then pass its bucketPath as an imageUrls entry in add_collection_items / update_collection_items. Keep images at or under 10 MB (maxBytes). Up to 10 slots per call.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `mimeType` | `"image/png" \| "image/jpeg" \| "image/heic" \| "image/webp"` | yes | The image type you will upload (all slots in one call share it). |
| `count` | `integer` | no | How many upload slots (default 1). (1 to 10) |

**Returns**

- `uploads` (`object[]`)
- `maxBytes` (`number`)
- `validForSeconds` (`number`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "create_image_upload",
    "arguments": {
      "mimeType": "image/png"
    }
  }
}
```

## Trash

Every delete is soft. The trash lists what was deleted and restores one item per call for about 30 days.

### list_deleted

**List deleted items (trash)** · `Read-only`

The trash: everything soft-deleted in the last ~30 days — tasks, notes, collections, and collection rows — newest first, each with the moment it is purged forever (purgesAt). Anything listed here can be brought back with restore_deleted. Filter by type, or omit `type` for all kinds.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `type` | `"task" \| "note" \| "collection" \| "collectionItem"` | no | Only this kind. Omit for all kinds. |
| `limit` | `integer` | no | Max entries per kind (default 25). (1 to 100) |

**Returns**

- `count` (`number`)
- `items` (`object[]`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "list_deleted",
    "arguments": {}
  }
}
```

### restore_deleted

**Restore deleted item** · `Adds data` · `Safe to retry`

Bring back one soft-deleted item from the trash (see list_deleted) — a task, note, collection, or collection row. Restoring a collection also brings back the rows deleted with it; a row whose list is still deleted can't come back alone (restore the collection instead). A restored task whose project was deleted meanwhile lands in the inbox (movedToInbox: true). Restores one item per call. If the item is already live the call succeeds with alreadyLive: true.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `type` | `"task" \| "note" \| "collection" \| "collectionItem"` | yes | The entry's type, as list_deleted reported it. |
| `id` | `string` | yes | The deleted item's UUID. |

**Returns**

- `restored` (`boolean`)
- `alreadyLive` (`boolean`)
- `type` (`string`)
- `id` (`string`)
- `title` (`string | null`)
- `restoredItems` (`number`)
- `movedToInbox` (`boolean`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "restore_deleted",
    "arguments": {
      "type": "task",
      "id": "<id>"
    }
  }
}
```

## Automations

Standing orders Roma runs on a schedule. Read them, read what their runs found, and start one when the user asks.

### list_automations

**List automations** · `Read-only`

List the user's automations — standing orders Roma runs on its own, on a schedule or on demand. Returns each one's id, name, what it does, status (active / paused / draft), when it runs, the next run, and how the last run ended. Use it when the user asks what runs on its own, when something runs next, or before reading or starting a run.

**Parameters**

This tool takes no parameters.

**Returns**

- `count` (`number`)
- `automations` (`object[]`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "list_automations",
    "arguments": {}
  }
}
```

### get_automation_runs

**Get automation runs** · `Read-only`

Read one automation's recent runs, newest first: when each ran, how it ended, what it wrote (one line per action), the message it left for the user, and any error. Use it for "what did my morning brief find", "why did it fail", or to read the result of a run started with run_automation once it has finished.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `automationId` | `string` | yes | The automation's id (from list_automations or get_context). |
| `limit` | `integer` | no | How many runs, newest first (default 5, max 20). (1 to 20) |

**Returns**

- `automation` (`object`)
- `runs` (`object[]`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "get_automation_runs",
    "arguments": {
      "automationId": "<automationId>"
    }
  }
}
```

### run_automation

**Run automation now** · `Updates or removes existing data` · `Reaches outside Roma`

Start one of the user's automations now — the same as Run now on its page in Roma. Use it only when the user asks to run a specific automation. The run happens inside Roma with the user's connected apps and can take a minute; its result lands in the user's Roma chat, not in this conversation. Read the outcome afterwards with get_automation_runs. Refused for a draft, while the same automation is already running, or once the daily run limit is reached.

**Parameters**

| Parameter | Type | Required | Description |
|---|---|---|---|
| `automationId` | `string` | yes | The automation's id (from list_automations or get_context). |

**Returns**

- `id` (`string`)
- `name` (`string`)
- `runId` (`string`)
- `status` (`string`)

**Example**

```json
{
  "method": "tools/call",
  "params": {
    "name": "run_automation",
    "arguments": {
      "automationId": "<automationId>"
    }
  }
}
```

