Developers
Usetally MCP server
Usetally makes branded quotes, invoices and receipts for small businesses. Its remote MCP server lets AI assistants (ChatGPT, Claude, Grok and any MCP client) work in a customer's Usetally: create and send quotes and invoices, record payments, and answer questions about money owed. Every customer connects their own account.
Connection
- Server URL
- https://usetally.cc/mcp
- Transport
- Streamable HTTP (stateless, JSON responses). POST only; no SSE stream or session ID.
- Protocol
- Model Context Protocol, revisions 2025-06-18 and 2025-11-25
- Authentication
- OAuth 2.1, authorization code with PKCE (S256). Each customer signs in with their own Usetally account.
- Client registration
- Dynamic Client Registration (RFC 7591) or Client ID Metadata Documents (CIMD). Public clients, token_endpoint_auth_method "none".
- Scopes
- usetally.read (view only) · usetally.write (create, send, record payments). offline_access for refresh tokens.
- Tokens
- Access tokens last 1 hour. Refresh tokens last 90 days, are single use and rotate; reusing one ends the connection.
How sign-in works
- The client calls
POST /mcpwithout a token and gets401withWWW-Authenticate: Bearer resource_metadata=…. - It reads the metadata documents below, then registers (DCR) or presents its CIMD URL as the client ID.
- The customer signs in to Usetally, picks one of their businesses and chooses Full access or View only.
- The client swaps the code (with its PKCE verifier) for tokens and calls
/mcpwithAuthorization: Bearer ….
Redirect URIs must be https, or http on localhost / 127.0.0.1 (matched on any port). Customers can see and disconnect every connection in Usetally under Settings → AI & MCP.
- Protected resource metadata (RFC 9728)
- https://usetally.cc/.well-known/oauth-protected-resource/mcp
- Authorization server metadata (RFC 8414)
- https://usetally.cc/.well-known/oauth-authorization-server
- Authorize
- https://usetally.cc/oauth/authorize
- Token
- https://usetally.cc/oauth/token
- Register (DCR)
- https://usetally.cc/oauth/register
- Revoke (RFC 7009)
- https://usetally.cc/oauth/revoke
Tools
12 tools. View-only connections get only the read tools. Connecting needs a Usetally trial or paid plan; a business on the Free plan gets one tool that explains how to upgrade, and no access to its data. Every change runs as the signed-in person, so their team role, approval rules and plan limits apply exactly as in the app. Amounts are normal amounts in the document's currency (150000 means ₦150,000).
get_business_overview
Read onlyWhat's happening in your business: money owed, overdue invoices, payments this month, quotes waiting for an answer, drafts, and whether it can send. Start here when asked how the business is doing.
list_documents
Read onlyFind quotes and invoices, newest first. Filter by kind, status (unpaid and overdue included) or customer.
| Parameter | Type | Notes |
|---|---|---|
| kind | quote | invoice | all | |
| status | all | draft | awaiting_approval | sent | viewed | accepted | declined | unpaid | overdue | partially_paid | paid | void | |
| customer | string | Part of the customer's name or company. |
| limit | integer |
get_document
Read onlyEverything on one quote or invoice: items, totals, what's been paid, and its links (the customer's link and PDF once it's sent).
| Parameter | Type | Notes |
|---|---|---|
| document* | string | The document's number (e.g. INV-0042, QT-0007) or id. |
find_customers
Read onlySearch the business's saved customers by name, company, email or phone.
| Parameter | Type | Notes |
|---|---|---|
| query | string | |
| limit | integer |
find_products
Read onlySearch the business's price list (saved products and services) to use their names and prices on documents.
| Parameter | Type | Notes |
|---|---|---|
| query | string | |
| limit | integer |
create_invoice
Changes data · asks firstCreate a draft invoice in your business, branded with the business's template. Nothing is sent: show the person the total and ask before using send_document. Prices are normal amounts in the document's currency.
| Parameter | Type | Notes |
|---|---|---|
| customer* | object | Who the document is for. |
| customer.id | string | An existing customer's id from find_customers. Leave out to use a name. |
| customer.name | string | Customer's name. An existing customer with exactly this name or email is reused. |
| customer.company | string | |
| customer.email | string | Needed to email the document to them. |
| customer.phone | string | |
| customer.address | string | |
| items* | array | What the customer pays for, 1 to 200 lines. |
| items[].description* | string | What it is, e.g. "Logo design". |
| items[].quantity | number | |
| items[].unit_price | number or string | Price for one, in the document's currency as a normal amount (150000 means ₦150,000, not kobo). Leave out when using product_id. |
| items[].details | string | A second line under the description. |
| items[].vat | standard | zero | exempt | Only for VAT-registered businesses: zero-rated or exempt items. |
| items[].product_id | string | A product from find_products; its name and price are used unless given. |
| title | string | Optional heading, e.g. "Website redesign". |
| currency | string | 3-letter code (NGN, USD, GBP…). Leave out for the business's usual currency. |
| discount | number or string | A discount off the total, as an amount. |
| tax_rate | number | Tax percentage. Leave out to use the business's usual tax. |
| tax_label | string | The tax's name, e.g. VAT. |
| notes | string | A note shown to the customer. |
| terms | string | Payment terms. Leave out for the business's usual terms. |
| due_date | string | YYYY-MM-DD. Leave out for the business's usual payment terms. |
create_quote
Changes data · asks firstCreate a draft quote in your business, branded with the business's template. Nothing is sent: show the person the total and ask before using send_document. Prices are normal amounts in the document's currency.
| Parameter | Type | Notes |
|---|---|---|
| customer* | object | Who the document is for. |
| customer.id | string | An existing customer's id from find_customers. Leave out to use a name. |
| customer.name | string | Customer's name. An existing customer with exactly this name or email is reused. |
| customer.company | string | |
| customer.email | string | Needed to email the document to them. |
| customer.phone | string | |
| customer.address | string | |
| items* | array | What the customer pays for, 1 to 200 lines. |
| items[].description* | string | What it is, e.g. "Logo design". |
| items[].quantity | number | |
| items[].unit_price | number or string | Price for one, in the document's currency as a normal amount (150000 means ₦150,000, not kobo). Leave out when using product_id. |
| items[].details | string | A second line under the description. |
| items[].vat | standard | zero | exempt | Only for VAT-registered businesses: zero-rated or exempt items. |
| items[].product_id | string | A product from find_products; its name and price are used unless given. |
| title | string | Optional heading, e.g. "Website redesign". |
| currency | string | 3-letter code (NGN, USD, GBP…). Leave out for the business's usual currency. |
| discount | number or string | A discount off the total, as an amount. |
| tax_rate | number | Tax percentage. Leave out to use the business's usual tax. |
| tax_label | string | The tax's name, e.g. VAT. |
| notes | string | A note shown to the customer. |
| terms | string | Payment terms. Leave out for the business's usual terms. |
| valid_until | string | YYYY-MM-DD. Leave out for the business's usual validity. |
update_draft
Changes data · asks firstChange a draft quote or invoice. Only the fields given change; items, if given, replace all the items. Sent documents can't be edited here.
| Parameter | Type | Notes |
|---|---|---|
| document* | string | The document's number (e.g. INV-0042, QT-0007) or id. |
| customer | object | Who the document is for. |
| customer.id | string | An existing customer's id from find_customers. Leave out to use a name. |
| customer.name | string | Customer's name. An existing customer with exactly this name or email is reused. |
| customer.company | string | |
| customer.email | string | Needed to email the document to them. |
| customer.phone | string | |
| customer.address | string | |
| items | array | What the customer pays for, 1 to 200 lines. |
| items[].description* | string | What it is, e.g. "Logo design". |
| items[].quantity | number | |
| items[].unit_price | number or string | Price for one, in the document's currency as a normal amount (150000 means ₦150,000, not kobo). Leave out when using product_id. |
| items[].details | string | A second line under the description. |
| items[].vat | standard | zero | exempt | Only for VAT-registered businesses: zero-rated or exempt items. |
| items[].product_id | string | A product from find_products; its name and price are used unless given. |
| title | string | Optional heading, e.g. "Website redesign". |
| currency | string | 3-letter code (NGN, USD, GBP…). Leave out for the business's usual currency. |
| discount | number or string | A discount off the total, as an amount. |
| tax_rate | number | Tax percentage. Leave out to use the business's usual tax. |
| tax_label | string | The tax's name, e.g. VAT. |
| notes | string | A note shown to the customer. |
| terms | string | Payment terms. Leave out for the business's usual terms. |
| due_date | string | Invoices: YYYY-MM-DD. |
| valid_until | string | Quotes: YYYY-MM-DD. |
send_document
Changes data · asks firstEmails the customerSend a quote or invoice: it's marked sent, gets its customer link and PDF, and is emailed to the customer (or the email given). Already-sent documents are emailed again. Always confirm with the person first. If the person's role needs approval, it's sent for approval instead.
| Parameter | Type | Notes |
|---|---|---|
| document* | string | The document's number (e.g. INV-0042, QT-0007) or id. |
| string | Send to this address instead of the customer's saved email. | |
| message | string | A short personal message for the email. |
| email_customer | boolean | false: just mark it sent and return the link, e.g. to share on WhatsApp. |
convert_quote_to_invoice
Changes data · asks firstMake an invoice from a sent or accepted quote, with the same customer and items. Like in the app, the invoice is live straight away (its customer link and PDF work) but isn't emailed: use send_document to email it.
| Parameter | Type | Notes |
|---|---|---|
| document* | string | The quote's number or id. |
record_payment
Changes data · asks firstRecord money the customer paid outside Usetally (bank transfer, cash, POS). A receipt is issued automatically. Confirm the amount first.
| Parameter | Type | Notes |
|---|---|---|
| document* | string | The invoice's number or id. |
| amount* | number or string | The amount received, as a normal amount. |
| method | bank_transfer | cash | pos | other | |
| date | string | YYYY-MM-DD when it was paid. Leave out for today. |
| reference | string | Bank or teller reference. |
| note | string |
void_document
Destructive · asks firstCancel a sent quote or invoice so it can't be paid or accepted. It stays in the records, marked void. This can't be undone, so confirm first.
| Parameter | Type | Notes |
|---|---|---|
| document* | string | The document's number (e.g. INV-0042, QT-0007) or id. |
Try it
With the MCP Inspector: npx @modelcontextprotocol/inspector, choose Streamable HTTP, enter https://usetally.cc/mcp and connect. It walks the same OAuth sign-in a customer sees.
Questions: signed-in customers can write to us from Ideas & help in the app. See also the privacy policy and terms.