> ## Documentation Index
> Fetch the complete documentation index at: https://docs.omi.me/llms.txt
> Use this file to discover all available pages before exploring further.

# Tools Reference

> Complete reference for all Omi MCP tools

## Memory Tools

The hosted server returns only the tools allowed by the OAuth grant or MCP key. A local
`mcp-server-omi` stdio process currently exposes the eight memory and conversation tools
in the first two sections below; the additional tools are hosted-server tools.

<AccordionGroup>
  <Accordion title="get_memories" icon="brain">
    Retrieve a list of user memories with optional filtering.

    **Parameters:**

    | Name | Type | Required | Description |
    | - | - | - | - |
    | `categories` | array | No | Categories to filter by |
    | `limit` | number | No | Maximum number of memories (default: 20, max: 100) |
    | `offset`/`cursor` | number/string | No | Offset for pagination, or opaque `next_cursor` from a previous page (mutually exclusive) |
    | `sort` | string | No | `scoring_desc`, `created_desc`, `updated_desc`, or `manual_first` |
    | `reviewed` | boolean | No | Filter by reviewed state |
    | `manually_added` | boolean | No | Filter by manually-added state |
    | `updated_after` | string | No | Only return memories updated after this ISO 8601 timestamp |
    | `include_activity` | boolean | No | Include focus/screen/activity memories, which are excluded by default |
    | `include_sensitive` | boolean | No | Include memories above standard data protection, default `true` for compatibility |

    **Returns:** `{ "memories": [...], "returned_count": 25, "has_more": true, "offset": 0, "limit": 25, "sort": "created_desc" }`

    The response may also include scan diagnostics such as `scanned_count` and `scan_truncated`.

    **Example:**

    ```
    "Search my memories" → get_memories with no filters
    "What do you know about my hobbies?" → get_memories with categories: ["hobbies"]
    ```

    **Memory categories:** `interesting`, `core`, `hobbies`, `lifestyle`, `interests`, `habits`, `work`, `skills`, `learnings`, `other`
  </Accordion>

  <Accordion title="search_memories" icon="magnifying-glass">
    Semantic search across memories. Returns results ranked by relevance using vector similarity.

    **Parameters:**

    | Name | Type | Required | Description |
    | - | - | - | - |
    | `query` | string | Yes | Natural language search query |
    | `limit` | number | No | Maximum number of results (default: 10) |

    **Returns:** `{ "memories": [{ ..., "relevance_score": 0.92 }, ...] }`

    Each result includes a `relevance_score` (0.0 to 1.0) indicating how well it matches the query.

    **Example:**

    ```
    "What do I know about machine learning?" → search_memories with query: "machine learning"
    "Find memories about my morning routine" → search_memories with query: "morning routine"
    ```
  </Accordion>

  <Accordion title="create_memory" icon="plus">
    Create a new memory. Category is auto-detected if not provided.

    **Parameters:**

    | Name | Type | Required | Description |
    | - | - | - | - |
    | `content` | string | Yes | Content of the memory |
    | `category` | string | No | Category (auto-detected if omitted) |

    **Returns:** `{ "success": true, "memory": { ... } }`
  </Accordion>

  <Accordion title="create_memories" icon="layer-plus">
    Create up to **25** memories in one call — prefer this over repeated
    `create_memory` calls when saving several facts.

    **Parameters:**

    | Name | Type | Required | Description |
    | - | - | - | - |
    | `items` | array | Yes | 1–25 objects of `{ "content": string, "category"?: string }` |

    **Returns:** `{ "results": [...] }` — every item is rate-limited
    individually and returns its own status: `created`, `duplicate` (exact
    content+category already created earlier in the same batch), or `error`.
  </Accordion>

  <Accordion title="edit_memory" icon="pen">
    Edit an existing memory's content.

    **Parameters:**

    | Name | Type | Required | Description |
    | - | - | - | - |
    | `memory_id` | string | Yes | ID of the memory to edit |
    | `content` | string | Yes | New content for the memory |

    **Returns:** `{ "success": true }`
  </Accordion>

  <Accordion title="delete_memory" icon="trash">
    Delete a memory by ID.

    **Parameters:**

    | Name | Type | Required | Description |
    | - | - | - | - |
    | `memory_id` | string | Yes | ID of the memory to delete |

    **Returns:** `{ "success": true }`
  </Accordion>
</AccordionGroup>

***

## Conversation Tools

