Rotor MCP

Connect Rotor via MCP to analyze your data!

1. What it is

Rotor is a CRM and field-service platform (leads, customers, jobs, visits, tasks, messaging,
quotes, invoices, payments, payroll, timesheets, and map-pin canvassing). The Rotor MCP server exposes a Rotor company's own records to Claude over Streamable HTTP, authenticated with OAuth 2.1 against the user's existing Rotor account.

Every tool runs as the connecting Rotor user, inside that user's company, with that user's
role, feature access, and record visibility. There is no admin backdoor and no cross-company
read.

2. Connection details

FieldValue
Server URLhttps://mcp.getrotor.com/mcp
TransportStreamable HTTP
Same URL for all usersYes
AuthenticationOAuth 2.1, authorization code + PKCE (S256), dynamic client registration
Issuerhttps://mcp.getrotor.com
Protected-resource metadatahttps://mcp.getrotor.com/.well-known/oauth-protected-resource/mcp
Authorization-server metadatahttps://mcp.getrotor.com/.well-known/oauth-authorization-server
PrerequisiteAn active Rotor account with membership in at least one company
Data directionReads and writes

Claude also POSTs Streamable HTTP to the issuer origin (/); the server accepts both / and /mcp with identical middleware (server.ts:90-94).

3. Authentication

Standard OAuth 2.1 discovery, registration, authorization, token. Implemented in
mcp.oauth.ts.

  • Dynamic client registration at POST /oauth/register. token_endpoint_auth_method is
    none (public client).
  • PKCE is mandatory. code_challenge_method must be S256; anything else is rejected
    with invalid_request (mcp.oauth.ts:282).
  • Consent is a Rotor-hosted screen. /oauth/authorize redirects to the Rotor web app,
    which authenticates the user, lets them pick which company to connect when they belong to
    more than one, and itemizes every requested scope in plain language before they approve.
  • Access tokens are HS256 JWTs, 1 hour TTL, signed with a dedicated MCP_JWT_SECRET
    (never the client-bundled ROTOR_API_KEY), scoped by aud to the MCP resource URL.
  • Refresh tokens are opaque, stored only as SHA-256 hashes, 30-day TTL, and rotated on
    every use
    - the previous token is marked rotated_at in the same conditional update, so a
    replayed refresh token fails.
  • Revocation at POST /oauth/revoke, and from Rotor itself: Company Settings, Connectors
    lists every active grant and revokes it (DELETE /api/mcp-management/connectors/:grantId).
    Revoking a grant kills its access tokens immediately - token verification re-checks the grant
    and the live company membership on every request.
  • Authorization codes are single-use with a 10-minute TTL.

Scopes

25 scopes are advertised and requested as one set. The consent screen is where the user sees
and controls them.

ScopeGrants
contacts:readList visible leads and customers
members:readRead company member names, emails, roles
leads:read / leads:writeRead / create and update leads
customers:read / customers:writeRead / create and update customers
jobs:readRead visible jobs
visits:read / visits:writeRead / reschedule visits
tasks:read / tasks:writeRead / create and update tasks
inbox:readRead visible inbox messages
campaigns:read / campaigns:writeRead campaigns / create them and queue recipients
templates:read / templates:writeRead / create message templates
service_plans:readRead visible service plans
pins:readRead map-pin and canvassing activity
invoices:readRead visible invoices
quotes:readRead visible quotes
payments:readRead company payments
payroll:readRead payroll records and rate settings - admins only
pipelines:readRead pipelines and stages
timesheets:readRead timesheets and clock status
offline_accessStay connected until the user revokes

payroll:read is dropped from the grant for non-admin members at consent time
(scopesForMembership, mcp.oauth.ts:396), so a member's token cannot carry it.

4. Tools

47 tools: 37 read-only, 10 write. Every tool declares a title and the applicable hint.
Read and write are separate tools throughout - there is no method-parameterized catch-all, and
no tool accepts a freeform endpoint, path, or request body.

destructiveHint follows the MCP schema meaning (destructive vs. additive), not "is a write":
a tool that only inserts a new row declares false; one that overwrites existing field values
declares true. mcp.server.ts enforces this at the type level - a write tool cannot omit the
hint.

