# Connect an AI assistant

> Connect an AI assistant to the Reassign MCP server. The assistant can then read and change your day plan.

Source: https://reassign.dev/mcp/

Reassign has a Model Context Protocol (MCP) server. An AI assistant that supports MCP can read and change your day plan through this server.

> The MCP server accepts only OAuth sign-in. For scripts and your own apps, use
> the [REST API](https://reassign.dev/authentication.md) with a personal access token.

**MCP server URL**

```text
https://reassign.app/api/mcp
```

**Claude Code**

```bash
claude mcp add --transport http reassign https://reassign.app/api/mcp
```

## Before you start

You need these items:

- A Reassign account.
- Reassign Pro. The 7-day free trial includes it.
- An AI app that can add a remote MCP server.

The trial needs no card. Without Pro or the trial, the sign-in page shows an "Upgrade to Pro" button.

## Server address

Add this address as a remote MCP server in your AI app:

**MCP server address**

**URL**

```text
https://reassign.app/api/mcp
```

You can also copy the address in the Reassign web app. Go to **Settings** › **Integrations** › **MCP** and find the **Server address** field.

| Item                     | Value                                                                                                                             |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
| Transport                | Streamable HTTP, in stateless JSON mode                                                                                           |
| Request                  | One `POST` for each call. The result is one JSON body.                                                                            |
| Server-sent events (SSE) | Not supported. A `GET` request gets HTTP 405.                                                                                     |
| Session                  | The server keeps no session.                                                                                                      |
| Server name              | `reassign` (title "Reassign")                                                                                                     |
| Server version           | `2026.10.3.1`, plus `+` and a 12-character build commit on a deployed server. A new version does not clear a cached `tools/list`. |

## Connect

Do these steps in an app that supports MCP:

1. Add `https://reassign.app/api/mcp` as a remote MCP server.
2. The app opens the Reassign sign-in page. Sign in with an email code or a passkey.
3. Read the access that the app asks for. Then click **Allow**.
4. In Reassign, go to **Settings** › **Integrations** › **Authorized apps**. Make sure that the app shows in the list.

The assistant can then read your events and create, edit, and delete them.

If you connected a calendar, the changes of the assistant also sync to that calendar. This is the same as a change that you make on the dial. The assistant cannot change events from a read-only calendar. Refer to [Calendars](https://reassign.dev/reference/calendars.md).

### claude.ai and Claude Desktop

claude.ai and Claude Desktop use the same connectors for your account. A connector that you add on claude.ai is also in Claude Desktop.

1. Go to **Settings** › **Connectors**.
2. Click **Add custom connector**.
3. Paste the URL `https://reassign.app/api/mcp`.
4. Sign in to Reassign and click **Allow**.

### Claude Code

1. Run this command in your terminal:

   **Terminal**

   ```bash
   claude mcp add --transport http reassign https://reassign.app/api/mcp
   ```

2. Start Claude Code, run `/mcp`, and select **reassign**.

3. Sign in to Reassign in the browser, and click **Allow**.

### ChatGPT

1. Add `https://reassign.app/api/mcp` as a remote MCP server (a custom connector) in ChatGPT.
2. Sign in to Reassign and click **Allow**.

> The menu names in ChatGPT can change.

## Sign-in and permissions

The server uses OAuth 2.0 with PKCE (`S256`). Your AI app does the OAuth steps itself:

1. The app sends a request without a token. The server replies with HTTP 401 and a `WWW-Authenticate` header.
2. The header points to the metadata at `/.well-known/oauth-protected-resource/api/mcp`.
3. The app registers itself at `/api/oauth/register` (dynamic client registration).
4. The app opens the consent page. You sign in and click **Allow** or **Deny**.
5. The app gets an access token and sends it as `Authorization: Bearer <token>`.

The consent page shows the name of the app and the label "Unverified app" for an app that registered itself.

### Scopes

| Scope          | Consent title               | Access                                                                                 |
| -------------- | --------------------------- | -------------------------------------------------------------------------------------- |
| `events:read`  | View your schedule          | Read your events, plans, and reflections.                                              |
| `events:write` | Read and edit your schedule | Read, create, change and delete events and other plan data. It includes `events:read`. |

- For `events:write`, the consent text is "Read your schedule, and add, change, or remove events."
- If the app asks for no scope, the server gives both scopes.
- The consent page shows only the scopes that the app asks for. It has no control to select read-only access.
- A token refresh cannot add a scope.
- Each token refresh returns a new refresh token and spends the old one. The client must store the new refresh token each time. Refer to [Authentication](https://reassign.dev/authentication.md).

### Token lifetimes

| Item               | Lifetime   |
| ------------------ | ---------- |
| Authorization code | 60 seconds |
| Access token       | 1 hour     |
| Refresh token      | 30 days    |

### Personal access tokens

The MCP server accepts only OAuth access tokens. It does not accept personal access tokens (prefix `rsk_live_`). It also refuses an OAuth token for the REST API. Use personal access tokens with the REST API. Refer to [Authentication](https://reassign.dev/authentication.md).

### Revoke access

1. In Reassign, go to **Settings** › **Integrations** › **Authorized apps**.
2. Find the app in the list. The list shows the scope, the date of approval, and the date of last use.
3. Click **Revoke**.

The server stops all tokens of that app immediately. The app gets HTTP 401 with the detail `authorization revoked`.

## Tools

Reassign has 10 tools. A read tool needs `events:read` or `events:write`. A write tool needs `events:write`.

| Tool                | What it does                                                                                                                                                                                                              | Access   |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `get_schedule`      | Reads the events, free time and load for a date range (`from` to `to`). For one day, send the same date two times. The load is for each area, activity type, and project. It can also include weather and energy reports. | Read     |
| `find_event`        | Finds scheduled events and Inbox items by name.                                                                                                                                                                           | Read     |
| `show_day`          | Shows the day as the interactive 24-hour dial in the conversation.                                                                                                                                                        | Read     |
| `write_events`      | Creates, updates, shifts, or reflects events, or changes their checklists, one or many in one call. An `update` with a new `start` or `end` moves an event. Optional `dryRun: true` checks the ops without applying them. | Write    |
| `delete_events`     | Deletes events or clears whole days.                                                                                                                                                                                      | Write    |
| `manage_categories` | Creates, updates, or deletes areas, activity types, and projects. It can also `split` or `relink` a project. A delete of a category that items use needs `reassignTo`.                                                    | Write    |
| `manage_inbox`      | Writes to the Inbox, the tray of time blocks that have no time yet.                                                                                                                                                       | Write    |
| `undo_changes`      | Reverses a recent change with its undo token.                                                                                                                                                                             | Write    |
| `review_day`        | Confirms the review of a past day, or discards the review of any day.                                                                                                                                                     | Write    |
| `send_feedback`     | Sends 1 to 10 product feedback reports together to the Reassign team. It does not change your schedule.                                                                                                                   | No scope |

`send_feedback` needs no scope, so a read-only token can report a problem. It writes no user data. Refer to [Rate limits](https://reassign.dev/mcp.md#rate-limits) for its limits.

`tools/list` can also show an eleventh tool, `get_more_tools`:

- It is not a Reassign tool. The PostHog MCP SDK adds it when the product analytics of the server are on.
- An assistant calls it when no tool fits the request. It sends a `context` text that tells what it needs.
- The server records the first 500 characters of `context` as a missing-tool report. The tool changes no data.
- It has no REST twin.

The server does not capture the assistant's model. Tool schemas have no `llm_model` parameter, and results contain no `conversation_id` block. Until 2026-12-01, calls from an older cached schema may still send `llm_model` or `conversation_id`; the server strips these arguments before validation. Refresh `tools/list` to get the current schemas.

- All dates are ISO `YYYY-MM-DD`.
- A time is a local datetime `YYYY-MM-DDTHH:MM` in the time zone of the user, with no offset. A span is `start` and `end`. An event past midnight ends on the next date.
- A result with a span gives `timezone` one time, at the top level.
- Each tool refuses an argument that it does not know.
- `get_schedule` gives `integrations.sources[].account`, the account name at the calendar provider, to every caller.
- `get_schedule` gives `copyStyle` on each writable event calendar in `integrations.sources[].calendars[]`, and `busyCopyTitle` with `busy`. It can also give `integrations.aiRuleWarnings`. Refer to [Scheduling](https://reassign.dev/reference/scheduling.md#what-the-response-contains).
- The clock times in the prose of a tool, for example in `show_day` and in the `get_schedule` weather line, are 24-hour (`15:00`). The time format setting of the app does not change them.
- Shared fields use the same names as the REST API. Refer to [Core concepts](https://reassign.dev/concepts.md) and the REST reference, for example [Events](https://reassign.dev/reference/events.md) and [Scheduling](https://reassign.dev/reference/scheduling.md). The MCP read fields below describe the differences.

### Read a schedule

Call `get_schedule` with `from` and `to`. It returns `now`, `timezone`, the events, free slots, and load for each day. The dates are inclusive. For one day, send the same date in both fields.

- `minDuration` is an optional whole number from 1 to 1440, in minutes. It keeps only `freeSlots` at least that long. It returns each full gap and leaves the events unchanged.
- `includeLookups: false` leaves out `areas`, `activityTypes`, `projects`, and `integrations`. Use it when the assistant has them from an earlier call.
- `includeSeries: true` adds the recurring series in `series`.
- `includeBacklog: true` adds up to 50 Inbox items in `backlog`, top of tray first. `backlogPlannedOn` filters by planned day. `backlogProjectId` filters by project; send `"none"` for the items with no project. `backlogMinPriority` (0 to 4) keeps the items with that priority or a higher priority. Pass `nextBacklogOffset` as `backlogOffset` with the same filters for the next page; `null` means the last page. These arguments need `includeBacklog: true`.
- `projects` lists the projects: `{ id, name, areaId }`. An archived project also has `archived: true`. An archived project refuses new links. A `manage_categories` project `update` with `archived: false` restores it.
- Each day has `loadByProject`, the blocking minutes for each project. `projectId: null` is the time with no project. A read of more than one day also has a top-level `loadByProject` with the total. Refer to [Projects and priority](https://reassign.dev/concepts.md#projects-and-priority).
- To find an Inbox item by name, use [`find_event`](https://reassign.dev/mcp.md#find-events-and-inbox-items). `get_schedule` refuses `backlogQuery`. The REST `GET /schedule` endpoint still accepts it.

#### Weather and energy

For one day, `get_schedule` can include two text reports:

| Argument               | Result                                                                                                                                                                  |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `includeWeather: true` | Replaces the short `weather` headline with the full forecast for the day. Use it for outdoor plans or weather questions.                                                |
| `weatherLocation`      | A city or place name to forecast, for example `London`. Requires `includeWeather: true`. Omit it to use the saved city, or a city guessed from the account's time zone. |
| `includeEnergy: true`  | Adds `energy`: the forecast energy curve, with peak and dip windows from logged sleep. With no sleep logged, the report asks the user to log sleep.                     |

`includeWeather: true` and `includeEnergy: true` each require `from` to equal `to`. A range, or `weatherLocation` without `includeWeather: true`, fails input validation.

**get\_schedule arguments**

```json
{
  "from": "2026-10-03",
  "to": "2026-10-03",
  "includeWeather": true,
  "weatherLocation": "London",
  "includeEnergy": true
}
```

The `weather` and `energy` values are prose. Their text can change; do not parse it. With `weatherLocation`, the forecast date and times are local to that place, and the report names its IANA time zone. The top-level `timezone` still applies to events and free slots.

For REST, use [GET /weather and GET /energy](https://reassign.dev/reference/energy-and-weather.md). REST `GET /schedule` does not accept these three arguments.

### Find events and Inbox items

Call `find_event` with a `query`. It searches names, with a case- and accent-insensitive match. Events match fuzzily; an Inbox name must contain the query.

**find\_event arguments**

```json
{
  "query": "dentist"
}
```

The result is `{ events, inbox, inboxMatchedCount, nextInboxOffset, ambiguous, timezone }`.

- `events` is best match first. A series appears once, as the occurrence that matches best; a tie gives the one nearest to today. `ambiguous` is `true` when different events match equally well. Inbox matches do not affect it.
- Each event has a `score` from 0 to 1 for its name match: `1` is exact, `0.9` is a prefix, and `0.75` is a substring. Matches below `0.34` are omitted. Inbox items have no `score`.
- `inbox` has up to 50 matches, top of tray first, in the same shape as the `get_schedule` `backlog` items. Use their ids with `manage_inbox`.
- `areaId` and `activityTypeId` filter both lists. `from`, `to`, and `timeOfDay` filter events only. The date range includes an event that overlaps a requested day, also an overnight event that started earlier. `timeOfDay` uses the start time. See [Search events](https://reassign.dev/reference/events.md#search-events) for the event search window and filters.
- `inboxMatchedCount` is the total after filtering. To read the next page, send `nextInboxOffset` as `inboxOffset` with the same query and filters. A `null` offset means the last page.
- `inboxOffset` is a nonnegative integer and defaults to `0`. It pages Inbox items only; it does not page `events`.

REST `GET /events/search` returns `{ events, ambiguous, timezone }`. To search the Inbox through REST, use `GET /schedule` with `includeBacklog=true` and `backlogQuery`.

### Undo tokens

- Each write tool call that changes data and records an undo receipt returns one `undoToken` and its `expiresAt`, at the top level. This is true for `write_events`, `delete_events`, `manage_categories`, `manage_inbox`, and `review_day`.
- One token undoes all the changes of that call.
- A call that changed nothing returns no `undoToken`. A rejected batch also returns no `undoToken`. If the server cannot record the undo, the call also returns no `undoToken`, and the change stays. A `review_day` discard of a day with nothing recorded returns `noop: true`, empty `updated` and `deletedIds`, and no `undoToken`.
- Send the token to `undo_changes` before `expiresAt` (30 minutes). After that, the change stays.
- You can use each token one time only.
- One `undo_changes` call takes 1 to 20 tokens. `undo_changes` returns no new token.
- A `stale` row can list the rows that block the undo in `error.conflictingRows`. Refer to [Stale tokens](https://reassign.dev/reference/scheduling.md#stale-tokens).

### Batches

- `write_events`, `delete_events`, and `manage_inbox` take 1 to 50 operations in one call.
- A batch is atomic by default. If one operation fails, the server applies none of them.
- With `partial: true`, the server applies the valid operations and reports the others as errors.
- A `schedule` operation of `manage_inbox` obeys the rules of an event write. The span is 5 minutes to 168 hours. A blocking block that overlaps a blocking event fails with `conflict` and `nearestSlots`.
- `get_schedule` gives `userPreferences.conflictPolicy`. Its value is always `"propose"`: a write that overlaps a blocking event fails with `conflict` and gives `nearestSlots`.
- The result has one row for each operation: `{ index, status, result?, error?, reason?, warnings? }`. `status` is `"ok"`, `"error"`, or `"skipped"`.
- For `manage_categories`, the rows are in the arrays `areas` and `activityTypes`. The result has a `projects` array only when the call sent project ops.
- `write_events` and `delete_events` read the result rows after the full batch commits. A later operation can change the row of an earlier operation.
- A `manage_categories` delete of a category that events, Inbox items, trackers, or calendar defaults use needs `reassignTo`. Send another id to move the links, or `null` to clear them. Without it, the row fails with `validation`, and its `error` has `usage` and `reassignTargets`. For an area, `usage` also has `projects`, the count of its projects that are not archived. Ask the user, then send the delete again. Refer to [Delete a category that items use](https://reassign.dev/reference/categories.md#delete-a-category-that-items-use).
- A `manage_categories` delete of a shared default hides it, and your copy of it, for you only.
- A `manage_categories` create or rename to the name of an area or an activity type that exists fails with `conflict`. Use the id of that category.
- A project name must be unique among your live projects, in all areas. A duplicate fails with `conflict`. A delete of a project that a synced task list or Linear project feeds also fails with `conflict`. Link the list to a different project first, or archive the project.
- `write_events` and `manage_inbox` take `projectId` and `priority` (0 none to 4 urgent). When a write sets a new project and no `areaId`, the item gets the area of the project, if the project has an area. On `update`, `projectId: null` removes the project and keeps the area.

An `ok` row from `write_events` can have `warnings: ["classification_pending"]`. The change is saved, but queued AI classification can fill eligible fields after the reply. A `create` keeps its `kind`, also the default `blocking`. Refer to [Rows](https://reassign.dev/reference/events.md#rows). Read the event again if you need its latest classification. The warning appears only when classification is queued and the account and plan allow it.

### Check an event write

Add top-level `dryRun: true` to `write_events` to check its operations without applying them. It still requires `events:write`.

**write\_events dry run arguments**

```json
{
  "dryRun": true,
  "ops": [
    {
      "op": "create",
      "name": "Deep work",
      "start": "2026-10-03T14:00",
      "end": "2026-10-03T15:30"
    }
  ]
}
```

- A valid op returns `status: "skipped"` and `reason: "Dry run: this op is valid and was not applied."`.
- An invalid op returns its usual `error`, including `conflicts` and `nearestSlots` when available.
- A dry run with only valid ops succeeds. If any op fails, the call has `isError: true`, including with `partial: true`; valid ops still appear as skipped rows.
- The call writes nothing and returns no `undoToken`. It does not reserve a time.
- To apply the ops, send them again without `dryRun`. The server checks conflicts again against the schedule at that time.

This flag belongs to MCP `write_events`. REST `POST /events` and MCP `delete_events` do not accept it.

### Schedule new work

1. Call `get_schedule` for the date or range. Read the local `now`, `timezone`, and each day's `freeSlots`. Set `minDuration` to the requested number of minutes to omit shorter gaps.
2. Choose a span that fits the requested duration inside a free slot. For a new event, call `write_events` with an `op: "create"`, a `name`, and the concrete local `start` and `end`.
3. Keep the returned `undoToken` so `undo_changes` can reverse the booking.

**write\_events arguments**

```json
{
  "ops": [
    {
      "op": "create",
      "name": "Deep work",
      "start": "2026-10-03T14:00",
      "end": "2026-10-03T15:30"
    }
  ]
}
```

- The example assumes that the span fits in a free slot from the preceding read. Times use the account's `timezone`.
- On today, the returned free slots begin on a 5-minute mark more than 5 minutes after `now`.
- `write_events` checks for conflicts when it writes. If the time became busy, read the schedule again or choose a returned `nearestSlots` span, then send the revised create.
- For an existing Inbox item, use `manage_inbox` with `op: "schedule"`, its `id`, and the chosen `start` and `end`. This places the same item on the dial.
- `calendarId` and `mirrorCalendarIds` on a create choose the calendars. `mirrorStyles` sets each copy to `full`, `private`, or `busy`. A series with copies needs a home calendar. A series from a connected calendar is an exception. Refer to [Rules of the fields](https://reassign.dev/reference/events.md#rules-of-the-fields).
- A client-minted create `id` must be a UUID. Omit it to let the server make one.

REST clients can use [POST /schedule/plan](https://reassign.dev/reference/scheduling.md) to search a window and book its best slot in one call.

### Send product feedback

Collect the session's product feedback in one `send_feedback` call, with one item per issue in `reports`. Send 1 to 10 reports. Each needs a `kind` (`bug`, `idea`, or `other`) and a nonempty `message` of up to 4000 characters. Describe the problem, what you expected, and steps to reproduce. Leave out personal details and private schedule contents; the account is attached automatically.

**send\_feedback arguments**

```json
{
  "reports": [
    {
      "kind": "bug",
      "message": "The dial did not refresh after a successful event move. Reopening the day showed the new time."
    },
    {
      "kind": "idea",
      "message": "Let the dial highlight the free slots returned for a requested duration."
    }
  ]
}
```

The tool returns `{}` once accepted. One call sends one email to the team. The user receives at most one acknowledgment email per UTC day. REST `POST /feedback` keeps its single-report body `{ kind, message, submissionId? }` and returns HTTP 204.

### Retries

- A `write_events` create has no `requestId`. If a response is lost, read the schedule to check whether the event was created before you send it again. A create can send its own UUID `id`. After a lost response, read that id to check the create.
- `send_feedback` takes an optional top-level `submissionId` (UUID). Use the same value with identical reports for retries within 24 hours; use a new value for new content.

## Resources

The server has one resource and no prompts.

| URI                  | Name          | Content                                                             |
| -------------------- | ------------- | ------------------------------------------------------------------- |
| `ui://reassign/dial` | Reassign dial | The interactive 24-hour dial as an HTML page, for the conversation. |

The `show_day` tool uses this resource. An app that supports MCP Apps can show the dial in the conversation.

## Errors

### Request errors

The server sends these errors before a tool runs. The body is a JSON-RPC error.

| HTTP | JSON-RPC code | Message                                                         | Cause                                                                                                            |
| ---- | ------------- | --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| 401  | `-32001`      | `Unauthorized`                                                  | No token, a token that is not valid or expired, or a revoked app.                                                |
| 403  | `-32600`      | `Reassign needs an active subscription.`                        | The account has no Reassign Pro plan and no trial. `error.data` is `{ "code": "permission", "feature": "mcp" }`. |
| 403  | `-32600`      | `Origin not allowed.`                                           | A browser request from an origin that is not allowed.                                                            |
| 405  | `-32000`      | `Method not allowed — this MCP endpoint is POST-only (no SSE).` | A `GET` request.                                                                                                 |
| 500  | `-32603`      | `Internal server error.`                                        | A server error. Do not retry.                                                                                    |
| 503  | `-32000`      | `Temporary backend error — please retry.`                       | A temporary server error. Retry the request.                                                                     |

### Tool errors

A tool that refuses a call returns `isError: true` and one text block. The text is the JSON error envelope `{ "error": { code, message } }`, also for a tool that returns prose. The `error` can also have the optional detail fields of the REST API: `issues`, `feature`, `conflictingRows`, `conflictingRowsTruncated`, `usage`, and `reassignTargets`. Refer to [Error format](https://reassign.dev/errors.md#error-format). The code is also in `_meta["reassign/error"].code`. `_meta` has only the code.

For a rejected batch, the text is `{ error, timezone?, results }`. For `manage_categories`, it is `{ error, areas, activityTypes, projects? }`. The detail fields are only in the rows. `_meta` has a code only when all failed operations have the same code. `_meta` never has the codes `unauthorized` or `batch_rejected`.

Arguments that do not match the input schema of a tool do not get to the tool. The MCP SDK refuses them with `isError: true` and a prose text `Input validation error: …`, with no `_meta`. The REST API answers the same input with 422 `validation`.

| Code           | Meaning                                                                                                                                                                            |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `conflict`     | The requested time, name, or id is already taken, or a short busy state blocks the write. A retry can work only for the busy state.                                                |
| `not_found`    | The event, area, activity type, project, or day does not exist. An archived project also gives `not_found` for a new link.                                                         |
| `validation`   | The arguments are wrong: out of range, contradictory, or not complete. A bad operation row has `issues`.                                                                           |
| `permission`   | The target item does not allow the action, for example a `park` of a recurring event.                                                                                              |
| `scope`        | The token does not have the scope that the tool needs.                                                                                                                             |
| `stale`        | An `undo_changes` row cannot apply, because a row that the write changed has a newer change. The undo changes nothing. The row can have `conflictingRows`.                         |
| `read_only`    | You cannot change the event or the field from Reassign. For example, a task app owns the planned day of an Inbox item, or a project change cannot move the linked task in its app. |
| `rate_limited` | The caller sent too many requests. Wait, then try again.                                                                                                                           |
| `internal`     | The server failed. A retry can work.                                                                                                                                               |

- In an atomic batch of `write_events`, `delete_events`, `manage_inbox`, or `manage_categories`, the valid operations show `status: "skipped"` when another operation fails. Only the failed operations show `status: "error"`.
- A `write_events` dry run uses `skipped` for every valid operation even when all of them are valid. Refer to [Check an event write](https://reassign.dev/mcp.md#check-an-event-write).
- In `write_events`, `manage_inbox`, and `manage_categories`, a bad operation becomes an error row with the code `validation`. It does not fail the full call.
- A `write_events` or `manage_inbox` call whose writes changed data is never a refusal. If the server cannot read a changed item again, its row has the code `internal`. The call keeps any recorded `undoToken`.
- An `undo_changes` row fails with `conflict` while a calendar sync sends the same change. The undo changes nothing. Try it again after a short time.

### Rate limits

The server has no general rate limit for tool calls, and no limit for each token. The limit of 600 requests per minute for each OAuth grant or personal access token applies to the REST API only. Refer to [Errors](https://reassign.dev/errors.md#rate-limits).

Only `send_feedback` has limits:

| Limit     | Value           |
| --------- | --------------- |
| Each user | 10 in 1 minute  |
| Each user | 30 in 1 hour    |
| All users | 120 in 1 minute |

These limits count submissions, including retries and delivery failures, across the app, REST, and MCP. A grouped submission counts once. Above a limit, `send_feedback` returns the code `rate_limited`. Each server instance counts these limits separately.

The OAuth token endpoint has its own limit for each IP address. Refer to [Authentication](https://reassign.dev/authentication.md).

## Example prompts

Type requests such as these to your assistant:

- "What is on my schedule today?"
- "Find 90 minutes of free time tomorrow afternoon for deep work."
- "Move my gym session to 18:00."
- "Clear my plan for Friday." Then: "Undo that."
- "Mark my events from yesterday as kept or skipped, then confirm the day."
