Skip to content

feat(mcp): add Connector Builder project tools for hosted connector building - #1407

Merged
Aaron ("AJ") Steers (aaronsteers) merged 47 commits into
release-candidate/v1from
devin/1792350894-connector-builder-tools
Oct 20, 2026
Merged

Aaron ("AJ") Steers (aaronsteers) merged 47 commits into
release-candidate/v1from
devin/1792350894-connector-builder-tools

Conversation

@aaronsteers

@aaronsteers Aaron ("AJ") Steers (aaronsteers) commented Oct 18, 2026 •

Copy link
Copy Markdown
Member

Overview

👉 TL;DR: Lets an agent build and test a custom low-code source entirely through hosted Cloud MCP. The draft and the test credentials live in an Airbyte Cloud Connector Builder project, and test reads run on Airbyte Cloud, so nothing runs on the user's machine and secrets never pass through the agent.

Specifically, this adds CloudConnectorBuilderProject (airbyte/cloud/connector_builder/), CloudWorkspace.create_connector_builder_project() / get_connector_builder_project(), and 9 MCP tools: create_connector_builder_project, update_connector_builder_manifest_text, set_connector_builder_testing_values, run_connector_builder_stream_test_read, get_connector_builder_resolved_manifest, run_connector_builder_readiness_checks (readiness checks + per-stream test reads, optional full sync), list_connector_builder_published_versions, get_connector_builder_published_manifest, revert_connector_builder_published_version. All 9 are insiders_only (hidden unless AIRBYTE_MCP_INSIDERS / X-MCP-Insiders is on) until they graduate.

