Connectors Module
MCP connector instances, credentials, and provider registry
The Connectors module manages per-org MCP integration instances and the global connector provider catalog. Source: packages/server/src/modules/connectors/ and packages/server/src/modules/connector-providers/.
Connectors REST Endpoints
All endpoints are prefixed with /api/v1/connectors and require ClerkAuthGuard.
| Method | Path | Description |
|---|---|---|
| GET | /connectors | List org's connector instances |
| POST | /connectors | Create a connector instance |
| GET | /connectors/:instanceId/credentials | Get credentials for an instance |
| POST | /connectors/:instanceId/credentials | Update credentials |
| DELETE | /connectors/:instanceId | Delete a connector instance |
Connector Providers REST Endpoints
| Method | Path | Guards | Description |
|---|---|---|---|
| GET | /connector-providers | None | List enabled providers (public) |
| PUT | /connector-providers | ClerkAuthGuard | Create or update a provider (admin) |
| DELETE | /connector-providers/:serverId | ClerkAuthGuard | Delete a provider (admin) |
Connectors Service (services/connectors.service.ts)
list(orgId, userId?)
Returns the org's connector instances. The userId param applies for per-user auth connectors (e.g. Microsoft 365):
- For
perUserAuth: trueproviders: returns only instances belonging to the requesting user. - For org-shared providers: returns all org-level instances.
Hosting override logic:
REMOTE_OAUTHandNONEconnectors:hostingis set toLOCALin the response (the desktop manages these locally).- All others:
hostingisCLOUD(server manages credentials).
create(orgId, userId, dto)
Creates a new MCPConfig record. Input:
| Field | Required | Description |
|---|---|---|
serverId | Yes | Provider ID (e.g. "notion") |
instanceId | Yes | Client-generated unique ID |
label | Yes | Human-readable name |
hosting | No | CLOUD / LOCAL |
transport | No | STDIO / SSE / HTTP |
config | No | Non-sensitive config JSON |
credentials | No | Initial credentials JSON |
If the provider has perUserAuth: true, userId is stored on the record (per-user scoping). Otherwise userId is null (org-shared).
Uniqueness constraint: (orgId, userId, instanceId).
getCredentials(orgId, instanceId, userId?)
Fetches the credentials JSON for a connector. For per-user connectors, userId must match the record's user.
updateCredentials(orgId, instanceId, credentials, userId)
Replaces the credentials JSON and updates status to CONNECTED and lastUsedAt to now.
Connector Providers Service (services/connector-providers.service.ts)
listPublic()
Returns all providers where enabled: true, with sensitive fields stripped:
clientSecretis not included.authParamswith secrets are excluded.
Returned fields: serverId, displayName, description, iconUrl, category, authMode, perUserAuth, requiresAdminConsent, mcpTransport.
getOAuthConfig(serverId)
Internal method (not exposed via REST). Returns the full provider record including clientId, clientSecret, authUrl, tokenUrl, scopes. Used by MCPOAuthService.
getMCPConfig(serverId)
Returns the connection config for starting an MCP session:
{
command?: string; // For STDIO transport
args?: string[];
url?: string; // For HTTP/SSE transport
transport: 'stdio' | 'sse' | 'http';
}MCPConfig Schema
| Field | Type | Description |
|---|---|---|
id | string | Primary key |
orgId | string | Owning organisation |
userId | string? | Owning user (null = org-shared) |
serverId | string | Provider slug |
instanceId | string | Unique instance ID |
label | string | Human-readable name |
hosting | CLOUD | LOCAL | Where the MCP process runs |
transport | STDIO | SSE | HTTP | Connection transport |
config | JSON? | Non-sensitive config |
credentials | JSON? | Encrypted OAuth tokens or API key |
status | string | CONNECTED | DISCONNECTED | CONNECTING | ERROR |
lastError | string? | Last error message |
lastUsedAt | DateTime? | Last usage |
MCP OAuth Module
Server-mediated OAuth for integrations like Notion, Google Drive, and ClickUp. Source: packages/server/src/modules/mcp-oauth/.
OAuth Endpoints
| Method | Path | Guards | Description |
|---|---|---|---|
| POST | /mcp-oauth/start | ClerkAuthGuard | Start OAuth flow → get authUrl |
| GET | /mcp-oauth/callback | None | OAuth provider callback |
| POST | /mcp-oauth/refresh | None | Refresh an expired token |
| GET | /mcp-oauth/poll | None | Poll for credentials after callback |
OAuth Flow
Client Server OAuth Provider
│ │ │
├─POST /start───▶│ │
│◀─── authUrl ───┤ │
│ │ │
│ (user opens browser) │
│ │◀─ GET /callback ─┤
│ ├─ exchange code ──▶│
│ │◀─── tokens ───────┤
│ │ (store credentials)
│ │ │
├─GET /poll ────▶│ │
│◀─ credentials ─┤ │POST /mcp-oauth/start: Client sends{ serverId, instanceId, state }. Server looks up provider'sauthUrl+clientId+scopes, constructs the full URL, and returns it.- Client opens URL in browser. User grants access. Provider redirects to
GET /mcp-oauth/callback?code=...&state=.... - Server exchanges the code for tokens using the provider's
tokenUrl. - Credentials are stored temporarily (keyed by
state) pending the client's poll. GET /mcp-oauth/poll?state=...: Client polls until{ ready: true, credentials: {...} }.- Client calls
POST /connectors/:id/credentialsto persist the credentials.
MCPOAuthService
| Method | Description |
|---|---|
startFlow({ serverId, instanceId, state, orgId }) | Build and return auth URL |
handleCallback(state, code) | Exchange code, store credentials temporarily |
refreshToken(serverId, refreshToken) | Refresh using stored client secret |
pollCredentials(state) | Return { ready, credentials? } |