Read-only tools (readOnlyHint: true)

ToolScopeWhat it does
get_current_context-Return the Rotor user, company, role, and scopes for this connection.
list_company_membersmembers:readActive company members with the user UUIDs other tools accept.
list_contactscontacts:readSearch leads and customers together by name, email, phone, address.
list_leadsleads:readList visible leads, filterable by search text and stage.
get_leadleads:readOne lead by ID.
list_customerscustomers:readList visible customers, filterable by search text and status.
get_customercustomers:readOne customer by ID.
list_jobsjobs:readList visible jobs, filterable by search text and status.
get_jobjobs:readOne job by ID.
list_visitsvisits:readScheduled visits in an ISO date range, with job, customer, service address.
get_visitvisits:readOne visit by ID.
get_clock_statustimesheets:readCurrent user's active clock status and clock-in categories.
list_timesheetstimesheets:readTimesheet entries in a range. Members see their own; admins see company-wide.
get_timesheettimesheets:readOne timesheet entry by ID.
list_visit_timersvisits:readVisit timer segments in a range, same member/admin split.
get_visit_timersvisits:readAll timer segments for one visit.
list_taskstasks:readList visible tasks, filterable by search, status, priority.
get_tasktasks:readOne task by ID.
list_messagesinbox:readInbox messages newest-first, filterable by contact, channel, direction, date.
list_campaignscampaigns:readCampaigns newest-first, when the campaigns feature is enabled.
list_message_templatestemplates:readCompany and Rotor example email/SMS templates, including bodies.
list_quotesquotes:readQuotes with statuses, totals, contacts, timestamps.
get_quotequotes:readOne quote with its current status and details.
list_paymentspayments:readPayment records and amounts, filterable by method, type, status, date.
get_paymentpayments:readOne payment record by ID.
list_payrollpayroll:readPaid payroll lines for a range; optional hourly source lines and rate tables. Admins only.
list_pipelinespipelines:readPipelines visible to the user.
get_pipelinepipelines:readOne pipeline and its ordered stages.
list_pipeline_stagespipelines:readOrdered stages across visible pipelines.
get_pipeline_stagepipelines:readOne stage by ID.
list_service_plansservice_plans:readVisible service plans, filterable by active state.
get_service_planservice_plans:readOne service plan by ID.
search_map_pinspins:readSearch map-pin / door-knocking activity: coordinates, notes, type, assignees, timestamps.
list_map_pin_typespins:readThe company's pin categories (Go-Back, Contacted, Sold, custom).
summarize_map_pin_activitypins:readAggregate pin activity by day, team member, and pin type.
list_invoicesinvoices:readVisible invoices, filterable by search text and status.
get_invoiceinvoices:readOne invoice by ID.

Write tools (readOnlyHint: false)

ToolScopedestructiveHintWhat it does
create_leadleads:writetrueCreates a lead. Emits record-created, plus tag-added and stage-change events; configured automations may then send email or SMS or change other records. No dedupe against existing contacts.
update_leadleads:writetrueUpdates a lead. Every update emits record-updated; stage and tag changes emit more.
create_customercustomers:writetrueCreates a customer. Emits record-created and, with tags, tag-added; automations may follow.
update_customercustomers:writetrueUpdates a customer. Status and tag changes emit automation events.
update_visitvisits:writetrueReschedules a visit. Rescheduling a job's first visit also moves the job start date; emits job- and visit-rescheduled events.
update_tasktasks:writetrueUpdates a task, its assignees, or its contact link. Runs no automations, sends no notifications.
create_tasktasks:writefalseInserts a task with assignee and contact links. Runs no automations, sends no notifications.
create_campaigncampaigns:writefalseCreates an inactive campaign from a template. Queues no recipients and sends nothing.
add_people_to_campaigncampaigns:writefalseQueues up to 100 visible leads/customers as pending recipients, skipping duplicates. Sends nothing by itself.
create_message_templatetemplates:writefalseStores a reusable email or SMS template. Sends nothing.

No tool sends a message, charges a card, moves money, deletes a record, or generates AI
media.
The three write tools that touch messaging (create_campaign,
add_people_to_campaign, create_message_template) all stop short of sending; a send is a deliberate action a human takes in the Rotor app. The tools whose side effects can reach a customer do so only through the company's own configured automations, and each says so in its description.

