The MCP server
The endpoint AI apps connect to, the tools it offers, the protocol versions it speaks and how it answers.
AI apps that speak the Model Context Protocol connect to TradeSender at one address:
https://app.tradesender.co.uk/mcp
This page is for someone building or debugging such an app. To connect Claude, ChatGPT or Codex as a user, start at Connect your AI assistant.
Transport
- Send each JSON-RPC message as its own
POST, withContent-Type: application/json. You get one JSON answer. A batch is refused. - There are no streams and no sessions.
GETandDELETEanswer 405 withAllow: POST. - A notification (a message with no
id) answers 202 with no body. - Nothing is remembered between requests, so any request can follow any other.
Protocol versions
The server speaks the stateless revision 2026-07-28, where each request names its version, and the earlier handshake revisions 2025-11-25, 2025-06-18, 2025-03-26 and 2024-11-05 for apps that open with initialize.
On 2026-07-28 each request carries _meta with the protocol version and the client's capabilities, and the MCP-Protocol-Version and Mcp-Method headers must agree with the body (Mcp-Name too on tools/call). server/discover returns the supported versions and the instructions.
Signing in
A request with no token answers 401 with a WWW-Authenticate header that points at the server's metadata:
WWW-Authenticate: Bearer resource_metadata="https://app.tradesender.co.uk/.well-known/oauth-protected-resource/mcp"
From there the app signs the person in with OAuth. See OAuth sign-in for assistants. The token works only at /mcp. An API key does not work here.
The tools
There is one tool for each operation offered, named by its id in the API reference, such as listVisits or createQuote. Its title is the operation's summary, and its description is the operation's description in the reference. A new operation becomes a new tool. tools/list may be kept for five minutes.
A tool takes the operation's path and query parameters by name, and its request body as body, written out in full. A tool that changes something also takes an optional idempotency_key: the tool makes its own when you send none, so send your own and repeat it to retry a change after a timeout. A field the reference marks as nullable may be null in the tool's schema.
Each tool says how far it reaches:
| Annotation | True for |
|---|---|
readOnlyHint | Every tool that only reads. |
destructiveHint | Every tool that changes something, except those that only add a record. Sending, recording a payment, finalising or voiding an invoice, editing, archiving and deleting are all destructive, and so is scheduling a visit, which makes a completed job active again. |
openWorldHint | The six that email a business's customers: sendQuote, sendInvoice, sendInvoiceReminder, sendVisitOnMyWay, createMonthEndInvoices and moveCalendarDay. |
A tool's answer is one text item holding JSON: the same body the API gives. When the operation fails, isError is true and the JSON carries the API's status and its errors, with the same codes as in Requests and conventions. When the call itself is wrong, such as an argument the tool does not take or a missing path parameter, the text is a sentence saying what to send instead.
What is offered
The operations for customers, contacts, properties, services, quotes, jobs, visits, repeating visits, time, time off, invoices and payments, with the day's route, moving a day's visits, the On my way email and the emails sent to a customer. The connection works as one member of one workspace with that member's role, so a technician's assistant is refused what a technician is refused.
Not offered: settings, the team, the plan, sign-in, API keys, connecting Stripe, refunds, collecting an invoice by Direct Debit (collectInvoice), photo uploads, PDFs and website enquiries. Nor is anything a business's customer does for themselves: paying an invoice online and setting up a Direct Debit.
Some fields the apps use are in no tool's description and in no answer:
- The cost fields:
unit_cost_centson a service and a line,cost_centson a quote and a job. A cost sent in a body is dropped without an error. direct_debiton a customer: how far their Direct Debit has got and the last four digits of their bank account. An invoice'scollect_on,collectableanddirect_debit_failedare sent, so an assistant can tell whether and when an invoice will be collected.
An assistant is offered 92 operations. Each one links to its entry in the API reference, which lists what it takes and what it answers with.
Customers
- List customersList customers
- Create a customerCreate a customer
- Import customers and their propertiesImport customers and their properties
- Get a customer, contacts, and propertiesGet a customer, contacts, and properties
- Update a customerUpdate a customer
- Archive a customerArchive a customer
- List a customer's contactsList a customer's contacts
- Create a customer contactCreate a customer contact
- Get a customer contactGet a customer contact
- Update a customer contactUpdate a customer contact
- Archive a customer contactArchive a customer contact
- List a customer's propertiesList a customer's properties
- Create a customer propertyCreate a customer property
- Get a customer propertyGet a customer property
- Update a customer propertyUpdate a customer property
- Archive a customer propertyArchive a customer property
- List the emails sent to a customerList the emails sent to a customer
- List the emails sent to every customerList the emails sent to every customer
Services
- List servicesList services
- Create a serviceCreate a service
- Get a serviceGet a service
- Update a serviceUpdate a service
- Deactivate a serviceDeactivate a service
Quotes
- List quotesList quotes
- Create a quoteCreate a quote
- Get a quoteGet a quote
- Update a draft quoteUpdate a draft quote
- Archive a draft quoteArchive a draft quote
- Email a quote to the customer, or mark it as sentEmail a quote to the customer, or mark it as sent
- Email yourself a preview of the quoteEmail yourself a preview of the quote
- Accept a sent quoteAccept a sent quote
- Decline a sent quoteDecline a sent quote
- Convert an accepted quote to a jobConvert an accepted quote to a job
Jobs and visits
- List visible jobsList visible jobs
- Create a jobCreate a job
- Get a job and its visitsGet a job and its visits
- Update a jobUpdate a job
- Archive a completed or cancelled jobArchive a completed or cancelled job
- Complete a jobComplete a job
- Cancel a job and outstanding visitsCancel a job and outstanding visits
- Reopen a completed or cancelled jobReopen a completed or cancelled job
- Schedule a job visitSchedule a job visit
- List visible visitsList visible visits
- Schedule a quote assessment without a work jobSchedule a quote assessment without a work job
- Get a visitGet a visit
- Reschedule or reassign a visitReschedule or reassign a visit
- Start a visit, optionally clocking inStart a visit, optionally clocking in
- Complete a visitComplete a visit
- Cancel a visitCancel a visit
- Email the customer that someone is on the wayEmail the customer that someone is on the way
- Create the draft quote for a completed assessmentCreate the draft quote for a completed assessment
- Remove a photo from a visitRemove a photo from a visit
- Repeat a visit on a jobRepeat a visit on a job
- List repeating visitsList repeating visits
- Get a repeating visitGet a repeating visit
- Change a repeating visit from a date onwardsChange a repeating visit from a date onwards
- Stop repeating a visitStop repeating a visit
- List job, visit and assessment time visible to this memberList job, visit and assessment time visible to this member
- Record completed time against a job, a work visit or a quote assessmentRecord completed time against a job, a work visit or a quote assessment
- Clock in on an active job or an unfinished visitClock in on an active job or an unfinished visit
- Get a job time entryGet a job time entry
- Correct recorded time or notesCorrect recorded time or notes
- Delete a completed time entryDelete a completed time entry
- Clock out of a running job timerClock out of a running job timer
Calendar and time off
- Get visits and absences for a time rangeGet visits and absences for a time range
- Move a day's visits to another dayMove a day's visits to another day
- Get a day's visits in an order to drive themGet a day's visits in an order to drive them
- List visible absencesList visible absences
- Create an absenceCreate an absence
- Get an absenceGet an absence
- Update an absenceUpdate an absence
- Delete an absenceDelete an absence
Invoices and payments
- Record one payment across a customer's invoicesRecord one payment across a customer's invoices
- Generate an invoice from a jobGenerate an invoice from a job
- List invoicesList invoices
- Create an invoiceCreate an invoice
- Invoice every job billed at month endInvoice every job billed at month end
- Get an invoiceGet an invoice
- Update a draft invoiceUpdate a draft invoice
- Archive a draft or void invoiceArchive a draft or void invoice
- Issue a draft invoiceIssue a draft invoice
- Email an invoice to the customerEmail an invoice to the customer
- Email yourself a preview of the invoiceEmail yourself a preview of the invoice
- Email the customer a reminder about an unpaid invoice nowEmail the customer a reminder about an unpaid invoice now
- Write off what is left to pay on an invoiceWrite off what is left to pay on an invoice
- Undo an invoice's write-offUndo an invoice's write-off
- Void an invoice without paymentsVoid an invoice without payments
- Record an invoice paymentRecord an invoice payment
Workspace and team
- Get the current account and membershipGet the current account and membership
- Get account settingsGet account settings
- List team membershipsList team memberships
- Get a team membershipGet a team membership
Instructions the server gives
The server's instructions tell the assistant how the records fit together, how money, quantities, tax and times are written, to look for an existing record before making one, and to say what it is about to do and wait for a yes before sendQuote, sendInvoice, sendVisitOnMyWay, sendInvoiceReminder, issueInvoice, createInvoicePayment, createCustomerPayment and voidInvoice. They also name the workspace, the member, their role, the time zone and the currency.
Five operations have instructions of their own:
createMonthEndInvoicesissues an invoice for every job billed at month end and emails each customer in one go. The assistant is told to say how many jobs and up to which date, and wait for a yes.moveCalendarDaymoves every scheduled visit on a day to another day and, withnotify_customers, emails each of their customers. The assistant is told to say which day, where to, how many visits and whether the customers are emailed, and wait for a yes.importCustomerswrites many customers at once. The assistant is told to call it withdry_run: truefirst, say what it would do, and wait for a yes.acceptQuoteon a quote with a deposit (deposit_cents) issues an invoice for that deposit, due today. The assistant is told to say so with the amount, and wait for a yes.writeOffInvoicesettles what a customer still owes without their paying it. The assistant is told to say which invoice, whose it is, how much and the reason, and wait for a yes.
Each tool's description repeats what the assistant is told to say before calling it.
These are instructions to a model. The server does not hold a change back until a person confirms. The annotations above let a client ask the person itself.
Limits
A connection may send 300 requests a minute. Over that, the answer is 429 with Retry-After: 60.
Emails an assistant sends with sendQuote, sendInvoice and sendVisitOnMyWay count towards the workspace's 100 emails a day. Once those are used up, a send fails with the API's status 429 and the code rate_limited until a day has passed. The emails of createMonthEndInvoices are not counted towards the 100, and nor are those of moveCalendarDay, which have a limit of their own: see Rate limits.
Checked against the app on 31 October 2026. Still stuck? Ask usAsk us.