> ## Documentation Index
> Fetch the complete documentation index at: https://developers.myhero.so/llms.txt
> Use this file to discover all available pages before exploring further.

# Tool catalog

> Full catalog of 88 HERO MCP tools — editor, knowledge, project tree, tables, web, workflows, and integrations (Gmail, Drive, Outlook, OneDrive, Dropbox, Notion).

The HERO MCP server exposes 88 tools to compatible clients, grouped by area below.

## General

* [**Get hero writing guide**](./general/get-hero-writing-guide) — `get_hero_writing_guide`\
  Get the complete HERO writing reference: extended markdown DSL, clause depth rules, placeholder usage, legal writing style, and tool selection guidance. Call this BEFORE writing any document content to ensure correct syntax. Returns \~1000 lines of guidance — call once per session and remember it.

## Knowledge

* [**List project documents**](./knowledge/list-project-documents) — `list_project_documents`\
  List all documents (files, subfiles, and external PDFs) in a project. Returns name, id, type, and externalType (e.g. 'PDF') for each.
* [**List project folders**](./knowledge/list-project-folders) — `list_project_folders`\
  List all folders in a project.
* [**Get document metadata**](./knowledge/get-document-metadata) — `get_document_metadata`\
  Get metadata for a specific document: name, type, description, collaborators, timestamps, parent folder, published status.
* [**Build document map**](./knowledge/build-document-map) — `build_document_map`\
  WHEN TO USE: You need a structural overview (table of contents, section list, defined terms) without reading full content. Build a structural map of a document: all clause sections (numbering, title, depth, content) and defined terms.
* [**Get section by numbering**](./knowledge/get-section-by-numbering) — `get_section_by_numbering`\
  Find a clause section by its numbering (e.g. "1.1", "22.1"). Returns numbering, title, depth, and full content.
* [**Get section titles**](./knowledge/get-section-titles) — `get_section_titles`\
  List clause section titles at a given depth (0 = top-level). Useful for getting a table of contents.
* [**Get document clauses**](./knowledge/get-document-clauses) — `get_document_clauses`\
  Return all clause blocks from a document as structured JSON.
* [**Explain term definition**](./knowledge/explain-term-definition) — `explain_term_definition`\
  Explain a defined term (e.g. "Party", "Effective Date") in a specific document. Returns the definition content.
* [**Read document text**](./knowledge/read-document-text) — `read_document_text`\
  WHEN TO USE: You need to understand content for questions, analysis, or summarization. Works for editor documents and PDFs. Prefer this over read\_document\_content unless you need raw JSON. Read the full text content of a document as plain text. Works for both HERO editor documents and external PDFs. For editor documents, clause numbering and headings are preserved. For PDFs, returns extracted text (no formatting structure). Use this when you need to read the actual content rather than just structural metadata, or when clause-specific tools don't return enough context.
* [**Find documents with clause blocks**](./knowledge/find-documents-with-clause-blocks) — `find_documents_with_clause_blocks`\
  Find all documents in a project that contain clause blocks (structured legal sections).
* [**Get document maps**](./knowledge/get-document-maps) — `get_document_maps`\
  Build document maps (sections + terms) for ALL documents in a project. Useful for cross-document search.
* [**Get table schema**](./knowledge/get-table-schema) — `get_table_schema`\
  Get the column schema of a table by table ID.
* [**Resolve table by name**](./knowledge/resolve-table-by-name) — `resolve_table_by_name`\
  Resolve a table ID from its name within a project.
* [**List clause blocks for reference**](./knowledge/list-clause-blocks-for-reference) — `list_clause_blocks_for_reference`\
  List all clause blocks in a document with their blockId, hierarchy, depth, numbering, and text preview. Use this to find the blockId needed to create a clause reference.
* [**Create clause reference**](./knowledge/create-clause-reference) — `create_clause_reference`\
  Create a clause reference record in the database. Returns a clauseReferenceId that you can embed in document content using \{\{clauseRef:CLAUSE\_REF\_ID}} (in extended Markdown) or as a \{ type: "clauseReference", attrs: \{ clauseReferenceId: "..." } } node (in TipTap JSON).  WORKFLOW: 1. Call list\_clause\_blocks\_for\_reference to find the target clause's blockId and hierarchy. 2. Call this tool with the target documentId, blockId, and hierarchy. 3. Use the returned clauseReferenceId in your content.  Local references: documentId = the document you are writing content into. Cross-document references: documentId = the OTHER document that contains the target clause.

## Project tree

* [**List project tree**](./project-tree/list-project-tree) — `list_project_tree`\
  Get the full document tree for a project: all folders and files with their parent-child relationships. Returns id, name, type, parentId, createdAt, updatedAt for each node.
* [**List user workspaces**](./project-tree/list-user-workspaces) — `list_user_workspaces`\
  List all workspaces the current user has access to. Returns each workspace's id, name, and metadata. Use this when the user asks about their workspaces or when you need a workspaceId for other tools.
* [**Search documents**](./project-tree/search-documents) — `search_documents`\
  Search for documents and folders by name across all workspaces the user has access to. Returns up to 20 matches with full path context (workspace, project, parent folder) AND a `format` field ('editor' | 'docx' | 'pdf' | 'folder') so you can pick the right tool family per document. Use this to find documents by name when the user references them informally without @-mentions. If multiple matches are returned, ask the user to disambiguate using the workspace/project context shown.
* [**Search projects**](./project-tree/search-projects) — `search_projects`\
  Search for projects by name across all workspaces the user has access to. Returns each match's \_id, name, description, workspaceId, and workspaceName so you can pick the right one without needing a workspaceId up front. ALWAYS use this before create\_project when the user references a project by name — it prevents creating duplicates in the wrong workspace. If multiple matches are returned, ask the user to disambiguate using workspace context.
* [**List workspace projects**](./project-tree/list-workspace-projects) — `list_workspace_projects`\
  List all projects in a workspace with their names, ids, and timestamps.
* [**Create project**](./project-tree/create-project) — `create_project`\
  Create a new project in the current workspace.
* [**Rename project**](./project-tree/rename-project) — `rename_project`\
  Rename an existing project.
* [**Delete project**](./project-tree/delete-project) — `delete_project`\
  Delete an entire project and all its documents. THIS IS DESTRUCTIVE — only call after confirming with the user.
* [**Create document**](./project-tree/create-document) — `create_document`\
  Create a new document (file) or folder in a project. Set type to "FOLDER" for folders, "FILE" for documents.
* [**Create document batch**](./project-tree/create-document-batch) — `create_document_batch`\
  Create multiple documents/folders in one operation. Useful for scaffolding a project structure. Items are created in order so you can reference earlier items as parents by using a temporary id pattern.
* [**Rename document**](./project-tree/rename-document) — `rename_document`\
  Rename a document or folder.
* [**Move document**](./project-tree/move-document) — `move_document`\
  Move a document or folder to a different parent. Omit newParentId to move to project root.
* [**Move document batch**](./project-tree/move-document-batch) — `move_document_batch`\
  Move multiple documents/folders in one operation. Provide a shared newParentId to move all items to the same folder, or specify a per-item newParentId to move each to a different destination. Omit newParentId (both shared and per-item) to move to project root.
* [**Delete documents**](./project-tree/delete-documents) — `delete_documents`\
  Delete one or more documents/folders (and their children). THIS IS DESTRUCTIVE — only call after confirming with the user.
* [**Update documents meta batch**](./project-tree/update-documents-meta-batch) — `update_documents_meta_batch`\
  Update metadata (icon, emoji, name, description, reference) for one or more documents, folders, or projects in a single call. Each item targets either a documentId or a projectId. Icon: a Lucide icon name + HSL color string. Emoji: a Unicode unified code (hex). Set icon OR emoji — if both are provided, icon takes priority. To clear an existing icon/emoji, pass null for both.
* [**Duplicate documents**](./project-tree/duplicate-documents) — `duplicate_documents`\
  Duplicate one or more documents/folders in place (same parent, same project). Folders are duplicated recursively — every nested document and subfolder is copied. Each copy gets a fresh ID but keeps the same content, tables, and references.
* [**Copy documents to**](./project-tree/copy-documents-to) — `copy_documents_to`\
  Copy one or more documents/folders into a specific destination folder (or project root). Folders are copied recursively — every nested document and subfolder is included. The copies get fresh IDs but keep the same content, tables, and references.

## Editor

* [**Read document content**](./editor/read-document-content) — `read_document_content`\
  WHEN TO USE: You need raw TipTap JSON for programmatic manipulation. For reading/understanding content, prefer read\_document\_text instead. Read a document's full content as TipTap JSON by connecting to the live collaboration server. Returns the structured JSON tree with node types, attributes, marks, and text.
* [**Write document markdown**](./editor/write-document-markdown) — `write_document_markdown`\
  ⚠️ REPLACES ALL existing content with new Markdown-based content. To ADD content to an existing document, use append\_markdown\_to\_document instead.  Converts extended Markdown to TipTap JSON server-side — supports ALL HERO node types (headings, @clause, @title, @signature, callouts, columns, tabs, tables, inline atoms, charts, etc.). See the Extended Markdown Syntax section in the system prompt for the full syntax reference.
* [**Append markdown to document**](./editor/append-markdown-to-document) — `append_markdown_to_document`\
  Append content to the END of an existing document. Existing content is PRESERVED — new content is added after it. Use when the user asks to ADD, INSERT, or EXTEND a document (NOT rewrite it). Same extended Markdown syntax as write\_document\_markdown — see system prompt for reference.
* [**List document blocks**](./editor/list-document-blocks) — `list_document_blocks`\
  WHEN TO USE: Before calling patch\_document to get block IDs. List all blocks in a document with their blockId, type, and text excerpt. Use this to identify blocks before patching. Much more token-efficient than read\_document\_content for editing workflows.
* [**Patch document**](./editor/patch-document) — `patch_document`\
  Surgically edit a document by applying block-level operations. Each operation targets a specific block by its blockId (use list\_document\_blocks to find IDs first). Operations: replace, insertBefore, insertAfter, delete. Applied in order; partial success possible. Markdown field uses the same extended syntax as write\_document\_markdown — see system prompt.
* [**Create document snapshot**](./editor/create-document-snapshot) — `create_document_snapshot`\
  Create a named version/snapshot of a document's current state before making significant edits. Use this before large rewrites or restructures of documents OTHER than the user's active document. The snapshot appears in the document's version history and can be restored by the user.

## Placeholders

* [**Lookup table columns**](./placeholders/lookup-table-columns) — `lookup_table_columns`\
  Look up a table's columns by table name or ID. Returns column metadata (columnId, name, type, isIdentifier) so you can decide which columns to use as placeholders. Provide either tableName or tableId.
* [**Prepare placeholder references**](./placeholders/prepare-placeholder-references) — `prepare_placeholder_references`\
  Create TableReference entries for one or more columns so you can insert placeholderNode nodes in document content. Call this BEFORE generating document content that includes placeholderNode nodes. Returns a mapping of columnId to tableReferenceId that you must use as the tableReferenceId attribute on each placeholderNode. IMPORTANT: If you just created a new document, you MUST pass the documentId parameter with the new document's ID.
