Repository navigation
fix(mcp): return direct-access enablement link from skill docs and rename tool to get_external_access_skill_docs - #1422
Conversation
Co-Authored-By: AJ Steers <aj@airbyte.io>
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
👋 Greetings, Airbyte Team Member!Here are some helpful tips and reminders for your convenience. 💡 Show Tips and TricksTesting This PyAirbyte VersionYou 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/1792977916-skill-docs-enablement-link' pyairbyte --help
# Install PyAirbyte from this branch for development:
pip install 'git+https://github.com/airbytehq/PyAirbyte.git@devin/1792977916-skill-docs-enablement-link'PR Slash CommandsAirbyte Maintainers can execute the following slash commands on your PR:
📚 Show Repo GuidanceHelpful ResourcesCommunity SupportQuestions? Join the #pyairbyte channel in our Slack workspace. |
Code coverage overviewLanguages: Python Python / code-coverage/pytest-no-creds
View coverage of the 10 most impacted files.
Python / code-coverage/pytest
View coverage of the 10 most impacted files.
Python / code-coverage/pytest-unit
Line coverage data for the release-candidate/v1 branch is not yet available. View coverage of the 10 most covered files.
ℹ️ Calculations represent line coverage. Results may change as calculations are updated. Updated |
There was a problem hiding this comment.
🟡 Changes recommended
The new structured error response exposes credentials embedded in connector labels without redaction.
1 open issue
What changed in this PR
This PR addresses #1421 by making get_agent_skill_docs return a direct-access enablement link, consistent with the external query tools.
Changes:
- Route source skill lookups through connector-level error handling.
- Return structured errors using a shared disabled-access message.
- Add regression coverage for enablement links, successful reads, and preserved exceptions.
| File | Description |
|---|---|
tests/unit_tests/test_mcp_cloud.py |
Tests enablement-link responses and re-raising without a URL. |
tests/unit_tests/test_cloud_guidance.py |
Tests source skill ID delegation. |
tests/unit_tests/test_cloud_direct_execute.py |
Covers disabled access, unrelated errors, API availability, and successful reads. |
tests/unit_tests/test_cloud_describe.py |
Updates assertions to require the enablement URL. |
airbyte/mcp/guidance.py |
Returns structured disabled-access errors from the docs tool. |
airbyte/mcp/cloud.py |
Extracts the shared disabled-access message helper. |
airbyte/mcp/_docs_results.py |
Adds an errors field to skill documentation results. |
airbyte/cloud/workspaces.py |
Delegates source skill IDs to connector documentation reads. |
airbyte/cloud/connectors.py |
Reads source skills directly and translates disabled-access errors. |
Review effort: Balanced
Co-Authored-By: AJ Steers <aj@airbyte.io>
…s_skill_docs Co-Authored-By: AJ Steers <aj@airbyte.io>
get_agent_skill_docsget_external_access_skill_docs
39c7e90
into
release-candidate/v1

Summary
Closes #1421. Requested by AJ Steers (Aaron ("AJ") Steers (@aaronsteers)).
Agents usually call the skill-docs tool before
execute_external_api_query, so it's often where a user first hits disabled direct access. Until now it raised the bareAirbyteExternalAccessNotEnabledError: no link, and guidance aboutenabled_features, a field users can't see. It now returns the same message theexecute_external_*tools return:Breaking for MCP clients: tool rename. The MCP tool
get_agent_skill_docsis nowget_external_access_skill_docs, so its name matches theexecute_external_*tools it documents and theexternal_accesstool category. Arguments (docs_skill_id,connector_id,section,workspace_id) are unchanged. There is no alias, so clients that hard-code the old name break.AgentSkillDocsResult/render_agent_skill_docs_resultbecomeExternalAccessSkillDocsResult/render_external_access_skill_docs_result. The Python API (CloudWorkspace.get_agent_skill_docs,CloudConnector.read_agent_skill_docs) keeps its names.Changes:
CloudConnector.read_agent_skill_docs: sources now readconnector-source:<id>directly. The old path first ran an unscopedinspectprobe of the same skill ID, then raised with no URL. Agents API errors go through_raise_if_feature_not_enabled(..., DIRECT_ACCESS, enablement_url=self._direct_access_enablement_url), the same as_execute_direct_action. A real not-enabled 403/404 therefore raises withenablement_url, plusorganization_enablement_urlwhen known. If access turns out to be enabled, the original error is re-raised. With no Context layer API, it still raises without a URL.CloudWorkspace.get_agent_skill_docs:connector-source:skill IDs now go throughget_source(...).read_agent_skill_docs(...), asconnector-destination:IDs already did. Previously the raw Agents API 403/404 came back as a plainAirbyteCloudApiError.get_external_access_skill_docsMCP tool: catchesAirbyteExternalAccessNotEnabledError.enablement_urlis set, it returnsExternalAccessSkillDocsResult(content="", errors=[...]). The message comes from the new_direct_access_disabled_messagehelper, which is now shared with_direct_access_disabled_result.redact_agent_text, because a returned result skipsAgentErrorTextMiddleware. The enablement URL is not redacted, so it keeps its query string.execute_external_*tools do.ExternalAccessSkillDocsResultgainserrors: list[str].Tests: added unit tests for the not-enabled, enabled-but-forbidden, no-Context-layer and success paths of
read_agent_skill_docs, forconnector-source:delegation, and for the MCP tool returning the link, redacting the label, or re-raising. Targeted unit suites, ruff and pyrefly pass locally. Not yet tested against a live Cloud workspace. Cloud MCP evals need a matching change in cloud-mcp-evals, because two regression scenarios list the old tool name.Link to Devin session: https://app.devin.ai/sessions/674dbb1ce8fc4307bb9b0c4979833f46
Open in Devin Desktop: https://app.devin.ai/desktop/session/674dbb1ce8fc4307bb9b0c4979833f46?variant=devin