Connector definition reference
Every member of a connector definition: identity, engines, auth methods, settings fields, actions and their access marking, guides, messages and assets.
Enterprise module
Connectors are the enterprise connectors module. A workspace without the module gets 402 from the connectors API.
You write the definition in TypeScript with defineConnector. cpc build imports it and writes connector.json, the manifest Console reads. The build checks the definition and fails on mistakes such as an unknown reference, a missing message or an invalid pattern, so most errors show up before you test.
import { createKit, defineConnector, field, guide, t, z } from '@cognipeer/connector-sdk'createKit<Settings>() returns the builders for actions, sources and auth methods, typed with your settings so ctx.settings is checked.
Top-level members
| Member | Required | What it is |
|---|---|---|
id | yes | <publisher>.<name>. Lower case; the publisher is 1 to 40 characters and the name 1 to 64, letters, digits and -, each starting with a letter. The publisher must match the namespace of the signing key |
name | yes | Display name |
description | yes | One sentence shown in the catalogue |
category | yes | One of document-management, project-management, crm, support, communication, commerce, finance, database, storage, developer, data, other |
icon | yes | Path to an SVG or PNG in the package, for example ./assets/icon.svg |
deployments | yes | ['saas'], ['onprem'] or both |
engines | yes | { console: '<range>' }. See Engines |
settings | yes | Fields of the connector form. {} for none. See Settings fields |
settingsVersion, migrations | no | Version of the settings shape and the functions that upgrade old values. See Settings versions |
auth | yes | List of sign-in methods. See Auth methods |
http | no | How ctx.http reaches the service |
permissions | yes | Hosts the package may call. permissions.egress is required, {} when the package makes no HTTP calls |
sql, mail | no | Declare ctx.sql or ctx.mail. See Database and mail blocks |
identity | no | Function that tells who the connected account is. Console uses it for Test connection and to label the account |
actions | no | Tools offered to agents. See Actions |
mcp | no | The service's official MCP server. See MCP server |
sources | no | Data sources for Knowledge Engine. See Sources |
options, browse, rpc, ui | no | Form choices, pickers, calls from package screens, and the screens |
guides | no | Setup guides. See Guides |
limits | no | { timeoutMs, memoryMb, concurrency }. See Resource limits |
A package with no actions, MCP server or sources builds with a warning.
Engines
engines.console is the range of Console versions the package runs on: comparators separated by spaces, all of which must hold, such as >=1.20.0 <2.0.0. The operators are >=, <=, >, < and =. Console refuses to install a package whose range does not include its own version.
Set the lower bound to the first Console version that has everything the package uses. This matters most for the host operations: a package that declares sql, mail, a signing inject kind or http.profile must not be published with a lower bound that predates them, because an older Console cannot refuse what it does not know.
cpc build adds engines.sdk, the SDK version the package was built with.
Resource limits
limits asks for less or more than the defaults. Console clamps the values.
| Member | Default | Range | Meaning |
|---|---|---|---|
timeoutMs | 60 000 | milliseconds | Longest time one call may run |
memoryMb | 256 | 64 to 2048 | Memory of the package process |
concurrency | 8 | 1 to 32 | Calls the process serves at once; more calls wait |
Messages and i18n
Every text a person reads is a message key: t('settings.baseUrl'). The definition holds the key, and i18n/en.json and i18n/tr.json hold the text. Both files are required, and cpc build fails if a key is missing in either.
- Keys use letters, digits,
_,.and-, at most 120 characters. - A literal string is accepted where text is expected, but it must not start with
i18n:. - The
descriptionof an action is the exception: it is plain English text written for the model, at most 1024 characters. ctx.t(key, { name: 'value' })returns a message at run time and replaces{name}placeholders.
Settings fields
settings is an object of fields. Settings are plain values such as a URL, a choice or a switch. Secrets never go in settings; they belong to an auth method. Keys start with a letter, then letters, digits, _ or -, up to 64 characters.
Options every field takes:
| Option | Meaning |
|---|---|
label | Text of the label (required) |
help | Text shown under the field |
required | The field must be filled while it is active |
default | Value used when the field is empty |
deployments | ['saas'] or ['onprem']. Console drops the field, and any option with the same deployments, on the other deployment before your code runs. Your code then sees undefined |
visibleWhen | A condition. While it is false the field is hidden and dropped |
advanced | Shows the field in the advanced part of the form |
Field kinds and their own options:
| Builder | Value | Options and validation |
|---|---|---|
field.text | string | placeholder, pattern (regular expression), maxLength |
field.secret | string | Masked everywhere, never logged, never sent to a package screen |
field.url | string | schemes ('https', 'http'), hostPattern (regular expression for the host). A url used for egress needs a hostPattern. http is accepted on-prem only |
field.number | number | min, max, step |
field.boolean | boolean | none |
field.select | string | options (a list of { value, label, deployments? }), or optionsFrom (the name of an entry in options) with dependsOn (keys the list depends on) |
field.multiselect | list of strings | Same as select, plus max |
field.tags | list of strings | maxItems, itemPattern, itemMaxLength. Console checks them every time the settings are saved |
field.date | string | none |
field.query | string | language, examples |
field.explorer | list of targets | A tree or master-detail picker fed by a browse provider: browse, layout, levels, coverage, emptyMeans, maxSelection, widget |
field.resource | string | kind: knowledge-base, dataset, config-ref or file |
field.json | any | none |
field.custom | any | widget (a ui entry with slot field) and schema (a zod schema) |
Patterns are checked at build time: a pattern, hostPattern or itemPattern that is not a valid regular expression fails the build.
const settings = {
serverUrl: field.url({
label: t('settings.serverUrl'),
schemes: ['https'],
hostPattern: '^[a-z0-9][a-z0-9.-]{0,252}$',
required: true,
}),
readonly: field.boolean({ label: t('settings.readonly'), default: true }),
}
type Settings = ValuesOf<typeof settings> // import type { ValuesOf } from '@cognipeer/connector-sdk'Conditions
A condition is data, not a function, because Console evaluates it without running your code. It is used by visibleWhen, when on auth methods, actions, sources and the MCP block.
{ field: 'host', equals: 'github.com' }
{ field: 'host', in: ['ghe.com', 'server'] }
{ field: 'buckets', notEmpty: true }
{ all: [ /* conditions */ ] }
{ any: [ /* conditions */ ] }when on an auth method, action, source or MCP block may name settings only. A condition that names an unknown field fails the build.
Settings versions
When a setting changes meaning, raise settingsVersion and add a migration. migrations is keyed by the target version. Console runs the function on upgrade, before the new code sees the settings.
settingsVersion: 2,
migrations: { 2: (previous) => ({ ...previous, host: previous.host ?? 'github.com' }) },Auth methods
auth lists the ways an account can sign in. Each method has an id (lower case letters, digits and -, up to 40 characters), a label, an optional when condition and a guide. Ids must be unique. The administrator picks one method when connecting.
| Kind | Builder | Credential |
|---|---|---|
api_key | kit.auth.apiKey | Fields the user types, stored sealed by Console |
oauth2 | kit.auth.oauth2 | OAuth tokens, obtained, stored and renewed by Console |
custom | kit.auth.custom | A session that your own authenticate function returns |
none | kit.auth.none | No credential: public access |
In every method Console injects the credential into requests that go to the origin of http.baseUrl and to the origins in inject.origins. Other hosts get none. The package never sees the token or key.
guide is a guide id, or an object that picks one per deployment: { saas: 'oauth-saas', onprem: 'oauth-app' }. Every method has a guide, and every guide must exist in guides.
API key and token injection
kit.auth.apiKey({
id: 'pat',
label: t('auth.pat'),
fields: { token: field.secret({ label: t('auth.pat.token'), required: true }) },
inject: { header: 'Authorization', scheme: 'Bearer', from: 'token' },
guide: 'pat',
})fields are the inputs of the connect form (any field kind). inject says where the value goes. It must hold exactly one of these kinds; an empty or unknown one fails the build.
inject | Members | Effect |
|---|---|---|
| Header | header, optional scheme ('Bearer' or 'Token'), from (the field that holds the value), optional origins | Sets the header. With scheme, the value is prefixed with it |
| Query | query, from, optional origins | Adds the value as a query parameter |
| Basic | basic: { username, password } (names of fields), optional origins | Sends HTTP Basic authentication |
| Database account | sql: { username, password } | Console uses the fields to open database connections. Nothing is sent over HTTP |
| Mail account | mail: { username, password } | Console uses the fields to sign in to the mail server |
| AWS Signature V4 | awsSigV4: { accessKeyId, secretAccessKey, sessionToken?, service: 's3', regionFromSettings } | Console signs each request |
| Azure Shared Key | azureSharedKey: { accountFromSettings, key } | Console signs each request |
| Azure SAS | azureSas: { from } | Console appends the stored token to each request |
The sql and mail kinds are valid only on an api_key method listed in sql.auth or mail.auth. The three signing kinds need http.profile; see Object storage. A signing inject has no origins: the signature goes to the origin of http.baseUrl only.
OAuth
kit.auth.oauth2 covers the sign-in where a user approves access at the vendor, and the server-to-server grants.
Options of the default grant, authorization_code:
| Option | Meaning |
|---|---|
endpoints | { authorize, token, revoke? }, or a function of the settings that returns them. revoke may contain {clientId} |
scopes | List sent as scope. An empty list sends none |
scopeSeparator | Separator of the scope list. Default a space |
pkce | Use PKCE if the vendor supports it |
app | Whose OAuth app, per deployment: { saas: 'customer', onprem: 'customer' }. See below |
appFields | The clientId and clientSecret fields of the OAuth app |
tokenRequest | How Console calls the token endpoint. See below |
revocation | How Console calls the revoke endpoint. See below |
capture | Function that turns the token response into non-secret values (tokens are removed first) that you can read as ctx.account.captured |
inject | Where the access token goes, usually { header: 'Authorization', scheme: 'Bearer' } |
app has two values. customer means the administrator registers an OAuth app at the vendor and enters it under OAuth apps in Console; the guide of the method must explain how, and can use for the callback address Console shows. deployment means the app comes from the Console deployment's own configuration; it needs fixed endpoints (not a function of the settings). For a package you distribute yourself, use customer.
Console runs the whole flow: it keeps a state value for 10 minutes, exchanges the code, stores the tokens sealed, renews them before they end and revokes them on disconnect. If a request gets HTTP 401 with an account that has a refresh token, Console renews the token once and sends the same request again. Packages do nothing for this.
Token request and revocation members, all optional:
| Member | Values | Default |
|---|---|---|
tokenRequest.clientAuth | body (client id and secret in the request) or basic (HTTP Basic) | body |
tokenRequest.body | form or json | form |
tokenRequest.headers | Static extra headers | none |
revocation.method | POST or DELETE | POST |
revocation.clientAuth | basic or body | basic |
revocation.body | form or json | form |
revocation.tokenField | Body key that holds the token, 1 to 64 letters, digits, _, ., - | token |
revocation.token | access or refresh | access |
revocation.headers | Static extra headers | none |
Static headers are never secrets. Names are HTTP header tokens of at most 64 characters, at most 8 headers, values printable ASCII of at most 256 characters. Authorization, Cookie, Set-Cookie, Host, Expect, hop-by-hop headers and every Proxy-* and Content-* header are refused at build time.
Server grants
Give oauth2 a grant of client_credentials or password when the service issues tokens to an application and no user signs in. There is no app, appFields or pkce; the connect form asks for the client id and secret (and a user name and password for password), and Console requests and renews the token. Use password only where the vendor documents it.
kit.auth.oauth2({
id: 'app-only',
label: t('auth.appOnly'),
grant: 'client_credentials',
endpoints: { token: 'https://login.example.com/{tenantId}/oauth2/v2.0/token' },
scopes: ['https://api.example.com/.default'],
tokenRequest: { clientAuth: 'basic' },
inject: { header: 'Authorization', scheme: 'Bearer' },
guide: 'app-only',
})| Option | Meaning |
|---|---|
endpoints | { token, revoke? }. token may contain {setting} placeholders in its path, filled from the connector's settings. A placeholder in the host part, or one that names no setting, fails the build |
tokenParams | Fixed extra token parameters such as audience. Never secrets |
fields | Relabel clientId, clientSecret, username and password. Console always asks for them and marks them required |
An account is marked as needing a new sign-in when the vendor answers invalid_client or invalid_grant, or HTTP 401, to a token request.
Custom sign-in
kit.auth.custom takes fields and an authenticate(ctx, credentials) function that exchanges them for a session: { session: Record<string, string>, expiresInSec? }. This is the only code that sees the credentials. Console caches the session and treats every session value as a secret. inject uses fromSession instead of from, and reauthOn lists HTTP statuses that make Console sign in again.
Public access
kit.auth.none({ label, id?, deployments?, when?, guide? }) stores no credential and ctx.http sends none. The default id is public. Console still keeps an account record, so "connected" checks work. Offer it next to a credential method when the service has public data. A mail relay that needs no sign-in uses a none method with deployments: ['onprem'].
HTTP and permissions
http: {
baseUrl: (s) => `https://${s.region}.example.com/api`,
headers: () => ({ Accept: 'application/json' }),
timeoutMs: 20_000,
maxResponseBytes: 5_000_000,
retry: { attempts: 3, on: [502, 503, 504], respectRetryAfter: true },
mapError,
},
permissions: { egress: { hosts: ['api.example.com'], fromSettings: ['serverUrl'] } },http member | Meaning |
|---|---|
baseUrl | A string, or a function of the settings. Resolved when the settings are saved, an account connects or a token refreshes, and checked against egress |
headers | Static headers sent with every request, or a function of the settings |
timeoutMs, maxResponseBytes | Defaults for requests: 30 000 ms and 10 MiB when absent |
retry | { attempts, on, respectRetryAfter?, methods? }. See Runtime context |
mapError | Turns a vendor response into a ConnectorError. See Errors |
readPost, graphql | Paths a read action may POST to. See Read actions |
profile, methods, scope | Object storage rules. See Object storage |
permissions.egress lists every host the package may call. It is shown on the install screen and enforced on every request, redirects included.
| Member | Meaning |
|---|---|
hosts | Exact host names or *.suffix. Wildcards are flagged on the install screen |
fromSettings | Keys of url settings that hold a host the administrator enters. Each needs a hostPattern |
fromCaptured | [{ key, hosts }]: the host of a value captured at sign-in (such as an instance URL) is allowed when it matches one of hosts. Names only, not patterns |
privateNetwork | 'onprem' allows private addresses for hosts the operator entered, when the operator's network allowance covers them. Never on SaaS. Default 'never' |
caFromSettings | Key of a text setting, on-prem only, that holds PEM certificates for a private endpoint |
permissions.tcp is a list of { fromSettings, ports?, portFromSettings?, privateNetwork? } for a server that Console reaches over TCP on the package's behalf, as the mail block does.
Database and mail blocks
sql and mail name the settings that hold the server. The values the administrator saves there are the only server the package can reach. The field requirements and limits are in Runtime context.
sql member | Meaning |
|---|---|
engines | Non-empty list from postgres, mysql, mariadb, mssql, oracle. Console runs PostgreSQL, MySQL and MariaDB |
engineFromSettings | Key of a select setting that holds the engine. Required when engines lists more than one |
host | Key of a text setting. Required |
port, database, caPem, schemas | Keys of a number, text, text and tags setting. An empty port means the engine's default |
tlsMode | Key of a select setting whose values are among verify-full, verify-ca, skip-verify, disable. Offer the last two on-prem only |
auth | Ids of api_key methods whose inject is sql. Required |
privateNetwork | never (default) or onprem |
limits | maxRows, maxBytes, timeoutMs, poolMax; can only lower Console's limits |
mail member | Meaning |
|---|---|
host, security, fromAddress | Keys of a text, select and text setting. Required. security values are among tls, starttls, plain, and plain is on-prem only |
port, caPem, fromName, replyTo | Keys of a number, text, text and text setting. An empty port means the default of the security mode |
allowedDomains | Key of a tags setting with the recipient domains. Empty means any |
maxRecipients | Key of a number setting from 1 to 25 |
auth | Ids of api_key methods whose inject is mail, or of none methods for a relay (on-prem only). Required |
privateNetwork | never (default) or onprem; the same value as the permissions.tcp entry |
limits | maxBodyBytes, maxRecipients; can only lower Console's limits |
A package with a mail block also needs a permissions.tcp entry whose fromSettings is the mail host setting, with portFromSettings set to the mail port setting when there is one, or ports when there is not. cpc build rejects a key that names no setting or a setting of the wrong kind, unknown members and limits outside their maximum.
Actions
An action is one tool. The key in actions is the tool name the model sees: lower case letters, digits and _, starting with a letter, up to 64 characters.
const getRepo = kit.action({
title: t('actions.get_repo'),
description: 'Get one repository: description, default branch, visibility and counts.',
access: 'read',
input: z.object({ owner: z.string().min(1).max(100), repo: z.string().min(1).max(100) }),
pinnable: ['owner', 'repo'],
async run(ctx, input) {
return ctx.http.get(p`/repos/${input.owner}/${input.repo}`)
},
})| Member | Required | Meaning |
|---|---|---|
title | yes | Display name |
description | yes | English text for the model, at most 1024 characters. Be specific: it decides when the model uses the tool |
access | yes | read, write or destructive |
input | yes | A zod object schema. Must be an object, and inlined (no $ref). Console shows the schema to the model |
output | no | A zod schema of the result |
when | no | A condition on settings. The action is offered only while it holds |
pinnable | no | Input keys an administrator may pin or constrain per connector |
approval | no | Accepted and ignored. Approval is decided per agent, not by the connector |
run(ctx, input) | yes | The implementation. Returns the result |
Access
access describes what the action does. Console turns it into the standard tool markings and does two things with it.
access | Marking on the tool | What Console does |
|---|---|---|
read | read-only | Agents run the tool without asking. Console enforces it on the request itself, see Read actions |
write | changes data, not destructive | The tool asks for approval by default |
destructive | changes data, destructive | The tool asks for approval by default |
The connector never decides whether a call asks. The agent owner sets that on the agent's tool settings, where a tool can be set to Never ask. A tool with no marking, or an unknown access, counts as destructive. See Tool approvals.
Mark an action write or destructive whenever it changes anything, including a send. Mark an action that only shows what would happen, such as a draft, as read, so an agent can use it without asking.
Read actions
A read action may send only GET and HEAD. Two members of http open narrow exceptions, and Console checks them on every request and every redirect hop:
| Member | What a read action may do |
|---|---|
http.readPost | POST to the listed paths, whatever the body. For search endpoints that carry the query in the body |
http.graphql | POST to the listed paths, or GET with a query parameter, only when the request holds queries. Mutations and subscriptions are refused |
A path is relative to baseUrl and is one of:
- exact, such as
/search; - with
*as a whole segment that is not the last, matching exactly one non-empty segment, such as/workspaces/*/search/code; - ending in
*orprefix*, matching anything below the prefix, such as/data_sources/*.
A pattern starts with /, has at most 200 characters and 16 segments, and a list holds at most 200 patterns. A request path with //, a dot segment, an encoded slash (%2F) or backslash, or ; never matches. Prefer the whole-segment form to a trailing prefix: it grants one endpoint instead of everything below. For a GraphQL path the body must be JSON of at most 256 KiB, with the query text at most 100 000 characters; write actions are not checked. cpc build validates both lists.
MCP server
If the service runs an official remote MCP server, point at it. Console connects with the account's credential and offers the server's tools instead of the package's own actions (one tool per connector).
| Member | Meaning |
|---|---|
url | Streamable HTTP endpoint: a string, or a function of the settings |
headers | Extra request headers, for example a toolset selection. A string map or a function of the settings |
auth | Id or ids of the auth methods whose credential is sent |
when | A condition on settings |
tools | { include?, exclude?, access? }. access maps tool names or patterns to read, write or destructive. Tools that match no pattern count as destructive |
beforeCall | Function that runs in the package before each MCP tool call and may rewrite the arguments |
A tool keeps the markings the MCP server sent; the package's access patterns can make a tool stricter but never looser. The URL is checked against egress.
Sources
A source lists items for Knowledge Engine and keeps them in step with the service.
| Member | Meaning |
|---|---|
title | Display name |
output | documents or records |
filters | Fields of the source form (same field kinds as settings) |
schedule | { default, minIntervalMin? } |
incremental | The source can continue from a checkpoint |
deletes | prune, events or none |
acl | The source reports access lists |
guide | Id of a guide shown beside the source form |
sync(ctx, run) | An async generator that yields changes |
Yield changes with the change helper: change.upsert(item), change.delete(id), change.skip(id, reason?), change.checkpoint(cursor, { scope? }), change.scopeComplete(scope?), change.progress({ done, total, message }) and change.record. Console pulls one change at a time and the generator stays paused at each yield until Console has handled it, so a file's data() can still use ctx.
| Rule | Value |
|---|---|
Item id | at most 512 characters |
Item title | cut at 500 characters |
Item url | dropped above 2048 characters |
Progress message | cut at 500 characters |
| Checkpoint cursor | at most 64 KB of JSON, else the call fails with POLICY_DENIED |
| File size | at most 20 MB; a larger file is skipped |
Report deletions only when a listing is complete (scopeComplete); never prune after a partial or failed listing. Stop at run.deadline after a checkpoint, and Console starts the next segment from it with resumed: true.
Guides
A guide is Markdown that Console shows to the administrator while connecting. Declare it with guide(path, options) and write one file per locale.
guides: {
pat: guide('./guides/pat', { audience: 'admin' }),
'network-onprem': guide('./guides/network-onprem', { audience: 'operator', deployments: ['onprem'] }),
}guide('./guides/pat')readsguides/pat.en.mdandguides/pat.tr.md. Both are required.audienceisoperatororadmin.deploymentslimits where the guide is shown.in the text is replaced with the connector's OAuth callback URL.- Console renders the Markdown without raw HTML.
- Every auth method and every on-prem network need has a guide. Name UI labels exactly as they appear in the messages.
Assets
assets/ holds the icon and any other file the package needs, as SVG or PNG. The icon member points at one of them. File names use letters, digits, ., _ and -, and the package may contain only files with the extensions json, mjs, js, map, md, svg, png, txt and sha256.
Package screens
ui declares React screens that Console renders in a sandboxed frame. ui entries use lower-kebab-case ids and take slot (field, settings, account, source.filters, tab or item.preview), entry, and optional for, title, rpc, browse and access. A screen may call only the rpc methods and browse providers it lists. cpc build bundles each entry into ui/<id>.js; the bundle is at most 1 MB. The components and hooks are in @cognipeer/connector-ui.

