airbyte.mcp.cloud

Airbyte Cloud MCP operations.

cloud module

MCP primitives registered by the cloud module of the airbyte-mcp server: 39 tool(s), 0 prompt(s), 0 resource(s).

Tools (39)

cancel_cloud_sync

Hints: destructive · open-world

Cancel a running sync job on an Airbyte Cloud connection.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
connection_id string yes The ID of the Airbyte Cloud connection.
job_id integer | null no null Optional job ID to cancel. If not provided, the connection's most recent sync job will be cancelled. Other job types require an explicit job ID.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "connection_id": {
      "description": "The ID of the Airbyte Cloud connection.",
      "type": "string"
    },
    "job_id": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional job ID to cancel. If not provided, the connection's most recent sync job will be cancelled. Other job types require an explicit job ID."
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    }
  },
  "required": [
    "connection_id"
  ],
  "type": "object"
}

Show output JSON schema

{
  "description": "Information about a sync job.",
  "properties": {
    "job_id": {
      "type": "integer"
    },
    "status": {
      "type": "string"
    },
    "bytes_synced": {
      "type": "integer"
    },
    "records_synced": {
      "type": "integer"
    },
    "start_time": {
      "type": "string"
    },
    "job_url": {
      "type": "string"
    }
  },
  "required": [
    "job_id",
    "status",
    "bytes_synced",
    "records_synced",
    "start_time",
    "job_url"
  ],
  "type": "object"
}

check_airbyte_cloud_workspace

Hints: read-only · idempotent · open-world

Check if we have a valid Airbyte Cloud connection and return workspace info.

Returns workspace details including workspace ID, name, organization info, and billing status.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    }
  },
  "type": "object"
}

Show output JSON schema

{
  "description": "Information about a workspace in Airbyte Cloud.",
  "properties": {
    "workspace_id": {
      "type": "string"
    },
    "workspace_name": {
      "type": "string"
    },
    "workspace_url": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "organization_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ]
    },
    "organization_name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "payment_status": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "subscription_status": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "is_account_locked": {
      "default": false,
      "type": "boolean"
    }
  },
  "required": [
    "workspace_id",
    "workspace_name",
    "organization_id"
  ],
  "type": "object"
}

check_cloud_destination

Hints: read-only · idempotent · open-world

Check the configuration and credentials of a deployed destination connector.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
destination_id string yes The ID of the deployed destination connector to check.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "destination_id": {
      "description": "The ID of the deployed destination connector to check.",
      "type": "string"
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    }
  },
  "required": [
    "destination_id"
  ],
  "type": "object"
}

Show output JSON schema

{
  "description": "Result of a connection check against a deployed Cloud connector.",
  "properties": {
    "connector_id": {
      "type": "string"
    },
    "connector_type": {
      "enum": [
        "source",
        "destination"
      ],
      "type": "string"
    },
    "succeeded": {
      "type": "boolean"
    },
    "message": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "required": [
    "connector_id",
    "connector_type",
    "succeeded",
    "message"
  ],
  "type": "object"
}

check_cloud_source

Hints: read-only · idempotent · open-world

Check the configuration and credentials of a deployed source connector.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
source_id string yes The ID of the deployed source connector to check.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "source_id": {
      "description": "The ID of the deployed source connector to check.",
      "type": "string"
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    }
  },
  "required": [
    "source_id"
  ],
  "type": "object"
}

Show output JSON schema

{
  "description": "Result of a connection check against a deployed Cloud connector.",
  "properties": {
    "connector_id": {
      "type": "string"
    },
    "connector_type": {
      "enum": [
        "source",
        "destination"
      ],
      "type": "string"
    },
    "succeeded": {
      "type": "boolean"
    },
    "message": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "required": [
    "connector_id",
    "connector_type",
    "succeeded",
    "message"
  ],
  "type": "object"
}

create_connection_on_cloud

Hints: open-world

Create a connection between a deployed source and destination on Airbyte Cloud.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
connection_name string yes The name of the connection.
source_id string yes The ID of the deployed source.
destination_id string yes The ID of the deployed destination.
selected_streams string | array<string> yes The selected stream names to sync within the connection. Must be an explicit stream name or list of streams. Cannot be empty or '*'.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.
table_prefix string | null no null Optional table prefix to use when syncing to the destination.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "connection_name": {
      "description": "The name of the connection.",
      "type": "string"
    },
    "source_id": {
      "description": "The ID of the deployed source.",
      "type": "string"
    },
    "destination_id": {
      "description": "The ID of the deployed destination.",
      "type": "string"
    },
    "selected_streams": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "items": {
            "type": "string"
          },
          "type": "array"
        }
      ],
      "description": "The selected stream names to sync within the connection. Must be an explicit stream name or list of streams. Cannot be empty or '*'."
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    },
    "table_prefix": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional table prefix to use when syncing to the destination."
    }
  },
  "required": [
    "connection_name",
    "source_id",
    "destination_id",
    "selected_streams"
  ],
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "type": "string"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

deploy_destination_to_cloud

Hints: open-world

Deploy a destination connector to Airbyte Cloud.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
destination_name string yes The name to use when deploying the destination.
destination_connector_name string yes The name of the destination connector (e.g., 'destination-postgres').
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.
config object | string | null no null The configuration for the destination connector.
config_secret_name string | null no null The name of the secret containing the configuration.
unique boolean no true Whether to require a unique name.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "destination_name": {
      "description": "The name to use when deploying the destination.",
      "type": "string"
    },
    "destination_connector_name": {
      "description": "The name of the destination connector (e.g., 'destination-postgres').",
      "type": "string"
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    },
    "config": {
      "anyOf": [
        {
          "additionalProperties": true,
          "type": "object"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The configuration for the destination connector."
    },
    "config_secret_name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The name of the secret containing the configuration."
    },
    "unique": {
      "default": true,
      "description": "Whether to require a unique name.",
      "type": "boolean"
    }
  },
  "required": [
    "destination_name",
    "destination_connector_name"
  ],
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "type": "string"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

deploy_noop_destination_to_cloud

Hints: open-world

Deploy the No-op destination to Airbyte Cloud for testing purposes.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
name string no "No-op Destination"
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.
unique boolean no true

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "name": {
      "default": "No-op Destination",
      "type": "string"
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    },
    "unique": {
      "default": true,
      "type": "boolean"
    }
  },
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "type": "string"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

deploy_source_to_cloud

Hints: open-world

Deploy a source connector to Airbyte Cloud.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
source_name string yes The name to use when deploying the source.
source_connector_name string yes The name of the source connector (e.g., 'source-faker').
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.
config object | string | null no null The configuration for the source connector.
config_secret_name string | null no null The name of the secret containing the configuration.
unique boolean no true Whether to require a unique name.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "source_name": {
      "description": "The name to use when deploying the source.",
      "type": "string"
    },
    "source_connector_name": {
      "description": "The name of the source connector (e.g., 'source-faker').",
      "type": "string"
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    },
    "config": {
      "anyOf": [
        {
          "additionalProperties": true,
          "type": "object"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The configuration for the source connector."
    },
    "config_secret_name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The name of the secret containing the configuration."
    },
    "unique": {
      "default": true,
      "description": "Whether to require a unique name.",
      "type": "boolean"
    }
  },
  "required": [
    "source_name",
    "source_connector_name"
  ],
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "type": "string"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

describe_cloud_connection

Hints: read-only · idempotent · open-world

Get detailed information about a specific deployed connection.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
connection_id string yes The ID of the connection to describe.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "connection_id": {
      "description": "The ID of the connection to describe.",
      "type": "string"
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    }
  },
  "required": [
    "connection_id"
  ],
  "type": "object"
}

Show output JSON schema

{
  "description": "Detailed information about a deployed connection in Airbyte Cloud.",
  "properties": {
    "connection_id": {
      "type": "string"
    },
    "connection_name": {
      "type": "string"
    },
    "connection_url": {
      "type": "string"
    },
    "source_id": {
      "type": "string"
    },
    "source_name": {
      "type": "string"
    },
    "destination_id": {
      "type": "string"
    },
    "destination_name": {
      "type": "string"
    },
    "selected_streams": {
      "items": {
        "type": "string"
      },
      "type": "array"
    },
    "table_prefix": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "required": [
    "connection_id",
    "connection_name",
    "connection_url",
    "source_id",
    "source_name",
    "destination_id",
    "destination_name",
    "selected_streams",
    "table_prefix"
  ],
  "type": "object"
}

describe_cloud_destination

Hints: read-only · idempotent · open-world

Get detailed information about a specific deployed destination connector.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
destination_id string yes The ID of the destination to describe.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "destination_id": {
      "description": "The ID of the destination to describe.",
      "type": "string"
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    }
  },
  "required": [
    "destination_id"
  ],
  "type": "object"
}

Show output JSON schema

{
  "description": "Detailed information about a deployed destination connector in Airbyte Cloud.",
  "properties": {
    "destination_id": {
      "type": "string"
    },
    "destination_name": {
      "type": "string"
    },
    "destination_url": {
      "type": "string"
    },
    "connector_definition_id": {
      "type": "string"
    }
  },
  "required": [
    "destination_id",
    "destination_name",
    "destination_url",
    "connector_definition_id"
  ],
  "type": "object"
}

describe_cloud_organization

Hints: read-only · idempotent · open-world

Get details about a specific organization including billing status.

Requires either organization_id OR organization_name (exact match) to be provided.
This tool is useful for looking up an organization's ID from its name, or vice versa.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
organization_id string | null no null Organization ID. Required if organization_name is not provided.
organization_name string | null no null Organization name (exact match). Required if organization_id is not provided.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "organization_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Organization ID. Required if organization_name is not provided."
    },
    "organization_name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Organization name (exact match). Required if organization_id is not provided."
    }
  },
  "type": "object"
}

Show output JSON schema

{
  "description": "Information about an organization in Airbyte Cloud.",
  "properties": {
    "id": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "email": {
      "type": "string"
    },
    "payment_status": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "subscription_status": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "is_account_locked": {
      "default": false,
      "type": "boolean"
    }
  },
  "required": [
    "id",
    "name",
    "email"
  ],
  "type": "object"
}

describe_cloud_source

Hints: read-only · idempotent · open-world

Get detailed information about a specific deployed source connector.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
source_id string yes The ID of the source to describe.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "source_id": {
      "description": "The ID of the source to describe.",
      "type": "string"
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    }
  },
  "required": [
    "source_id"
  ],
  "type": "object"
}

Show output JSON schema

{
  "description": "Detailed information about a deployed source connector in Airbyte Cloud.",
  "properties": {
    "source_id": {
      "type": "string"
    },
    "source_name": {
      "type": "string"
    },
    "source_url": {
      "type": "string"
    },
    "connector_definition_id": {
      "type": "string"
    }
  },
  "required": [
    "source_id",
    "source_name",
    "source_url",
    "connector_definition_id"
  ],
  "type": "object"
}

get_cloud_sync_logs

Hints: read-only · idempotent · open-world

Get the logs from a sync job attempt on Airbyte Cloud.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
connection_id string yes The ID of the Airbyte Cloud connection.
job_id integer | null | null no null
attempt_number integer | null | null no null
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.
max_lines integer no 4000 Maximum number of lines to return. Defaults to 4000 if not specified. If '0' is provided, no limit is applied.
from_tail boolean | null no null Pull from the end of the log text if total lines is greater than 'max_lines'. Defaults to True if line_offset is not specified. Cannot combine from_tail=True with line_offset.
line_offset integer | null no null Number of lines to skip from the beginning of the logs. Cannot be combined with from_tail=True.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "connection_id": {
      "description": "The ID of the Airbyte Cloud connection.",
      "type": "string"
    },
    "job_id": {
      "anyOf": [
        {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "description": "Optional job ID. If not provided, the latest job will be used."
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "attempt_number": {
      "anyOf": [
        {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "description": "Optional attempt number. If not provided, the latest attempt will be used."
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    },
    "max_lines": {
      "default": 4000,
      "description": "Maximum number of lines to return. Defaults to 4000 if not specified. If '0' is provided, no limit is applied.",
      "type": "integer"
    },
    "from_tail": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Pull from the end of the log text if total lines is greater than 'max_lines'. Defaults to True if `line_offset` is not specified. Cannot combine `from_tail=True` with `line_offset`."
    },
    "line_offset": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Number of lines to skip from the beginning of the logs. Cannot be combined with `from_tail=True`."
    }
  },
  "required": [
    "connection_id"
  ],
  "type": "object"
}

Show output JSON schema

{
  "description": "Result of reading sync logs with pagination support.",
  "properties": {
    "job_id": {
      "type": "integer"
    },
    "attempt_number": {
      "type": "integer"
    },
    "log_text": {
      "type": "string"
    },
    "log_text_start_line": {
      "type": "integer"
    },
    "log_text_line_count": {
      "type": "integer"
    },
    "total_log_lines_available": {
      "type": "integer"
    }
  },
  "required": [
    "job_id",
    "attempt_number",
    "log_text",
    "log_text_start_line",
    "log_text_line_count",
    "total_log_lines_available"
  ],
  "type": "object"
}

get_cloud_sync_status

Hints: read-only · idempotent · open-world

Get the status of a sync job from the Airbyte Cloud.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
connection_id string yes The ID of the Airbyte Cloud connection.
job_id integer | null no null Optional job ID. If not provided, the latest job will be used.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.
include_attempts boolean no false Whether to include detailed attempts information.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "connection_id": {
      "description": "The ID of the Airbyte Cloud connection.",
      "type": "string"
    },
    "job_id": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional job ID. If not provided, the latest job will be used."
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    },
    "include_attempts": {
      "default": false,
      "description": "Whether to include detailed attempts information.",
      "type": "boolean"
    }
  },
  "required": [
    "connection_id"
  ],
  "type": "object"
}

Show output JSON schema

{
  "additionalProperties": true,
  "type": "object"
}

get_connection_artifact

Hints: read-only · idempotent · open-world

Get a connection artifact (state or catalog) from Airbyte Cloud.

By default, returns artifacts in Airbyte protocol format (snake_case,
suitable for passing to connector CLI flags like `--state` or `--catalog`).

Retrieves the specified artifact for a connection:
- `state`: Returns a list of protocol-format `AirbyteStateMessage` dicts,
  or `{"ERROR": "..."}` if no state is set.
- `catalog`: Returns the protocol-format `ConfiguredAirbyteCatalog` dict,
  or `{"ERROR": "..."}` if not found.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
connection_id string yes The ID of the Airbyte Cloud connection.
artifact_type enum("state", "catalog") yes The type of artifact to retrieve: 'state' or 'catalog'.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "connection_id": {
      "description": "The ID of the Airbyte Cloud connection.",
      "type": "string"
    },
    "artifact_type": {
      "description": "The type of artifact to retrieve: 'state' or 'catalog'.",
      "enum": [
        "state",
        "catalog"
      ],
      "type": "string"
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    }
  },
  "required": [
    "connection_id",
    "artifact_type"
  ],
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "anyOf": [
        {
          "additionalProperties": true,
          "type": "object"
        },
        {
          "items": {
            "additionalProperties": true,
            "type": "object"
          },
          "type": "array"
        }
      ]
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

get_connector_builder_draft_manifest

Hints: read-only · idempotent · open-world

Get the Connector Builder draft manifest for a custom source definition.

Returns the working draft manifest that has been saved in the Connector Builder UI but not yet published. This is useful for inspecting what a user is currently working on before they publish their changes.

If no draft exists, 'has_draft' will be False and 'draft_manifest' will be None. The published manifest is always included for comparison.

Parameters

Name Type Required Default Description
definition_id string yes The ID of the custom source definition to retrieve the draft for.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "definition_id": {
      "description": "The ID of the custom source definition to retrieve the draft for.",
      "type": "string"
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    }
  },
  "required": [
    "definition_id"
  ],
  "type": "object"
}

Show output JSON schema

{
  "additionalProperties": true,
  "type": "object"
}

get_custom_source_definition

Hints: read-only · idempotent · open-world

Get a custom YAML source definition from Airbyte Cloud, including its manifest.

Returns the full definition details including the published manifest YAML content. Optionally includes the Connector Builder draft manifest (unpublished changes) when include_draft=True.

Note: Only YAML (declarative) connectors are currently supported. Docker-based custom sources are not yet available.

Parameters

Name Type Required Default Description
definition_id string yes The ID of the custom source definition to retrieve.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.
include_draft boolean no false Whether to include the Connector Builder draft manifest in the response. If True and a draft exists, the response will include 'has_draft' and 'draft_manifest' fields. Defaults to False.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "definition_id": {
      "description": "The ID of the custom source definition to retrieve.",
      "type": "string"
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    },
    "include_draft": {
      "default": false,
      "description": "Whether to include the Connector Builder draft manifest in the response. If True and a draft exists, the response will include 'has_draft' and 'draft_manifest' fields. Defaults to False.",
      "type": "boolean"
    }
  },
  "required": [
    "definition_id"
  ],
  "type": "object"
}

