Skip to content

Building Connectors

A connector is defined by its descriptor -- a YAML or JSON document that declares the external system's API operations, authentication requirements, rate limits, and capabilities. The platform validates the descriptor and registers it in the connector catalog.


Connector Descriptor Structure

A descriptor has the following top-level sections:

graph TD
    CD["Connector Descriptor"] --> Meta["metadata<br/>name, slug, version, publisher"]
    CD --> Auth["authentication<br/>auth profiles + credential fields"]
    CD --> Chains["credential_chains<br/>multi-step auth flows (optional)"]
    CD --> Ops["operations<br/>API endpoints + parameters"]
    CD --> Cap["capabilities<br/>sync modes, schema discovery"]
    CD --> RL["rate_limits<br/>per-account/user/token limits"]
    CD --> SLA["sla<br/>availability, latency targets"]
    CD --> MCP["mcp_config<br/>MCP tool generation (optional)"]
    CD --> DB["database_config<br/>adapter settings (optional)"]

Metadata

Every connector starts with metadata that identifies it in the catalog:

metadata:
  name: "Jira Cloud"
  slug: "jira-cloud"
  version: "1.2.0"
  description: "Connect to Atlassian Jira Cloud for issue tracking and project management."
  summary: "Jira Cloud connector for issue CRUD, search, and project management"
  publisher: "Acme Corp"
  documentation_url: "https://developer.atlassian.com/cloud/jira/platform/rest/v3/"
  categories:
    - saas
  tags:
    - project-management
    - issue-tracking
    - atlassian
Field Required Rules
name Yes 3-200 characters
slug Yes 3-100 characters, lowercase alphanumeric with hyphens
version No Defaults to 0.1.0
description Yes 10-2000 characters
summary No Up to 300 characters; short label for listings
publisher Yes 2-200 characters
documentation_url No URL to external API documentation
categories No One or more of: database, file_storage, saas, messaging, analytics, custom
tags No Free-form string labels for search and filtering

Authentication Profiles

Define how users authenticate with the external system. A connector can support multiple auth methods (e.g., both API key and OAuth2).

Supported types: api_key, basic, oauth2_authorization_code, oauth2_client_credentials, service_account, none.

Authentication Profile Fields

Field Required Description
type Yes Auth type (see supported types above)
description No Human-readable description (up to 500 chars)
docs_url No Link to external auth documentation
fields No List of credential fields the user must supply
oauth No OAuth2 settings (required for oauth2_* types)
test_endpoint No Endpoint called to validate credentials on instance creation
credential_chain_id No References a credential_chains entry for multi-step auth

Credential Field Properties

Each entry in fields has:

Field Required Description
key Yes Internal identifier (1-100 chars)
label Yes Display name shown in the UI (1-200 chars)
field_type No One of: string, secret, integer, boolean, password, json. Defaults to string
required No Whether the field must be supplied. Defaults to true
secret No Encrypts the value at rest. Defaults to false
description No Help text (up to 500 chars)
example No Example value shown in the UI (up to 500 chars)
authentication:
  - type: api_key
    description: "Jira API token (generated in Atlassian account settings)"
    docs_url: "https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/"
    fields:
      - key: email
        label: "Email Address"
        field_type: string
        required: true
        description: "Atlassian account email"
        example: "user@company.com"
      - key: api_token
        label: "API Token"
        field_type: secret
        required: true
        secret: true
        description: "Jira API token"
    test_endpoint:
      url: "https://{domain}.atlassian.net/rest/api/3/myself"
      method: GET
      expected_status: 200
authentication:
  - type: oauth2_authorization_code
    description: "OAuth2 with user consent for Jira Cloud"
    oauth:
      authorize_url: "https://auth.atlassian.com/authorize"
      token_url: "https://auth.atlassian.com/oauth/token"
      scopes:
        - name: "read:jira-work"
          description: "Read Jira project and issue data"
        - name: "write:jira-work"
          description: "Create and update Jira issues"
      default_scopes:
        - "read:jira-work"
authentication:
  - type: oauth2_client_credentials
    description: "Machine-to-machine OAuth2 flow"
    fields:
      - key: client_id
        label: "Client ID"
        field_type: string
        required: true
      - key: client_secret
        label: "Client Secret"
        field_type: secret
        required: true
        secret: true
    oauth:
      token_url: "https://auth.example.com/oauth/token"
      scopes:
        - name: "api:read"
          description: "Read access"
      default_scopes:
        - "api:read"
authentication:
  - type: basic
    description: "Username and password for Jira Server"
    fields:
      - key: username
        label: "Username"
        field_type: string
        required: true
      - key: password
        label: "Password"
        field_type: password
        required: true
        secret: true
    test_endpoint:
      url: "https://{base_url}/rest/api/2/myself"
      method: GET
      expected_status: 200
authentication:
  - type: service_account
    description: "GCP service account JSON key"
    fields:
      - key: service_account_json
        label: "Service Account JSON"
        field_type: json
        required: true
        secret: true
        description: "Contents of the service account key file"

Credential field types

Use field_type: secret, field_type: password, or field_type: json for sensitive values. These fields are encrypted at rest and never returned in API responses.

