From e5fa197968858c638b42219c9f3951129ec79d86 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Thu, 9 Jul 2026 15:00:25 -0300 Subject: [PATCH] refactor(mcp): relocate tool result envelope into core core/tool_middleware.short_circuit_error imported tools/tool_error_envelope, a back-edge against the inward-only layering where tools sits above core. The error/success envelope is the shared result currency used both by the tool adapters and by the core middleware, so it belongs at core, not in tools. Move the module to core/tool_error_envelope.py (and its test to tests/core/), repoint every importer, and hoist the previously lazy import in short_circuit_error now that relocating the module removes the load-time cycle that forced it. No behavior change: the module content is untouched. This clears the pipefy_mcp.core -> pipefy_mcp.tools edge so the intra-package layering contract holds. --- .../{tools => core}/tool_error_envelope.py | 0 packages/mcp/src/pipefy_mcp/core/tool_middleware.py | 6 +----- .../mcp/src/pipefy_mcp/tools/ai_automation_tools.py | 2 +- packages/mcp/src/pipefy_mcp/tools/ai_tool_helpers.py | 10 +++++----- .../src/pipefy_mcp/tools/attachment_tool_helpers.py | 2 +- .../src/pipefy_mcp/tools/automation_tool_helpers.py | 2 +- .../mcp/src/pipefy_mcp/tools/automation_tools.py | 2 +- .../src/pipefy_mcp/tools/field_condition_tools.py | 2 +- .../src/pipefy_mcp/tools/graphql_error_helpers.py | 2 +- .../pipefy_mcp/tools/introspection_tool_helpers.py | 2 +- .../mcp/src/pipefy_mcp/tools/member_tool_helpers.py | 2 +- .../pipefy_mcp/tools/observability_tool_helpers.py | 2 +- .../mcp/src/pipefy_mcp/tools/pagination_helpers.py | 2 +- .../src/pipefy_mcp/tools/phase_transition_helpers.py | 2 +- .../src/pipefy_mcp/tools/pipe_config_tool_helpers.py | 2 +- .../mcp/src/pipefy_mcp/tools/pipe_config_tools.py | 10 +++++----- .../mcp/src/pipefy_mcp/tools/pipe_tool_helpers.py | 12 ++++++------ packages/mcp/src/pipefy_mcp/tools/pipe_tools.py | 12 ++++++------ .../mcp/src/pipefy_mcp/tools/portal_tool_helpers.py | 2 +- packages/mcp/src/pipefy_mcp/tools/portal_tools.py | 2 +- .../src/pipefy_mcp/tools/relation_tool_helpers.py | 2 +- .../mcp/src/pipefy_mcp/tools/report_tool_helpers.py | 8 ++++---- packages/mcp/src/pipefy_mcp/tools/report_tools.py | 8 ++++---- .../mcp/src/pipefy_mcp/tools/table_tool_helpers.py | 2 +- packages/mcp/src/pipefy_mcp/tools/table_tools.py | 10 +++++----- .../mcp/src/pipefy_mcp/tools/validation_envelope.py | 2 +- .../mcp/src/pipefy_mcp/tools/validation_helpers.py | 2 +- .../mcp/src/pipefy_mcp/tools/webhook_tool_helpers.py | 2 +- .../{tools => core}/test_tool_error_envelope.py | 2 +- packages/mcp/tests/core/test_tool_middleware.py | 2 +- packages/mcp/tests/tools/test_ai_agent_tools.py | 2 +- packages/mcp/tests/tools/test_ai_automation_tools.py | 2 +- .../mcp/tests/tools/test_attachment_tool_helpers.py | 2 +- packages/mcp/tests/tools/test_attachment_tools.py | 2 +- packages/mcp/tests/tools/test_automation_tools.py | 2 +- .../mcp/tests/tools/test_field_condition_tools.py | 2 +- .../mcp/tests/tools/test_graphql_error_enrichment.py | 2 +- .../mcp/tests/tools/test_introspection_scenarios.py | 2 +- packages/mcp/tests/tools/test_introspection_tools.py | 2 +- packages/mcp/tests/tools/test_member_tools.py | 2 +- packages/mcp/tests/tools/test_observability_tools.py | 2 +- packages/mcp/tests/tools/test_organization_tools.py | 2 +- .../mcp/tests/tools/test_phase_transition_helpers.py | 2 +- packages/mcp/tests/tools/test_pipe_config_tools.py | 2 +- packages/mcp/tests/tools/test_pipe_tool_helpers.py | 2 +- packages/mcp/tests/tools/test_pipe_tools.py | 2 +- packages/mcp/tests/tools/test_portal_tools.py | 2 +- packages/mcp/tests/tools/test_relation_tools.py | 2 +- packages/mcp/tests/tools/test_report_tools.py | 2 +- packages/mcp/tests/tools/test_table_tools.py | 2 +- .../mcp/tests/tools/test_tool_success_envelope.py | 2 +- packages/mcp/tests/tools/test_validation_helpers.py | 2 +- packages/mcp/tests/tools/test_webhook_tools.py | 2 +- 53 files changed, 80 insertions(+), 84 deletions(-) rename packages/mcp/src/pipefy_mcp/{tools => core}/tool_error_envelope.py (100%) rename packages/mcp/tests/{tools => core}/test_tool_error_envelope.py (92%) diff --git a/packages/mcp/src/pipefy_mcp/tools/tool_error_envelope.py b/packages/mcp/src/pipefy_mcp/core/tool_error_envelope.py similarity index 100% rename from packages/mcp/src/pipefy_mcp/tools/tool_error_envelope.py rename to packages/mcp/src/pipefy_mcp/core/tool_error_envelope.py diff --git a/packages/mcp/src/pipefy_mcp/core/tool_middleware.py b/packages/mcp/src/pipefy_mcp/core/tool_middleware.py index 3ed8c1dc..6599c94f 100644 --- a/packages/mcp/src/pipefy_mcp/core/tool_middleware.py +++ b/packages/mcp/src/pipefy_mcp/core/tool_middleware.py @@ -34,6 +34,7 @@ from mcp.server.lowlevel.server import request_ctx from pipefy_mcp.auth.request_identity import CallerIdentity, caller_identity +from pipefy_mcp.core.tool_error_envelope import tool_error if TYPE_CHECKING: from mcp.server.fastmcp import FastMCP @@ -201,11 +202,6 @@ def short_circuit_error( (where an in-tool error carries it too) and in ``structuredContent``. The match to an in-tool error is on the decoded envelope, not the byte serialization. """ - # Imported lazily: pipefy_mcp.tools.tool_error_envelope pulls the tools - # package, which imports the runtime, which imports this module. A top-level - # import would form a cycle at load time. - from pipefy_mcp.tools.tool_error_envelope import tool_error - envelope = tool_error(message, code=code, details=details) return types.ServerResult( types.CallToolResult( diff --git a/packages/mcp/src/pipefy_mcp/tools/ai_automation_tools.py b/packages/mcp/src/pipefy_mcp/tools/ai_automation_tools.py index da9ba34f..7c0a77f3 100644 --- a/packages/mcp/src/pipefy_mcp/tools/ai_automation_tools.py +++ b/packages/mcp/src/pipefy_mcp/tools/ai_automation_tools.py @@ -16,6 +16,7 @@ ) from pydantic import ValidationError +from pipefy_mcp.core.tool_error_envelope import tool_error_message from pipefy_mcp.tools.ai_tool_helpers import ( build_ai_tool_error, build_create_automation_success, @@ -29,7 +30,6 @@ ) from pipefy_mcp.tools.destructive_tool_guard import check_destructive_confirmation from pipefy_mcp.tools.tool_context import get_pipefy_client -from pipefy_mcp.tools.tool_error_envelope import tool_error_message from pipefy_mcp.tools.validation_helpers import ( validate_optional_tool_id, validate_tool_id, diff --git a/packages/mcp/src/pipefy_mcp/tools/ai_tool_helpers.py b/packages/mcp/src/pipefy_mcp/tools/ai_tool_helpers.py index a4d12602..cd2012e9 100644 --- a/packages/mcp/src/pipefy_mcp/tools/ai_tool_helpers.py +++ b/packages/mcp/src/pipefy_mcp/tools/ai_tool_helpers.py @@ -19,16 +19,16 @@ ) from typing_extensions import TypedDict -from pipefy_mcp.tools.graphql_error_helpers import ( - extract_error_strings, - strip_internal_api_diagnostic_markers, -) -from pipefy_mcp.tools.tool_error_envelope import ( +from pipefy_mcp.core.tool_error_envelope import ( ToolErrorDetail, is_unified_envelope_enabled, tool_error, tool_success, ) +from pipefy_mcp.tools.graphql_error_helpers import ( + extract_error_strings, + strip_internal_api_diagnostic_markers, +) logger = logging.getLogger(__name__) diff --git a/packages/mcp/src/pipefy_mcp/tools/attachment_tool_helpers.py b/packages/mcp/src/pipefy_mcp/tools/attachment_tool_helpers.py index 4e7b1891..e2073dd5 100644 --- a/packages/mcp/src/pipefy_mcp/tools/attachment_tool_helpers.py +++ b/packages/mcp/src/pipefy_mcp/tools/attachment_tool_helpers.py @@ -6,8 +6,8 @@ from pydantic import ValidationError +from pipefy_mcp.core.tool_error_envelope import tool_error from pipefy_mcp.tools.graphql_error_helpers import extract_error_strings -from pipefy_mcp.tools.tool_error_envelope import tool_error UploadFlowStep = Literal[ "validation", diff --git a/packages/mcp/src/pipefy_mcp/tools/automation_tool_helpers.py b/packages/mcp/src/pipefy_mcp/tools/automation_tool_helpers.py index 84eef899..abf7df73 100644 --- a/packages/mcp/src/pipefy_mcp/tools/automation_tool_helpers.py +++ b/packages/mcp/src/pipefy_mcp/tools/automation_tool_helpers.py @@ -13,6 +13,7 @@ ) from typing_extensions import TypedDict +from pipefy_mcp.core.tool_error_envelope import ToolErrorDetail, tool_error from pipefy_mcp.tools.graphql_error_helpers import ( extract_error_strings, extract_graphql_correlation_id, @@ -21,7 +22,6 @@ try_enrich_graphql_error, with_debug_suffix, ) -from pipefy_mcp.tools.tool_error_envelope import ToolErrorDetail, tool_error AutomationReadToolData = ( AutomationRuleRecord diff --git a/packages/mcp/src/pipefy_mcp/tools/automation_tools.py b/packages/mcp/src/pipefy_mcp/tools/automation_tools.py index f7a695fc..159ab1d1 100644 --- a/packages/mcp/src/pipefy_mcp/tools/automation_tools.py +++ b/packages/mcp/src/pipefy_mcp/tools/automation_tools.py @@ -11,6 +11,7 @@ from pipefy_sdk.automation_preflight import AutomationPreflightError from pydantic import ValidationError +from pipefy_mcp.core.tool_error_envelope import tool_error_message from pipefy_mcp.tools.automation_tool_helpers import ( build_automation_error_payload, build_automation_mutation_success_payload, @@ -21,7 +22,6 @@ from pipefy_mcp.tools.destructive_tool_guard import check_destructive_confirmation from pipefy_mcp.tools.graphql_error_helpers import enrich_permission_denied_error from pipefy_mcp.tools.tool_context import get_pipefy_client -from pipefy_mcp.tools.tool_error_envelope import tool_error_message from pipefy_mcp.tools.validation_helpers import ( mutation_error_if_not_optional_dict, validate_optional_tool_id, diff --git a/packages/mcp/src/pipefy_mcp/tools/field_condition_tools.py b/packages/mcp/src/pipefy_mcp/tools/field_condition_tools.py index 8084a017..f1c0a98f 100644 --- a/packages/mcp/src/pipefy_mcp/tools/field_condition_tools.py +++ b/packages/mcp/src/pipefy_mcp/tools/field_condition_tools.py @@ -9,6 +9,7 @@ from mcp.types import ToolAnnotations from pipefy_sdk import PipefyId +from pipefy_mcp.core.tool_error_envelope import tool_error from pipefy_mcp.tools.destructive_tool_guard import check_destructive_confirmation from pipefy_mcp.tools.pipe_config_tool_helpers import ( build_field_condition_delete_payload, @@ -18,7 +19,6 @@ handle_pipe_config_tool_graphql_error, ) from pipefy_mcp.tools.tool_context import get_pipefy_client -from pipefy_mcp.tools.tool_error_envelope import tool_error from pipefy_mcp.tools.validation_helpers import ( validate_tool_id, ) diff --git a/packages/mcp/src/pipefy_mcp/tools/graphql_error_helpers.py b/packages/mcp/src/pipefy_mcp/tools/graphql_error_helpers.py index c8ef3b93..8f257d56 100644 --- a/packages/mcp/src/pipefy_mcp/tools/graphql_error_helpers.py +++ b/packages/mcp/src/pipefy_mcp/tools/graphql_error_helpers.py @@ -35,7 +35,7 @@ from pipefy_sdk import PipefyClient import pipefy_mcp.settings as _settings_mod -from pipefy_mcp.tools.tool_error_envelope import tool_error +from pipefy_mcp.core.tool_error_envelope import tool_error # Suffixes appended by the Internal API executor for service-layer diagnostics; # MCP tools strip these from default user-visible errors. diff --git a/packages/mcp/src/pipefy_mcp/tools/introspection_tool_helpers.py b/packages/mcp/src/pipefy_mcp/tools/introspection_tool_helpers.py index 9982acf2..d824ba88 100644 --- a/packages/mcp/src/pipefy_mcp/tools/introspection_tool_helpers.py +++ b/packages/mcp/src/pipefy_mcp/tools/introspection_tool_helpers.py @@ -5,7 +5,7 @@ import json from typing import Any -from pipefy_mcp.tools.tool_error_envelope import tool_error +from pipefy_mcp.core.tool_error_envelope import tool_error def _format_graphql_data_for_llm(data: dict[str, Any]) -> str: diff --git a/packages/mcp/src/pipefy_mcp/tools/member_tool_helpers.py b/packages/mcp/src/pipefy_mcp/tools/member_tool_helpers.py index cf83ee0e..c8e3a4e8 100644 --- a/packages/mcp/src/pipefy_mcp/tools/member_tool_helpers.py +++ b/packages/mcp/src/pipefy_mcp/tools/member_tool_helpers.py @@ -6,10 +6,10 @@ from typing_extensions import TypedDict +from pipefy_mcp.core.tool_error_envelope import tool_error from pipefy_mcp.tools.graphql_error_helpers import ( handle_tool_graphql_error, ) -from pipefy_mcp.tools.tool_error_envelope import tool_error class MemberMutationSuccessPayload(TypedDict): diff --git a/packages/mcp/src/pipefy_mcp/tools/observability_tool_helpers.py b/packages/mcp/src/pipefy_mcp/tools/observability_tool_helpers.py index 35f801f1..6dc48c13 100644 --- a/packages/mcp/src/pipefy_mcp/tools/observability_tool_helpers.py +++ b/packages/mcp/src/pipefy_mcp/tools/observability_tool_helpers.py @@ -6,10 +6,10 @@ from typing_extensions import TypedDict +from pipefy_mcp.core.tool_error_envelope import tool_error from pipefy_mcp.tools.graphql_error_helpers import ( handle_tool_graphql_error, ) -from pipefy_mcp.tools.tool_error_envelope import tool_error class ObservabilityReadSuccessPayload(TypedDict): diff --git a/packages/mcp/src/pipefy_mcp/tools/pagination_helpers.py b/packages/mcp/src/pipefy_mcp/tools/pagination_helpers.py index b781cf2e..60488d25 100644 --- a/packages/mcp/src/pipefy_mcp/tools/pagination_helpers.py +++ b/packages/mcp/src/pipefy_mcp/tools/pagination_helpers.py @@ -6,7 +6,7 @@ from typing_extensions import TypedDict -from pipefy_mcp.tools.tool_error_envelope import tool_error +from pipefy_mcp.core.tool_error_envelope import tool_error __all__ = [ "DEFAULT_PAGE_SIZE", diff --git a/packages/mcp/src/pipefy_mcp/tools/phase_transition_helpers.py b/packages/mcp/src/pipefy_mcp/tools/phase_transition_helpers.py index 5dad8098..00635076 100644 --- a/packages/mcp/src/pipefy_mcp/tools/phase_transition_helpers.py +++ b/packages/mcp/src/pipefy_mcp/tools/phase_transition_helpers.py @@ -11,7 +11,7 @@ format_allowed_destinations_phrase, ) -from pipefy_mcp.tools.tool_error_envelope import tool_error +from pipefy_mcp.core.tool_error_envelope import tool_error logger = logging.getLogger(__name__) diff --git a/packages/mcp/src/pipefy_mcp/tools/pipe_config_tool_helpers.py b/packages/mcp/src/pipefy_mcp/tools/pipe_config_tool_helpers.py index c39af573..c0af7f1b 100644 --- a/packages/mcp/src/pipefy_mcp/tools/pipe_config_tool_helpers.py +++ b/packages/mcp/src/pipefy_mcp/tools/pipe_config_tool_helpers.py @@ -6,10 +6,10 @@ from pipefy_sdk import PipefyClient from typing_extensions import TypedDict +from pipefy_mcp.core.tool_error_envelope import ToolErrorDetail, tool_error from pipefy_mcp.tools.graphql_error_helpers import ( handle_tool_graphql_error, ) -from pipefy_mcp.tools.tool_error_envelope import ToolErrorDetail, tool_error from pipefy_mcp.tools.validation_helpers import UUID_RE, format_json_preview diff --git a/packages/mcp/src/pipefy_mcp/tools/pipe_config_tools.py b/packages/mcp/src/pipefy_mcp/tools/pipe_config_tools.py index 03a5a972..84feabf4 100644 --- a/packages/mcp/src/pipefy_mcp/tools/pipe_config_tools.py +++ b/packages/mcp/src/pipefy_mcp/tools/pipe_config_tools.py @@ -11,6 +11,11 @@ is_get_phase_not_found_error, ) +from pipefy_mcp.core.tool_error_envelope import ( + is_unified_envelope_enabled, + tool_error_message, + tool_success, +) from pipefy_mcp.tools.destructive_tool_guard import check_destructive_confirmation from pipefy_mcp.tools.graphql_error_helpers import ( extract_error_strings, @@ -38,11 +43,6 @@ from pipefy_mcp.tools.pipe_tool_helpers import find_label_dependents from pipefy_mcp.tools.remote_profile import REMOTE from pipefy_mcp.tools.tool_context import get_pipefy_client -from pipefy_mcp.tools.tool_error_envelope import ( - is_unified_envelope_enabled, - tool_error_message, - tool_success, -) from pipefy_mcp.tools.validation_helpers import ( validate_optional_tool_id, validate_tool_id, diff --git a/packages/mcp/src/pipefy_mcp/tools/pipe_tool_helpers.py b/packages/mcp/src/pipefy_mcp/tools/pipe_tool_helpers.py index d51ec8be..483a1465 100644 --- a/packages/mcp/src/pipefy_mcp/tools/pipe_tool_helpers.py +++ b/packages/mcp/src/pipefy_mcp/tools/pipe_tool_helpers.py @@ -14,18 +14,18 @@ from pydantic import ValidationError from typing_extensions import TypedDict -from pipefy_mcp.tools.destructive_tool_guard import ( - DestructiveCancelledPayload, - DestructivePreviewPayload, -) -from pipefy_mcp.tools.graphql_error_helpers import extract_error_strings -from pipefy_mcp.tools.tool_error_envelope import ( +from pipefy_mcp.core.tool_error_envelope import ( ToolErrorDetail, ToolSuccessPayload, is_unified_envelope_enabled, tool_error, tool_success, ) +from pipefy_mcp.tools.destructive_tool_guard import ( + DestructiveCancelledPayload, + DestructivePreviewPayload, +) +from pipefy_mcp.tools.graphql_error_helpers import extract_error_strings class UserCancelledError(Exception): diff --git a/packages/mcp/src/pipefy_mcp/tools/pipe_tools.py b/packages/mcp/src/pipefy_mcp/tools/pipe_tools.py index 5b370410..f8faae49 100644 --- a/packages/mcp/src/pipefy_mcp/tools/pipe_tools.py +++ b/packages/mcp/src/pipefy_mcp/tools/pipe_tools.py @@ -25,6 +25,12 @@ from pipefy_sdk.models.form import MalformedFieldDefinitionError from pydantic import ValidationError +from pipefy_mcp.core.tool_error_envelope import ( + is_unified_envelope_enabled, + tool_error, + tool_error_message, + tool_success, +) from pipefy_mcp.tools.destructive_tool_guard import check_destructive_confirmation from pipefy_mcp.tools.graphql_error_helpers import ( enrich_permission_denied_error, @@ -70,12 +76,6 @@ ) from pipefy_mcp.tools.remote_profile import REMOTE from pipefy_mcp.tools.tool_context import get_pipefy_client -from pipefy_mcp.tools.tool_error_envelope import ( - is_unified_envelope_enabled, - tool_error, - tool_error_message, - tool_success, -) from pipefy_mcp.tools.validation_helpers import validate_tool_id # Key for findCards response; used when reading edges and adding empty message. diff --git a/packages/mcp/src/pipefy_mcp/tools/portal_tool_helpers.py b/packages/mcp/src/pipefy_mcp/tools/portal_tool_helpers.py index 273d6684..2010ea54 100644 --- a/packages/mcp/src/pipefy_mcp/tools/portal_tool_helpers.py +++ b/packages/mcp/src/pipefy_mcp/tools/portal_tool_helpers.py @@ -15,6 +15,7 @@ from pipefy_sdk.exceptions import PortalPermissionError from pydantic import ValidationError +from pipefy_mcp.core.tool_error_envelope import tool_error from pipefy_mcp.tools.graphql_error_helpers import ( extract_error_strings, extract_graphql_error_codes, @@ -24,7 +25,6 @@ build_error_payload, build_success_payload, ) -from pipefy_mcp.tools.tool_error_envelope import tool_error from pipefy_mcp.tools.validation_helpers import validate_tool_id _PORTAL_PERMISSION_GUIDANCE = ( diff --git a/packages/mcp/src/pipefy_mcp/tools/portal_tools.py b/packages/mcp/src/pipefy_mcp/tools/portal_tools.py index 1d4f2ac4..c292b74f 100644 --- a/packages/mcp/src/pipefy_mcp/tools/portal_tools.py +++ b/packages/mcp/src/pipefy_mcp/tools/portal_tools.py @@ -16,6 +16,7 @@ ) from pydantic import ValidationError +from pipefy_mcp.core.tool_error_envelope import tool_error from pipefy_mcp.tools.destructive_tool_guard import check_destructive_confirmation from pipefy_mcp.tools.introspection_tool_helpers import ( build_error_payload, @@ -32,7 +33,6 @@ validate_tool_ids, ) from pipefy_mcp.tools.tool_context import get_pipefy_client -from pipefy_mcp.tools.tool_error_envelope import tool_error from pipefy_mcp.tools.validation_helpers import validate_tool_id diff --git a/packages/mcp/src/pipefy_mcp/tools/relation_tool_helpers.py b/packages/mcp/src/pipefy_mcp/tools/relation_tool_helpers.py index b6f9a5e4..d65169f1 100644 --- a/packages/mcp/src/pipefy_mcp/tools/relation_tool_helpers.py +++ b/packages/mcp/src/pipefy_mcp/tools/relation_tool_helpers.py @@ -6,10 +6,10 @@ from typing_extensions import TypedDict +from pipefy_mcp.core.tool_error_envelope import tool_error from pipefy_mcp.tools.graphql_error_helpers import ( handle_tool_graphql_error, ) -from pipefy_mcp.tools.tool_error_envelope import tool_error class RelationReadSuccessPayload(TypedDict): diff --git a/packages/mcp/src/pipefy_mcp/tools/report_tool_helpers.py b/packages/mcp/src/pipefy_mcp/tools/report_tool_helpers.py index 0e8af65c..78e5bb5c 100644 --- a/packages/mcp/src/pipefy_mcp/tools/report_tool_helpers.py +++ b/packages/mcp/src/pipefy_mcp/tools/report_tool_helpers.py @@ -6,14 +6,14 @@ from typing_extensions import TypedDict -from pipefy_mcp.tools.graphql_error_helpers import ( - handle_tool_graphql_error, -) -from pipefy_mcp.tools.tool_error_envelope import ( +from pipefy_mcp.core.tool_error_envelope import ( is_unified_envelope_enabled, tool_error, tool_success, ) +from pipefy_mcp.tools.graphql_error_helpers import ( + handle_tool_graphql_error, +) # The ``Legacy*SuccessPayload`` TypedDicts below describe the flag=false shape # only. Under the default ``PIPEFY_MCP_UNIFIED_ENVELOPE=true``, helpers return diff --git a/packages/mcp/src/pipefy_mcp/tools/report_tools.py b/packages/mcp/src/pipefy_mcp/tools/report_tools.py index deac48fe..a228f3dc 100644 --- a/packages/mcp/src/pipefy_mcp/tools/report_tools.py +++ b/packages/mcp/src/pipefy_mcp/tools/report_tools.py @@ -9,6 +9,10 @@ from mcp.types import ToolAnnotations from pipefy_sdk import PipefyId +from pipefy_mcp.core.tool_error_envelope import ( + is_unified_envelope_enabled, + tool_success, +) from pipefy_mcp.tools.destructive_tool_guard import check_destructive_confirmation from pipefy_mcp.tools.pagination_helpers import ( build_pagination_info, @@ -21,10 +25,6 @@ handle_report_tool_graphql_error, ) from pipefy_mcp.tools.tool_context import get_pipefy_client -from pipefy_mcp.tools.tool_error_envelope import ( - is_unified_envelope_enabled, - tool_success, -) from pipefy_mcp.tools.validation_helpers import validate_tool_id diff --git a/packages/mcp/src/pipefy_mcp/tools/table_tool_helpers.py b/packages/mcp/src/pipefy_mcp/tools/table_tool_helpers.py index 1623b7e0..e1503d17 100644 --- a/packages/mcp/src/pipefy_mcp/tools/table_tool_helpers.py +++ b/packages/mcp/src/pipefy_mcp/tools/table_tool_helpers.py @@ -6,10 +6,10 @@ from typing_extensions import TypedDict +from pipefy_mcp.core.tool_error_envelope import ToolErrorDetail, tool_error from pipefy_mcp.tools.graphql_error_helpers import ( handle_tool_graphql_error, ) -from pipefy_mcp.tools.tool_error_envelope import ToolErrorDetail, tool_error from pipefy_mcp.tools.validation_helpers import format_json_preview diff --git a/packages/mcp/src/pipefy_mcp/tools/table_tools.py b/packages/mcp/src/pipefy_mcp/tools/table_tools.py index dfae625e..2d1abdd5 100644 --- a/packages/mcp/src/pipefy_mcp/tools/table_tools.py +++ b/packages/mcp/src/pipefy_mcp/tools/table_tools.py @@ -13,6 +13,11 @@ PipefyId, ) +from pipefy_mcp.core.tool_error_envelope import ( + is_unified_envelope_enabled, + tool_error_message, + tool_success, +) from pipefy_mcp.tools.destructive_tool_guard import check_destructive_confirmation from pipefy_mcp.tools.graphql_error_helpers import ( extract_graphql_correlation_id, @@ -36,11 +41,6 @@ map_delete_table_error_to_message, ) from pipefy_mcp.tools.tool_context import get_pipefy_client -from pipefy_mcp.tools.tool_error_envelope import ( - is_unified_envelope_enabled, - tool_error_message, - tool_success, -) from pipefy_mcp.tools.validation_helpers import ( mutation_error_if_not_optional_dict, validate_optional_tool_id, diff --git a/packages/mcp/src/pipefy_mcp/tools/validation_envelope.py b/packages/mcp/src/pipefy_mcp/tools/validation_envelope.py index 01cfb752..1545ee2d 100644 --- a/packages/mcp/src/pipefy_mcp/tools/validation_envelope.py +++ b/packages/mcp/src/pipefy_mcp/tools/validation_envelope.py @@ -27,7 +27,7 @@ from mcp.server.fastmcp.tools.tool_manager import ToolManager from pydantic import ValidationError -from pipefy_mcp.tools.tool_error_envelope import tool_error +from pipefy_mcp.core.tool_error_envelope import tool_error if TYPE_CHECKING: from collections.abc import Callable diff --git a/packages/mcp/src/pipefy_mcp/tools/validation_helpers.py b/packages/mcp/src/pipefy_mcp/tools/validation_helpers.py index 77b6cd8f..cdf351a0 100644 --- a/packages/mcp/src/pipefy_mcp/tools/validation_helpers.py +++ b/packages/mcp/src/pipefy_mcp/tools/validation_helpers.py @@ -6,7 +6,7 @@ import re from typing import Any -from pipefy_mcp.tools.tool_error_envelope import tool_error +from pipefy_mcp.core.tool_error_envelope import tool_error UUID_RE = re.compile( r"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" diff --git a/packages/mcp/src/pipefy_mcp/tools/webhook_tool_helpers.py b/packages/mcp/src/pipefy_mcp/tools/webhook_tool_helpers.py index 9bd70e0c..cca3b938 100644 --- a/packages/mcp/src/pipefy_mcp/tools/webhook_tool_helpers.py +++ b/packages/mcp/src/pipefy_mcp/tools/webhook_tool_helpers.py @@ -6,10 +6,10 @@ from typing_extensions import TypedDict +from pipefy_mcp.core.tool_error_envelope import tool_error from pipefy_mcp.tools.graphql_error_helpers import ( handle_tool_graphql_error, ) -from pipefy_mcp.tools.tool_error_envelope import tool_error class WebhookMutationSuccessPayload(TypedDict): diff --git a/packages/mcp/tests/tools/test_tool_error_envelope.py b/packages/mcp/tests/core/test_tool_error_envelope.py similarity index 92% rename from packages/mcp/tests/tools/test_tool_error_envelope.py rename to packages/mcp/tests/core/test_tool_error_envelope.py index 40268376..ea420f72 100644 --- a/packages/mcp/tests/tools/test_tool_error_envelope.py +++ b/packages/mcp/tests/core/test_tool_error_envelope.py @@ -1,6 +1,6 @@ """Unit tests for canonical tool error helpers.""" -from pipefy_mcp.tools.tool_error_envelope import ( +from pipefy_mcp.core.tool_error_envelope import ( tool_error, tool_error_message, ) diff --git a/packages/mcp/tests/core/test_tool_middleware.py b/packages/mcp/tests/core/test_tool_middleware.py index df691470..85e87c95 100644 --- a/packages/mcp/tests/core/test_tool_middleware.py +++ b/packages/mcp/tests/core/test_tool_middleware.py @@ -17,6 +17,7 @@ from mcp.server.lowlevel.server import request_ctx from mcp.shared.context import RequestContext +from pipefy_mcp.core.tool_error_envelope import tool_error from pipefy_mcp.core.tool_middleware import ( ToolCallContext, compose, @@ -24,7 +25,6 @@ install_tool_call_middleware, short_circuit_error, ) -from pipefy_mcp.tools.tool_error_envelope import tool_error def _app() -> FastMCP: diff --git a/packages/mcp/tests/tools/test_ai_agent_tools.py b/packages/mcp/tests/tools/test_ai_agent_tools.py index 13831440..3d457126 100644 --- a/packages/mcp/tests/tools/test_ai_agent_tools.py +++ b/packages/mcp/tests/tools/test_ai_agent_tools.py @@ -19,8 +19,8 @@ ) from pipefy_sdk.models.ai_agent import UpdateAiAgentInput +from pipefy_mcp.core.tool_error_envelope import tool_error_message from pipefy_mcp.tools.ai_agent_tools import AiAgentTools -from pipefy_mcp.tools.tool_error_envelope import tool_error_message from tools.conftest import ( assert_invalid_arguments_envelope, build_tool_test_server, diff --git a/packages/mcp/tests/tools/test_ai_automation_tools.py b/packages/mcp/tests/tools/test_ai_automation_tools.py index 46e2bff8..8f109f82 100644 --- a/packages/mcp/tests/tools/test_ai_automation_tools.py +++ b/packages/mcp/tests/tools/test_ai_automation_tools.py @@ -10,8 +10,8 @@ ) from pipefy_sdk import PipefyClient +from pipefy_mcp.core.tool_error_envelope import tool_error_message from pipefy_mcp.tools.ai_automation_tools import AiAutomationTools -from pipefy_mcp.tools.tool_error_envelope import tool_error_message from tools.conftest import ( assert_invalid_arguments_envelope, build_tool_test_server, diff --git a/packages/mcp/tests/tools/test_attachment_tool_helpers.py b/packages/mcp/tests/tools/test_attachment_tool_helpers.py index 3d8a4f8d..04c103d9 100644 --- a/packages/mcp/tests/tools/test_attachment_tool_helpers.py +++ b/packages/mcp/tests/tools/test_attachment_tool_helpers.py @@ -5,13 +5,13 @@ from pipefy_sdk.models.attachment import UploadAttachmentToCardInput from pydantic import ValidationError +from pipefy_mcp.core.tool_error_envelope import tool_error from pipefy_mcp.tools.attachment_tool_helpers import ( build_upload_error_payload, build_upload_success_payload, format_s3_upload_failure, map_upload_error_to_message, ) -from pipefy_mcp.tools.tool_error_envelope import tool_error @pytest.mark.unit diff --git a/packages/mcp/tests/tools/test_attachment_tools.py b/packages/mcp/tests/tools/test_attachment_tools.py index 11bec755..628d0c8e 100644 --- a/packages/mcp/tests/tools/test_attachment_tools.py +++ b/packages/mcp/tests/tools/test_attachment_tools.py @@ -18,8 +18,8 @@ ) from pipefy_sdk.models.attachment import infer_content_type +from pipefy_mcp.core.tool_error_envelope import tool_error_message from pipefy_mcp.tools.attachment_tools import AttachmentTools -from pipefy_mcp.tools.tool_error_envelope import tool_error_message from tools.conftest import build_tool_test_server diff --git a/packages/mcp/tests/tools/test_automation_tools.py b/packages/mcp/tests/tools/test_automation_tools.py index 9c613b23..ae3fe0bc 100644 --- a/packages/mcp/tests/tools/test_automation_tools.py +++ b/packages/mcp/tests/tools/test_automation_tools.py @@ -10,8 +10,8 @@ ) from pipefy_sdk import PipefyClient +from pipefy_mcp.core.tool_error_envelope import tool_error_message from pipefy_mcp.tools.automation_tools import AutomationTools -from pipefy_mcp.tools.tool_error_envelope import tool_error_message from tools.conftest import assert_invalid_arguments_envelope, build_tool_test_server diff --git a/packages/mcp/tests/tools/test_field_condition_tools.py b/packages/mcp/tests/tools/test_field_condition_tools.py index 62f27f5a..d95b4ade 100644 --- a/packages/mcp/tests/tools/test_field_condition_tools.py +++ b/packages/mcp/tests/tools/test_field_condition_tools.py @@ -10,8 +10,8 @@ ) from pipefy_sdk import PipefyClient +from pipefy_mcp.core.tool_error_envelope import tool_error_message from pipefy_mcp.tools.field_condition_tools import FieldConditionTools -from pipefy_mcp.tools.tool_error_envelope import tool_error_message from tools.conftest import build_tool_test_server diff --git a/packages/mcp/tests/tools/test_graphql_error_enrichment.py b/packages/mcp/tests/tools/test_graphql_error_enrichment.py index a92b9548..48c140f3 100644 --- a/packages/mcp/tests/tools/test_graphql_error_enrichment.py +++ b/packages/mcp/tests/tools/test_graphql_error_enrichment.py @@ -2,13 +2,13 @@ import pytest +from pipefy_mcp.core.tool_error_envelope import tool_error_message from pipefy_mcp.tools.graphql_error_helpers import ( enrich_ambiguous_access_error, enrich_invalid_arguments_error, enrich_not_found_error, handle_tool_graphql_error, ) -from pipefy_mcp.tools.tool_error_envelope import tool_error_message class _FakeGraphQLError(Exception): diff --git a/packages/mcp/tests/tools/test_introspection_scenarios.py b/packages/mcp/tests/tools/test_introspection_scenarios.py index 1149db93..ec90e3f7 100644 --- a/packages/mcp/tests/tools/test_introspection_scenarios.py +++ b/packages/mcp/tests/tools/test_introspection_scenarios.py @@ -9,8 +9,8 @@ ) from pipefy_sdk import PipefyClient +from pipefy_mcp.core.tool_error_envelope import tool_error_message from pipefy_mcp.tools.introspection_tools import IntrospectionTools -from pipefy_mcp.tools.tool_error_envelope import tool_error_message from tools.conftest import build_tool_test_server diff --git a/packages/mcp/tests/tools/test_introspection_tools.py b/packages/mcp/tests/tools/test_introspection_tools.py index 5fc6799e..77d3d0cd 100644 --- a/packages/mcp/tests/tools/test_introspection_tools.py +++ b/packages/mcp/tests/tools/test_introspection_tools.py @@ -10,8 +10,8 @@ ) from pipefy_sdk import PipefyClient +from pipefy_mcp.core.tool_error_envelope import tool_error_message from pipefy_mcp.tools.introspection_tools import IntrospectionTools -from pipefy_mcp.tools.tool_error_envelope import tool_error_message from tools.conftest import build_tool_test_server diff --git a/packages/mcp/tests/tools/test_member_tools.py b/packages/mcp/tests/tools/test_member_tools.py index cd8f4c48..17b19103 100644 --- a/packages/mcp/tests/tools/test_member_tools.py +++ b/packages/mcp/tests/tools/test_member_tools.py @@ -10,8 +10,8 @@ ) from pipefy_sdk import PipefyClient +from pipefy_mcp.core.tool_error_envelope import tool_error_message from pipefy_mcp.tools.member_tools import MemberTools -from pipefy_mcp.tools.tool_error_envelope import tool_error_message from tools.conftest import build_tool_test_server diff --git a/packages/mcp/tests/tools/test_observability_tools.py b/packages/mcp/tests/tools/test_observability_tools.py index ca1c8ac3..2bcb1923 100644 --- a/packages/mcp/tests/tools/test_observability_tools.py +++ b/packages/mcp/tests/tools/test_observability_tools.py @@ -11,8 +11,8 @@ ) from pipefy_sdk import PipefyClient +from pipefy_mcp.core.tool_error_envelope import tool_error_message from pipefy_mcp.tools.observability_tools import _MAX_PAGE_SIZE, ObservabilityTools -from pipefy_mcp.tools.tool_error_envelope import tool_error_message from tools.conftest import ( assert_invalid_arguments_envelope, build_tool_test_server, diff --git a/packages/mcp/tests/tools/test_organization_tools.py b/packages/mcp/tests/tools/test_organization_tools.py index cd239e6b..0c6faf1a 100644 --- a/packages/mcp/tests/tools/test_organization_tools.py +++ b/packages/mcp/tests/tools/test_organization_tools.py @@ -10,8 +10,8 @@ ) from pipefy_sdk import PipefyClient +from pipefy_mcp.core.tool_error_envelope import tool_error_message from pipefy_mcp.tools.organization_tools import OrganizationTools -from pipefy_mcp.tools.tool_error_envelope import tool_error_message from tools.conftest import build_tool_test_server diff --git a/packages/mcp/tests/tools/test_phase_transition_helpers.py b/packages/mcp/tests/tools/test_phase_transition_helpers.py index 0a2fa955..9f3e5f1b 100644 --- a/packages/mcp/tests/tools/test_phase_transition_helpers.py +++ b/packages/mcp/tests/tools/test_phase_transition_helpers.py @@ -17,10 +17,10 @@ collect_ai_behavior_move_transition_problems, ) +from pipefy_mcp.core.tool_error_envelope import tool_error_message from pipefy_mcp.tools.phase_transition_helpers import ( try_enrich_move_card_to_phase_failure, ) -from pipefy_mcp.tools.tool_error_envelope import tool_error_message @pytest.fixture diff --git a/packages/mcp/tests/tools/test_pipe_config_tools.py b/packages/mcp/tests/tools/test_pipe_config_tools.py index c7cbc432..a89116d1 100644 --- a/packages/mcp/tests/tools/test_pipe_config_tools.py +++ b/packages/mcp/tests/tools/test_pipe_config_tools.py @@ -12,6 +12,7 @@ ) from pipefy_sdk import PipefyClient +from pipefy_mcp.core.tool_error_envelope import tool_error, tool_error_message from pipefy_mcp.tools.field_condition_tools import FieldConditionTools from pipefy_mcp.tools.pipe_config_tool_helpers import ( DeletePipeErrorPayload, @@ -22,7 +23,6 @@ normalize_phase_cards_list, ) from pipefy_mcp.tools.pipe_config_tools import PipeConfigTools -from pipefy_mcp.tools.tool_error_envelope import tool_error, tool_error_message from tools.conftest import assert_invalid_arguments_envelope, build_tool_test_server diff --git a/packages/mcp/tests/tools/test_pipe_tool_helpers.py b/packages/mcp/tests/tools/test_pipe_tool_helpers.py index 8ba82fa5..2a6b3c2a 100644 --- a/packages/mcp/tests/tools/test_pipe_tool_helpers.py +++ b/packages/mcp/tests/tools/test_pipe_tool_helpers.py @@ -11,6 +11,7 @@ from pipefy_sdk import CommentInput from pydantic import ValidationError +from pipefy_mcp.core.tool_error_envelope import tool_error from pipefy_mcp.tools.graphql_error_helpers import ( extract_error_strings, extract_graphql_correlation_id, @@ -31,7 +32,6 @@ map_delete_card_error_to_message, message_for_add_card_comment_validation_error, ) -from pipefy_mcp.tools.tool_error_envelope import tool_error # ============================================================================= # UserCancelledError diff --git a/packages/mcp/tests/tools/test_pipe_tools.py b/packages/mcp/tests/tools/test_pipe_tools.py index f933a915..37728dfe 100644 --- a/packages/mcp/tests/tools/test_pipe_tools.py +++ b/packages/mcp/tests/tools/test_pipe_tools.py @@ -18,13 +18,13 @@ from pipefy_sdk import PipefyClient from pipefy_mcp.core.runtime import McpRuntime, RequestScopedIdentity +from pipefy_mcp.core.tool_error_envelope import tool_error, tool_error_message from pipefy_mcp.settings import settings from pipefy_mcp.tools.pipe_tool_helpers import ( FIND_CARDS_EMPTY_MESSAGE, DeleteCardErrorPayload, ) from pipefy_mcp.tools.pipe_tools import FIND_CARDS_RESPONSE_KEY, PipeTools -from pipefy_mcp.tools.tool_error_envelope import tool_error, tool_error_message from tools.conftest import build_tool_test_server # ============================================================================= diff --git a/packages/mcp/tests/tools/test_portal_tools.py b/packages/mcp/tests/tools/test_portal_tools.py index f26e487d..7bcb9d33 100644 --- a/packages/mcp/tests/tools/test_portal_tools.py +++ b/packages/mcp/tests/tools/test_portal_tools.py @@ -14,8 +14,8 @@ from pipefy_sdk import PipefyClient from pipefy_sdk.exceptions import PortalPermissionError +from pipefy_mcp.core.tool_error_envelope import tool_error_message from pipefy_mcp.tools.portal_tools import PortalTools -from pipefy_mcp.tools.tool_error_envelope import tool_error_message from tools.conftest import assert_invalid_arguments_envelope, build_tool_test_server _PORTAL_LIST_NODE = { diff --git a/packages/mcp/tests/tools/test_relation_tools.py b/packages/mcp/tests/tools/test_relation_tools.py index 38b8151a..ff7f7894 100644 --- a/packages/mcp/tests/tools/test_relation_tools.py +++ b/packages/mcp/tests/tools/test_relation_tools.py @@ -10,8 +10,8 @@ ) from pipefy_sdk import PipefyClient +from pipefy_mcp.core.tool_error_envelope import tool_error_message from pipefy_mcp.tools.relation_tools import RelationTools -from pipefy_mcp.tools.tool_error_envelope import tool_error_message from tools.conftest import assert_invalid_arguments_envelope, build_tool_test_server diff --git a/packages/mcp/tests/tools/test_report_tools.py b/packages/mcp/tests/tools/test_report_tools.py index e26346b5..a0916aa4 100644 --- a/packages/mcp/tests/tools/test_report_tools.py +++ b/packages/mcp/tests/tools/test_report_tools.py @@ -11,8 +11,8 @@ from pipefy_sdk import PipefyClient from pipefy_sdk.report_filter_preflight import EXAMPLE_PHASE_FILTER +from pipefy_mcp.core.tool_error_envelope import tool_error_message from pipefy_mcp.tools.report_tools import ReportTools -from pipefy_mcp.tools.tool_error_envelope import tool_error_message from tools.conftest import assert_invalid_arguments_envelope, build_tool_test_server GOLDEN_REPORT_PHASE_FILTER = { diff --git a/packages/mcp/tests/tools/test_table_tools.py b/packages/mcp/tests/tools/test_table_tools.py index 7f1c07a6..96c411c4 100644 --- a/packages/mcp/tests/tools/test_table_tools.py +++ b/packages/mcp/tests/tools/test_table_tools.py @@ -11,8 +11,8 @@ ) from pipefy_sdk import PipefyClient +from pipefy_mcp.core.tool_error_envelope import tool_error_message from pipefy_mcp.tools.table_tools import TableTools -from pipefy_mcp.tools.tool_error_envelope import tool_error_message from tools.conftest import assert_invalid_arguments_envelope, build_tool_test_server diff --git a/packages/mcp/tests/tools/test_tool_success_envelope.py b/packages/mcp/tests/tools/test_tool_success_envelope.py index c6b96897..26603ebe 100644 --- a/packages/mcp/tests/tools/test_tool_success_envelope.py +++ b/packages/mcp/tests/tools/test_tool_success_envelope.py @@ -1,6 +1,6 @@ """Unit tests for ``tool_success``.""" -from pipefy_mcp.tools.tool_error_envelope import tool_success +from pipefy_mcp.core.tool_error_envelope import tool_success def test_minimal_call_returns_only_success_true(): diff --git a/packages/mcp/tests/tools/test_validation_helpers.py b/packages/mcp/tests/tools/test_validation_helpers.py index c47c429b..3093d928 100644 --- a/packages/mcp/tests/tools/test_validation_helpers.py +++ b/packages/mcp/tests/tools/test_validation_helpers.py @@ -2,7 +2,7 @@ import pytest -from pipefy_mcp.tools.tool_error_envelope import tool_error_message +from pipefy_mcp.core.tool_error_envelope import tool_error_message from pipefy_mcp.tools.validation_helpers import ( format_json_preview, mutation_error_if_not_optional_dict, diff --git a/packages/mcp/tests/tools/test_webhook_tools.py b/packages/mcp/tests/tools/test_webhook_tools.py index 68ac46f9..d4d8582d 100644 --- a/packages/mcp/tests/tools/test_webhook_tools.py +++ b/packages/mcp/tests/tools/test_webhook_tools.py @@ -11,7 +11,7 @@ ) from pipefy_sdk import PipefyClient -from pipefy_mcp.tools.tool_error_envelope import tool_error_message +from pipefy_mcp.core.tool_error_envelope import tool_error_message from pipefy_mcp.tools.webhook_tools import WebhookTools from tools.conftest import assert_invalid_arguments_envelope, build_tool_test_server