<AccordionGroup>
  <Accordion title="get_conversations" icon="comments">
    Retrieve a list of conversations with optional date and category filtering.

    **Parameters:**

    | Name | Type | Required | Description |
    | - | - | - | - |
    | `start_date` | string | No | Filter after this date (YYYY-MM-DD) |
    | `end_date` | string | No | Filter before this date (YYYY-MM-DD) |
    | `categories` | array | No | Categories to filter by |
    | `limit` | number | No | Maximum number of conversations (default: 20) |
    | `offset`/`cursor` | number/string | No | Offset for pagination, or opaque `next_cursor` from a previous page (mutually exclusive) |

    **Returns:** `{ "conversations": [...] }` — metadata only. Use `get_conversation_by_id` for full transcripts.

    **Example:**

    ```
    "What did I talk about last week?" → get_conversations with date range
    "Show my work conversations" → get_conversations with categories: ["work"]
    ```

    **Conversation categories:** `personal`, `education`, `health`, `finance`, `technology`, `business`, `work`, `social`, `travel`, `entertainment`, `sports`, `family`, and more.
  </Accordion>

  <Accordion title="search_conversations" icon="magnifying-glass">
    Semantic search across conversations. Returns results ranked by relevance using vector similarity.

    **Parameters:**

    | Name | Type | Required | Description |
    | - | - | - | - |
    | `query` | string | Yes | Natural language search query |
    | `start_date` | string | No | Filter after this date (YYYY-MM-DD) |
    | `end_date` | string | No | Filter before this date (YYYY-MM-DD) |
    | `limit` | number | No | Maximum number of results (default: 10) |

    **Returns:** `{ "conversations": [...] }` — ranked by relevance to the query.

    **Example:**

    ```
    "When did I discuss the product launch?" → search_conversations with query: "product launch"
    "Find conversations about hiring from January" → search_conversations with query: "hiring", start_date: "2026-01-01", end_date: "2026-01-31"
    ```
  </Accordion>

  <Accordion title="get_conversation_by_id" icon="file-lines">
    Retrieve a single conversation by ID, including the full transcript with speaker segments.

    **Parameters:**

    | Name | Type | Required | Description |
    | - | - | - | - |
    | `conversation_id` | string | Yes | The ID of the conversation |
    | `max_segments` | number | No | Max transcript segments (default 120, max 500) |
    | `max_chars` | number | No | Max transcript characters (default 24000, max 100000) |

    **Returns:** Full conversation object with transcript segments, timestamps, structured summary, and metadata.
  </Accordion>

  <Accordion title="get_conversations_by_ids" icon="files">
    Deep-read up to **20** conversations in one call — the preferred follow-up
    after `get_conversations` or `search_conversations` returns several
    relevant ids.

    **Parameters:**

    | Name | Type | Required | Description |
    | - | - | - | - |
    | `conversation_ids` | array | Yes | 1–20 conversation IDs (duplicates fetched once) |
    | `max_segments` | number | No | Max transcript segments per conversation (same bounds as `get_conversation_by_id`) |
    | `max_chars` | number | No | Max transcript characters per conversation (same bounds) |

    **Returns:** `{ "conversations": [...], "not_found": [...], "truncated": false }`
    — each item carries the same bounded card and transcript as
    `get_conversation_by_id` with its own `truncated` flag; ids that resolve to
    nothing are listed in `not_found`. When the response budget is hit, later
    items are omitted and top-level `truncated` is `true` — retry them with
    smaller `max_segments`/`max_chars`.
  </Accordion>
</AccordionGroup>

***

## Profile, Imported Data, and Activity Tools

| Tool | Parameters | Description |
| - | - | - |
| `get_user_profile` | None | Return Omi's cached high-level user summary, if generated |
| `get_x_posts` | `kind?` (`tweet` or `bookmark`), `limit?` (default 50) | List imported X posts and bookmarks, newest first |
| `search_x_posts` | `query`, `limit?` (default 10) | Semantic search over imported X posts and bookmarks |
| `get_goals` | `include_inactive?` (default false) | List goals, active by default |
| `get_chat_messages` | `limit?` (default 50), `offset?`/`cursor?` | List recent Omi chat messages, newest first |
| `get_people` | None | List recognized people with speaker samples |
| `rename_person` | `person_id`, `name` | Correct a display name without exposing speaker samples in the response |
| `dismiss_person` | `person_id` | Soft-dismiss a false-positive person; requires the opt-in `people.cleanup` scope |
| `get_screen_activity` | `start_date?`, `end_date?`, `app?`, `group_by?` (`none`\|`app`\|`hour`\|`day`, default `none`), `summary?`, `limit?`, `cursor?` | List synced screen activity rows, aggregate them into buckets, or return the legacy per-app summary |
| `get_daily_summaries` | `start_date?`, `end_date?`, `limit?` (default 30), `offset?` | List Omi's daily summaries, newest first |

Dates use `YYYY-MM-DD`. `get_screen_activity` defaults to 200 raw rows per page
(max 1000); `limit` is ignored when `summary` is true. `group_by` buckets rows
by app, hour, or day with counts, estimated observation seconds (bounded
capture gaps — never actual usage duration), and top window titles.

Screen summaries count **synced observations**, not elapsed app usage. OCR gating,
frame deduplication, privacy exclusions, and sync compaction mean a row cannot be
converted to a fixed number of seconds or treated as proof of the user's intent.
The same summary contract serves hosted MCP, REST MCP, and
`GET /v1/screen-activity/summary`:

