Skip to main content
Glama

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
PORTNoServer listen port.8322
FILES_DIRNoLocal file store path./data/files
SHARED_DIRNoPath to the cross-MCP shared mount./shared
NOTION_TOKENNoNotion internal integration token (starts with ntn_). Required.
DRIVE_ACCOUNTNoGoogle account email for Drive access (optional).
XBERG_BASE_URLNoBase URL for OCR delegation to an xberg server.http://xberg:8000
GOOGLE_CLIENT_IDNoOAuth client ID for Google Drive integration (optional).
MCP_BEARER_TOKENNoBearer token for authenticating MCP clients. Required for HTTP mode, not for stdio mode.
DRIVE_FOLDER_NAMENoShared Drive folder name.mcp-google-accounts
XBERG_VLM_API_KEYNoAPI key for the xberg VLM backend (optional).
NOTION_API_VERSIONNoNotion API version header.2026-03-11
GMAIL_TOKEN_DB_PATHNoLegacy alternative to GOOGLE_TOKEN_DB_PATH.
GOOGLE_CLIENT_SECRETNoOAuth client secret for Google Drive integration (optional).
GOOGLE_TOKEN_DB_PATHNoPath to google-accounts-mcp's SQLite token DB (read-only). Legacy GMAIL_TOKEN_DB_PATH is also honored./google-data/tokens.db

Capabilities

Features and capabilities supported by this server

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
notion_search_pagesA

Search Notion for pages the integration has access to. Returns titles and page IDs — use these IDs with notion_upload_file / list_files_on_page. The integration only sees pages explicitly shared with it in Notion. in_trash=True searches trashed pages instead of active ones (restore matches with notion_restore_page).

notion_search_databasesA

Search Notion for databases the integration has access to. Returns titles, IDs, and property schemas. Use the database ID with notion_query_database, notion_describe_database, or notion_create_page (with database_id).

The integration only sees databases explicitly shared with it in Notion.

notion_list_files_on_pageA

List all file/image/pdf/video/audio blocks on a Notion page. Returns block IDs and filenames — use block IDs with notion_download_file.

notion_purge_shared_filesA

Delete files from the cross-MCP shared mount (SHARED_DIR, /shared inside the container) whose modification time is older than max_age_hours. Use this to clean up attachments handed over from the companion google-accounts-mcp server once they've been uploaded to Notion.

A host-level TTL sweep (if you run one) makes this automatic; the tool is mainly for agents that want to clean up proactively at the end of a workflow without waiting for it.

Set dry_run=True to list victims without deleting. Only regular files are touched — subdirectories are left alone.

notion_purge_fileA

Delete a single file from the cross-MCP shared mount by bare filename. Use this after a successful upload to free the shared slot instead of waiting for the daily TTL sweep (or calling notion_purge_shared_files with max_age_hours=0, which would wipe any unrelated in-flight handoffs). Rejects any filename containing path separators.

notion_list_local_filesA

List files available to notion-mcp by scheme, so the agent can verify a handoff before attaching it to Notion.

location: • 'files' (default) — the notion-mcp private store under FILES_DIR. These are addressable as source='local:'. • 'shared' — the cross-MCP shared mount under SHARED_DIR. Files placed here by google-accounts-mcp (download_attachment with destination='shared') are addressable as source='shared:'.

Optional substring filter on the filename.

notion_upload_fileA

Upload a file to Notion and attach it as a new block.

source accepts one of: • local:<relative-path> — a file under the notion-mcp private store (FILES_DIR). List with notion_list_local_files. • shared:<filename> — a file on the shared cross-MCP mount, written there by google-accounts-mcp download_attachment with destination='shared'. List with notion_list_local_files(location='shared'). • drive:<name-or-id> — a file in the shared Drive folder (DRIVE_FOLDER_NAME) Google Drive folder (read from google-accounts-mcp's credentials, read-only). • base64:<bytes> — raw base64 content; requires filename. Subject to MCP parameter size limits — prefer shared: or drive: for anything over ~20KB.

parent_page_id is a Notion page ID (find via notion_search_pages) OR any block ID that supports children (toggle, column, callout, ...) to attach the file inside that block.

position controls where the new block lands among the parent's children: 'end' (default), 'start', or a block ID to insert directly AFTER that block (get block IDs from notion_read_page(include_block_ids=True) or notion_list_files_on_page).

filename overrides the source filename when provided. caption is shown below the file block in Notion. Files larger than 20 MB are uploaded via Notion's multi-part protocol automatically. To swap the file in an existing block without moving it, use notion_replace_file instead.

Cross-MCP file transfer

To upload a Gmail attachment to a Notion page:

  1. google-accounts-mcp download_attachment(..., destination='shared')

  2. notion_upload_file(source='shared:', parent_page_id=...) Files never traverse MCP parameters — no size limits.

notion_replace_fileA

Replace the file inside an EXISTING file/image/pdf/video/audio block, in place — the block keeps its position on the page. Use this to update a document without re-arranging anything; use notion_upload_file(position=...) to add a new block instead.

block_id: the file block to update (from notion_list_files_on_page or notion_read_page(include_block_ids=True)). source: same schemes as notion_upload_file (local:, shared:, drive:, base64:). caption: when non-empty, replaces the caption; when empty, the existing caption is left untouched.

The new file must map to the same block type as the existing block (e.g. you cannot replace an image block's content with a PDF — Notion blocks are typed). In that case delete the block and upload anew.

notion_import_file_from_urlA

Import a file into Notion directly from a public HTTPS URL — the bytes go Notion-side, never through this server or MCP parameters.

url must be publicly accessible over HTTPS. filename must carry an extension Notion accepts (it determines the block type). The import is asynchronous: this tool polls until the upload reaches a terminal status or wait_seconds elapses. parent_page_id and position behave as in notion_upload_file.

Size limits are plan-dependent (5 MiB free / 5 GiB paid). No sha256 is reported — the bytes never pass through this server; verify via notion_download_file if integrity matters.

notion_set_page_visualA

Set or remove a Notion page's icon or cover image.

target: 'icon' or 'cover'. Provide exactly one of: • emoji — a single emoji character (icon only), e.g. '📊'. • source — an image via the usual schemes (local:, shared:, drive:, base64:); uploaded and attached as the icon/cover. • remove=True — clear the icon/cover entirely.

notion_describe_databaseA

Retrieve a Notion database's schema. Returns each property name and type — use this to find the exact files & media column name to pass to notion_upload_file_to_database / notion_add_file_to_row.

database_id can be found by calling notion_list_files_on_page on the page that holds the inline database (child_database blocks will show), or pasted from the database URL.

notion_upload_file_to_databaseA

Upload a file and create a NEW row in a Notion database with the file attached to the given files & media column.

source: local:<path>, shared:<filename>, drive:<name-or-id>, or base64:<bytes> — see notion_upload_file for scheme details and the cross-MCP handoff pattern. files_property: exact name of the files & media column (e.g. "Files & media"). Use notion_describe_database to confirm the name — it is case-sensitive. title: text value for the row's title column. title_property: override the auto-detected title column name. filename: override the source filename.

notion_add_file_to_rowA

Upload a file and attach it to an EXISTING database row's files & media column.

page_id: the row (page) ID — paste from the row's "Copy link" or obtain via notion_search_pages. source: same schemes as notion_upload_file: local:<path>, shared:<filename>, drive:<name-or-id>, or base64:<bytes>. files_property: exact name of the files & media column. mode: append (default) keeps existing files and adds the new one. replace overwrites the column with just the new file. filename: override the source filename.

Cross-MCP file transfer

To attach a Gmail attachment to an existing Notion row:

  1. google-accounts-mcp download_attachment(msg_id, name, destination='shared')

  2. notion_add_file_to_row(page_id, source='shared:', files_property='')

Files never traverse MCP parameters — no size limits. Alternative via Drive: download_attachment → drive_upload(local_filename=...) → notion_add_file_to_row(source='drive:', ...).

notion_batch_add_file_to_rowA

Attach files to many existing Notion rows in one call.

items_json is a JSON array of objects. Each item takes the same shape as the single-shot tool's parameters::

[
  {"page_id": "...", "source": "shared:invoice1.pdf"},
  {"page_id": "...", "source": "shared:invoice2.pdf",
   "filename": "Renamed.pdf"},
  {"page_id": "...", "source": "drive:<id>",
   "files_property": "Attachments", "mode": "replace"}
]

default_files_property and default_mode fill in any item that omits those fields — pass them once at the batch level instead of repeating per item.

Items are uploaded with bounded concurrency (NOTION_BATCH_CONCURRENCY, default 3) so a batch of N finishes in roughly ceil(N/concurrency) waves rather than serially — a batch of ~8 used to exceed the client's 4-minute timeout when serial. Concurrent items targeting the SAME row are still serialised (the 'append' path is a read-modify-write). The 429/5xx backoff in the client absorbs any rate-limit bursts. Per-item failures are reported in the output (in input order) but do NOT abort the batch — use the per-item status to retry individual items.

Files are staged in the shared mount; the typical pattern is to stage N files via google-accounts-mcp download_attachment, call this tool once, then call notion_purge_file to remove each staged file.

notion_download_fileA

Download a file from a Notion file/image/pdf/video/audio block.

destination is one of: local, shared, drive, base64. • local — the notion-mcp private store (FILES_DIR). • shared — the cross-MCP shared mount, immediately attachable by google-accounts-mcp as attachments=['shared:'] on draft_email / send_email. 24h TTL applies. • drive — upload to the shared Drive folder (DRIVE_FOLDER_NAME). • base64 — inline; subject to MCP response size limits.

filename overrides the inferred name. When destination=local, filename may include subdirectories (e.g. reports/q3.pdf); they are created under the local store. Use notion_list_files_on_page to find block IDs.

Cross-MCP file transfer (Notion → Gmail)

To email a file stored in Notion:

  1. notion_download_file(block_id, destination='shared')

  2. google-accounts-mcp draft_email(..., attachments=['shared:']) Bytes never traverse MCP parameters — no size limits.

notion_extract_file_textA

Extract text from a PDF anywhere notion-mcp can reach — a file stored in Notion, the shared cross-MCP mount, the private store, or the Drive folder — without moving the bytes over MCP.

source schemes: 'notion:' (file/pdf block on a page — get block IDs from notion_list_files_on_page), 'shared:', 'local:', 'drive:'.

Returns JSON: {"text", "page_count", "pages_returned", "mode", "truncated", "filename"} (+ "ocr_used"/"ocr_pages"/"ocr_engine" when OCR ran). Response ceiling 200 KB — truncation happens on a page boundary with a trailing marker naming the pages to fetch next.

pages: pdftotext-style spec — None/"" (all), "3", "1-5", "1,3,5", "1-3,7". Out-of-range pages are silently dropped. mode: 'text' (flowing), 'layout' (preserve columns), 'tables' (extract_tables → markdown). Applies to native extraction only.

OCR (scanned / image-only PDFs) — delegated to the fleet xberg service (XBERG_BASE_URL env; pages rasterised locally, sent as PNGs): ocr='auto' (default) — pages whose native text is < 20 chars are OCR'd (tesseract backend, seconds/page). "ocr_error" in the response means OCR was needed but xberg was unreachable/failed. ocr='off' — native extraction only. ocr='force' — OCR every requested page (garbled font encodings). ocr='llm' — transcribe pages with a vision model (xberg vlm backend → LiteLLM; env: XBERG_VLM_API_KEY, optional XBERG_VLM_MODEL / XBERG_VLM_BASE_URL). Best for handwriting and messy tables; slower and metered.

notion_render_file_pageA

Render one page of a PDF (from Notion, shared, local, or Drive) as a viewable image. The default return is a real MCP image content block, so you SEE the page directly — for a scanned document this is often all you need. Use when notion_extract_file_text isn't enough: charts, stamps, layouts, visual validation.

source schemes as in notion_extract_file_text ('notion:', 'shared:', 'local:', 'drive:').

Set return_base64=True for a JSON envelope {"image_base64", "mime_type", "width", "height", "page", "page_count", "filename"} instead (for relaying bytes programmatically). Errors return a JSON string with an "error" key in both modes.

page: 1-indexed. max_width: 200..4000 px (default 1200). format: 'jpeg' (default) or 'png'. quality: JPEG 1..100 (default 75).

notion_read_pageA

Read a Notion page's properties and content as markdown.

Returns the page title, properties, and full block content rendered as readable markdown. Nested blocks (toggles, list children, columns) are fetched recursively up to max_depth levels.

page_id: Notion page ID (from notion_search_pages or a URL). max_depth: how many levels of nested blocks to fetch (1-5, default 3). include_block_ids: if True, each block line is suffixed with an HTML comment containing the block UUID, e.g. . Use these IDs with notion_update_block / notion_delete_block.

notion_create_pageA

Create a new Notion page with optional markdown content.

For a standalone page under another page, provide parent_page_id. For a database row, provide database_id and properties_json.

title: the page title. content: markdown text that becomes the page body. Supports headings, lists, quotes, code blocks, inline formatting. parent_page_id: ID of the parent page. database_id: ID of a database to add the row to. properties_json: JSON object of extra Notion properties (for database rows). Keys are property names, values are Notion API property value objects. icon: emoji character for the page icon (e.g. "🚀").

notion_update_pageA

Update a Notion page's title, icon, or other properties.

page_id: the page to update. title: new title (leave empty to keep current). properties_json: JSON object of properties to update. Keys are property names, values are Notion API property value objects. Omitted properties are left unchanged. icon: emoji for page icon, or "remove" to clear it.

notion_append_contentA

Append markdown content to an existing Notion page.

Parses the markdown into blocks and appends them to the end of the page. Supports: headings (# ## ###), bullet/numbered/to-do lists, quotes, fenced code blocks, dividers (---), paragraphs with inline formatting (bold, italic, code, strike, links).

page_id: the page to append to. content: markdown text to append.

notion_archive_pageA

Archive (soft-delete) a Notion page. The page can be restored from the Notion trash within 30 days using notion_restore_page.

page_id: the page to archive.

notion_restore_pageA

Restore an archived page from the Notion trash.

page_id: the archived page to restore.

notion_update_blockA

Update an existing block's text content.

block_id: ID of the block to update (from notion_read_page output). content: new text for the block (supports inline markdown). block_type: the block type (paragraph, heading_1, heading_2, heading_3, bulleted_list_item, numbered_list_item, to_do, quote, callout, toggle, code). If omitted, the block is fetched to detect it.

notion_delete_blockA

Delete a block from a Notion page. This removes the block and all its children. The deletion is permanent (blocks cannot be restored).

block_id: ID of the block to delete.

notion_query_databaseA

Query a Notion database with optional filter, sort, and pagination.

Returns matching rows with their properties. Use notion_describe_database first to see the schema and property names.

database_id: the database to query. filter_json: Notion API filter object as JSON. Example: {"property": "Status", "select": {"equals": "Done"}} Compound example: {"and": [ {"property": "Status", "select": {"equals": "Active"}}, {"property": "Priority", "number": {"greater_than": 3}} ]} sorts_json: JSON array of sort objects. Example: [{"property": "Due", "direction": "ascending"}] Use "ascending" or "descending". limit: page size (default 50, max 100 — Notion's hard cap). start_cursor: opaque cursor returned by a previous call. Pass it to fetch the next page. When the output shows next_cursor: <token> the result set has more rows; when it shows next_cursor: (end) you have reached the end. properties: optional comma-separated list of property names to include (e.g. "Gmail Message ID, Invoice, Status"). Slims the output dramatically when you only need a few columns. The title column is always shown. Unknown names are ignored silently so a caller can ask for a union across a few databases.

notion_create_databaseA

Create a new Notion database under a page.

parent_page_id: page to create the database under (it appears as an inline database on that page). title: database title. schema_json: JSON object mapping property names to their type config in Notion API format. A title property is required. Example: { "Name": {"title": {}}, "Status": {"select": {"options": [ {"name": "To Do", "color": "red"}, {"name": "Done", "color": "green"} ]}}, "Due Date": {"date": {}}, "Priority": {"number": {"format": "number"}}, "Tags": {"multi_select": {"options": [ {"name": "bug"}, {"name": "feature"} ]}}, "Assignee": {"people": {}}, "Done": {"checkbox": {}}, "Notes": {"rich_text": {}}, "Link": {"url": {}} }

notion_update_databaseA

Update a Notion database's title, description, or property schema.

database_id: the database to update. title: new database title (leave empty to keep current). description: new description (leave empty to keep current). properties_json: JSON object of property changes. Notion API format:

  • Add property: {"New Column": {"rich_text": {}}}

  • Remove property: {"Old Column": null}

  • Rename property: {"Old Column": {"name": "New Column"}}

  • Change type: {"Column": {"number": {"format": "percent"}}}

  • Add select opts: {"Status": {"select": {"options": [ {"name": "New Option", "color": "blue"} ]}}}

Multiple changes can be combined in one call. Use notion_describe_database first to see current schema.

notion_get_propertyA

Retrieve a single property from a Notion page with full pagination.

Useful for large properties (relations, rollups, long rich_text) that get truncated in the normal page response. Provide either property_name or property_id.

page_id: the page to read from. property_name: human-readable property name (looked up from page metadata). property_id: Notion property ID (from notion_describe_database schema). Takes precedence over property_name if both given.

notion_get_commentsA

Get all comments on a Notion page.

Returns comment text, author, and timestamps. Use this to read discussion threads on a page.

page_id: the page to get comments from.

notion_add_commentA

Add a comment to a Notion page or reply to a discussion thread.

page_id: the page to comment on. text: comment text. Sent as native API markdown — inline formatting, inline equations, and @mentions all work. discussion_id: if provided, the comment is a reply to this existing discussion thread. Get discussion IDs from notion_get_comments.

notion_update_commentA

Edit a comment previously created by this integration (Notion returns 404 for comments created by anyone else).

comment_id: from notion_get_comments or notion_add_comment. text: replacement text (native API markdown — inline formatting, equations, @mentions).

notion_delete_commentA

Delete a comment previously created by this integration (Notion returns 404 for comments created by anyone else).

comment_id: from notion_get_comments or notion_add_comment.

notion_list_viewsA

List the views defined on a Notion database — name, type, id, and whether each carries a saved filter/sorts. Use the view id with notion_query_view to run a view's saved filter, or with notion_update_view / notion_delete_view to manage it.

notion_query_viewA

Run a database view's saved filter and sorts, returning the matching rows (title + id + url). Use this instead of notion_query_database when the view already encodes the filter you want — no filter JSON needed.

view_id: from notion_list_views. limit: max rows to return (max 100).

notion_create_viewA

Create a view on a Notion database.

database_id: the database to add the view to. name: display name for the view. view_type: table | board | list | calendar | timeline | gallery | chart (default table). filter_json: optional Notion filter object as JSON (same shape as notion_query_database's filter_json). sorts_json: optional JSON array of sort objects.

notion_update_viewA

Update a view's name, saved filter, and/or sorts. Only provided fields change (fields left empty are preserved).

notion_delete_viewA

Delete a view from its database. The database and its rows are untouched — only the saved view configuration is removed.

notion_list_usersA

List all users in the Notion workspace.

Returns user names, IDs, emails, and types (person or bot). User IDs are needed for people properties and @mentions in comments.

notion_get_userA

Get details for a specific Notion user by ID.

Returns the user's name, email, avatar URL, and type. Use notion_list_users to find user IDs first.

user_id: Notion user UUID.

notion_read_page_markdownA

Read a Notion page's content as native Notion-flavored markdown.

Uses the direct markdown API endpoint — faster than block-by-block fetching and returns Notion's own markdown representation including special tags for databases, files, and embeds.

For block-level editing (update/delete individual blocks), use notion_read_page with include_block_ids=True instead.

page_id: Notion page ID.

notion_update_page_contentA

Edit page content using search-and-replace on the page's markdown.

Finds old_text in the page content and replaces it with new_text. Use notion_read_page_markdown first to see the current content and copy the exact text to replace.

page_id: the page to edit. old_text: exact text to find in the page content. new_text: replacement text (use empty string to delete).

notion_replace_page_contentA

Replace a page's entire content with new markdown.

Overwrites all existing content. Use notion_read_page_markdown first to see what's there. For targeted edits, use notion_update_page_content instead.

page_id: the page to replace content on. markdown: new page content in markdown format.

notion_move_pageA

Move a Notion page to a new parent page or database.

page_id: the page to move. new_parent_page_id: move under this page. new_parent_database_id: move into this database (as a new row). Only one of the two parent args should be set.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/snickery/notion-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server