The Propresenter MCP server exposes tools that can move money, delete data, or destroy resources. Without policy enforcement, an autonomous agent has unrestricted access to every one of them.
Destructive tools (clear_get_group, clear_get_groups, clear_layer) permanently delete resources. There is no undo. An agent calling these in a retry loop causes irreversible damage.
Write operations (messages_create, messages_update, playlists_create) modify state. Without rate limits, an agent can make hundreds of changes in seconds -- faster than any human can review or revert.
Execute tools (announcement_trigger_active, announcement_trigger_cue, announcement_trigger_next) trigger processes with side effects. Builds, notifications, workflows -- all fired without throttling.
These Propresenter tools can modify, create, or destroy resources. Without a policy, your agent has unrestricted access to all of them.
messages_create Create a new message Write messages_update Update an existing message Write playlists_create Create a new playlist Write playlists_create_under Create a new playlist under an existing playlist Write playlists_set Update the contents of a specific playlist Write props_create_collection Create a new prop collection Write props_resume_auto_clear Resume auto-clear for a specific prop Write props_set Update a specific prop Write props_set_collection Update a specific prop collection Write stage_set_layout_map Set the stage layout map configuration Write stage_set_screen_layout Set the layout for a specific stage screen Write themes_set_slide Update a specific slide in a theme Write transport_set_time Set the playback time of the specified layer Write clear_get_group Get details of a specific clear group Destructive clear_get_groups Get a list of all configured clear groups Destructive clear_layer Clear a specific layer (audio, props, messages, announcements, slide, media, video_input) Destructive clear_trigger_group Trigger a specific clear group Destructive messages_clear Clear (hide) a specific message Destructive messages_delete Delete a specific message Destructive props_clear Clear a specific prop from display Destructive props_delete Delete a specific prop Destructive props_delete_collection Delete a specific prop collection Destructive props_pause_auto_clear Pause auto-clear for a specific prop Destructive stage_delete_layout Delete a specific stage layout Destructive timers_operation Perform a specific operation on a timer (start, stop, reset) Destructive timers_reset Reset a specific timer Destructive transport_cancel_auto_advance Cancel auto-advance for presentation or announcement layer Destructive announcement_trigger_active Retrigger the currently active announcement (starts from beginning) Execute announcement_trigger_cue Trigger a specific cue by index in the active announcement Execute announcement_trigger_next Trigger the next cue in the active announcement Execute announcement_trigger_previous Trigger the previous cue in the active announcement Execute audio_trigger_active_next Trigger the next item in the active playlist Execute audio_trigger_active_playlist Trigger the active audio playlist (restart from beginning) Execute audio_trigger_active_previous Trigger the previous item in the active playlist Execute audio_trigger_focused_next Trigger the next item in the focused playlist Execute audio_trigger_focused_playlist Trigger the focused audio playlist Execute audio_trigger_focused_previous Trigger the previous item in the focused playlist Execute audio_trigger_playlist Trigger a specific audio playlist Execute audio_trigger_playlist_item Trigger a specific item in a specific playlist Execute capture_operation Perform a capture operation (start or stop) Execute library_trigger_presentation Trigger the first cue of a presentation in a library Execute library_trigger_presentation_cue Trigger a specific cue of a presentation in a library Execute looks_trigger Trigger a specific audience look to make it live/current Execute macros_trigger Trigger a specific macro Execute messages_trigger Trigger (show) a specific message with optional token values Execute playlists_trigger Trigger a specific playlist Execute playlists_trigger_active_announcement Trigger the active announcement in the playlist Execute playlists_trigger_active_announcement_item Trigger a specific announcement item in the active playlist Execute playlists_trigger_active_presentation Trigger the active presentation in the playlist Execute playlists_trigger_active_presentation_item Trigger a specific presentation item in the active playlist Execute playlists_trigger_focused Trigger the focused playlist item Execute playlists_trigger_focused_item Trigger a specific item in the focused playlist Execute playlists_trigger_focused_next Trigger the next item in the focused playlist Execute playlists_trigger_focused_previous Trigger the previous item in the focused playlist Execute playlists_trigger_item Trigger a specific item in a playlist Execute playlists_trigger_next Trigger the next item in a specific playlist Execute playlists_trigger_previous Trigger the previous item in a specific playlist Execute props_trigger Trigger a specific prop to display Execute timers_start Start a specific timer Execute timers_stop Stop a specific timer Execute trigger_active_group Trigger a specific group in the active presentation Execute trigger_active_presentation Retrigger the currently active presentation (starts from beginning) Execute trigger_focused_cue Trigger a specific cue by index in the focused presentation Execute trigger_focused_group Trigger a specific group in the focused presentation Execute trigger_focused_next Trigger the next cue in the focused presentation Execute trigger_focused_presentation Trigger the currently focused presentation Execute trigger_focused_previous Trigger the previous slide in the focused presentation Execute trigger_next_slide Trigger the next cue in the current presentation Execute trigger_presentation Trigger a specific presentation by UUID, optionally starting at a specific slide index Execute trigger_presentation_cue Trigger a specific cue by index in a presentation by UUID Execute trigger_presentation_group Trigger a specific group in a presentation by UUID Execute trigger_presentation_next Trigger the next cue in a specific presentation by UUID Execute trigger_presentation_previous Trigger the previous cue in a specific presentation by UUID Execute trigger_previous_slide Trigger the previous cue in the current presentation Execute These rules are based on the tool categories exposed by the Propresenter MCP server. Adjust the limits to match your use case.
clear_get_group:
rules:
- action: deny
on_deny: "Destructive operations blocked by policy" Destructive tools should never be available to autonomous agents without human approval.
messages_create:
rules:
- name: "write-rate-limit"
rate_limit: 30/hour
on_deny: "Write rate limit reached" Prevents bulk unintended modifications from agents caught in loops.
announcement_focus_active:
rules:
- action: allow
rate_limit: 60/minute Controls API costs and prevents retry loops from exhausting upstream rate limits.
This is the complete policy file for Propresenter. It lists every tool with suggested default rules. Download it, adjust the limits, and run with Intercept.
version: "1" default: "deny" tools: clear_get_group: rules: - action: deny on_deny: "Destructive operation blocked by policy" clear_get_groups: rules: - action: deny on_deny: "Destructive operation blocked by policy" clear_layer: rules: - action: deny on_deny: "Destructive operation blocked by policy" clear_trigger_group: rules: - action: deny on_deny: "Destructive operation blocked by policy" messages_clear: rules: - action: deny on_deny: "Destructive operation blocked by policy" messages_delete: rules: - action: deny on_deny: "Destructive operation blocked by policy" props_clear: rules: - action: deny on_deny: "Destructive operation blocked by policy" props_delete: rules: - action: deny on_deny: "Destructive operation blocked by policy" props_delete_collection: rules: - action: deny on_deny: "Destructive operation blocked by policy" props_pause_auto_clear: rules: - action: deny on_deny: "Destructive operation blocked by policy" stage_delete_layout: rules: - action: deny on_deny: "Destructive operation blocked by policy" timers_operation: rules: - action: deny on_deny: "Destructive operation blocked by policy" timers_reset: rules: - action: deny on_deny: "Destructive operation blocked by policy" transport_cancel_auto_advance: rules: - action: deny on_deny: "Destructive operation blocked by policy" announcement_trigger_active: rules: - action: allow rate_limit: 10/hour validate: required_args: true announcement_trigger_cue: rules: - action: allow rate_limit: 10/hour validate: required_args: true announcement_trigger_next: rules: - action: allow rate_limit: 10/hour validate: required_args: true announcement_trigger_previous: rules: - action: allow rate_limit: 10/hour validate: required_args: true audio_trigger_active_next: rules: - action: allow rate_limit: 10/hour validate: required_args: true audio_trigger_active_playlist: rules: - action: allow rate_limit: 10/hour validate: required_args: true audio_trigger_active_previous: rules: - action: allow rate_limit: 10/hour validate: required_args: true audio_trigger_focused_next: rules: - action: allow rate_limit: 10/hour validate: required_args: true audio_trigger_focused_playlist: rules: - action: allow rate_limit: 10/hour validate: required_args: true audio_trigger_focused_previous: rules: - action: allow rate_limit: 10/hour validate: required_args: true audio_trigger_playlist: rules: - action: allow rate_limit: 10/hour validate: required_args: true audio_trigger_playlist_item: rules: - action: allow rate_limit: 10/hour validate: required_args: true capture_operation: rules: - action: allow rate_limit: 10/hour validate: required_args: true library_trigger_presentation: rules: - action: allow rate_limit: 10/hour validate: required_args: true library_trigger_presentation_cue: rules: - action: allow rate_limit: 10/hour validate: required_args: true looks_trigger: rules: - action: allow rate_limit: 10/hour validate: required_args: true macros_trigger: rules: - action: allow rate_limit: 10/hour validate: required_args: true messages_trigger: rules: - action: allow rate_limit: 10/hour validate: required_args: true playlists_trigger: rules: - action: allow rate_limit: 10/hour validate: required_args: true playlists_trigger_active_announcement: rules: - action: allow rate_limit: 10/hour validate: required_args: true playlists_trigger_active_announcement_item: rules: - action: allow rate_limit: 10/hour validate: required_args: true playlists_trigger_active_presentation: rules: - action: allow rate_limit: 10/hour validate: required_args: true playlists_trigger_active_presentation_item: rules: - action: allow rate_limit: 10/hour validate: required_args: true playlists_trigger_focused: rules: - action: allow rate_limit: 10/hour validate: required_args: true playlists_trigger_focused_item: rules: - action: allow rate_limit: 10/hour validate: required_args: true playlists_trigger_focused_next: rules: - action: allow rate_limit: 10/hour validate: required_args: true playlists_trigger_focused_previous: rules: - action: allow rate_limit: 10/hour validate: required_args: true playlists_trigger_item: rules: - action: allow rate_limit: 10/hour validate: required_args: true playlists_trigger_next: rules: - action: allow rate_limit: 10/hour validate: required_args: true playlists_trigger_previous: rules: - action: allow rate_limit: 10/hour validate: required_args: true props_trigger: rules: - action: allow rate_limit: 10/hour validate: required_args: true timers_start: rules: - action: allow rate_limit: 10/hour validate: required_args: true timers_stop: rules: - action: allow rate_limit: 10/hour validate: required_args: true trigger_active_group: rules: - action: allow rate_limit: 10/hour validate: required_args: true trigger_active_presentation: rules: - action: allow rate_limit: 10/hour validate: required_args: true trigger_focused_cue: rules: - action: allow rate_limit: 10/hour validate: required_args: true trigger_focused_group: rules: - action: allow rate_limit: 10/hour validate: required_args: true trigger_focused_next: rules: - action: allow rate_limit: 10/hour validate: required_args: true trigger_focused_presentation: rules: - action: allow rate_limit: 10/hour validate: required_args: true trigger_focused_previous: rules: - action: allow rate_limit: 10/hour validate: required_args: true trigger_next_slide: rules: - action: allow rate_limit: 10/hour validate: required_args: true trigger_presentation: rules: - action: allow rate_limit: 10/hour validate: required_args: true trigger_presentation_cue: rules: - action: allow rate_limit: 10/hour validate: required_args: true trigger_presentation_group: rules: - action: allow rate_limit: 10/hour validate: required_args: true trigger_presentation_next: rules: - action: allow rate_limit: 10/hour validate: required_args: true trigger_presentation_previous: rules: - action: allow rate_limit: 10/hour validate: required_args: true trigger_previous_slide: rules: - action: allow rate_limit: 10/hour validate: required_args: true announcement_focus_active: rules: - action: allow rate_limit: 60/minute announcement_get_active: rules: - action: allow rate_limit: 60/minute announcement_get_slide_index: rules: - action: allow rate_limit: 60/minute announcement_get_timeline_status: rules: - action: allow rate_limit: 60/minute announcement_timeline_operation: rules: - action: allow rate_limit: 60/minute audio_focus_active_playlist: rules: - action: allow rate_limit: 60/minute audio_focus_next_playlist: rules: - action: allow rate_limit: 60/minute audio_focus_playlist: rules: - action: allow rate_limit: 60/minute audio_focus_previous_playlist: rules: - action: allow rate_limit: 60/minute audio_get_active_playlist: rules: - action: allow rate_limit: 60/minute audio_get_focused_playlist: rules: - action: allow rate_limit: 60/minute audio_get_playlist: rules: - action: allow rate_limit: 60/minute audio_get_playlist_updates: rules: - action: allow rate_limit: 60/minute audio_get_playlists: rules: - action: allow rate_limit: 60/minute capture_get_encodings: rules: - action: allow rate_limit: 60/minute capture_get_settings: rules: - action: allow rate_limit: 60/minute capture_get_status: rules: - action: allow rate_limit: 60/minute find_my_mouse: rules: - action: allow rate_limit: 60/minute focus_active_presentation: rules: - action: allow rate_limit: 60/minute focus_next_presentation: rules: - action: allow rate_limit: 60/minute focus_presentation: rules: - action: allow rate_limit: 60/minute focus_previous_presentation: rules: - action: allow rate_limit: 60/minute focused_timeline_operation: rules: - action: allow rate_limit: 60/minute get_active_presentation: rules: - action: allow rate_limit: 60/minute get_active_slide_index: rules: - action: allow rate_limit: 60/minute get_chord_chart: rules: - action: allow rate_limit: 60/minute get_chord_chart_updates: rules: - action: allow rate_limit: 60/minute get_focused_presentation: rules: - action: allow rate_limit: 60/minute get_focused_timeline_status: rules: - action: allow rate_limit: 60/minute get_presentation: rules: - action: allow rate_limit: 60/minute get_presentation_thumbnail: rules: - action: allow rate_limit: 60/minute get_propresenter_version: rules: - action: allow rate_limit: 60/minute get_timeline_status: rules: - action: allow rate_limit: 60/minute global_groups_get_all: rules: - action: allow rate_limit: 60/minute library_get: rules: - action: allow rate_limit: 60/minute library_get_libraries: rules: - action: allow rate_limit: 60/minute looks_get: rules: - action: allow rate_limit: 60/minute looks_get_all: rules: - action: allow rate_limit: 60/minute looks_get_current: rules: - action: allow rate_limit: 60/minute macros_get: rules: - action: allow rate_limit: 60/minute macros_get_all: rules: - action: allow rate_limit: 60/minute masks_get: rules: - action: allow rate_limit: 60/minute masks_get_all: rules: - action: allow rate_limit: 60/minute masks_get_thumbnail: rules: - action: allow rate_limit: 60/minute messages_get: rules: - action: allow rate_limit: 60/minute messages_get_all: rules: - action: allow rate_limit: 60/minute playlists_focus: rules: - action: allow rate_limit: 60/minute playlists_focus_active_announcement: rules: - action: allow rate_limit: 60/minute playlists_focus_active_presentation: rules: - action: allow rate_limit: 60/minute playlists_focus_next: rules: - action: allow rate_limit: 60/minute playlists_focus_previous: rules: - action: allow rate_limit: 60/minute playlists_get: rules: - action: allow rate_limit: 60/minute playlists_get_active: rules: - action: allow rate_limit: 60/minute playlists_get_active_announcement_thumbnail: rules: - action: allow rate_limit: 60/minute playlists_get_active_presentation_thumbnail: rules: - action: allow rate_limit: 60/minute playlists_get_all: rules: - action: allow rate_limit: 60/minute playlists_get_focused: rules: - action: allow rate_limit: 60/minute playlists_get_focused_next: rules: - action: allow rate_limit: 60/minute playlists_get_focused_previous: rules: - action: allow rate_limit: 60/minute playlists_get_thumbnail: rules: - action: allow rate_limit: 60/minute playlists_get_updates: rules: - action: allow rate_limit: 60/minute presentation_timeline_operation: rules: - action: allow rate_limit: 60/minute props_get: rules: - action: allow rate_limit: 60/minute props_get_all: rules: - action: allow rate_limit: 60/minute props_get_collection: rules: - action: allow rate_limit: 60/minute props_get_collections: rules: - action: allow rate_limit: 60/minute props_get_thumbnail: rules: - action: allow rate_limit: 60/minute stage_get_layout_map: rules: - action: allow rate_limit: 60/minute stage_get_layout_thumbnail: rules: - action: allow rate_limit: 60/minute stage_get_layouts: rules: - action: allow rate_limit: 60/minute stage_get_message: rules: - action: allow rate_limit: 60/minute stage_get_screen_layout: rules: - action: allow rate_limit: 60/minute stage_get_screens: rules: - action: allow rate_limit: 60/minute stage_hide_message: rules: - action: allow rate_limit: 60/minute stage_show_message: rules: - action: allow rate_limit: 60/minute status_get_audience: rules: - action: allow rate_limit: 60/minute status_get_layers: rules: - action: allow rate_limit: 60/minute status_get_screens: rules: - action: allow rate_limit: 60/minute status_get_slide: rules: - action: allow rate_limit: 60/minute status_get_stage: rules: - action: allow rate_limit: 60/minute status_post_updates: rules: - action: allow rate_limit: 60/minute status_set_audience: rules: - action: allow rate_limit: 60/minute status_set_stage: rules: - action: allow rate_limit: 60/minute themes_get: rules: - action: allow rate_limit: 60/minute themes_get_all: rules: - action: allow rate_limit: 60/minute themes_get_slide: rules: - action: allow rate_limit: 60/minute themes_get_slide_thumbnail: rules: - action: allow rate_limit: 60/minute timeline_operation: rules: - action: allow rate_limit: 60/minute timers_get: rules: - action: allow rate_limit: 60/minute timers_get_all: rules: - action: allow rate_limit: 60/minute timers_get_current: rules: - action: allow rate_limit: 60/minute timers_get_system_time: rules: - action: allow rate_limit: 60/minute timers_get_video_countdown: rules: - action: allow rate_limit: 60/minute timers_increment: rules: - action: allow rate_limit: 60/minute timers_operate_all: rules: - action: allow rate_limit: 60/minute transport_get_auto_advance: rules: - action: allow rate_limit: 60/minute transport_get_current: rules: - action: allow rate_limit: 60/minute transport_get_time: rules: - action: allow rate_limit: 60/minute transport_go_to_end: rules: - action: allow rate_limit: 60/minute transport_pause: rules: - action: allow rate_limit: 60/minute transport_play: rules: - action: allow rate_limit: 60/minute transport_skip_backward: rules: - action: allow rate_limit: 60/minute transport_skip_forward: rules: - action: allow rate_limit: 60/minute messages_create: rules: - action: allow rate_limit: 30/hour messages_update: rules: - action: allow rate_limit: 30/hour playlists_create: rules: - action: allow rate_limit: 30/hour playlists_create_under: rules: - action: allow rate_limit: 30/hour playlists_set: rules: - action: allow rate_limit: 30/hour props_create_collection: rules: - action: allow rate_limit: 30/hour props_resume_auto_clear: rules: - action: allow rate_limit: 30/hour props_set: rules: - action: allow rate_limit: 30/hour props_set_collection: rules: - action: allow rate_limit: 30/hour stage_set_layout_map: rules: - action: allow rate_limit: 30/hour stage_set_screen_layout: rules: - action: allow rate_limit: 30/hour themes_set_slide: rules: - action: allow rate_limit: 30/hour transport_set_time: rules: - action: allow rate_limit: 30/hour
Download the policy
curl -o io-github-alxpark-propresenter-mcp.yaml https://raw.githubusercontent.com/policylayer/intercept/main/policies/io-github-alxpark-propresenter-mcp.yaml
Run Intercept in front of the server
intercept -c io-github-alxpark-propresenter-mcp.yaml -- npx -y @@alxpark/propresenter-mcp
Works with any MCP client:
Every tool call is now checked against your policy before it reaches Propresenter. Denied calls are blocked and logged. Allowed calls pass through with no latency impact.
Open source. One binary. Zero dependencies.
npx -y @policylayer/intercept