test_endpoint

The optional test_endpoint on an authentication profile is called when a user creates a connector instance to verify their credentials are valid.

Field Required Description
url Yes URL to call (supports {variable} substitution)
method No HTTP method, defaults to GET
expected_status No Expected HTTP status code, defaults to 200
headers No Additional headers as a key/value map

Credential Chains

For systems with multi-step authentication, define a credential chain and reference it from the auth profile:

credential_chains:
  - chain_id: securonix_oauth
    description: "Multi-step OAuth for Securonix SIEM"
    initial_credentials_required:
      - username
      - password
      - base_url
      - gateway_url
    steps:
      - step_name: ws_token
        endpoint: "{base_url}/Snypr/ws/token/generate"
        method: GET
        headers:
          username: "{username}"
          password: "{password}"
          validity: "365"
        extract:
          ws_token: "$.token"
        ttl_seconds: 31536000
      - step_name: oauth_token
        endpoint: "{gateway_url}/api/v2/oauth/token"
        method: POST
        headers:
          wstoken: "{ws_token}"
        extract:
          bearer_token: "$.access_token"
          expires_in: "$.expires_in"
    final_credential_name: bearer_token

authentication:
  - type: api_key
    description: "Securonix bearer token via multi-step OAuth"
    credential_chain_id: securonix_oauth

The platform executes each step in order, using JSONPath to extract intermediate credentials and caching them based on TTL.

Credential Chain Fields

Field Required Description
chain_id No Identifier referenced by credential_chain_id in an auth profile (1-100 chars)
description Yes Human-readable description (1-500 chars)
initial_credentials_required Yes List of field keys the user must provide before the chain runs
steps Yes Ordered list of auth steps (minimum 1)
final_credential_name Yes Which extracted key from the last step is used as the credential

Credential Chain Step Fields

Field Required Description
step_name Yes Step identifier (1-100 chars)
endpoint Yes URL template with {variable} substitution
method No HTTP method, defaults to POST
headers No Header key/value map with {variable} substitution
body No Body key/value map with {variable} substitution
query_params No Query param key/value map with {variable} substitution
extract Yes JSONPath expressions mapping response fields to credential names
ttl_seconds No How long to cache the extracted credential
cache_key No Template string used as the cache key

Defining Operations

Operations are the core of a connector. Each operation maps to one API endpoint on the external system.

operations:
  - operation_id: list_issues
    endpoint: "https://{domain}.atlassian.net/rest/api/3/search"
    method: GET
    summary: "Search Jira issues using JQL"
    description: "Returns issues matching a JQL query with pagination support"
    auth_type_ref: api_key
    auth_headers:
      Authorization: "Basic {base64({email}:{api_token})}"
    parameters:
      - name: jql
        location: query
        description: "JQL query string"
        required: true
        field_type: string
        example: "project = PROJ AND status = Open"
      - name: maxResults
        location: query
        description: "Maximum results per page"
        required: false
        field_type: integer
        default_value: 50
      - name: startAt
        location: query
        description: "Pagination offset"
        required: false
        field_type: integer
        default_value: 0
    response_schema:
      type: object
      required: ["issues", "total"]
      properties:
        issues:
          type: array
        total:
          type: integer
    tags:
      - read
      - search

  - operation_id: create_issue
    endpoint: "https://{domain}.atlassian.net/rest/api/3/issue"
    method: POST
    summary: "Create a new Jira issue"
    auth_type_ref: api_key
    auth_headers:
      Authorization: "Basic {base64({email}:{api_token})}"
    parameters:
      - name: project_key
        location: body
        description: "Project key (e.g., PROJ)"
        required: true
        field_type: string
      - name: summary
        location: body
        description: "Issue summary/title"
        required: true
        field_type: string
      - name: description
        location: body
        description: "Issue description"
        required: false
        field_type: string
      - name: issue_type
        location: body
        description: "Issue type (Bug, Story, Task, etc.)"
        required: true
        field_type: string
    tags:
      - write
      - create

Operation Fields

Field Required Description
operation_id Yes Unique identifier (lowercase, alphanumeric, underscores). Pattern: ^[a-z0-9_]+$
endpoint Yes URL path or full URL. Supports {variable} substitution
method No HTTP method (defaults to GET)
summary Yes Brief description (1-200 chars)
auth_type_ref Yes References an authentication profile defined in the descriptor
auth_headers No Header templates using {credential_field} substitution (e.g., Authorization: "Bearer {token}")
credential_field No Which extracted credential to inject (e.g., bearer_token from a credential chain)
parameters No List of input parameters
response_schema No JSON Schema for response validation
rate_limit_scope No References a rate_limits scope by name for per-operation enforcement
tags No Categorization tags (e.g., read, write, admin)

Parameter Fields

Field Required Description
name Yes Parameter identifier (1-100 chars)
location Yes Where the parameter is sent (see table below)
description No Human-readable description (up to 500 chars)
required No Defaults to false
field_type No One of: string, integer, boolean, secret, password, json. Defaults to string
default_value No Default value used when the parameter is not supplied
example No Example value (up to 200 chars)

