# Dora MCP server

Dora's MCP server lets your own AI work with your Dora account: read what needs you, create and update requests, comment, hand work over, and ask Dora herself. It's at `https://dora.work/mcp` (Streamable HTTP, JSON responses).

## Connect

Connect Claude, ChatGPT, or any MCP client to `https://dora.work/mcp`, sign in, and approve. It acts as you, with the same access you have in Dora. In Claude Code:

```bash
claude mcp add --transport http dora https://dora.work/mcp
```

Details: [MCP docs](https://dora.work/docs/mcp), [auth.md](https://dora.work/auth.md). Scripts can use the [REST API](https://dora.work/docs/api) with an API key ([OpenAPI spec](https://dora.work/openapi.json)).

Sign-in is OAuth 2.1 with PKCE. Clients register themselves, the person signs in with an email link and approves the app on a consent screen, and the token acts as that person with the same access they have in the app. People see and disconnect apps in Settings.

For agents that run without a person to sign in (scheduled jobs, CI), send an API key instead: `Authorization: Bearer rzp_...`. People make keys on Connect your AI in Dora's settings, limited to one client or to reading if they choose. Read-only keys only see read-only tools.

Start with `get_briefing`: it says where things stand, in Dora's words.

## Who sees which tools

Clients of a company only get the tools for their own workspaces. Tools marked staff only are for a company's team. Read-only access only sees read-only tools.

## Tools

### get_me (read-only)

Who you are, and what this connection can do.

No parameters.

### update_me

Change your display name, profile photo, or whether you get the weekly and monthly summary emails.

- `name` (string): Display name.
- `avatarFileId` (string): Image file ID from upload_file, under 5 MB. null removes the photo.
- `summaryEmails` (boolean): Summary emails: weekly (and Dora's monthly recap) for client teams, weekly across all clients for company staff.

### list_notifications (read-only)

Your 50 most recent notifications, newest first.

No parameters.

### mark_notifications_read

Mark notifications read. Leave out IDs to mark all read.

- `notificationIds` (array): Notification IDs.

### list_workspaces (read-only)

List the client workspaces you can access.

No parameters.

### get_config (read-only)

A company's setup: services, request types, library categories, and client profile fields, with the keys other tools take. Pass a workspace for its company, or a company ID from get_me.

- `workspaceId` (string): Workspace ID.
- `orgId` (string): Company ID from get_me.

### create_company

Create a company portal from its website: Dora reads the site and drafts the setup (request types, library, client profile) and logo. You become its owner. If the site can't be read, it asks for an answer: call again with what clients usually ask for. If you already have a company for that site, returns it with existing: true instead of making another.

- `website` (string, required): The company's website, e.g. acme.com.
- `answer` (string): What clients usually ask the company for, when asked.

### propose_config_change (staff only)

Describe a change to your company's setup in plain words and get the full setup after it, plus a summary. Nothing is saved: apply it with update_config. Admins only.

- `orgId` (string, required): Company ID from get_me.
- `instruction` (string, required): The change, e.g. "Add an onboarding request type".

### add_clients (staff only)

Add clients from a list, one per line: websites, emails, or company names. Each company gets a workspace; people at the same company share it and get an invite. Admins only.

- `orgId` (string, required): Company ID from get_me.
- `text` (string, required): The list, one client per line.

### list_webhooks (staff only) (read-only)

A company's webhooks and how their last delivery went.

- `orgId` (string, required): Company ID.

### create_webhook (staff only)

Add a webhook: Dora POSTs every request event to the URL (request.created, request.status_changed, request.approved, request.changes_requested, comment.created, work.submitted, estimate.proposed, estimate.answered). Returns the signing secret once. Each POST has a Dora-Event header and Dora-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<body>">.

- `orgId` (string, required): Company ID.
- `url` (string, required): An https:// URL.

### delete_webhook (staff only)

Remove a webhook.

- `webhookId` (string, required): Webhook ID from list_webhooks.

### update_company (staff only)

Change your company's name, the name its emails come from, or its logo. Admins only.

- `orgId` (string, required): Company ID from get_me.
- `name` (string): Company name.
- `emailFromName` (string): Name emails come from. Empty uses the company name.
- `logoFileId` (string): Image file ID from upload_file. null removes the logo.

### update_config (staff only)

Replace sections of your company's setup (services, requestTypes, libraryName, libraryCategories, profileFields, assetChecklist, autoApproveDays: days until a request in review approves itself, 0 for never, default 7). Send whole sections; omitted ones stay. Read the current setup with get_config first. Admins only.

- `orgId` (string, required): Company ID from get_me.
- `config` (object, required): Sections to replace, same shape as get_config returns plus each item's key. requestTypes items need key, label, description, placeholder, include, icon, services. To pause a request type (clients can't open new ones), add paused: { until?: "2026-11-04" (the day it reopens; omit to pause until resumed), note?: "shown to clients" }; remove paused to resume.

### list_company_people (staff only) (read-only)

Your company's staff with their roles, plus pending invites.

- `orgId` (string, required): Company ID from get_me.

### invite_company_member (staff only)

Invite someone to your company's team. Roles: owner, admin, member. Admins only; only owners invite owners.

- `orgId` (string, required): Company ID from get_me.
- `email` (string, required): Their email.
- `role` (string, required): Role. One of: owner, admin, member.

### set_company_member_role (staff only)

Change a teammate's role. Admins only; only owners touch owners.

- `orgId` (string, required): Company ID from get_me.
- `userId` (string, required): User ID from list_company_people.
- `role` (string, required): Role. One of: owner, admin, member.

### remove_company_member (staff only)

Remove someone from your company's team. Admins only.

- `orgId` (string, required): Company ID from get_me.
- `userId` (string, required): User ID from list_company_people.

### revoke_company_invite (staff only)

Cancel a pending invite to your company's team.

- `inviteId` (string, required): Invite ID from list_company_people.

### create_workspace (staff only)

Create a client workspace. The website pre-fills the brand profile, and emails get invites.

- `orgId` (string): Company (from get_me) the client belongs to. Optional if you admin one.
- `name` (string, required): Client name.
- `website` (string): Client website, e.g. acme.com.
- `services` (array, required): Service keys from get_config: what the contract covers.
- `emails` (array): Client teammates to invite.

### update_workspace (staff only)

Rename a workspace, change its services, or archive it.

- `workspaceId` (string, required): Workspace ID.
- `name` (string): New name.
- `services` (array): Service keys from get_config: what the contract covers.
- `archived` (boolean): Archive or restore.
- `allowance` (object): Monthly allowance: { requestsPerMonth: number, overLimit: "warn" | "queue" }. Over it, a client's new request is marked over allowance; with queue, it waits for next month. null removes the allowance.
- `agreement` (object): What the client's agreement covers, shown to them as "What's included": notes (plain text), startsOn and endsOn (YYYY-MM-DD). Empty strings clear a field.

### list_people (read-only)

Everyone on a workspace: the client team and the company's staff. Use staff IDs for assignees.

- `workspaceId` (string, required): Workspace ID.

### list_members (read-only)

The client team on a workspace, plus pending invites.

- `workspaceId` (string, required): Workspace ID.

### invite_member

Invite someone to a workspace by email.

- `workspaceId` (string, required): Workspace ID.
- `email` (string, required): Their email.

### remove_member (staff only)

Remove someone from a workspace.

- `workspaceId` (string, required): Workspace ID.
- `userId` (string, required): User ID.

### revoke_invite (staff only)

Cancel a pending invite.

- `inviteId` (string, required): Invite ID from list_members.

### list_requests (read-only)

List requests in a workspace, newest activity first. Optionally filter by status.

- `workspaceId` (string, required): Workspace ID.
- `status` (string): Only this status. One of: backlog, todo, in_progress, needs_input, in_review, done, cancelled.

### suggest_assignee (staff only) (read-only)

Who should take a request, and why: weighs the client's account team, who's done this kind of work before, what each person says they do, who's away, and how much each has open. Use it to assign or to explain a choice.

- `requestId` (string, required): Request ID.

### team_load (staff only) (read-only)

Everyone on a company's team with how many open requests they have, what they do, and when they're back if away. Use it to spot who's overloaded and to rebalance.

- `orgId` (string, required): Company ID.

### set_auto_assign (staff only)

Turn Dora's auto-assign on or off for a company. When it's on and a client's request has no account lead (or the lead is away), she assigns it to whoever fits best and leaves a note saying why. Admins only.

- `orgId` (string, required): Company ID.
- `on` (boolean, required): On or off.

### get_my_work (staff only) (read-only)

Your work profile at each company you're on the team of: what you focus on (Dora uses it to suggest who should take a request) and the day you're away until, if any.

No parameters.

### update_my_work (staff only)

Change your work profile at a company: what you focus on (a short phrase, like 'web builds and SEO'), or the day you're away until (Dora won't assign you work until then; null means you're back).

- `orgId` (string, required): Company ID.
- `focus` (string): What you focus on. Empty clears it.
- `awayUntil` (string): Away until this day. null means you're back. Date like 2026-10-30. null clears it.

### attach_request_files

Attach files to a request's details (not a comment). Upload them with upload_file first.

- `requestId` (string, required): Request ID.
- `files` (array, required): Files from upload_file, as { fileId, name }.

### remove_request_file

Remove a file from a request's details. The file IDs are in get_request's attachments.

- `attachmentId` (string, required): File ID from get_request.

### get_briefing (read-only)

Where things stand for the person you're helping, in Dora's words. For the team: their next requests in the order to do them, what's past due, what's waiting on clients, and what's up for grabs. For a client: what needs them. Call it first when someone starts a conversation about their work.

No parameters.

### inbox (staff only) (read-only)

Requests across every client of your company, for staff.

- `view` (string, required): Which requests to show. One of: mine, unassigned, waiting, open.
- `clients` (string): mine: clients whose account team you're on, plus anything assigned to you. Default all. Doesn't apply to view mine. One of: mine, all.

### get_request (read-only)

One request with its full timeline of comments and changes, files, and Brand Library references.

- `requestId` (string, required): Request ID.

### get_request_context (read-only)

Everything needed to do a request, in one call: the request and its thread, files, the kind of request and what it needs, the client's rules and decisions (follow them), the client's agreement and brand profile, related Brand Library items, and similar requests already delivered with what was handed over. Start here before working on a request.

- `requestId` (string, required): Request ID.

### submit_work (staff only)

Hand over finished work for the client to review: a note of what changed, a preview link, and files. It's posted on the request as the work, the request moves to In review, and the client team is emailed to approve it or ask for changes.

- `requestId` (string, required): Request ID.
- `note` (string, required): What was done and anything the client should check, plain text.
- `previewUrl` (string): Where to see the work, an https:// link.
- `files` (array): Files from upload_file, as { fileId, name }.

### create_request

Open a new request in a workspace.

- `workspaceId` (string, required): Workspace ID.
- `title` (string, required): Short title.
- `body` (string): Details, plain text.
- `type` (string): Request type key from get_config.
- `neededBy` (string): When the client needs it. Date like 2026-10-30. null clears it.
- `files` (array): Files from upload_file, as { fileId, name }.

### update_request

Edit a request. Anyone who can see it can change title, body, type, and neededBy. Status, assignee, priority, due date, and waitingOnClient are staff only.

- `requestId` (string, required): Request ID.
- `title` (string): New title.
- `body` (string): New body, plain text.
- `type` (string): Request type key from get_config.
- `neededBy` (string): When the client needs it. Date like 2026-10-30. null clears it.
- `status` (string): Workflow status. One of: backlog, todo, in_progress, needs_input, in_review, done, cancelled.
- `assigneeId` (string): Staff user ID from list_people. null unassigns.
- `priority` (string): Priority. One of: none, low, medium, high, urgent.
- `dueDate` (string): The team's due date. Date like 2026-10-30. null clears it.
- `waitingOnClient` (boolean): false: the team isn't waiting on the client for this request (it stops showing as waiting until someone asks them something new). true undoes that.

### answer_request

For a request that's Needs input (Waiting on the client): say the client has answered, which hands it back to the team (to the status it had before, usually In progress). Use it when the client has given what was asked, or says there's nothing more they can add.

- `requestId` (string, required): Request ID.

### sign_off_request

Answer a request that's In review: approve it (it becomes Done) or ask for changes (back to In progress, with a comment saying what). Clients normally do this; staff can record an approval they got elsewhere.

- `requestId` (string, required): Request ID.
- `decision` (string, required): Approve, or ask for changes. One of: approve, changes.
- `comment` (string): What should change. Required when asking for changes.

### propose_change_order (staff only)

Mark a request as outside the client's agreement and send them an estimate to approve or decline. It doesn't count toward their monthly allowance. Pass estimate null to withdraw an unanswered estimate.

- `requestId` (string, required): Request ID.
- `estimate` (string, required): The price or effort, as the client should read it, like "$450" or "6 hours". null withdraws it.
- `note` (string): Why it's extra, or what the estimate covers.

### answer_change_order

Approve or decline the estimate on a request that's outside the agreement. Clients do this.

- `requestId` (string, required): Request ID.
- `approve` (boolean, required): True to approve, false to decline.

### delete_request

Delete a request and its comments and files. Staff can delete any request; clients only their own, before it's picked up.

- `requestId` (string, required): Request ID.

### list_recurring_requests (staff only) (read-only)

A client's recurring requests: what each opens, its schedule, the next day it opens, and whether it's paused.

- `workspaceId` (string, required): Workspace ID.

### create_recurring_request (staff only)

Set up a request that opens itself on a schedule, like a monthly report. Give fromRequestId to copy an existing request (it counts as the first one), or a title and body. The repeat is { unit: "week" | "month", every: 1-12, day } where day is 1 (Monday) to 7 (Sunday) for weeks, or 1-31 for months (31 means the last day). Team only.

- `workspaceId` (string, required): Workspace ID.
- `fromRequestId` (string): Copy this request's title, text, type, assignee, and priority.
- `title` (string): Title for each request it opens.
- `body` (string): Text for each request, in Markdown.
- `type` (string): Request type key from get_config.
- `assigneeId` (string): Who each request is assigned to (team).
- `priority` (string): Priority for each request. One of: none, low, medium, high, urgent.
- `repeat` (object, required): { unit: "week" | "month", every: number, day: number }, for example { unit: "month", every: 1, day: 1 } for the 1st of every month.
- `startOn` (string): The first day it can open; it opens on the first scheduled day from then. Date like 2026-10-30. null clears it.
- `dueAfterDays` (number): Each request is due this many days after it opens.

### update_recurring_request (staff only)

Change a recurring request: what it opens (fields, or fromRequestId to copy a request), its schedule, or pause it (active false) and resume it (active true). Team only.

- `recurringId` (string, required): Recurring request ID.
- `fromRequestId` (string): Future ones copy this request's title, text, type, assignee, and priority.
- `title` (string): New title.
- `body` (string): New text, in Markdown.
- `type` (string): Request type key. null clears it.
- `assigneeId` (string): Assignee (team). null clears it.
- `priority` (string): Priority. One of: none, low, medium, high, urgent.
- `repeat` (object): New schedule: { unit: "week" | "month", every, day }.
- `startOn` (string): Restart the schedule from this day. Date like 2026-10-30. null clears it.
- `dueAfterDays` (number): Days after opening that each is due. null clears it.
- `active` (boolean): false pauses, true resumes.

### run_recurring_request (staff only)

Open one of a recurring request now, outside its schedule (the schedule carries on). Team only.

- `recurringId` (string, required): Recurring request ID.

### delete_recurring_request (staff only)

Stop a recurring request for good. Requests it already opened stay. Team only.

- `recurringId` (string, required): Recurring request ID.

### add_comment

Comment on a request, or reply in a comment's thread with parentId (threads are one level: a reply to a reply joins the same thread, and is as private as it). Internal comments are only visible to staff.

- `requestId` (string, required): Request ID.
- `body` (string, required): Comment, plain text.
- `internal` (boolean): Staff only.
- `parentId` (string): Comment ID to reply to, from get_request.
- `files` (array): Files from upload_file, as { fileId, name }.

### edit_comment

Edit one of your comments.

- `commentId` (string, required): Comment ID from get_request.
- `body` (string, required): New text.

### delete_comment

Delete one of your comments.

- `commentId` (string, required): Comment ID from get_request.

### upload_file

Upload a file (up to 10 MB), then attach it with create_request, add_comment, or add_library_files.

- `name` (string, required): File name, e.g. logo.svg.
- `contentType` (string, required): MIME type, e.g. image/svg+xml.
- `data` (string, required): File contents, base64-encoded.

### search_library (read-only)

List or search a client's library: files, links, notes, docs, and work delivered on finished requests. Searching includes each item's text. Old versions are left out unless includeOld is true. Each item has a link to cite it with.

- `workspaceId` (string, required): Workspace ID.
- `query` (string): Search text.
- `category` (string): Only this category key, from get_config.
- `includeOld` (boolean): Include versions a newer one has replaced.

### search_company_library (staff only) (read-only)

List or search the company library: the team's own docs, templates, and files for every client. Team only.

- `orgId` (string, required): Company ID.
- `query` (string): Search text.
- `category` (string): Only this category key, from get_config.
- `includeOld` (boolean): Include versions a newer one has replaced.

### get_library_item (read-only)

One library item with its text (a doc's full text, a file's extracted text), its link, and its versions.

- `itemId` (string, required): Library item ID.

### add_to_library

Add a link or a note to a client's library. It's read and sorted automatically.

- `workspaceId` (string, required): Workspace ID.
- `url` (string): A link to add.
- `text` (string): Or a note to add.
- `title` (string): Title for a note.
- `teamOnly` (boolean): Only the company's team sees it. Team only.

### add_to_company_library (staff only)

Add a link or a note to the company library. Team only.

- `orgId` (string, required): Company ID.
- `url` (string): A link to add.
- `text` (string): Or a note to add.
- `title` (string): Title for a note.

### add_library_files

Add uploaded files to a client's library. With replaces (one file), it's a new version of that item and the old one is kept as an earlier version.

- `workspaceId` (string, required): Workspace ID.
- `files` (array, required): Files from upload_file, as { fileId, name }.
- `replaces` (string): Library item ID this file is a new version of.
- `teamOnly` (boolean): Only the company's team sees them. Team only.

### add_company_library_files (staff only)

Add uploaded files to the company library. Team only.

- `orgId` (string, required): Company ID.
- `files` (array, required): Files from upload_file, as { fileId, name }.

### create_library_doc

Write a doc in a client's library (workspaceId) or the company library (orgId): a brand voice, kickoff notes, how you work together. The body is Markdown (headings, lists, bold, links); don't repeat the title as a heading.

- `workspaceId` (string): Workspace ID, for a client's library.
- `orgId` (string): Or the company ID, for the company library.
- `title` (string, required): Doc title.
- `body` (string): The doc, in Markdown.
- `teamOnly` (boolean): In a client's library, only the company's team sees it. Team only.

### update_library_doc

Rename a library doc or replace its text (Markdown). Read it first with get_library_item and send the whole doc back. Don't repeat the title as a heading.

- `itemId` (string, required): Library item ID of the doc.
- `title` (string): New title.
- `body` (string): The whole doc, in Markdown.

### update_library_item

Rename, recategorize, or retag a library item, change who sees it, or mark it as the newer version of another item (replaces; null undoes it and turns down Dora's suggestion).

- `itemId` (string, required): Library item ID.
- `title` (string): New title.
- `category` (string): Category key from get_config.
- `tags` (array): Tags.
- `teamOnly` (boolean): Only the company's team sees it. Team only.
- `replaces` (string): Library item ID this is the newer version of. null undoes it.

### delete_library_item

Remove an item from a library.

- `itemId` (string, required): Library item ID.

### retry_library_item

Have Dora read a library item again: after it failed to process, or after the file or linked page changed. For a link, Dora fetches the page again. Replaces what Dora wrote about it, and hands its category back to Dora even if someone set it by hand.

- `itemId` (string, required): Library item ID.

### list_library_rules (read-only)

A client's rules (standing preferences, like "Never use orange") and decisions (choices made on past requests), or the company's own rules (orgId). Follow them in any work for the client. The team also gets Dora's suggestions waiting for review.

- `workspaceId` (string): Workspace ID, for a client's rules.
- `orgId` (string): Or the company ID, for the company's own rules.

### add_library_rule

Keep a rule or decision for a client (workspaceId) or the company (orgId). One short sentence. Link the request it came from if there is one.

- `workspaceId` (string): Workspace ID, for a client's rule.
- `orgId` (string): Or the company ID, for a company rule.
- `kind` (string): Rule (default) or decision. One of: rule, decision.
- `text` (string, required): The rule, in one short sentence.
- `teamOnly` (boolean): Only the company's team sees it. Team only.
- `requestId` (string): The request it came from.

### update_library_rule

Reword a rule, switch rule and decision, or change who sees it.

- `ruleId` (string, required): Rule ID.
- `text` (string): New wording.
- `kind` (string): Rule or decision. One of: rule, decision.
- `teamOnly` (boolean): Only the company's team sees it. Team only.

### resolve_library_rule (staff only)

Keep (optionally reworded) or skip one of Dora's suggested rules. Team only.

- `ruleId` (string, required): Rule ID.
- `accept` (boolean, required): Keep it.
- `text` (string): Reworded, if keeping it.

### delete_library_rule

Delete a rule or decision.

- `ruleId` (string, required): Rule ID.

### get_brand_profile (read-only)

A workspace's brand profile, its rules and decisions, what's still missing, and details found in uploads waiting for review.

- `workspaceId` (string, required): Workspace ID.

### get_delivery_record (read-only)

What a client got in a month: requests delivered and how they were approved, average turnaround, use of the monthly allowance, approved estimates, and Dora's recap once the month is over.

- `workspaceId` (string, required): Workspace ID.
- `month` (string): Month like 2026-10. Defaults to this month.

### update_brand_profile

Set brand profile fields. An empty value clears a field.

- `workspaceId` (string, required): Workspace ID.
- `fields` (array, required): Fields to set, as { field, value }.

### resolve_suggestion

Accept or skip a brand profile detail found in an upload (from get_brand_profile).

- `suggestionId` (string, required): Suggestion ID.
- `accept` (boolean, required): true to use it, false to skip it.

### ask_dora (read-only)

Ask Dora herself: planning someone's day, who should take a request, what a client is likely to need, how to word a nudge. She looks things up as the person you're helping and answers in her own words. She can't change anything from here; if a change is needed she says exactly what, for you to make with the other tools. Counts against the company's Dora allowance.

- `question` (string, required): What to ask her, with any context she'll need.

## Prompts

### work_on_request (staff only)

Do a client request: read its context, do the work, and hand it over for review. Takes `request`: the request's ID or its link in Dora.

## Discovery

- [REST API docs](https://dora.work/docs/api) and [OpenAPI spec](https://dora.work/openapi.json)
- [Server card](https://dora.work/.well-known/mcp/server-card.json)
- [Protected resource metadata](https://dora.work/.well-known/oauth-protected-resource/mcp)
- [Authorization server metadata](https://dora.work/.well-known/oauth-authorization-server)
- [auth.md](https://dora.work/auth.md)
