Skip to main content
The Omni Connector SDKs enable you to build custom connectors that integrate any data source with Omni’s search and AI capabilities. Whether you’re connecting an internal database, a SaaS application, or a proprietary system, the SDKs provide everything you need.

Why Build a Custom Connector?

While Omni includes connectors for popular platforms (Google Workspace, Slack, Atlassian, HubSpot), you may need to integrate:
  • Internal systems — Databases, wikis, or custom applications
  • Niche SaaS tools — Industry-specific platforms not yet supported
  • Proprietary data sources — File formats or APIs unique to your organization
  • Legacy systems — Older systems with custom APIs

SDK Features

The SDKs share these core capabilities, although language-specific APIs and advanced features differ:

Available SDKs

Python SDK

Build connectors in Python with FastAPI

TypeScript SDK

Build connectors in TypeScript with Express

Rust SDK

Build connectors in Rust with Axum
Choose the language that best fits your connector and consult its SDK reference for the supported APIs. The built-in connectors provide language-specific reference implementations across the Python, TypeScript, and Rust SDKs.
The SDKs are not published to PyPI or npm. All connector development happens inside the Omni monorepo, with the SDK consumed as a local path dependency ({ path = "../../sdk/python" } for Python, "file:../../sdk/typescript" for TypeScript). To build a connector, clone omni and add a new directory under connectors/. This keeps connectors and the SDK versioned together, so you never have to chase a mismatched release.

Scaffolding with the /build-connector skill

The omni repository ships with a Claude Code skill called build-connector that scaffolds an entire new connector — sync logic, manifest, Dockerfile, package config, frontend wiring (icon, setup dialog, source type enum), Docker Compose service, AWS and GCP Terraform, and integration tests — following the conventions of the built-in connectors. To use it, install Claude Code, open the omni repo, and run:
(or any other service name). The skill walks through the full checklist:
  1. Choose a language (Python, TypeScript, or Rust) and read the matching reference connector
  2. Implement sync, manifest, and any custom actions
  3. Add a database migration for the new source type
  4. Add the variant to the Rust SourceType enum in shared/src/models.rs
  5. Wire up the frontend (icon, setup dialog, integrations page entry)
  6. Add the service to docker/docker-compose.yml and .env.example
  7. Add AWS ECS and GCP Cloud Run definitions
  8. Write integration tests against a real ParadeDB + Redis + connector-manager via testcontainers
The skill is not required — you can build a connector by hand by reading the existing ones — but it eliminates a lot of boilerplate and ensures nothing is missed.

Architecture

Custom connectors integrate with Omni exclusively through HTTP communication with the connector-manager service. Connectors have no direct database access — all document emission, state management, and content storage is handled via the SDK client which communicates with connector-manager over HTTP.

Connector Lifecycle

  1. omni-connector-manager triggers a sync via HTTP POST /sync
  2. Your connector receives the request with source configuration and credentials
  3. Your connector fetches data from the external source
  4. Documents are emitted through the SDK, which sends them to connector-manager
  5. Long-running syncs can save per-run checkpoints so interrupted runs resume safely
  6. connector-manager queues events for the indexer
  7. Your connector reports completion or failure; on success, the run checkpoint is promoted to the source’s persisted checkpoint

HTTP Endpoints

The SDK automatically exposes these endpoints:

Document Conversion (Docling)

Binary documents (PDFs, Word, Excel, PowerPoint, images) are converted to text via the centralized Docling service rather than per-connector logic. The SDK exposes this through ctx.content_storage.extract_text(data, mime_type, filename) (and extract_and_store_content(...) when you want to extract and persist in one call). Under the hood the SDK calls POST /sdk/extract-text on connector-manager, which routes to Docling when the admin has enabled it and falls back to lightweight built-in extractors otherwise. All built-in connectors (IMAP, Gmail, Filesystem, Nextcloud, etc.) use this pathway — custom connectors should too.

Quick Start Example

Here’s a minimal connector implementation in Python:

Wrapping an MCP Server

The Python SDK can expose tools from a Model Context Protocol server to Omni. Override the mcp_server property on your connector to return either a StdioMcpServer (subprocess transport) or an HttpMcpServer (Streamable HTTP transport for remote MCP servers). Consult the language-specific SDK references for their supported MCP APIs. Stdio (local subprocess):
Remote (Streamable HTTP):
The github connector is a reference implementation that wraps the official GitHub MCP server over stdio. Return None (the default) to disable MCP support entirely for your connector.

Connector-owned Skills

Connectors can also ship skills — Markdown documents that guide the Omni agent through connector-specific workflows. Return a list of ConnectorSkillDefinition values from the skills property:
Skills are loaded into Omni when the connector is enabled. The Google connector is a reference: it ships Drive and Gmail skills that teach the agent how to navigate the Google Workspace API surface.

Python OAuth Credential-Ready Lifecycle

For Python MCP connectors that require per-user OAuth, override oauth_credential_ready to run provider-specific post-OAuth setup — such as authenticated MCP catalog discovery — once credentials are stored:
This hook is called by connector-manager after a user completes the OAuth flow, with the resolved credentials passed in the request.

Example Connectors

Both SDKs include an RSS connector example that demonstrates:
  • Fetching data from an external API
  • Parsing and transforming content
  • Emitting documents with metadata
  • Implementing incremental sync
  • Handling errors and cancellation
  • Implementing custom actions
See the SDK-specific documentation for the complete example walkthrough.

Deploying Your Connector

Docker Deployment

Each connector ships its own Dockerfile. Copy from a reference connector in your chosen language (e.g. connectors/notion/Dockerfile for Python, connectors/linear/Dockerfile for TypeScript, connectors/google/Dockerfile for Rust). Add the connector as a service in docker/docker-compose.yml, gated by a Compose profile so it only starts when the user opts in via ENABLED_CONNECTORS:
Then add the port to .env.example and document the new profile name in the ENABLED_CONNECTORS comment.

Registration with Connector Manager

You don’t need to set per-connector URLs in connector-manager’s environment. Connectors auto-register their manifest with connector-manager on a 30-second heartbeat (90s TTL) — as long as the container is reachable on the Docker network and CONNECTOR_MANAGER_URL, CONNECTOR_HOST_NAME, and PORT are set, it will appear automatically. CONNECTOR_HOST_NAME is the hostname connector-manager should call back to, usually the Docker Compose service name (for example, my-connector). The SDK combines it with PORT to register the connector URL.

What’s Next

Python SDK

Detailed Python SDK documentation

TypeScript SDK

Detailed TypeScript SDK documentation

Rust SDK

Detailed Rust SDK documentation