Changes

  • airbyte/_util/api_util.py: Config API helpers for connector_builder_projects/create, read_stream, full_resolve, publish, get_with_manifest (version), and declarative_source_definitions/list_manifests.
  • airbyte/cloud/connector_builder/ (new package; private _models.py result models and _util.py helpers, project.py the class; __init__.py exports the class and the 3 return types of its public methods: ConnectorBuilderStreamReadResult, ConnectorBuilderPageSummary, ConnectorBuilderResolvedManifest). Public CloudConnectorBuilderProject surface: builder_project_id, name, connector_builder_project_url, source_definition_id, draft_manifest_dict, draft_manifest_yaml, published_manifest_dict, replace_draft_manifest(), replace_testing_values(), run_stream_test_read(), get_resolved_manifest(), publish(pre_validate=..., description=None) (description defaults to Published by PyAirbyte at <UTC>; republishing uses Config API declarative_source_definitions/create_manifest so the description is kept), list_published_versions() → ConnectorBuilderPublishedVersion(version, is_active, description), get_published_manifest_dict(version=None) / get_published_manifest_yaml(version=None), revert_to_published_version(version, *, as_draft=True, description=None) (as_draft=True saves the version as the pending draft; False publishes it as a new active version and refuses if the draft has unpublished edits). Private (MCP-only for now, can graduate later): _get_info(), _update_draft_manifest_yaml(), _run_readiness_checks(), _get_or_create_default_test_source(), _run_full_sync(), and the readiness models (ConnectorBuilderReadinessCheck(description, result, detail) with result in passed/failed/unknown, ...).
  • airbyte/cloud/workspaces.py: create_connector_builder_project(), get_connector_builder_project(builder_project_id | definition_id), and a builder_project_id option on publish_custom_source_definition().
  • airbyte/cloud/connectors.py: private CustomCloudSourceDefinition._connector_builder_project (keeps the owning workspace for shared definitions); _unwrap_builder_manifest moved to the new module.
  • airbyte/mcp/connector_builder.py (new MCP module, register_connector_builder_tools, a Cloud module for policy filters): the 6 new tools, plus get_connector_builder_draft_manifest (moved from cloud.py), which now takes definition_id or builder_project_id and returns draft_manifest_yaml; publish_custom_source_definition takes an optional builder_project_id. Tools only parse args, call the project methods above, and return typed Pydantic result models (ConnectorBuilderDraftManifestResult, ConnectorBuilderProjectCreateResult, ConnectorBuilderStreamTestReadToolResult, ConnectorBuilderResolvedManifestResult, ConnectorBuilderReadinessReportResult). secret_reference:: guidance and testing_values_secret_name appear only with trusted execution (also on publish_custom_source_definition / update_custom_source_definition), the same way manifest_yaml_file does. Tools that mutate an existing project enforce the created-in-session guard (project ID or definition ID); test read, resolve and readiness report are external_access=True.
  • create_connector_builder_project(create_test_source=True): publishes v1, then CloudConnectorBuilderProject._get_or_create_default_test_source() creates <name> (Connector Builder test) on the definition with the non-secret testing values (deferred credentials when the spec has airbyte_secret fields or a required field without a value or default). The spec comes from the published manifest when the first publish cleared the draft. Returns definition_id, test_source_id, test_source_settings_url, so the user enters source credentials before the agent's heavy lifting.
  • run_connector_builder_readiness_checks(run_full_sync, test_source_id) → CloudConnectorBuilderProject._run_full_sync(): when nothing failed/pending/not-attempted (or no streams were named), checks the test source (an explicit test_source_id must be on this project's definition) and finds or creates the dev-null Connector Builder Test (No-op) destination (a same-name non-dev-null destination fails), all before publishing. Then publishes the draft (no draft: syncs the published version), selects every stream the test source discovers (streams.get_stream_properties, ignore_cache=True), reuses or creates the <name> (Connector Builder full sync) connection, and starts the sync without waiting. Returns full_sync (source_id, destination_id, destination_created, connection_id, connection_created, job_id, job_url). An on_resource_created callback registers each created destination/connection in the MCP session as soon as it exists; poll with get_cloud_sync_status.
  • Tests: tests/unit_tests/test_cloud_connector_builder.py (new); arg-trace fixture and trusted-execution schema test cover the new tools.

Review Spotlight

Reviewers with limited time, please review first:

  • apply_manifest_text_edit(): the replace_full / replace_text (exactly one match) / replace_all semantics.
  • CloudConnectorBuilderProject.publish(): first publish goes through Config API publish (creates v1, clears the draft); an already-published project adds a new active version via the Public API instead.
  • ConnectorBuilderStreamReadiness.from_stream_read(): a stream passes when it returns records with no HTTP >= 400 pages and no ERROR/FATAL logs (WARN is reported but doesn't fail).
  • CloudConnectorBuilderProject._run_readiness_checks(stream_names, timeout_seconds=None): reads any number of named streams in parallel (5 at a time, input order kept) at Cloud's max caps (10,000 records, 20 pages per slice, 20 slices). Each stream reports read_to_end (not test_read_limit_reached). The verdict covers only the named streams: passed means each one passed, was read to the end, and finished before the timeout. The report lists passed_streams, failed_streams, pending_streams (still reading at the timeout; results dropped, Cloud may still finish them; each read's HTTP timeout ends at the deadline) and not_attempted_streams (never started), plus checks (readiness checks derived from one project read, never stored) and next_steps (fix failures, resume with not-attempted streams, then publish and full-sync). The whole connector is validated by the full sync, not this report. After publishing, the readiness checks and tool description point to a full sync into a no-op destination (deploy_noop_destination_to_cloud, deploy_connector_to_cloud, create_connection_on_cloud, run_cloud_sync).
  • _redact_stream_diagnostics() in airbyte/mcp/connector_builder.py: test-read and readiness results are successful tool data, so the error middleware doesn't see them; page URLs, error bodies, logs and errors go through redact_agent_text() here.
  • New MCP tools in airbyte/mcp/connector_builder.py: names, arg names, and descriptions are proposals for review.

Design: one noun per state

Draft tools take builder_project_id or definition_id (exactly one). Every response returns both IDs; definition_id is null until the project is published. "Connector Builder project" is the draft workspace; "custom source definition" is the published artifact.

Risks

  • Config API dependency: drafts, testing values, test reads and resolve only exist on the Config API (cloud.airbyte.com/api/v1), which the platform treats as subject to change. PyAirbyte already depends on it for get_with_manifest and update_testing_values.
  • Draft text is a normalized YAML rendering: Cloud stores the parsed manifest, so comments and original formatting are not preserved (the Builder UI behaves the same way).
  • The agent and the Builder UI write the same single draft slot; concurrent edits overwrite each other.
  • Cloud test reads stop at 20 pages per slice and 20 slices, so large streams can't be read to the end on a draft; the report says so per stream (read_to_end: false) and won't pass. The full sync after publishing is the real end-to-end check.
  • Parallel reads (5 at a time) against the Cloud builder server: throughput and rate limits not measured yet.
  • Test source: users enter source credentials separately from Builder testing values (no Cloud route copies them). The deferred-source path for a custom definition hasn't been run live.
  • Not yet tested against a live Cloud workspace; only unit tests with mocked API calls.

Follow-ups

  • End-to-end check against a real Cloud workspace (create → edit → testing values → test read → readiness checks → publish).
  • Port connector-builder-mcp's YAML guidance content behind the existing docs tools.

Test plan

  • uv run pytest tests/unit_tests/test_cloud_connector_builder.py tests/unit_tests/test_mcp_cloud.py tests/unit_tests/test_mcp_arg_trace_parity.py tests/unit_tests/test_mcp_tool_annotations.py (touched tests pass on latest push).
  • ruff check, ruff format, pyrefly check, ./scripts/check_docstring_markdown.uv

Link to Devin session: https://app.devin.ai/sessions/1c8e32703d37402a9c8db8aaffe27db7
Open in Devin Desktop: https://app.devin.ai/desktop/session/1c8e32703d37402a9c8db8aaffe27db7?variant=devin
Requested by: Aaron ("AJ") Steers (@aaronsteers)

devin-ai-integration Bot and others added 2 commits October 18, 2026 19:27
…test reads, and resolve tools

Co-Authored-By: AJ Steers <aj@airbyte.io>
Co-Authored-By: AJ Steers <aj@airbyte.io>
@devin-ai-integration

Copy link
Copy Markdown
Contributor

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@github-actions

Copy link
Copy Markdown

👋 Greetings, Airbyte Team Member!

Here are some helpful tips and reminders for your convenience.

💡 Show Tips and Tricks

Testing This PyAirbyte Version

You can test this version of PyAirbyte using the following:

# Run PyAirbyte CLI from this branch:
uvx --from 'git+https://github.com/airbytehq/PyAirbyte.git@devin/1792350894-connector-builder-tools' pyairbyte --help

# Install PyAirbyte from this branch for development:
pip install 'git+https://github.com/airbytehq/PyAirbyte.git@devin/1792350894-connector-builder-tools'

PR Slash Commands

Airbyte Maintainers can execute the following slash commands on your PR:

  • /fix-pr - Fixes most formatting and linting issues
  • /uv-lock - Updates uv.lock file
  • /test-pr - Runs tests with the updated PyAirbyte
  • /prerelease - Builds and publishes a prerelease version to PyPI
  • /evals - Runs the Cloud MCP evals that use the MCP tools this PR changed (/evals full=true runs the full suite)
📚 Show Repo Guidance

Helpful Resources

Community Support

Questions? Join the #pyairbyte channel in our Slack workspace.

📝 Edit this welcome message.

…ch repo convention

Co-Authored-By: AJ Steers <aj@airbyte.io>
@github-code-quality

github-code-quality Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Code coverage overview

Languages: Python

Python / code-coverage/pytest-no-creds

release-candidate/v1 d9f652f devin/1792350894-con... b914836 +/-
65% 80% +15%
View coverage of the 10 most impacted files.
File release-candidate/v1 d9f652f devin/1792350894-con... b914836 +/-
airbyte/_util/api_util.py 36% 67% +31%
airbyte/mcp/cloud.py 52% 85% +33%
airbyte/cloud/connectors.py 34% 79% +45%
airbyte/mcp/_datadog.py 0% 50% +50%
airbyte/mcp/_telemetry.py 0% 94% +94%
airbyte/cloud/c...lder/project.py 0% 94% +94%
airbyte/_direct...ctors/models.py 0% 95% +95%
airbyte/mcp/_sso_auth.py 0% 96% +96%
airbyte/cloud/models.py 0% 97% +97%
airbyte/mcp/int...nc_status_ui.py 0% 97% +97%

Python / code-coverage/pytest

release-candidate/v1 d9f652f devin/1792350894-con... b914836 +/-
71% 82% +11%
View coverage of the 10 most impacted files.
File release-candidate/v1 d9f652f devin/1792350894-con... b914836 +/-
airbyte/cloud/connectors.py 51% 82% +31%
airbyte/mcp/cloud.py 52% 85% +33%
airbyte/mcp/_datadog.py 0% 50% +50%
airbyte/mcp/_user_identity.py 0% 93% +93%
airbyte/mcp/_telemetry.py 0% 94% +94%
airbyte/cloud/c...lder/project.py 0% 94% +94%
airbyte/_direct...ctors/models.py 0% 95% +95%
airbyte/mcp/_sso_auth.py 0% 96% +96%
airbyte/cloud/models.py 0% 97% +97%
airbyte/mcp/int...nc_status_ui.py 0% 97% +97%

Python / code-coverage/pytest-unit

release-candidate/v1 devin/1792350894-con... b914836 +/-
— 77% —

Line coverage data for the release-candidate/v1 branch is not yet available.

View coverage of the 10 most covered files.
File release-candidate/v1 devin/1792350894-con... b914836 +/-
airbyte/cloud/models.py — 97% —
airbyte/mcp/_sso_auth.py — 96% —
airbyte/_direct...ctors/models.py — 95% —
airbyte/cloud/client.py — 90% —
airbyte/exceptions.py — 90% —
airbyte/mcp/cloud.py — 85% —
airbyte/progress.py — 80% —
airbyte/cloud/connectors.py — 79% —
airbyte/shared/...ql_processor.py — 68% —
airbyte/_util/api_util.py — 67% —

ℹ️ Calculations represent line coverage. Results may change as calculations are updated.


Updated October 20, 2026 06:04 UTC

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits October 18, 2026 19:39
…workspace, pre_validate, single-read draft info)

Co-Authored-By: AJ Steers <aj@airbyte.io>
…ist tools

Co-Authored-By: AJ Steers <aj@airbyte.io>

This comment was marked as resolved.

…treams, check name before saving draft

Co-Authored-By: AJ Steers <aj@airbyte.io>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Cross-API publishing and credential workflows need live Cloud validation and human review beyond the mocked tests.

No open issues 🎉

3 previously missed issues

In code that hasn't changed since last review

Medium severity Convert documentation and OAuth metadata to API field names

airbyte/​cloud/​connector_builder.py:143

First publication sends this object as initialDeclarativeManifest.spec, but only connection_specification is converted to the API's camelCase keys. documentation_url and advanced_auth therefore do not populate documentationUrl and advancedAuth, leaving documentation and OAuth metadata missing from the published spec. Reuse the conversion in _builder_testing_values_spec(), which also matches the existing testing-values conversion in connectors.py.

Medium severity Accept input-free connection schemas with empty properties

airbyte/​cloud/​connector_builder.py:666

A valid input-free connector can define connection_specification: {type: object, properties: {}}, as the test fixture does. Requiring nonempty properties marks that spec as missing and keeps asking for it in next_steps. Check whether the schema is defined instead of whether it has user inputs.

Medium severity Treat empty testing configuration as valid for input-free connectors

airbyte/​cloud/​connector_builder.py:675

For an input-free connector, {} is a valid testing configuration. Even after set_testing_values({}) succeeds, this truthiness check marks the step incomplete and keeps telling the agent to enter testing values or secrets. Treat the step as satisfied or not applicable when the defined connection schema accepts an empty configuration; retain the missing-values check when configuration is required.

Review effort: Balanced

devin-ai-integration Bot and others added 2 commits October 18, 2026 20:17
…ctors in checklist

Co-Authored-By: AJ Steers <aj@airbyte.io>
…th explicit streams

Co-Authored-By: AJ Steers <aj@airbyte.io>

This comment was marked as resolved.

…an read errors

Co-Authored-By: AJ Steers <aj@airbyte.io>

This comment was marked as resolved.

Comment thread airbyte/cloud/connector_builder/project.py Outdated
Comment thread airbyte/cloud/connector_builder/project.py Outdated
Comment thread airbyte/mcp/connector_builder.py Outdated
Comment thread airbyte/mcp/connector_builder.py Outdated
Comment thread airbyte/mcp/connector_builder.py Outdated
…draft_manifest_yaml and replace_testing_values, one arg per line in MCP tool decorators

Co-Authored-By: AJ Steers <aj@airbyte.io>
Comment thread airbyte/cloud/connector_builder/project.py Outdated
Comment thread airbyte/cloud/connector_builder/project.py
Comment thread airbyte/mcp/connector_builder.py Outdated
Comment thread airbyte/mcp/connector_builder.py Outdated
Comment thread airbyte/mcp/connector_builder.py Outdated
Comment thread airbyte/mcp/connector_builder.py Outdated
devin-ai-integration Bot and others added 3 commits October 20, 2026 04:03
…ith trusted execution

Co-Authored-By: AJ Steers <aj@airbyte.io>
…est versions

Co-Authored-By: AJ Steers <aj@airbyte.io>
Comment thread airbyte/cloud/connector_builder/project.py
Comment thread airbyte/cloud/connector_builder/project.py Outdated
Comment thread airbyte/cloud/connector_builder/project.py Outdated
Comment thread airbyte/cloud/connector_builder/project.py Outdated
devin-ai-integration Bot and others added 2 commits October 20, 2026 05:28
…d revert, defaulting to a UTC timestamp

Co-Authored-By: AJ Steers <aj@airbyte.io>
Comment thread airbyte/mcp/connector_builder.py Outdated
devin-ai-integration Bot and others added 2 commits October 20, 2026 05:43
…aved on Cloud

Co-Authored-By: AJ Steers <aj@airbyte.io>
…lues tool

Co-Authored-By: AJ Steers <aj@airbyte.io>
Comment thread airbyte/mcp/connector_builder.py Outdated
…_values

Co-Authored-By: AJ Steers <aj@airbyte.io>
Comment thread airbyte/mcp/connector_builder.py
@aaronsteers
Aaron ("AJ") Steers (aaronsteers) merged commit 9edd3ce into release-candidate/v1 Oct 20, 2026
29 checks passed
@aaronsteers
Aaron ("AJ") Steers (aaronsteers) deleted the devin/1792350894-connector-builder-tools branch October 20, 2026 06:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants