snapshot of https://github.com/twentyhq/twenty.git (main, 2026-09-17; blobs > 131072B omitted)
Some checks failed
App Prod-Parity E2E Dispatch / dispatch (push) Failing after 10s
CD Storybook UI / build (push) Failing after 3m25s
CD Storybook UI / dispatch (push) Has been skipped
CD deploy main / website-changed-files (push) Successful in 18m8s
CI Agent Skills / changed-files-check (push) Successful in 18m9s
CI Create App E2E minimal / changed-files-check (push) Successful in 24s
CI Create App / changed-files-check (push) Successful in 26s
CI Docs / changed-files-check (push) Successful in 26s
CI Emails / changed-files-check (push) Successful in 28s
CI Example App Hello World / changed-files-check (push) Successful in 23s
CI Front / changed-files-check (push) Has been skipped
CI Example App Postcard / changed-files-check (push) Successful in 27s
CI UI / changed-files-check (push) Has been skipped
CI Utils Test / changed-files-check (push) Successful in 45s
CI Twenty Apps / discover (push) Successful in 1m3s
CD deploy main / deploy-main (push) Failing after 3s
CI Agent Skills / agent-skills-validate (push) Has been skipped
CI Create App / create-app-test (lint) (push) Has been skipped
CI Emails / emails-test (push) Has been skipped
CI Front / front-task (lingui:compile) (push) Has been skipped
CI Front / front-task (lint) (push) Has been skipped
CI Example App Postcard / example-app-postcard (push) Has been skipped
CI UI / ui-task (lint) (push) Has been skipped
CI UI / ui-task (pack-size) (push) Has been skipped
CI UI / ui-task (size) (push) Has been skipped
CI UI / ui-task (test) (push) Has been skipped
CI UI / ui-task (typecheck) (push) Has been skipped
CI Utils Test / utils-test (push) Has been skipped
CI Twenty Apps / ${{ matrix.app.name }} (push) Has been skipped
CI Emails / ci-emails-status-check (push) Successful in 2s
CI Example App Hello World / ci-example-app-hello-world-status-check (push) Successful in 2s
CI Example App Postcard / ci-example-app-postcard-status-check (push) Successful in 3s
CI UI / ui-sb-test (push) Has been skipped
CI Utils Test / ci-utils-test-status-check (push) Successful in 2s
CI Twenty Apps / ci-twenty-apps-status-check (push) Successful in 2s
CI UI / ci-ui-status-check (push) Successful in 2s
CI Desktop / desktop (push) Failing after 1m8s
Push docs to Crowdin / Push documentation to Crowdin (push) Failing after 55s
Push translations to Crowdin / Extract and upload translations (push) Failing after 5s
Push website translations to Crowdin / Extract and upload website translations (push) Failing after 5s
CI Create App / create-app-test (test) (push) Has been skipped
CI Create App / create-app-test (typecheck) (push) Has been skipped
CI Docs / docs-lint (push) Has been skipped
CI Example App Hello World / example-app-hello-world (push) Has been skipped
CI Front / front-task (lingui:extract) (push) Has been skipped
CI Front / front-task (test) (push) Has been skipped
CI Front / front-task (typecheck) (push) Has been skipped
CI UI / ui-sb-build (push) Failing after 1m32s
CI Twenty Apps / ${{ matrix.app.name }} (${{ matrix.server-source }}) (push) Has been skipped
CI Agent Skills / agent-skills-publish (push) Has been skipped
CI Create App / ci-create-app-status-check (push) Successful in 2s
CI Agent Skills / agent-skills-remote-source (push) Has been skipped
CI Create App E2E minimal / create-app-e2e-minimal (push) Has been cancelled
CI E2E Main / e2e-test (push) Has been cancelled
CI Front / front-sb-build (push) Has been cancelled
CI Front / front-build (push) Has been cancelled
CI Create App E2E minimal / ci-create-app-e2e-minimal-status-check (push) Has been cancelled
CI E2E Main / ci-e2e-main-status-check (push) Has been cancelled
CI E2E Main / notify-main-ci-failure (push) Has been cancelled
CI E2E Main / qa-scout-comment (push) Has been cancelled
CI Front / front-sb-test (push) Has been cancelled
CI Front / front-sb-screenshots (push) Has been cancelled
CI Front / ci-front-status-check (push) Has been cancelled
DPA Sub-Processor Sync / sync-subprocessors (push) Failing after 3s
AI Catalog Sync / sync-catalog (push) Failing after 3s

This commit is contained in:
upstream-mirror
2026-09-17 23:28:13 +05:00
commit e7da97194a
32688 changed files with 4208681 additions and 0 deletions

View File

@@ -0,0 +1,186 @@
# Retrieve Workspace Data
## Overview
Retrieve the Twenty records needed to answer the user's question, then present them as a useful answer, not as raw API output. Always translate technical fields, timestamps, IDs, and nested structures into readable summaries that help the user scan, compare, and act.
## Retrieval Workflow
Resolve the intended workspace before selecting a Twenty MCP server:
- If the user names a workspace, host, MCP server, or URL, use only the matching Twenty MCP namespace or server.
- If multiple Twenty MCP namespaces or configured servers are available and the intended workspace is ambiguous, ask one concise clarifying question before retrieving data.
- If exactly one Twenty MCP namespace is available and the user did not specify a workspace, use it and mention which workspace or server was used when reporting results.
- If a configured server exists but the matching MCP tools are not visible in the current thread, use the MCP setup troubleshooting workflow in `setup.md` instead of falling back to a different workspace.
- Before querying workspace data, confirm the callable Twenty MCP namespace or server name corresponds to the intended workspace whenever there is any ambiguity.
Use the selected connected Twenty MCP server when it is available:
```text
learn_tools -> execute_tool
```
- Discover object, field, filter, and sort names before querying.
- Retrieve only answer, ordering, and disambiguation fields.
- For "latest", "most recent", or "recent" requests, show the timestamp used for sorting.
- Limit broad lists and state how many records are shown.
- Ask one clarifying question only when tools cannot supply required context.
- If no Twenty MCP tools are available, use the setup workflow in `setup.md`; do not invent workspace data.
## Workspace Origin
Record links need a workspace origin, such as `https://example.twenty.com` or `http://workspace.localhost:3001`.
- If the user provides the workspace URL, use that origin after removing any trailing `/mcp`.
- If the selected MCP server URL is visible, derive the origin from it by removing the trailing `/mcp`.
- If the selected MCP server is configured locally but the URL is not in context, inspect that exact server configuration before formatting linked records.
- If the origin is still unknown, do not invent a hostname. Explain that direct record links need the workspace URL.
## Response Shape
Start with the answer or count, then show the records in the clearest compact shape:
- For one record, use a short labelled summary.
- For two to ten comparable records, use a Markdown table.
- For larger sets, show the most relevant rows first, mention the total, and offer the next useful filter or page only when needed.
- For nested records, summarize the important nested values instead of dumping JSON.
- When comparing records across workspaces, prefer one combined table with a `Workspace` column if it improves scanning. Use separate sections only when each workspace needs different columns.
Use English labels and prose. Keep user-provided names, record values, emails, URLs, and proper nouns unchanged.
## Record Links
Link records back to their original Twenty context whenever the workspace origin and record identity are known.
- Build record links with the Twenty show-page path: `/object/:objectNameSingular/:objectRecordId`.
- For absolute links, combine the workspace origin with that path: `{workspaceOrigin}/object/{objectNameSingular}/{recordId}`.
- Preserve the workspace scheme and port for local workspaces, for example `http://workspace.localhost:3001/object/person/record-id`.
- Use `recordReferences` from MCP responses when available to get `objectNameSingular`, `recordId`, and `displayName`.
- If `recordReferences` is missing, use the record's `id` and the object name from the tool that returned it.
- If `recordReferences` and workspace origin are both available, the first record-name column or record heading MUST link the display name. Do not output unlinked record names in that case.
- Prefer linking the record display name in tables and summaries instead of adding a raw ID column.
- When showing records from multiple workspaces, generate links with each record's own workspace origin.
- If the workspace origin is unknown, do not invent a hostname. Add a compact `Record` column with the object name and record ID, or say that direct links need the workspace URL.
## Visual Identifiers
Add a small visual identifier next to records when it improves scanning and the source data provides one.
- Twenty AI chat currently renders Markdown with `react-markdown` and `remark-gfm`, without raw HTML rendering. Do not rely on HTML such as `<img width="16" height="16">`.
- Use standard Markdown image syntax only: `![alt](image-url)`.
- The current Twenty AI chat image CSS preserves intrinsic image size with `height: auto` and only caps `max-width`. Do not place full-size photos or large avatars in tables unless the image URL is already a small thumbnail.
- Prefer the record's own `avatarUrl`, logo, or image field when present and non-empty.
- For People, show the person's avatar or profile image only when the URL is known to be a small thumbnail. If there is no suitable image, keep the linked name and do not generate fake headshots.
- For Companies, Workspaces, domains, or records mainly identified by an email/domain, prefer a small favicon or logo when the record provides a safe public website, domain, or avatar URL.
- Derive a domain from `emails.primaryEmail`, `website`, `domainName`, or equivalent fields only for display or favicon lookup; never expose private internal domains as external image requests.
- If image sizing is not reliable, use a text `Domain`, `Company`, or `Source` column instead of an image.
- Always include readable text next to the image. Never make an image the only record label.
- If no trustworthy image or favicon source is available, omit the image instead of showing a broken placeholder.
- Avoid adding images to very large result sets unless the user asks for a visual scan.
- Avoid stacking multiple visual tokens before a record name, such as favicon plus emoji plus linked text. Redundant icons make table alignment harder to scan.
## Dates And Times
Never expose ISO/RFC3339 timestamps as the main date display.
- Parse common technical formats such as `2026-05-05T09:43:18.123Z`, `2026-05-05T09:43:18+02:00`, Unix seconds, and Unix milliseconds.
- Convert instants with `Z` or an explicit offset to the user's timezone when known. If timezone is unknown, keep the source timezone or ask only when it changes the meaning.
- Preserve date-only values as dates. Do not shift date-only values across timezones.
- Display absolute dates. Use relative words such as "today", "yesterday", or "last week" only as a supplement when helpful.
- Include the year unless it is truly redundant in a small same-year table.
- Show seconds and milliseconds only when they matter for debugging, audit logs, or ordering events with near-identical times.
Examples:
- Timestamp: `2026-05-05T09:43:18.123Z` -> `May 5, 2026, 11:43 AM`
- Date-only value: `2026-05-05` -> `May 5, 2026`
If the exact raw timestamp is relevant, put it after the readable value:
```text
Created: May 5, 2026, 11:43 AM (raw: 2026-05-05T09:43:18.123Z)
```
## Field Labels
Convert raw field names into user-facing labels:
- `createdAt` -> `Created`
- `updatedAt` -> `Last updated`
- `deletedAt` -> `Deleted`
- `createdBy` -> `Created by`
- `workspaceMemberId` -> `Workspace member`
- `opportunityStage` -> `Opportunity stage`
Prefer the label users see in Twenty when it is available from metadata. Otherwise, split camelCase, snake_case, and kebab-case into normal words.
## Value Formatting
Format values by meaning:
- Empty or null: `Not set`, or omit if the field is irrelevant.
- Booleans: `Yes` / `No`.
- Money: include currency and grouping, for example `EUR 12,450` or `USD 12,450` based on the record currency.
- Percentages: use `%`, round only enough to stay meaningful.
- URLs and emails: make them clickable Markdown links when useful.
- IDs and UUIDs: hide by default unless the user asks for identifiers, deduplication, debugging, or exact references.
- Arrays: show the count and the most important names, not the full serialized array.
## Record Ordering
When the user asks for "latest", "recent", or "last records":
- State which date field was used when it is not obvious, for example `sorted by Last updated`.
- Prefer `updatedAt` for "recent activity" and `createdAt` for "newest records" unless the user's wording or object semantics points to another date.
- Display the chosen date column in readable form.
- If multiple records share the same date, keep a deterministic secondary order such as name or ID.
## Table Alignment
Make tables easy to scan before making them visually decorative.
- Use Markdown alignment markers intentionally: text columns left-aligned (`:---`), numeric money/count columns right-aligned (`---:`), and short status columns centered only when that actually improves scanning (`:---:`).
- Keep record names on a stable left edge. If rows have favicons, avatars, or logos, prefer a dedicated narrow `Icon`, `Logo`, or `Avatar` column followed by a linked record-name column.
- If the table is compact and the image is known to be consistently small, it is acceptable to put `![alt](url) [Name](record-url)` in one cell. Do not also add emoji or extra symbols before the name.
- Keep fixed-format fields such as `Created`, `Updated`, `Amount`, and `Source` to the right of variable-width fields such as `Name`, `Company`, `Person`, and `Domain`.
- Use a consistent date format within a table so rows line up visually, for example `May 5, 2026, 11:43 AM` or `May 5, 11:43`.
- Prefer natural links over extra link columns: link the record name to Twenty, and link the domain or email only when that external destination is useful.
- Avoid raw ID columns in normal user-facing tables. IDs are long, visually dominant, and destroy alignment unless the user asks for them.
## Markdown Patterns
Use a compact table for comparable records:
```markdown
I found 5 recent opportunities, sorted by last updated date.
| Logo | Name | Stage | Amount | Last updated |
| :---: | :--- | :--- | ---: | :--- |
| ![Acme icon](https://example.com/favicon.ico) | [Acme renewal](https://example.twenty.com/object/opportunity/record-id-1) | Negotiation | EUR 12,450 | May 5, 2026, 11:43 AM |
| ![Globex icon](https://globex.example/favicon.ico) | [Globex expansion](https://example.twenty.com/object/opportunity/record-id-2) | Discovery | EUR 8,000 | May 4, 2026, 4:10 PM |
```
For recent companies with `recordReferences`, link the company name:
```markdown
I found 5 recent companies, sorted by Created.
| Company | Domain | Created |
| :--- | :--- | :--- |
| [Acme](https://workspace.example/object/company/00000000-0000-0000-0000-000000000001) | [acme.example](https://acme.example) | May 5, 2026, 11:43 AM |
```
Use a labelled block for one important record:
```markdown
**[Acme renewal](https://example.twenty.com/object/opportunity/record-id-1)**
- Stage: Negotiation
- Amount: EUR 12,450
- Next action: Not set
- Last updated: May 5, 2026, 11:43 AM
```
## Raw Data Exceptions
Show raw JSON, raw timestamps, internal IDs, or full nested objects only when the user asks for debugging, export, exact API payloads, schema inspection, or reproducible commands. Even then, put a readable summary before the raw block.

View File

@@ -0,0 +1,158 @@
# Set Up Twenty MCP
## Overview
Use this reference to configure a workspace-specific Twenty MCP endpoint. The skill must not assume a fixed workspace domain; collect the user's workspace URL first, normalize it to an MCP URL, then configure and authenticate the MCP client of the agent in use.
Self-hosted instances are first-class targets. Any Twenty workspace works: managed cloud, self-hosted on a custom domain, or a local instance over HTTP. Never require a `twenty.com` workspace.
## Required User Input
Ask for the workspace URL or host if it is missing. Do not invent or reuse a private default domain.
Accept any of these forms:
```text
myworkspace.twenty.com
myworkspace.customdomain.com
myworkspace.localhost:3001
https://myworkspace.twenty.com
https://myworkspace.customdomain.com/mcp
http://myworkspace.localhost:3001/mcp
```
Optional inputs:
- MCP server name. Default to a workspace-derived name in the form `twenty-<host-without-tld>`, for example `acme.example.com` becomes `twenty-acme-example`.
- Whether to force CLI OAuth login immediately. Default to no when the agent opens OAuth on its own after the MCP server is added. Only force login if the automatic OAuth window does not appear.
## URL Normalization
Normalize workspace input as follows:
- If the input already starts with `http://` or `https://`, preserve that scheme.
- If the input has no scheme and is `localhost`, `127.x.x.x`, `[::1]`, `*.localhost`, or `*.localhost:<port>`, use `http://`.
- If the input has no scheme and is any other host, use `https://`.
- Strip any trailing `/` before looking at the path, so `https://acme.example.com/` and `https://acme.example.com/mcp/` normalize the same as their unslashed forms.
- If the final URL does not end with `/mcp`, append `/mcp`.
Examples:
```text
myworkspace.twenty.com -> https://myworkspace.twenty.com/mcp name: twenty-myworkspace
acme.example.com -> https://acme.example.com/mcp name: twenty-acme-example
myworkspace.customdomain.com -> https://myworkspace.customdomain.com/mcp name: twenty-myworkspace-customdomain
myworkspace.localhost:3001 -> http://myworkspace.localhost:3001/mcp name: twenty-myworkspace-localhost-3001
https://acme.example.com/ -> https://acme.example.com/mcp name: twenty-acme-example
https://acme.example.com/mcp/ -> https://acme.example.com/mcp name: twenty-acme-example
```
A trailing slash that survives normalization produces `//mcp` or `/mcp//mcp`, neither of which is the registered endpoint.
## Setup Per Agent
The Twenty MCP server uses streamable HTTP transport with OAuth authentication. Configure it with the agent the user is actually running.
### Codex
```bash
codex mcp add twenty-myworkspace --url https://myworkspace.twenty.com/mcp
codex mcp login twenty-myworkspace
```
For a local instance:
```bash
codex mcp add twenty-local --url http://myworkspace.localhost:3001/mcp
codex mcp login twenty-local
```
OAuth guards specific to this client:
- Do not pass `--login` to `codex mcp add`. It is deprecated.
- Codex can open OAuth on its own when it sees the new MCP server. Run `codex mcp login <server-name>` only if that window does not appear.
- Do not manually run `open <authorization-url>` for an OAuth URL printed by `codex mcp add` unless the user confirms no browser tab opened. Opening the same authorization URL twice creates two callback tabs with the same `state` and different one-time `code` values.
The Twenty marketplace plugin for this client bundles a `setup-mcp.sh` helper that automates URL normalization, server naming, and this add-then-login sequence.
### Claude Code
```bash
claude mcp add --transport http twenty-myworkspace https://myworkspace.twenty.com/mcp
```
For a local instance:
```bash
claude mcp add --transport http twenty-local http://myworkspace.localhost:3001/mcp
```
Claude Code prompts for OAuth when the server is first used. `/mcp` inside a session shows connection and authentication status, and re-runs the OAuth flow on demand.
### Cursor
Add the server to `.cursor/mcp.json` in the project, or `~/.cursor/mcp.json` for every project:
```json
{
"mcpServers": {
"twenty-myworkspace": {
"url": "https://myworkspace.twenty.com/mcp"
}
}
}
```
Cursor opens the OAuth flow when the server is enabled in its MCP settings.
### Other MCP Clients
Any client that supports streamable HTTP MCP servers with OAuth works. Configure a server entry pointing at the normalized MCP URL:
```json
{
"mcpServers": {
"twenty-myworkspace": {
"url": "https://myworkspace.twenty.com/mcp"
}
}
}
```
If the client cannot do OAuth, configure bearer headers in the user's private MCP client config only, never in shared or committed files.
## Validation
After setup, verify the server is available with the client's own inspection command (`codex mcp get <server-name>`, `claude mcp list`, or the equivalent), or by listing available tools in a fresh session.
When connected, use the Twenty MCP discovery flow:
```text
learn_tools -> execute_tool
```
## Troubleshooting
### Debugging Workflow
Use this workflow when the user reports missing tools, unexpected workspace data, authentication failures, or suspects the agent queried the wrong Twenty workspace.
1. Identify the intended workspace URL or host from the user's request, using Required User Input when it is missing.
2. Normalize the intended workspace to its MCP URL with the URL Normalization rules above.
3. Inspect the configured Twenty MCP servers and compare their URLs to the intended normalized URL (`codex mcp list`, `claude mcp list`, or the client's MCP config file).
4. If no configured server points at the intended MCP URL, configure one with a workspace-specific name using the per-agent setup above.
5. If the server exists but authentication fails, or MCP startup reports `Auth required`, run the client's OAuth login for that exact server.
6. If the configured server is correct and authenticated but its tools are not visible in the current session, explain that the session may have loaded tools before the server was added or authenticated. Ask the user to reload the agent or start a new session so it picks up the updated MCP config.
7. Before querying workspace data, confirm the callable Twenty MCP namespace or tool name corresponds to the intended server. If only a different Twenty server is callable, do not use it as a fallback unless the user explicitly asks.
8. When reporting results, state which workspace URL or MCP server was used if there was any ambiguity.
### Common Failure Modes
- If OAuth fails for a self-hosted workspace, check that `SERVER_URL` matches the public workspace origin. OAuth metadata and MCP URLs derive from that value.
- If a local workspace fails over HTTPS, use `http://` explicitly per the localhost normalization rule.
- If the server name already exists, replace that entry with the new URL, or pick a different name to keep several workspaces side by side.
### Safety Rules
- Do not put API keys in skill files. Prefer OAuth login. If an MCP client does not support OAuth, configure bearer headers only in the user's private MCP client config.
- Do not inspect or manually extract OAuth tokens as a workaround.