---
title: "Create custom connector"
method: POST
path: "/connector"
tags: ["Custom connectors"]
---

# Create custom connector

`POST /connector`

## Request

- Base URL: `https://api.elaichi.ai`
- URL: `https://api.elaichi.ai/connector`
- Auth: HTTP bearer

Authors a new org-owned connector, either from a catalog `config` or — bring your own — from a remote streamable-HTTP MCP server (`remote_mcp`). Send exactly one of the two. Requires `connector:create` and the `custom_connectors` plan feature. The config is schema-validated: a malformed one answers 422 with the exact issues. The slug is permanent and must be unique within the catalog. A remote MCP connector is private to its creator until shared (the ordinary connector grants), and its tools are discovered per connection, not at creation. `remote_mcp.url` must be https, must not name Elaichi itself, and is immutable afterwards. `auth_mode` says how members sign in: `oauth_auto` (Elaichi registers itself with the server's authorization server — Client ID Metadata Document first, else dynamic registration; 400 when neither exists), `oauth_client` (your own `client_id` and optional `client_secret`), `custom` (an `auth_config` declaring a token form, no OAuth) or `none`. Absent, it is inferred: `client_id` means `oauth_client`, `auth_config` means `custom`, and otherwise the server is probed (OAuth metadata means `oauth_auto`, even when it also answers anonymously; a server with no sign-in at all answers 400 `sign_in_not_offered` unless you send `auth_mode: "none"`; anything else answers 400 `remote_mcp_auth_required`). A field that does not belong to the mode is a 400. The OAuth client is stored as the organization's own app for the connector, never in the connector entry. An organization may hold 25 remote MCP connectors (409 `remote_mcp_server_limit`). The 201 is the connector detail, with `kind: "remote_mcp"`, `remote_mcp` (`url`, `auth_mode`, `oauth_registration`) and `auth` (what sign-in the connector declares, names only — never a secret).

## Headers

- `X-Organization-Id` string

## Request body

- object
  - `remote_mcp` object: Mutually exclusive with `config`.
    - `url` string, required: The server's streamable-HTTP MCP endpoint (https).
    - `auth_mode` 'oauth_auto' | 'oauth_client' | 'custom' | 'none'
    - `auth_config` object: `custom` only: `credentials` (an `api_key` form), `authorization`, `headers`, `query` — the shape of a connector config minus `resources`. Values are placeholders (`{{api_key}}`); a literal secret is refused.
    - `client_id` string: `oauth_client` only.
    - `client_secret` string: `oauth_client` only. Write-only.
    - `scopes` string[]: OAuth only. Defaults to what the server advertises.
    - `omit_refresh_scope` boolean: OAuth modes only (400 for `custom` and `none`). Off by default. `true` makes a token refresh send no `scope` (RFC 6749 §6: omitted means the original grant); the RFC 8707 `resource` is still sent. For a server that rejects a scope on refresh, such as Close (`400 invalid_scope`). Echoed as `auth.omit_refresh_scope`.
  - `logo` string: `remote_mcp` only. An https URL.
  - `description` string: `remote_mcp` only.
  - `slug` string, required: Lowercase letters, digits and hyphens. `new` is reserved.
  - `label` string, required
  - `category` string, nullable
  - `config` object: Connector definition (resources, methods, auth). Mutually exclusive with `remote_mcp`; `config.remote_mcp` is reserved.

## Response `201`

Created

- object

## Other responses

- `400`: Bad request
- `401`: Unauthorized
- `403`: Forbidden
- `404`: Not found
- `429`: Rate limited

---

[API](https://skmtc.dev/elaichi/apis/elaichi-api.md) · [All operations](https://skmtc.dev/elaichi/apis/elaichi-api/llms.txt) · [OpenAPI document](https://skmtc.dev/elaichi/apis/elaichi-api/revisions/b22cfb7b6d15?raw)
