diff --git a/packages/mcp/src/pipefy_mcp/tools/ai_agent_tools.py b/packages/mcp/src/pipefy_mcp/tools/ai_agent_tools.py index 5cb183b6..2adf1b95 100644 --- a/packages/mcp/src/pipefy_mcp/tools/ai_agent_tools.py +++ b/packages/mcp/src/pipefy_mcp/tools/ai_agent_tools.py @@ -41,6 +41,7 @@ enrich_permission_denied_error, extract_error_strings, ) +from pipefy_mcp.tools.remote_profile import REMOTE from pipefy_mcp.tools.tool_context import get_pipefy_client VALIDATE_FETCH_TIMEOUT_SECONDS = 30 @@ -481,6 +482,7 @@ async def toggle_ai_agent_status( @mcp.tool( annotations=ToolAnnotations(readOnlyHint=True), + meta=REMOTE, ) async def get_ai_agent(ctx: Context, uuid: str) -> dict: """Get an AI Agent by UUID with full behavior configuration. @@ -513,6 +515,7 @@ async def get_ai_agent(ctx: Context, uuid: str) -> dict: @mcp.tool( annotations=ToolAnnotations(readOnlyHint=True), + meta=REMOTE, ) async def get_ai_agents(ctx: Context, repo_uuid: str) -> dict: """List all AI Agents for a pipe. Use before creating an agent to avoid duplicates. @@ -575,6 +578,7 @@ async def delete_ai_agent( @mcp.tool( annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False), + meta=REMOTE, ) async def validate_ai_agent_behaviors( ctx: Context, 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 7c0a77f3..df795ab5 100644 --- a/packages/mcp/src/pipefy_mcp/tools/ai_automation_tools.py +++ b/packages/mcp/src/pipefy_mcp/tools/ai_automation_tools.py @@ -29,6 +29,7 @@ handle_automation_tool_graphql_error, ) from pipefy_mcp.tools.destructive_tool_guard import check_destructive_confirmation +from pipefy_mcp.tools.remote_profile import REMOTE from pipefy_mcp.tools.tool_context import get_pipefy_client from pipefy_mcp.tools.validation_helpers import ( validate_optional_tool_id, @@ -45,6 +46,7 @@ def register(mcp: FastMCP) -> None: @mcp.tool( annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False), + meta=REMOTE, ) async def validate_ai_automation_prompt( ctx: Context, @@ -125,6 +127,7 @@ async def validate_ai_automation_prompt( @mcp.tool( annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False), + meta=REMOTE, ) async def get_ai_automation( ctx: Context, @@ -173,6 +176,7 @@ async def get_ai_automation( @mcp.tool( annotations=ToolAnnotations(readOnlyHint=True, destructiveHint=False), + meta=REMOTE, ) async def get_ai_automations( ctx: Context, diff --git a/packages/mcp/src/pipefy_mcp/tools/llm_provider_tools.py b/packages/mcp/src/pipefy_mcp/tools/llm_provider_tools.py index 695665f2..12debe03 100644 --- a/packages/mcp/src/pipefy_mcp/tools/llm_provider_tools.py +++ b/packages/mcp/src/pipefy_mcp/tools/llm_provider_tools.py @@ -17,6 +17,7 @@ build_pagination_info, validate_page_size, ) +from pipefy_mcp.tools.remote_profile import REMOTE from pipefy_mcp.tools.tool_context import get_pipefy_client from pipefy_mcp.tools.validation_helpers import validate_tool_id @@ -132,7 +133,7 @@ async def get_llm_providers( page_size=nfirst, ) - @mcp.tool(annotations=ToolAnnotations(readOnlyHint=True)) + @mcp.tool(annotations=ToolAnnotations(readOnlyHint=True), meta=REMOTE) async def get_available_ai_models( ctx: Context, provider_name: str, diff --git a/packages/mcp/src/pipefy_mcp/tools/observability_tools.py b/packages/mcp/src/pipefy_mcp/tools/observability_tools.py index 9457de8d..882d9d87 100644 --- a/packages/mcp/src/pipefy_mcp/tools/observability_tools.py +++ b/packages/mcp/src/pipefy_mcp/tools/observability_tools.py @@ -22,6 +22,7 @@ build_observability_read_success_payload, handle_observability_tool_graphql_error, ) +from pipefy_mcp.tools.remote_profile import REMOTE from pipefy_mcp.tools.tool_context import get_pipefy_client from pipefy_mcp.tools.validation_helpers import ( validate_optional_tool_id, @@ -72,6 +73,7 @@ class ObservabilityTools: def register(mcp: FastMCP) -> None: @mcp.tool( annotations=ToolAnnotations(readOnlyHint=True), + meta=REMOTE, ) async def get_ai_agent_logs( repo_uuid: str, @@ -123,6 +125,7 @@ async def get_ai_agent_logs( @mcp.tool( annotations=ToolAnnotations(readOnlyHint=True), + meta=REMOTE, ) async def get_ai_agent_log_details( log_uuid: str, @@ -261,6 +264,7 @@ async def get_automation_logs_by_repo( @mcp.tool( annotations=ToolAnnotations(readOnlyHint=True), + meta=REMOTE, ) async def get_agents_usage( organization_uuid: PipefyId, @@ -369,6 +373,7 @@ async def get_automations_usage( @mcp.tool( annotations=ToolAnnotations(readOnlyHint=True), + meta=REMOTE, ) async def get_ai_credit_usage( organization_uuid: PipefyId, diff --git a/packages/mcp/tests/tools/test_remote_profile.py b/packages/mcp/tests/tools/test_remote_profile.py index 3cbb5a4c..ee593e6a 100644 --- a/packages/mcp/tests/tools/test_remote_profile.py +++ b/packages/mcp/tests/tools/test_remote_profile.py @@ -39,6 +39,20 @@ "introspect_query", "introspect_mutation", "introspect_type", + # AI agent & automation reads (#437): read/validate tools that reach the + # API with the request-scoped bearer and are governed by API permissions; + # no filesystem or per-user process-global settings reads. + "get_ai_agent", + "get_ai_agents", + "get_ai_agent_logs", + "get_ai_agent_log_details", + "get_agents_usage", + "validate_ai_agent_behaviors", + "get_ai_automation", + "get_ai_automations", + "validate_ai_automation_prompt", + "get_ai_credit_usage", + "get_available_ai_models", } )