---
title: "Connect Claude via MCP (Beta)"
description: "Let Claude create rooms and schedules in your account using an Agent access token."
---

# Connect Claude via MCP (Beta)

Tamora runs a small [MCP](https://modelcontextprotocol.io) server so a chat assistant
can create rooms and build schedules on your behalf, using the same [Agent access](agent-access.md)
token a script or automation tool would use — without you needing to paste that token into
a chat message.

This is a beta feature. The two tools it exposes, and the token system underneath them, are
the same ones the REST API uses, but the MCP integration itself is new and may change.

## What this does, and does not, replace

MCP gives an assistant exactly two abilities, matching the REST API exactly:

- Create a room (`rooms.create`)
- Add a running order of timers to a room it just created, or any room the token's owner
  owns (`schedules.create`)

Nothing else. An assistant connected this way cannot read, edit, delete, or reorder anything,
cannot see your other rooms, and cannot touch account or billing settings.

## Which assistants this works with today

**Claude supports this now.** Claude's connector setup lets you configure a fixed
authorization header for a remote MCP server, which is exactly what an Agent access token is
for.

**ChatGPT does not support this yet.** ChatGPT's custom connector setup only offers "no
authentication" or a full OAuth sign-in flow — there is no field to paste a bearer token into.
Wiring up ChatGPT would mean building a sign-in flow for it, which is a larger piece of work
than this feature currently ships (see [Agent access](agent-access.md) for the REST API a
script or OAuth-capable integration can already use instead). If you specifically want ChatGPT
support, that is tracked as a follow-up, not an oversight.

## Prerequisites

Before connecting Claude, create an [Agent access token](agent-access.md) with the scopes
you want it to have — `rooms:create`, `schedules:create`, or both. Copy the raw token value;
you will paste it once, into Claude's connector configuration, not into a chat message.

## Connecting Claude

1. In Claude, open the connector/integration settings for adding a custom remote MCP server.
2. Set the server URL to `https://YOUR-TAMORA-DOMAIN/api/mcp` (your own Tamora
   domain, followed by `/api/mcp`).
3. Set the connector's authentication to send an `Authorization` header with the value
   `Bearer` followed by a space and the raw token value you copied above.
4. Save and enable the connector.

Claude's own connector UI has changed shape before and may again — if a step here doesn't
match what you see, look for wherever Claude lets you add a remote server with a custom
authorization header, rather than an OAuth-only connector.

Once connected, ask Claude to create a room or build a schedule in plain English — see the
worked example below.

## A worked example

One message can create a room and populate it in a single turn. Claude calls `rooms.create`
first, then `schedules.create` with the room id it gets back:

```text
Create a new Tamora room called "Product All-Hands" in the Europe/London
timezone. Then add this running order to it:
1. Welcome & intro — 5 min (speaker: Alex)
2. Q3 roadmap — 15 min (speaker: Priya)
3. Open Q&A — 10 min
4. Wrap-up — 5 min
```

Claude replies with the new room's id and a summary of the timers it created. From there, open
the room in the [Controller](controller.md) exactly as you would one you created by hand — the
MCP tools do not add a new place to view or run the show.

Claude can only act on a room it just created in that same conversation, or one whose id you
give it directly — it has no way to look up a room by name (see "What this does, and does not,
replace" above). A prompt like "add a timer to my Monday Standup room" only works if that room's
id is already earlier in the conversation.

## What the two tools do

Both tools require the matching scope on the token the connector is configured with, and both
act only on the token owner's own account — a tool call can never be pointed at a room it does
not own by supplying a different id, exactly like the REST API.

### rooms.create

| Input      | Type                               |
| ---------- | ---------------------------------- |
| `title`    | text                               |
| `timezone` | an IANA name, e.g. `Europe/London` |

Returns the new room's id, title, timezone, and creation time. Requires `rooms:create`.

### schedules.create

| Input                         | Type                                                    |
| ----------------------------- | ------------------------------------------------------- |
| `roomId`                      | the room id from rooms.create                           |
| `items`                       | a list of timers to create                              |
| each item's `title`           | text, optional — defaults to an empty title             |
| each item's `duration_sec`    | seconds, optional — defaults to 300, clamped 1 to 86400 |
| each item's `speaker`/`notes` | text, optional                                          |

Returns the timers that were created, including each one's id, title, and duration. The
same 500-item cap as [CSV import](csv-import.md) applies. Requires `schedules:create`.

Both tools accept an optional `idempotencyKey`: if Claude retries a call after a dropped
response, passing the same key returns the original result instead of creating a duplicate
room or schedule.

## Troubleshooting

| You see                 | What it means                                                                                                                                                            |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| "Authentication failed" | The token is missing, malformed, expired, revoked, or lacks the scope this tool needs. Check it in [Agent access](agent-access.md) settings.                             |
| "Not authorized"        | The room id does not exist, or the token's owner does not belong to it — these are intentionally indistinguishable, so a token can't be used to probe which rooms exist. |
| "Upgrade required"      | The account is on the free tier and already has a room — the same limit the dashboard enforces.                                                                          |
| "Rate limited"          | Too many calls in a short window. Wait and try again.                                                                                                                    |
| "Invalid request"       | A required field was missing or malformed — check the tables above.                                                                                                      |

If Claude cannot connect at all, double check the server URL ends in `/api/mcp` and that the
authorization header value starts with `Bearer` followed by a space and the token.

## Treat the token like a password

Everything in [Agent access](agent-access.md)'s security guidance applies here too: a raw
token grants whatever its scopes allow, to whoever holds it. Put it in the connector's
dedicated authentication field, never in a chat message — a chat message becomes part of
that provider's conversation history and logs, which is exactly the exposure this feature's
token hashing is designed to prevent on our side. If a token leaks, revoke it immediately.

## Related

- [Agent access](agent-access.md) — creating, scoping, revoking, and rotating the token this
  page uses
- [CSV import](csv-import.md) — the row cap and duration clamp `schedules.create` shares with
  CSV import
