๐ค Twenty CRM MCP Server
Transform your CRM into an AI-powered assistant
A Model Context Protocol server that connects Twenty CRM with Claude and other AI assistants, enabling natural language interactions with your customer data.
๐ Quick Start โข ๐ ๏ธ Tools โข ๐ Search & Filtering โข ๐ณ Docker โข ๐ค Contributing
โจ Features
- Complete CRUD for people, companies, opportunities, notes and tasks
- Working search โ built on Twenty's real
filtergrammar (ilikematching), not the nonexistentsearchparam - Correct composite-field mapping โ flat inputs like
firstName/email/amountare converted to Twenty'sname/emails/amountcomposite shapes on write - Cursor pagination (
startingAfter/endingBefore) plus rawfilter,orderByanddepthpassthrough on every list tool - Notes & tasks attach to records โ pass
personId/companyId/opportunityIdwhen creating and the target links are created for you - Batch creates โ up to 60 people or companies per call
- Resilient client โ 30s timeouts, automatic retry with backoff on 429/5xx (honors
Retry-After), structured error messages - Schema discovery โ metadata tools expose your workspace's objects, fields and enum options, including custom objects
๐ Installation
Prerequisites
- Node.js 18 or higher
- A Twenty CRM instance (cloud or self-hosted)
- Claude Desktop, Claude Code, or any MCP-compatible client
Setup
-
Get your Twenty CRM API key: in Twenty, go to Settings โ API & Webhooks (under Developers) and generate a key.
-
Configure your MCP client.
Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"twenty-crm": {
"command": "npx",
"args": ["-y", "github:mhenry3164/twenty-crm-mcp-server"],
"env": {
"TWENTY_API_KEY": "your_api_key_here",
"TWENTY_BASE_URL": "https://api.twenty.com"
}
}
}
}
Claude Code:
claude mcp add twenty-crm -e TWENTY_API_KEY=your_api_key_here -e TWENTY_BASE_URL=https://api.twenty.com -- npx -y github:mhenry3164/twenty-crm-mcp-server
Or clone and run from source:
git clone https://github.com/mhenry3164/twenty-crm-mcp-server.git
cd twenty-crm-mcp-server
npm install
then point your client at node /path/to/twenty-crm-mcp-server/index.js.
Environment variables
๐ฌ Usage
Once configured, use natural language to interact with your Twenty CRM:
"List the first 10 people in my CRM"
"Create a new person named John Doe with email [email protected] at Acme (company id ...)"
"Create a $12,000 opportunity called 'Acme renewal' in PROPOSAL stage"
"Add a note about today's call and attach it to the Acme company record"
"Create a follow-up task due Friday assigned to Sam, linked to the deal"
"Search people, companies and opportunities for 'blockchain'"
๐ ๏ธ Tools
Composite fields, handled for you
Twenty stores identity/contact/money data in composite fields. This server accepts flat parameters and maps them to the shapes the API expects:
Anything else โ including your workspace's custom fields โ passes through untouched.
Note on company revenue: the field is
annualRecurringRevenueon most deployed Twenty versions andannualRevenueon Twenty v2.x+. Both parameters are supported; use the one that matches your instance (checkget_object_metadataforcompaniesif unsure).
๐ Search, filtering & pagination
Twenty's REST API has no search or offset query params โ this server builds real filters instead:
searchon list tools becomes a case-insensitiveilikefilter across sensible fields per object (people: first/last name + email; companies: name + domain; opportunities/notes/tasks: name/title).filteraccepts Twenty's raw filter grammar for anything more specific:createdAt[gte]:2026-01-01or(city[eq]:Austin,city[eq]:Dallas)emails.primaryEmail[ilike]:%@acme.com- Comparators:
eq, neq, in, containsAny, is, gt, gte, lt, lte, startsWith, endsWith, like, ilike; combine withand(...),or(...),not(...). Usefield[is]:NULL/NOT_NULLfor empty checks.
orderBy: e.g.createdAt[DescNullsLast](directions:AscNullsFirst,AscNullsLast,DescNullsFirst,DescNullsLast).- Pagination is cursor-based: results include
pageInfo.endCursorโ pass it asstartingAfterfor the next page.limitmax is 200. depth:0(default) or1to include first-level related records.
๐ณ Docker
docker build -t twenty-crm-mcp-server .
{
"mcpServers": {
"twenty-crm": {
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "TWENTY_API_KEY", "-e", "TWENTY_BASE_URL", "twenty-crm-mcp-server"],
"env": {
"TWENTY_API_KEY": "your_api_key_here",
"TWENTY_BASE_URL": "https://api.twenty.com"
}
}
}
}
๐งช Development
npm install
npm test # unit tests (node --test, no network needed)
npm start # run the stdio server
โฌ๏ธ Upgrading from v1.x
v2.0.0 fixes writes and search against the actual Twenty API. Breaking changes:
offsetwas removed from list tools (Twenty's REST API never supported it) โ use cursor pagination (startingAfter).- Note/task
bodynow maps tobodyV2.markdown;positionparams were dropped. - Updates now use
PATCH(Twenty's documented verb) instead ofPUT. - List results are returned as
{ records, pageInfo, totalCount? }instead of the raw API envelope.
๐ค Contributing
This project is community-supported โ the maintainer no longer runs Twenty day-to-day, so bug reports and PRs from active Twenty users are especially welcome and get reviewed and merged. See CONTRIBUTING.md.
v2.0.0 builds on excellent community work: composite-field mapping (#4 by @zaks), filter-based search (#6 by @studio7A, #8 by @InDebted-Growth), opportunity tools (#7 by @tarikhennen), and patterns from the forks by @BCJonkhout, @archie1492, @ndrkltsk and @atilladeniz.
๐ License
MIT โ see LICENSE.