Parameter Locations

Parameters can appear in four locations:

Location Description Example
query URL query string ?jql=project=PROJ
path URL path segment /issues/{issue_id}
header HTTP request header X-Custom-Header: value
body Request body (JSON) {"summary": "Bug fix"}

Rate Limits

Declare the external system's rate limits so the platform can enforce them:

rate_limits:
  - scope: per_account
    limit: 100
    interval_seconds: 60
    burst: 20
    note: "Jira Cloud standard rate limit"
  - scope: per_user
    limit: 50
    interval_seconds: 60
Field Required Description
scope Yes One of: per_account, per_user, per_token, per_connection
limit Yes Maximum number of requests allowed in the interval
interval_seconds Yes Rolling window duration in seconds
burst No Additional requests allowed above the limit in a burst
note No Human-readable explanation (up to 300 chars)

SLA Metrics

Define the expected service level:

sla:
  availability_percentage: 99.9
  latency_ms_p95: 2000
  error_budget_percentage: 0.1
  data_freshness_minutes_p95: 5
  rto_minutes: 60
  rpo_minutes: 15
Field Required Description
availability_percentage Yes Target uptime (0-100)
latency_ms_p95 No p95 API response latency in milliseconds
error_budget_percentage No Acceptable error rate (0-100)
data_freshness_minutes_p95 No p95 data freshness in minutes
rto_minutes No Recovery Time Objective in minutes
rpo_minutes No Recovery Point Objective in minutes

Capabilities

Declare what the connector can do:

capabilities:
  sync_modes:
    - full_refresh
    - incremental
    - streaming
  supports_schema_discovery: true
  supports_incremental_bookmark: true
  supports_change_data_capture: false
  supports_custom_sql: false
  supports_file_ingestion: false
  max_parallel_tasks: 5
Field Required Description
sync_modes No List of supported modes: full_refresh, incremental, streaming
supports_schema_discovery No Whether the connector can enumerate its schema. Defaults to true
supports_incremental_bookmark No Whether incremental syncs use a bookmark cursor. Defaults to false
supports_change_data_capture No Whether CDC is available. Defaults to false
supports_custom_sql No Whether arbitrary SQL can be executed. Defaults to false
supports_file_ingestion No Whether the connector can ingest files. Defaults to false
max_parallel_tasks No Maximum concurrent sync tasks

MCP Configuration

Expose connector operations as MCP tools so AI agents can call them directly:

mcp_config:
  enabled: true
  server_name: "jira-mcp"
  server_description: "Jira Cloud MCP server for issue management"
  route_mappings:
    - operation_id: list_issues
      mcp_tool_name: "search_issues"
      mcp_tool_description: "Search Jira issues using a JQL query"
      parameter_mappings:
        jql: "jql_query"
    - operation_id: create_issue
      mcp_tool_name: "create_issue"
      mcp_tool_description: "Create a new issue in a Jira project"
Field Required Description
enabled No Defaults to false
server_name Yes MCP server identifier (1-100 chars)
server_description Yes Human-readable description (1-500 chars)
route_mappings No List of operation → MCP tool mappings

Each route_mappings entry:

Field Required Description
operation_id Yes Must reference an operation defined in this descriptor
mcp_tool_name Yes Name exposed to MCP clients (must be unique)
mcp_tool_description Yes Description of the tool for the LLM (1-500 chars)
parameter_mappings No Map connector parameter names to MCP parameter names

Database Connectors

For database-category connectors, add database-specific configuration:

database_config:
  adapter: postgres
  default_schema: public
  tables: []  # empty = all tables accessible
Field Required Description
adapter No Database adapter. Defaults to postgres
default_schema No Default schema to use. Defaults to public
tables No List of tables to expose. Empty list means all accessible tables

Supported adapters: postgres, mysql, and others via the connector adapter registry.


Validation

Before registering a connector, validate the descriptor:

Coming Soon

The Python SDK for local development is not yet publicly available.

from flow_sdk.cli_client import CLIClient

client = CLIClient(config)

result = client.connectors.validate(descriptor={
    "metadata": {"name": "My Connector", "slug": "my-connector", ...},
    "authentication": [...],
    "operations": [...],
    ...
})

if result.valid:
    print("Descriptor is valid")
else:
    for error in result.errors:
        print(f"Error: {error}")

The validator checks:

  • All required fields are present with valid types
  • Authentication profiles have no duplicates
  • Operations reference valid authentication profiles
  • Operation IDs are unique
  • MCP route mappings (if configured) reference existing operations and have unique tool names
  • Credential chain steps are properly sequenced

Registering the Connector

Once validated, register the connector in the catalog:

Coming Soon

The Python SDK for local development is not yet publicly available.

connector = client.connectors.create({
    "descriptor": descriptor,
    "status": "draft",       # draft, published, or archived
    "visibility": "organization",  # private, workspace, organization, marketplace
})

print(f"Registered: {connector.id} ({connector.slug} v{connector.version})")

Version management

Update the version field in metadata when changing operations or auth profiles. The platform tracks connector versions and instances can be pinned to specific versions.