Twenty CRM MCP
Give Codex, Claude Code, and other MCP clients controlled access to yourTwenty CRM.
This is an unofficial, community-built integration. It is not affiliatedwith, endorsed by, or sponsored by Twenty.com, PBC.
Why this server
Twenty exposes the same operation families across many object types. Thisserver uses a validated entity parameter, so an agent loads 14 composabletools instead of hundreds of near-duplicate tool definitions.
- Read, search, create, update, group, deduplicate, merge, restore, and batchrecords.
- Covers 28 standard Twenty objects, including companies, people,opportunities, tasks, notes, workflows, calendar objects, and messagingobjects.
- Runs locally over stdio. Your API key is sent only to the Twenty API.
- Uses conservative defaults: no hard delete, guarded soft delete and merge,and a restricted write allowlist.
- Returns structured MCP content for reliable follow-up tool calls.
Native Twenty MCP or this server?
Twenty 2.0 introduced native MCP capabilities. If your workspace alreadyprovides the access and controls you need, start with the native integration.
This project is useful when you want a small, auditable local stdio process,API-key authentication, compatibility with a self-hosted or older workspace,or explicit safety controls in front of record writes. Its differentiator is astable 14-tool surface with a write allowlist, dry-run merges, and no harddelete—not replacing every native Twenty feature.
Quick start
1. Requirements
- Node.js 20.6 or newer
- Codex, Claude Code, or another stdio-compatible MCP client
- A Twenty workspace and API key
2. Install
git clone https://github.com/0xfabrica/twentycrm-mcp.git
cd twentycrm-mcp
npm ci
npm test
3. Add your Twenty credentials
Create a local environment file:
cp .env.example .env
Edit .env:
# Twenty Cloud
TWENTY_API_URL=https://api.twenty.com/rest
# Create this in Settings > API & Webhooks
TWENTY_API_KEY=replace_with_your_api_key
# Keep destructive operations disabled for normal agent sessions
TWENTY_ALLOW_DESTRUCTIVE=false
This example omits TWENTY_WRITABLE_ENTITIES, so the server uses its defaultCRM write allowlist: companies, people, opportunities, tasks, notes, notetargets, and task targets. To start in fully read-only mode, add:
TWENTY_WRITABLE_ENTITIES=
TWENTY_ALLOW_DESTRUCTIVE=false
An empty TWENTY_WRITABLE_ENTITIES value disables every write tool. Bycontrast, TWENTY_ALLOW_DESTRUCTIVE=false only blocks soft deletes and realmerges; it does not block ordinary creates, updates, upserts, or restores.
For a self-hosted workspace, use https://your-domain.example/rest. The URLmust end in /rest, not /rest/core.
Create the key in Settings > API & Webhooks > Create key. Twenty shows itonce, so store it immediately. Assign the key a least-privilege role wheneverpossible. See the official Twenty API documentation.
The .env file is ignored by Git. On macOS or Linux, you can additionallyrestrict it to your user:
chmod 600 .env
4. Register the MCP server
Both commands below store absolute paths, so run them from the cloned repo.
Codex
codex mcp add twenty-crm -- node \
--env-file="$(pwd)/.env" \
"$(pwd)/dist/index.js"
Inspect the registration:
codex mcp get twenty-crm
For manual configuration, add this to ~/.codex/config.toml and replace bothpaths:
[mcp_servers.twenty-crm]
command = "node"
args = [
"--env-file=/absolute/path/to/twentycrm-mcp/.env",
"/absolute/path/to/twentycrm-mcp/dist/index.js"
]
startup_timeout_sec = 20
tool_timeout_sec = 60
default_tools_approval_mode = "prompt"
Claude Code
claude mcp add --scope user twenty-crm -- node \
--env-file="$(pwd)/.env" \
"$(pwd)/dist/index.js"
Inspect the registration:
claude mcp get twenty-crm
Restart the MCP client after registering the server.
Windows PowerShell
From the cloned repository:
$Repo = (Get-Location).Path
Copy-Item .env.example .env
# Edit .env and replace the example API key before continuing.
codex mcp add twenty-crm -- node "--env-file=$Repo\.env" "$Repo\dist\index.js"
claude mcp add --scope user twenty-crm -- node "--env-file=$Repo\.env" "$Repo\dist\index.js"
Then restart Codex or Claude Code and inspect the registration with the samemcp get commands shown above. Codex's manual user configuration is at$env:USERPROFILE\.codex\config.toml.
Do not keep .env in a shared or cloud-synced folder. If you prefer persistentuser environment variables on Windows, set them from PowerShell and restartthe client:
[Environment]::SetEnvironmentVariable("TWENTY_API_URL", "https://api.twenty.com/rest", "User")
[Environment]::SetEnvironmentVariable("TWENTY_API_KEY", "your-api-key", "User")
Environment-only alternative
If you prefer not to use a local .env, export the variables in the parentenvironment before launching your MCP client:
export TWENTY_API_URL="https://api.twenty.com/rest"
export TWENTY_API_KEY="your-api-key"
Then register node /absolute/path/to/twentycrm-mcp/dist/index.js without the--env-file argument. Do not place a real key directly in MCP JSON or TOML.
Example prompts
Start with discovery and keep writes explicit:
List the 10 most recently updated companies in Twenty. Do not modify anything.
Find people whose email domain is example.com and summarize their companies.
Preview possible duplicate companies named Acme. Do not merge records.
Create a follow-up task for this opportunity, then show me the created record.
Tools
| Tool | Behavior |
|---|---|
twenty_list_records |
List, filter, order, and page through an object |
twenty_search_records |
Targeted list with a required filter |
twenty_get_record |
Fetch one record by UUID |
twenty_create_record |
Create or optionally upsert one record |
twenty_update_record |
Patch one record |
twenty_soft_delete_record |
Guarded soft delete |
twenty_batch_create_records |
Create 1–50 records |
twenty_batch_update_records |
Patch records matching a required filter |
twenty_batch_soft_delete_records |
Guarded filtered soft delete |
twenty_find_duplicates |
Check IDs or candidate data for duplicates |
twenty_group_records |
Group and aggregate records |
twenty_merge_records |
Preview a merge or perform a guarded merge |
twenty_restore_record |
Restore one soft-deleted record |
twenty_restore_records |
Restore records matching a filter |
Safety model
Agents can make mistakes. This server limits the blast radius, but it is not anauthorization boundary.
- There is no hard-delete tool.
- Delete operations always request Twenty's soft-delete behavior.
- Soft delete and real merges are disabled unless
TWENTY_ALLOW_DESTRUCTIVE=true. - Merge defaults to
dry_run=true. - Batch creates are limited to 50 records per call.
- Non-local API URLs must use HTTPS.
- API errors do not echo response bodies or credentials.
- Tool annotations tell clients which operations are read-only or destructive.
Use a least-privilege Twenty role, review tool calls before approval, and keepbackups appropriate for your workspace.
TWENTY_WRITABLE_ENTITIES: choose what agents may modify
This is a server-side write allowlist. It controls which supported Twentyobjects the MCP may create, update, restore, soft-delete, or merge.
If the variable is omitted, writes are allowed by default only for:
companies,people,opportunities,tasks,notes,noteTargets,taskTargets
Set a narrower comma-separated list to reduce write access:
TWENTY_WRITABLE_ENTITIES=companies,people,opportunities,tasks,notes
Set an explicitly empty value for read-only mode:
TWENTY_WRITABLE_ENTITIES=
Objects outside the allowlist remain readable but cannot be modified throughthis MCP. The allowlist can only reduce access: the role assigned to the TwentyAPI key must also permit the operation. Keep internal and system objectsread-only unless you have reviewed their schema and permissions.
Changes take effect when the MCP process starts. Restart Codex, Claude Code, oryour other MCP client after editing .env.
TWENTY_ALLOW_DESTRUCTIVE: guard deletes and merges
Keep this setting false or unset during routine use:
TWENTY_ALLOW_DESTRUCTIVE=false
With false:
twenty_soft_delete_recordandtwenty_batch_soft_delete_recordsareblocked before an HTTP request is sent.twenty_merge_recordsmay preview a merge withdry_run=true, but cannotperform the real merge.- Ordinary creates, upserts, updates, batch writes, and restores are stillallowed for objects in
TWENTY_WRITABLE_ENTITIES.
Set it to true only for a deliberate, supervised session. The write allowlistand Twenty API-key permissions still apply. This server never exposes a harddelete, even when destructive operations are enabled.
After the supervised operation, set it back to false and restart the MCPclient.
Recommended safety presets
| Preset | Configuration | Result |
|---|---|---|
| Read-only first run | TWENTY_WRITABLE_ENTITIES= and TWENTY_ALLOW_DESTRUCTIVE=false |
All reads work; every write is blocked |
| Standard CRM work | Omit TWENTY_WRITABLE_ENTITIES; keep destructive false |
Common CRM objects can be created or updated; deletes and real merges are blocked |
| Narrow writer | Set only the required entities; keep destructive false |
Writes are limited to those objects |
| Supervised cleanup | Set only required entities and temporarily set destructive true |
Soft delete and real merge become available for those objects |
Operation risk matrix
TWENTY_ALLOW_DESTRUCTIVE=false does not make the entire server read-only.It blocks soft deletes and real merges; the configured write allowlist stillpermits ordinary record writes.
| Category | Tools | Behavior |
|---|---|---|
| Read-only | list, search, get, find duplicates, group | Never modifies records |
| Writes | create/upsert, update, batch create/update, restore | Modifies allowed objects without the destructive flag |
| Guarded | soft delete, batch soft delete | Requires TWENTY_ALLOW_DESTRUCTIVE=true |
| Preview/guarded | merge | Dry-run by default; a real merge requires the destructive flag |
An upsert may update an existing record when Twenty finds a matching uniquevalue. Review the proposed data and use a least-privilege API-key role evenwhen destructive operations are disabled.
Configuration reference
| Variable | Required | Default | Purpose |
|---|---|---|---|
TWENTY_API_URL |
Yes | — | Twenty REST root ending in /rest |
TWENTY_API_KEY |
Yes | — | Workspace API key |
TWENTY_WRITABLE_ENTITIES |
No | Common CRM objects when omitted | Comma-separated write allowlist; an empty value disables all writes |
TWENTY_ALLOW_DESTRUCTIVE |
No | false |
Enables soft delete and non-dry-run merge; does not control ordinary writes |
TWENTY_ALLOW_INSECURE_HTTP |
No | false |
Allows HTTP for non-local testing; not recommended |
Supported objects
The current allowlist contains 28 standard objects:
Show all objectscompanies
people
opportunities
tasks
notes
attachments
timelineActivities
dashboards
workflows
workflowVersions
workflowRuns
workflowAutomatedTriggers
calendarEvents
calendarChannels
calendarEventParticipants
calendarChannelEventAssociations
messages
messageChannels
messageThreads
messageParticipants
messageChannelMessageAssociations
messageFolders
messageChannelMessageAssociationMessageFolders
noteTargets
taskTargets
connectedAccounts
blocklists
workspaceMembers
Twenty generates APIs from each workspace schema. Custom objects are not yetaccepted by this server's validated entity allowlist; contributions that add asafe discovery mechanism are welcome.
Development and verification
Build the TypeScript server:
npm run build
Run the offline protocol and API-contract smoke test:
npm test
Run the optional live, read-only smoke test after setting credentials:
npm run test:live
The live test lists at most one company and does not modify CRM data.Unlike codex mcp get and claude mcp get, which inspect client registration,this command verifies authenticated access to the Twenty API.
CI runs the build, offline smoke test, and a production-dependency audit onevery pull request.
Troubleshooting
TWENTY_API_KEY and TWENTY_API_URL are required
The MCP process cannot see your credentials. Use an absolute .env path in theclient configuration or launch the client from a shell that exports bothvariables.
getaddrinfo ENOTFOUND your-twenty.example.com
The example URL was not replaced. Twenty Cloud useshttps://api.twenty.com/rest; self-hosted installations use their own domain.
401 or 403
Replace or rotate the API key, then check the role assigned to that key inTwenty. A valid key can still be denied access to specific objects or writes.
404
Check that the base URL ends in /rest, the entity exists in your workspace,and the record UUID is correct.
The client does not show the tools
Run npm run build, confirm the configured dist/index.js path is absolute,and restart the client. Use codex mcp get twenty-crm orclaude mcp get twenty-crm to inspect the registration.
Scope and limitations
- This server targets Twenty's core REST record API, not its metadata API.
- It does not send email. Use an approved Twenty workflow, n8n workflow, or mailintegration for delivery.
- Workspace-specific custom objects are not currently auto-discovered.
- Twenty's native MCP may be a better fit for current cloud workspaces.
- Twenty's API and object schemas may change; deploy a reviewed commit orrelease tag and test it before using sensitive workflows.
Security
Never commit a Twenty API key. If a key appears in a commit, issue, CI log, orterminal transcript, rotate it immediately. See SECURITY.md forthe vulnerability-reporting process.
Contributing
Issues and pull requests are welcome. Read CONTRIBUTING.mdand CODE_OF_CONDUCT.md before proposing a change.
License
This project is available under the MIT License.
Twenty is a product and name of Twenty.com, PBC. This independent project usesthe name only to identify API compatibility. See NOTICE.md.