Current
Polling and streaming connectors
Benchmark first
Corpora: QASPER · WikiSection · DocRED. Connectors use recorded provider fixtures because public content corpora do not test cursors, deletes, retries, or event ordering.
Protocol: Score text preservation, section Boundary F1/Pk/WindowDiff, entity/relation F1, stable-ID rate, duplicate rate, and incremental/full-sync equivalence. For polling and streaming, replay the same create→update→delete trace with injected duplicates, reordering, throttling, and cursor expiry; the final snapshot and emitted change set must agree.
Every catalog connector defines a frozen configuration object, validation, and batch polling. GitHub, GitLab, Slack, Google Drive, OneDrive, SharePoint, Confluence, and Box also accept verified provider events. S3, GCS, and Azure Blob use an SDK-neutral batch boundary and checkpoint-free event hints. Generic CloudEvents provide the streaming escape hatch. Network calls use an injected HttpTransport.
How it works
A batch connector starts from the caller’s cursor, requests bounded pages, normalizes provider objects, emits explicit tombstones, and returns the next cursor/checkpoint. A streaming connector verifies the raw delivery before parsing it, reduces provider payloads to bounded ChangeHint keys, and coalesces duplicates. Streaming has no checkpoint state. The application may canonically refetch the changed object into a PollPage, so partial webhook payloads cannot bypass synchronization invariants.
Code and work |
Documents and files |
Business systems |
Open protocols |
|---|---|---|---|
GitHub, GitLab, Linear, Jira |
Drive, OneDrive, SharePoint, Dropbox, Box, Confluence, Notion |
Slack, Airtable, Asana, Trello, Zendesk |
Filesystem, JSON REST, RSS/Atom, Singer, CloudEvents, S3/GCS/Azure object stores |
Scheduled pollPollRequest · cursor · checkpoint
→
Canonical PollPageupserts · tombstones · revision
→
plan_syncone persistence path
Provider streamraw body · headers
verify + parse
ChangeHintbounded · coalesced
canonical refetch
PollPagesame synchronization path
Provider examples
All polling functions accept the same PollRequest and injected HttpTransport, and return an iterator of PollPage values.
GitHub
Files, issues, pull requests, and commits.
from mari_components.connectors import GitHubConfig, poll_github
cfg = GitHubConfig(token=token, repository="acme/product",
branch="main", paths=("docs/**",),
content_types=("files", "issues", "pull_requests"))
pages = poll_github(cfg, request, http=http)
Slack
Channels, DMs, and canonical thread documents.
from mari_components.connectors import SlackConfig, poll_slack
cfg = SlackConfig(bot_token=bot_token,
history_token=history_token, channels=("C0123",))
pages = poll_slack(cfg, request, http=http)
Google Drive
Drive files, Google Docs, changes, and push watches.
from mari_components.connectors import GoogleDriveConfig, poll_google_drive
cfg = GoogleDriveConfig(access_token=token, folder_id="folder-id")
pages = poll_google_drive(cfg, request, http=http)
# poll_google_drive_changes(...) and start_google_drive_watch(...)
Confluence
Cloud pages converted from storage HTML to Markdown-like text.
from mari_components.connectors import ConfluenceConfig, poll_confluence
cfg = ConfluenceConfig(site_url="https://acme.atlassian.net/wiki",
email="bot@acme.com", api_token=token, space_key="ENG")
pages = poll_confluence(cfg, request, http=http)
Dropbox
Native delta cursor with explicit deleted entries.
from mari_components.connectors import DropboxConfig, poll_dropbox
cfg = DropboxConfig(token=token, path="/Knowledge")
pages = poll_dropbox(cfg, request, http=http)
Notion
Page search and bounded block-tree ingestion.
from mari_components.connectors import NotionConfig, poll_notion
cfg = NotionConfig(token=token)
pages = poll_notion(cfg, request, http=http)
Airtable
Base metadata and table snapshots.
from mari_components.connectors import AirtableConfig, poll_airtable
cfg = AirtableConfig(token=token, base_id="appABC123")
pages = poll_airtable(cfg, request, http=http)
Asana
Workspace or project tasks with offset checkpoints.
from mari_components.connectors import AsanaConfig, poll_asana
cfg = AsanaConfig(token=token, workspace_gid="workspace-gid",
project_gid="project-gid")
pages = poll_asana(cfg, request, http=http)
Jira
Cloud issues with project or custom JQL scope.
from mari_components.connectors import JiraConfig, poll_jira
cfg = JiraConfig(site_url="https://acme.atlassian.net",
email="bot@acme.com", api_token=token, project_key="SUP")
pages = poll_jira(cfg, request, http=http)
Linear
Issues and comments through the GraphQL API.
from mari_components.connectors import LinearConfig, poll_linear
cfg = LinearConfig(api_key=api_key, team_id="team-id")
pages = poll_linear(cfg, request, http=http)
Trello
Open boards, lists, and cards.
from mari_components.connectors import TrelloConfig, poll_trello
cfg = TrelloConfig(api_key=api_key, token=token)
pages = poll_trello(cfg, request, http=http)
Zendesk
Guide articles with ordered page checkpoints.
from mari_components.connectors import ZendeskConfig, poll_zendesk
cfg = ZendeskConfig(subdomain="acme",
email="bot@acme.com", api_token=token)
pages = poll_zendesk(cfg, request, http=http)
GitLab
Repository documents with head cursors and resumable tree pages.
from mari_components.connectors import GitLabConfig, poll_gitlab
cfg = GitLabConfig(token=token, project="acme/handbook",
branch="main", paths=("docs/**", "README.md"))
pages = poll_gitlab(cfg, request, http=http)
Microsoft Graph drive deltas, downloads, and deleted items.
from mari_components.connectors import MicrosoftDriveConfig, poll_microsoft_drive
cfg = MicrosoftDriveConfig(access_token=token, drive_id="drive-id",
folder_id="root", provider="sharepoint")
pages = poll_microsoft_drive(cfg, request, http=http)
Box
Folder files with marker pagination.
from mari_components.connectors import BoxConfig, poll_box
cfg = BoxConfig(access_token=token, folder_id="0")
pages = poll_box(cfg, request, http=http)
RSS / Atom
Bounded XML feeds with ETag and Last-Modified conditional polling.
from mari_components.connectors import RSSConfig, poll_rss
cfg = RSSConfig(feed_url="https://example.com/feed.xml")
pages = poll_rss(cfg, request, http=http)
S3, GCS, and Azure Blob
SDK-neutral object listing and reading.
from mari_components.connectors import ObjectStoreConfig, poll_object_store
cfg = ObjectStoreConfig(provider="s3", container="knowledge", prefix="docs/")
pages = poll_object_store(cfg, request,
list_objects=s3_adapter.list_objects, read_object=s3_adapter.read_object)
Singer / Meltano
Singer RECORD and STATE messages from external taps.
from mari_components.connectors import singer_pages
pages = singer_pages(tap_stdout, document=normalize_record, page_size=100)
Local filesystem
Stable snapshots with content revisions and resumable bounded pages.
from pathlib import Path
from mari_components.connectors import FilesystemConfig, poll_filesystem
cfg = FilesystemConfig(root=Path("knowledge"), patterns=("*.md", "*.txt"))
pages = poll_filesystem(cfg, request)
JSON REST collections
Same-origin pagination with an injected record-to-document mapping.
from mari_components.connectors import JSONAPIConfig, poll_json_api
cfg = JSONAPIConfig(url="https://api.example.com/articles",
records_path=("data",), next_path=("paging", "next"))
pages = poll_json_api(cfg, request, http=http, document=normalize_article)
from mari_components import PollRequest
from mari_components.connectors import GitHubConfig, poll_github, validate_github
config = GitHubConfig(token=token, repository="acme/product",
paths=("docs/**",), content_types=("files", "issues"))
validation = validate_github(config, http=http)
request = PollRequest(cursor=saved_cursor, page_size=100, page_limit=20)
for page in poll_github(config, request, http=http):
consume(page)
Streaming
stream_hints requires a verifier, rejects oversized deliveries and batches, parses provider-specific hints, and coalesces repeated aggregate keys. It has no cursor or checkpoint. The application owns the webhook server, queue, acknowledgement, retries, and optional canonical hydration.
from mari_components.connectors import StreamEvent, stream_hints
event = StreamEvent(provider="slack", raw_body=raw_body, headers=headers)
for hint in stream_hints((event,), verify=verify_signature):
enqueue_canonical_refetch(hint)
Connector-specific capabilities
Eighteen catalog connectors: batch polling, validation, pagination limits, and normalized documents.
GitHub, GitLab, Slack, Google Drive, OneDrive, SharePoint, Confluence, and Box: verified, checkpoint-free streaming hints.
S3, GCS, and Azure Blob: injected SDK batch operations plus checkpoint-free provider-event parsing.
CloudEvents: verified generic dirty hints with no checkpoint state.
Singer/Meltano: bounded RECORD pages and surfaced STATE checkpoints without subprocess ownership.
Local filesystem: content-hashed snapshots with change detection across resumed batches.
JSON REST: bounded same-origin pages with application-defined document normalization.
Slack: canonical thread fetch by ID.
Google Drive: native Changes polling and push-watch registration.
Confluence: direct canonical page fetch.
ConnectorDefinition.supports(ConnectorMode.POLL | STREAM)exposes mode capabilities for setup UIs.
Standards and protocol basis
OpenAPI: HTTP operation contractsCloudEvents: event envelopesRFC 2104: HMAC verification
Permissive implementation references LlamaIndex connectors — MIT dlt filesystem/REST sources — Apache-2.0 Meltano Singer SDK — Apache-2.0 Unstructured ingestion — Apache-2.0
Provider pagination, cursor, and signature schemes differ. Mari normalizes their observable results; it does not claim a universal delivery guarantee.