Show output JSON schema

{
  "additionalProperties": true,
  "type": "object"
}

list_cloud_organizations

Hints: read-only · idempotent · open-world

List organizations visible to the authenticated Airbyte Cloud credentials.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

_No parameters._

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {},
  "type": "object"
}

Show output JSON schema

{
  "description": "Result of discovering organizations in Airbyte Cloud.",
  "properties": {
    "organizations": {
      "items": {
        "description": "Information about an organization in Airbyte Cloud.",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "payment_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "subscription_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "is_account_locked": {
            "default": false,
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "name",
          "email"
        ],
        "type": "object"
      },
      "type": "array"
    },
    "message": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    }
  },
  "required": [
    "organizations"
  ],
  "type": "object"
}

list_cloud_sync_jobs

Hints: read-only · idempotent · open-world

List sync jobs for a connection with limit support.

This tool allows you to retrieve a list of sync jobs for a connection,
with control over ordering and result limit. By default, jobs are returned
newest-first (`from_tail=True`).

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
connection_id string yes The ID of the Airbyte Cloud connection.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.
max_jobs integer no 20 Maximum number of jobs to return. Defaults to 20 if not specified. Maximum allowed value is 500.
from_tail boolean | null no null When True, jobs are ordered newest-first (createdAt DESC). When False, jobs are ordered oldest-first (createdAt ASC). Defaults to True.
job_type enum("sync", "reset", "refresh", "clear") | null no null Filter by job type. Options: 'sync', 'reset', 'refresh', 'clear'. If not specified, defaults to sync and reset jobs only (API default). Use 'refresh' to find refresh jobs or 'clear' to find clear jobs.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "connection_id": {
      "description": "The ID of the Airbyte Cloud connection.",
      "type": "string"
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    },
    "max_jobs": {
      "default": 20,
      "description": "Maximum number of jobs to return. Defaults to 20 if not specified. Maximum allowed value is 500.",
      "type": "integer"
    },
    "from_tail": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "When True, jobs are ordered newest-first (createdAt DESC). When False, jobs are ordered oldest-first (createdAt ASC). Defaults to True."
    },
    "job_type": {
      "anyOf": [
        {
          "description": "Job type values for Airbyte Cloud jobs.",
          "enum": [
            "sync",
            "reset",
            "refresh",
            "clear"
          ],
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Filter by job type. Options: 'sync', 'reset', 'refresh', 'clear'. If not specified, defaults to sync and reset jobs only (API default). Use 'refresh' to find refresh jobs or 'clear' to find clear jobs."
    }
  },
  "required": [
    "connection_id"
  ],
  "type": "object"
}

Show output JSON schema

{
  "description": "Result of listing sync jobs with limit support.",
  "properties": {
    "jobs": {
      "items": {
        "description": "Information about a sync job.",
        "properties": {
          "job_id": {
            "type": "integer"
          },
          "status": {
            "type": "string"
          },
          "bytes_synced": {
            "type": "integer"
          },
          "records_synced": {
            "type": "integer"
          },
          "start_time": {
            "type": "string"
          },
          "job_url": {
            "type": "string"
          }
        },
        "required": [
          "job_id",
          "status",
          "bytes_synced",
          "records_synced",
          "start_time",
          "job_url"
        ],
        "type": "object"
      },
      "type": "array"
    },
    "jobs_count": {
      "type": "integer"
    },
    "from_tail": {
      "type": "boolean"
    }
  },
  "required": [
    "jobs",
    "jobs_count",
    "from_tail"
  ],
  "type": "object"
}

list_cloud_workspaces

Hints: read-only · idempotent · open-world

List all workspaces visible to the authenticated credentials.

When an organization ID or exact organization name is provided, the Config API
lists workspaces in that organization. When neither is provided and the client
has no default organization, the public API lists workspaces across organizations
visible to the current credentials. Otherwise, results are scoped to the client's
default organization.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
organization_id string | null no null Optional organization ID to list workspaces within.
organization_name string | null no null Optional organization name (exact match) to list workspaces within.
name_contains string | null no null Optional substring to filter workspaces by name (server-side filtering)
limit integer | null no null Optional maximum number of items to return (default: no limit)

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "organization_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional organization ID to list workspaces within."
    },
    "organization_name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional organization name (exact match) to list workspaces within."
    },
    "name_contains": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional substring to filter workspaces by name (server-side filtering)"
    },
    "limit": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional maximum number of items to return (default: no limit)"
    }
  },
  "type": "object"
}

Show output JSON schema

{
  "description": "Result of discovering workspaces in Airbyte Cloud.",
  "properties": {
    "workspaces": {
      "items": {
        "description": "Information about a workspace in Airbyte Cloud.",
        "properties": {
          "workspace_id": {
            "type": "string"
          },
          "workspace_name": {
            "type": "string"
          },
          "workspace_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "organization_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "organization_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "payment_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "subscription_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "is_account_locked": {
            "default": false,
            "type": "boolean"
          }
        },
        "required": [
          "workspace_id",
          "workspace_name",
          "organization_id"
        ],
        "type": "object"
      },
      "type": "array"
    },
    "message": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null
    }
  },
  "required": [
    "workspaces"
  ],
  "type": "object"
}

list_custom_source_definitions

Hints: read-only · idempotent · open-world

List custom YAML source definitions in the Airbyte Cloud workspace.

Note: Only YAML (declarative) connectors are currently supported. Docker-based custom sources are not yet available.

Parameters

Name Type Required Default Description
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    }
  },
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "items": {
        "additionalProperties": true,
        "type": "object"
      },
      "type": "array"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

list_deployed_cloud_connections

Hints: read-only · idempotent · open-world

List all deployed connections in the Airbyte Cloud workspace.

When with_connection_status is True, each connection result will include
information about the most recent sync job status, skipping over any
currently in-progress syncs to find the last completed job.

When failing_connections_only is True, only connections where the most
recent completed sync job failed or was cancelled will be returned.
This implicitly enables with_connection_status.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.
name_contains string | null no null Optional case-insensitive substring to filter connections by name
limit integer | null no null Optional maximum number of items to return (default: no limit)
with_connection_status boolean | null no false If True, include status info for each connection's most recent sync job
failing_connections_only boolean | null no false If True, only return connections with failed/cancelled last sync

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    },
    "name_contains": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional case-insensitive substring to filter connections by name"
    },
    "limit": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional maximum number of items to return (default: no limit)"
    },
    "with_connection_status": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        }
      ],
      "default": false,
      "description": "If True, include status info for each connection's most recent sync job"
    },
    "failing_connections_only": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        }
      ],
      "default": false,
      "description": "If True, only return connections with failed/cancelled last sync"
    }
  },
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "items": {
        "description": "Information about a deployed connection in Airbyte Cloud.",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "source_id": {
            "type": "string"
          },
          "destination_id": {
            "type": "string"
          },
          "last_job_status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "last_job_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "last_job_time": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "currently_running_job_id": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "currently_running_job_start_time": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          }
        },
        "required": [
          "id",
          "name",
          "url",
          "source_id",
          "destination_id"
        ],
        "type": "object"
      },
      "type": "array"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

list_deployed_cloud_destination_connectors

Hints: read-only · idempotent · open-world

List all deployed destination connectors in the Airbyte Cloud workspace.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.
name_contains string | null no null Optional case-insensitive substring to filter destinations by name
limit integer | null no null Optional maximum number of items to return (default: no limit)

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    },
    "name_contains": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional case-insensitive substring to filter destinations by name"
    },
    "limit": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional maximum number of items to return (default: no limit)"
    }
  },
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "items": {
        "description": "Information about a deployed destination connector in Airbyte Cloud.",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "url"
        ],
        "type": "object"
      },
      "type": "array"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

list_deployed_cloud_source_connectors

Hints: read-only · idempotent · open-world

List all deployed source connectors in the Airbyte Cloud workspace.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.
name_contains string | null no null Optional case-insensitive substring to filter sources by name
limit integer | null no null Optional maximum number of items to return (default: no limit)

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    },
    "name_contains": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional case-insensitive substring to filter sources by name"
    },
    "limit": {
      "anyOf": [
        {
          "type": "integer"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional maximum number of items to return (default: no limit)"
    }
  },
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "items": {
        "description": "Information about a deployed source connector in Airbyte Cloud.",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "url"
        ],
        "type": "object"
      },
      "type": "array"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

permanently_delete_cloud_connection

Hints: destructive · open-world

Permanently delete a connection from Airbyte Cloud.

IMPORTANT: This operation requires the connection name to contain "delete-me" or "deleteme"
(case insensitive).

If the connection does not meet this requirement, the deletion will be rejected with a
helpful error message. Instruct the user to rename the connection appropriately to authorize
the deletion.

The provided name must match the actual name of the connection for the operation to proceed.
This is a safety measure to ensure you are deleting the correct resource.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
connection_id string yes The ID of the connection to delete.
name string yes The expected name of the connection (for verification).
cascade_delete_source boolean no false Whether to also delete the source connector associated with this connection.
cascade_delete_destination boolean no false Whether to also delete the destination connector associated with this connection.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "connection_id": {
      "description": "The ID of the connection to delete.",
      "type": "string"
    },
    "name": {
      "description": "The expected name of the connection (for verification).",
      "type": "string"
    },
    "cascade_delete_source": {
      "default": false,
      "description": "Whether to also delete the source connector associated with this connection.",
      "type": "boolean"
    },
    "cascade_delete_destination": {
      "default": false,
      "description": "Whether to also delete the destination connector associated with this connection.",
      "type": "boolean"
    }
  },
  "required": [
    "connection_id",
    "name"
  ],
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "type": "string"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

permanently_delete_cloud_destination

Hints: destructive · open-world

Permanently delete a deployed destination connector from Airbyte Cloud.

IMPORTANT: This operation requires the destination name to contain "delete-me" or "deleteme"
(case insensitive).

If the destination does not meet this requirement, the deletion will be rejected with a
helpful error message. Instruct the user to rename the destination appropriately to authorize
the deletion.

The provided name must match the actual name of the destination for the operation to proceed.
This is a safety measure to ensure you are deleting the correct resource.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
destination_id string yes The ID of the deployed destination to delete.
name string yes The expected name of the destination (for verification).

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "destination_id": {
      "description": "The ID of the deployed destination to delete.",
      "type": "string"
    },
    "name": {
      "description": "The expected name of the destination (for verification).",
      "type": "string"
    }
  },
  "required": [
    "destination_id",
    "name"
  ],
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "type": "string"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

permanently_delete_cloud_source

Hints: destructive · open-world

Permanently delete a deployed source connector from Airbyte Cloud.

IMPORTANT: This operation requires the source name to contain "delete-me" or "deleteme"
(case insensitive).

If the source does not meet this requirement, the deletion will be rejected with a
helpful error message. Instruct the user to rename the source appropriately to authorize
the deletion.

The provided name must match the actual name of the source for the operation to proceed.
This is a safety measure to ensure you are deleting the correct resource.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
source_id string yes The ID of the deployed source to delete.
name string yes The expected name of the source (for verification).

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "source_id": {
      "description": "The ID of the deployed source to delete.",
      "type": "string"
    },
    "name": {
      "description": "The expected name of the source (for verification).",
      "type": "string"
    }
  },
  "required": [
    "source_id",
    "name"
  ],
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "type": "string"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

permanently_delete_custom_source_definition

Hints: destructive · open-world

Permanently delete a custom YAML source definition from Airbyte Cloud.

IMPORTANT: This operation requires the connector name to contain "delete-me" or "deleteme" (case insensitive).

If the connector does not meet this requirement, the deletion will be rejected with a helpful error message. Instruct the user to rename the connector appropriately to authorize the deletion.

The provided name must match the actual name of the definition for the operation to proceed. This is a safety measure to ensure you are deleting the correct resource.

Note: Only YAML (declarative) connectors are currently supported. Docker-based custom sources are not yet available.

Parameters

Name Type Required Default Description
definition_id string yes The ID of the custom source definition to delete.
name string yes The expected name of the custom source definition (for verification).
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "definition_id": {
      "description": "The ID of the custom source definition to delete.",
      "type": "string"
    },
    "name": {
      "description": "The expected name of the custom source definition (for verification).",
      "type": "string"
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    }
  },
  "required": [
    "definition_id",
    "name"
  ],
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "type": "string"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

publish_custom_source_definition

Hints: open-world

Publish a custom YAML source connector definition to Airbyte Cloud.

Note: Only YAML (declarative) connectors are currently supported.
Docker-based custom sources are not yet available.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
name string yes The name for the custom connector definition.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.
manifest_yaml string | string | null | null no null
unique boolean no true Whether to require a unique name.
pre_validate boolean no true Whether to validate the manifest client-side before publishing.
testing_values object | string | null no null Optional testing configuration values for the Builder UI. Can be provided as a JSON object or JSON string. Supports inline secret refs via 'secret_reference::ENV_VAR_NAME' syntax. If provided, these values replace any existing testing values for the connector builder project, allowing immediate test read operations.
testing_values_secret_name string | null no null Optional name of a secret containing testing configuration values in JSON or YAML format. The secret will be resolved by the MCP server and merged into testing_values, with secret values taking precedence. This lets the agent reference secrets without sending raw values as tool arguments.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "name": {
      "description": "The name for the custom connector definition.",
      "type": "string"
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    },
    "manifest_yaml": {
      "anyOf": [
        {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "format": "path",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The Low-code CDK manifest as a YAML string or file path. Required for YAML connectors."
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "unique": {
      "default": true,
      "description": "Whether to require a unique name.",
      "type": "boolean"
    },
    "pre_validate": {
      "default": true,
      "description": "Whether to validate the manifest client-side before publishing.",
      "type": "boolean"
    },
    "testing_values": {
      "anyOf": [
        {
          "additionalProperties": true,
          "type": "object"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional testing configuration values for the Builder UI. Can be provided as a JSON object or JSON string. Supports inline secret refs via 'secret_reference::ENV_VAR_NAME' syntax. If provided, these values replace any existing testing values for the connector builder project, allowing immediate test read operations."
    },
    "testing_values_secret_name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional name of a secret containing testing configuration values in JSON or YAML format. The secret will be resolved by the MCP server and merged into testing_values, with secret values taking precedence. This lets the agent reference secrets without sending raw values as tool arguments."
    }
  },
  "required": [
    "name"
  ],
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "type": "string"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

rename_cloud_connection

Hints: open-world

Rename a connection on Airbyte Cloud.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
connection_id string yes The ID of the connection to rename.
name string yes New name for the connection.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "connection_id": {
      "description": "The ID of the connection to rename.",
      "type": "string"
    },
    "name": {
      "description": "New name for the connection.",
      "type": "string"
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    }
  },
  "required": [
    "connection_id",
    "name"
  ],
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "type": "string"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

rename_cloud_destination

Hints: open-world

Rename a deployed destination connector on Airbyte Cloud.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
destination_id string yes The ID of the deployed destination to rename.
name string yes New name for the destination.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "destination_id": {
      "description": "The ID of the deployed destination to rename.",
      "type": "string"
    },
    "name": {
      "description": "New name for the destination.",
      "type": "string"
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    }
  },
  "required": [
    "destination_id",
    "name"
  ],
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "type": "string"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

rename_cloud_source

Hints: open-world

Rename a deployed source connector on Airbyte Cloud.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
source_id string yes The ID of the deployed source to rename.
name string yes New name for the source.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "source_id": {
      "description": "The ID of the deployed source to rename.",
      "type": "string"
    },
    "name": {
      "description": "New name for the source.",
      "type": "string"
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    }
  },
  "required": [
    "source_id",
    "name"
  ],
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "type": "string"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

run_cloud_sync

Hints: open-world

Run a sync job on Airbyte Cloud.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
connection_id string yes The ID of the Airbyte Cloud connection.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.
wait boolean no false Whether to wait for the sync to complete. Since a sync can take between several minutes and several hours, this option is not recommended for most scenarios.
wait_timeout integer no 300 Maximum time to wait for sync completion (seconds).

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "connection_id": {
      "description": "The ID of the Airbyte Cloud connection.",
      "type": "string"
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    },
    "wait": {
      "default": false,
      "description": "Whether to wait for the sync to complete. Since a sync can take between several minutes and several hours, this option is not recommended for most scenarios.",
      "type": "boolean"
    },
    "wait_timeout": {
      "default": 300,
      "description": "Maximum time to wait for sync completion (seconds).",
      "type": "integer"
    }
  },
  "required": [
    "connection_id"
  ],
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "type": "string"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

set_cloud_connection_selected_streams

Hints: destructive · open-world

Set the selected streams for a connection on Airbyte Cloud.

