Skip to content

feat(mcp)!: replace Cloud MCP session "safe mode" with opt-in STDIO "local demo mode" - #1359

Merged
Aaron ("AJ") Steers (aaronsteers) merged 8 commits into
release-candidate/v1from
devin/1791825520-remove-mcp-safe-mode
Oct 12, 2026
Merged

Aaron ("AJ") Steers (aaronsteers) merged 8 commits into
release-candidate/v1from
devin/1791825520-remove-mcp-safe-mode

Conversation

@aaronsteers

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

Copy link
Copy Markdown
Member

Overview

👉 TL;DR: Cloud MCP no longer blocks agents from changing or deleting resources they didn't create in the current session. That session tracking survives only as an opt-in "local demo mode" for STDIO.

The old default-on AIRBYTE_CLOUD_MCP_SAFE_MODE blocked users from enabling connections and editing streams. It's removed, and setting it, or sending an X-MCP-Safe-Mode header, now hard-fails with guidance on the replacement options. The same tracking is now gated behind AIRBYTE_CLOUD_MCP_LOCAL_DEMO_MODE=1. It's off by default, and the hosted HTTP transport ignores it. The delete-me/deleteme deletion guard and the explicit policy controls are unchanged and always on.

Pairs with airbytehq/airbyte#88481 (hosted advanced-configuration docs):

Changes

  • airbyte/mcp/_tool_utils.py:
    • New local_demo_mode_enabled(), which reads the env var at call time:
      _str_to_bool(os.environ.get(MCP_LOCAL_DEMO_MODE_ENV_VAR)) is True and not is_hosted_mcp_mode()
    • check_guid_created_in_session() raises only when that is true. Registration always happens. Renames stay unguarded, as on base.
    • external_access_allowed() now falls back only on pipeline-change denial:
      -return False if pipeline_changes_allowed(ctx) is False or explicitly_enabled_safe_mode else None
      +return False if pipeline_changes_allowed(ctx) is False else None
    • New legacy-config guards, both raising AirbyteLibInputError (unmasked):
      • check_if_demo_mode_guards() runs at startup in server.main() and http_main.main() and fails if AIRBYTE_CLOUD_MCP_SAFE_MODE is set to any value. Its guidance lists the env-var alternatives, with demo mode last and only for STDIO.
      • check_legacy_safe_mode_header() is called from PolicyGuardMiddleware.on_call_tool and a new on_list_tools, and fails if X-MCP-Safe-Mode is present. Its guidance lists only the header alternatives.
  • airbyte/constants.py:
    • Adds MCP_LOCAL_DEMO_MODE_ENV_VAR (AIRBYTE_CLOUD_MCP_LOCAL_DEMO_MODE).
    • Adds MCP_LEGACY_SAFE_MODE_HEADER (X-MCP-Safe-Mode).
    • Keeps CLOUD_MCP_SAFE_MODE_ENV_VAR, used only by the guard.
  • airbyte/exceptions.py, airbyte/mcp/_error_handling.py: replaces AirbyteSafeModeError with AirbyteLocalDemoModeError (user-facing) and drops the safe-mode sentence from AirbyteExternalAccessDisabledError.guidance.
  • airbyte/mcp/cloud.py: the register/check call sites are unchanged from base.
  • airbyte/mcp/server.py: the instructions now describe the deletion guard in place of safe mode.
  • airbyte/mcp/__init__.py: new short "Local Demo Mode" section. Safe-mode docs are removed here, in docs/CONTRIBUTING.md, and in .github/mcp-ci-tests.mcp.json.
  • Tests:
    • Demo mode is covered for unset, STDIO+on, and hosted+on.
    • The env guard is covered for STDIO and hosted, and the header guard both directly and through the middleware.
    • The schedule, Datadog, and error-masking tests are updated.

Review Spotlight

Reviewers with limited time, please review first:

Risks

  • Behavior change (breaking): by default, agents can now update, enable/disable, and delete existing sources, destinations, connections, and definitions. Deletes still require delete-me/deleteme in the resource name: safe_mode=True on the api_util / CloudWorkspace delete paths is unchanged.
  • Startup hard-fail: any deployment or launcher that still sets AIRBYTE_CLOUD_MCP_SAFE_MODE will refuse to start after upgrading. Known instance: coral-agents scripts/start_mcp_server.py calls setdefault("AIRBYTE_CLOUD_MCP_SAFE_MODE", "1"). The hosted deploy configs in this org don't set it, but live Cloud Run env vars weren't checked.

Follow-ups

  • Remove the AIRBYTE_CLOUD_MCP_SAFE_MODE setdefault from coral-agents scripts/start_mcp_server.py before it picks up this RC.

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

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

Copy link
Copy Markdown
Contributor

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

  • Disable automatic comment, CI, and merge conflict monitoring

@github-actions

Copy link
Copy Markdown

👋 Greetings, Airbyte Team Member!

Here are some helpful tips and reminders for your convenience.

💡 Show Tips and Tricks

Testing This PyAirbyte Version

You can test this version of PyAirbyte using the following:

# Run PyAirbyte CLI from this branch:
uvx --from 'git+https://github.com/airbytehq/PyAirbyte.git@devin/1791825520-remove-mcp-safe-mode' pyairbyte --help

# Install PyAirbyte from this branch for development:
pip install 'git+https://github.com/airbytehq/PyAirbyte.git@devin/1791825520-remove-mcp-safe-mode'

PR Slash Commands

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

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

Helpful Resources

Community Support

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

📝 Edit this welcome message.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Removing a default safety boundary is an intentional breaking behavior change that warrants final human validation despite no concrete implementation defects found.

0 open findings

What changed in this PR

Removes Cloud MCP’s session-based safe mode so agents can modify existing resources, while retaining policy controls and name-based deletion guards.

Changes:

  • Removes safe-mode configuration, GUID tracking, and related errors.
  • Updates external-access defaults, safety guidance, and documentation.
  • Revises tests for the new policy behavior.
File Description
.github/​mcp-ci-tests.mcp.json Removes the safe-mode environment setting.
airbyte/​constants.py Removes the safe-mode constant.
airbyte/​exceptions.py Removes the safe-mode exception and guidance.
airbyte/​mcp/​__init__.py Updates MCP safety documentation.
airbyte/​mcp/​_error_handling.py Removes safe-mode error handling.
airbyte/​mcp/​_tool_utils.py Removes GUID tracking and changes external-access defaults.
airbyte/​mcp/​cloud.py Allows operations on resources from prior sessions.
airbyte/​mcp/​server.py Replaces safe-mode guidance with deletion-guard guidance.
docs/​CONTRIBUTING.md Removes obsolete safe-mode configuration.
tests/​unit_tests/​test_deferred_cloud_credentials.py Updates deferred-deployment error tests.
tests/​unit_tests/​test_mcp_cloud.py Removes session-registration test setup and assertions.
tests/​unit_tests/​test_mcp_connection_schedules.py Removes safe-mode schedule tests.
tests/​unit_tests/​test_mcp_datadog.py Removes safe-mode telemetry coverage.
tests/​unit_tests/​test_mcp_http_main.py Updates hosted instruction assertions.
tests/​unit_tests/​test_mcp_policy_middleware.py Updates policy middleware cases.
tests/​unit_tests/​test_mcp_tool_errors.py Preserves error-masking coverage with a supported error.
tests/​unit_tests/​test_mcp_tool_filters.py Updates external-access filter cases.
tests/​unit_tests/​test_mcp_tool_utils.py Removes GUID-tracking tests.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@github-code-quality

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

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: Python

Python / code-coverage/pytest-no-creds

The overall line coverage in commit 8e5943f in the devin/1791825520-rem... branch is 79%. The line coverage in commit d9f652f in the release-candidate/v1 branch is 65%.

Show a line coverage summary of the most impacted files.
File release-candidate/v1 d9f652f devin/1791825520-rem... 8e5943f +/-
airbyte/mcp/cloud.py 52% 83% +31%
airbyte/_util/api_util.py 36% 68% +32%
airbyte/cloud/connectors.py 34% 75% +41%
airbyte/mcp/_datadog.py 0% 50% +50%
airbyte/mcp/_error_handling.py 0% 89% +89%
airbyte/_direct...ctors/models.py 0% 94% +94%
airbyte/mcp/_telemetry.py 0% 94% +94%
airbyte/mcp/_sso_auth.py 0% 96% +96%
airbyte/cloud/models.py 0% 97% +97%
airbyte/mcp/int...nc_status_ui.py 0% 97% +97%

Python / code-coverage/pytest

The overall line coverage in commit 8e5943f in the devin/1791825520-rem... branch is 81%. The line coverage in commit d9f652f in the release-candidate/v1 branch is 71%.

Show a line coverage summary of the most impacted files.
File release-candidate/v1 d9f652f devin/1791825520-rem... 8e5943f +/-
airbyte/mcp/cloud.py 52% 83% +31%
airbyte/mcp/_datadog.py 0% 50% +50%
airbyte/mcp/_error_handling.py 0% 89% +89%
airbyte/mcp/int..._registry_ui.py 0% 92% +92%
airbyte/mcp/_user_identity.py 0% 93% +93%
airbyte/_direct...ctors/models.py 0% 94% +94%
airbyte/mcp/_telemetry.py 0% 94% +94%
airbyte/mcp/_sso_auth.py 0% 96% +96%
airbyte/cloud/models.py 0% 97% +97%
airbyte/mcp/int...nc_status_ui.py 0% 97% +97%

Python / code-coverage/pytest-unit

The overall line coverage in commit 8e5943f in the devin/1791825520-rem... branch is 75%. Line coverage data for the release-candidate/v1 branch is not yet available.

Show a line coverage summary of the most covered files.
File release-candidate/v1 devin/1791825520-rem... 8e5943f +/-
airbyte/cloud/models.py — 97% —
airbyte/mcp/_sso_auth.py — 96% —
airbyte/_direct...ctors/models.py — 94% —
airbyte/cloud/client.py — 90% —
airbyte/exceptions.py — 89% —
airbyte/mcp/cloud.py — 83% —
airbyte/progress.py — 80% —
airbyte/cloud/connectors.py — 75% —
airbyte/_util/api_util.py — 68% —
airbyte/shared/...ql_processor.py — 68% —

Updated October 12, 2026 18:25 UTC

@devin-ai-integration devin-ai-integration Bot changed the title feat(mcp)!: remove Cloud MCP session safe mode feat(mcp)!: replace Cloud MCP session safe mode with opt-in STDIO local demo mode Oct 12, 2026

This comment was marked as resolved.

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

Copy link
Copy Markdown
Member Author

Please add a config guard. If users explicitly pass safe mode as an input header arg or env var, then hard-fail with a message the explains the new correct options. Only present the options relevant to the env var. For hosted mode (header inputs), give only the viable inputs with no mention of demo mode. for local mode, give the suggested alternatives, followed lastly by the demo mode option (not recommended except for demos).

Co-Authored-By: AJ Steers <aj@airbyte.io>
@aaronsteers
Aaron ("AJ") Steers (aaronsteers) marked this pull request as ready for review October 12, 2026 18:04
@devin-ai-integration

Copy link
Copy Markdown
Contributor

Aaron ("AJ") Steers (@aaronsteers) Added the config guard in a2fbf8c:

  • Env var AIRBYTE_CLOUD_MCP_SAFE_MODE: if it's set to any value, empty or 0 included, check_legacy_safe_mode_env() fails startup in both server.main() and http_main.main().
    • STDIO guidance lists AIRBYTE_CLOUD_MCP_ALLOW_PIPELINE_CHANGES=0, AIRBYTE_CLOUD_MCP_ALLOW_EXTERNAL_ACCESS=0, AIRBYTE_CLOUD_MCP_READONLY_MODE=1 and MCP_NO_DESTRUCTIVE_TOOLS=1, then last AIRBYTE_CLOUD_MCP_LOCAL_DEMO_MODE=1 ("not recommended except for demos").
    • HTTP guidance lists the same env vars without demo mode.
  • Header X-MCP-Safe-Mode: if it's sent with any value, PolicyGuardMiddleware fails both on_list_tools and on_call_tool via check_legacy_safe_mode_header(). The guidance lists only the X-MCP-Allow-Pipeline-Changes / X-MCP-Allow-External-Access / X-MCP-Readonly-Mode / X-MCP-No-Destructive-Tools headers. It never mentions demo mode.

Both raise AirbyteLibInputError, so the client sees the message and guidance unmasked.

Written by Devin

Comment thread airbyte/mcp/server.py Outdated

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

1 flag not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)

Devin Review

Comment thread airbyte/mcp/_policy_middleware.py
Comment thread airbyte/exceptions.py Outdated
Comment thread airbyte/mcp/_tool_utils.py
devin-ai-integration Bot and others added 2 commits October 12, 2026 18:11
Co-Authored-By: AJ Steers <aj@airbyte.io>
Comment thread airbyte/mcp/_tool_utils.py Outdated
Co-Authored-By: AJ Steers <aj@airbyte.io>
@aaronsteers Aaron ("AJ") Steers (aaronsteers) changed the title feat(mcp)!: replace Cloud MCP session safe mode with opt-in STDIO local demo mode feat(mcp)!: replace Cloud MCP session "safe mode" with opt-in STDIO "local demo mode" Oct 12, 2026
@aaronsteers
Aaron ("AJ") Steers (aaronsteers) merged commit aa84fe6 into release-candidate/v1 Oct 12, 2026
29 checks passed
@aaronsteers
Aaron ("AJ") Steers (aaronsteers) deleted the devin/1791825520-remove-mcp-safe-mode branch October 12, 2026 19:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants