## Summary This PR implements OAuth 2.0 Dynamic Client Registration (RFC 7591) and OAuth 2.0 Protected Resource Metadata (RFC 9728) support, enabling third-party applications to dynamically register as OAuth clients without manual configuration. ## Key Changes ### OAuth Dynamic Client Registration - **New Controller**: `OAuthRegistrationController` at `POST /oauth/register` endpoint - Validates client metadata according to RFC 7591 specifications - Enforces PKCE-only public client model (no client secrets) - Supports only `authorization_code` grant type and `code` response type - Rate limits registrations to 10 per hour per IP address - Returns `client_id` and registration metadata in response - **Input Validation**: `OAuthRegisterInput` DTO with constraints on: - Client name (max 256 chars) - Redirect URIs (max 20, validated for security) - Grant types, response types, scopes, and auth methods - Logo and client URIs (max 2048 chars) - **Discovery Endpoint Update**: Added `registration_endpoint` to OAuth discovery metadata ### Stale Registration Cleanup - **Cleanup Service**: Automatically removes OAuth-only registrations older than 30 days that have no active installations - **Cron Job**: Runs daily at 02:30 AM UTC with batch processing (100 records per batch) - **CLI Command**: `cron:stale-registration-cleanup` to manually trigger cleanup ### MCP (Model Context Protocol) Authentication - **New Guard**: `McpAuthGuard` implements RFC 9728 compliance - Wraps JWT authentication with proper error responses - Returns `WWW-Authenticate` header with protected resource metadata URL on 401 - Enables OAuth-protected MCP endpoints ### Protected Resource Metadata - **New Endpoint**: `GET /.well-known/oauth-protected-resource` (RFC 9728) - Advertises MCP resource as OAuth-protected - Lists supported scopes and bearer token methods - Enables OAuth clients to discover authorization requirements ### Application Registration Updates - **New Source Type**: `OAUTH_ONLY` enum value for OAuth-only registrations - **Install Service**: Skips artifact installation for OAuth-only apps (no code artifacts) ### Frontend Updates - **Authorization Page**: Support both snake_case (standard OAuth) and camelCase (legacy) query parameters - `client_id` / `clientId` - `code_challenge` / `codeChallenge` - `redirect_uri` / `redirectUrl` ## Implementation Details - **Rate Limiting**: Uses token bucket algorithm with 10 registrations per 3,600,000ms window per IP - **Scope Validation**: Requested scopes are capped to allowed OAuth scopes; defaults to all scopes if not specified - **Redirect URI Validation**: Uses existing `validateRedirectUri` utility for security - **Cache Headers**: Registration responses include `Cache-Control: no-store` and `Pragma: no-cache` - **Batch Processing**: Cleanup operations process 100 records at a time to avoid memory issues - **Grace Period**: 30-day grace period before cleanup to allow time for client activation https://claude.ai/code/session_01PxcuWFFRuXMASMaMGTLYk2 --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: github-actions <github-actions@twenty.com> Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
140 lines
5.6 KiB
Plaintext
140 lines
5.6 KiB
Plaintext
---
|
|
title: MCP Server
|
|
description: Connect AI assistants to your Twenty workspace using the Model Context Protocol.
|
|
---
|
|
|
|
<Warning>
|
|
MCP is currently in **alpha** and is only available on some workspaces. It may not be enabled for your workspace yet.
|
|
</Warning>
|
|
|
|
Twenty exposes an [MCP](https://modelcontextprotocol.io/) server so that AI assistants — Claude Desktop, Claude Code, Cursor, ChatGPT, and others — can read and write your CRM data through natural language.
|
|
|
|
Use your **workspace URL** (the URL you use to access Twenty) as the MCP endpoint. On Twenty Cloud, your workspace URL might be `https://{mycompany}.twenty.com` or a custom domain. The server is available at:
|
|
|
|
| Environment | MCP Endpoint |
|
|
|-------------|-------------|
|
|
| **Cloud** | `https://{your-workspace-url}/mcp` (e.g. `https://mycompany.twenty.com/mcp`) |
|
|
| **Self-Hosted** | `https://{your-domain}/mcp` |
|
|
|
|
## Authentication Methods
|
|
|
|
You have two ways to authenticate your MCP client: **OAuth** (recommended) or **API Key**.
|
|
|
|
### Option A — OAuth (Recommended)
|
|
|
|
With OAuth, your MCP client opens a browser window for you to log in. No secrets are stored in config files, and tokens refresh automatically.
|
|
|
|
<Note>
|
|
OAuth requires an MCP client that supports the [MCP Authorization specification](https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization). Claude Desktop, Claude Code, Cursor, and ChatGPT support it.
|
|
</Note>
|
|
|
|
Add this to your MCP client configuration, replacing `{your-workspace-url}` with your workspace host (e.g. `mycompany.twenty.com`):
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"twenty": {
|
|
"type": "streamable-http",
|
|
"url": "https://{your-workspace-url}/mcp"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
That's it — no API key needed. When the client connects for the first time it will:
|
|
|
|
1. Discover Twenty's OAuth metadata via `/.well-known/oauth-protected-resource` and `/.well-known/oauth-authorization-server`
|
|
2. Register itself as an OAuth client via dynamic client registration (RFC 7591)
|
|
3. Open your browser to authorize access
|
|
4. Receive tokens and connect to the MCP server
|
|
|
|
Subsequent connections reuse the stored tokens and refresh them automatically.
|
|
|
|
### Option B — API Key
|
|
|
|
If your MCP client does not support OAuth, or you prefer static credentials, pass an API key in the `Authorization` header:
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"twenty": {
|
|
"type": "streamable-http",
|
|
"url": "https://{your-workspace-url}/mcp",
|
|
"headers": {
|
|
"Authorization": "Bearer YOUR_API_KEY"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
<Warning>
|
|
Your API key grants access to workspace data. Keep it out of version control and shared dotfiles.
|
|
</Warning>
|
|
|
|
To create an API key, go to **Settings > APIs & Webhooks > + Create key**. See [APIs](/developers/extend/api#create-an-api-key) for details.
|
|
|
|
## Quick Start
|
|
|
|
### 1. Copy the config
|
|
|
|
Go to **Settings > AI > More > MCP Server** in Twenty. Choose your authentication method (OAuth or API Key), copy the JSON snippet (it will already use your workspace URL), and paste it into your MCP client's config file.
|
|
|
|
| Client | Config file location |
|
|
|--------|---------------------|
|
|
| **Claude Desktop** | `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows) |
|
|
| **Claude Code** | `~/.claude.json` (user) or `.mcp.json` (project) |
|
|
| **Cursor** | `.cursor/mcp.json` in your project, or `~/.cursor/mcp.json` globally |
|
|
| **ChatGPT** | Turn on Developer Mode in **Settings > Apps & Connectors > Advanced settings**, then use **Create** in **Settings > Apps & Connectors** to add the MCP server |
|
|
|
|
### 2. Connect
|
|
|
|
Restart your MCP client (or reload the config). If using OAuth you will be redirected to Twenty to authorize access. If using an API key the connection is immediate.
|
|
|
|
### 3. Start using it
|
|
|
|
Ask your AI assistant to interact with your CRM:
|
|
|
|
- *"Show me the 5 most recently created companies"*
|
|
- *"Create a new person named Jane Doe at Acme Corp"*
|
|
- *"Find all open opportunities worth more than $10k"*
|
|
|
|
## Available Tools
|
|
|
|
Once connected, the MCP server exposes tools that mirror the Twenty API. The recommended workflow is:
|
|
|
|
1. **`get_tool_catalog`** — discover all available tools
|
|
2. **`learn_tools`** — get the input schema for specific tools
|
|
3. **`execute_tool`** — run a tool
|
|
|
|
You don't need to remember tool names. Ask your AI assistant what it can do and it will call `get_tool_catalog` automatically.
|
|
|
|
## Permissions
|
|
|
|
MCP connections inherit the permissions of the authenticated user (OAuth) or the role assigned to the API key. To restrict what the MCP server can do:
|
|
|
|
- **OAuth**: The user's workspace role applies.
|
|
- **API Key**: Assign a role to the API key under **Settings > Roles**. See [Permissions](/user-guide/permissions-access/capabilities/permissions).
|
|
|
|
## Self-Hosted Configuration
|
|
|
|
For self-hosted instances, replace `{your-workspace-url}` with your server URL. Make sure `SERVER_URL` in your environment matches the public URL of your Twenty instance — this is used to generate the OAuth discovery metadata.
|
|
|
|
```bash
|
|
SERVER_URL=https://twenty.yourcompany.com
|
|
```
|
|
|
|
The MCP endpoint, OAuth endpoints, and discovery metadata all derive from this value.
|
|
|
|
## Troubleshooting
|
|
|
|
**"Unauthorized" or 401 errors**
|
|
- OAuth: re-authorize by clearing the stored tokens in your MCP client and reconnecting.
|
|
- API Key: verify the key is valid and hasn't expired. Regenerate it if needed.
|
|
|
|
**OAuth flow doesn't open a browser**
|
|
- Ensure your MCP client supports MCP Authorization. Fall back to the API Key method if it doesn't.
|
|
|
|
**Connection timeout**
|
|
- Confirm the MCP endpoint URL is reachable from your machine. For self-hosted instances, check that the server is running and `SERVER_URL` is set correctly.
|