This is a destructive operation that can break existing connections if the
stream selection is changed incorrectly. Use with caution.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
connection_id string yes The ID of the connection to update.
stream_names string | array<string> yes The selected stream names to sync within the connection. Must be an explicit stream name or list of streams.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "connection_id": {
      "description": "The ID of the connection to update.",
      "type": "string"
    },
    "stream_names": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "items": {
            "type": "string"
          },
          "type": "array"
        }
      ],
      "description": "The selected stream names to sync within the connection. Must be an explicit stream name or list of streams."
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    }
  },
  "required": [
    "connection_id",
    "stream_names"
  ],
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "type": "string"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

set_cloud_connection_table_prefix

Hints: destructive · open-world

Set the table prefix for a connection on Airbyte Cloud.

This is a destructive operation that can break downstream dependencies if the
table prefix is changed incorrectly. Use with caution.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
connection_id string yes The ID of the connection to update.
prefix string yes New table prefix to use when syncing to the destination.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "connection_id": {
      "description": "The ID of the connection to update.",
      "type": "string"
    },
    "prefix": {
      "description": "New table prefix to use when syncing to the destination.",
      "type": "string"
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    }
  },
  "required": [
    "connection_id",
    "prefix"
  ],
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "type": "string"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

update_cloud_connection

Hints: destructive · open-world

Update a connection's settings on Airbyte Cloud.

This tool allows updating multiple connection settings in a single call:
- Enable or disable the connection
- Set a cron schedule for automatic syncs
- Switch to manual scheduling (no automatic syncs)

At least one setting must be provided. The 'cron_expression' and 'manual_schedule'
parameters are mutually exclusive.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
connection_id string yes The ID of the connection to update.
enabled boolean | null no null Set the connection's enabled status. True enables the connection (status='active'), False disables it (status='inactive'). Leave unset to keep the current status.
cron_expression string | null no null A cron expression defining when syncs should run. Examples: '0 0 * * *' (daily at midnight UTC), '0 */6 * * *' (every 6 hours), '0 0 * * 0' (weekly on Sunday at midnight UTC). Leave unset to keep the current schedule. Cannot be used together with 'manual_schedule'.
manual_schedule boolean | null no null Set to True to disable automatic syncs (manual scheduling only). Syncs will only run when manually triggered. Cannot be used together with 'cron_expression'.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "connection_id": {
      "description": "The ID of the connection to update.",
      "type": "string"
    },
    "enabled": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Set the connection's enabled status. True enables the connection (status='active'), False disables it (status='inactive'). Leave unset to keep the current status."
    },
    "cron_expression": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "A cron expression defining when syncs should run. Examples: '0 0 * * *' (daily at midnight UTC), '0 */6 * * *' (every 6 hours), '0 0 * * 0' (weekly on Sunday at midnight UTC). Leave unset to keep the current schedule. Cannot be used together with 'manual_schedule'."
    },
    "manual_schedule": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Set to True to disable automatic syncs (manual scheduling only). Syncs will only run when manually triggered. Cannot be used together with 'cron_expression'."
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    }
  },
  "required": [
    "connection_id"
  ],
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "type": "string"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

update_cloud_destination_config

Hints: destructive · open-world

Update a deployed destination connector's configuration on Airbyte Cloud.

This is a destructive operation that can break existing connections if the
configuration is changed incorrectly. Use with caution.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
destination_id string yes The ID of the deployed destination to update.
config object | string yes New configuration for the destination connector.
config_secret_name string | null no null The name of the secret containing the configuration.
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "destination_id": {
      "description": "The ID of the deployed destination to update.",
      "type": "string"
    },
    "config": {
      "anyOf": [
        {
          "additionalProperties": true,
          "type": "object"
        },
        {
          "type": "string"
        }
      ],
      "description": "New configuration for the destination connector."
    },
    "config_secret_name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The name of the secret containing the configuration."
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    }
  },
  "required": [
    "destination_id",
    "config"
  ],
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "type": "string"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

update_cloud_source_config

Hints: destructive · open-world

Update a deployed source connector's configuration on Airbyte Cloud.

This is a destructive operation that can break existing connections if the
configuration is changed incorrectly. Use with caution.

When connecting to a hosted MCP server, provide a bearer token via the Authorization header, or client credentials via the transport Client-Id and Client-Secret headers. To discover available organizations and workspaces, call list_cloud_organizations and list_cloud_workspaces before asking the user for an ID. For local or stdio connections, set the AIRBYTE_CLOUD_BEARER_TOKEN environment variable, or both AIRBYTE_CLOUD_CLIENT_ID and AIRBYTE_CLOUD_CLIENT_SECRET. If discovery returns multiple candidates, ask the user to choose one; do not select automatically.

Parameters

Name Type Required Default Description
source_id string yes The ID of the deployed source to update.
config object | string yes New configuration for the source connector.
config_secret_name string | null | null no null
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "source_id": {
      "description": "The ID of the deployed source to update.",
      "type": "string"
    },
    "config": {
      "anyOf": [
        {
          "additionalProperties": true,
          "type": "object"
        },
        {
          "type": "string"
        }
      ],
      "description": "New configuration for the source connector."
    },
    "config_secret_name": {
      "anyOf": [
        {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The name of the secret containing the configuration."
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    }
  },
  "required": [
    "source_id",
    "config"
  ],
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "type": "string"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

update_custom_source_definition

Hints: destructive · open-world

Update a custom YAML source definition in Airbyte Cloud.

Updates the manifest and/or testing values for an existing custom source definition. At least one of manifest_yaml, testing_values, or testing_values_secret_name must be provided.

Parameters

Name Type Required Default Description
definition_id string yes The ID of the definition to update.
manifest_yaml string | string | null | null no null
workspace_id string | null no null Workspace ID. Hosted MCP connections pass it via the X-Airbyte-Workspace-Id header; local or stdio connections use the AIRBYTE_CLOUD_WORKSPACE_ID environment variable.
pre_validate boolean no true Whether to validate the manifest client-side before updating.
testing_values object | string | null no null Optional testing configuration values for the Builder UI. Can be provided as a JSON object or JSON string. Supports inline secret refs via 'secret_reference::ENV_VAR_NAME' syntax. If provided, these values replace any existing testing values for the connector builder project. The entire testing values object is overwritten, so pass the full set of values you want to persist.
testing_values_secret_name string | null no null Optional name of a secret containing testing configuration values in JSON or YAML format. The secret will be resolved by the MCP server and merged into testing_values, with secret values taking precedence. This lets the agent reference secrets without sending raw values as tool arguments.

Show input JSON schema

{
  "additionalProperties": false,
  "properties": {
    "definition_id": {
      "description": "The ID of the definition to update.",
      "type": "string"
    },
    "manifest_yaml": {
      "anyOf": [
        {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "format": "path",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "New manifest as YAML string or file path. Optional; omit to update only testing values."
        },
        {
          "type": "null"
        }
      ],
      "default": null
    },
    "workspace_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Workspace ID. Hosted MCP connections pass it via the `X-Airbyte-Workspace-Id` header; local or stdio connections use the `AIRBYTE_CLOUD_WORKSPACE_ID` environment variable."
    },
    "pre_validate": {
      "default": true,
      "description": "Whether to validate the manifest client-side before updating.",
      "type": "boolean"
    },
    "testing_values": {
      "anyOf": [
        {
          "additionalProperties": true,
          "type": "object"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional testing configuration values for the Builder UI. Can be provided as a JSON object or JSON string. Supports inline secret refs via 'secret_reference::ENV_VAR_NAME' syntax. If provided, these values replace any existing testing values for the connector builder project. The entire testing values object is overwritten, so pass the full set of values you want to persist."
    },
    "testing_values_secret_name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Optional name of a secret containing testing configuration values in JSON or YAML format. The secret will be resolved by the MCP server and merged into testing_values, with secret values taking precedence. This lets the agent reference secrets without sending raw values as tool arguments."
    }
  },
  "required": [
    "definition_id"
  ],
  "type": "object"
}

Show output JSON schema

{
  "properties": {
    "result": {
      "type": "string"
    }
  },
  "required": [
    "result"
  ],
  "type": "object",
  "x-fastmcp-wrap-result": true
}

   1# Copyright (c) 2024 Airbyte, Inc., all rights reserved.
   2"""Airbyte Cloud MCP operations.
   3
   4.. include:: ../../docs/mcp-generated/cloud.md
   5"""
   6
   7# No public Python API — MCP primitives are registered via decorators and
   8# documented via the generated Markdown include above. Setting `__all__` to an
   9# empty list tells pdoc (and other doc tools) not to surface the individual
  10# tool / helper definitions as a redundant "API Documentation" list.
  11__all__: list[str] = []
  12
  13from collections.abc import Callable
  14from http import HTTPStatus
  15from pathlib import Path
  16from typing import Annotated, Any, Literal, TypeVar, cast
  17
  18from fastmcp import Context, FastMCP
  19from fastmcp_extensions import get_mcp_config, mcp_tool, register_mcp_tools
  20from pydantic import BaseModel, Field
  21
  22from airbyte import cloud, get_destination, get_source
  23from airbyte._util import api_util
  24from airbyte.cloud.client import CloudClient
  25from airbyte.cloud.connectors import CheckResult, CustomCloudSourceDefinition
  26from airbyte.cloud.constants import FAILED_STATUSES
  27from airbyte.cloud.models import JobTypeEnum
  28from airbyte.cloud.workspaces import CloudWorkspace
  29from airbyte.constants import (
  30    CLOUD_BEARER_TOKEN_ENV_VAR,
  31    CLOUD_CLIENT_ID_ENV_VAR,
  32    CLOUD_CLIENT_SECRET_ENV_VAR,
  33    CLOUD_WORKSPACE_ID_ENV_VAR,
  34    MCP_BEARER_TOKEN_HEADER,
  35    MCP_CONFIG_API_URL,
  36    MCP_CONFIG_BEARER_TOKEN,
  37    MCP_CONFIG_CLIENT_ID,
  38    MCP_CONFIG_CLIENT_SECRET,
  39    MCP_CONFIG_CONFIG_API_URL,
  40    MCP_CONFIG_WORKSPACE_ID,
  41    MCP_WORKSPACE_ID_HEADER,
  42)
  43from airbyte.destinations.util import get_noop_destination
  44from airbyte.exceptions import (
  45    AirbyteError,
  46    AirbyteMissingResourceError,
  47    AirbyteMissingWorkspaceContextError,
  48    PyAirbyteInputError,
  49)
  50from airbyte.mcp._arg_resolvers import resolve_connector_config, resolve_list_of_strings
  51from airbyte.mcp._tool_utils import (
  52    AIRBYTE_CLOUD_WORKSPACE_ID_IS_SET,
  53    check_guid_created_in_session,
  54    register_guid_created_in_session,
  55)
  56
  57
  58CLOUD_AUTH_TIP_TEXT = (
  59    f"When connecting to a hosted MCP server, provide a bearer token via the "
  60    f"`{MCP_BEARER_TOKEN_HEADER}` header, or client credentials via the transport "
  61    f"`Client-Id` and `Client-Secret` headers. To discover available organizations "
  62    f"and workspaces, call `list_cloud_organizations` and `list_cloud_workspaces` "
  63    f"before asking the user for an ID. For local or "
  64    f"stdio connections, set the `{CLOUD_BEARER_TOKEN_ENV_VAR}` environment "
  65    f"variable, or both `{CLOUD_CLIENT_ID_ENV_VAR}` and "
  66    f"`{CLOUD_CLIENT_SECRET_ENV_VAR}`. If discovery returns multiple candidates, "
  67    f"ask the user to choose one; do not select automatically."
  68)
  69WORKSPACE_ID_TIP_TEXT = (
  70    f"Workspace ID. Hosted MCP connections pass it via the "
  71    f"`{MCP_WORKSPACE_ID_HEADER}` header; local or stdio connections use the "
  72    f"`{CLOUD_WORKSPACE_ID_ENV_VAR}` environment variable."
  73)
  74CONNECTOR_CHECK_FAILURE_FALLBACK = "Connector check failed without a failure message."
  75
  76_DiscoveryResult = TypeVar("_DiscoveryResult")
  77
  78
  79def _handle_discovery_permission_error(
  80    error: AirbyteError,
  81    *,
  82    make_result: Callable[[str], _DiscoveryResult],
  83) -> _DiscoveryResult:
  84    """Return a graceful result for discovery permission errors."""
  85    status_code = (error.context or {}).get("status_code")
  86    if status_code not in {HTTPStatus.UNAUTHORIZED, HTTPStatus.FORBIDDEN}:
  87        raise error
  88    return make_result(
  89        "Organization or workspace discovery is unavailable because these credentials "
  90        "do not have the required permission or access. Provide an organization or "
  91        "workspace ID, or use credentials with the needed access."
  92    )
  93
  94
  95def _get_connector_check_message(check_result: CheckResult) -> str | None:
  96    """Return the check failure message, if applicable."""
  97    if check_result.success:
  98        return None
  99    return (
 100        check_result.error_message
 101        or check_result.internal_error
 102        or CONNECTOR_CHECK_FAILURE_FALLBACK
 103    )
 104
 105
 106class CloudSourceResult(BaseModel):
 107    """Information about a deployed source connector in Airbyte Cloud."""
 108
 109    id: str
 110    """The source ID."""
 111    name: str
 112    """Display name of the source."""
 113    url: str
 114    """Web URL for managing this source in Airbyte Cloud."""
 115
 116
 117class CloudDestinationResult(BaseModel):
 118    """Information about a deployed destination connector in Airbyte Cloud."""
 119
 120    id: str
 121    """The destination ID."""
 122    name: str
 123    """Display name of the destination."""
 124    url: str
 125    """Web URL for managing this destination in Airbyte Cloud."""
 126
 127
 128class CloudConnectionResult(BaseModel):
 129    """Information about a deployed connection in Airbyte Cloud."""
 130
 131    id: str
 132    """The connection ID."""
 133    name: str
 134    """Display name of the connection."""
 135    url: str
 136    """Web URL for managing this connection in Airbyte Cloud."""
 137    source_id: str
 138    """ID of the source used by this connection."""
 139    destination_id: str
 140    """ID of the destination used by this connection."""
 141    last_job_status: str | None = None
 142    """Status of the most recent completed sync job (e.g., 'succeeded', 'failed', 'cancelled').
 143    Only populated when with_connection_status=True."""
 144    last_job_id: int | None = None
 145    """Job ID of the most recent completed sync. Only populated when with_connection_status=True."""
 146    last_job_time: str | None = None
 147    """ISO 8601 timestamp of the most recent completed sync.
 148    Only populated when with_connection_status=True."""
 149    currently_running_job_id: int | None = None
 150    """Job ID of a currently running sync, if any.
 151    Only populated when with_connection_status=True."""
 152    currently_running_job_start_time: str | None = None
 153    """ISO 8601 timestamp of when the currently running sync started.
 154    Only populated when with_connection_status=True."""
 155
 156
 157class CloudSourceDetails(BaseModel):
 158    """Detailed information about a deployed source connector in Airbyte Cloud."""
 159
 160    source_id: str
 161    """The source ID."""
 162    source_name: str
 163    """Display name of the source."""
 164    source_url: str
 165    """Web URL for managing this source in Airbyte Cloud."""
 166    connector_definition_id: str
 167    """The connector definition ID (e.g., the ID for 'source-postgres')."""
 168
 169
 170class CloudDestinationDetails(BaseModel):
 171    """Detailed information about a deployed destination connector in Airbyte Cloud."""
 172
 173    destination_id: str
 174    """The destination ID."""
 175    destination_name: str
 176    """Display name of the destination."""
 177    destination_url: str
 178    """Web URL for managing this destination in Airbyte Cloud."""
 179    connector_definition_id: str
 180    """The connector definition ID (e.g., the ID for 'destination-snowflake')."""
 181
 182
 183class CloudConnectionDetails(BaseModel):
 184    """Detailed information about a deployed connection in Airbyte Cloud."""
 185
 186    connection_id: str
 187    """The connection ID."""
 188    connection_name: str
 189    """Display name of the connection."""
 190    connection_url: str
 191    """Web URL for managing this connection in Airbyte Cloud."""
 192    source_id: str
 193    """ID of the source used by this connection."""
 194    source_name: str
 195    """Display name of the source."""
 196    destination_id: str
 197    """ID of the destination used by this connection."""
 198    destination_name: str
 199    """Display name of the destination."""
 200    selected_streams: list[str]
 201    """List of stream names selected for syncing."""
 202    table_prefix: str | None
 203    """Table prefix applied when syncing to the destination."""
 204
 205
 206class CloudOrganizationResult(BaseModel):
 207    """Information about an organization in Airbyte Cloud."""
 208
 209    id: str
 210    """The organization ID."""
 211    name: str
 212    """Display name of the organization."""
 213    email: str
 214    """Email associated with the organization."""
 215    payment_status: str | None = None
 216    """Payment status of the organization (e.g., 'okay', 'grace_period', 'disabled', 'locked').
 217    When 'disabled', syncs are blocked due to unpaid invoices."""
 218    subscription_status: str | None = None
 219    """Subscription status of the organization (e.g., 'pre_subscription', 'subscribed',
 220    'unsubscribed')."""
 221    is_account_locked: bool = False
 222    """Whether the account is locked due to billing issues.
 223    True if payment_status is 'disabled'/'locked' or subscription_status is 'unsubscribed'.
 224    Defaults to False unless we have affirmative evidence of a locked state."""
 225
 226
 227class CloudOrganizationListResult(BaseModel):
 228    """Result of discovering organizations in Airbyte Cloud."""
 229
 230    organizations: list[CloudOrganizationResult]
 231    """Organizations visible to the authenticated credentials."""
 232
 233    message: str | None = None
 234    """Additional guidance when discovery returns no results or is unavailable."""
 235
 236
 237class CloudWorkspaceResult(BaseModel):
 238    """Information about a workspace in Airbyte Cloud."""
 239
 240    workspace_id: str
 241    """The workspace ID."""
 242    workspace_name: str
 243    """Display name of the workspace."""
 244    workspace_url: str | None = None
 245    """URL to access the workspace in Airbyte Cloud."""
 246    organization_id: str | None
 247    """ID of the organization, if known and available."""
 248    organization_name: str | None = None
 249    """Name of the organization (requires ORGANIZATION_READER permission)."""
 250    payment_status: str | None = None
 251    """Payment status of the organization (e.g., 'okay', 'grace_period', 'disabled', 'locked').
 252    When 'disabled', syncs are blocked due to unpaid invoices.
 253    Requires ORGANIZATION_READER permission."""
 254    subscription_status: str | None = None
 255    """Subscription status of the organization (e.g., 'pre_subscription', 'subscribed',
 256    'unsubscribed'). Requires ORGANIZATION_READER permission."""
 257    is_account_locked: bool = False
 258    """Whether the account is locked due to billing issues.
 259    True if payment_status is 'disabled'/'locked' or subscription_status is 'unsubscribed'.
 260    Defaults to False unless we have affirmative evidence of a locked state.
 261    Requires ORGANIZATION_READER permission."""
 262
 263
 264class CloudWorkspaceListResult(BaseModel):
 265    """Result of discovering workspaces in Airbyte Cloud."""
 266
 267    workspaces: list[CloudWorkspaceResult]
 268    """Workspaces visible to the authenticated credentials."""
 269
 270    message: str | None = None
 271    """Additional guidance when discovery returns no results."""
 272
 273
 274class LogReadResult(BaseModel):
 275    """Result of reading sync logs with pagination support."""
 276
 277    job_id: int
 278    """The job ID the logs belong to."""
 279    attempt_number: int
 280    """The attempt number the logs belong to."""
 281    log_text: str
 282    """The string containing the log text we are returning."""
 283    log_text_start_line: int
 284    """1-based line index of the first line returned."""
 285    log_text_line_count: int
 286    """Count of lines we are returning."""
 287    total_log_lines_available: int
 288    """Total number of log lines available, shows if any lines were missed due to the limit."""
 289
 290
 291class SyncJobResult(BaseModel):
 292    """Information about a sync job."""
 293
 294    job_id: int
 295    """The job ID."""
 296    status: str
 297    """The job status (e.g., 'succeeded', 'failed', 'running', 'pending')."""
 298    bytes_synced: int
 299    """Number of bytes synced in this job."""
 300    records_synced: int
 301    """Number of records synced in this job."""
 302    start_time: str
 303    """ISO 8601 timestamp of when the job started."""
 304    job_url: str
 305    """URL to view the job in Airbyte Cloud."""
 306
 307
 308class ConnectorCheckResult(BaseModel):
 309    """Result of a connection check against a deployed Cloud connector."""
 310
 311    connector_id: str
 312    """The deployed connector ID."""
 313    connector_type: Literal["source", "destination"]
 314    """The connector type: 'source' or 'destination'."""
 315    succeeded: bool
 316    """Whether the connector check succeeded."""
 317    message: str | None
 318    """The failure message when the check failed, otherwise None."""
 319
 320
 321class SyncJobListResult(BaseModel):
 322    """Result of listing sync jobs with limit support."""
 323
 324    jobs: list[SyncJobResult]
 325    """List of sync jobs."""
 326    jobs_count: int
 327    """Number of jobs returned in this response."""
 328    from_tail: bool
 329    """Whether jobs are ordered newest-first (True) or oldest-first (False)."""
 330
 331
 332def _get_cloud_workspace(
 333    ctx: Context,
 334    workspace_id: str | None = None,
 335) -> CloudWorkspace:
 336    """Get an authenticated CloudWorkspace.
 337
 338    Resolves credentials from multiple sources via MCP config args in order:
 339    1. HTTP headers (when running as MCP server with HTTP/SSE transport)
 340    2. Environment variables
 341
 342    The ctx parameter provides access to MCP config values that are resolved
 343    from HTTP headers or environment variables based on the config args
 344    defined in server.py.
 345    """
 346    resolved_workspace_id = workspace_id or get_mcp_config(ctx, MCP_CONFIG_WORKSPACE_ID)
 347    if not resolved_workspace_id:
 348        raise AirbyteMissingWorkspaceContextError
 349
 350    return _get_cloud_client(ctx).get_workspace(resolved_workspace_id)
 351
 352
 353def _get_cloud_client(
 354    ctx: Context,
 355    *,
 356    organization_id: str | None = None,
 357) -> CloudClient:
 358    """Get an authenticated `CloudClient` from MCP config."""
 359    bearer_token = get_mcp_config(ctx, MCP_CONFIG_BEARER_TOKEN)
 360    client_id = get_mcp_config(ctx, MCP_CONFIG_CLIENT_ID)
 361    client_secret = get_mcp_config(ctx, MCP_CONFIG_CLIENT_SECRET)
 362    api_url = get_mcp_config(ctx, MCP_CONFIG_API_URL)
 363    config_api_url = get_mcp_config(ctx, MCP_CONFIG_CONFIG_API_URL)
 364
 365    return CloudClient(
 366        client_id=client_id,
 367        client_secret=client_secret,
 368        bearer_token=bearer_token,
 369        public_api_root=api_url,
 370        config_api_root=config_api_url,
 371        organization_id=organization_id,
 372    )
 373
 374
 375@mcp_tool(
 376    open_world=True,
 377    extra_help_text=CLOUD_AUTH_TIP_TEXT,
 378)
 379def deploy_source_to_cloud(
 380    ctx: Context,
 381    source_name: Annotated[
 382        str,
 383        Field(description="The name to use when deploying the source."),
 384    ],
 385    source_connector_name: Annotated[
 386        str,
 387        Field(description="The name of the source connector (e.g., 'source-faker')."),
 388    ],
 389    *,
 390    workspace_id: Annotated[
 391        str | None,
 392        Field(
 393            description=WORKSPACE_ID_TIP_TEXT,
 394            default=None,
 395        ),
 396    ],
 397    config: Annotated[
 398        dict | str | None,
 399        Field(
 400            description="The configuration for the source connector.",
 401            default=None,
 402        ),
 403    ],
 404    config_secret_name: Annotated[
 405        str | None,
 406        Field(
 407            description="The name of the secret containing the configuration.",
 408            default=None,
 409        ),
 410    ],
 411    unique: Annotated[
 412        bool,
 413        Field(
 414            description="Whether to require a unique name.",
 415            default=True,
 416        ),
 417    ],
 418) -> str:
 419    """Deploy a source connector to Airbyte Cloud."""
 420    source = get_source(
 421        source_connector_name,
 422        no_executor=True,
 423    )
 424    config_dict = resolve_connector_config(
 425        config=config,
 426        config_secret_name=config_secret_name,
 427        config_spec_jsonschema=source.config_spec,
 428    )
 429    source.set_config(config_dict, validate=True)
 430
 431    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
 432    deployed_source = workspace.deploy_source(
 433        name=source_name,
 434        source=source,
 435        unique=unique,
 436    )
 437
 438    register_guid_created_in_session(deployed_source.connector_id)
 439    return (
 440        f"Successfully deployed source '{source_name}' with ID '{deployed_source.connector_id}'"
 441        f" and URL: {deployed_source.connector_url}"
 442    )
 443
 444
 445@mcp_tool(
 446    open_world=True,
 447    extra_help_text=CLOUD_AUTH_TIP_TEXT,
 448)
 449def deploy_destination_to_cloud(
 450    ctx: Context,
 451    destination_name: Annotated[
 452        str,
 453        Field(description="The name to use when deploying the destination."),
 454    ],
 455    destination_connector_name: Annotated[
 456        str,
 457        Field(description="The name of the destination connector (e.g., 'destination-postgres')."),
 458    ],
 459    *,
 460    workspace_id: Annotated[
 461        str | None,
 462        Field(
 463            description=WORKSPACE_ID_TIP_TEXT,
 464            default=None,
 465        ),
 466    ],
 467    config: Annotated[
 468        dict | str | None,
 469        Field(
 470            description="The configuration for the destination connector.",
 471            default=None,
 472        ),
 473    ],
 474    config_secret_name: Annotated[
 475        str | None,
 476        Field(
 477            description="The name of the secret containing the configuration.",
 478            default=None,
 479        ),
 480    ],
 481    unique: Annotated[
 482        bool,
 483        Field(
 484            description="Whether to require a unique name.",
 485            default=True,
 486        ),
 487    ],
 488) -> str:
 489    """Deploy a destination connector to Airbyte Cloud."""
 490    destination = get_destination(
 491        destination_connector_name,
 492        no_executor=True,
 493    )
 494    config_dict = resolve_connector_config(
 495        config=config,
 496        config_secret_name=config_secret_name,
 497        config_spec_jsonschema=destination.config_spec,
 498    )
 499    destination.set_config(config_dict, validate=True)
 500
 501    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
 502    deployed_destination = workspace.deploy_destination(
 503        name=destination_name,
 504        destination=destination,
 505        unique=unique,
 506    )
 507
 508    register_guid_created_in_session(deployed_destination.connector_id)
 509    return (
 510        f"Successfully deployed destination '{destination_name}' "
 511        f"with ID: {deployed_destination.connector_id}"
 512    )
 513
 514
 515@mcp_tool(
 516    open_world=True,
 517    extra_help_text=CLOUD_AUTH_TIP_TEXT,
 518)
 519def create_connection_on_cloud(
 520    ctx: Context,
 521    connection_name: Annotated[
 522        str,
 523        Field(description="The name of the connection."),
 524    ],
 525    source_id: Annotated[
 526        str,
 527        Field(description="The ID of the deployed source."),
 528    ],
 529    destination_id: Annotated[
 530        str,
 531        Field(description="The ID of the deployed destination."),
 532    ],
 533    selected_streams: Annotated[
 534        str | list[str],
 535        Field(
 536            description=(
 537                "The selected stream names to sync within the connection. "
 538                "Must be an explicit stream name or list of streams. "
 539                "Cannot be empty or '*'."
 540            )
 541        ),
 542    ],
 543    *,
 544    workspace_id: Annotated[
 545        str | None,
 546        Field(
 547            description=WORKSPACE_ID_TIP_TEXT,
 548            default=None,
 549        ),
 550    ],
 551    table_prefix: Annotated[
 552        str | None,
 553        Field(
 554            description="Optional table prefix to use when syncing to the destination.",
 555            default=None,
 556        ),
 557    ],
 558) -> str:
 559    """Create a connection between a deployed source and destination on Airbyte Cloud."""
 560    resolved_streams_list: list[str] = resolve_list_of_strings(selected_streams)
 561    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
 562    deployed_connection = workspace.deploy_connection(
 563        connection_name=connection_name,
 564        source=source_id,
 565        destination=destination_id,
 566        selected_streams=resolved_streams_list,
 567        table_prefix=table_prefix,
 568    )
 569
 570    register_guid_created_in_session(deployed_connection.connection_id)
 571    return (
 572        f"Successfully created connection '{connection_name}' "
 573        f"with ID '{deployed_connection.connection_id}' and "
 574        f"URL: {deployed_connection.connection_url}"
 575    )
 576
 577
 578@mcp_tool(
 579    open_world=True,
 580    extra_help_text=CLOUD_AUTH_TIP_TEXT,
 581)
 582def run_cloud_sync(
 583    ctx: Context,
 584    connection_id: Annotated[
 585        str,
 586        Field(description="The ID of the Airbyte Cloud connection."),
 587    ],
 588    *,
 589    workspace_id: Annotated[
 590        str | None,
 591        Field(
 592            description=WORKSPACE_ID_TIP_TEXT,
 593            default=None,
 594        ),
 595    ],
 596    wait: Annotated[
 597        bool,
 598        Field(
 599            description=(
 600                "Whether to wait for the sync to complete. Since a sync can take between several "
 601                "minutes and several hours, this option is not recommended for most "
 602                "scenarios."
 603            ),
 604            default=False,
 605        ),
 606    ],
 607    wait_timeout: Annotated[
 608        int,
 609        Field(
 610            description="Maximum time to wait for sync completion (seconds).",
 611            default=300,
 612        ),
 613    ],
 614) -> str:
 615    """Run a sync job on Airbyte Cloud."""
 616    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
 617    connection = workspace.get_connection(connection_id=connection_id)
 618    sync_result = connection.run_sync(wait=wait, wait_timeout=wait_timeout)
 619
 620    if wait:
 621        status = sync_result.get_job_status()
 622        return (
 623            f"Sync completed with status: {status}. "
 624            f"Job ID is '{sync_result.job_id}' and "
 625            f"job URL is: {sync_result.job_url}"
 626        )
 627    return f"Sync started. Job ID is '{sync_result.job_id}' and job URL is: {sync_result.job_url}"
 628
 629
 630@mcp_tool(
 631    read_only=True,
 632    idempotent=True,
 633    open_world=True,
 634    extra_help_text=CLOUD_AUTH_TIP_TEXT,
 635)
 636def check_airbyte_cloud_workspace(
 637    ctx: Context,
 638    *,
 639    workspace_id: Annotated[
 640        str | None,
 641        Field(
 642            description=WORKSPACE_ID_TIP_TEXT,
 643            default=None,
 644        ),
 645    ],
 646) -> CloudWorkspaceResult:
 647    """Check if we have a valid Airbyte Cloud connection and return workspace info.
 648
 649    Returns workspace details including workspace ID, name, organization info, and billing status.
 650    """
 651    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
 652
 653    # Get workspace details from the public API using workspace's credentials
 654    workspace_response = api_util.get_workspace(
 655        workspace_id=workspace.workspace_id,
 656        api_root=workspace.api_root,
 657        client_id=workspace.client_id,
 658        client_secret=workspace.client_secret,
 659        bearer_token=workspace.bearer_token,
 660    )
 661
 662    # Try to get organization info (including billing), but fail gracefully if we don't have
 663    # permissions. Fetching organization info requires ORGANIZATION_READER permissions on the
 664    # organization, which may not be available with workspace-scoped credentials.
 665    organization = workspace.get_organization(raise_on_error=False)
 666
 667    return CloudWorkspaceResult(
 668        workspace_id=workspace_response.workspace_id,
 669        workspace_name=workspace_response.name,
 670        workspace_url=workspace.workspace_url,
 671        organization_id=(
 672            organization.organization_id
 673            if organization
 674            else "[unavailable - requires ORGANIZATION_READER permission]"
 675        ),
 676        organization_name=organization.organization_name if organization else None,
 677        payment_status=organization.payment_status if organization else None,
 678        subscription_status=organization.subscription_status if organization else None,
 679        is_account_locked=organization.is_account_locked if organization else False,
 680    )
 681
 682
 683@mcp_tool(
 684    open_world=True,
 685    extra_help_text=CLOUD_AUTH_TIP_TEXT,
 686)
 687def deploy_noop_destination_to_cloud(
 688    ctx: Context,
 689    name: str = "No-op Destination",
 690    *,
 691    workspace_id: Annotated[
 692        str | None,
 693        Field(
 694            description=WORKSPACE_ID_TIP_TEXT,
 695            default=None,
 696        ),
 697    ],
 698    unique: bool = True,
 699) -> str:
 700    """Deploy the No-op destination to Airbyte Cloud for testing purposes."""
 701    destination = get_noop_destination()
 702    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
 703    deployed_destination = workspace.deploy_destination(
 704        name=name,
 705        destination=destination,
 706        unique=unique,
 707    )
 708    register_guid_created_in_session(deployed_destination.connector_id)
 709    return (
 710        f"Successfully deployed No-op Destination "
 711        f"with ID '{deployed_destination.connector_id}' and "
 712        f"URL: {deployed_destination.connector_url}"
 713    )
 714
 715
 716@mcp_tool(
 717    read_only=True,
 718    idempotent=True,
 719    open_world=True,
 720    extra_help_text=CLOUD_AUTH_TIP_TEXT,
 721)
 722def get_cloud_sync_status(
 723    ctx: Context,
 724    connection_id: Annotated[
 725        str,
 726        Field(
 727            description="The ID of the Airbyte Cloud connection.",
 728        ),
 729    ],
 730    job_id: Annotated[
 731        int | None,
 732        Field(
 733            description="Optional job ID. If not provided, the latest job will be used.",
 734            default=None,
 735        ),
 736    ],
 737    *,
 738    workspace_id: Annotated[
 739        str | None,
 740        Field(
 741            description=WORKSPACE_ID_TIP_TEXT,
 742            default=None,
 743        ),
 744    ],
 745    include_attempts: Annotated[
 746        bool,
 747        Field(
 748            description="Whether to include detailed attempts information.",
 749            default=False,
 750        ),
 751    ],
 752) -> dict[str, Any]:
 753    """Get the status of a sync job from the Airbyte Cloud."""
 754    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
 755    connection = workspace.get_connection(connection_id=connection_id)
 756
 757    # If a job ID is provided, get the job by ID.
 758    sync_result: cloud.SyncResult | None = connection.get_sync_result(job_id=job_id)
 759
 760    if not sync_result:
 761        return {"status": None, "job_id": None, "attempts": []}
 762
 763    result = {
 764        "status": sync_result.get_job_status(),
 765        "job_id": sync_result.job_id,
 766        "bytes_synced": sync_result.bytes_synced,
 767        "records_synced": sync_result.records_synced,
 768        "start_time": sync_result.start_time.isoformat(),
 769        "job_url": sync_result.job_url,
 770        "attempts": [],
 771    }
 772
 773    if include_attempts:
 774        attempts = sync_result.get_attempts()
 775        result["attempts"] = [
 776            {
 777                "attempt_number": attempt.attempt_number,
 778                "attempt_id": attempt.attempt_id,
 779                "status": attempt.status,
 780                "bytes_synced": attempt.bytes_synced,
 781                "records_synced": attempt.records_synced,
 782                "created_at": attempt.created_at.isoformat(),
 783            }
 784            for attempt in attempts
 785        ]
 786
 787    return result
 788
 789
 790@mcp_tool(
 791    read_only=True,
 792    idempotent=True,
 793    open_world=True,
 794    extra_help_text=CLOUD_AUTH_TIP_TEXT,
 795)
 796def list_cloud_sync_jobs(
 797    ctx: Context,
 798    connection_id: Annotated[
 799        str,
 800        Field(description="The ID of the Airbyte Cloud connection."),
 801    ],
 802    *,
 803    workspace_id: Annotated[
 804        str | None,
 805        Field(
 806            description=WORKSPACE_ID_TIP_TEXT,
 807            default=None,
 808        ),
 809    ],
 810    max_jobs: Annotated[
 811        int,
 812        Field(
 813            description=(
 814                "Maximum number of jobs to return. "
 815                "Defaults to 20 if not specified. "
 816                "Maximum allowed value is 500."
 817            ),
 818            default=20,
 819        ),
 820    ],
 821    from_tail: Annotated[
 822        bool | None,
 823        Field(
 824            description=(
 825                "When True, jobs are ordered newest-first (createdAt DESC). "
 826                "When False, jobs are ordered oldest-first (createdAt ASC). "
 827                "Defaults to True."
 828            ),
 829            default=None,
 830        ),
 831    ],
 832    job_type: Annotated[
 833        JobTypeEnum | None,
 834        Field(
 835            description=(
 836                "Filter by job type. Options: 'sync', 'reset', 'refresh', 'clear'. "
 837                "If not specified, defaults to sync and reset jobs only (API default). "
 838                "Use 'refresh' to find refresh jobs or 'clear' to find clear jobs."
 839            ),
 840            default=None,
 841        ),
 842    ],
 843) -> SyncJobListResult:
 844    """List sync jobs for a connection with limit support.
 845
 846    This tool allows you to retrieve a list of sync jobs for a connection,
 847    with control over ordering and result limit. By default, jobs are returned
 848    newest-first (`from_tail=True`).
 849    """
 850    if from_tail is None:
 851        from_tail = True
 852
 853    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
 854    connection = workspace.get_connection(connection_id=connection_id)
 855
 856    # Cap at 500 to avoid overloading agent context
 857    effective_limit = min(max_jobs, 500) if max_jobs > 0 else 20
 858
 859    sync_results = connection.get_previous_sync_logs(
 860        limit=effective_limit,
 861        from_tail=from_tail,
 862        job_type=job_type,
 863    )
 864
 865    jobs = [
 866        SyncJobResult(
 867            job_id=sync_result.job_id,
 868            status=sync_result.get_job_status().value,
 869            bytes_synced=sync_result.bytes_synced,
 870            records_synced=sync_result.records_synced,
 871            start_time=sync_result.start_time.isoformat(),
 872            job_url=sync_result.job_url,
 873        )
 874        for sync_result in sync_results
 875    ]
 876
 877    return SyncJobListResult(
 878        jobs=jobs,
 879        jobs_count=len(jobs),
 880        from_tail=from_tail,
 881    )
 882
 883
 884@mcp_tool(
 885    destructive=True,
 886    open_world=True,
 887    extra_help_text=CLOUD_AUTH_TIP_TEXT,
 888)
 889def cancel_cloud_sync(
 890    ctx: Context,
 891    connection_id: Annotated[
 892        str,
 893        Field(description="The ID of the Airbyte Cloud connection."),
 894    ],
 895    job_id: Annotated[
 896        int | None,
 897        Field(
 898            description=(
 899                "Optional job ID to cancel. If not provided, the connection's most recent "
 900                "sync job will be cancelled. Other job types require an explicit job ID."
 901            ),
 902            default=None,
 903        ),
 904    ],
 905    *,
 906    workspace_id: Annotated[
 907        str | None,
 908        Field(
 909            description=WORKSPACE_ID_TIP_TEXT,
 910            default=None,
 911        ),
 912    ],
 913) -> SyncJobResult:
 914    """Cancel a running sync job on an Airbyte Cloud connection."""
 915    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
 916    connection = workspace.get_connection(connection_id=connection_id)
 917    # Deliberately omit check_guid_created_in_session: cancelling a sync is reversible.
 918    sync_result = connection.cancel_sync(job_id=job_id)
 919    return SyncJobResult(
 920        job_id=sync_result.job_id,
 921        status=sync_result.get_job_status().value,
 922        bytes_synced=sync_result.bytes_synced,
 923        records_synced=sync_result.records_synced,
 924        start_time=sync_result.start_time.isoformat(),
 925        job_url=sync_result.job_url,
 926    )
 927
 928
 929@mcp_tool(
 930    read_only=True,
 931    idempotent=True,
 932    open_world=True,
 933    extra_help_text=CLOUD_AUTH_TIP_TEXT,
 934)
 935def list_deployed_cloud_source_connectors(
 936    ctx: Context,
 937    *,
 938    workspace_id: Annotated[
 939        str | None,
 940        Field(
 941            description=WORKSPACE_ID_TIP_TEXT,
 942            default=None,
 943        ),
 944    ],
 945    name_contains: Annotated[
 946        str | None,
 947        Field(
 948            description="Optional case-insensitive substring to filter sources by name",
 949            default=None,
 950        ),
 951    ],
 952    limit: Annotated[
 953        int | None,
 954        Field(
 955            description="Optional maximum number of items to return (default: no limit)",
 956            default=None,
 957        ),
 958    ],
 959) -> list[CloudSourceResult]:
 960    """List all deployed source connectors in the Airbyte Cloud workspace."""
 961    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
 962    sources = workspace.list_sources(limit=None if name_contains else limit)
 963
 964    # Filter by name if requested
 965    if name_contains:
 966        needle = name_contains.lower()
 967        sources = [s for s in sources if s.name is not None and needle in s.name.lower()]
 968    if limit is not None:
 969        sources = sources[:limit]
 970
 971    # Note: name and url are guaranteed non-null from list API responses
 972    return [
 973        CloudSourceResult(
 974            id=source.source_id,
 975            name=cast(str, source.name),
 976            url=cast(str, source.connector_url),
 977        )
 978        for source in sources
 979    ]
 980
 981
 982@mcp_tool(
 983    read_only=True,
 984    idempotent=True,
 985    open_world=True,
 986    extra_help_text=CLOUD_AUTH_TIP_TEXT,
 987)
 988def list_deployed_cloud_destination_connectors(
 989    ctx: Context,
 990    *,
 991    workspace_id: Annotated[
 992        str | None,
 993        Field(
 994            description=WORKSPACE_ID_TIP_TEXT,
 995            default=None,
 996        ),
 997    ],
 998    name_contains: Annotated[
 999        str | None,
1000        Field(
1001            description="Optional case-insensitive substring to filter destinations by name",
1002            default=None,
1003        ),
1004    ],
1005    limit: Annotated[
1006        int | None,
1007        Field(
1008            description="Optional maximum number of items to return (default: no limit)",
1009            default=None,
1010        ),
1011    ],
1012) -> list[CloudDestinationResult]:
1013    """List all deployed destination connectors in the Airbyte Cloud workspace."""
1014    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
1015    destinations = workspace.list_destinations(limit=None if name_contains else limit)
1016
1017    # Filter by name if requested
1018    if name_contains:
1019        needle = name_contains.lower()
1020        destinations = [d for d in destinations if d.name is not None and needle in d.name.lower()]
1021    if limit is not None:
1022        destinations = destinations[:limit]
1023
1024    # Note: name and url are guaranteed non-null from list API responses
1025    return [
1026        CloudDestinationResult(
1027            id=destination.destination_id,
1028            name=cast(str, destination.name),
1029            url=cast(str, destination.connector_url),
1030        )
1031        for destination in destinations
1032    ]
1033
1034
1035@mcp_tool(
1036    read_only=True,
1037    idempotent=True,
1038    open_world=True,
1039    extra_help_text=CLOUD_AUTH_TIP_TEXT,
1040)
1041def describe_cloud_source(
1042    ctx: Context,
1043    source_id: Annotated[
1044        str,
1045        Field(description="The ID of the source to describe."),
1046    ],
1047    *,
1048    workspace_id: Annotated[
1049        str | None,
1050        Field(
1051            description=WORKSPACE_ID_TIP_TEXT,
1052            default=None,
1053        ),
1054    ],
1055) -> CloudSourceDetails:
1056    """Get detailed information about a specific deployed source connector."""
1057    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
1058    source = workspace.get_source(source_id=source_id)
1059
1060    source_name = cast(str, source.name)
1061
1062    return CloudSourceDetails(
1063        source_id=source.source_id,
1064        source_name=source_name,
1065        source_url=source.connector_url,
1066        connector_definition_id=source.definition_id,
1067    )
1068
1069
1070@mcp_tool(
1071    read_only=True,
1072    idempotent=True,
1073    open_world=True,
1074    extra_help_text=CLOUD_AUTH_TIP_TEXT,
1075)
1076def describe_cloud_destination(
1077    ctx: Context,
1078    destination_id: Annotated[
1079        str,
1080        Field(description="The ID of the destination to describe."),
1081    ],
1082    *,
1083    workspace_id: Annotated[
1084        str | None,
1085        Field(
1086            description=WORKSPACE_ID_TIP_TEXT,
1087            default=None,
1088        ),
1089    ],
1090) -> CloudDestinationDetails:
1091    """Get detailed information about a specific deployed destination connector."""
1092    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
1093    destination = workspace.get_destination(destination_id=destination_id)
1094
1095    destination_name = cast(str, destination.name)
1096
1097    return CloudDestinationDetails(
1098        destination_id=destination.destination_id,
1099        destination_name=destination_name,
1100        destination_url=destination.connector_url,
1101        connector_definition_id=destination.definition_id,
1102    )
1103
1104
1105@mcp_tool(
1106    read_only=True,
1107    idempotent=True,
1108    open_world=True,
1109    extra_help_text=CLOUD_AUTH_TIP_TEXT,
1110)
1111def check_cloud_source(
1112    ctx: Context,
1113    source_id: Annotated[
1114        str,
1115        Field(description="The ID of the deployed source connector to check."),
1116    ],
1117    *,
1118    workspace_id: Annotated[
1119        str | None,
1120        Field(
1121            description=WORKSPACE_ID_TIP_TEXT,
1122            default=None,
1123        ),
1124    ],
1125) -> ConnectorCheckResult:
1126    """Check the configuration and credentials of a deployed source connector."""
1127    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
1128    source = workspace.get_source(source_id=source_id)
1129    check_result = source.check(raise_on_error=False)
1130    return ConnectorCheckResult(
1131        connector_id=source_id,
1132        connector_type=source.connector_type,
1133        succeeded=check_result.success,
1134        message=_get_connector_check_message(check_result),
1135    )
1136
1137
1138@mcp_tool(
1139    read_only=True,
1140    idempotent=True,
1141    open_world=True,
1142    extra_help_text=CLOUD_AUTH_TIP_TEXT,
1143)
1144def check_cloud_destination(
1145    ctx: Context,
1146    destination_id: Annotated[
1147        str,
1148        Field(description="The ID of the deployed destination connector to check."),
1149    ],
1150    *,
1151    workspace_id: Annotated[
1152        str | None,
1153        Field(
1154            description=WORKSPACE_ID_TIP_TEXT,
1155            default=None,
1156        ),
1157    ],
1158) -> ConnectorCheckResult:
1159    """Check the configuration and credentials of a deployed destination connector."""
1160    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
1161    destination = workspace.get_destination(destination_id=destination_id)
1162    check_result = destination.check(raise_on_error=False)
1163    return ConnectorCheckResult(
1164        connector_id=destination_id,
1165        connector_type=destination.connector_type,
1166        succeeded=check_result.success,
1167        message=_get_connector_check_message(check_result),
1168    )
1169
1170
1171@mcp_tool(
1172    read_only=True,
1173    idempotent=True,
1174    open_world=True,
1175    extra_help_text=CLOUD_AUTH_TIP_TEXT,
1176)
1177def describe_cloud_connection(
1178    ctx: Context,
1179    connection_id: Annotated[
1180        str,
1181        Field(description="The ID of the connection to describe."),
1182    ],
1183    *,
1184    workspace_id: Annotated[
1185        str | None,
1186        Field(
1187            description=WORKSPACE_ID_TIP_TEXT,
1188            default=None,
1189        ),
1190    ],
1191) -> CloudConnectionDetails:
1192    """Get detailed information about a specific deployed connection."""
1193    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
1194    connection = workspace.get_connection(connection_id=connection_id)
1195
1196    return CloudConnectionDetails(
1197        connection_id=connection.connection_id,
1198        connection_name=cast(str, connection.name),
1199        connection_url=cast(str, connection.connection_url),
1200        source_id=connection.source_id,
1201        source_name=cast(str, connection.source.name),
1202        destination_id=connection.destination_id,
1203        destination_name=cast(str, connection.destination.name),
1204        selected_streams=connection.stream_names,
1205        table_prefix=connection.table_prefix,
1206    )
1207
1208
1209@mcp_tool(
1210    read_only=True,
1211    idempotent=True,
1212    open_world=True,
1213    extra_help_text=CLOUD_AUTH_TIP_TEXT,
1214)
1215def get_cloud_sync_logs(
1216    ctx: Context,
1217    connection_id: Annotated[
1218        str,
1219        Field(description="The ID of the Airbyte Cloud connection."),
1220    ],
1221    job_id: Annotated[
1222        int | None,
1223        Field(description="Optional job ID. If not provided, the latest job will be used."),
1224    ] = None,
1225    attempt_number: Annotated[
1226        int | None,
1227        Field(
1228            description="Optional attempt number. If not provided, the latest attempt will be used."
1229        ),
1230    ] = None,
1231    *,
1232    workspace_id: Annotated[
1233        str | None,
1234        Field(
1235            description=WORKSPACE_ID_TIP_TEXT,
1236            default=None,
1237        ),
1238    ],
1239    max_lines: Annotated[
1240        int,
1241        Field(
1242            description=(
1243                "Maximum number of lines to return. "
1244                "Defaults to 4000 if not specified. "
1245                "If '0' is provided, no limit is applied."
1246            ),
1247            default=4000,
1248        ),
1249    ],
1250    from_tail: Annotated[
1251        bool | None,
1252        Field(
1253            description=(
1254                "Pull from the end of the log text if total lines is greater than 'max_lines'. "
1255                "Defaults to True if `line_offset` is not specified. "
1256                "Cannot combine `from_tail=True` with `line_offset`."
1257            ),
1258            default=None,
1259        ),
1260    ],
1261    line_offset: Annotated[
1262        int | None,
1263        Field(
1264            description=(
1265                "Number of lines to skip from the beginning of the logs. "
1266                "Cannot be combined with `from_tail=True`."
1267            ),
1268            default=None,
1269        ),
1270    ],
1271) -> LogReadResult:
1272    """Get the logs from a sync job attempt on Airbyte Cloud."""
1273    # Validate that line_offset and from_tail are not both set
1274    if line_offset is not None and from_tail:
1275        raise PyAirbyteInputError(
1276            message="Cannot specify both 'line_offset' and 'from_tail' parameters.",
1277            context={"line_offset": line_offset, "from_tail": from_tail},
1278        )
1279
1280    if from_tail is None and line_offset is None:
1281        from_tail = True
1282    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
1283    connection = workspace.get_connection(connection_id=connection_id)
1284
1285    sync_result: cloud.SyncResult | None = connection.get_sync_result(job_id=job_id)
1286
1287    if not sync_result:
1288        raise AirbyteMissingResourceError(
1289            resource_type="sync job",
1290            resource_name_or_id=connection_id,
1291        )
1292
1293    attempts = sync_result.get_attempts()
1294
1295    if not attempts:
1296        raise AirbyteMissingResourceError(
1297            resource_type="sync attempt",
1298            resource_name_or_id=str(sync_result.job_id),
1299        )
1300
1301    if attempt_number is not None:
1302        target_attempt = None
1303        for attempt in attempts:
1304            if attempt.attempt_number == attempt_number:
1305                target_attempt = attempt
1306                break
1307
1308        if target_attempt is None:
1309            raise AirbyteMissingResourceError(
1310                resource_type="sync attempt",
1311                resource_name_or_id=f"job {sync_result.job_id}, attempt {attempt_number}",
1312            )
1313    else:
1314        target_attempt = max(attempts, key=lambda a: a.attempt_number)
1315
1316    logs = target_attempt.get_full_log_text()
1317
1318    if not logs:
1319        # Return empty result with zero lines
1320        return LogReadResult(
1321            log_text=(
1322                f"[No logs available for job '{sync_result.job_id}', "
1323                f"attempt {target_attempt.attempt_number}.]"
1324            ),
1325            log_text_start_line=1,
1326            log_text_line_count=0,
1327            total_log_lines_available=0,
1328            job_id=sync_result.job_id,
1329            attempt_number=target_attempt.attempt_number,
1330        )
1331
1332    # Apply line limiting
1333    log_lines = logs.splitlines()
1334    total_lines = len(log_lines)
1335
1336    # Determine effective max_lines (0 means no limit)
1337    effective_max = total_lines if max_lines == 0 else max_lines
1338
1339    # Calculate start_index and slice based on from_tail or line_offset
1340    if from_tail:
1341        start_index = max(0, total_lines - effective_max)
1342        selected_lines = log_lines[start_index:][:effective_max]
1343    else:
1344        start_index = line_offset or 0
1345        selected_lines = log_lines[start_index : start_index + effective_max]
1346
1347    return LogReadResult(
1348        log_text="\n".join(selected_lines),
1349        log_text_start_line=start_index + 1,  # Convert to 1-based index
1350        log_text_line_count=len(selected_lines),
1351        total_log_lines_available=total_lines,
1352        job_id=sync_result.job_id,
1353        attempt_number=target_attempt.attempt_number,
1354    )
1355
1356
1357@mcp_tool(
1358    read_only=True,
1359    idempotent=True,
1360    open_world=True,
1361    extra_help_text=CLOUD_AUTH_TIP_TEXT,
1362)
1363def list_deployed_cloud_connections(
1364    ctx: Context,
1365    *,
1366    workspace_id: Annotated[
1367        str | None,
1368        Field(
1369            description=WORKSPACE_ID_TIP_TEXT,
1370            default=None,
1371        ),
1372    ],
1373    name_contains: Annotated[
1374        str | None,
1375        Field(
1376            description="Optional case-insensitive substring to filter connections by name",
1377            default=None,
1378        ),
1379    ],
1380    limit: Annotated[
1381        int | None,
1382        Field(
1383            description="Optional maximum number of items to return (default: no limit)",
1384            default=None,
1385        ),
1386    ],
1387    with_connection_status: Annotated[
1388        bool | None,
1389        Field(
1390            description="If True, include status info for each connection's most recent sync job",
1391            default=False,
1392        ),
1393    ],
1394    failing_connections_only: Annotated[
1395        bool | None,
1396        Field(
1397            description="If True, only return connections with failed/cancelled last sync",
1398            default=False,
1399        ),
1400    ],
1401) -> list[CloudConnectionResult]:
1402    """List all deployed connections in the Airbyte Cloud workspace.
1403
1404    When with_connection_status is True, each connection result will include
1405    information about the most recent sync job status, skipping over any
1406    currently in-progress syncs to find the last completed job.
1407
1408    When failing_connections_only is True, only connections where the most
1409    recent completed sync job failed or was cancelled will be returned.
1410    This implicitly enables with_connection_status.
1411    """
1412    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
1413    connections = workspace.list_connections(
1414        limit=None if name_contains or failing_connections_only else limit
1415    )
1416
1417    # Filter by name if requested
1418    if name_contains:
1419        needle = name_contains.lower()
1420        connections = [c for c in connections if c.name is not None and needle in c.name.lower()]
1421
1422    # If failing_connections_only is True, implicitly enable with_connection_status
1423    if failing_connections_only:
1424        with_connection_status = True
1425
1426    results: list[CloudConnectionResult] = []
1427
1428    for connection in connections:
1429        last_job_status: str | None = None
1430        last_job_id: int | None = None
1431        last_job_time: str | None = None
1432        currently_running_job_id: int | None = None
1433        currently_running_job_start_time: str | None = None
1434
1435        if with_connection_status:
1436            sync_logs = connection.get_previous_sync_logs(limit=5)
1437            last_completed_job_status = None  # Keep enum for comparison
1438
1439            for sync_result in sync_logs:
1440                job_status = sync_result.get_job_status()
1441
1442                if not sync_result.is_job_complete():
1443                    currently_running_job_id = sync_result.job_id
1444                    currently_running_job_start_time = sync_result.start_time.isoformat()
1445                    continue
1446
1447                last_completed_job_status = job_status
1448                last_job_status = job_status.value
1449                last_job_id = sync_result.job_id
1450                last_job_time = sync_result.start_time.isoformat()
1451                break
1452
1453            if failing_connections_only and (
1454                last_completed_job_status is None
1455                or last_completed_job_status not in FAILED_STATUSES
1456            ):
1457                continue
1458
1459        results.append(
1460            CloudConnectionResult(
1461                id=connection.connection_id,
1462                name=cast(str, connection.name),
1463                url=cast(str, connection.connection_url),
1464                source_id=connection.source_id,
1465                destination_id=connection.destination_id,
1466                last_job_status=last_job_status,
1467                last_job_id=last_job_id,
1468                last_job_time=last_job_time,
1469                currently_running_job_id=currently_running_job_id,
1470                currently_running_job_start_time=currently_running_job_start_time,
1471            )
1472        )
1473
1474        if limit is not None and len(results) >= limit:
1475            break
1476
1477    return results
1478
1479
1480def _resolve_organization_id(
1481    organization_id: str | None,
1482    organization_name: str | None,
1483    *,
1484    client: CloudClient,
1485) -> str:
1486    """Resolve organization ID from either ID or exact name match."""
1487    if organization_id is not None:
1488        return organization_id
1489
1490    org = client.get_organization(
1491        organization_id=organization_id,
1492        organization_name=organization_name,
1493    )
1494    return org.organization_id
1495
1496
1497@mcp_tool(
1498    read_only=True,
1499    idempotent=True,
1500    open_world=True,
1501    extra_help_text=CLOUD_AUTH_TIP_TEXT,
1502)
1503def list_cloud_workspaces(
1504    ctx: Context,
1505    *,
1506    organization_id: Annotated[
1507        str | None,
1508        Field(
1509            description="Optional organization ID to list workspaces within.",
1510            default=None,
1511        ),
1512    ],
1513    organization_name: Annotated[
1514        str | None,
1515        Field(
1516            description=("Optional organization name (exact match) to list workspaces within."),
1517            default=None,
1518        ),
1519    ],
1520    name_contains: Annotated[
1521        str | None,
1522        Field(
1523            description="Optional substring to filter workspaces by name (server-side filtering)",
1524            default=None,
1525        ),
1526    ],
1527    limit: Annotated[
1528        int | None,
1529        Field(
1530            description="Optional maximum number of items to return (default: no limit)",
1531            default=None,
1532        ),
1533    ],
1534) -> CloudWorkspaceListResult:
1535    """List all workspaces visible to the authenticated credentials.
1536
1537    When an organization ID or exact organization name is provided, the Config API
1538    lists workspaces in that organization. When neither is provided and the client
1539    has no default organization, the public API lists workspaces across organizations
1540    visible to the current credentials. Otherwise, results are scoped to the client's
1541    default organization.
1542    """
1543    client = _get_cloud_client(ctx)
1544
1545    try:
1546        workspaces = client.list_workspaces(
1547            organization_id=(
1548                _resolve_organization_id(
1549                    organization_id=organization_id,
1550                    organization_name=organization_name,
1551                    client=client,
1552                )
1553                if organization_id is not None or organization_name is not None
1554                else None
1555            ),
1556            name_contains=name_contains,
1557            limit=limit,
1558        )
1559    except AirbyteError as error:
1560        return _handle_discovery_permission_error(
1561            error,
1562            make_result=lambda message: CloudWorkspaceListResult(
1563                workspaces=[],
1564                message=message,
1565            ),
1566        )
1567
1568    results = [
1569        CloudWorkspaceResult(
1570            workspace_id=ws.workspace_id,
1571            workspace_name=ws.name,
1572            organization_id=ws.organization_id,
1573        )
1574        for ws in workspaces
1575    ]
1576    return CloudWorkspaceListResult(
1577        workspaces=results,
1578        message=(
1579            "No workspaces were returned for these credentials. Verify the "
1580            "credentials or ask the user to provide a workspace ID."
1581            if not results
1582            else None
1583        ),
1584    )
1585
1586
1587@mcp_tool(
1588    read_only=True,
1589    idempotent=True,
1590    open_world=True,
1591    extra_help_text=CLOUD_AUTH_TIP_TEXT,
1592)
1593def list_cloud_organizations(
1594    ctx: Context,
1595) -> CloudOrganizationListResult:
1596    """List organizations visible to the authenticated Airbyte Cloud credentials."""
1597    try:
1598        organizations = _get_cloud_client(ctx).list_organizations()
1599    except AirbyteError as error:
1600        return _handle_discovery_permission_error(
1601            error,
1602            make_result=lambda message: CloudOrganizationListResult(
1603                organizations=[],
1604                message=message,
1605            ),
1606        )
1607
1608    if not organizations:
1609        return CloudOrganizationListResult(
1610            organizations=[],
1611            message=(
1612                "No organizations were returned for these credentials. Verify the "
1613                "credentials or ask the user to provide an organization ID."
1614            ),
1615        )
1616
1617    return CloudOrganizationListResult(
1618        organizations=[
1619            CloudOrganizationResult(
1620                id=organization.organization_id,
1621                name=organization.organization_name or "",
1622                email=organization.email or "",
1623            )
1624            for organization in organizations
1625        ]
1626    )
1627
1628
1629@mcp_tool(
1630    read_only=True,
1631    idempotent=True,
1632    open_world=True,
1633    extra_help_text=CLOUD_AUTH_TIP_TEXT,
1634)
1635def describe_cloud_organization(
1636    ctx: Context,
1637    *,
1638    organization_id: Annotated[
1639        str | None,
1640        Field(
1641            description="Organization ID. Required if organization_name is not provided.",
1642            default=None,
1643        ),
1644    ],
1645    organization_name: Annotated[
1646        str | None,
1647        Field(
1648            description=(
1649                "Organization name (exact match). " "Required if organization_id is not provided."
1650            ),
1651            default=None,
1652        ),
1653    ],
1654) -> CloudOrganizationResult:
1655    """Get details about a specific organization including billing status.
1656
1657    Requires either organization_id OR organization_name (exact match) to be provided.
1658    This tool is useful for looking up an organization's ID from its name, or vice versa.
1659    """
1660    org = _get_cloud_client(ctx).get_organization(
1661        organization_id=organization_id,
1662        organization_name=organization_name,
1663    )
1664
1665    # CloudOrganization has lazy loading of billing properties
1666    return CloudOrganizationResult(
1667        id=org.organization_id,
1668        name=org.organization_name,
1669        email=org.email,
1670        payment_status=org.payment_status,
1671        subscription_status=org.subscription_status,
1672        is_account_locked=org.is_account_locked,
1673    )
1674
1675
1676def _get_custom_source_definition_description(
1677    custom_source: CustomCloudSourceDefinition,
1678) -> str:
1679    return "\n".join(
1680        [
1681            f" - Custom Source Name: {custom_source.name}",
1682            f" - Definition ID: {custom_source.definition_id}",
1683            f" - Definition Version: {custom_source.version}",
1684            f" - Connector Builder Project ID: {custom_source.connector_builder_project_id}",
1685            f" - Connector Builder Project URL: {custom_source.connector_builder_project_url}",
1686        ]
1687    )
1688
1689
1690@mcp_tool(
1691    open_world=True,
1692    extra_help_text=CLOUD_AUTH_TIP_TEXT,
1693)
1694def publish_custom_source_definition(
1695    ctx: Context,
1696    name: Annotated[
1697        str,
1698        Field(description="The name for the custom connector definition."),
1699    ],
1700    *,
1701    workspace_id: Annotated[
1702        str | None,
1703        Field(
1704            description=WORKSPACE_ID_TIP_TEXT,
1705            default=None,
1706        ),
1707    ],
1708    manifest_yaml: Annotated[
1709        str | Path | None,
1710        Field(
1711            description=(
1712                "The Low-code CDK manifest as a YAML string or file path. "
1713                "Required for YAML connectors."
1714            ),
1715            default=None,
1716        ),
1717    ] = None,
1718    unique: Annotated[
1719        bool,
1720        Field(
1721            description="Whether to require a unique name.",
1722            default=True,
1723        ),
1724    ] = True,
1725    pre_validate: Annotated[
1726        bool,
1727        Field(
1728            description="Whether to validate the manifest client-side before publishing.",
1729            default=True,
1730        ),
1731    ] = True,
1732    testing_values: Annotated[
1733        dict | str | None,
1734        Field(
1735            description=(
1736                "Optional testing configuration values for the Builder UI. "
1737                "Can be provided as a JSON object or JSON string. "
1738                "Supports inline secret refs via 'secret_reference::ENV_VAR_NAME' syntax. "
1739                "If provided, these values replace any existing testing values "
1740                "for the connector builder project, allowing immediate test read operations."
1741            ),
1742            default=None,
1743        ),
1744    ],
1745    testing_values_secret_name: Annotated[
1746        str | None,
1747        Field(
1748            description=(
1749                "Optional name of a secret containing testing configuration values "
1750                "in JSON or YAML format. The secret will be resolved by the MCP "
1751                "server and merged into testing_values, with secret values taking "
1752                "precedence. This lets the agent reference secrets without sending "
1753                "raw values as tool arguments."
1754            ),
1755            default=None,
1756        ),
1757    ],
1758) -> str:
1759    """Publish a custom YAML source connector definition to Airbyte Cloud.
1760
1761    Note: Only YAML (declarative) connectors are currently supported.
1762    Docker-based custom sources are not yet available.
1763    """
1764    processed_manifest = manifest_yaml
1765    if isinstance(manifest_yaml, str) and "\n" not in manifest_yaml:
1766        processed_manifest = Path(manifest_yaml)
1767
1768    # Resolve testing values from inline config and/or secret
1769    testing_values_dict: dict[str, Any] | None = None
1770    if testing_values is not None or testing_values_secret_name is not None:
1771        testing_values_dict = (
1772            resolve_connector_config(
1773                config=testing_values,
1774                config_secret_name=testing_values_secret_name,
1775            )
1776            or None
1777        )
1778
1779    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
1780    custom_source = workspace.publish_custom_source_definition(
1781        name=name,
1782        manifest_yaml=processed_manifest,
1783        unique=unique,
1784        pre_validate=pre_validate,
1785        testing_values=testing_values_dict,
1786    )
1787    register_guid_created_in_session(custom_source.definition_id)
1788    return (
1789        "Successfully published custom YAML source definition:\n"
1790        + _get_custom_source_definition_description(
1791            custom_source=custom_source,
1792        )
1793        + "\n"
1794    )
1795
1796
1797@mcp_tool(
1798    read_only=True,
1799    idempotent=True,
1800    open_world=True,
1801)
1802def list_custom_source_definitions(
1803    ctx: Context,
1804    *,
1805    workspace_id: Annotated[
1806        str | None,
1807        Field(
1808            description=WORKSPACE_ID_TIP_TEXT,
1809            default=None,
1810        ),
1811    ],
1812) -> list[dict[str, Any]]:
1813    """List custom YAML source definitions in the Airbyte Cloud workspace.
1814
1815    Note: Only YAML (declarative) connectors are currently supported.
1816    Docker-based custom sources are not yet available.
1817    """
1818    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
1819    definitions = workspace.list_custom_source_definitions(
1820        definition_type="yaml",
1821    )
1822
1823    return [
1824        {
1825            "definition_id": d.definition_id,
1826            "name": d.name,
1827            "version": d.version,
1828            "connector_builder_project_url": d.connector_builder_project_url,
1829        }
1830        for d in definitions
1831    ]
1832
1833
1834@mcp_tool(
1835    read_only=True,
1836    idempotent=True,
1837    open_world=True,
1838)
1839def get_custom_source_definition(
1840    ctx: Context,
1841    definition_id: Annotated[
1842        str,
1843        Field(description="The ID of the custom source definition to retrieve."),
1844    ],
1845    *,
1846    workspace_id: Annotated[
1847        str | None,
1848        Field(
1849            description=WORKSPACE_ID_TIP_TEXT,
1850            default=None,
1851        ),
1852    ],
1853    include_draft: Annotated[
1854        bool,
1855        Field(
1856            description=(
1857                "Whether to include the Connector Builder draft manifest in the response. "
1858                "If True and a draft exists, the response will include 'has_draft' and "
1859                "'draft_manifest' fields. Defaults to False."
1860            ),
1861            default=False,
1862        ),
1863    ] = False,
1864) -> dict[str, Any]:
1865    """Get a custom YAML source definition from Airbyte Cloud, including its manifest.
1866
1867    Returns the full definition details including the published manifest YAML content.
1868    Optionally includes the Connector Builder draft manifest (unpublished changes)
1869    when include_draft=True.
1870
1871    Note: Only YAML (declarative) connectors are currently supported.
1872    Docker-based custom sources are not yet available.
1873    """
1874    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
1875    definition = workspace.get_custom_source_definition(
1876        definition_id=definition_id,
1877        definition_type="yaml",
1878    )
1879
1880    result: dict[str, Any] = {
1881        "definition_id": definition.definition_id,
1882        "name": definition.name,
1883        "version": definition.version,
1884        "connector_builder_project_id": definition.connector_builder_project_id,
1885        "connector_builder_project_url": definition.connector_builder_project_url,
1886        "manifest": definition.manifest,
1887    }
1888
1889    if include_draft:
1890        result["has_draft"] = definition.has_draft
1891        result["draft_manifest"] = definition.draft_manifest
1892
1893    return result
1894
1895
1896@mcp_tool(
1897    read_only=True,
1898    idempotent=True,
1899    open_world=True,
1900)
1901def get_connector_builder_draft_manifest(
1902    ctx: Context,
1903    definition_id: Annotated[
1904        str,
1905        Field(description="The ID of the custom source definition to retrieve the draft for."),
1906    ],
1907    *,
1908    workspace_id: Annotated[
1909        str | None,
1910        Field(
1911            description=WORKSPACE_ID_TIP_TEXT,
1912            default=None,
1913        ),
1914    ],
1915) -> dict[str, Any]:
1916    """Get the Connector Builder draft manifest for a custom source definition.
1917
1918    Returns the working draft manifest that has been saved in the Connector Builder UI
1919    but not yet published. This is useful for inspecting what a user is currently working
1920    on before they publish their changes.
1921
1922    If no draft exists, 'has_draft' will be False and 'draft_manifest' will be None.
1923    The published manifest is always included for comparison.
1924    """
1925    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
1926    definition = workspace.get_custom_source_definition(
1927        definition_id=definition_id,
1928        definition_type="yaml",
1929    )
1930
1931    return {
1932        "definition_id": definition.definition_id,
1933        "name": definition.name,
1934        "connector_builder_project_id": definition.connector_builder_project_id,
1935        "connector_builder_project_url": definition.connector_builder_project_url,
1936        "has_draft": definition.has_draft,
1937        "draft_manifest": definition.draft_manifest,
1938        "published_manifest": definition.manifest,
1939    }
1940
1941
1942@mcp_tool(
1943    destructive=True,
1944    open_world=True,
1945)
1946def update_custom_source_definition(
1947    ctx: Context,
1948    definition_id: Annotated[
1949        str,
1950        Field(description="The ID of the definition to update."),
1951    ],
1952    manifest_yaml: Annotated[
1953        str | Path | None,
1954        Field(
1955            description=(
1956                "New manifest as YAML string or file path. "
1957                "Optional; omit to update only testing values."
1958            ),
1959            default=None,
1960        ),
1961    ] = None,
1962    *,
1963    workspace_id: Annotated[
1964        str | None,
1965        Field(
1966            description=WORKSPACE_ID_TIP_TEXT,
1967            default=None,
1968        ),
1969    ],
1970    pre_validate: Annotated[
1971        bool,
1972        Field(
1973            description="Whether to validate the manifest client-side before updating.",
1974            default=True,
1975        ),
1976    ] = True,
1977    testing_values: Annotated[
1978        dict | str | None,
1979        Field(
1980            description=(
1981                "Optional testing configuration values for the Builder UI. "
1982                "Can be provided as a JSON object or JSON string. "
1983                "Supports inline secret refs via 'secret_reference::ENV_VAR_NAME' syntax. "
1984                "If provided, these values replace any existing testing values "
1985                "for the connector builder project. The entire testing values object "
1986                "is overwritten, so pass the full set of values you want to persist."
1987            ),
1988            default=None,
1989        ),
1990    ],
1991    testing_values_secret_name: Annotated[
1992        str | None,
1993        Field(
1994            description=(
1995                "Optional name of a secret containing testing configuration values "
1996                "in JSON or YAML format. The secret will be resolved by the MCP "
1997                "server and merged into testing_values, with secret values taking "
1998                "precedence. This lets the agent reference secrets without sending "
1999                "raw values as tool arguments."
2000            ),
2001            default=None,
2002        ),
2003    ],
2004) -> str:
2005    """Update a custom YAML source definition in Airbyte Cloud.
2006
2007    Updates the manifest and/or testing values for an existing custom source definition.
2008    At least one of manifest_yaml, testing_values, or testing_values_secret_name must be provided.
2009    """
2010    check_guid_created_in_session(definition_id)
2011
2012    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
2013
2014    if manifest_yaml is None and testing_values is None and testing_values_secret_name is None:
2015        raise PyAirbyteInputError(
2016            message=(
2017                "At least one of manifest_yaml, testing_values, or testing_values_secret_name "
2018                "must be provided to update a custom source definition."
2019            ),
2020            context={
2021                "definition_id": definition_id,
2022                "workspace_id": workspace.workspace_id,
2023            },
2024        )
2025
2026    processed_manifest: str | Path | None = manifest_yaml
2027    if isinstance(manifest_yaml, str) and "\n" not in manifest_yaml:
2028        processed_manifest = Path(manifest_yaml)
2029
2030    # Resolve testing values from inline config and/or secret
2031    testing_values_dict: dict[str, Any] | None = None
2032    if testing_values is not None or testing_values_secret_name is not None:
2033        testing_values_dict = (
2034            resolve_connector_config(
2035                config=testing_values,
2036                config_secret_name=testing_values_secret_name,
2037            )
2038            or None
2039        )
2040
2041    definition = workspace.get_custom_source_definition(
2042        definition_id=definition_id,
2043        definition_type="yaml",
2044    )
2045    custom_source: CustomCloudSourceDefinition = definition
2046
2047    if processed_manifest is not None:
2048        custom_source = definition.update_definition(
2049            manifest_yaml=processed_manifest,
2050            pre_validate=pre_validate,
2051        )
2052
2053    if testing_values_dict is not None:
2054        custom_source.set_testing_values(testing_values_dict)
2055
2056    return (
2057        "Successfully updated custom YAML source definition:\n"
2058        + _get_custom_source_definition_description(
2059            custom_source=custom_source,
2060        )
2061    )
2062
2063
2064@mcp_tool(
2065    destructive=True,
2066    open_world=True,
2067)
2068def permanently_delete_custom_source_definition(
2069    ctx: Context,
2070    definition_id: Annotated[
2071        str,
2072        Field(description="The ID of the custom source definition to delete."),
2073    ],
2074    name: Annotated[
2075        str,
2076        Field(description="The expected name of the custom source definition (for verification)."),
2077    ],
2078    *,
2079    workspace_id: Annotated[
2080        str | None,
2081        Field(
2082            description=WORKSPACE_ID_TIP_TEXT,
2083            default=None,
2084        ),
2085    ],
2086) -> str:
2087    """Permanently delete a custom YAML source definition from Airbyte Cloud.
2088
2089    IMPORTANT: This operation requires the connector name to contain "delete-me" or "deleteme"
2090    (case insensitive).
2091
2092    If the connector does not meet this requirement, the deletion will be rejected with a
2093    helpful error message. Instruct the user to rename the connector appropriately to authorize
2094    the deletion.
2095
2096    The provided name must match the actual name of the definition for the operation to proceed.
2097    This is a safety measure to ensure you are deleting the correct resource.
2098
2099    Note: Only YAML (declarative) connectors are currently supported.
2100    Docker-based custom sources are not yet available.
2101    """
2102    check_guid_created_in_session(definition_id)
2103    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
2104    definition = workspace.get_custom_source_definition(
2105        definition_id=definition_id,
2106        definition_type="yaml",
2107    )
2108    actual_name: str = definition.name
2109
2110    # Verify the name matches
2111    if actual_name != name:
2112        raise PyAirbyteInputError(
2113            message=(
2114                f"Name mismatch: expected '{name}' but found '{actual_name}'. "
2115                "The provided name must exactly match the definition's actual name. "
2116                "This is a safety measure to prevent accidental deletion."
2117            ),
2118            context={
2119                "definition_id": definition_id,
2120                "expected_name": name,
2121                "actual_name": actual_name,
2122            },
2123        )
2124
2125    definition.permanently_delete(
2126        safe_mode=True,  # Hard-coded safe mode for extra protection when running in LLM agents.
2127    )
2128    return f"Successfully deleted custom source definition '{actual_name}' (ID: {definition_id})"
2129
2130
2131@mcp_tool(
2132    destructive=True,
2133    open_world=True,
2134    extra_help_text=CLOUD_AUTH_TIP_TEXT,
2135)
2136def permanently_delete_cloud_source(
2137    ctx: Context,
2138    source_id: Annotated[
2139        str,
2140        Field(description="The ID of the deployed source to delete."),
2141    ],
2142    name: Annotated[
2143        str,
2144        Field(description="The expected name of the source (for verification)."),
2145    ],
2146) -> str:
2147    """Permanently delete a deployed source connector from Airbyte Cloud.
2148
2149    IMPORTANT: This operation requires the source name to contain "delete-me" or "deleteme"
2150    (case insensitive).
2151
2152    If the source does not meet this requirement, the deletion will be rejected with a
2153    helpful error message. Instruct the user to rename the source appropriately to authorize
2154    the deletion.
2155
2156    The provided name must match the actual name of the source for the operation to proceed.
2157    This is a safety measure to ensure you are deleting the correct resource.
2158    """
2159    check_guid_created_in_session(source_id)
2160    workspace: CloudWorkspace = _get_cloud_workspace(ctx)
2161    source = workspace.get_source(source_id=source_id)
2162    actual_name: str = cast(str, source.name)
2163
2164    # Verify the name matches
2165    if actual_name != name:
2166        raise PyAirbyteInputError(
2167            message=(
2168                f"Name mismatch: expected '{name}' but found '{actual_name}'. "
2169                "The provided name must exactly match the source's actual name. "
2170                "This is a safety measure to prevent accidental deletion."
2171            ),
2172            context={
2173                "source_id": source_id,
2174                "expected_name": name,
2175                "actual_name": actual_name,
2176            },
2177        )
2178
2179    # Safe mode is hard-coded to True for extra protection when running in LLM agents
2180    workspace.permanently_delete_source(
2181        source=source_id,
2182        safe_mode=True,  # Requires name to contain "delete-me" or "deleteme" (case insensitive)
2183    )
2184    return f"Successfully deleted source '{actual_name}' (ID: {source_id})"
2185
2186
2187@mcp_tool(
2188    destructive=True,
2189    open_world=True,
2190    extra_help_text=CLOUD_AUTH_TIP_TEXT,
2191)
2192def permanently_delete_cloud_destination(
2193    ctx: Context,
2194    destination_id: Annotated[
2195        str,
2196        Field(description="The ID of the deployed destination to delete."),
2197    ],
2198    name: Annotated[
2199        str,
2200        Field(description="The expected name of the destination (for verification)."),
2201    ],
2202) -> str:
2203    """Permanently delete a deployed destination connector from Airbyte Cloud.
2204
2205    IMPORTANT: This operation requires the destination name to contain "delete-me" or "deleteme"
2206    (case insensitive).
2207
2208    If the destination does not meet this requirement, the deletion will be rejected with a
2209    helpful error message. Instruct the user to rename the destination appropriately to authorize
2210    the deletion.
2211
2212    The provided name must match the actual name of the destination for the operation to proceed.
2213    This is a safety measure to ensure you are deleting the correct resource.
2214    """
2215    check_guid_created_in_session(destination_id)
2216    workspace: CloudWorkspace = _get_cloud_workspace(ctx)
2217    destination = workspace.get_destination(destination_id=destination_id)
2218    actual_name: str = cast(str, destination.name)
2219
2220    # Verify the name matches
2221    if actual_name != name:
2222        raise PyAirbyteInputError(
2223            message=(
2224                f"Name mismatch: expected '{name}' but found '{actual_name}'. "
2225                "The provided name must exactly match the destination's actual name. "
2226                "This is a safety measure to prevent accidental deletion."
2227            ),
2228            context={
2229                "destination_id": destination_id,
2230                "expected_name": name,
2231                "actual_name": actual_name,
2232            },
2233        )
2234
2235    # Safe mode is hard-coded to True for extra protection when running in LLM agents
2236    workspace.permanently_delete_destination(
2237        destination=destination_id,
2238        safe_mode=True,  # Requires name-based delete disposition ("delete-me" or "deleteme")
2239    )
2240    return f"Successfully deleted destination '{actual_name}' (ID: {destination_id})"
2241
2242
2243@mcp_tool(
2244    destructive=True,
2245    open_world=True,
2246    extra_help_text=CLOUD_AUTH_TIP_TEXT,
2247)
2248def permanently_delete_cloud_connection(
2249    ctx: Context,
2250    connection_id: Annotated[
2251        str,
2252        Field(description="The ID of the connection to delete."),
2253    ],
2254    name: Annotated[
2255        str,
2256        Field(description="The expected name of the connection (for verification)."),
2257    ],
2258    *,
2259    cascade_delete_source: Annotated[
2260        bool,
2261        Field(
2262            description=(
2263                "Whether to also delete the source connector associated with this connection."
2264            ),
2265            default=False,
2266        ),
2267    ] = False,
2268    cascade_delete_destination: Annotated[
2269        bool,
2270        Field(
2271            description=(
2272                "Whether to also delete the destination connector associated with this connection."
2273            ),
2274            default=False,
2275        ),
2276    ] = False,
2277) -> str:
2278    """Permanently delete a connection from Airbyte Cloud.
2279
2280    IMPORTANT: This operation requires the connection name to contain "delete-me" or "deleteme"
2281    (case insensitive).
2282
2283    If the connection does not meet this requirement, the deletion will be rejected with a
2284    helpful error message. Instruct the user to rename the connection appropriately to authorize
2285    the deletion.
2286
2287    The provided name must match the actual name of the connection for the operation to proceed.
2288    This is a safety measure to ensure you are deleting the correct resource.
2289    """
2290    check_guid_created_in_session(connection_id)
2291    workspace: CloudWorkspace = _get_cloud_workspace(ctx)
2292    connection = workspace.get_connection(connection_id=connection_id)
2293    actual_name: str = cast(str, connection.name)
2294
2295    # Verify the name matches
2296    if actual_name != name:
2297        raise PyAirbyteInputError(
2298            message=(
2299                f"Name mismatch: expected '{name}' but found '{actual_name}'. "
2300                "The provided name must exactly match the connection's actual name. "
2301                "This is a safety measure to prevent accidental deletion."
2302            ),
2303            context={
2304                "connection_id": connection_id,
2305                "expected_name": name,
2306                "actual_name": actual_name,
2307            },
2308        )
2309
2310    # Safe mode is hard-coded to True for extra protection when running in LLM agents
2311    workspace.permanently_delete_connection(
2312        safe_mode=True,  # Requires name-based delete disposition ("delete-me" or "deleteme")
2313        connection=connection_id,
2314        cascade_delete_source=cascade_delete_source,
2315        cascade_delete_destination=cascade_delete_destination,
2316    )
2317    return f"Successfully deleted connection '{actual_name}' (ID: {connection_id})"
2318
2319
2320@mcp_tool(
2321    open_world=True,
2322    extra_help_text=CLOUD_AUTH_TIP_TEXT,
2323)
2324def rename_cloud_source(
2325    ctx: Context,
2326    source_id: Annotated[
2327        str,
2328        Field(description="The ID of the deployed source to rename."),
2329    ],
2330    name: Annotated[
2331        str,
2332        Field(description="New name for the source."),
2333    ],
2334    *,
2335    workspace_id: Annotated[
2336        str | None,
2337        Field(
2338            description=WORKSPACE_ID_TIP_TEXT,
2339            default=None,
2340        ),
2341    ],
2342) -> str:
2343    """Rename a deployed source connector on Airbyte Cloud."""
2344    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
2345    source = workspace.get_source(source_id=source_id)
2346    source.rename(name=name)
2347    return f"Successfully renamed source '{source_id}' to '{name}'. URL: {source.connector_url}"
2348
2349
2350@mcp_tool(
2351    destructive=True,
2352    open_world=True,
2353    extra_help_text=CLOUD_AUTH_TIP_TEXT,
2354)
2355def update_cloud_source_config(
2356    ctx: Context,
2357    source_id: Annotated[
2358        str,
2359        Field(description="The ID of the deployed source to update."),
2360    ],
2361    config: Annotated[
2362        dict | str,
2363        Field(
2364            description="New configuration for the source connector.",
2365        ),
2366    ],
2367    config_secret_name: Annotated[
2368        str | None,
2369        Field(
2370            description="The name of the secret containing the configuration.",
2371            default=None,
2372        ),
2373    ] = None,
2374    *,
2375    workspace_id: Annotated[
2376        str | None,
2377        Field(
2378            description=WORKSPACE_ID_TIP_TEXT,
2379            default=None,
2380        ),
2381    ],
2382) -> str:
2383    """Update a deployed source connector's configuration on Airbyte Cloud.
2384
2385    This is a destructive operation that can break existing connections if the
2386    configuration is changed incorrectly. Use with caution.
2387    """
2388    check_guid_created_in_session(source_id)
2389    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
2390    source = workspace.get_source(source_id=source_id)
2391
2392    config_dict = resolve_connector_config(
2393        config=config,
2394        config_secret_name=config_secret_name,
2395        config_spec_jsonschema=None,  # We don't have the spec here
2396    )
2397
2398    source.update_config(config=config_dict)
2399    return f"Successfully updated source '{source_id}'. URL: {source.connector_url}"
2400
2401
2402@mcp_tool(
2403    open_world=True,
2404    extra_help_text=CLOUD_AUTH_TIP_TEXT,
2405)
2406def rename_cloud_destination(
2407    ctx: Context,
2408    destination_id: Annotated[
2409        str,
2410        Field(description="The ID of the deployed destination to rename."),
2411    ],
2412    name: Annotated[
2413        str,
2414        Field(description="New name for the destination."),
2415    ],
2416    *,
2417    workspace_id: Annotated[
2418        str | None,
2419        Field(
2420            description=WORKSPACE_ID_TIP_TEXT,
2421            default=None,
2422        ),
2423    ],
2424) -> str:
2425    """Rename a deployed destination connector on Airbyte Cloud."""
2426    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
2427    destination = workspace.get_destination(destination_id=destination_id)
2428    destination.rename(name=name)
2429    return (
2430        f"Successfully renamed destination '{destination_id}' to '{name}'. "
2431        f"URL: {destination.connector_url}"
2432    )
2433
2434
2435@mcp_tool(
2436    destructive=True,
2437    open_world=True,
2438    extra_help_text=CLOUD_AUTH_TIP_TEXT,
2439)
2440def update_cloud_destination_config(
2441    ctx: Context,
2442    destination_id: Annotated[
2443        str,
2444        Field(description="The ID of the deployed destination to update."),
2445    ],
2446    config: Annotated[
2447        dict | str,
2448        Field(
2449            description="New configuration for the destination connector.",
2450        ),
2451    ],
2452    config_secret_name: Annotated[
2453        str | None,
2454        Field(
2455            description="The name of the secret containing the configuration.",
2456            default=None,
2457        ),
2458    ],
2459    *,
2460    workspace_id: Annotated[
2461        str | None,
2462        Field(
2463            description=WORKSPACE_ID_TIP_TEXT,
2464            default=None,
2465        ),
2466    ],
2467) -> str:
2468    """Update a deployed destination connector's configuration on Airbyte Cloud.
2469
2470    This is a destructive operation that can break existing connections if the
2471    configuration is changed incorrectly. Use with caution.
2472    """
2473    check_guid_created_in_session(destination_id)
2474    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
2475    destination = workspace.get_destination(destination_id=destination_id)
2476
2477    config_dict = resolve_connector_config(
2478        config=config,
2479        config_secret_name=config_secret_name,
2480        config_spec_jsonschema=None,  # We don't have the spec here
2481    )
2482
2483    destination.update_config(config=config_dict)
2484    return (
2485        f"Successfully updated destination '{destination_id}'. " f"URL: {destination.connector_url}"
2486    )
2487
2488
2489@mcp_tool(
2490    open_world=True,
2491    extra_help_text=CLOUD_AUTH_TIP_TEXT,
2492)
2493def rename_cloud_connection(
2494    ctx: Context,
2495    connection_id: Annotated[
2496        str,
2497        Field(description="The ID of the connection to rename."),
2498    ],
2499    name: Annotated[
2500        str,
2501        Field(description="New name for the connection."),
2502    ],
2503    *,
2504    workspace_id: Annotated[
2505        str | None,
2506        Field(
2507            description=WORKSPACE_ID_TIP_TEXT,
2508            default=None,
2509        ),
2510    ],
2511) -> str:
2512    """Rename a connection on Airbyte Cloud."""
2513    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
2514    connection = workspace.get_connection(connection_id=connection_id)
2515    connection.rename(name=name)
2516    return (
2517        f"Successfully renamed connection '{connection_id}' to '{name}'. "
2518        f"URL: {connection.connection_url}"
2519    )
2520
2521
2522@mcp_tool(
2523    destructive=True,
2524    open_world=True,
2525    extra_help_text=CLOUD_AUTH_TIP_TEXT,
2526)
2527def set_cloud_connection_table_prefix(
2528    ctx: Context,
2529    connection_id: Annotated[
2530        str,
2531        Field(description="The ID of the connection to update."),
2532    ],
2533    prefix: Annotated[
2534        str,
2535        Field(description="New table prefix to use when syncing to the destination."),
2536    ],
2537    *,
2538    workspace_id: Annotated[
2539        str | None,
2540        Field(
2541            description=WORKSPACE_ID_TIP_TEXT,
2542            default=None,
2543        ),
2544    ],
2545) -> str:
2546    """Set the table prefix for a connection on Airbyte Cloud.
2547
2548    This is a destructive operation that can break downstream dependencies if the
2549    table prefix is changed incorrectly. Use with caution.
2550    """
2551    check_guid_created_in_session(connection_id)
2552    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
2553    connection = workspace.get_connection(connection_id=connection_id)
2554    connection.set_table_prefix(prefix=prefix)
2555    return (
2556        f"Successfully set table prefix for connection '{connection_id}' to '{prefix}'. "
2557        f"URL: {connection.connection_url}"
2558    )
2559
2560
2561@mcp_tool(
2562    destructive=True,
2563    open_world=True,
2564    extra_help_text=CLOUD_AUTH_TIP_TEXT,
2565)
2566def set_cloud_connection_selected_streams(
2567    ctx: Context,
2568    connection_id: Annotated[
2569        str,
2570        Field(description="The ID of the connection to update."),
2571    ],
2572    stream_names: Annotated[
2573        str | list[str],
2574        Field(
2575            description=(
2576                "The selected stream names to sync within the connection. "
2577                "Must be an explicit stream name or list of streams."
2578            )
2579        ),
2580    ],
2581    *,
2582    workspace_id: Annotated[
2583        str | None,
2584        Field(
2585            description=WORKSPACE_ID_TIP_TEXT,
2586            default=None,
2587        ),
2588    ],
2589) -> str:
2590    """Set the selected streams for a connection on Airbyte Cloud.
2591
2592    This is a destructive operation that can break existing connections if the
2593    stream selection is changed incorrectly. Use with caution.
2594    """
2595    check_guid_created_in_session(connection_id)
2596    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
2597    connection = workspace.get_connection(connection_id=connection_id)
2598
2599    resolved_streams_list: list[str] = resolve_list_of_strings(stream_names)
2600    connection.set_selected_streams(stream_names=resolved_streams_list)
2601
2602    return (
2603        f"Successfully set selected streams for connection '{connection_id}' "
2604        f"to {resolved_streams_list}. URL: {connection.connection_url}"
2605    )
2606
2607
2608@mcp_tool(
2609    open_world=True,
2610    destructive=True,
2611    extra_help_text=CLOUD_AUTH_TIP_TEXT,
2612)
2613def update_cloud_connection(
2614    ctx: Context,
2615    connection_id: Annotated[
2616        str,
2617        Field(description="The ID of the connection to update."),
2618    ],
2619    *,
2620    enabled: Annotated[
2621        bool | None,
2622        Field(
2623            description=(
2624                "Set the connection's enabled status. "
2625                "True enables the connection (status='active'), "
2626                "False disables it (status='inactive'). "
2627                "Leave unset to keep the current status."
2628            ),
2629            default=None,
2630        ),
2631    ],
2632    cron_expression: Annotated[
2633        str | None,
2634        Field(
2635            description=(
2636                "A cron expression defining when syncs should run. "
2637                "Examples: '0 0 * * *' (daily at midnight UTC), "
2638                "'0 */6 * * *' (every 6 hours), "
2639                "'0 0 * * 0' (weekly on Sunday at midnight UTC). "
2640                "Leave unset to keep the current schedule. "
2641                "Cannot be used together with 'manual_schedule'."
2642            ),
2643            default=None,
2644        ),
2645    ],
2646    manual_schedule: Annotated[
2647        bool | None,
2648        Field(
2649            description=(
2650                "Set to True to disable automatic syncs (manual scheduling only). "
2651                "Syncs will only run when manually triggered. "
2652                "Cannot be used together with 'cron_expression'."
2653            ),
2654            default=None,
2655        ),
2656    ],
2657    workspace_id: Annotated[
2658        str | None,
2659        Field(
2660            description=WORKSPACE_ID_TIP_TEXT,
2661            default=None,
2662        ),
2663    ],
2664) -> str:
2665    """Update a connection's settings on Airbyte Cloud.
2666
2667    This tool allows updating multiple connection settings in a single call:
2668    - Enable or disable the connection
2669    - Set a cron schedule for automatic syncs
2670    - Switch to manual scheduling (no automatic syncs)
2671
2672    At least one setting must be provided. The 'cron_expression' and 'manual_schedule'
2673    parameters are mutually exclusive.
2674    """
2675    check_guid_created_in_session(connection_id)
2676
2677    # Validate that at least one setting is provided
2678    if enabled is None and cron_expression is None and manual_schedule is None:
2679        raise ValueError(
2680            "At least one setting must be provided: 'enabled', 'cron_expression', "
2681            "or 'manual_schedule'."
2682        )
2683
2684    # Validate mutually exclusive schedule options
2685    if cron_expression is not None and manual_schedule is True:
2686        raise ValueError(
2687            "Cannot specify both 'cron_expression' and 'manual_schedule=True'. "
2688            "Use 'cron_expression' for scheduled syncs or 'manual_schedule=True' "
2689            "for manual-only syncs."
2690        )
2691
2692    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
2693    connection = workspace.get_connection(connection_id=connection_id)
2694
2695    changes_made: list[str] = []
2696
2697    # Apply enabled status change
2698    if enabled is not None:
2699        connection.set_enabled(enabled=enabled)
2700        status_str = "enabled" if enabled else "disabled"
2701        changes_made.append(f"status set to '{status_str}'")
2702
2703    # Apply schedule change
2704    if cron_expression is not None:
2705        connection.set_schedule(cron_expression=cron_expression)
2706        changes_made.append(f"schedule set to '{cron_expression}'")
2707    elif manual_schedule is True:
2708        connection.set_manual_schedule()
2709        changes_made.append("schedule set to 'manual'")
2710
2711    changes_summary = ", ".join(changes_made)
2712    return (
2713        f"Successfully updated connection '{connection_id}': {changes_summary}. "
2714        f"URL: {connection.connection_url}"
2715    )
2716
2717
2718@mcp_tool(
2719    read_only=True,
2720    idempotent=True,
2721    open_world=True,
2722    extra_help_text=CLOUD_AUTH_TIP_TEXT,
2723)
2724def get_connection_artifact(
2725    ctx: Context,
2726    connection_id: Annotated[
2727        str,
2728        Field(description="The ID of the Airbyte Cloud connection."),
2729    ],
2730    artifact_type: Annotated[
2731        Literal["state", "catalog"],
2732        Field(description="The type of artifact to retrieve: 'state' or 'catalog'."),
2733    ],
2734    *,
2735    workspace_id: Annotated[
2736        str | None,
2737        Field(
2738            description=WORKSPACE_ID_TIP_TEXT,
2739            default=None,
2740        ),
2741    ],
2742) -> dict[str, Any] | list[dict[str, Any]]:
2743    """Get a connection artifact (state or catalog) from Airbyte Cloud.
2744
2745    By default, returns artifacts in Airbyte protocol format (snake_case,
2746    suitable for passing to connector CLI flags like `--state` or `--catalog`).
2747
2748    Retrieves the specified artifact for a connection:
2749    - `state`: Returns a list of protocol-format `AirbyteStateMessage` dicts,
2750      or `{"ERROR": "..."}` if no state is set.
2751    - `catalog`: Returns the protocol-format `ConfiguredAirbyteCatalog` dict,
2752      or `{"ERROR": "..."}` if not found.
2753    """
2754    workspace: CloudWorkspace = _get_cloud_workspace(ctx, workspace_id)
2755    connection = workspace.get_connection(connection_id=connection_id)
2756
2757    if artifact_type == "state":
2758        state = connection.dump_raw_state()
2759        if not state:
2760            return {"ERROR": "No state is set for this connection (stateType: not_set)"}
2761        return state
2762
2763    # artifact_type == "catalog"
2764    catalog = connection.dump_raw_catalog()
2765    if catalog is None:
2766        return {"ERROR": "No catalog found for this connection"}
2767    return catalog
2768
2769
2770def _add_defaults_for_exclude_args(
2771    exclude_args: list[str],
2772) -> None:
2773    """Patch registered tool functions to add Python-level defaults for excluded args.
2774
2775    FastMCP requires that excluded args have Python-level default values, but MCP tool
2776    functions should only use Field(default=...) in their Annotated type hints (not
2777    Python-level `= None`). This function bridges the gap by dynamically adding Python
2778    defaults to the function signatures at registration time, so the source code stays
2779    clean while satisfying FastMCP's requirement.
2780
2781    Args:
2782        exclude_args: List of argument names that will be excluded from the tool schema.
2783    """
2784    import inspect  # noqa: PLC0415  # Local import for optional patching logic
2785
2786    from fastmcp_extensions.decorators import (  # noqa: PLC0415
2787        _REGISTERED_TOOLS,  # noqa: PLC2701
2788    )
2789
2790    for func, _annotations in _REGISTERED_TOOLS:
2791        sig = inspect.signature(func)
2792        needs_patch = any(
2793            arg_name in sig.parameters
2794            and sig.parameters[arg_name].default is inspect.Parameter.empty
2795            for arg_name in exclude_args
2796        )
2797        if needs_patch:
2798            new_params = [
2799                p.replace(default=None)
2800                if name in exclude_args and p.default is inspect.Parameter.empty
2801                else p
2802                for name, p in sig.parameters.items()
2803            ]
2804            func.__signature__ = sig.replace(parameters=new_params)  # type: ignore[attr-defined]
2805
2806
2807def register_cloud_tools(app: FastMCP) -> None:
2808    """Register cloud tools with the FastMCP app.
2809
2810    Args:
2811        app: FastMCP application instance
2812    """
2813    exclude_args = ["workspace_id"] if AIRBYTE_CLOUD_WORKSPACE_ID_IS_SET else None
2814    if exclude_args:
2815        _add_defaults_for_exclude_args(exclude_args)
2816    register_mcp_tools(
2817        app,
2818        mcp_module=__name__,
2819        exclude_args=exclude_args,
2820    )