twenty-crm-mcp-server
Health Gecti
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Community trust — 84 GitHub stars
Code Uyari
- process.env — Environment variable access in index.js
- network request — Outbound network request in index.js
Permissions Gecti
- Permissions — No dangerous permissions requested
Bu listing icin henuz AI raporu yok.
A Model Context Protocol (MCP) server for Twenty CRM integration. Enables natural language interactions with your CRM data through Claude and other AI assistants. Supports CRUD operations, dynamic schema discovery, and advanced search across people, companies, tasks, and notes.
🤖 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
| Variable | Required | Default | Description |
|---|---|---|---|
TWENTY_API_KEY |
✅ | — | API key from Settings → API & Webhooks |
TWENTY_BASE_URL |
https://api.twenty.com |
Your instance URL if self-hosted | |
TWENTY_DEFAULT_CURRENCY |
USD |
Currency code used when none is given for money fields |
💬 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
| Category | Tools |
|---|---|
| People | create_person, get_person, update_person, list_people, delete_person |
| Companies | create_company, get_company, update_company, list_companies, delete_company |
| Opportunities | create_opportunity, get_opportunity, update_opportunity, list_opportunities, delete_opportunity |
| Notes | create_note (with record targets), get_note, update_note, list_notes, delete_note |
| Tasks | create_task (with record targets + assignee), get_task, update_task, list_tasks, delete_task |
| Batch | batch_create_people, batch_create_companies (up to 60 records) |
| Workspace | list_workspace_members (for task assignment) |
| Metadata | get_metadata_objects, get_object_metadata |
| Search | search_records (across people, companies, opportunities, notes, tasks) |
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:
| You pass | Twenty receives |
|---|---|
firstName, lastName |
name: { firstName, lastName } |
email |
emails: { primaryEmail, additionalEmails: [] } |
phone |
phones: { primaryPhoneNumber, ... } |
linkedinUrl / xUrl / domainName |
{ primaryLinkUrl, ... } link composites |
amount: 12000 + currencyCode |
amount: { amountMicros: 12000000000, currencyCode } |
body (notes/tasks) |
bodyV2: { markdown } |
address (string) |
address: { addressStreet1, ... } (or pass a full address object) |
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
Contributions are welcome! 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.
Yorumlar (0)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi