Skip to content

Conversation

@devin-ai-integration
Copy link
Contributor

@devin-ai-integration devin-ai-integration bot commented Dec 16, 2025

This PR targets the following PR:


Summary

Enable PyAirbyte MCP tools to authenticate via Authorization header when running over HTTP transport. This allows a single shared MCP server to handle requests from multiple users with different bearer tokens, rather than requiring a subprocess per request.

Changes:

  • Add get_bearer_token_from_headers() utility in airbyte/mcp/_util.py that extracts bearer tokens from HTTP Authorization headers using fastmcp's get_http_headers()
  • Update resolve_cloud_bearer_token() in airbyte/cloud/auth.py to check HTTP headers first before falling back to environment variables
  • Add noqa: SLF001 comments in airbyte/cloud/connectors.py for private member access (lint fixes)
  • Add noqa: PLR0904 comment on CloudWorkspace class (lint fix for too many public methods)

Token resolution order:

  1. Explicit input_value parameter
  2. HTTP Authorization: Bearer <token> header (when running as MCP HTTP server)
  3. AIRBYTE_CLOUD_BEARER_TOKEN environment variable

Review & Testing Checklist for Human

  • Verify import side effects are acceptable: airbyte.cloud.auth now imports from airbyte.mcp._util at module load time, which triggers fastmcp imports. Verify this doesn't break code that imports auth.py but doesn't use MCP.
  • Review resolution order change: The original resolve_cloud_bearer_token() passed input_value as default to try_get_secret(). Now it checks input_value first explicitly and passes default=None to the env var fallback - verify this doesn't break existing callers.
  • Verify HTTP transport works: Start MCP HTTP server, send request with Authorization: Bearer <token> header, verify API calls use that token
  • Verify stdio transport still works: Confirm env var fallback works when not running over HTTP

Recommended test plan:

# Start MCP HTTP server
poetry run poe mcp-serve-http

# Test with bearer token header (in another terminal)
curl -X POST http://127.0.0.1:8000/... \
  -H "Authorization: Bearer <your-token>" \
  -H "Content-Type: application/json" \
  -d '{"tool": "list_workspaces", "args": {}}'

Notes

Updates since last revision

  • Removed unrelated CI type fixes per user request (changes to api_util.py, cloud_ops.py, and .github/ workflow files)
  • PR now contains only spec-related changes and lint fixes (noqa comments)
  • Base PR feat: Add bearer token authentication support #866 is expected to handle any remaining CI type issues

aaronsteers and others added 6 commits December 11, 2025 22:22
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ility (#912)

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Enable PyAirbyte MCP tools to authenticate via Authorization header when
running over HTTP transport. This allows a single shared MCP server to
handle requests from multiple users with different bearer tokens.

Changes:
- Add get_bearer_token_from_headers() utility in airbyte/mcp/_util.py
- Update resolve_cloud_bearer_token() to check HTTP headers first

Resolution order for bearer token:
1. Explicit input_value parameter
2. HTTP Authorization header (when running as MCP HTTP server)
3. AIRBYTE_CLOUD_BEARER_TOKEN environment variable

Co-Authored-By: [email protected] <[email protected]>
@devin-ai-integration
Copy link
Contributor Author

Original prompt from [email protected]
Received message in Slack channel #ask-devin-ai:

@Devin can you stack an PR on the top of <https://github.com/airbytehq/PyAirbyte/pull/866> for the below spec?
```## PyAirbyte MCP: HTTP Header Bearer Token Authentication Spec

### Overview

Enable PyAirbyte MCP tools to authenticate via `Authorization` header when running over HTTP transport, allowing a single shared MCP server to handle requests from multiple users with different bearer tokens.

### Current Behavior

Tools read bearer token from environment variable only:

```python
# airbyte/cloud/auth.py
def resolve_cloud_bearer_token(...) -&gt; SecretString | None:
    return try_get_secret(constants.CLOUD_BEARER_TOKEN_ENV_VAR, default=input_value)

Required Changes

1. Add HTTP header extraction utility

File: airbyte/mcp/_util.py (or new file)

from fastmcp.server.dependencies import get_http_headers

def get_bearer_token_from_headers() -&gt; str | None:
    """Extract bearer token from HTTP Authorization header.
    
    Returns None if not running over HTTP transport or no header present.
    """
    try:
        headers = get_http_headers()
        auth_header = headers.get("authorization", "")
        if auth_header.startswith("Bearer "):
            return auth_header[7:]  # Strip "Bearer " prefix
        return None
    except Exception:
        # Not running over HTTP transport
        return None

2. Update resolve_cloud_bearer_token to check headers first

File: airbyte/cloud/auth.py

def resolve_cloud_bearer_token(
    input_value: str | SecretString | None = None,
    /,
) -&gt; SecretString | None:
    """Get the Airbyte Cloud bearer token.
    
    Resolution order:
    1. Explicit input_value parameter
    2. HTTP Authorization header (when running as MCP HTTP server)
    3. AIRBYTE_CLOUD_BEARER_TOKEN environment variable
    """
    if input_value:
        return SecretString(input_value)
    
    # Try HTTP header first (for MCP HTTP tran... (1427 chars truncated...)

@devin-ai-integration
Copy link
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@github-actions
Copy link

👋 Greetings, Airbyte Team Member!

Here are some helpful tips and reminders for your convenience.

Testing This PyAirbyte Version

You can test this version of PyAirbyte using the following:

# Run PyAirbyte CLI from this branch:
uvx --from 'git+https://github.com/airbytehq/PyAirbyte.git@devin/1765845063-http-header-bearer-token' pyairbyte --help

# Install PyAirbyte from this branch for development:
pip install 'git+https://github.com/airbytehq/PyAirbyte.git@devin/1765845063-http-header-bearer-token'

Helpful Resources

PR Slash Commands

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

  • /fix-pr - Fixes most formatting and linting issues
  • /poetry-lock - Updates poetry.lock file
  • /test-pr - Runs tests with the updated PyAirbyte
  • /prerelease - Builds and publishes a prerelease version to PyPI

Community Support

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

📝 Edit this welcome message.

@github-actions
Copy link

github-actions bot commented Dec 16, 2025

PyTest Results (Fast Tests Only, No Creds)

348 tests  ±0   348 ✅ ±0   5m 48s ⏱️ +10s
  1 suites ±0     0 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit 98d6d26. ± Comparison against base commit 4f05142.

♻️ This comment has been updated with latest results.

- Move fastmcp.server.dependencies.get_http_headers import to top-level in _util.py
- Move airbyte.mcp._util.get_bearer_token_from_headers import to top-level in auth.py
- Remove noqa: PLC0415 comments as inline imports are no longer used

Co-Authored-By: [email protected] <[email protected]>
…th' into devin/1765845063-http-header-bearer-token
@aldogonzalez8 aldogonzalez8 self-assigned this Dec 16, 2025
@aldogonzalez8 aldogonzalez8 marked this pull request as ready for review December 16, 2025 00:50
@aldogonzalez8
Copy link
Contributor

Devin CI is failing


- name: Compute prerelease version
id: version
run: |

Choose a reason for hiding this comment

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

📝 [actionlint] reported by reviewdog 🐶
shellcheck reported issue in this script: SC2086:info:7:39: Double quote to prevent globbing and word splitting [shellcheck]

- uses: hynek/build-and-inspect-python-package@efb823f52190ad02594531168b7a2d5790e66516 # v2.14.0
- name: Prepare version override
id: version
run: |

Choose a reason for hiding this comment

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

📝 [actionlint] reported by reviewdog 🐶
shellcheck reported issue in this script: SC2086:info:1:51: Double quote to prevent globbing and word splitting [shellcheck]

- uses: hynek/build-and-inspect-python-package@efb823f52190ad02594531168b7a2d5790e66516 # v2.14.0
- name: Prepare version override
id: version
run: |

Choose a reason for hiding this comment

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

📝 [actionlint] reported by reviewdog 🐶
shellcheck reported issue in this script: SC2086:info:2:61: Double quote to prevent globbing and word splitting [shellcheck]

@aldogonzalez8 aldogonzalez8 changed the title feat(mcp): Add HTTP header bearer token authentication support (do not merge) feat(mcp): Add HTTP header bearer token authentication support Dec 16, 2025
@github-actions
Copy link

PyTest Results (Full)

416 tests  ±0   391 ✅ ±0   23m 23s ⏱️ + 1m 39s
  1 suites ±0    17 💤 ±0 
  1 files   ±0     8 ❌ ±0 

For more details on these failures, see this check.

Results for commit 98d6d26. ± Comparison against base commit 4f05142.

"""Authentication-related constants and utilities for the Airbyte Cloud."""

from airbyte import constants
from airbyte.mcp._util import get_bearer_token_from_headers
Copy link
Contributor

Choose a reason for hiding this comment

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

Devin, Can you create a follow-on issue to refactor slightly...

Ideally nothing outside the MCP module would import from the MCP module. That said, this is expedient and doesn't seem to create circular dependencies or side effects (that I can see). So I'm inclined to merge and create follow-on issue for refactoring.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Created follow-on issue: #915

The issue proposes moving get_bearer_token_from_headers() to a shared utility location (like airbyte/_util/http_auth.py) so the MCP module can import from it rather than the other way around.

Copy link
Contributor

@aaronsteers aaronsteers left a comment

Choose a reason for hiding this comment

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

Approving with one post-merge update requested: https://github.com/airbytehq/PyAirbyte/pull/914/changes#r2625121278

devin-ai-integration bot added a commit that referenced this pull request Dec 17, 2025
…on support

This commit consolidates authentication handling for Airbyte Cloud API:

- Add CloudCredentials dataclass in airbyte/cloud/credentials.py that
  encapsulates auth configuration (client_id/secret or bearer_token)
- Add bearer token authentication support to api_util functions
- Add resolve_cloud_credentials() in MCP _util.py for multi-source
  credential resolution (explicit params -> HTTP headers -> env vars)
- Add HTTP header extraction helpers for MCP HTTP/SSE transport
- Update CloudWorkspace to support bearer token authentication
- Export CloudCredentials from airbyte.cloud module

This replaces PRs #866, #867, and #914 with a unified implementation.

Co-Authored-By: AJ Steers <[email protected]>
@aaronsteers
Copy link
Contributor

Replaced by #916

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants