Skip to content

feat(mcp): add get_external_sql_schema and list valid destination IDs on SQL errors - #1469

Open
Caleb Evans (calebevans-ab) wants to merge 9 commits into
release-candidate/v1from
devin/1794513113-sql-schema-tool
Open

Caleb Evans (calebevans-ab) wants to merge 9 commits into
release-candidate/v1from
devin/1794513113-sql-schema-tool

Conversation

@calebevans-ab

@calebevans-ab Caleb Evans (calebevans-ab) commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Overview

👉 TL;DR: Agents querying warehouse data through the Cloud MCP can now look up tables and columns in one call, and a wrong destination id now returns the list of valid ones instead of a bare failure. The descriptions of the search and SQL tools are also rewritten neutrally, so each one says what it is good for and what it is not.

Specifically, this adds the get_external_sql_schema tool, makes execute_external_sql_query raise an AirbyteLibInputError listing SQL-passthrough destinations (id, name, dialect), and rebalances the execute_external_search_query / execute_external_sql_query docstrings.

Changes

  • New read-only tool get_external_sql_schema(connector_id, table_name_contains=None, max_tables=20): returns qualified table names with one line per column (name type - meaning). It runs metadata-only SHOW TABLES and DESCRIBE TABLE and never reads rows. A column's meaning comes from the JSON-schema description of a selected stream in a connection to that destination, when one exists. truncated is set when matches exceed max_tables or SHOW TABLES reports another page. The logic lives in the new airbyte/cloud/sql.py.
  • execute_external_sql_query and the new tool now check the destination first (_get_sql_destination). A missing id, a source id, or a destination without SQL passthrough fails with Connector '<id>' is not an available SQL-passthrough destination., and the guidance lists the valid destinations as id, name, dialect. The list comes from the workspace that owns the connector (or the requested or pinned workspace), not the default workspace. Only AirbyteMissingResourceError is converted. If the listing itself fails, the original error is kept as the cause. A new SqlDestinationInputError in airbyte/mcp/_error_handling.py keeps this guidance in the text the agent receives, even when the formatter picks a chained Cloud error.
  • Neutral description review: the search and SQL docstrings now each state capabilities and limits (SQL: 254 -> 177 words; search, rewritten on top of the snippet-result wording from release-candidate/v1: 235 words). No cross-tool ordering advice was added. describe_connector, describe_connection and execute_external_api_query got light "not for" clarifications.
  • AGENTS.md: the agent-facing Cloud error policy now lists SQL-destination recovery guidance (valid destination IDs, appended after the Cloud text) as a permitted addition.
  • Tests: new tests/unit_tests/test_cloud_sql_schema.py, plus updated tool-annotation, external-access policy and arg-trace snapshots.

Review Spotlight

Reviewers with limited time, please review first:

Risks

  • get_external_sql_schema was not run against a live warehouse. In the smoke test the Cloud BigQuery destination had external access disabled, and I did not change that setting. Coverage is unit tests with mocks only.
  • The schema tool makes one DESCRIBE TABLE call per table, up to max_tables.

Test plan

  • Review-fix commits add tests for the workspace used in recovery, pagination truncation, unselected streams, and guidance reaching the agent through the MCP error middleware.
  • uv run poe check: passes
  • uv run pytest on the schema, MCP Cloud, arg-trace, annotation, tool-policy and Cloud describe test files, with the Cloud credential env vars unset: 452 passed after rebasing onto release-candidate/v1
  • One unrelated, pre-existing failure appears in test_cloud_direct_execute.py::test_agent_request_problem_message_and_guidance when run together with the MCP tests (the global MCP mode is switched on at collection time)

Link to Devin session: https://app.devin.ai/sessions/7364cd512f9c451988468ff085fb021c

@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/1794513113-sql-schema-tool' pyairbyte --help

# Install PyAirbyte from this branch for development:
pip install 'git+https://github.com/airbytehq/PyAirbyte.git@devin/1794513113-sql-schema-tool'

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.

@github-code-quality

github-code-quality Bot commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Code coverage overview

Languages: Python

Python / code-coverage/pytest-no-creds

release-candidate/v1 d9f652f devin/1794513113-sql... 4c529ca +/-
65% 81% +16%
View coverage of the 10 most impacted files.
File release-candidate/v1 d9f652f devin/1794513113-sql... 4c529ca +/-
airbyte/_util/api_util.py 36% 68% +32%
airbyte/mcp/cloud.py 52% 87% +35%
airbyte/cloud/connectors.py 34% 81% +47%
airbyte/cloud/connections.py 26% 76% +50%
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% 96% +96%

Python / code-coverage/pytest

release-candidate/v1 d9f652f devin/1794513113-sql... 4c529ca +/-
71% 83% +12%
View coverage of the 10 most impacted files.
File release-candidate/v1 d9f652f devin/1794513113-sql... 4c529ca +/-
airbyte/cloud/connectors.py 51% 84% +33%
airbyte/mcp/cloud.py 52% 87% +35%
airbyte/cloud/connections.py 34% 78% +44%
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% 96% +96%
airbyte/mcp/int...nc_status_ui.py 0% 97% +97%

Python / code-coverage/pytest-unit

release-candidate/v1 devin/1794513113-sql... 4c529ca +/-
— 78% —

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/1794513113-sql... 4c529ca +/-
airbyte/mcp/_sso_auth.py — 96% —
airbyte/cloud/models.py — 96% —
airbyte/_direct...ctors/models.py — 95% —
airbyte/cloud/client.py — 91% —
airbyte/mcp/cloud.py — 87% —
airbyte/cloud/connectors.py — 81% —
airbyte/progress.py — 80% —
airbyte/cloud/connections.py — 76% —
airbyte/_util/api_util.py — 68% —
airbyte/shared/...ql_processor.py — 68% —

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


Updated November 12, 2026 21:51 UTC

@devin-ai-integration

devin-ai-integration Bot commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

Devin Review

🟢 Devin Review found nothing to fix · View findings · Follow Devin's work

@calebevans-ab

Copy link
Copy Markdown
Contributor Author

Devin and you give me an example of what a schema might look like when returned back to the agent?

@calebevans-ab

Copy link
Copy Markdown
Contributor Author

Codex (@codex) review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 12, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-12T20:24:47.286857Z 784fed5 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Caleb Evans (@calebevans-ab) here's what get_external_sql_schema would return for the study's GitHub pull_requests and Zendesk tickets tables, i.e. connector_id=<bigquery dest>, table_name_contains=None, trimmed to those two tables.

This is built, not live. The only BigQuery destination I can reach has external access disabled, and my credentials can't see the study workspace. I took the column names and meanings from the stream catalogs (GitHub pull_requests from a synced Cloud connection catalog, Zendesk tickets from the connector's manifest schema). Types use the BigQuery destination's standard mapping, and the project/dataset names are placeholders.

Size: about 980 tokens for both tables as compact JSON (Anthropic count_tokens, Sonnet 4.5). That's roughly 600 for pull_requests (41 columns) and 300 for tickets (45 columns).

One thing this shows: the GitHub catalog gives a meaning for 35 of its 37 fields, while the Zendesk tickets schema has a description on only 1 of 41. So for Zendesk the agent mainly gets names, types, and the JSON flag (e.g. via, custom_fields, tags), with no meanings.

Example return value (pretty-printed; the agent receives the same structure)
{
  "dialect": "bigquery",
  "tables": [
    {
      "table": "`study-project.ablation_github.pull_requests`",
      "columns": [
        "_airbyte_raw_id STRING - ",
        "_airbyte_extracted_at TIMESTAMP - ",
        "_airbyte_meta JSON - ",
        "_airbyte_generation_id INT64 - ",
        "issue_url STRING - URL for viewing the issue associated with this pull request",
        "_links JSON - Object containing links related to the pull request.",
        "diff_url STRING - URL to view the diff for this pull request",
        "assignees JSON - Users assigned to this pull request",
        "created_at TIMESTAMP - Date and time when the pull request was created",
        "requested_reviewers JSON - Requested reviewers for this pull request",
        "body STRING - Body content of the pull request",
        "title STRING - Title of the pull request",
        "repository STRING - Repository information",
        "requested_teams JSON - Requested teams for this pull request",
        "head JSON - Head branch information",
        "author_association STRING - Association of the author with this pull request",
        "number INT64 - Number assigned to the pull request",
        "patch_url STRING - URL for fetching the patch file for this pull request",
        "updated_at TIMESTAMP - Date and time when the pull request was last updated",
        "draft BOOL - Indicates if the pull request is a draft",
        "comments_url STRING - URL for fetching comments on this pull request",
        "merge_commit_sha STRING - SHA hash of the merged commit",
        "review_comment_url STRING - URL for fetching review comments on this pull request",
        "active_lock_reason STRING - Reason this pull request is locked",
        "id INT64 - Unique identifier for the pull request",
        "state STRING - State of the pull request",
        "locked BOOL - Indicates if the pull request is locked",
        "commits_url STRING - URL for fetching commits on this pull request",
        "closed_at TIMESTAMP - Date and time when the pull request was closed",
        "statuses_url STRING - URL for fetching status information for this pull request",
        "merged_at TIMESTAMP - Date and time when the pull request was merged",
        "auto_merge JSON - Details about automatic merging of this pull request",
        "url STRING - URL for fetching detailed information about this pull request",
        "labels JSON - Labels attached to this pull request",
        "milestone JSON - Milestone information for this pull request",
        "html_url STRING - URL for viewing the pull request on GitHub",
        "review_comments_url STRING - URL for fetching review comments on this pull request",
        "assignee JSON - ",
        "user JSON - ",
        "base JSON - Base branch information",
        "node_id STRING - Node identifier for the pull request"
      ]
    },
    {
      "table": "`study-project.ablation_zendesk.tickets`",
      "columns": [
        "_airbyte_raw_id STRING - ",
        "_airbyte_extracted_at TIMESTAMP - ",
        "_airbyte_meta JSON - ",
        "_airbyte_generation_id INT64 - ",
        "organization_id INT64 - ",
        "requester_id INT64 - ",
        "problem_id INT64 - ",
        "is_public BOOL - ",
        "description STRING - ",
        "follower_ids JSON - ",
        "submitter_id INT64 - ",
        "generated_timestamp INT64 - ",
        "brand_id INT64 - ",
        "id INT64 - ",
        "group_id INT64 - ",
        "type STRING - ",
        "recipient STRING - ",
        "collaborator_ids JSON - ",
        "tags JSON - ",
        "has_incidents BOOL - ",
        "created_at TIMESTAMP - ",
        "raw_subject STRING - ",
        "status STRING - ",
        "updated_at TIMESTAMP - ",
        "fields JSON - ",
        "custom_fields JSON - ",
        "url STRING - ",
        "allow_channelback BOOL - ",
        "allow_attachments BOOL - ",
        "due_at TIMESTAMP - ",
        "followup_ids JSON - ",
        "priority STRING - ",
        "assignee_id INT64 - ",
        "subject STRING - ",
        "external_id STRING - ",
        "via JSON - ",
        "ticket_form_id INT64 - ",
        "deleted_ticket_form_id INT64 - ",
        "satisfaction_rating JSON - ",
        "sharing_agreement_ids JSON - ",
        "email_cc_ids JSON - ",
        "forum_topic_id INT64 - ",
        "custom_status_id INT64 - ",
        "from_messaging_channel BOOL - ",
        "result_type STRING - The type of search result (added by Export Search Results endpoint)."
      ]
    }
  ],
  "truncated": false,
  "warnings": []
}```
</details>

---
Posted by [Devin](https://app.devin.ai/sessions/7364cd512f9c451988468ff085fb021c), on behalf of @calebevans-ab.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration
devin-ai-integration Bot force-pushed the devin/1794513113-sql-schema-tool branch from 7ab5790 to 8e25bfc Compare November 12, 2026 20:44

@devin-ai-integration devin-ai-integration Bot 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.

Devin Review found 1 finding. Devin automatically fixed it.

Fixed by Devin (1)
  • Unapproved guidance on Cloud errors — Appending the valid destination IDs to the Cloud 404 is the behavior the requester asked for. It adds to the Cloud text and never overrides it. Updated the agent-facing error policy in AGENTS.md to list SQL-destination recovery guidance as a permitted addition.

View findings in Devin Review · Follow Devin's work

Devin Review

@devin-ai-integration
devin-ai-integration Bot marked this pull request as ready for review November 12, 2026 21:01
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

This branch has not been deployed

No deployments
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.

1 participant