PrivacyFence
OfficialServer Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| apps_script_list_projectsA | List standalone Google Apps Script projects visible to the user (id, name, last-modified time). Container-bound scripts attached to a Sheet/Doc/Form are not returned. Returns a list of {id, name, created_time, modified_time}, in Drive's order. Reads up to max_results items across pages. Pass an id as script_id to apps_script_get_content and the other Apps Script tools. Auto-approved. |
| apps_script_get_contentA | Fetch the full source of a Google Apps Script project -- every file (.gs/.html) plus the appsscript.json manifest. Returns {script_id, files}, where files is a list of {name, type, source} and type is 'SERVER_JS', 'HTML' or 'JSON'. Get the script id from apps_script_list_projects, and change the source with apps_script_write_content. Requires user approval. |
| apps_script_write_contentA | Write new source to a Google Apps Script project. Replaces the project's entire file set -- there is no single-file/partial update, so always pass every file the project should have afterward, not just the ones you changed (fetch the current set with apps_script_get_content first if you need to preserve files you aren't touching). This only writes source -- PrivacyFence never runs the script; the user runs it themselves in the Apps Script editor once this write is approved. Returns {script_id, file_count}, the number of files now in the project. Requires user approval. |
| apps_script_get_execution_logA | Read the result of the most recent run(s) of a script that the user triggered themselves outside PrivacyFence (status, duration, which function ran) -- not a live console.log transcript. Returns a list of {function_name, status, start_time, duration, process_type}, where status is for example COMPLETED, FAILED, RUNNING or TIMED_OUT and duration is like '1.234s'. Reads up to max_results items across pages. Get the script id from apps_script_list_projects. Requires user approval. |
| assets_list_schemasA | List the Jira Assets object schemas on the connected Atlassian site. Returns a list of {id, name, key, description, object_count, object_type_count}, at most max_results entries. Use assets_list_object_types to see what a schema contains. Auto-approved. |
| assets_list_object_typesA | List the object types in one Jira Assets schema. Returns a list of {id, name, parent_id, description, object_count}. Use assets_list_schemas to find the schema id, and assets_list_attributes to see the attributes of one type. Auto-approved. |
| assets_list_attributesA | List the attribute definitions of one Jira Assets object type, including which attributes reference other object types. Returns a list of {id, name, kind, value_type, reference_type_id, reference_type_name, reference_kind, min_cardinality, max_cardinality, is_label}; system attributes are left out. Use assets_list_object_types to find the type id, and assets_search_objects to read objects of that type. Auto-approved. |
| assets_search_objectsA | Search Jira Assets objects with an AQL query and return them with their attribute values. Returns a list of {id, key, label, type, type_id, schema_id, created, updated, attributes, references}, at most max_results entries. Use assets_get_object to read one object by id, assets_export_objects to write a large result to a file, and assets_list_attributes to see which attributes a type has. Requires user approval. |
| assets_get_objectA | Read one Jira Assets object with every attribute value and its outbound references. Returns {id, key, label, type, type_id, schema_id, created, updated, attributes, references}. Use assets_search_objects to find the object id, and assets_get_related_objects to follow its links. Requires user approval. |
| assets_get_related_objectsA | Read the Jira Assets objects linked to one object, following references outbound, inbound or both, up to three hops. Returns {root_id, objects, edges: [{from, to, attribute}], truncated}, with depth 1 to 3 and at most 200 objects; truncated true means that limit was hit. Use assets_get_object to read only the object itself. Requires user approval. |
| assets_get_connected_ticketsA | List the Jira tickets connected to one Jira Assets object. Returns {object: {id, key, label, type}, tickets: [{key, summary, status, issue_type, priority}]}. Use assets_get_object to read the object itself. Requires user approval. |
| assets_export_objectsA | Write every Jira Assets object an AQL query matches, up to 10,000, to a CSV or JSON file on the user's computer, in one approval. Columns: id, key, label, type, then every attribute name; a multi-value cell joins its values with "; ". Returns {rows, columns, sha256, path, name, size_bytes, delivery}, never the objects. A query matching no object writes no file and returns rows 0. Use assets_search_objects to read a few objects in the reply. On an organization-managed install nothing is saved to destination_dir: the result carries a one-time download_url instead. Requires user approval. |
| calendar_list_calendarsA | List all Google Calendars for the authenticated user. Returns a list of {id, summary, primary, access_role}. Pass an id as calendar_id to calendar_list_events and the other calendar tools. Auto-approved. |
| calendar_list_eventsA | List events from a calendar (id, title, start_time, end_time, all_day, status). No attendees, description, or links returned. Returns a list of {id, title, start_time, end_time, day_of_week, all_day, status}, recurring events expanded into single occurrences and sorted by start time. Reads up to max_results events across pages. Use calendar_get_event_details to read one event's attendees and description, or calendar_list_calendars to find calendar_id. Auto-approved. |
| calendar_get_free_busyA | Query colleagues' schedules for a time range. For each email, tries to fetch full event details (title, time, status) when the authenticated user has calendar access; falls back to free/busy slots only when access is unavailable. Use this for meeting scheduling. Returns one entry per email: {email, source: 'events', events: [{id, title, start_time, end_time, status, all_day}]} (up to 50 events), or {email, source: 'free_busy', busy: [{start, end}]}, or {email, source: 'error', error}; the user's privacy settings may reduce 'events' to busy slots. Use calendar_list_events instead for the user's own calendar. Auto-approved. |
| calendar_get_event_detailsA | Fetch full details of a calendar event including attendees, description and location. Returns {id, calendar_id, title, description, start_time, end_time, day_of_week, all_day, organizer_email, attendees: [{email, display_name, response_status, organizer}], location, status, html_link}; conferencing links and attachments are not included. Use calendar_list_events instead to find events. Requires user approval. |
| calendar_get_event_visibilityA | Get a calendar event's visibility setting (default, public, private, or confidential) without fetching its full details (attendees, description, etc.) the way calendar_get_event_details does. Returns {visibility}. Use calendar_set_event_visibility to change it. Auto-approved. |
| calendar_set_event_visibilityA | Set a calendar event's visibility. 'default' follows the calendar's own sharing settings; 'public' makes it visible to anyone who can see the calendar; 'private' hides its details from viewers who aren't invited; 'confidential' is a legacy synonym the Calendar API still accepts for 'private'. Only visibility changes — no other fields are affected. Returns {id, title, visibility}. Use calendar_get_event_visibility to read the current value. Requires user approval. |
| calendar_list_roomsA | List meeting rooms and resource calendars from the organization's room directory. This is a locally-cached list IT refreshes with scripts/sync_room_directory.py, not a live Workspace lookup — it may come back empty if IT hasn't synced one yet. Returns a list of {resource_id, resource_name, resource_email, building_id, floor_name, capacity, description}, unpaged. To check whether a room is actually free before booking, call calendar_get_free_busy with its resource_email. Use the room email with calendar_create_event or calendar_update_event to book. Auto-approved. |
| calendar_list_colorsA | List Calendar's fixed event color palette: each color's id, name (e.g. "Tomato", "Sage"), and hex background/foreground. Use a color's id or name as the color argument to calendar_create_event, calendar_update_event, or calendar_set_event_color instead of guessing a numeric id. Returns a list of {id, name, background, foreground}, sorted by id (1-11). Auto-approved. |
| calendar_create_eventA | Create a new calendar event. Returns {id, title, start_time, end_time, html_link}, plus conference_link when a Google Meet was added. Timed events only: all-day events cannot be created. Use calendar_create_out_of_office for time off, calendar_list_rooms to find rooms to book and calendar_list_colors for color ids. Requires user approval. |
| calendar_update_eventA | Update an existing calendar event. For a recurring event, 'scope' controls which occurrences this touches: 'this' (default) affects only the given event_id; 'following' splits the series so this instance and every later one get the changes, leaving earlier ones untouched; 'all' updates the entire series. Only the fields you pass non-empty change; guests cannot be edited here. Returns {id, title, start_time, end_time, html_link}, plus conference_link when the event has a Google Meet. Use calendar_set_event_color or calendar_set_event_visibility to change only the color or visibility. Requires user approval. |
| calendar_delete_eventA | Delete a calendar event. For a recurring event, 'scope' controls what's deleted: 'this' (default) deletes only the given event_id; 'following' ends the series just before this instance, deleting it and every later occurrence but keeping earlier ones; 'all' deletes the entire series. Returns {id, deleted: true, scope}. Use calendar_update_event instead to change an event rather than remove it. Requires user approval. |
| calendar_set_event_colorA | Set a calendar event's color. Only the color changes — no other fields are affected. Accepts a color id (1-11) or name, e.g. "Tomato" -- see calendar_list_colors. Returns {id, title, color_id}. Requires user approval. |
| calendar_create_out_of_officeA | Create an out-of-office event on the primary calendar. Always auto-declines new conflicting meeting invitations that arrive while it's in effect — existing invitations already on the calendar are left alone. Returns {id, title, start_time, end_time, html_link}. Timed events only (not all-day). Use calendar_create_event for an ordinary event. Requires user approval. |
| calendar_set_working_locationA | Set your working-location presence (office or home) for a single day on the primary calendar — the same picker Google Calendar's web UI exposes. Replaces the day's existing working-location entry if there is one. Returns {id, start_time, end_time, html_link}. Use calendar_create_out_of_office for time off. Requires user approval. |
| confluence_list_spacesA | List Confluence spaces the user has access to (key, name, type, description). Returns a list of {key, name, space_type, description, url}, at most max_results (default 50, capped at 1000). Use confluence_list_pages to list the pages in one of them. Auto-approved. |
| confluence_searchA | Full-text search across Confluence content. Returns matching pages/blog posts with excerpts, as a list of {id, title, content_type, space_key, space_name, excerpt, url}, most recently modified first, at most max_results (default 20, capped at 100); excerpts may be redacted by the user's privacy settings. It sends the query as the CQL text ~ "" (no operators); use confluence_cql_search to filter by space, type, label or date. Get the page with confluence_get_page. Auto-approved. |
| confluence_cql_searchA | Search Confluence using CQL (Confluence Query Language). Sends your CQL exactly as written, so it can filter by space, content type, label, creator or date, which confluence_search cannot. Returns a list of {id, title, content_type, space_key, space_name, excerpt, url} in the order your CQL gives (add 'order by lastmodified desc' for newest first), at most max_results (default 20, capped at 100); excerpts may be redacted by the user's privacy settings. Use confluence_search instead for plain keywords. Auto-approved. |
| confluence_list_pagesA | List pages in a Confluence space (title, id, version). Returns a list of {id, title, space_key, space_name, version, author, created, updated, url} without page bodies, at most max_results (default 20, capped at 1000), in the API's order. author is an opaque Atlassian account id; author_name is the resolved name. Use confluence_search instead to find pages by words, and confluence_get_page to read one. Auto-approved. |
| confluence_list_attachmentsA | List attachment names, media types, and sizes for a Confluence page. Auto-approved -- metadata only, no attachment content is returned. Returns {page_id, attachments: a list of {name, media_type, size in bytes}}, at most 500 attachments; names may be redacted by the user's privacy settings. Use confluence_download_attachment to fetch the actual file. |
| confluence_find_usersA | Find Atlassian users by name or email and return their account ids. Returns a list of {account_id, display_name, active, account_type}, at most max_results entries; email addresses are never returned. Auto-approved -- mention someone in a page body by writing @Name. Use confluence_search instead to find pages, not people. |
| confluence_refresh_user_cacheA | Re-fetch the names of every Atlassian account id PrivacyFence has cached. Auto-approved -- use this when a renamed or newly added person shows up wrong; cached names otherwise refresh on their own after 7 days. Returns {cached_users: n}, the number of account ids re-fetched. Use confluence_find_users instead to look up someone by name. |
| confluence_download_attachmentA | Download a Confluence page attachment's content. Identify the attachment by the name returned from confluence_list_attachments. On a local install: saved to destination_dir, which is required (no default): pass ~/Downloads (or a path the user asked for) for a deliverable, or your own scratch directory to just read or process it. On an organization-managed install: destination_dir is ignored -- a small attachment's bytes come back directly in the result, a larger one as a one-time link the human opens in their own browser. Returns {path, name, size_bytes} on a local install, or the inline or link delivery result on an organization-managed one. Requires user approval. |
| confluence_get_pageA | Fetch the full content of a Confluence page by page ID. Returns the page body as HTML storage format, inside one page object {id, title, space_key, space_name, version, author, created, updated, body, url}; author is an opaque Atlassian account id, author_name is the name resolved for it, and mentions maps each @mentioned account id in the body to a name. Use confluence_get_page_by_title when you know the space and title but not the id. Requires user approval. |
| confluence_get_page_by_titleA | Fetch a Confluence page by space key and exact title. Returns one page in the same shape confluence_get_page returns, body included; errors when no page has that title in the space. Use confluence_get_page instead when you already have the page id. Requires user approval. |
| confluence_create_pageA | Create a new Confluence page in the given space. Body is HTML storage format. Returns the created page, with its new id, in the same shape confluence_get_page returns. Use confluence_update_page instead to change a page that already exists. Requires user approval. |
| confluence_update_pageA | Update the title and/or body of an existing Confluence page. Body is HTML storage format. Pass a new title, a new body, or both; an omitted one keeps its current value, so an empty body no longer clears the page. Returns the updated page, with its new version number, in the same shape confluence_get_page returns. Call confluence_get_page first to read the current content. Requires user approval. |
| contacts_listA | List contacts from the user's Google address book. Google blends personally-saved contacts together with Workspace directory profiles (colleagues) by default; use 'source' to split them apart. Returns a list of contacts as {resource_name, display_name, given_name, family_name, emails [{value, type}], phones [{value, type}], organization, job_title, notes, photo_url, source, source_types}, where source is 'personal', 'directory', 'both' (a saved contact who is also a colleague) or 'other', and notes may be redacted by the user's privacy settings. Reads up to max_results contacts across pages; 'source' is applied before counting. Use contacts_search instead to find a contact by name or email. Auto-approved. |
| contacts_searchA | Search contacts by name or email address. The default 'both' searches saved contacts only; only 'directory' scans Workspace directory contacts. Note: 'directory' search only finds directory profiles you already have some contact history with; there is no full company-directory search under this app's permissions. Returns a list of contacts in the same shape contacts_list returns (source is 'personal', 'directory', 'both' or 'other'), at most max_results; notes may be redacted by the user's privacy settings. Use contacts_list instead to browse without a query, and get a contact's full record with contacts_get. Auto-approved. |
| contacts_getA | Fetch a single contact by resource name (e.g. 'people/c12345'). 'source' asserts the expected kind of contact ('personal', 'directory', or 'both'/default); the call fails if the resource doesn't match. Returns one contact in the same shape contacts_list returns; notes may be redacted by the user's privacy settings. Get the resource name from contacts_search or contacts_list. Auto-approved. |
| contacts_updateA | Update a contact's fields. Provide only the fields you want to change. Requires user approval. emails and phones are JSON strings, e.g. '[{"value": "a@b.com", "type": "work"}]'. An empty value leaves that field as it is, except that emails and phones passed as '[]' clear the list. Returns the updated contact in the same shape contacts_get returns. Get the resource name from contacts_search, and read the current values with contacts_get first. |
| contacts_createA | Create a new contact in the user's Google address book. Requires user approval. emails and phones are JSON strings, e.g. '[{"value": "a@b.com", "type": "work"}]'. Contact deletion is not supported. Returns the created contact, with its new resource_name, in the same shape contacts_get returns. Search with contacts_search first to avoid creating a duplicate. |
| contacts_add_labelA | Add a label to a contact, creating the label if it doesn't already exist. Returns {resource_name, label_added}. Labels are matched by name without regard to case. Use contacts_remove_label to take a label off again. Requires user approval. |
| contacts_remove_labelA | Remove a label from a contact. Returns {resource_name, label_removed}, with a note of 'label not found' if no label has that name (nothing changes then). Use contacts_add_label to put a label on a contact. Requires user approval. |
| drive_list_filesA | Search Google Drive and return matching file metadata (id, name, mime_type, owners, sharing status). Returns a list of {id, name, mime_type, size, created_time, modified_time, owners, shared, web_view_link, parent_ids, drive_id, thumbnail_link}: at most max_results files (default 20, capped at 1000), read across pages, in the order the Drive API gives for the query; fields may be redacted by the user's privacy settings. Use drive_list_folder to list one folder's children, or drive_get_file_metadata when you already have a file's id. Auto-approved. |
| drive_get_file_metadataA | Fetch metadata for a single Drive file by id (name, owners, times, sharing status). Returns one file in the same shape drive_list_files lists ({id, name, mime_type, size, created_time, modified_time, owners, shared, web_view_link, parent_ids, drive_id, thumbnail_link}), or only {id} if the user's privacy settings hide file metadata. Use drive_get_file_content to read the file's text. Auto-approved. |
| drive_list_revisionsA | List the saved versions (revision history) of a Drive file by id: when each was saved and by whom. Returns a list of {id, modified_time, author_name, author_email, size, keep_forever, before_cutoff}, newest first: at most max_results (default 50, capped at 1000) plus the before_cutoff entry, read across pages. Google merges a Doc's, Sheet's or Slides' frequent edits into fewer versions, and does not say which cell or paragraph each one changed. If the user's privacy settings hide file metadata, each entry is only {id, before_cutoff}. Use drive_get_revision_content to read one version's text, and drive_get_file_metadata for the file's current details. Auto-approved. |
| drive_list_folderA | List the direct children of a Drive folder by id. Returns a list of files in the same shape drive_list_files returns: at most max_results children (default 50, capped at 1000), read across pages, excluding trashed files, in the order the Drive API gives. Use drive_list_files to search by name or content instead of browsing one folder. Auto-approved. |
| drive_create_blank_fileA | Create a new blank Drive file. Returns {id, name, mime_type} of the new, empty file. Fill it with drive_write_doc_content (a Google Doc), drive_write_file_content (a text file) or drive_upload_file (any file with content); use drive_sheets_create for a spreadsheet. Auto-approved. |
| drive_get_file_contentA | Fetch the content of a Drive file by id. A Google Doc comes back as Markdown (headings, bold, italic, |
| drive_get_revision_contentA | Fetch the content of one earlier saved version of a Drive file, by file id and revision id. A Google Doc or Slides version comes back as plain text (not the Markdown drive_get_file_content gives), a Sheet version as a Markdown table per tab, a PDF, .docx, .pptx or .xlsx version as its extracted text, a .zip as its list of entries, and a text file as its text; other files, such as images, only get a placeholder with their size. Returns {file_id, revision_id, modified_time, content}, plus 'truncated': true when content was cut to fit; content may be redacted by the user's privacy settings. To compare with the current version, read the newest revision from drive_list_revisions with this tool rather than mixing in drive_get_file_content's different format. Requires user approval. |
| drive_write_file_contentA | Write content to an existing Drive file. Replaces the file's whole content with content, written as UTF-8 text. Returns {file_id, modified_time}. Use drive_write_doc_content instead for a formatted Google Doc, or drive_upload_file for a binary file or a new one. Requires user approval. |
| drive_upload_fileA | Upload any file (e.g. a PDF or image) to Drive as a new file — use this instead of drive_write_file_content for any binary file, since that tool only writes UTF-8 text. Provide exactly one of local_path (a path on the user's computer, absolute or starting with ~/), content_base64 (base64-encoded file bytes; 'name' is then required), or upload_id (the id privacyfence_create_upload_slot returned after you PUT the file's bytes to its upload_url — use this if local_path fails because PrivacyFence cannot read files in your home folder). On an organization-managed install, local_path is read from the server, not the user's machine: prefer content_base64 or upload_id there. Returns {id, name, mime_type, size_bytes}. Requires user approval. |
| drive_move_fileA | Move a Drive file to a different folder. The file leaves every folder it is in now. Returns {file_id, new_parent}. Get the destination's id from drive_list_folder. Requires user approval. |
| drive_copy_fileA | Copy a Drive file into a folder. The original stays where it is, unchanged. Returns {id, name, mime_type, web_view_link, source_file_id, parent}, where id is the new copy's id. Folders cannot be copied. Get the destination's id from drive_list_folder. Requires user approval. |
| drive_add_commentA | Add a comment to a Drive file. Returns {file_id, comment_id, content}, where comment_id is the new comment's id. The comment is posted as the user and is not anchored to any text. Requires user approval. |
| drive_list_shared_drivesA | List all Google Workspace Shared Drives the user can access (returns id and name for each). Returns a list of {id, name}: at most max_results drives (default 50, capped at 1000), read across pages. Pass a drive's id as folder_id to drive_list_folder to browse it. Auto-approved. |
| drive_write_doc_contentA | Write Markdown content to a Google Doc with rich formatting: headings (# through ######), bold, italic, bold-italic, |
| drive_docs_edit_contentA | Replace one occurrence of existing text in a Google Doc with new Markdown, without touching the rest of the document. find_text must match exactly one location in the document's plain, unformatted text — the words as typed, with no Markdown syntax in them at all (this is not the same as drive_get_file_content's output for a Doc, which now renders formatting as Markdown; strip any '**'/'#'/etc. markers back out of find_text first) — include enough surrounding context to make it unique, the same way a unique-match text editor requires; set replace_all=true to replace every occurrence instead. replace_markdown supports the same Markdown syntax as drive_write_doc_content, including GFM pipe tables. Returns {file_id, occurrences_replaced}. Use drive_docs_format_content to change formatting without changing the text. Requires user approval. |
| drive_docs_format_contentA | Apply formatting (bold, italic, highlight, text color) to existing text in a Google Doc, located the same way as drive_docs_edit_content, without changing the text itself. Every formatting parameter is opt-in — its default means 'leave that aspect unchanged', so a call that only sets highlight_color never touches bold/italic already on the matched text. Returns {file_id, occurrences_formatted}. Use drive_docs_edit_content to change the text itself. Requires user approval. |
| drive_download_fileA | Download a Drive file. Google Workspace documents are exported as text/CSV. On a local install: saved to destination_dir, and it Returns {path, name, size_bytes, truncated} -- destination_dir is required, there is no default, so choose deliberately: pass ~/Downloads (or a path the user asked for) for a deliverable, or your own scratch directory to just read or process it. On an organization-managed install: destination_dir is ignored -- a small file's bytes come back directly in the result, a larger file as a one-time link the human opens in their own browser. Use drive_get_file_content instead to read a file's text. Requires user approval. |
| drive_sheets_createA | Create a new Google Sheets spreadsheet, optionally with named tabs. Returns {id, name, web_view_link}; id is the spreadsheet_id the other drive_sheets_* tools take. Use drive_sheets_add_sheet to add a tab to a spreadsheet that already exists. Auto-approved. |
| drive_sheets_get_metadataA | List the tabs in a spreadsheet (id, title, index, row/column count). Returns a list of {sheet_id, title, index, row_count, column_count, hidden}, one per tab. Use drive_sheets_get_values to read a tab's cells; sheet_id is the tab id other drive_sheets_* tools take. Auto-approved. |
| drive_sheets_get_valuesA | Read a range of cells from a spreadsheet: display values by default, or the underlying values, or formulas instead of computed results, and optionally cell formatting alongside them. Returns the cells as a list of rows (each a list of values; the Sheets API leaves out trailing empty cells), or {values, formatting} with per-cell formatting dicts when include_formatting is true; values may be redacted by the user's privacy settings. Use drive_sheets_get_metadata to list the tab names and sizes first. Requires user approval. |
| drive_sheets_write_rangeA | Write values and/or formulas into a range of an existing spreadsheet. A cell string starting with '=' is evaluated as a formula, exactly as if typed into the Sheets UI — there is no separate tool for formulas. Writing an empty row/column clears those cells. Returns {spreadsheet_id, updated_range, updated_cells}. Use drive_sheets_format_range to change how cells look, not their values. Requires user approval. |
| drive_sheets_add_sheetA | Add a new tab to an existing spreadsheet. Returns {sheet_id, title, index} of the new tab. Use drive_sheets_create for a new spreadsheet, and drive_sheets_get_metadata to see the tabs that exist. Requires user approval. |
| drive_sheets_rename_sheetA | Rename an existing tab in a spreadsheet. There is no delete-sheet tool — to mark a tab for removal, rename it (e.g. to 'TO BE DELETED - ') and the user can delete it by hand in the Sheets UI. Returns {spreadsheet_id, sheet_id, title} with the new title. Get sheet_id from drive_sheets_get_metadata. Requires user approval. |
| drive_sheets_format_rangeA | Apply formatting to a range in a spreadsheet: bold/italic, colors, number format, horizontal/vertical alignment, text wrap, column width, frozen rows/columns, and merged cells. Every parameter is opt-in — its default means 'leave that aspect unchanged', so a call that only sets a background color never touches unrelated formatting already on the range. Returns {spreadsheet_id, sheet_id, requests_applied}. Use drive_sheets_write_range to change cell values. Requires user approval. |
| drive_sheets_insert_dimensionsA | Insert blank rows or columns into a sheet tab, shifting existing content after the insertion point. Values/formulas are untouched, only their position shifts; formulas referencing shifted cells are adjusted automatically. Returns {spreadsheet_id, sheet_id, dimension, inserted}. Use drive_sheets_delete_dimensions to remove them. Requires user approval. |
| drive_sheets_delete_dimensionsA | Delete rows or columns from a sheet tab, including any values, formulas, and formatting they contain. This is destructive — deleted cell content is not recoverable through PrivacyFence. Remaining rows/columns shift to close the gap. Returns {spreadsheet_id, sheet_id, dimension, deleted}. Use drive_sheets_insert_dimensions to add blank ones. Requires user approval. |
| gmail_list_messagesA | Search Gmail and return matching message summaries (id, thread_id, subject, sender, date). Returns a list of {id, thread_id, subject, sender, date}, up to max_results (default 10, capped at 100), reading up to max_results messages across pages, in the order Gmail returns them; subject, sender and date may be redacted by the user's privacy settings. Messages whose metadata cannot be fetched are omitted. Use gmail_list_threads instead to search by conversation, and gmail_get_message to read a message once you have its id. Auto-approved — no body content is returned. |
| gmail_list_threadsA | Search Gmail and return matching thread summaries (id, snippet). Returns a list of {id, snippet}, up to max_results (default 10, capped at 100), reading up to max_results threads across pages, in the order Gmail returns them. Use gmail_list_messages instead when you need each message's subject, sender or date, and gmail_get_thread to read a whole thread once you have its id. Auto-approved — snippet is a short excerpt of the last message's body, subject to the same 'body' privacy category as gmail_get_message. |
| gmail_get_messageA | Fetch a single Gmail message by id, including body, metadata, and attachment list. Returns {id, thread_id, subject, sender, recipients, date, body_text, attachments (name, mime_type, and size of each), labels}, plus body_html when include_html is true; body, subject, sender, recipients and date may be redacted by the user's privacy settings. Get the id from gmail_list_messages. Use gmail_get_thread instead to read the whole conversation. Requires user approval. |
| gmail_get_threadA | Fetch a full Gmail thread by id, including all messages. Returns {id, subject, messages}, where each message is {id, subject, sender, date, body_text, attachments} in the order Gmail returns them (oldest first); recipients and labels are not included, and bodies fall under the 'thread_history' privacy category and may be redacted. Get the id from gmail_list_threads, or from the thread_id field of gmail_list_messages. Use gmail_get_message instead to read one message with its recipients and labels. Requires user approval. |
| gmail_list_message_attachmentsA | List attachment names, MIME types, and sizes for a Gmail message. Returns {message_id, attachments: [{name, mime_type, size}]} with size in bytes; attachments is empty when the message has none or the user's privacy settings hide them. Auto-approved — metadata only, no attachment content is returned. Use gmail_download_attachment to fetch the actual file. |
| gmail_download_attachmentA | Download a Gmail attachment's content. Identify the attachment by the name returned from gmail_list_message_attachments. Local install: saved to destination_dir (required, no default): pass ~/Downloads, or a path the user asked for, if they should find the file afterward, or your own scratch directory if it is only for you to read. Organization-managed install: destination_dir is ignored; a small attachment comes back inline in the result, a larger one as a one-time link the human opens in their own signed-in browser. Returns {path, name, size_bytes} for a file saved on a local install (a save through the file bridge returns {path, delivery} instead), the file content inline, or {delivery: 'link', name, size_bytes, download_url, expires_at, note}. Requires user approval. |
| gmail_create_draftA | Create a Gmail draft. Returns {draft_id, to, subject}; the draft is only saved, never sent. Use gmail_create_draft_with_attachments instead when there is something to attach, and gmail_reply_draft to answer an existing message so the draft threads with it. Requires user approval. |
| gmail_reply_draftA | Create a Gmail draft replying to a single message, staying in the same thread (sets threadId plus In-Reply-To/References so it actually threads, unlike gmail_create_draft). Addressed only to the original sender. Returns {draft_id, thread_id, to, cc, subject}; the subject is the original's with 'Re: ' added if missing, and cc holds only the addresses you passed. Use gmail_reply_all_draft instead to include the other participants, and gmail_reply_draft_with_attachments when there is something to attach. Requires user approval. |
| gmail_reply_all_draftA | Create a Gmail draft replying to all participants of a message (original sender plus To/Cc recipients, excluding yourself), staying in the same thread. Returns {draft_id, thread_id, to, cc, subject}: to is the original sender, cc the other participants plus any address you passed, and the subject is the original's with 'Re: ' added if missing. Use gmail_reply_draft instead to answer only the sender, and gmail_reply_all_draft_with_attachments when there is something to attach. Requires user approval. |
| gmail_create_draft_with_attachmentsA | Create a Gmail draft with one or more local-file attachments. Parallel to gmail_create_draft -- use this variant only when there is something to attach; use gmail_create_draft when there isn't, so a draft doesn't need this tool's extra attachments argument for nothing. Returns {draft_id, to, subject}; the draft is only saved, never sent. Requires user approval. |
| gmail_reply_draft_with_attachmentsA | Create a Gmail draft replying to a single message, staying in the same thread, with one or more local-file attachments. Parallel to gmail_reply_draft -- use this variant only when there is something to attach. Addressed only to the original sender. Returns {draft_id, thread_id, to, cc, subject}, as gmail_reply_draft does. Requires user approval. |
| gmail_reply_all_draft_with_attachmentsA | Create a Gmail draft replying to all participants of a message (original sender plus To/Cc recipients, excluding yourself), staying in the same thread, with one or more local-file attachments. Parallel to gmail_reply_all_draft -- use this variant only when there is something to attach. Returns {draft_id, thread_id, to, cc, subject}, as gmail_reply_all_draft does. Requires user approval. |
| gmail_add_labelA | Add a label to a Gmail message. Returns {message_id, label_added}. A label that does not exist yet is created first. Use gmail_list_labels to see the existing label names, gmail_create_label to create a label without applying it (it fails if the name exists), and gmail_remove_label to take one off. Requires user approval. |
| gmail_remove_labelA | Remove a label from a Gmail message. Returns {message_id, label_removed}, with a note of 'label not found' added (and nothing changed) when no label has that name. Use gmail_list_labels to see the label names, and gmail_add_label to put one back. Requires user approval. |
| gmail_archive_messageA | Archive a Gmail message by removing it from the Inbox. The message is not deleted and remains searchable. Returns {message_id, archived: true}. Requires user approval. |
| gmail_list_filtersA | List all Gmail filters with their criteria and actions. Returns a list of {id, criteria, action} in Gmail's own filter format (criteria keys such as from, to, subject, query, hasAttachment; action keys such as addLabelIds, removeLabelIds, forward); label ids are not translated to names. Get a filter_id here for gmail_update_filter. Auto-approved -- filter rules only, no message content is returned. |
| gmail_list_labelsA | List all Gmail labels (system and user-created). Nested labels have a '/' in their name (e.g. 'Work/Projects'). Returns a list of {id, name, type}, where type is 'system' or 'user'. Use the name with gmail_add_label and gmail_remove_label. Auto-approved -- label metadata only. |
| gmail_create_filterA | Create a Gmail filter. Provide at least one criteria field (from_address, to_address, subject, query, has_attachment) and at least one action (add_label_names, archive, mark_as_read, star, forward_to). Returns {id, criteria, action} for the new filter. Use gmail_update_filter instead to change an existing filter. Requires user approval. |
| gmail_update_filterA | Replace an existing Gmail filter's criteria and actions, identified by filter_id (from gmail_list_filters). Gmail's API has no native filter update, so this creates a new filter with the given fields (which gets a new id) and then deletes the old one. Returns {old_id, id, criteria, action}; the fields you leave empty are not kept from the old filter. The replacement is created before the old filter is deleted, so a failure leaves the original in place. Use gmail_create_filter instead to add a filter without replacing one. Requires user approval. |
| gmail_create_labelA | Create a Gmail label. Use '/' to create nested labels (e.g. 'Work/Projects' creates 'Projects' nested under 'Work', creating 'Work' first if it doesn't already exist). Fails if the exact label name already exists. Returns {id, name, type} of the new label. Use gmail_list_labels to check which labels exist first. Requires user approval. |
| grist_list_documentsA | List the Grist documents this account can open, with their workspace and team. Returns {documents: [{id, name, workspace, team}]}. Some Grist servers do not allow apps to list documents; then ask the user for the Document ID shown under the document's Settings. Pass an id as doc_id to grist_list_tables. Auto-approved. |
| grist_list_tablesA | List the tables of one Grist document and each table's columns (id, label and type). Returns {doc_id, tables: [{id, columns: [{id, label, type, is_formula}]}]}. Use grist_list_documents first to find the doc_id, and grist_get_records to read a table's records. Auto-approved. |
| grist_get_recordsA | Read records from one table of a Grist document, optionally filtered and sorted. Returns {doc_id, table_id, records: [{id, fields}], truncated, next_after_id}. truncated is true when more records match. To read a whole table, leave sort empty and call again with after_id set to next_after_id until truncated is false; each page needs its own approval. Use grist_list_tables first to find the table and column ids. Requires user approval. |
| grist_export_recordsA | Write every record of one table of a Grist document, optionally filtered, to a CSV or JSON file on the user's computer, in one approval. The first column is the record id (id), then the table's columns by column id; dates are written as YYYY-MM-DD and choice lists as JSON arrays. To write changes back with grist_update_csv (key_column id, up to 20000 rows), keep only id and the data columns you change: formula and list columns cannot be written. Up to 50000 records. Returns {rows, columns, sha256, path, name, size_bytes, delivery}, never the records; read the file at path, which may be a numbered name if a file of that name exists. Use grist_get_records to look at a few records. On an organization-managed install nothing is saved to destination_dir: the result carries a one-time download_url instead. Requires user approval. |
| grist_export_sqlA | Run one read-only SQL query over a Grist document and write the result to a CSV or JSON file on the user's computer, in one approval. Use it to join or filter across tables; use grist_export_records for one table. Cells are written as Grist stores them: dates as seconds since 1970, true/false as 1/0. Grist runs SQL only for people who can copy the whole document. Up to 50000 rows. Returns {rows, columns, sha256, path, name, size_bytes, delivery}, never the rows. On an organization-managed install nothing is saved to destination_dir: the result carries a one-time download_url instead. Requires user approval. |
| grist_add_recordsA | Add new records to one table of a Grist document. Returns {doc_id, table_id, added_ids}. Use grist_update_records to change existing records and grist_list_tables to find the column ids. Requires user approval. |
| grist_update_recordsA | Change cells of existing records in one table of a Grist document. Returns {doc_id, table_id, updated_ids}. Use grist_add_records to add new records and grist_get_records to find record ids. Requires user approval. |
| grist_create_tableA | Create a new table, with its columns, in a Grist document. Returns {doc_id, table_id, column_ids}; table_id is the id Grist assigned. Use grist_add_columns to add columns to a table that already exists and grist_list_tables to see the existing tables. Requires user approval. |
| grist_add_columnsA | Add new columns to an existing table of a Grist document. Returns {doc_id, table_id, column_ids}. Use grist_create_table to create a new table and grist_list_tables to see the existing columns. Requires user approval. |
| grist_import_csvA | Add every row of a CSV file as a new record in one table of a Grist document, in one approval. The first row names the columns (column ids or labels from grist_list_tables); empty cells are left empty. Provide exactly one of local_path (a path on the user's computer, absolute or starting with ~/) or upload_id (the id privacyfence_create_upload_slot returned after you PUT the file's bytes to its upload_url; use this if local_path fails because PrivacyFence cannot read files in your home folder, and always on an organization-managed install). Up to 20000 rows; dates as YYYY-MM-DD. Returns {doc_id, table_id, added, first_added_id, last_added_id}. Use grist_add_records for a few records. Requires user approval. |
| grist_update_csvA | Update records of one table of a Grist document from a CSV file, in one approval: each row is matched to the record whose key_column has the same value, and only cells that differ change. Empty cells change nothing, unless clear_empty is true. Rows that match no record are skipped, or added when create_missing is true. Provide exactly one of local_path or upload_id, as for grist_import_csv. Returns {doc_id, table_id, updated, added, unchanged, skipped}. Use grist_update_records to change a few records by id. Requires user approval. |
| jira_list_projectsA | List Jira projects accessible to the user (key, name, type, lead). Returns a list of {key, name, project_type, description, lead}, at most max_results (default 50, capped at 500), in the API's order. Use the key as project_key in jira_create_issue, or in a JQL query for jira_search_issues. Auto-approved. |
| jira_search_issuesA | Search Jira issues using JQL. Returns summary info for matching issues, as a list of {key, summary, status, issue_type, priority, assignee, reporter, labels, created, updated, url} with description left empty, at most max_results (default 20, capped at 500), in the order the JQL gives. Use jira_get_issue instead for one issue's description and comments. Auto-approved. |
| jira_search_issues_with_fieldsA | Search Jira issues using JQL and add extra fields to each one: custom fields such as Story Points or Sprint, or built-in ones such as due date or fix versions. Returns the list jira_search_issues returns, each issue with an added fields object mapping each requested field's Jira name to its value (people as display names, options and statuses as their names, rich text as plain text with mentions as @Name, an empty field as null), at most max_results (default 20, capped at 100), in the order the JQL gives. Find field names with jira_list_fields. Use jira_search_issues instead when its standard fields are enough: it needs no approval. Requires user approval. |
| jira_export_issuesA | Write every issue a JQL query matches, up to 10,000, to a CSV or JSON file on the user's computer, in one approval. Columns: key, summary, status, issue_type, priority, assignee, reporter, labels, created, updated, url, then the requested extra fields. Returns {rows, columns, sha256, path, name, size_bytes, delivery}, never the issues. A query matching no issue writes no file and returns rows 0. On an organization-managed install nothing is saved to destination_dir: the result carries a one-time download_url instead. Requires user approval. |
| jira_get_issueA | Fetch full details of a Jira issue by key (e.g. PROJ-123), including description and comments. Returns the issue as {key, summary, status, issue_type, priority, assignee, reporter, description, labels, created, updated, url, comments: a list of {id, author, body, created, updated}}; with fields, it also has a fields object mapping each requested field's Jira name to its value, as jira_search_issues_with_fields returns it. Use jira_search_issues instead to find issues without reading them in full. Mentions appear as @Name. Requires user approval. |
| jira_get_transitionsA | List the status transitions available for a Jira issue right now (name and target status), given its current workflow state. Use before jira_transition_issue to see what transition names are valid. Returns a list of {id, name, to_status}; pass a name to jira_transition_issue. Auto-approved. |
| jira_list_fieldsA | List the Jira site's fields, built-in and custom, with the id and JQL names behind each display name. Returns a list of {id, name, custom, type, jql_names}, sorted by name, at most max_results (default 50, capped at 200). Pass a name in the fields parameter of jira_search_issues_with_fields or jira_get_issue; in a JQL query for jira_search_issues use one of jql_names, e.g. cf[10016] > 3 or "Story Points" > 3. Auto-approved. |
| jira_find_usersA | Find Atlassian users by name or email and return their account ids. Returns a list of {account_id, display_name, active, account_type}, at most max_results entries; email addresses are never returned. Auto-approved -- mention someone in a comment or description by writing @Name, or assign an issue with assignee_account_id. Use jira_search_issues instead to find issues, not people. |
| jira_refresh_user_cacheA | Re-fetch the names of every Atlassian account id PrivacyFence has cached. Auto-approved -- use this when a renamed or newly added person shows up wrong; cached names otherwise refresh on their own after 7 days. Returns {cached_users: n}, the number of account ids re-fetched. Use jira_find_users instead to look up someone by name. |
| jira_create_issueA | Create a new Jira issue. Returns the created issue, with its new key, in the same shape jira_get_issue returns minus comments. Get project_key from jira_list_projects. Requires user approval. |
| jira_add_commentA | Add a comment to an existing Jira issue. Returns the new comment as {id, author, body, created, updated}. Use jira_update_issue instead to change the issue's own fields. Requires user approval. |
| jira_update_issueA | Update fields on an existing Jira issue (summary, description, priority, and/or custom fields). Only the fields you pass non-empty change, and at least one is required. Returns the updated issue in the same shape jira_get_issue returns minus comments. Use jira_transition_issue instead to change its status. Pass assignee_account_id to reassign it. Requires user approval. |
| jira_transition_issueA | Move a Jira issue to a new status by transition name (e.g. "Done", "In Progress") — call jira_get_transitions first to see what's valid from the issue's current status. Returns the issue after the move, in the same shape jira_get_issue returns minus comments; errors, listing the valid names, if the name is not available. Requires user approval. |
| miro_list_boardsA | List the Miro boards this account can open in the connected Miro team, optionally only those matching a search text. Only boards in the Miro team chosen when PrivacyFence was signed in are visible. Returns a list of {id, name, team, modified_at, view_link}. Pass an id as board_id to miro_get_board. Auto-approved. |
| miro_get_boardA | Get one Miro board's name, team, dates and link. Returns {id, name, team, created_at, modified_at, view_link}. Use miro_list_boards first to find the board_id, and miro_list_items to read what is on the board. Auto-approved. |
| miro_list_tagsA | List the tags defined on one Miro board. Returns a list of {id, title, color}. Use miro_list_items to read the board's items. Auto-approved. |
| miro_list_itemsA | Read the items on one Miro board, optionally only one type of item or only the items inside one frame. Returns a list of items with their id, type, text, color, position, size and frame. Use miro_get_items to read specific items by id, and miro_create_items to add to the board. Requires user approval. |
| miro_get_itemsA | Read specific items of one Miro board by their ids. Returns a list of items with their id, type, text, color, position, size and frame. Use miro_list_items to find the ids, and miro_update_items to change items. Requires user approval. |
| miro_list_connectorsA | Read the connector lines on one Miro board and the ids of the items each one joins. Returns a list of {id, start_item_id, end_item_id, shape, captions}. Use miro_create_connectors to draw new lines. Requires user approval. |
| miro_create_itemsA | Add sticky notes, cards, texts, shapes or frames to one Miro board, up to 20 in one request. Returns {board_id, created: [{id, type}]}. Use miro_update_items to change items that already exist. Requires user approval. |
| miro_create_connectorsA | Draw connector lines between existing items on one Miro board, up to 20 in one request. Returns {board_id, created_ids}. Use miro_list_connectors to read the lines already there. Requires user approval. |
| miro_update_itemsA | Change existing items on one Miro board (text, color, position, size, or which frame they are in), up to 20 in one request. Nothing can be deleted; to take an item out of its frame set frame_id to an empty string. Returns {board_id, updated_ids}. Use miro_get_items to read the items first, and miro_create_items to add new ones. Requires user approval. |
| miro_update_boardA | Rename a Miro board or change its description. Returns {board_id, name, description}. Use miro_get_board to read the board's current name. Requires user approval. |
| peek_list_pagesA | List the Peek pages this account can manage, newest first, with each page's link and who can open it. An admin account sees every page. Returns a list of {slug, name, owner, size_bytes, visibility, url, created_at, version}, where version is the page's latest version. Use peek_get_comments to read the comments on a page and peek_get_stats to see how often it was opened. Auto-approved. |
| peek_get_commentsA | Read the reviewers' comments on one Peek page, with what each comment is anchored to. Comments belong to one version of the page: the latest unless you give version. Returns {slug, name, version, comments: [{id, author, verified, body, anchor_kind, selector, element_text, created_at, version}]}, where version is the one read and verified is true when a signed-in Peek account wrote the comment and false when a viewer typed the author name. Use peek_get_stats to see how often the page was opened and peek_add_comment to reply. Requires user approval. |
| peek_get_statsA | Read how often one Peek page was opened, and the names visitors gave. IP addresses and browsers are never returned. Returns {slug, name, total_visits, unique_visitors, recent: [{visitor_name, visited_at}]}. Use peek_get_comments to read the comments. Requires user approval. |
| peek_upload_pageA | Publish an HTML page on Peek, or a new version of one of your pages, and get its share link. Give the page as html, local_path or upload_id. Give slug to replace what an existing page's link shows with this new version; its visibility stays as it is. A new page is restricted unless you choose otherwise: only you, Peek admins and the people granted access can open it. Returns {slug, url, visibility, version, version_url}. Use peek_set_visibility to change who can open a page later. Requires user approval. |
| peek_set_visibilityA | Change who can open a Peek page: anyone with the link, anyone signed in to Peek, or only the people granted access (restricted). Returns {slug, visibility, notified}, where notified says whether Peek emailed the people granted access. Use peek_upload_page to publish a new version. Use peek_grant_access to choose who can open a restricted page. Requires user approval. |
| peek_add_commentA | Post a comment on a Peek page under your own Peek account name, on the latest version or the one you give. Copy selector and element_text from a comment returned by peek_get_comments to reply at the same spot. Returns {slug, version, comment: {id, author, verified, body, anchor_kind, selector, element_text, created_at}}. Use peek_get_comments to read the existing comments. Use peek_list_versions to find a version. Requires user approval. |
| peek_delete_pageA | Delete a Peek page, with its comments and visit history. Returns {deleted: slug}. Use peek_list_pages to find the slug. Requires user approval. |
| peek_rename_pageA | Rename a Peek page; its link may change to match the new name, and old links keep redirecting to it in browsers. Use the slug it returns from then on; the old slug no longer works in the other Peek tools. Get the current slug from peek_list_pages. Returns {old_slug, slug, url, name}. Requires user approval. |
| peek_list_versionsA | List the versions of one Peek page you manage, newest first, with each version's size, time and link. Returns {slug, name, versions: [{version, size_bytes, created_at, url}]}. Use a version number with peek_get_comments or peek_add_comment. Auto-approved. |
| peek_list_grantsA | List who can open one restricted Peek page: the people and Google groups granted access. Returns {slug, name, visibility, grants: [{kind, email, created_at}]}. Grants apply only while the page is restricted. Use peek_grant_access and peek_revoke_access to change them. Requires user approval. |
| peek_grant_accessA | Let a person or a Google group open a restricted Peek page. Peek emails them the link when the page is restricted and they did not have access yet. Returns {slug, kind, email, notified}. Use peek_set_visibility to restrict the page, and peek_list_grants to see who has access. Requires user approval. |
| peek_revoke_accessA | Remove a person's or a Google group's access to a restricted Peek page. Returns {slug, kind, email, removed}. Use peek_list_grants to see who has access. Requires user approval. |
| salesforce_list_reportsA | List Salesforce reports accessible to the user. Returns a list of {id, name, report_type, folder_name, description}, ordered by name, at most 200 (no paging). report_type is the report's developer name. Pass an id as report_id to salesforce_run_report. Auto-approved. |
| salesforce_get_recordA | Fetch a Salesforce record by object type and id. Returns {object_type, id, fields}, where fields maps every field name the object returns to its value. Use salesforce_search instead when you only have a name and need the id. Requires user approval. |
| salesforce_run_reportA | Run a Salesforce report by id and return the results. Returns Salesforce's Analytics API report result as-is: reportMetadata, reportExtendedMetadata, groupingsDown/groupingsAcross and a factMap holding each group's rows and aggregates. By default it runs the report as saved; columns, filters and summary_only narrow this one run without changing the saved report. Salesforce returns at most 2,000 detail rows per run: allData false means rows were cut off. To read every row, pass page_by (a column with a unique value per row) and call again with cursor=next_cursor until next_cursor is null; each page is one report run and carries page {number, first_row, last_row, more}. Get report_id from salesforce_list_reports. Requires user approval. |
| salesforce_export_reportA | Write every row of a Salesforce report to a CSV or JSON file on the user's computer, in one approval. Columns are the report's column API names. columns and filters narrow this export as on salesforce_run_report: for example [{"column": "LAST_UPDATE", "operator": "greaterOrEqual", "value": "2026-10-04"}] exports only rows changed since that date. A report of more than 2,000 rows, or a grouped report, needs page_by; the export then reads it page by page internally. Returns {rows, columns, sha256, path, name, size_bytes, delivery}, never the rows; read the file at path. On an organization-managed install nothing is saved to destination_dir: the result carries a one-time download_url instead. Requires user approval. |
| salesforce_searchA | Search Salesforce by name or id across one or more object types — the same mechanism as the search bar at the top of the Salesforce UI. Returns lightweight matches as a list of {object_type, id, fields}: fields is {Id, Name} when object_types is set (objects with no Name field, such as Case, fail that query) and only {Id} without it. At most max_results (default 20, capped at 200), per object type when object_types is set; call salesforce_get_record for full field details on a match. Requires user approval. |
| salesforce_create_recordA | Create one new Salesforce record. fields maps field API names to values, such as {"Name": "Acme", "Industry": "Retail"}; the names are checked against the object's own fields before you are asked. Returns {object_type, id}, the new record's 18-character id. Use salesforce_create_records to create several records of one object type in one approval, and salesforce_get_record to see an existing record's field names. Requires user approval. |
| salesforce_update_recordA | Change fields of one existing Salesforce record, by its id. Only the fields you list change; a field set to null is cleared. The approval card shows each field's current and new value; fields that already hold the given value are left as they are. Returns {object_type, id, fields}. Use salesforce_update_records to change several records in one approval, and salesforce_get_record to read the record first. Requires user approval. |
| salesforce_create_recordsA | Create 1 to 200 new records of one Salesforce object type in one approval, all or none: if Salesforce refuses one record, none is created and the error names each refused record by its position. Returns {object_type, created, ids}, the new ids in input order. Use salesforce_create_record for a single record. Requires user approval. |
| salesforce_update_recordsA | Change 1 to 200 existing records of one Salesforce object type in one approval, all or none. Each record is found by key_field: Id (default) or a field marked External ID. Only the fields listed change, records that already have those values are left alone, and a key that matches no record or several records refuses the whole call. Returns {object_type, updated, ids}. Use salesforce_update_record for one record by id and salesforce_search to find ids. Requires user approval. |
| slack_list_channelsA | List Slack channels visible to the user (id, name, privacy, topic, purpose, member count). Optionally filter to channels a specific participant belongs to. Returns a list of {id, name, is_private, topic, purpose, member_count}, in Slack's order, up to max_results (default 100, capped at 1000); names and topics may be redacted by the user's privacy settings. Use slack_list_dms for 1:1 conversations or slack_list_group_chats for group DMs. Auto-approved. |
| slack_list_dmsA | List 1:1 direct-message conversations visible to the user (id, other participant). Optionally filter to the DM with a specific participant (user id, handle, or display name). Returns a list of {id, user_id, user_name}, up to max_results (default 100, capped at 1000); with a participant, the filter is applied while reading, so max_results bounds the matches returned, not the DMs searched. Names may be redacted by the user's privacy settings. Use slack_list_channels for channels or slack_list_group_chats for group DMs. Auto-approved. |
| slack_list_group_chatsA | List group-DM conversations visible to the user (id, name, participants). Optionally filter to group chats containing a specific participant (user id, handle, or display name). Returns a list of {id, name, member_ids, member_names}, up to max_results (default 100, capped at 1000); with a participant, the filter is applied while reading, so max_results bounds the matches returned, not the chats searched. Member ids and names may be redacted by the user's privacy settings. Use slack_list_dms for 1:1 conversations, or slack_create_group_chat to open a group DM that does not exist yet. Auto-approved. |
| slack_resolve_permalinkA | Parse a Slack message permalink (from a message's "Copy link") into the channel id, timestamp, and (if the link points at a threaded reply) thread root timestamp needed by slack_get_channel_history/slack_get_thread_replies. Reads no message content -- just decodes the link. Returns {channel_id, channel_name, ts, thread_ts}; thread_ts is empty unless the link points at a threaded reply. Pass channel_id and thread_ts (or ts when thread_ts is empty) to slack_get_thread_replies. Auto-approved. |
| slack_refresh_user_cacheA | Force an immediate refresh of PrivacyFence's local cache of Slack workspace member names/emails, used to resolve message authors in channel history, thread replies, and search results without a per-message users.info call. Refreshes automatically about once a week; call this when a teammate who joined recently isn't resolving correctly yet. Returns {cached_users: }. Auto-approved -- refreshes name/email lookups only, reads no message content. |
| slack_refresh_channel_cacheA | Force an immediate refresh of PrivacyFence's local cache of Slack channel/DM/group-DM names, used to resolve which conversation a message belongs to in search results and history/thread reads without a per-message conversations.info call. Refreshes automatically about once a week; call this after a new channel is created so it resolves by name right away. On a workspace with a lot of channels, one call may not finish the whole sync -- check the result's has_more flag and, if true, call this tool again (same args) to continue from where it left off. Returns {cached_channels: , has_more: bool}, plus a note when has_more is true. Auto-approved -- refreshes name lookups only, reads no message content. |
| slack_get_channel_historyA | Fetch recent messages in a Slack channel. Returns {messages: [...], has_more: bool, next_cursor: str}, plus a note when has_more is true -- more messages exist than were returned (a Slack-imposed cap can make a page smaller than limit; see docs/slack-setup.md) -- call again with cursor=next_cursor to read the next page instead of assuming this is everything. Each message is {ts, channel_id, channel_name, user_id, user_name, text, thread_ts, reply_count, read_state}, newest first (read_state is 'unread', 'read' or 'unknown', from your own Slack read marker), one page of up to limit messages (default 50, capped at 1000); text and names may be redacted by the user's privacy settings. Use slack_get_thread_replies for a thread's replies, or slack_search_messages to find messages by text or person. Requires user approval. Pass minutes to read only the last N minutes of this conversation; it reads the conversation itself, so nothing is lost to search-index delay. |
| slack_get_thread_repliesA | Fetch all replies in a Slack thread. Returns {messages: [...], has_more: bool, next_cursor: str}, plus a note when has_more is true -- more replies exist than were returned; call again with cursor=next_cursor to read the next page (see slack_get_channel_history's own note on why the page can be short). Each message is {ts, channel_id, channel_name, user_id, user_name, text, thread_ts, reply_count, read_state}, the parent message included, in Slack's order; read_state is 'unread', 'read' or 'unknown' (a reply in a thread you do not follow); text and names may be redacted by the user's privacy settings. Use slack_get_channel_history for the channel's top-level messages; get thread_ts from a permalink with slack_resolve_permalink. Requires user approval. |
| slack_search_messagesA | Search Slack messages by query, participant, time window, or a combination. For messages from or with someone prefer participant over query -- 'Bob wrote me' is participant='Bob'; 'Bob in a chat with Jane' is participant='Bob,Jane' -- it reads those DM/group-chat conversations directly, more reliably than search; query then filters their text. Defaults to 90 days; widen or disable via days. For the last N minutes in every channel, DM, group DM and thread, pass minutes (query may be empty): newest first; search-index delay can miss the last minute or two. Returns a list of {ts, channel_id, channel_name, user_id, user_name, text, thread_ts, reply_count}, up to count (default 20, max 100); a participant search reads at most 10 conversations. Text and names may be redacted. Use read_state=true with care: one Slack request per conversation, easily rate-limited; prefer slack_get_read_state for a few messages. Use slack_get_channel_history for one known channel. Requires user approval. |
| slack_get_read_stateA | Get your own Slack read state for a few specific messages you already have, without reading them again. Use it sparingly, only for messages whose read state matters (for example the ones you are about to report as new), not for every search result: each distinct conversation costs one Slack request and each distinct thread one rate-limited conversations.replies request (about a minute each on an app distributed outside the Slack Marketplace). Returns a list of {channel_id, ts, thread_ts, read_state}, one per distinct requested message in request order, where read_state is 'unread', 'read' or 'unknown' (a thread you do not follow, or no marker). Prefer it over slack_search_messages' read_state=true for more than a few conversations. Returns no message text. Auto-approved. |
| slack_create_group_chatA | Create (or reopen the existing) group-DM conversation with the given participants and return its channel id, ready for slack_send_message. Participants must already have a Slack user id (from slack_list_dms, slack_list_group_chats, or a message's user_id) -- this does not resolve email addresses or handles. Returns {id, name, member_ids, member_names}; member ids and names may be redacted by the user's privacy settings. Requires user approval. |
| slack_send_messageA | Send a message to a Slack channel or DM. Requires user approval. Set mark_unread=true to leave the message unread after sending (useful when sending a DM to yourself as a note; requires the im:write scope on the user token for DMs). Returns {channel_id, ts, text} of the sent message; channel_id is the resolved conversation id, which for a DM is the D... id even if you passed a user id. Use slack_create_group_chat first to message a new group of people. |
| tasks_list_task_listsA | List all Google Task lists. Returns a list of {id, title, updated}. Pass an id as task_list_id to tasks_list_tasks and the other task tools. Auto-approved. |
| tasks_list_tasksA | List tasks in a task list. Returns a list of tasks as {id, task_list_id, title, notes, due, status ('needsAction' or 'completed'), completed, updated, position, parent, deleted}, in the API's order. Reads up to 100 tasks across pages; notes may be redacted by the user's privacy settings. Use tasks_get_task instead when you already have a task's id. Auto-approved. |
| tasks_get_taskA | Fetch a single task by id. Returns one task in the same shape tasks_list_tasks lists; deleted is true for a task deleted but not yet purged, and notes may be redacted by the user's privacy settings. Get the id from tasks_list_tasks. Auto-approved. |
| tasks_create_taskA | Create a new task. Returns the created task, with its new id, in the same shape tasks_get_task returns. Get task_list_id from tasks_list_task_lists. Requires user approval. |
| tasks_update_taskA | Update a task's title, notes, or due date. Only the fields you pass non-empty change: an empty value leaves that field as it is; to remove notes or the due date, set clear_notes or clear_due. Returns the updated task in the same shape tasks_get_task returns. Use tasks_complete_task or tasks_uncomplete_task to change whether it is done. Requires user approval. |
| tasks_complete_taskA | Mark a task as completed. Returns the updated task in the same shape tasks_get_task returns, with status 'completed' and the completion time in completed. Use tasks_uncomplete_task to undo it. Requires user approval. |
| tasks_uncomplete_taskA | Mark a task as not completed. Returns the updated task in the same shape tasks_get_task returns, with status 'needsAction' and completed cleared. Use tasks_complete_task for the opposite. Requires user approval. |
| tasks_move_taskA | Move a task from one list to another. The task keeps its id, status and subtasks. Recurring tasks cannot be moved between lists. Returns the moved task in the same shape tasks_get_task returns. Get both list ids from tasks_list_task_lists. Requires user approval. |
| telegram_list_chatsA | List Telegram chats (id, name, type, unread count). Returns a list of {id, name, username, type, unread_count, is_self}, most recently active first, up to limit (default 50, capped at 200); username is the @handle without the @, empty if none; type is 'user', 'group', 'channel' or 'bot', and is_self marks Saved Messages. Pass an id as chat_id to telegram_get_messages or telegram_send_message; call telegram_refresh_chat_cache first if a new chat is missing or shows no name. Auto-approved. |
| telegram_get_messagesA | Fetch recent messages from a Telegram chat by chat id. Returns a list of {id, sender_name, text, date} (date is ISO 8601), newest first, up to limit messages (default 50, capped at 200); media messages carry only their text or caption, if any. Use telegram_search_messages to find messages by keyword across all chats; get chat_id from telegram_list_chats. Requires user approval. |
| telegram_search_messagesA | Search messages across Telegram chats by keyword. Returns a list of {id, chat_id, chat_name, sender_name, text, date} (date is ISO 8601), newest first, up to limit messages (default 30, capped at 100); id is the message id and chat_id is the value telegram_get_messages takes. Use telegram_get_messages to read one chat's recent messages in full. Requires user approval. |
| telegram_refresh_chat_cacheA | Force an immediate refresh of PrivacyFence's local cache of Telegram chat/group/channel names, used to resolve which chat a message belongs to in search results and chat history without a per-message lookup. Refreshes automatically about once a week; call this after a new chat starts so it resolves by name right away. Auto-approved -- refreshes name lookups only, reads no message content. Returns {cached_chats: }. |
| telegram_send_messageA | Send a message to a Telegram chat or user by chat id. Returns {chat_id, chat_name, msg_id, text} of the sent message. Get chat_id from telegram_list_chats. Requires user approval. |
| privacyfence_check_policyA | Before calling a gated tool, ask whether that exact call would auto-accept or need a human. Pass the connector, tool and args you're about to call. Returns {gate, verdict, matched_rule, matched_rule_id, reason, pii_gate_may_apply, pii_gate, pii_gate_detail, suggested_rules}. verdict: 'auto_accept' (the real call passes through identically), 'requires_review' (no rule can match these args) or 'unknown' (depends on fetched content). matched_rule_id (auto_accept only) is privacyfence_propose_policy_change's rule_id. suggested_rules: rules that would cover an uncovered call, {group, label, value, value_known, verb, operation, requires_args?}; value is null if the call reaches it at run time, [] if the rule takes none; requires_args: args the call must also pass. pii_gate: whether the PII scan can still force a popup or, unattended or with a scoped token, a denial: 'none', 'allowed_by_token', 'allowed_unless_inline' or 'applies' (see pii_gate_detail). No side effects. reason: why you check (logged, unverified). |
| privacyfence_list_policyA | List every configured auto-accept rule, plus the scope catalogue privacyfence_propose_policy_change accepts. Returns {rules, scope_groups}. Each rule has: id (pass as privacyfence_propose_policy_change's rule_id to update or remove it), sentence (human-readable), connector, scope_type, value, operations (internal keys, informational), verbs ({verb, family} pairs; family is 'read', 'write', 'send' or 'destructive'), conditions, and covered_tools (every tool name the rule can auto-accept). Each scope_groups entry has an id (pass as group), the verbs that scope can govern (pass a subset as verbs; any other verb is rejected before a popup), and whether it needs a value. Call this before proposing a change: an id or group only matches something real if you listed it rather than guessed. Read-only, no popup. reason: one sentence on why you're listing the policy now (logged, self-reported; this discloses the full rule set). |
| privacyfence_propose_policy_changeA | Propose adding, updating or removing an auto-accept rule (a scope plus allowed verbs). ALWAYS blocks on a human-approved dialog. If declined, or in an unattended session, it errors -- never assume success. Call privacyfence_list_policy first: group, verbs and rule_id must be listed, not guessed; a verb not in that group's scope_groups entry is rejected before any popup. operation='add'/'update' need group (a scope_groups id, e.g. 'drive.folder'), value (the resource's id -- folder id, channel ID, project key -- not its name or title, except label names and file types; a non-id is refused; omit unless needs_value or value_optional) and verbs (non-empty subset of the group's verbs). Verbs: read, download, search, add, update, restructure, move, send, delete (older names map). 'update' also takes rule_id (replaces that rule). 'remove' needs only rule_id. Returns {confirmed, changed, description, rule_ids}; changed is false if nothing differed. reason: one sentence on why you're proposing this (logged). |
| privacyfence_begin_unattended_sessionA | Tell PrivacyFence this conversation is an unattended/scheduled Cowork run (e.g. a Routine firing on a schedule) with no human necessarily watching, for the rest of this connection. From then on, any gated tool call that isn't already covered by a configured auto-accept rule is denied immediately with a clear error, instead of PrivacyFence opening a native approval dialog that nobody will answer. Call this once at the start of a scheduled run, and pair it with privacyfence_check_policy to plan which steps are safe to attempt. Never changes what auto-accepts, only what happens when nothing does. Errors if an administrator hasn't enabled unattended sessions for this install. Do not call this during a normal interactive conversation -- it makes denials immediate instead of prompting. reason: one sentence on why this session is unattended (e.g. the Routine/schedule that triggered it) -- logged in the audit entry for this session change, since no popup is shown for it to appear in. |
| privacyfence_end_unattended_sessionA | Clear the unattended-session flag set by privacyfence_begin_unattended_session for this connection, restoring normal interactive approval behavior. Call this when a scheduled run finishes. Not strictly required -- the flag also clears automatically when the connection closes -- but call it if this connection might be reused afterward for something interactive. reason: one sentence on why the unattended session is ending now -- logged the same way as privacyfence_begin_unattended_session's. |
| privacyfence_await_approvalA | Long-poll pending approvals from gated calls' {status: 'approval_pending', approval_id, ...} results; status only, never content. Before the first call for an approval, relay that result's message and url (binder_url if several) to the user -- never wait silently. If pending_count > 1, first issue your other ready gated calls, then pass all approval_ids in one call (one human pass). Keep timeout_seconds under your client's tool-call timeout. Returns {approval_id: status}: 'pending' (schedule a follow-up if you can, else call again), 'approved' (re-issue the ORIGINAL call with identical arguments -- the only way to get the data), 'denied' (a human said no -- re-issuing will not change that; don't retry, ask the user how to proceed unless denial_feedback says otherwise), 'expired' (re-issuing starts a fresh approval) or 'unknown' (no such id here). denial_feedback holds the user's instruction for a denial: follow it. Returns on any change or at the timeout. Prefer this over re-issuing the original call to poll. |
| privacyfence_statusA | Check whether THIS PrivacyFence install is set up: call it before the first PrivacyFence-governed action in a conversation, or when asked why a connector (gmail_*, ...) is missing. An empty or partial tool list means connectors aren't authenticated yet, NOT that PrivacyFence is irrelevant -- this is the one tool guaranteed to exist even when every other tool is missing. Returns {mode ('local'/'org'), setup_complete (any connector authenticated), connectors [{name, enabled, authenticated, blocked_by: null, 'no_org_config', 'not_authenticated' or a reason}], next_step, message, sign_in_url (always null)}. If setup isn't complete, relay message to the human as-is. next_step 'open_privacyfence_companion' (local): the human opens PrivacyFence's companion app (menu-bar/tray icon; Linux: applications menu) and chooses Open Settings; you can't, and have no link. 'contact_your_administrator' (org): sign-in is via the org's IdP. Only side effect: an audit entry. reason: one sentence on why you're checking now (logged). |
| privacyfence_create_upload_slotA | Get a one-time URL to upload a local file to PrivacyFence, for a client without the PrivacyFence extension (e.g. Claude Code) -- use it when a tool's local_path/attachments parameter says PrivacyFence can't read your files directly. Returns {upload_id, upload_url, method: 'PUT', max_bytes, expires_at, example}: PUT the raw bytes to upload_url (e.g. the curl -T example); no Authorization header -- the URL is the credential. Then pass upload_id to the tool that needs the file (its upload_id parameter, e.g. drive_upload_file, or an 'upload:<upload_id>' attachments entry, e.g. gmail_*_with_attachments). Never fetch upload_url yourself or pass it as local_path. Single-use, expires in 10 minutes, claimable only by your next tool call in this conversation. This uploads, gates and approves nothing: that happens when the destination tool runs. reason: one sentence on why this file is needed now (logged, self-reported, unverified). |
| privacyfence_propose_scoped_tokenA | Propose a scoped token (a named, expiring bearer credential limited to some rules and tools, for a routine or scheduled job) for the person to review in PrivacyFence Settings. Returns at once with review_url: give it to the person. Nothing is created until they review it, type its name and confirm; they may narrow it. You never receive the token, nor whether it was created. Set from_session=true to build its rules and tools from the calls approved in this session, or pass rules (each {kind:'new', group, value, verbs} with group and verbs from privacyfence_list_policy's scope_groups and value a comma-separated id list, or {kind:'copy', rule_id}) and tools. days defaults to 90. Ask for allow_personal_data or allow_personal_data_reads only if the job needs them. Refused in an unattended session. reason: one sentence on what the token is for (logged and shown to the person). |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 180 tools
Most tools within a connector are clearly scoped and heavily cross-referenced in their descriptions, which does a lot of the disambiguation work. But the set contains many near-twin pairs that an agent must pick between on subtle grounds: jira_search_issues vs jira_search_issues_with_fields, confluence_search vs confluence_cql_search, gmail_create_draft vs gmail_create_draft_with_attachments, and drive_get_file_content vs drive_download_file. Across 15+ connectors the volume makes misselection realistically likely even though individual boundaries are documented.
Almost everything follows a predictable connector_verb_noun snake_case convention (gmail_list_messages, jira_create_issue, drive_sheets_write_range), which makes scanning by prefix easy. Minor deviations exist: privacyfence_status and miro_list_boards/get_board use noun-only or shortened forms, and a few names are long compounds (assets_get_connected_tickets). Overall the pattern holds well.
180 tools is an extreme mismatch for any single assistant surface, far past the 50+ threshold. Even if each connector's subset is reasonable in isolation, the combined set is not a well-scoped tool list — it is a federation of fifteen products. Agents cannot reliably hold this surface in context, and the approval/policy meta-tools add further weight.
Coverage is unusually broad: CRUD across Drive, Gmail, Calendar, Jira, Confluence, Salesforce, Slack, Miro, Grist, Peek, Tasks and Contacts, plus lifecycle extras (revisions, drafts, filters, transitions, caches, policy tools). Gaps exist — contact deletion is explicitly unsupported, Miro has no delete, Drive has no folder creation or permission tools — but these are minor and workaroundable.