* `total_screenshots` and per-app `count` count only the summarized rows.
* `coverage.source` is `synced_screen_activity`; `coverage.row_limit` is 5000.
* `coverage.truncated` is true only when a lookahead row proves more matching
  rows exist. Only the earliest 5000 rows contribute to the summary. Narrow the
  date range to inspect later observations.
* `coverage.first_observed_at` and `last_observed_at` bound the summarized rows,
  in UTC (`YYYY-MM-DD HH:MM:SS.mmm`), and are null for an empty result. They do
  not establish continuous activity or the device's latest capture time.
* `coverage.capture_completeness` is `unknown`, even when `truncated` is false:
  the cloud query cannot attest to device capture status, excluded activity,
  retention, or pending sync. An empty result does not prove inactivity.

Window titles are samples, not a ranking by dwell time. Summaries remain derived
views of screen evidence; they do not create or promote semantic memories.

`rename_person` requires `people.rename`, which is part of the compatible default MCP key grant.
`dismiss_person` requires the explicitly requested `people.cleanup` scope. Dismissal is soft: it
hides the person from default app and MCP People reads while preserving the record for data export.
Existing and newly created default keys do not receive `people.cleanup` automatically.

***

## Pagination and cursors

List tools that can return more results emit an opaque `next_cursor` in the
response. Pass it back as the `cursor` argument — together with the **same**
filters — to fetch the next page (`cursor` and a non-zero `offset` are mutually
exclusive). The field is absent when no further page exists.

The same key authenticates the REST `/v1/mcp/*` list endpoints; they carry the
cursor in the **`X-Next-Cursor`** response header instead of the body.

## Incremental sync (`updated_since`)

`GET /v1/mcp/action-items` accepts `updated_since`, a strict ISO-8601 timestamp
with an explicit timezone offset. It switches the feed to an incremental
`(updated_at ASC, id ASC)` keyset — combine it with the `X-Next-Cursor` cursor
to page through updates. On each sync pass, re-read starting from
`watermark − 60 seconds` and deduplicate by `id`: `updated_at` is a timestamp,
not a transaction sequence, and the overlap covers delayed-commit visibility.
Note that action-item deletes are **hard deletes** — a deleted item leaves no
row and is not emitted by the feed.

`GET /v1/mcp/conversations` and `GET /v1/mcp/memories` do **not** support
`updated_since`: a valid timestamp returns HTTP `400` with detail
`incremental_sync_unsupported` (permanent capability gap — no `Retry-After`,
do not retry). For conversations, page instead with the
`(created_at DESC, id)` keyset cursor.

***

## Action Item Tools

| Tool | Required parameters | Optional parameters | Description |
| - | - | - | - |
| `get_action_items` | None | `completed`, `due_start_date`, `due_end_date`, `limit` (default 100), `offset`/`cursor` | List tasks and to-dos |
| `search_action_items` | `query` | `limit` (default 10) | Semantic search over tasks |
| `create_action_item` | `description` | `due_at`, `completed` (default false) | Create a task; identical retries do not duplicate it |
| `complete_action_item` | `action_item_id` | `completed` (default true) | Complete or reopen a task |
| `update_action_item` | `action_item_id` | `description`, `due_at` | Update only the supplied fields |
| `delete_action_item` | `action_item_id` | None | Delete a task |

Due dates accept `YYYY-MM-DD` or an ISO 8601 date-time where noted by the client schema.

***

## Error Handling

A `tools/call` result always carries `structuredContent` (a JSON value) plus a
matching text block for compatibility. **Tool execution failures** come back as
a tool result — visible to the model — with `isError: true` and
`structuredContent.error` of `{ "code": string, "message": string }`; `code` is
one of:

| `structuredContent.error.code` | Meaning |
| - | - |
| `invalid_arguments` | Bad parameter (bad date format, unknown category, malformed ID) |
| `not_found` | Resource not found (memory or conversation doesn't exist) |
| `paid_plan_required` | Locked content (paid plan required) |
| `authorization_denied` | The OAuth grant is missing the tool's required scope, or policy denied the operation |
| `rate_limited` | Per-user rate limit hit — retry after the current window |
| `unavailable` | Temporarily unavailable (e.g. a search index still building) |
| `internal` | Unexpected server-side failure |

**Protocol failures** stay JSON-RPC errors: unknown method/tool (`-32601`),
malformed params (`-32602`), unsupported protocol version (`-32022`), and
header/body mismatches (`-32020`) never reach the tool result.

**Example tool failure** — the text block mirrors the serialized
`structuredContent`, so both forms carry the same error:

```json theme={null}
{
  "isError": true,
  "content": [{"type": "text", "text": "{\"error\":{\"code\":\"not_found\",\"message\":\"Memory not found\"}}"}],
  "structuredContent": {"error": {"code": "not_found", "message": "Memory not found"}}
}
```

***

## Locked Content

Memories and conversations behind the paid plan are handled gracefully:

* **Memories:** Content is truncated to 70 characters with `...`
* **Conversations:** Action items and events are hidden from the structured data
* **Direct access:** Returns a tool result with `isError: true` and
  `structuredContent.error.code` of `paid_plan_required`, with a clear message


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.