diff --git a/.github/ISSUE_TEMPLATE/airbyte-mcp-beta.yml b/.github/ISSUE_TEMPLATE/airbyte-mcp-beta.yml new file mode 100644 index 000000000..9e119f9cb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/airbyte-mcp-beta.yml @@ -0,0 +1,72 @@ +name: Airbyte MCP beta feedback +description: Report a bug, request a feature, or share feedback about the Airbyte MCP server. +title: "[Airbyte MCP beta]: " +labels: [airbyte-mcp-beta] +body: + - type: markdown + attributes: + value: | + Thanks for testing the Airbyte MCP server. Your feedback helps us shape it before general availability. + + Don't paste API keys, client secrets, passwords, or connector credentials into this issue. GitHub issues in this repository are public. + - type: dropdown + id: feedback-type + attributes: + label: Feedback type + options: + - Bug + - Feature request + - Documentation + - Other feedback + validations: + required: true + - type: dropdown + id: deployment + attributes: + label: How are you running the MCP server? + options: + - Hosted on Airbyte Cloud + - Local (`uvx airbyte-mcp`) + - Self-hosted over HTTP (`airbyte-mcp-http`) + - Not sure + validations: + required: true + - type: input + id: mcp-client + attributes: + label: MCP client + description: The app or agent you connected to the server, and its version if you know it. + placeholder: Claude Desktop, Claude Code, Cursor, VS Code, Codex + validations: + required: true + - type: input + id: pyairbyte-version + attributes: + label: PyAirbyte version + description: For local and self-hosted servers, check the `airbyte@` pin in your MCP config. If you use `airbyte@latest`, enter `latest`. Leave blank for the hosted server. + - type: textarea + id: description + attributes: + label: What happened? + description: Describe the problem or idea. If you're reporting a bug, include the prompt you gave your agent and the MCP tools it called, if you know them. + validations: + required: true + - type: textarea + id: expected + attributes: + label: What did you expect to happen? + - type: textarea + id: steps + attributes: + label: Steps to reproduce + description: For bugs, list the steps that lead to the problem. + placeholder: | + 1. Ask the agent to ... + 2. The agent calls ... + 3. ... + - type: textarea + id: logs + attributes: + label: Relevant log output + description: Paste any error messages or MCP server logs. Remove secrets first. This field is formatted as code automatically. + render: shell diff --git a/.github/workflows/poe-command.yml b/.github/workflows/poe-command.yml index ac8e044bf..51b1cf1ba 100644 --- a/.github/workflows/poe-command.yml +++ b/.github/workflows/poe-command.yml @@ -28,7 +28,7 @@ jobs: private-key: ${{ secrets.OCTAVIA_BOT_PRIVATE_KEY }} - name: Run Poe Slash Command Processor - uses: aaronsteers/poe-command-processor@v1.3.3 + uses: airbytehq/poe-command-processor@v1.3.3 with: pr: ${{ github.event.inputs.pr }} comment-id: ${{ github.event.inputs.comment-id }} diff --git a/.github/workflows/release_drafter.yml b/.github/workflows/release_drafter.yml index 7863690f0..ba734e9b6 100644 --- a/.github/workflows/release_drafter.yml +++ b/.github/workflows/release_drafter.yml @@ -33,7 +33,7 @@ jobs: fetch-depth: 1 - name: Create draft release (not ready) - uses: aaronsteers/semantic-pr-release-drafter@v2.5.1 + uses: airbytehq/semantic-pr-release-drafter@v2.5.1 id: not-ready-draft env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -52,7 +52,7 @@ jobs: run: UV_DYNAMIC_VERSIONING_BYPASS="${VERSION#v}" uv build - name: Attach assets and finalize draft - uses: aaronsteers/semantic-pr-release-drafter@v2.5.1 + uses: airbytehq/semantic-pr-release-drafter@v2.5.1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/.github/workflows/tk-todo-check.yml b/.github/workflows/tk-todo-check.yml index 48ed49129..4e17d4443 100644 --- a/.github/workflows/tk-todo-check.yml +++ b/.github/workflows/tk-todo-check.yml @@ -18,4 +18,4 @@ jobs: uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 - name: Check for TK-TODO markers # IGNORE:TK - uses: aaronsteers/tk-todo-check-action@76cd8dbb434bc93c7898ebdf43eff6105ca186ac # v1.0.0 IGNORE:TK + uses: airbytehq/tk-todo-check-action@76cd8dbb434bc93c7898ebdf43eff6105ca186ac # v1.0.0 IGNORE:TK diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 15ae64644..744af4fe3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,6 +12,6 @@ Use **Markdown** formatting in all docstrings — not reStructuredText (reST). ## 🚀 Releasing -This project uses [`semantic-pr-release-drafter`](https://github.com/aaronsteers/semantic-pr-release-drafter) for automated release management. To release, simply click "`Edit`" on the latest release draft from the [releases page](https://github.com/airbytehq/PyAirbyte/releases), and then click "`Publish release`". This publish operation will trigger all necessary downstream publish operations. +This project uses [`semantic-pr-release-drafter`](https://github.com/airbytehq/semantic-pr-release-drafter) for automated release management. To release, simply click "`Edit`" on the latest release draft from the [releases page](https://github.com/airbytehq/PyAirbyte/releases), and then click "`Publish release`". This publish operation will trigger all necessary downstream publish operations. -â„šī¸ For more detailed instructions, please see the [Releasing Guide](https://github.com/aaronsteers/semantic-pr-release-drafter/blob/main/docs/releasing.md). +â„šī¸ For more detailed instructions, please see the [Releasing Guide](https://github.com/airbytehq/semantic-pr-release-drafter/blob/main/docs/releasing.md). diff --git a/airbyte/_util/api_util.py b/airbyte/_util/api_util.py index e64460517..84dd2f9a1 100644 --- a/airbyte/_util/api_util.py +++ b/airbyte/_util/api_util.py @@ -60,6 +60,28 @@ """Connect and read timeouts for a deferred-credential create on the Config API.""" +def _register_queued_job_status() -> None: + """Register the `queued` job status on the `airbyte-api` SDK enum. + + The Airbyte API returns `queued` for jobs waiting to start, but `airbyte-api<1.0` doesn't + define it, so decoding any job response with that status raises a `ValueError`. + """ + sdk_enum: Any = models.JobStatusEnum + if "queued" in sdk_enum._value2member_map_: + return + + member: Any = str.__new__(sdk_enum, "queued") + member._name_ = "QUEUED" + member._value_ = "queued" + sdk_enum.QUEUED = member + sdk_enum._member_names_.append("QUEUED") + sdk_enum._member_map_["QUEUED"] = member + sdk_enum._value2member_map_["queued"] = member + + +_register_queued_job_status() + + def status_ok(status_code: int) -> bool: """Check if a status code is OK.""" return status_code >= 200 and status_code < 300 # noqa: PLR2004 # allow inline magic numbers diff --git a/airbyte/cloud/models.py b/airbyte/cloud/models.py index 6cde86c2d..6140ce55b 100644 --- a/airbyte/cloud/models.py +++ b/airbyte/cloud/models.py @@ -92,6 +92,7 @@ class JobStatusEnum(str, Enum): """Status values for an Airbyte Cloud job.""" PENDING = "pending" + QUEUED = "queued" RUNNING = "running" INCOMPLETE = "incomplete" FAILED = "failed" diff --git a/airbyte/mcp/cloud.py b/airbyte/mcp/cloud.py index 1247d6785..e52f63e54 100644 --- a/airbyte/mcp/cloud.py +++ b/airbyte/mcp/cloud.py @@ -411,7 +411,7 @@ class SyncJobResult(BaseModel): job_id: int """The job ID.""" status: str - """The job status (e.g., 'succeeded', 'failed', 'running', 'pending').""" + """The job status (e.g., 'succeeded', 'failed', 'running', 'queued', 'pending').""" bytes_synced: int """Number of bytes synced in this job.""" records_synced: int diff --git a/airbyte/mcp/http_main.py b/airbyte/mcp/http_main.py index 30a185a94..383d77087 100644 --- a/airbyte/mcp/http_main.py +++ b/airbyte/mcp/http_main.py @@ -170,7 +170,7 @@ # Human-facing landing page shown when a browser GETs the MCP endpoint. MCP_LANDING_TITLE = "Airbyte MCP Server" -MCP_LANDING_DOCS_URL = "https://docs.airbyte.com/community/mcp-servers/replication-mcp" +MCP_LANDING_DOCS_URL = "https://docs.airbyte.com/platform/airbyte-mcp" RELEASE_TAG_URL_TEMPLATE = "https://github.com/airbytehq/PyAirbyte/releases/tag/v{}" COMMIT_URL_TEMPLATE = "https://github.com/airbytehq/PyAirbyte/commit/{}" RELEASES_URL = "https://github.com/airbytehq/PyAirbyte/releases" diff --git a/tests/unit_tests/test_cloud_api_util.py b/tests/unit_tests/test_cloud_api_util.py index dfa04aa0b..8d0e38bdd 100644 --- a/tests/unit_tests/test_cloud_api_util.py +++ b/tests/unit_tests/test_cloud_api_util.py @@ -3,6 +3,7 @@ from __future__ import annotations +import json from collections.abc import Callable from types import SimpleNamespace @@ -10,6 +11,7 @@ import requests from airbyte import constants from airbyte._util import api_util, meta +from airbyte.cloud.models import CloudJobInfo, JobStatusEnum from airbyte.exceptions import ( AirbyteError, AirbyteMissingResourceError, @@ -17,7 +19,7 @@ PyAirbyteInputError, ) from airbyte.secrets.base import SecretString -from airbyte_api import api, models +from airbyte_api import api, models, utils from airbyte_api.errors import SDKError @@ -966,6 +968,26 @@ def test_list_connections_rejects_invalid_limits(limit: int) -> None: ) +def test_sdk_decodes_queued_job_status() -> None: + payload = { + "data": [ + { + "connectionId": "connection-id", + "jobId": 1, + "jobType": "sync", + "startTime": "2026-01-01T00:00:00Z", + "status": "queued", + } + ] + } + + response = utils.unmarshal_json(json.dumps(payload), models.JobsResponse) + job = response.data[0] + + assert job.status is models.JobStatusEnum("queued") + assert CloudJobInfo.from_api_response(job).status is JobStatusEnum.QUEUED + + def test_get_job_logs_paginates_until_limit(monkeypatch: pytest.MonkeyPatch) -> None: """Verify job log pagination stops after collecting the requested limit.""" captured_requests: list[api.ListJobsRequest] = []