MT

mhenry3164/twenty-crm-mcp-server

Developer tools
106 stars 40 forks Quality 77 Trend 19MIT

A Model Context Protocol server that connects Twenty CRM with Claude and other AI assistants, enabling natural language interactions with your customer data.

Overview

A Model Context Protocol server that connects Twenty CRM with Claude and other AI assistants, enabling natural language interactions with your customer data.

README


✨ Features

  • Complete CRUD for people, companies, opportunities, notes and tasks
  • Working search — built on Twenty’s real filter grammar (ilike matching), not the nonexistent search param
  • Correct composite-field mapping — flat inputs like firstName/email/amount are converted to Twenty’s name/emails/amount composite shapes on write
  • Cursor pagination (startingAfter/endingBefore) plus raw filter, orderBy and depth passthrough on every list tool
  • Notes & tasks attach to records — pass personId/companyId/opportunityId when 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

  1. Get your Twenty CRM API key: in Twenty, go to Settings → API & Webhooks (under Developers) and generate a key.

  2. 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 annualRecurringRevenue on most deployed Twenty versions and annualRevenue on Twenty v2.x+. Both parameters are supported; use the one that matches your instance (check get_object_metadata for companies if unsure).

🔍 Search, filtering & pagination

Twenty’s REST API has no search or offset query params — this server builds real filters instead:

  • search on list tools becomes a case-insensitive ilike filter across sensible fields per object (people: first/last name + email; companies: name + domain; opportunities/notes/tasks: name/title).
  • filter accepts Twenty’s raw filter grammar for anything more specific:
    • createdAt[gte]:2026-01-01
    • or(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 with and(...), or(...), not(...). Use field[is]:NULL / NOT_NULL for empty checks.
  • orderBy: e.g. createdAt[DescNullsLast] (directions: AscNullsFirst, AscNullsLast, DescNullsFirst, DescNullsLast).
  • Pagination is cursor-based: results include pageInfo.endCursor — pass it as startingAfter for the next page. limit max is 200.
  • depth: 0 (default) or 1 to 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:

  • offset was removed from list tools (Twenty’s REST API never supported it) — use cursor pagination (startingAfter).
  • Note/task body now maps to bodyV2.markdown; position params were dropped.
  • Updates now use PATCH (Twenty’s documented verb) instead of PUT.
  • 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.

View the full README on GitHub

Install

npx -y github:mhenry3164/twenty-crm-mcp-server
New to MCP? Start with the mcpskill.org guide →

Configuration

{ "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" } } } }