5. Access control

Four independent gates, all server-side:

  1. Company scoping. Every query filters on the token's company_id. The token binds one
    user to one company; connecting a second company is a second authorization.
  2. Role and record visibility. Non-admin members see only records assigned to them, matching
    what the Rotor web and mobile apps show them. list_payroll is admin-only.
  3. Feature access. requireFeatureAccess resolves the company feature gate and the
    member's own feature_overrides / default_feature_access, the same resolver the apps use -
    a per-member deny is honored, not just the company setting.
  4. Scope. Each tool declares its required scope in MCP_TOOL_SCOPES; a missing scope fails
    with insufficient_scope and names the scope in the error.

Membership is re-validated on every token verification, so removing someone from a company ends
their MCP access without waiting for token expiry.

6. Errors, limits, and response size

  • Errors are structured, never bare 500s: { code, message, retryable, hint?, example_args?, missing_scope?, allowed_values? } (mcp.errors.ts). Internal messages are not leaked to the
    model.
  • Inputs are validated with Zod. IDs must be well-formed UUIDs or positive integers; date ranges
    require ISO 8601 with a timezone offset.
  • Pagination: default 25, maximum 100 per page. Visit ranges are capped at 62 days. No tool
    returns an unbounded dump.
  • Rate limits: 60-second windows, per-user for tools (keyed on the authenticated Rotor user, not
    IP, so one Claude customer cannot throttle another) and per-IP for the OAuth endpoints.
  • Origin validation: browser requests must present an allowed Origin; the wildcard CORS header
    is stripped from every MCP response.

7. Privacy and data handling

  • First-party. The server calls Rotor's own API and database. Nothing is proxied from a third
    party.
  • What it accesses: only the connected Rotor company's records, scoped to the connecting
    user. Rotor CRM data includes customer names, contact details, service addresses, and billing
    records - all of it already the customer's own data in their own Rotor account.
  • What it does not do: it does not read Claude's memory, chat history, conversation
    summaries, or user files, and it collects no conversation data beyond the tool arguments needed
    to serve the call.
  • No health data. No sponsored content. No financial transfers.
  • Privacy policy: https://getrotor.com/privacy | Terms: https://getrotor.com/terms

8. Example prompts

  • "What visits are on the schedule tomorrow, and for which customers?"
  • "Which leads came in this week and what stage is each one at?"
  • "Summarize our door-knocking numbers for last week - who dropped the most pins, and what was the Go-Back rate?"
  • "Find the pins from Saturday that have phone numbers in the notes and create leads for them."
  • "Show me unpaid invoices over $2,000."
  • "Move Thursday's 9am visit for the Ramirez job to Friday at 8am."
  • "Create a follow-up task for me on the Chen quote, due Monday."

9. Submission checklist

RequirementStatus
Remote server, https://, Streamable HTTPMet - https://mcp.getrotor.com/mcp
OAuth 2.0/2.1 for authenticated serviceMet - DCR + authorization code + S256 PKCE
Every tool has a titleMet - 47/47
Every tool has readOnlyHint or destructiveHintMet - type-enforced
Reads and writes in separate toolsMet - no method-parameterized tool
No freeform-endpoint query toolMet - none exist
Tool names 64 chars or fewerMet - longest is summarize_map_pin_activity (26)
Descriptions match behavior, no prompt-injection patternsMet - descriptive only; no instructions about Claude's behavior
Actionable errors, no bare 500sMet - structured McpHttpError
Bounded responsesMet - page max 100, 62-day visit cap
First-party API, domain matches serviceMet - mcp.getrotor.com
No money transfer, no AI media generationMet
Privacy policy URLMet - https://getrotor.com/privacy
Public documentation URLOutstanding - publish this document at a public URL before the listing goes live
Test account, fully populatedOutstanding - provision and record credentials in the portal
Every tool exercised via Inspector or custom connectorOutstanding - run before submitting
Allowed link URIsn/a - the server does not use ui/open-link
Carousel screenshotsn/a - not an MCP App (no UI resources)

Did this page help you?