Contacts
Search, open and enrich a person record: crm_search_contacts, crm_get_contact, crm_get_contact_activity, plus writes such as crm_tag_contact and crm_set_lead_score.
Connect Claude, Cursor, VS Code, Windsurf or any Model Context Protocol client to CRM Solid and your assistant stops describing your CRM and starts using it. 62 tools, 21 resources and 15 prompts over one authenticated endpoint, with every call limited by the scopes on the key you minted.
Free forever plan · No credit card required · Cancel anytime
The Model Context Protocol (MCP) is an open standard that lets an AI assistant call another piece of software through a described set of tools, resources and prompts, instead of guessing at it from pasted text.
A CRM MCP server is that standard placed in front of a CRM: it publishes contacts, conversations, deals, tasks, invoices and campaigns as operations an assistant can call, so the assistant can read your pipeline and change it inside the permissions you granted.
CRM Solid runs one at https://api.crmsolid.com/mcp. It speaks protocol revision 2025-06-18 over JSON-RPC 2.0, authenticates with a bearer API key you mint yourself, and covers twelve capability areas across twelve messaging channels.
The 62 tools are not a random pile of endpoints. They cluster into twelve areas that mirror how a revenue team actually works, and each area maps onto its own read and write scopes.
Search, open and enrich a person record: crm_search_contacts, crm_get_contact, crm_get_contact_activity, plus writes such as crm_tag_contact and crm_set_lead_score.
Read the thread before answering it. crm_list_recent_conversations surfaces who is waiting, crm_get_conversation pages through history, crm_send_telegram_message queues the reply.
crm_search_email_threads and crm_get_email_thread read the shared mailbox. crm_set_email_thread_status and crm_assign_email_thread route the work without sending mail.
crm_list_deals and crm_get_deal answer what is in the pipeline. crm_create_deal and crm_update_deal_stage move opportunities, with the Won transition deliberately reserved for the panel.
crm_list_tasks answers what is due and what is overdue. crm_create_task books the follow-up, crm_complete_task closes it and stamps the completion time.
crm_list_pipelines and crm_get_pipeline expose every board with its ordered stages and live per-stage counts, so an assistant learns the shape of your funnel before touching it.
crm_finance_summary, crm_list_transactions, crm_list_invoices and crm_revenue_sources_summary report on the ledger. All four are reporting only: nothing here moves money.
crm_list_sequences and crm_get_sequence_status report campaign progress. crm_pause_sequence and crm_resume_sequence are the two controls an assistant is trusted with.
crm_social_inbox_summary opens triage in one call. crm_list_social_conversations and crm_get_social_conversation load the thread, crm_send_social_message answers it.
crm_list_social_posts shows the calendar, crm_schedule_social_post books content across accounts, crm_update_social_post and crm_cancel_social_post fix what has not gone out yet.
crm_list_webhooks and crm_list_webhook_deliveries answer why an endpoint is not firing. crm_create_webhook registers one and returns its signing secret exactly once.
crm_list_agents reports what is automating replies, crm_run_agent test-drives one without delivering anything, crm_list_jobs and crm_get_job show whether a send actually left.
The Model Context Protocol is an open standard for connecting an AI assistant to external software through a self-describing interface. A server publishes what it can do, a client asks for that list, and the model chooses from it. Nothing about the pairing is hard-coded on either side, which is the entire point: the assistant learns your CRM at runtime rather than shipping with a built-in idea of what a CRM is.
Before a standard existed, every combination of assistant and business tool needed its own bespoke integration. Ten assistants and ten tools meant a hundred adapters, each maintained by somebody who cared about only one side of it. MCP inverts the arithmetic. The CRM describes itself once, and every compliant client can drive it. The same argument won for the Language Server Protocol in code editors: one server, many editors, nobody writing the same completion engine ten times.
The protocol has three primitives, and the difference between them is about who is in control:
crm_search_contacts and crm_create_task are tools.crm://social/inbox and crm://deals/pipeline.daily-briefing, pipeline-review and social-inbox-triage.That three-way split matters more in a CRM than almost anywhere else, because a CRM is a system of record. Tools are the model acting. Resources are the client deciding what background to load. Prompts are a human saying: run this specific play, now, on this specific record. Any product that collapses all three into one undifferentiated pile of functions has made it harder for you to reason about what your assistant is allowed to do on its own.
MCP is transport agnostic. A server that runs as a local process communicates over standard input and output. A server that lives on the internet, like a hosted CRM, uses HTTP. CRM Solid is the second kind, so everything below describes the remote path.
A CRM is the system where an assistant that cannot act is least useful, because almost every worthwhile CRM question ends in a change. Who should I reply to first ends in a reply. Which deals are stalling ends in a task. What did we agree with this customer ends in a note that somebody has to write down. An assistant that can only talk about your pipeline leaves the last and most tedious step to you, every single time.
The gap is easiest to see in the copy-paste loop most teams are living in today. You export a view to CSV or screenshot a board, paste it into a chat window, get a genuinely good analysis, then retype the outcome back into the CRM by hand. Three problems compound. The data was stale the moment it left the system. The analysis is detached from the records it describes, so nothing links back. And the write-back is manual, which means on a busy day it does not happen at all and your CRM quietly rots.
An MCP connection removes all three. The read is live, because the tool call hits the database at the moment of the question. The result carries record identifiers, so the follow-up action targets the right row. And the write is one more tool call, which is the difference between an insight and a change.
Copy-paste and screenshots. The most common CRM and AI workflow in 2026 is still a human acting as a data bus between two browser tabs. MCP deletes that role. You stop being the integration.
Tab switching. A rep answering a DM checks the contact record, the last email thread, the open deal and the overdue task, in four places. With MCP the assistant assembles that picture in one turn, because crm_get_contact already returns the last ten messages and crm_get_contact_activity returns the timeline behind them.
Brittle no-code automations. A zap encodes a decision at build time: when this trigger fires, always do that. It works beautifully for deterministic plumbing and badly for judgement. An assistant with MCP access decides at call time, with the actual thread in front of it. The two are complements rather than rivals, and we work through exactly where each one wins on the MCP versus REST API versus automation tools comparison.
There is one more reason a CRM is the right place to attach an assistant. It is where multi-channel context already lives. CRM Solid unifies Telegram, WhatsApp, Instagram, Facebook, X, LinkedIn, TikTok, YouTube, Threads, Pinterest, Reddit and Bluesky DMs alongside email and live chat in one unified inbox. An assistant plugged into that inbox can answer a question like which customer has been waiting longest across every channel, which no single-channel tool can answer at all.
The server is a remote Model Context Protocol endpoint at https://api.crmsolid.com/mcp, speaking JSON-RPC 2.0 over the Streamable HTTP transport at protocol revision 2025-06-18, and authenticated with a bearer API key. Every element of that sentence has a practical consequence, so here is each one in plain language followed by the exact wire detail.
In plain language: every message is a small JSON envelope with a method name, some parameters and an id, and every response comes back matched to that id. It is a boring, forty-year-old idea and that is a feature. There is no bespoke framing to learn and no ambiguity about which reply belongs to which request.
On the wire: a request body looks like {"jsonrpc":"2.0","id":1,"method":"tools/list"}. Errors are returned as a JSON-RPC error object rather than an HTTP status where the protocol calls for it, which is why a missing scope shows up as error code -32002 in the body rather than an HTTP 403.
In plain language: one URL handles everything, and the connection upgrades to a stream only when there is something to stream. You do not run a long-lived socket just to ask a question.
On the wire, the three verbs each have a job:
initialize, tools/list, tools/call, resources/read and prompts/get all travel. The client should send Accept: application/json, text/event-stream so the server can answer with either a single JSON body or an event stream.In plain language: the server can remember you across calls, but it does not have to. That matters for anyone running the assistant inside a serverless function or a CI job, where the same process may never handle two requests in a row.
On the wire: the response to initialize carries an Mcp-Session-Id header. A client that keeps a session echoes that value back on later requests and tears it down with a DELETE. A client that sends no session header still gets answers, because stateless calls are supported: authentication comes from the key on every single request, not from the session. The session is an optimisation, never the security boundary.
In plain language: you mint a key in the panel, the client sends it on every request, and there is no login dance. A discovery document tells standards-aware clients how the endpoint expects to be authenticated.
On the wire: pass Authorization: Bearer csk_live_... with every request. Keys are created in the panel at Settings, then Developers, then API keys, and the full token is shown once. The endpoint publishes an RFC 9728 protected resource document at GET /.well-known/oauth-protected-resource, which advertises bearer API-key authentication. Its authorization_servers array is currently empty, and that single detail explains a whole class of connection failures: clients that will only connect through an authorization server flow, rather than a static header, cannot use a key directly. That is why Claude Desktop connectors and ChatGPT custom connectors need a different setup path than Claude Code or Cursor, which we walk through on the connect Claude to your CRM page.
In plain language: if you parse MCP tool results in your own code, expect contactId and not ContactId.
On the wire: MCP responses are camelCase throughout, while the REST v1 API returns PascalCase properties. The two surfaces sit on the same data and the same permissions model, but they were shaped for different consumers, and mixing up the casing is the most common cause of a null field when a developer moves a script from one to the other. Within MCP the convention is consistent across all 62 tools, so you learn it once.
Wire summary. Endpointhttps://api.crmsolid.com/mcp. Transport Streamable HTTP. Protocol2025-06-18. Format JSON-RPC 2.0. AuthAuthorization: Bearer csk_live_.... Session headerMcp-Session-Id, optional. Scope failure-32002. Rate limit 60 requests per minute by default, 300 ceiling on Business. Discovery/.well-known/oauth-protected-resource.
The surface covers twelve capability areas: contacts, conversations, inbox and email, deals, tasks, pipelines, finance, sequences, social DMs, social posts, webhooks, and agents and jobs. Cutting across all of them are three analytics tools, crm_dashboard_summary, crm_messaging_stats and crm_top_contacts, which answer the how-am-I-doing questions without belonging to any one area. What follows is a paragraph per area with representative tool names. The complete reference, with every tool, its required scope and whether it reads or writes, is on the MCP tools reference.
Eight read tools and seven write tools, the largest area by some distance. crm_search_contacts finds a person by name, username or phone and returns up to 25 results ordered by most recently contacted. crm_get_contact opens one record and includes the last ten messages exchanged, which is usually enough context for a reply without a second call. On the write side, crm_tag_contact, crm_set_lead_score and crm_assign_contact each log an entry to the activity timeline, so the change is attributable afterwards. One honest caveat worth knowing before you let an assistant loose: crm_add_contact_note appends to a 500-character field, and once it is full the oldest text is dropped from the front to make room.
crm_list_recent_conversations is the tool most assistants reach for first, because it answers who needs a reply with a last-message preview per contact. crm_get_conversation pages back through a thread fifty messages at a time. Sending is deliberately split by channel and by scope: crm_send_telegram_message requires telegram:send and queues asynchronously, while crm_send_twitter_dm requires twitter:send and goes out through the connected X session. crm_list_accounts is the call that tells the assistant which account id it is allowed to send from, and skipping it is the usual reason a send fails on the first try.
Two read tools and two write tools, and the important detail is what the write tools deliberately do not do. crm_search_email_threads and crm_get_email_thread read the shared mailbox, the second returning plain-text messages oldest-first along with any AI summary and lead score. crm_set_email_thread_status and crm_assign_email_thread move a thread through open, pending and closed, or hand it to a colleague. Neither sends mail. An assistant with email:read and email:write can run your triage without ever being able to email a customer, which is exactly the shape most support teams want first.
crm_list_deals returns the pipeline ordered by stage then value, with open-task counts attached, so a forecast question needs one call. crm_get_deal opens one with its linked tasks and resolved contact name. crm_create_deal and crm_update_deal_stage handle the writes, and both stop short of the same line: a deal can move between lead, qualified, proposal, negotiation and lost, but it cannot be moved to won over MCP, because won books an income entry in the ledger. Closing a deal stays a human action in the panel.
crm_list_tasks sorts by due date then priority, which makes what is overdue and what is due today a single call. crm_create_task books a follow-up and can link it to a contact and a deal at the same time, so the reminder carries its own context. crm_complete_task marks one done and stamps the completion time, or reopens it by passing an explicit status. This is the smallest area on the server and, in practice, the one that changes daily behaviour fastest, because it is where an assistant turns a conclusion into an obligation.
crm_list_pipelines and crm_get_pipeline are read-only and exist to teach an assistant the shape of your CRM before it edits anything. They return each board with its ordered stage columns and a live contact count per stage. A well-behaved assistant calls one of them before it tries to move a contact, because stage names are yours, not ours, and guessing them is how an assistant produces a confident, wrong answer.
Four tools, all read-only, all reporting. crm_finance_summary returns realised income, expense and net per currency over a window, plus outstanding totals and the top expense categories. crm_list_transactions lists ledger entries newest-first. crm_list_invoices summarises what is still owed per currency. crm_revenue_sources_summary reports the connected revenue feeds with their last sync status and never returns the credentials behind them. None of these four can create, edit, refund, settle or pay anything. A finance assistant on this server can tell you the number and cannot change it.
crm_list_sequences answers what campaigns are running, with status and target progress. crm_get_sequence_status goes deeper on one, returning processed, successful and failed counts along with the message steps and recent job activity. The write side is intentionally two controls rather than a full editor: crm_pause_sequence and crm_resume_sequence, both idempotent. An assistant can stop a campaign that is misfiring at three in the morning. It cannot rewrite your outreach copy while you sleep. Building the campaign itself stays in the sequence builder.
Five read tools and two write tools spanning every connected network. crm_social_inbox_summary is the opening move for triage: one call returns conversation and unread totals overall and per network, plus the threads still waiting on a reply, oldest first. crm_list_social_messages pages through a thread and carries transcripts for voice notes and both wordings for translated messages. crm_send_social_message is the one that reaches a real person: it delivers through the account that owns the thread, pauses AI auto-reply for that contact so two robots do not answer at once, and records the send on the CRM timeline. Platform windows still apply, and WhatsApp only allows free-form replies within 24 hours of the customer's last message. The full social workflow has its own page: social media management over MCP.
Three read tools and three write tools. crm_list_social_posts shows what is scheduled and what published, including any failure reason. crm_schedule_social_post books content on one or more connected accounts, creating one post per target account, and enforces per-platform rules at call time: TikTok and YouTube need a video, Instagram needs media, X caps at 280 characters. crm_update_social_post and crm_cancel_social_post only touch posts that are still pending. Anything already published, in flight, failed or cancelled is rejected, which means an assistant cannot quietly rewrite history.
crm_list_webhooks and crm_list_webhook_deliveries exist mostly to answer one question: why is my endpoint not firing. The delivery tool returns recent attempts with status, attempt count, last response code and last error, newest first, which is usually enough to diagnose it without opening the panel. Signing secrets are never returned by the list tool, only a short preview. crm_create_webhook registers an HTTPS endpoint and returns its signing secret exactly once, so store it immediately. crm_delete_webhook is the single hard delete on the entire server and is annotated as destructive.
crm_list_agents reports the AI agents currently automating replies, with status, channels, response mode, model and a 24-hour run count. crm_run_agent is a playground: it runs an agent against a sample inbound message and returns the reply it would have sent, without delivering anything and without creating, changing or deleting a single CRM record. It is flagged as a non-read-only tool purely because each run calls an external model provider and spends AI credits. crm_list_jobs and crm_get_job close the loop on outbound sending, showing whether a queued message actually left and, if it did not, the exact error.
Alongside the tools, 21 resources give a client something to load before the first question is asked. crm://me carries identity and plan. crm://social/inbox carries unread totals per network and the twenty most recently active DM threads. crm://tasks/overdue carries only tasks whose due date has already passed, which is a different list from crm://tasks/today and worth keeping separate. The 15 prompts are the workflows a person triggers on purpose: daily-briefing, triage-inbox, pipeline-review, weekly-finance-report, lost-deal-postmortem, dm-reply-draft and nine more.
Three steps: mint a scoped key, add the server to your client, verify with a question that has a checkable answer. The per-client detail differs more than you would expect, because every vendor invented its own configuration file shape, so the exact form for Claude Code, Claude Desktop, Cursor, VS Code and Windsurf lives on the connect Claude to your CRM page. What follows is the summary plus two correct snippets.
In the panel, open Settings, then Developers, then API keys, and create a key. Choose only the scopes this assistant needs. A reporting assistant is fine with contacts:read, deals:read, pipelines:read and analytics:read. The full token starts with csk_live_ and is shown once, so copy it into an environment variable straight away and never into a repository.
In Claude Code, one command does it. The -s flag chooses where the entry is stored: local for just you in this project, project for a checked-in .mcp.json, user for every project on your machine.
claude mcp add --transport http crmsolid https://api.crmsolid.com/mcp \
--header "Authorization: Bearer csk_live_YOUR_KEY" \
-s userIf you prefer a file that lives with the repository, this is the correct .mcp.json shape. The type field is not optional: a url entry without "type": "http" is parsed as a local stdio command and the connection fails with an empty tool list rather than a useful error.
{
"mcpServers": {
"crmsolid": {
"type": "http",
"url": "https://api.crmsolid.com/mcp",
"headers": {
"Authorization": "Bearer csk_live_YOUR_KEY"
}
}
}
}To see the raw wire before trusting a client, ask the server what it can do with a single POST. The Accept header carries both content types because a Streamable HTTP server may answer with either.
curl -X POST https://api.crmsolid.com/mcp \
-H "Authorization: Bearer csk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'A full handshake starts with initialize, which is where the protocol revision is negotiated and where the response carries the Mcp-Session-Id header if you want to keep a session:
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": {},
"clientInfo": { "name": "my-client", "version": "1.0.0" }
}
}Do not verify by asking whether the connection works. Ask something only your CRM can answer and then check it. Good first questions: which social conversations are still waiting on a reply, how many deals sit in each pipeline stage, what tasks are overdue right now. The assistant should call crm_social_inbox_summary, crm_list_deals or crm_list_tasks, and the numbers should match the panel. If the answer is vague or hedged, the tool list is probably empty and the assistant is improvising.
The security model rests on five things: a per-key scope list checked on every tool call, a write surface that deliberately stops short of irreversible actions, a per-key rate limit, key rotation you control, and tenant isolation enforced at the query level rather than in the model prompt. None of it depends on the assistant behaving well, which is the only sane way to design permissions for a system where the caller is a language model.
Every tool declares the one scope it requires. These are the scope strings a key can carry, and the count is the number of tools each one unlocks in the current build:
contacts:read (8 tools), contacts:write (7), telegram:read, telegram:send (1), twitter:send (1).social:read (5), social:write (2), posts:read (3), posts:write (3).deals:read (2), deals:write (2), tasks:read (1), tasks:write (2), pipelines:read (2).email:read (2), email:write (2).sequences:read (2), sequences:write (2), jobs:read (2), webhooks:read (2), webhooks:write (2), agents:read (1), agents:run (1).analytics:read (3), finance:read (4).finance:write, email:send, keys:manage. If you find yourself reaching for one of these for a chat assistant, stop and ask what you are actually trying to automate.Note the punctuation, because it is a common source of a failed first call: the resource comes first and the verb second. It is contacts:read, never read:contacts. When a key is missing a scope, the call fails with JSON-RPC error -32002 and a data object carrying requiredScope and granted, so the assistant can tell you precisely which permission to add instead of reporting a generic failure.
Scope sprawl happens when one key is minted for everything and then reused. The alternative is one key per assistant persona. These three cover most teams:
contacts:read, deals:read, pipelines:read, tasks:read, analytics:read, finance:read. It answers forecast, workload and revenue questions and cannot change a single record. This is the key you share most widely, and the one whose leak costs you the least.contacts:read, contacts:write, social:read, email:read, email:write, tasks:read, tasks:write, agents:read, agents:run. It triages, tags, scores, assigns, drafts and books follow-ups. Because neither email:write nor social:read can deliver a message, this persona can run your whole triage loop without ever reaching a customer. Every change it makes is reversible and lands on the activity timeline.social:write, telegram:send, twitter:send, posts:read, posts:write, sequences:read, sequences:write, jobs:read. This is the only persona that can reach a real person, so it should be the one with a named owner, the shortest rotation interval and the tightest review.The write tools deliberately stop short of irreversible money and identity actions. This is a design decision, not an oversight, and it is worth spelling out exactly where the line sits:
crm_list_invoices reports what is outstanding and returns no payment link. There is no tool that sends, voids or pays an invoice.crm_update_deal_stage accepts lead, qualified, proposal, negotiation and lost, and rejects won, because won books income. That transition stays a human decision in the panel.crm_run_agent returns the reply an agent would have sent. The reply is never delivered to any contact and no CRM record is created, changed or deleted by the run.crm_delete_webhook permanently removes an endpoint you registered. It is the only destructive operation on the server and carries the destructive annotation so a client can require confirmation.crm_list_webhooks returns a short preview of a signing secret, never the secret. crm_create_webhook returns the secret once at creation. crm_revenue_sources_summary never returns the credentials for a connected revenue feed.Two write tools do reach the outside world and deserve deliberate thought before you grant them. crm_send_social_message delivers to a real person immediately. crm_schedule_social_post publishes to a real audience straight away when publishNow is set. Everything else on the write surface changes a record you can change back.
The default limit is 60 requests per minute per key, and a Business workspace can raise a key to a ceiling of 300 per minute. Going over returns HTTP 429 with a Retry-After header giving the number of seconds to wait. The limit is applied per key rather than per workspace, which is the important part: an assistant stuck in a retry loop throttles only itself and cannot starve your reporting dashboard or your webhook processor. If you are running several assistants, give each its own key for this reason alone, independent of the scope argument.
The key is validated on every single request rather than exchanged for a session token, so revocation takes effect on the next call. There is no grace period in which an already-connected client keeps working, and no cached session to expire. That makes the rotation procedure simple and zero-downtime if you do it in this order: mint the replacement key with the same scopes, update the client configuration and confirm it lists tools, then revoke the old key. Both keys are valid during the overlap, so nothing fails mid-cutover.
Rotate on a schedule for any key carrying a sending scope, and rotate immediately whenever a key has been pasted into a chat window, a ticket, a screenshot or a repository. Because keys are per-assistant in the recipe above, rotating one never disturbs the others.
The audit trail is the CRM's own activity timeline, which is a better place for it than a separate log nobody opens. Write tools record what they did on the record they touched: crm_tag_contact logs a TagAdded entry, crm_untag_contact logs TagRemoved, crm_set_lead_score logs ScoreChanged and marks the score as a manual override rather than an AI one, crm_assign_contact logs Assigned or Unassigned, crm_add_contact_note appends a timestamped note, and crm_send_social_message records the send on the timeline. Read it back with crm_get_contact_activity, newest first, or open the contact in the panel and see the same entries. On the delivery side, crm_list_jobs and crm_get_job show every outbound send with its status and its last error.
An API key identifies exactly one workspace user, and every tool resolves its query against that authenticated user id before it touches the database. There is no tool parameter that names a different account, workspace or tenant, so there is nothing for a model to fill in wrongly and nothing for a prompt injection to aim at. This matters specifically in an MCP context: the caller is a language model that can be influenced by content it reads, so the isolation cannot live in an instruction telling the model to stay in its lane. It lives in the query.
The same reasoning applies to the scope check. It runs on the server before the tool body executes, not in the tool description the model reads. A model that has been talked into wanting to send a message still cannot send one with a key that lacks social:write.
Before. Open the CRM, open the social inbox, open email, scan three lists for anything unanswered, guess at priority from whatever is visible on the first screen, and start typing. Twenty minutes, most of it spent deciding rather than doing, and the oldest unanswered thread is frequently the one nobody scrolled to.
After. Ask: who is waiting on a reply across every channel, ranked by how long they have waited and how valuable the relationship is, and tell me what each one wants. The assistant calls crm_social_inbox_summary for the waiting threads oldest first, crm_list_recent_conversations for the direct channels, crm_search_email_threads for the mailbox, and crm_get_contact on the top few for context. You get a ranked list with a one-line reason each. Follow up with: draft a reply to the first three and book me a task to call the second one tomorrow. That is crm_get_social_conversation for thread history and crm_create_task for the reminder.
Before. A colleague goes on leave and their open threads get reassigned by dragging rows in a list, with no shared understanding of what any of them is actually about. The receiving agent reads each thread from scratch and the customer repeats themselves.
After. Ask: summarise every open email thread assigned to this person, tell me which are blocked on us, and reassign those to me. The assistant calls crm_search_email_threads to pull the open threads, crm_get_email_thread on each one to read the messages and any AI summary, then crm_assign_email_thread to move the blocked ones. It can add crm_add_contact_note so the handover context lives on the contact rather than in a chat log that disappears. The whole loop needs email:read, email:write and contacts:write, and cannot send a single email.
Before. Export the ledger, build a pivot, reconcile currencies by hand, and produce a number you half trust two hours later.
After. Ask: how did the business do over the last 30 days by currency, what is still outstanding, and which expense categories moved most. The assistant calls crm_finance_summary for realised income, expense and net per currency, crm_list_invoices for what is owed, and crm_list_transactions to look at the entries behind an anomaly. The weekly-finance-report prompt packages the same thing as a repeatable weekly workflow. This runs on finance:read alone, which means the assistant that produces your finance review cannot touch your ledger even if it is asked to. Pair it with the CRM finance module for the panel view.
Before. A recurring calendar block called pipeline review that gets skipped, followed by a quarter-end scramble to work out which deals were real.
After. Ask: show me open deals by stage with value and probability, flag anything with no activity in two weeks, and book me a task for each one. The assistant calls crm_list_deals and crm_list_pipelines to get the board shape, crm_get_contact_activity to check for recent movement, then crm_create_task per stalled deal and crm_update_deal_stage where a deal has genuinely slipped backwards. The pipeline-review prompt does the analysis half as a one-click workflow, and lost-deal-postmortem handles the ones that did not make it. Remember that moving a deal to won is not available here by design: the assistant can clean the board, and you close the business.
MCP access is part of the Business plan. A key minted on a Free or Pro workspace authenticates correctly and still answers HTTP 402 on every MCP request, because entitlement is checked separately from authentication. That separation is deliberate and has a useful side effect: a 402 tells you the key itself is fine, so you are looking at a plan question rather than a credential question.
MCP comes with the plan rather than as a metered add-on, and the rate limit is the fair-use boundary: 60 requests per minute per key by default, up to a 300 per minute ceiling on Business. Because the entitlement check runs on every request rather than at connection time, upgrading takes effect on the key you already have: no re-mint, no client reconfiguration. Current plan details are on the pricing page.
One cost that is worth naming because it is easy to miss: crm_run_agent calls an external model provider on every run and spends AI credits from your workspace. It is the only tool on the server that does, which is exactly why it is annotated as a write tool despite changing nothing.
Nearly every failed first connection is one of six things. The response itself usually tells you which:
| What you see | What it means | What to do |
|---|---|---|
| HTTP 401 | The key is invalid, revoked, or never arrived intact. | Confirm the token starts with csk_live_ and that the header is exactly Authorization: Bearer <token>. If the key works in curl but not in your client, suspect a truncated header, below. |
| HTTP 402 | The key is valid but the workspace is on Free or Pro. MCP is a Business-plan capability. | Upgrade the workspace. The same key starts working immediately, with no re-mint and no client change. |
JSON-RPC error -32002 | The key does not carry the scope this tool requires. The error data object names it. | Read data.requiredScope and compare it with data.granted. Add the scope, or mint a second key for that persona rather than widening the first one. |
HTTP 429 with Retry-After | More than 60 requests in a minute on this key, or more than the 300 ceiling if it has been raised. | Wait the number of seconds in Retry-After. If it happens repeatedly, the assistant is probably looping: give it its own key so it throttles only itself. |
| Empty tool list after connecting | The client parsed the entry as a local stdio command, or the configuration used the wrong key name for that client. | In a .mcp.json, add "type": "http". Client shapes differ: the per-client forms are on the Claude setup page. |
| Silent 401 from one client only | The client did not escape the space inside Authorization: Bearer ... when it was passed as a single argument, so the header arrived truncated. | Split it. Pass --header "Authorization:${AUTH_HEADER}" with the full Bearer csk_live_... value in an environment variable. |
One more diagnostic worth knowing: if a tool call returns data but the fields you expected are all null, check the casing. MCP results are camelCase and the REST v1 API is PascalCase, and a script moved from one to the other will parse cleanly and silently find nothing.
Things this server does not do, stated plainly so you do not discover them at the wrong moment:
authorization_servers list is currently empty. Clients whose only connector path requires an authorization server cannot use a static key directly and need a bridge process instead.crm_send_telegram_message queues a job. Confirm delivery with crm_list_jobs or crm_get_job rather than assuming a successful tool call means a delivered message.crm_add_contact_note drops the oldest text from the front to make room, so it can remove earlier note text. Use it for durable facts, not for a running transcript.If you need something on this list, the REST v1 API covers a wider surface for code you write yourself, and the API and MCP integration guide walks through webhooks, signature verification and the parts of the platform that are better driven by a service than by an assistant.
“The most useful thing an assistant can do with a CRM is not summarize it. It is to change one record correctly, refuse the change it should not make, and leave a trail you can read afterwards.”
The single most valuable security decision is not which tools exist. It is which scopes each assistant's key carries. Start with the leftmost recipe and widen only when a specific job needs it.
| Capability | Reporting analystRecommended | Inbox copilot | Outreach operator |
|---|---|---|---|
| Reading the CRM | |||
Search contacts and read threads contacts:read | |||
Read the social inbox social:read | |||
Read deals, pipelines and tasks deals:read, pipelines:read, tasks:read | |||
Read the ledger and invoices finance:read | |||
| Changing the CRM | |||
Write notes, tags and lead scores contacts:write | |||
Create and complete tasks tasks:write | |||
Route email threads without sending mail email:write | |||
Move a deal between open stages deals:write | |||
| Reaching a real person | |||
Answer a social DM social:write | |||
Queue a Telegram message telegram:send | |||
Publish or schedule a post posts:write | |||
Pause or resume a campaign sequences:write | |||
| Blast radius if the key leaks | |||
Could contact a customer | Yes | ||
Could change a record | Reversible | Reversible | |
Could move money | |||
No persona can move money: all four finance tools are reporting only and finance:write is an advanced scope that is unchecked by default. Reversible means the change lands on the contact activity timeline and can be undone from the panel.
An AI assistant is a caller that can be argued with. Permissions have to live somewhere it cannot reach.
Not in the tool description the model reads. A model that has been persuaded it should send a message still cannot, if the key lacks social:write.
Every tool filters by the authenticated user id from the key. No tool takes a workspace or tenant parameter, so there is nothing for an injected instruction to aim at.
No transaction creation, no invoice payment, no forcing a deal to won. The server reports on the ledger and refuses to change it.
60 requests per minute by default and a 300 ceiling on Business, so one looping assistant throttles itself instead of starving your dashboards.
Tags, scores, assignments, notes and sends all record activity on the contact, readable back through crm_get_contact_activity or in the panel.
A remote Streamable HTTP server means nothing to install, nothing to keep updated, and one URL plus one header to configure.
Do these in sequence and you will never debug two problems at once.
The questions teams ask in the first hour, answered with the real numbers.
Four companion pages on the MCP surface, plus the platform features an assistant will be calling.
Per-client setup for Claude Code, Claude Desktop, Cursor, VS Code and Windsurf, including the config shapes that genuinely differ.
All 62 tools, 21 resources and 15 prompts with the scope each one requires and whether it reads or writes.
Read DMs, draft replies and schedule posts across twelve networks from one assistant conversation.
When an assistant should call a tool, when to write code against the API, and when a no-code trigger is enough.
The v1 API behind the same data, for the integrations you write yourself rather than hand to an assistant.
Developer walkthrough covering scoped keys, webhooks, signature verification and rate-limit backoff.
The same CRM in a workflow rather than a conversation: contacts, deals and conversations as n8n operations.
The auto-reply agents crm_list_agents reports on, and that crm_run_agent lets you dry-run safely.
The twelve-channel inbox that the social and conversation tools read from and write into.
Everything else CRM Solid connects to, for the parts of your stack that sit outside the assistant.
Plan comparison, including the Business plan that includes MCP access and the 300 per minute ceiling.
62 tools, 21 resources and 15 prompts behind one authenticated endpoint. Mint a read-only key, connect a client, and ask it something only your CRM can answer.
Free forever plan · GDPR-ready · No credit card required
We value your privacy
We use cookies to improve our site, analyze traffic, and personalize ads. You can accept all, reject non-essential, or customize your choices. Read our Cookie Policy.