* [**Prepare global references**](./placeholders/prepare-global-references) — `prepare_global_references`\
  Create GLOBAL references (globalReferenceNode) pinned to ONE SPECIFIC row. Use this when a document must reference MULTIPLE DIFFERENT rows of the same table at once (e.g. Alice's email AND Bob's email, a roster, a comparison). Each reference is locked to the rowId you pass and is independent of the document's active row, so different references can point to different rows. Call lookup\_table\_rows first to get the rowId. Returns a mapping of columnId to tableReferenceId to use on globalReferenceNode nodes (markdown: \{\{globalref:ID}}). For the common case where ALL placeholders should share one row that the user can switch later, use prepare\_placeholder\_references instead. IMPORTANT: If you just created a new document, pass the documentId parameter with the new document's ID.
* [**Lookup table rows**](./placeholders/lookup-table-rows) — `lookup_table_rows`\
  Look up rows in a table. Returns each row's ID and identifier (primary key) value, plus a preview of cell values for the first few columns. Use this to find the correct rowId when the user references a specific record (e.g. 'the 2nd row' or 'David Smith').
* [**Update referenced row**](./placeholders/update-referenced-row) — `update_referenced_row`\
  Change which row the placeholders display for a given table in a document. Updates the ReferencedRowInDocument link so all existing placeholderNode nodes for that table show the new row's values. Use when the user wants to switch which record the placeholders point to.

## Tables — schema

* [**List project tables**](./tables-schema/list-project-tables) — `list_project_tables`\
  List all tables in a project with column summaries.
* [**Get table data**](./tables-schema/get-table-data) — `get_table_data`\
  Read the full data of a table: all rows with their cell values. Returns column schema and rows as maps of column name to value.
* [**Create table**](./tables-schema/create-table) — `create_table`\
  Create a new table with a name and an initial set of columns. Exactly ONE column must have isIdentifier: true — this is the primary key column (e.g. a person's name, a product title, an email). Choose the most meaningful unique field as the identifier. Valid column types: string, number, money, date, time, checkbox, select, multiSelect, email, url, phone, location, formula, linkCell, oneMany. For select/multiSelect columns: provide selectOptions (array of label strings) so the dropdown is pre-populated. For oneMany columns: provide linkedTableId (the \_id of the table to link to). The target table must already exist. For formula columns: just create the column, then use the set\_formula tool to configure the expression. For linkCell columns: just create the column — cell values are set individually via cell operations.
* [**Rename table**](./tables-schema/rename-table) — `rename_table`\
  Rename an existing table.
* [**Delete table**](./tables-schema/delete-table) — `delete_table`\
  Delete a table and all its data. DESTRUCTIVE — confirm with user first.
* [**Add column**](./tables-schema/add-column) — `add_column`\
  Add a new column to an existing table. Also creates empty cells for all existing rows. For select/multiSelect: provide selectOptions (array of label strings). For oneMany: provide linkedTableId. For formula: create the column, then use set\_formula separately.
* [**Update column**](./tables-schema/update-column) — `update_column`\
  Update a column's name, type, selectOptions, or linkedTableId. For select/multiSelect: pass selectOptions to replace the available options. For oneMany: pass linkedTableId to change the linked table.
* [**Delete column**](./tables-schema/delete-column) — `delete_column`\
  Delete a column and all its cells. DESTRUCTIVE — confirm first.

## Tables — data

* [**Add row**](./tables-data/add-row) — `add_row`\
  Add a SINGLE row to a table. For adding 2+ rows, use add\_row\_batch instead — it is faster and more reliable. Pass cellValues as an object mapping column names to values. For linked identifiers (cross-table references): pass an object \{"linkedTableId": "\<sourceTableId>", "linkedRowId": "\<sourceRowId>"} instead of a plain string. Use lookup\_table\_cells to discover source row IDs first. For oneMany columns: pass an array of row IDs from the linked table (resolved automatically).
* [**Add row batch**](./tables-data/add-row-batch) — `add_row_batch`\
  Add multiple rows to a table at once. Each item in `rows` is a map of column name → value. For linked identifiers: pass \{"linkedTableId": "...", "linkedRowId": "..."} instead of a plain string for the identifier column. This creates a cross-table reference. Use lookup\_table\_cells on the source table first to get the row IDs. For oneMany columns: pass an array of row IDs from the linked table (resolved automatically).
* [**Update cells**](./tables-data/update-cells) — `update_cells`\
  Update cell values for a specific row. Pass values as column name → new value. For linked identifiers: pass \{"linkedTableId": "...", "linkedRowId": "..."} to link to a row in another table.
* [**Batch update column**](./tables-data/batch-update-column) — `batch_update_column`\
  Apply a transformation to all cell values in a column. Supports operations: "set" (set all to a value), "add" (add a number), "subtract" (subtract a number), "multiply", "divide". Works with number, money, and checkbox columns.
* [**Delete row**](./tables-data/delete-row) — `delete_row`\
  Delete a row from a table. DESTRUCTIVE — confirm first.
* [**Lookup table cells**](./tables-data/lookup-table-cells) — `lookup_table_cells`\
  Look up cells in a table, returning cell IDs and row IDs alongside their values. Essential before setting linked identifiers, linkCell values, oneMany references, or formula expressions. For linked identifiers: use the returned rowId to build \{"linkedTableId": tableId, "linkedRowId": rowId}. Returns rows with \{ rowId, cells: \[\{ cellId, columnName, columnType, value, isIdentifier }] }.

## Tables — references

* [**Create table reference**](./tables-references/create-table-reference) — `create_table_reference`\
  Create a table reference linking a table column to a document. This enables placeholder values from the table to appear in the document. Returns reference IDs that the frontend uses to insert placeholder nodes.
* [**Get document table references**](./tables-references/get-document-table-references) — `get_document_table_references`\
  Get all table references (placeholder links) used within a document.
* [**Set formula**](./tables-references/set-formula) — `set_formula`\
  Configure a formula for a formula-type column. The expression uses column names wrapped in curly braces, e.g. "\{Salary} + \{Bonus}" or "\{Price} \* \{Quantity} - \{Discount}". The tool resolves column names to per-row cell IDs and computes initial results. Referenced columns must be number or money type. Supports +, -, \*, / and parentheses.

## Web

* [**Fetch url content**](./web/fetch-url-content) — `fetch_url_content`\
  Fetch and extract text content from a web URL. Returns clean text from HTML pages. Use this when the user provides a link and wants you to read or use its content.
* [**Search web**](./web/search-web) — `search_web`\
  Search the web for information. Returns results with titles, URLs, and snippets. Use when you need external information or to find a specific page.
* [**Web cache get meta**](./web/web-cache-get-meta) — `web_cache_get_meta`\
  Get metadata for a cached web document by id (length, title).
* [**Web cache read chunk**](./web/web-cache-read-chunk) — `web_cache_read_chunk`\
  Read a chunk of cached web document HTML by character range. Use iteratively for large documents.
* [**Web cache read tail**](./web/web-cache-read-tail) — `web_cache_read_tail`\
  Read the last N characters of a cached web document to verify and process tail content.

## Workflows

* [**Plan**](./workflows/plan) — `plan`\
  Create or update an execution plan with numbered steps. Call this BEFORE starting a multi-step task to show the user what you intend to do. You can call it again later to mark steps as completed or to revise the plan. The frontend renders this as a visual checklist.
* [**Finish with summary**](./workflows/finish-with-summary) — `finish_with_summary`\
  Call this when you have completed all requested work. Provide a brief summary of what was done. This signals to the frontend that the agent run is complete and renders a summary card. After calling this tool, do NOT call any more tools or produce additional content.

## Integrations — Gmail

* [**Gmail search**](./integrations-gmail/gmail-search) — `gmail_search`\
  Search the user's Gmail using Gmail's native query syntax. Returns message headers + snippets (NOT full bodies). Gmail query examples:   - `from:sarah@example.com` — messages from Sarah   - `subject:invoice newer_than:7d` — invoices from the last week   - `has:attachment filename:pdf` — PDFs   - `label:inbox is:unread` — unread inbox items   - `in:sent to:bob@example.com` — mail I sent to Bob   - Leave `query` empty to list the most recent messages. Follow up with `gmail_get_message` or `gmail_get_thread` to fetch full bodies.
* [**Gmail get message**](./integrations-gmail/gmail-get-message) — `gmail_get_message`\
  Fetch a single Gmail message with its full body text. Use the `id` returned by `gmail_search`. Returns headers, snippet, full plain-text body (capped at 10 KB), and a list of attachments with their IDs. Use `gmail_get_attachment` to read attachment contents.
* [**Gmail get thread**](./integrations-gmail/gmail-get-thread) — `gmail_get_thread`\
  Fetch an entire Gmail conversation thread given a `threadId` (from `gmail_search` results). Returns all messages in the thread with their full plain-text bodies (each capped at 5 KB) and attachment metadata. Use `gmail_get_attachment` to read specific attachments.
* [**Gmail get attachment**](./integrations-gmail/gmail-get-attachment) — `gmail_get_attachment`\
  Download and read the content of an email attachment from Gmail. Requires the `messageId` and `attachmentId` from the attachments list returned by `gmail_get_message` or `gmail_get_thread`. PDFs are extracted to text server-side. Text-based files (CSV, JSON, TXT, HTML, XML) are returned as text. All other formats (DOCX, XLSX, images, etc.) are returned as raw base64 for direct reading.

## Integrations — Google Drive

* [**Drive search**](./integrations-google-drive/drive-search) — `drive_search`\
  Search the user's Google Drive using Drive's native query syntax. Returns file metadata only (no content — follow up with `drive_get_file_content`). Drive query examples:   - `name contains 'invoice'` — name substring   - `fullText contains 'Q4 planning'` — full-text search of doc contents   - `mimeType = 'application/pdf'` — only PDFs   - `mimeType = 'application/vnd.google-apps.document'` — only native Google Docs   - `modifiedTime > '2026-01-01T00:00:00'` — modified after a date   - `'alice@example.com' in owners` — owned by Alice   - Combine with `and` / `or`: `name contains 'invoice' and mimeType = 'application/pdf'` The tool automatically appends `trashed = false` to every query. Leave `query` empty to list the most recently-modified files.
* [**Drive list folder**](./integrations-google-drive/drive-list-folder) — `drive_list_folder`\
  List files and subfolders directly inside a Google Drive folder. Pass the folder's id, or omit `folderId` to list the root.
* [**Drive get file content**](./integrations-google-drive/drive-get-file-content) — `drive_get_file_content`\
  Fetch the text content of a Drive file. Native Google Docs/Sheets/Slides are exported to plain text/CSV. Text files are fetched directly. PDFs and binary formats return an error — the model cannot read them. Content is truncated to 15 KB.

## Integrations — Outlook

* [**Outlook search**](./integrations-outlook/outlook-search) — `outlook_search`\
  Search the user's Outlook / Microsoft 365 mailbox via Microsoft Graph. Returns message headers + snippets (not full bodies — follow up with `outlook_get_message`). Two modes:   - `search` (free-text, KQL-like): `subject:invoice`, `from:sarah@example.com`, `hasattachment:yes`, `received:2026-01-01..2026-01-31`. Combine with spaces.   - `filter` (OData, precise): `from/emailAddress/address eq 'sarah@example.com'`, `receivedDateTime ge 2026-01-01T00:00:00Z`, `hasAttachments eq true`. Combine with `and`/`or`. Prefer `search` for natural-language queries; use `filter` when you need exact field matching or date ranges. Leave both empty for most-recent messages.
* [**Outlook get message**](./integrations-outlook/outlook-get-message) — `outlook_get_message`\
  Fetch a single Outlook message with its full body (capped at 10 KB). Use `id` from `outlook_search`. If the message has attachments, returns their IDs and metadata. Use `outlook_get_attachment` to read attachment contents.
* [**Outlook get conversation**](./integrations-outlook/outlook-get-conversation) — `outlook_get_conversation`\
  Fetch all Outlook messages in a conversation, sorted chronologically, with full bodies (each capped at 5 KB). Pass the `conversationId` from `outlook_search` results. Returns attachment metadata for each message. Use `outlook_get_attachment` to read specific attachments.
* [**Outlook get attachment**](./integrations-outlook/outlook-get-attachment) — `outlook_get_attachment`\
  Download and read the content of an email attachment from Outlook. Requires the `messageId` and `attachmentId` from the attachments list returned by `outlook_get_message` or `outlook_get_conversation`. PDFs are extracted to text server-side. Text-based files (CSV, JSON, TXT, HTML, XML) are returned as text. All other formats (DOCX, XLSX, images, etc.) are returned as raw base64 for direct reading.

## Integrations — OneDrive

* [**Onedrive search**](./integrations-onedrive/onedrive-search) — `onedrive_search`\
  Search the user's OneDrive for files by name and content. The query is a single free-text string — Graph matches it against filenames, content, and metadata. Returns file summaries (NOT content — follow up with `onedrive_get_file_content`).
* [**Onedrive list folder**](./integrations-onedrive/onedrive-list-folder) — `onedrive_list_folder`\
  List files and subfolders directly inside a OneDrive folder. Omit `folderId` to list the root.
* [**Onedrive get file content**](./integrations-onedrive/onedrive-get-file-content) — `onedrive_get_file_content`\
  Fetch the text content of a OneDrive file. Only text-like files (text/\*, json, xml, javascript) are supported. PDFs, Office docs, and binary formats return an error. Content is truncated to 15 KB.

## Integrations — Dropbox

* [**Dropbox search**](./integrations-dropbox/dropbox-search) — `dropbox_search`\
  Search the user's Dropbox by filename and (for supported text formats) content. Returns file/folder metadata. Follow up with `dropbox_get_file_content` for text content.
* [**Dropbox list folder**](./integrations-dropbox/dropbox-list-folder) — `dropbox_list_folder`\
  List files and subfolders inside a Dropbox path. Pass empty string for the Dropbox root.
* [**Dropbox get file content**](./integrations-dropbox/dropbox-get-file-content) — `dropbox_get_file_content`\
  Fetch the text content of a Dropbox file. Only text-like extensions are supported (txt, md, json, csv, log, yml, yaml, html, xml, common code files). PDFs and binary formats return an error. Content is truncated to 15 KB. `pathOrId` accepts either a Dropbox path (e.g. '/Documents/notes.md') or the file id from search results.

## Integrations — Notion

* [**Notion search**](./integrations-notion/notion-search) — `notion_search`\
  Search the user's Notion workspace for pages and databases by TITLE. IMPORTANT: Notion's search only matches titles, NOT page content. To search content, use `notion_query_database` against a specific database. To read a page, use `notion_get_page`.
* [**Notion get page**](./integrations-notion/notion-get-page) — `notion_get_page`\
  Fetch a Notion page's full content. Walks the top-level blocks and flattens them to plain text. Content is truncated to 15 KB. Use `id` from `notion_search` results.
* [**Notion query database**](./integrations-notion/notion-query-database) — `notion_query_database`\
  Query a Notion database with optional filter and sort. Returns rows (each is a Notion page) with their property values. Use this when the user asks for structured data like 'employees with role = engineer' or 'tasks due this week'. Get the `databaseId` from `notion_search` with filter=database. The `filter` and `sorts` arguments follow Notion's database query DSL — pass them as JSON strings. See [https://developers.notion.com/reference/post-database-query](https://developers.notion.com/reference/post-database-query) for the full schema.
