# io.usefulapi/twenty (remote · twenty.usefulapi.io)

Read people, companies, opportunities, notes and tasks; create and update records in Twenty CRM.

- Trust score: 68/100 (medium)
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-03

## Components

- remote · `twenty.usefulapi.io`: 68/100 (this document), [markdown](https://verifymcp.io/servers/io-usefulapi-twenty/twenty.md), [page](https://verifymcp.io/servers/io-usefulapi-twenty/twenty)

## Channel facts

- Endpoint: `https://twenty.usefulapi.io/mcp`
- Transports: `streamable-http`
- Auth: `none`
- Version: `1.0.0`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-08-03.

- **Endpoint Security**: 78/100
  - The endpoint's TLS certificate is valid, in date, and uses a strong key.
  - Authorisation is enforced on tool calls, advertised via RFC 9728 protected-resource metadata. Discovery is public, which costs nothing: no tool can be invoked without a token.
  - HTTPS not yet verified: we couldn't determine whether a plaintext access path exists.
  - HSTS check failed: the Strict-Transport-Security header is absent.
  - DNSSEC check failed: this domain isn't protected by DNSSEC.
  - The authorisation server offers only Dynamic Client Registration (RFC 7591), which MCP 2026-07-28 deprecated in favour of Client ID Metadata Documents.
- **Transport & Reachability**: 100/100
  - Verified streamable-http transport via a live MCP handshake.
- **Schema Quality & AI Usability**: 68/100
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 3156 tokens (~157/item across 20 items; 20 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 3/100
  - Stability observed for 1 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 100/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 100% of tool parameters carry a description.
- **Capabilities**: 60/100
  - Spec-recency check failed: implements MCP spec 2025-06-18; the latest is 2026-07-28.

## Install

### Claude

```bash
claude mcp add --transport http io-usefulapi-twenty https://twenty.usefulapi.io/mcp
```

### Codex

```toml
[mcp_servers.io-usefulapi-twenty]
url = "https://twenty.usefulapi.io/mcp"
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "io-usefulapi-twenty": {
      "type": "remote",
      "url": "https://twenty.usefulapi.io/mcp",
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add io-usefulapi-twenty --url https://twenty.usefulapi.io/mcp --transport streamable-http
```

### Hermes

```yaml
mcp_servers:
  io-usefulapi-twenty:
    url: "https://twenty.usefulapi.io/mcp"
```

### Other

```json
{
  "mcpServers": {
    "io-usefulapi-twenty": {
      "type": "http",
      "url": "https://twenty.usefulapi.io/mcp"
    }
  }
}
```

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-08-03 (score 68, 0)

- [functional improvement] Stability: unverified → 0.03

### 2026-08-02 (score 68, +50)

- [security improvement] Authorization: unverified → pass
- [security improvement] Transport: fail → pass
- [security] First check of Authorization: partial
- [functional regression] MCP protocol: unverified → fail
- [functional improvement] Tool coverage: unverified → 100
- [functional] First check of Schema quality: excellent
- [functional] First check of Schema quality: fail
- [functional] First check of Tool coverage: 100
- [functional] First check of Schema quality: fail

### 2026-08-01 (score 18)

First indexed and scored.

## MCP tools (20)

### `twenty_list_metadata_objects` (~50 tokens)

List metadata objects

List all objects (standard + custom) and their fields from the Twenty schema — use this to discover custom objects/fields and valid field names. Twenty REST: GET /rest/metadata/objects.

### `twenty_list_people` (~243 tokens)

List people

List/filter people (contacts). Supports cursor pagination, raw filter/order_by, and relation depth. Twenty REST: GET /rest/people.

Input parameters:

- `depth` (integer): How deep to hydrate related records: 0, 1, or 2.
- `ending_before` (string): Pagination cursor — return records before this cursor (from a previous page's pageInfo).
- `filter` (string): Raw Twenty filter string, passed verbatim as ?filter=. Syntax: field[comparator]:value, e.g. `employees[gte]:100` or `stage[eq]:"MEETING"`. Comparators: eq, neq, gt, gte, lt, lte, in, is, like, ilike…
- `limit` (integer): Results per page (1-60, default 20 — Twenty caps at 60).
- `order_by` (string): Raw Twenty ordering string, passed verbatim as ?order_by=, e.g. `createdAt[DescNullsLast]`.
- `starting_after` (string): Pagination cursor — return records after this cursor (from a previous page's pageInfo).

### `twenty_get_person` (~63 tokens)

Get person

Get a single person (contact) by id. Twenty REST: GET /rest/people/{id}.

Input parameters:

- `depth` (integer): How deep to hydrate related records: 0, 1, or 2.
- `id` (string, required): The person id.

### `twenty_list_companies` (~242 tokens)

List companies

List/filter companies. Supports cursor pagination, raw filter/order_by, and relation depth. Twenty REST: GET /rest/companies.

Input parameters:

- `depth` (integer): How deep to hydrate related records: 0, 1, or 2.
- `ending_before` (string): Pagination cursor — return records before this cursor (from a previous page's pageInfo).
- `filter` (string): Raw Twenty filter string, passed verbatim as ?filter=. Syntax: field[comparator]:value, e.g. `employees[gte]:100` or `stage[eq]:"MEETING"`. Comparators: eq, neq, gt, gte, lt, lte, in, is, like, ilike…
- `limit` (integer): Results per page (1-60, default 20 — Twenty caps at 60).
- `order_by` (string): Raw Twenty ordering string, passed verbatim as ?order_by=, e.g. `createdAt[DescNullsLast]`.
- `starting_after` (string): Pagination cursor — return records after this cursor (from a previous page's pageInfo).

### `twenty_get_company` (~60 tokens)

Get company

Get a single company by id. Twenty REST: GET /rest/companies/{id}.

Input parameters:

- `depth` (integer): How deep to hydrate related records: 0, 1, or 2.
- `id` (string, required): The company id.

### `twenty_list_opportunities` (~245 tokens)

List opportunities

List/filter opportunities (deals). Supports cursor pagination, raw filter/order_by, and relation depth. Twenty REST: GET /rest/opportunities.

Input parameters:

- `depth` (integer): How deep to hydrate related records: 0, 1, or 2.
- `ending_before` (string): Pagination cursor — return records before this cursor (from a previous page's pageInfo).
- `filter` (string): Raw Twenty filter string, passed verbatim as ?filter=. Syntax: field[comparator]:value, e.g. `employees[gte]:100` or `stage[eq]:"MEETING"`. Comparators: eq, neq, gt, gte, lt, lte, in, is, like, ilike…
- `limit` (integer): Results per page (1-60, default 20 — Twenty caps at 60).
- `order_by` (string): Raw Twenty ordering string, passed verbatim as ?order_by=, e.g. `createdAt[DescNullsLast]`.
- `starting_after` (string): Pagination cursor — return records after this cursor (from a previous page's pageInfo).

### `twenty_get_opportunity` (~61 tokens)

Get opportunity

Get a single opportunity by id. Twenty REST: GET /rest/opportunities/{id}.

Input parameters:

- `depth` (integer): How deep to hydrate related records: 0, 1, or 2.
- `id` (string, required): The opportunity id.

### `twenty_list_notes` (~241 tokens)

List notes

List/filter notes. Supports cursor pagination, raw filter/order_by, and relation depth. Twenty REST: GET /rest/notes.

Input parameters:

- `depth` (integer): How deep to hydrate related records: 0, 1, or 2.
- `ending_before` (string): Pagination cursor — return records before this cursor (from a previous page's pageInfo).
- `filter` (string): Raw Twenty filter string, passed verbatim as ?filter=. Syntax: field[comparator]:value, e.g. `employees[gte]:100` or `stage[eq]:"MEETING"`. Comparators: eq, neq, gt, gte, lt, lte, in, is, like, ilike…
- `limit` (integer): Results per page (1-60, default 20 — Twenty caps at 60).
- `order_by` (string): Raw Twenty ordering string, passed verbatim as ?order_by=, e.g. `createdAt[DescNullsLast]`.
- `starting_after` (string): Pagination cursor — return records after this cursor (from a previous page's pageInfo).

### `twenty_get_note` (~60 tokens)

Get note

Get a single note by id. Twenty REST: GET /rest/notes/{id}.

Input parameters:

- `depth` (integer): How deep to hydrate related records: 0, 1, or 2.
- `id` (string, required): The note id.

### `twenty_list_tasks` (~240 tokens)

List tasks

List/filter tasks. Supports cursor pagination, raw filter/order_by, and relation depth. Twenty REST: GET /rest/tasks.

Input parameters:

- `depth` (integer): How deep to hydrate related records: 0, 1, or 2.
- `ending_before` (string): Pagination cursor — return records before this cursor (from a previous page's pageInfo).
- `filter` (string): Raw Twenty filter string, passed verbatim as ?filter=. Syntax: field[comparator]:value, e.g. `employees[gte]:100` or `stage[eq]:"MEETING"`. Comparators: eq, neq, gt, gte, lt, lte, in, is, like, ilike…
- `limit` (integer): Results per page (1-60, default 20 — Twenty caps at 60).
- `order_by` (string): Raw Twenty ordering string, passed verbatim as ?order_by=, e.g. `createdAt[DescNullsLast]`.
- `starting_after` (string): Pagination cursor — return records after this cursor (from a previous page's pageInfo).

### `twenty_get_task` (~59 tokens)

Get task

Get a single task by id. Twenty REST: GET /rest/tasks/{id}.

Input parameters:

- `depth` (integer): How deep to hydrate related records: 0, 1, or 2.
- `id` (string, required): The task id.

### `twenty_create_person` (~222 tokens)

Create person

Create a new person (contact). All fields optional; firstName/lastName combine into name:{firstName,lastName}. Twenty REST: POST /rest/people.

Input parameters:

- `city` (string): City.
- `companyId` (string): Id of the company to link this person to.
- `extra` (object): Passthrough object of additional/custom fields merged into the request body verbatim.
- `firstName` (string): First name (combined into name:{firstName,lastName}).
- `jobTitle` (string): Job title.
- `lastName` (string): Last name (combined into name:{firstName,lastName}).
- `linkedinUrl` (string): LinkedIn URL (sent as linkedinLink:{primaryLinkUrl}).
- `primaryEmail` (string): Primary email address (sent as emails:{primaryEmail}).
- `primaryPhone` (string): Primary phone number (sent as phones:{primaryPhoneNumber}).
- `xUrl` (string): X/Twitter URL (sent as xLink:{primaryLinkUrl}).

### `twenty_update_person` (~223 tokens)

Update person

Update fields on an existing person. Only provided fields change. Twenty REST: PATCH /rest/people/{id}.

Input parameters:

- `city` (string): City.
- `companyId` (string): Id of the company to link this person to.
- `extra` (object): Passthrough object of additional/custom fields merged into the request body verbatim.
- `firstName` (string): First name (combined into name:{firstName,lastName}).
- `id` (string, required): The person id to update.
- `jobTitle` (string): Job title.
- `lastName` (string): Last name (combined into name:{firstName,lastName}).
- `linkedinUrl` (string): LinkedIn URL (sent as linkedinLink:{primaryLinkUrl}).
- `primaryEmail` (string): Primary email address (sent as emails:{primaryEmail}).
- `primaryPhone` (string): Primary phone number (sent as phones:{primaryPhoneNumber}).
- `xUrl` (string): X/Twitter URL (sent as xLink:{primaryLinkUrl}).

### `twenty_create_company` (~172 tokens)

Create company

Create a new company. `name` is required. Twenty REST: POST /rest/companies.

Input parameters:

- `addressCity` (string): City (sent as address:{addressCity}).
- `domainName` (string): Primary domain / website URL (sent as domainName:{primaryLinkUrl}).
- `employees` (number): Employee count.
- `extra` (object): Passthrough object of additional/custom fields merged into the request body verbatim.
- `idealCustomerProfile` (boolean): Whether this company matches the ideal customer profile.
- `linkedinUrl` (string): LinkedIn URL (sent as linkedinLink:{primaryLinkUrl}).
- `name` (string, required): The company name (required).
- `xUrl` (string): X/Twitter URL (sent as xLink:{primaryLinkUrl}).

### `twenty_update_company` (~185 tokens)

Update company

Update fields on an existing company. Only provided fields change. Twenty REST: PATCH /rest/companies/{id}.

Input parameters:

- `addressCity` (string): City (sent as address:{addressCity}).
- `domainName` (string): Primary domain / website URL (sent as domainName:{primaryLinkUrl}).
- `employees` (number): Employee count.
- `extra` (object): Passthrough object of additional/custom fields merged into the request body verbatim.
- `id` (string, required): The company id to update.
- `idealCustomerProfile` (boolean): Whether this company matches the ideal customer profile.
- `linkedinUrl` (string): LinkedIn URL (sent as linkedinLink:{primaryLinkUrl}).
- `name` (string): The company name.
- `xUrl` (string): X/Twitter URL (sent as xLink:{primaryLinkUrl}).

### `twenty_create_opportunity` (~219 tokens)

Create opportunity

Create a new opportunity (deal). `name` is required; amountMicros combines with currencyCode into amount:{amountMicros,currencyCode}. Twenty REST: POST /rest/opportunities.

Input parameters:

- `amountMicros` (number): Opportunity amount in micros (× 1,000,000). Sent as amount:{amountMicros,currencyCode}.
- `closeDate` (string): Expected close date (ISO 8601).
- `companyId` (string): Id of the associated company.
- `currencyCode` (string): Currency code for the amount (default USD; only sent when amountMicros is provided).
- `extra` (object): Passthrough object of additional/custom fields merged into the request body verbatim.
- `name` (string, required): The opportunity name (required).
- `pointOfContactId` (string): Id of the point-of-contact person.
- `stage` (string): Pipeline stage — e.g. SCREENING, MEETING, PROPOSAL, NEGOTIATION, CUSTOMER (custom pipelines vary).

### `twenty_update_opportunity` (~213 tokens)

Update opportunity

Update fields on an existing opportunity. Only provided fields change. Twenty REST: PATCH /rest/opportunities/{id}.

Input parameters:

- `amountMicros` (number): Opportunity amount in micros (× 1,000,000). Sent as amount:{amountMicros,currencyCode}.
- `closeDate` (string): Expected close date (ISO 8601).
- `companyId` (string): Id of the associated company.
- `currencyCode` (string): Currency code for the amount (default USD; only sent when amountMicros is provided).
- `extra` (object): Passthrough object of additional/custom fields merged into the request body verbatim.
- `id` (string, required): The opportunity id to update.
- `name` (string): The opportunity name.
- `pointOfContactId` (string): Id of the point-of-contact person.
- `stage` (string): Pipeline stage — e.g. SCREENING, MEETING, PROPOSAL, NEGOTIATION, CUSTOMER (custom pipelines vary).

### `twenty_create_note` (~94 tokens)

Create note

Create a note. `title` is required; `body` holds the note content. (Attaching to records via noteTargets is out of scope.) Twenty REST: POST /rest/notes.

Input parameters:

- `body` (string): The note content/body.
- `extra` (object): Passthrough object of additional/custom fields merged into the request body verbatim.
- `title` (string, required): The note title (required).

### `twenty_create_task` (~125 tokens)

Create task

Create a task. `title` is required. Twenty REST: POST /rest/tasks.

Input parameters:

- `assigneeId` (string): Id of the workspace member assigned to the task.
- `body` (string): Task body / description.
- `dueAt` (string): Due date/time (ISO 8601).
- `extra` (object): Passthrough object of additional/custom fields merged into the request body verbatim.
- `status` (string): Task status — e.g. TODO, IN_PROGRESS, DONE.
- `title` (string, required): The task title (required).

### `twenty_update_task` (~139 tokens)

Update task

Update fields on an existing task. Only provided fields change. Twenty REST: PATCH /rest/tasks/{id}.

Input parameters:

- `assigneeId` (string): Id of the workspace member assigned to the task.
- `body` (string): Task body / description.
- `dueAt` (string): Due date/time (ISO 8601).
- `extra` (object): Passthrough object of additional/custom fields merged into the request body verbatim.
- `id` (string, required): The task id to update.
- `status` (string): Task status — e.g. TODO, IN_PROGRESS, DONE.
- `title` (string): The task title.

## Diagnostics

Captured diagnostic sections: TLS, DNSSEC, Authorisation, Transports. The full working is on the page: https://verifymcp.io/servers/io-usefulapi-twenty/twenty#diagnostics

## Score history

- 2026-08-03: 68
- 2026-08-02: 68
- 2026-08-01: 18

## Links

- Remote endpoint: https://twenty.usefulapi.io/mcp
- Repository: https://github.com/m190/usefulapi-mcp
- Changelog RSS feed: https://verifymcp.io/servers/io-usefulapi-twenty/twenty/changelog.xml
- Changelog JSON feed: https://verifymcp.io/servers/io-usefulapi-twenty/twenty/changelog.json
- HTML version of this page: https://verifymcp.io/servers/io-usefulapi-twenty/twenty
