Companion to the read-tool remote migrations (#437–#441). Those are mechanical (mark pure reads meta=REMOTE). This issue is the policy decision for the ~100 write tools, which the remote profile deliberately withholds today ("write mutations that haven't been reviewed for remote exposure yet", packages/mcp/CLAUDE.md).
Decision needed
Exposing mutations on a hosted, multi-user server is a security/product posture change, not a marker flip. Before marking any write remote-safe, decide the policy:
- Governance: do remote writes need per-user quotas / rate limiting / cost weighting (the tool-call middleware seam exists) before exposure?
- Destructive ops: how does the two-step
confirm flow behave for a hosted caller, and is that sufficient for deletes?
- Input restriction: which writes need per-call input restriction under the remote profile (via
is_remote_profile(ctx)), like create_ipaas_connection rejecting {"$env": ...} refs?
- Internal-API writes (e.g.
delete_card_relation): any additional review beyond the ordinary per-permission governance?
- Per-deployment vs per-user settings: confirm no write reads a process-global setting for a per-user decision (e.g.
default_webhook_name, allow_insecure_urls on webhook create/update).
Hard-excluded (not candidates, ever)
- Local-filesystem inputs:
upload_attachment_to_card, upload_attachment_to_table_record, create_ai_knowledge_base_document, create_llm_provider, update_llm_provider. (A file_url-style remote variant would be separate follow-up work.)
execute_graphql — arbitrary GraphQL escape hatch.
Scope of the ~100 writes (for staging once policy is set)
Creates, updates, deletes across pipes/cards/phases/fields/tables/records/relations/labels/reports/portals/webhooks/members/automations/AI agents/AI automations/knowledge bases/LLM providers, plus action-style writes (move_card_to_phase, set_role, toggle_ai_agent_status, fill_card_phase_fields, set_table_record_field_value, invite_members, send_*, export_*, publish_*/unpublish_*, clone_pipe, simulate_automation, duplicate_portal_element, sort_portal_pages, the LLM provider owner ops, …).
Acceptance
- A written policy for remote write exposure (governance + input-restriction + destructive-op stance).
- A decision on which categories (if any) to expose, and follow-up migration issues per category, each following the read-migration mechanism (
meta=REMOTE + REMOTE_SEED + the input-restriction call where needed).
Companion to the read-tool remote migrations (#437–#441). Those are mechanical (mark pure reads
meta=REMOTE). This issue is the policy decision for the ~100 write tools, which the remote profile deliberately withholds today ("write mutations that haven't been reviewed for remote exposure yet",packages/mcp/CLAUDE.md).Decision needed
Exposing mutations on a hosted, multi-user server is a security/product posture change, not a marker flip. Before marking any write remote-safe, decide the policy:
confirmflow behave for a hosted caller, and is that sufficient for deletes?is_remote_profile(ctx)), likecreate_ipaas_connectionrejecting{"$env": ...}refs?delete_card_relation): any additional review beyond the ordinary per-permission governance?default_webhook_name,allow_insecure_urlson webhook create/update).Hard-excluded (not candidates, ever)
upload_attachment_to_card,upload_attachment_to_table_record,create_ai_knowledge_base_document,create_llm_provider,update_llm_provider. (Afile_url-style remote variant would be separate follow-up work.)execute_graphql— arbitrary GraphQL escape hatch.Scope of the ~100 writes (for staging once policy is set)
Creates, updates, deletes across pipes/cards/phases/fields/tables/records/relations/labels/reports/portals/webhooks/members/automations/AI agents/AI automations/knowledge bases/LLM providers, plus action-style writes (
move_card_to_phase,set_role,toggle_ai_agent_status,fill_card_phase_fields,set_table_record_field_value,invite_members,send_*,export_*,publish_*/unpublish_*,clone_pipe,simulate_automation,duplicate_portal_element,sort_portal_pages, the LLM provider owner ops, …).Acceptance
meta=REMOTE+REMOTE_SEED+ the input-restriction call where needed).