MCP server
This API serves a Model Context Protocol
server over HTTP at https://api.salesbud.com.br/mcp. Registered once as a custom
connector in claude.ai, it lets the model read meetings, calls, transcripts,
template answers, evaluations, email and WhatsApp conversations as you or with
a company credential — nothing to install.
It is a client of the public API, not a new surface. Same OAuth credential, same scopes, same rate limits, read operations only — nothing it can reach is anything the HTTP API would not return to the same credential.
Before you start
Section titled “Before you start”Your company needs the API_ACCESS feature enabled. What else you need depends on how the
assistant signs in:
- Signing in with Salesbud (OAuth) — each person connects their own account and reads what they can see. Nothing to create beforehand. This is the way for Claude and ChatGPT: see Connect Claude or ChatGPT.
- A fixed credential in headers — an administrator enters one API credential that the whole Claude organization shares. You need that credential and owner access to the Claude organization. See the Quickstart for the two kinds of credential.
Sign in with Salesbud
Section titled “Sign in with Salesbud”Point the assistant at https://api.salesbud.com.br/mcp and let it sign you in: it finds the authorization
server on its own, opens the Salesbud consent page, and connects as you. Step by step for each
assistant, approval and disconnection are in
Connect Claude or ChatGPT.
A connection made by someone who does not approve credentials waits for an administrator. Until then, every tool answers that the connection is awaiting administrator approval.
Use a fixed credential instead
Section titled “Use a fixed credential instead”An owner of the Claude organization can still add a custom connector pointing at
https://api.salesbud.com.br/mcp with no sign-in, sending the credential of the company whose data the
connector should read in two request headers:
| Header | Value |
|---|---|
X-Client-Id | sb_client_... |
X-Client-Secret | sb_secret_... |
Any other HTTP client may send the same credential as RFC 7617 Basic instead:
Authorization: Basic <base64 of client_id:client_secret>Two consequences of a credential entered once by an administrator:
- It is stored on Anthropic’s side and shared by the whole Claude organization. Everyone in it reads whatever the scopes allow, and the audit trail records the credential, not the person who asked.
- Revoking means rotating. Rotating the secret breaks every other integration using the same credential, so give the connector one of its own.
If the credential restricts access by IP, the allowlist has to include
Anthropic’s egress range, 160.79.104.0/21: the request reaches this API from
there, not from the user’s browser.
One tool per public read operation. The scope column is what the credential has
to carry — a missing scope comes back as a readable INSUFFICIENT_SCOPE message
the model can report, not an exception.
| Tool | Scope |
|---|---|
get_api_context | none beyond a valid credential |
list_meetings | meetings.read |
find_meetings | meetings.read |
get_meeting | meetings.read |
get_meeting_overall_evaluation | meetings.read |
get_meeting_answers | meetings.read |
get_meeting_transcript | meetings.read + transcriptions.read |
list_calls | calls.read |
find_calls | calls.read |
get_call | calls.read |
get_call_overall_evaluation | calls.read |
get_call_answers | calls.read |
get_call_transcript | calls.read + transcriptions.read |
list_emails | emails.read |
get_email | emails.read |
list_email_messages | emails.read + emails.content.read |
list_whatsapp_conversations | whatsapp.read |
get_whatsapp_conversation | whatsapp.read |
list_whatsapp_messages | whatsapp.read + whatsapp.content.read |
list_accounts | any of meetings.read, calls.read, emails.read, whatsapp.read |
list_teams | any of meetings.read, calls.read, emails.read, whatsapp.read |
list_tags | any of meetings.read, calls.read, emails.read, whatsapp.read |
list_accounts searches by name or domain with q; list_teams and
list_tags list the company’s teams and meeting and call tags.
list_meetings and list_calls accept account_id, team_id, tag_id,
score_min and score_max; list_emails and list_whatsapp_conversations
accept account_id and team_id. A typical flow is list_accounts with
q: "acme" to find the id, then list_meetings with that account_id. List
results name every account of each record, up to three. See
Filtering by account, team, tag and score.
Ask get_api_context first when you are unsure what a credential reaches: it answers with the
client, whether it is a company or a user credential and, for a user credential, its owner, the
company, the scopes and the per-minute limit.
/oauth/token is deliberately not a tool, and exposing it would burn the OAuth bucket and put
the token in the conversation. With a fixed credential the server issues and renews the token
itself. With a signed-in connection the assistant (Claude or ChatGPT) renews its own token with
the refresh token. The liveness and readiness probes are not tools either.
The tool catalog
Section titled “The tool catalog”GET /mcp/tools lists the server’s tools without a credential: the same name, title,
description, inputSchema and annotations that tools/list returns, plus the server version in
serverVersion. A client can build its tool list, or notice that a description changed, without
opening an MCP session. The answer may be cached for five minutes
(Cache-Control: public, max-age=300). It describes the tools only; calling one still needs a
credential.
curl https://api.salesbud.com.br/mcp/toolsFinding one account’s meetings and calls
Section titled “Finding one account’s meetings and calls”“Show me the meetings with Acme” is one call to find_meetings (or find_calls). It resolves the
account by name, domain, CNPJ or id in the account catalog and reads the records linked to it — the
last 12 months unless you pass meeting_after or meeting_before. When none is linked, it reads the
period record by record (90 days by default) and matches the account in the title, the linked
accounts and the participants’ e-mail domain. A name that matches several accounts comes back with
the candidates, so the model asks or picks by id instead of guessing.
One call reads at most 30 pages in 20 seconds. complete says whether the period was covered; when
a ceiling stops the search, next_cursor continues it, passed back with the same account and
filters. The answer carries the 50 most recent records, whole, in structuredContent, and only says
an account has no records about a period it read to the end.
Transcripts arrive in windows
Section titled “Transcripts arrive in windows”A one-hour transcript is thousands of utterances and does not belong in a
model’s context in one piece. The transcript tools return 200 utterances per
call and say how many are left; the model passes offset to continue. The API
returns the transcript whole — this windowing lives in the MCP server.
A record with no transcript is not an error: the tool reports
transcript unavailable (status: not_started), which is the contract described
in Meetings and calls.
Email bodies cost more than email metadata
Section titled “Email bodies cost more than email metadata”list_emails and get_email return conversation metadata — participants, connected
mailboxes, linked accounts, counts — and never a body. Reading the messages is a
separate tool, list_email_messages, and it asks for more: emails.content.read on
top of emails.read, plus its own rate-limit policy, tighter than the rest of the
API. Ask for a page at a time instead of walking a whole mailbox.
A body longer than 2,000 characters is trimmed in the text the model reads and kept
whole in structuredContent. Attachment content, HTML bodies and bcc are never
served by the API, so no tool reaches them.
WhatsApp text costs more than WhatsApp metadata
Section titled “WhatsApp text costs more than WhatsApp metadata”list_whatsapp_conversations and get_whatsapp_conversation return conversation
metadata — contact, seller, linked accounts, activity instants — and never a message.
Reading the messages is a separate tool, list_whatsapp_messages, and it asks for more:
whatsapp.content.read on top of whatsapp.read, plus its own rate-limit policy. Ask
for a page at a time instead of walking a whole history.
A text or an audio transcription longer than 2,000 characters is trimmed in the text the
model reads and kept whole in structuredContent. A message deleted for everyone stays as
a tombstone with no content; an edited message shows its current text. Media content,
provider identifiers, reactions and read state never reach the model — the API does not
serve them. See the WhatsApp reference.
What the server handles, and what it does not
Section titled “What the server handles, and what it does not”It handles token renewal with a safety margin and one retry on 401 with a fresh
token when it holds a fixed credential, Retry-After on 429, backoff on 503,
and immediate failure on the other 4xx. With a signed-in connection the assistant
renews its own token, and the server does not retry a 401: the tool answers with an
error asking you to reconnect. Errors reach the model carrying code and request_id, so a bad
date filter comes back as INVALID_DATETIME and the model corrects the format
itself.
When the client cancels a call, or gives up on the request, the server stops the reads that call
started. Every date parameter declares format: "date-time" in its input schema.
It does not paginate for you, except inside find_meetings and find_calls. The model follows has_more and next_cursor
like any other client, and the tool description says so, because
a short page is not the last page.
It also does not give you incremental sync, because v1 has none: window by
meeting_at or created_at and reprocess idempotently by id.
Shared quota
Section titled “Shared quota”Every credential of a company draws from the same 600 requests/minute company bucket. An agent walking a long history consumes quota your other integrations are using; see Rate limits.