{"$schema":"https://verifymcp.io/schemas/trust-report.json","schemaVersion":1,"license":{"name":"CC BY-NC 4.0","url":"https://creativecommons.org/licenses/by-nc/4.0/"},"generatedAt":"2026-11-05T17:00:41.042Z","url":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion","markdownUrl":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion.md","server":{"slug":"com-foreverworks-notion","name":"Notion","registryName":"com.foreverworks/notion","description":"Search, read and write your Notion workspaces, with pages as Markdown and typed database queries.","registryStatus":"active","deletedAt":null,"statusMessage":null,"liveness":"live","publisher":{"class":"unknown","claimed":false}},"component":{"slug":"foreverworks-mcp-notion","type":"npm","identifier":"@foreverworks/mcp-notion","withdrawn":false,"url":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion","version":"0.1.1","transport":"stdio","scoredAt":"2026-11-05T03:27:40.011Z"},"score":{"total":83,"tier":"high trust","status":"scored","weekDelta":3,"history":[{"date":"2026-11-05","total":83},{"date":"2026-11-04","total":83},{"date":"2026-11-03","total":82},{"date":"2026-11-02","total":82},{"date":"2026-11-01","total":81},{"date":"2026-10-31","total":66},{"date":"2026-10-30","total":81},{"date":"2026-10-29","total":80},{"date":"2026-10-28","total":80},{"date":"2026-10-27","total":79},{"date":"2026-10-26","total":79}]},"categories":[{"name":"Supply Chain Security","score":99,"verdict":"partial","reasons":["No malware found by supply-chain analysis.","No known CVEs affecting this package version or its production dependencies.","No install/post-install scripts declared.","7 of 23 dependencies flagged as unhealthy."],"codes":[{"code":"supplychain.malware_clean","args":{}},{"code":"cve.none","args":{}},{"code":"installscript.none","args":{}},{"code":"dephealth.assessed","args":{"deps":"23","unhealthy":"7"}}]},{"name":"Provenance & Transparency","score":100,"verdict":"pass","reasons":["Source repository is publicly reachable at the declared URL.","Cryptographically verified build provenance (signed, bound to foreverworks/mcps).","Clear OSI-approved license (MIT).","Actively maintained (last published 4 days ago).","Publishes a security disclosure policy (SECURITY.md)."],"codes":[{"code":"provenance.repo_verified","args":{}},{"code":"provenance.verified","args":{"repo":"foreverworks/mcps"}},{"code":"license.osi","args":{"spdx":"MIT"}},{"code":"maintenance.recent","args":{"age_days":"4"}},{"code":"disclosure.present","args":{}}]},{"name":"Schema Quality & AI Usability","score":61,"verdict":"fail","reasons":["AI-judged instruction clarity (good).","Context-footprint check failed: tool/resource definitions use about 5676 tokens (~210/item across 27 items; 27 tools + 0 resources), over budget; trim descriptions and params.","Usage-examples check failed: none of the tools include examples."],"codes":[{"code":"schema.ai_quality","args":{"band":"good"}},{"code":"schema.footprint_heavy","args":{"avg":"210","items":"27","tools":"27","tokens":"5676","resources":"0"}},{"code":"schema.examples_absent","args":{}}]},{"name":"Stability & Change Management","score":33,"verdict":"partial","reasons":["Stability observed for 10 of 30 days with no destabilising changes; credit accrues until the full window elapses."],"codes":[{"code":"stability.building_history","args":{"days":"10"}}]},{"name":"Tool Coverage","score":100,"verdict":"partial","reasons":["100% of tools have a non-trivial description (not blank, and not just the tool's name).","98% of tool parameters carry a description.","Structured output schemas are declared (7% of tools); any adoption earns full credit."],"codes":[{"code":"toolquality.descriptions","args":{"pct":"100"}},{"code":"toolquality.param_docs","args":{"pct":"98"}},{"code":"toolquality.output_present","args":{"pct":"7"}}]},{"name":"Tool Safety","score":100,"verdict":"pass","reasons":["No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.","We read all 27 captured tool definition(s), and no name or description among them implies an irreversible operation.","An AI judge read all 28 captured unit(s) of tool text and found none that tries to manipulate the model reading it."],"codes":[{"code":"toolsafety.injection_clean","args":{}},{"code":"toolsafety.destructive_none","args":{"tools":"27"}},{"code":"toolsafety.manipulation_clean","args":{"units":"28","judged":"28"}}]},{"name":"Capabilities","score":100,"verdict":"pass","reasons":["Implements a current MCP spec version (2026-07-28)."],"codes":[{"code":"protocol.current","args":{"version":"2026-07-28"}}]}],"inconclusive":[],"malware":[],"components":[{"slug":"foreverworks-mcp-notion","type":"npm","identifier":"@foreverworks/mcp-notion","withdrawn":false,"score":83,"current":true,"url":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion","markdownUrl":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion.md"}],"facts":[{"label":"Registry","value":"npm"},{"label":"Package","value":"@foreverworks/mcp-notion"},{"label":"Version","value":"0.1.1"},{"label":"Transport","value":"stdio"}],"install":{"available":true,"bundleSha256":null},"tools":[{"name":"add_column","title":"Add a column","description":"Add a column to a database: a name it does not have yet, a type, and that type's settings (options, a number's format, a formula's expression, a relation's target). Checked against the table as it is now before anything is sent; answers the column as Notion made it. Renaming and deleting columns are left to Notion's app.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"column","type":"object","required":true,"description":null},{"name":"database","type":"string","required":true,"description":"The database: its id, its Notion URL, or the dataSourceId search returned for it."},{"name":"source","type":"string","required":false,"description":"Which table, only when the database holds several (describe_database lists them): its name or id."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":175},{"name":"add_comment","title":"Add a comment","description":"A comment on a page, or a reply in one of its discussions, shown in Notion as the workspace's integration. Not resent after a lost answer (outcome_unknown): get_comments says whether it arrived.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"discussion","type":"string","required":false,"description":"A discussionId from get_comments, to reply in that thread. Default: a new comment on the page."},{"name":"markdown","type":"string","required":true,"description":"The comment, in Markdown."},{"name":"page","type":"string","required":true,"description":"The page: its id, or its Notion URL (a row of a database is a page too)."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":150},{"name":"add_options","title":"Add options to a column","description":"Add options to a select, multi-select or status column (a status option in a group: To-do, In progress, Complete). The options already there are kept and sent back by id, and the column is read back after: an option that went missing fails the call. Names already there are skipped and listed under alreadyThere. For one new option while writing a row, create_page's allow_new_options is enough.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"column","type":"string","required":true,"description":"A select, multi-select or status column, by name."},{"name":"database","type":"string","required":true,"description":"The database: its id, its Notion URL, or the dataSourceId search returned for it."},{"name":"group","type":"string","required":false,"description":"Status only: the group the new options go in. Default: To-do."},{"name":"options","type":"array","required":true,"description":"The options to add; one already there is left as it is."},{"name":"source","type":"string","required":false,"description":"Which table, only when the database holds several (describe_database lists them): its name or id."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":237},{"name":"append_content","title":"Add to a page","description":"Markdown added to a page's body: at the end (default), at the start, or after a passage. Not resent after a lost answer: that is outcome_unknown, and read_page says whether it went through.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"after","type":"string","required":false,"description":"Or after a passage, named \"first words...last words\" as it reads in the page."},{"name":"at","type":"string","required":false,"description":"Where it goes."},{"name":"markdown","type":"string","required":true,"description":"Notion's Markdown: headings, lists, to-dos (- [ ]), quotes, code, tables, callouts."},{"name":"page","type":"string","required":true,"description":"The page: its id, or its Notion URL (a row of a database is a page too)."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":178},{"name":"count_rows","title":"Count rows","description":"How many rows match where, and with by, how many hold each value of one column (\"how many tasks per status\"), most first; an empty value counts as \"(empty)\", and a multi-select row counts once per option. Reads the matching rows without sending them, up to Notion's 10,000 per query.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"by","type":"string","required":false,"description":"A column to count by: rows per option, per value, per related page."},{"name":"database","type":"string","required":true,"description":"The database: its id, its Notion URL, or the dataSourceId search returned for it."},{"name":"in_trash","type":"boolean","required":false,"description":"Rows in Notion's trash instead of the live ones."},{"name":"match","type":"string","required":false,"description":"Whether a row must meet all the conditions in where, or any of them."},{"name":"notion_filter","type":"object","required":false,"description":"Notion's own filter object, for what where cannot say (nested and/or, rollups). ANDed with where when both are given."},{"name":"source","type":"string","required":false,"description":"Which table, only when the database holds several (describe_database lists them): its name or id."},{"name":"where","type":"array","required":false,"description":"Conditions on the columns, exactly as query_database's where takes them."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":279},{"name":"create_database","title":"Create a database","description":"Create a database under a page, with a title column and the other columns given, each checked against the others before anything is made (and a relation's target found in the same workspace). Answers its id, URL and table. A database is not created twice: if the answer is lost it is outcome_unknown, and search says whether it exists.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"columns","type":"array","required":false,"description":"Its other columns, as add_column takes one."},{"name":"inline","type":"boolean","required":false,"description":"Shown inside the page's body rather than as a page of its own."},{"name":"parent","type":"string","required":true,"description":"The page it goes under: its id or Notion URL."},{"name":"title","type":"string","required":true,"description":"The database's title."},{"name":"title_column","type":"string","required":false,"description":"The name of its title column, which every row is known by. Default: Name."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":202},{"name":"create_page","title":"Create a page","description":"A new row in a database, its properties checked against the columns first (an unknown column or option is refused with the ones that exist), a child page under a page, or with no parent a private page at the top of a workspace (a title and a body, no properties). The body is Notion's Markdown. A row can start from one of its database's templates (template): Notion applies it just after the page is made, so read_page a moment later shows what it filled in. Answers the new page's workspace, id and URL. A page is not created twice: if the answer is lost it is outcome_unknown, and search or query_database says whether it exists.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"allow_new_options","type":"boolean","required":false,"description":"Let a select or multi-select value add an option the column does not have yet. A status can never be added."},{"name":"icon","type":"string","required":false,"description":"An emoji for the page's icon."},{"name":"markdown","type":"string","required":false,"description":"The body, in Notion's Markdown. Notion takes a leading '# ' heading as the title, so start the body below it."},{"name":"parent","type":"string","required":false,"description":"Where it goes: a database (id, URL or dataSourceId) for a new row, or a page for a child page. Leave it out for a private page at the top level of the workspace account names."},{"name":"properties","type":"object","required":false,"description":"Column name -> value, checked against the database's columns (describe_database). Text and title: a string. Number: a number. Select and status: an existing option's name. Multi-select: a list of nam…"},{"name":"source","type":"string","required":false,"description":"Which table, only when the database holds several (describe_database lists them): its name or id."},{"name":"template","type":"string","required":false,"description":"For a row: \"default\" for the database's default template, or a template's name or id (list_database_templates). Notion fills the row's body and properties from it just after making it; properties giv…"},{"name":"title","type":"string","required":false,"description":"The title. For a row, this fills the database's title column."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":543},{"name":"describe_database","title":"Describe a database","description":"A database's columns: name, type, the options of a select, multi-select or status (with a status's groups), where a relation points, a formula's expression. Read it before writing where, sort or properties: every one of those names these columns. A database holding several tables (data sources) lists each.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"database","type":"string","required":true,"description":"The database: its id, its Notion URL, or the dataSourceId search returned for it."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":132},{"name":"download_files","title":"Download a page's files","description":"Save the files Notion hosts for a page to this server's outbox: its files columns and the file blocks of its body (up to 50 MiB each). Answers each file's path, size and SHA-256, and where it was on the page. External links are listed, not fetched. A file that fails is listed with why, beside the others.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"body","type":"boolean","required":false,"description":"Also the files in the page's body: file, image, PDF, video and audio blocks, nested ones included."},{"name":"column","type":"string","required":false,"description":"Only this files column; the body is then left alone."},{"name":"page","type":"string","required":true,"description":"The page: its id, or its Notion URL (a row of a database is a page too)."},{"name":"save_dir","type":"string","required":false,"description":"A folder inside the outbox, e.g. \"2026-10/contracts\". Default: a folder named after the page's id."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":226},{"name":"edit_content","title":"Edit a page","description":"Find and replace in a page's body, in its Markdown as read_page shows it. The smallest change that does the job: the rest of the page, its comments and its history stay as they were. Not resent after a lost answer: that is outcome_unknown, and read_page says whether it went through.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"allow_deleting","type":"boolean","required":false,"description":"Let the change remove child pages or databases inside the page. Off, Notion refuses such a change."},{"name":"edits","type":"array","required":true,"description":"Find-and-replace pairs, applied in order."},{"name":"page","type":"string","required":true,"description":"The page: its id, or its Notion URL (a row of a database is a page too)."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":175},{"name":"get_comments","title":"Get comments","description":"The open comments on a page, oldest first, each with its discussion, author, time and text. Resolved ones are not listed by Notion.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"cursor","type":"string","required":false,"description":"nextCursor from the previous call, exactly as it came back, to read on."},{"name":"limit","type":"integer","required":false,"description":"Comments per call."},{"name":"page","type":"string","required":true,"description":"The page: its id, or its Notion URL (a row of a database is a page too)."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":131},{"name":"health","title":"Health","description":"Ask each workspace: is its integration token accepted, which workspace and integration it is, and whether it sees any page at all (a new integration sees nothing until pages are shared with it). One broken workspace never hides the others' answers. Run this before concluding the server is broken.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":95},{"name":"list_accounts","title":"List accounts","description":"The Notion workspaces this server reaches, by label (one per token file), from the token files alone: no request to Notion. Every other tool finds an id's workspace by itself, so a label is needed only to narrow a search. Says nothing about whether a token works; that is health.","inputs":[],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":71},{"name":"list_database_templates","title":"List database templates","description":"The page templates of a database or data source, with their page ids, names and default flags. Use this catalog to distinguish templates from ordinary rows; search can return both. Inspect their pages before editing recurring content. Follow nextCursor when hasMore is true.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"cursor","type":"string","required":false,"description":"nextCursor from the previous call, exactly as it came back, to read on."},{"name":"database","type":"string","required":true,"description":"The database: its id, its Notion URL, or the dataSourceId search returned for it."},{"name":"limit","type":"integer","required":false,"description":null},{"name":"source","type":"string","required":false,"description":"Which table, only when the database holds several (describe_database lists them): its name or id."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":175},{"name":"list_users","title":"List users","description":"The people (and bots) of every workspace, or of the one account names: each one's id, name, and email when the token may read it. A person column's where takes a name or an email directly, so this is for checking who is who, or for the id when two people share a name.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"query","type":"string","required":false,"description":"Words in a name or an email. Leave it out to list everyone."}],"outputs":[{"name":"failed","type":"object","required":false,"description":"Workspaces that could not be read, with why"},{"name":"users","type":"array","required":true,"description":null}],"hasOutputSchema":true,"hasExamples":false,"tokenEstimate":125},{"name":"list_views","title":"List a database's views","description":"A database's saved views (table, board, calendar, ...): each one's id, name, type, the table it shows, and the filter and sorts saved in it, in Notion's query grammar with columns by name. Use it to find the view a person means (\"my Open tasks\"), then query_view to read its rows exactly as Notion shows them.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"database","type":"string","required":true,"description":"The database: its id, its Notion URL, or the dataSourceId search returned for it."},{"name":"source","type":"string","required":false,"description":"Which table, only when the database holds several (describe_database lists them): its name or id."}],"outputs":[{"name":"account","type":"string","required":true,"description":null},{"name":"database","type":"string","required":true,"description":null},{"name":"source","type":"string","required":false,"description":"The table the views were narrowed to"},{"name":"views","type":"array","required":true,"description":null}],"hasOutputSchema":true,"hasExamples":false,"tokenEstimate":167},{"name":"move_page","title":"Move a page","description":"Under another page, or into a database as a row. Only within the page's own workspace: Notion cannot move a page between workspaces.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"page","type":"string","required":true,"description":"The page: its id, or its Notion URL (a row of a database is a page too)."},{"name":"source","type":"string","required":false,"description":"Which table, only when the database holds several (describe_database lists them): its name or id."},{"name":"to","type":"string","required":true,"description":"The new parent: a page, or a database (the page becomes a row). Same workspace only."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":150},{"name":"query_database","title":"Query a database","description":"Rows of a database, filtered by where (checked against the columns first), sorted, with the columns asked for. Each row is its id, its title and its non-empty columns as plain values. A relation lists its first 25 pages here (truncated names it); read_page lists them all. nextCursor reads on; Notion stops one query at 10,000 rows (incomplete says so). Works on the Free plan, unlike the hosted connector's SQL query.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"cursor","type":"string","required":false,"description":"nextCursor from the previous call, exactly as it came back, to read on."},{"name":"database","type":"string","required":true,"description":"The database: its id, its Notion URL, or the dataSourceId search returned for it."},{"name":"in_trash","type":"boolean","required":false,"description":"Rows in Notion's trash instead of the live ones."},{"name":"limit","type":"integer","required":false,"description":"Rows to return; more than 100 are read 100 at a time."},{"name":"match","type":"string","required":false,"description":"Whether a row must meet all the conditions in where, or any of them."},{"name":"notion_filter","type":"object","required":false,"description":"Notion's own filter object, for what where cannot say (nested and/or, rollups). ANDed with where when both are given."},{"name":"properties","type":"array","required":false,"description":"The columns to return, by name; the title always comes back. Default: all."},{"name":"sort","type":"array","required":false,"description":"The order, first key first. Default: Notion's (the database's own order)."},{"name":"source","type":"string","required":false,"description":"Which table, only when the database holds several (describe_database lists them): its name or id."},{"name":"where","type":"array","required":false,"description":"Conditions on the columns, e.g. [{\"property\": \"Status\", \"op\": \"equals\", \"value\": \"In progress\"}]. The column type comes from the schema."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":403},{"name":"query_view","title":"Query a saved view","description":"The rows a saved view shows, in its order, filtered and sorted exactly as Notion applies the view (quick filters and 'me' included), with total, the number of rows the view holds. Each row is its id, title and non-empty columns as query_database answers them. Notion keeps a view's result about 15 minutes: nextCursor reads on in that same result, and after that a new call without cursor starts again. A view takes no extra filter: for that, query_database with where.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"cursor","type":"string","required":false,"description":"nextCursor from the previous call, exactly as it came back, to read on."},{"name":"limit","type":"integer","required":false,"description":"Rows to return. Each row is one more request, so read a long view in pages."},{"name":"properties","type":"array","required":false,"description":"The columns to keep in each row, by name; the title always comes back. Default: all."},{"name":"view","type":"string","required":true,"description":"The view: its id from list_views, or the view's own Notion link (it carries ?v=)."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":249},{"name":"read_blocks","title":"Read blocks","description":"The blocks directly inside a page or a block, in order, one level down: each one's id, type and plain text, and hasChildren when it holds more (read those by its id). An AI meeting-notes block answers its title, status, recording and calendar times, and the ids of the blocks that hold its summary, notes and transcript, each readable here in turn. A type the API does not support says its Notion name under unsupported. For a page's body as one text, read_page is cheaper.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"block","type":"string","required":true,"description":"The page or block: its id, or a Notion URL. A URL's #fragment names a block inside the page, and that block is the one read."},{"name":"cursor","type":"string","required":false,"description":"nextCursor from the previous call, exactly as it came back, to read on."},{"name":"limit","type":"integer","required":false,"description":"Blocks to return; more than 100 are read 100 at a time."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":231},{"name":"read_page","title":"Read a page","description":"One page by id or URL, in whichever workspace has it: its title, parent and properties as plain values (a select is its option's name, a relation its page ids, all of them), and its body as Notion's Markdown. Empty properties are left out. A body past Notion's limit (~20,000 blocks) comes back cut, with contentTruncated and the ids of the parts left out, each readable as a page. A database's id is refused: use describe_database.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"content","type":"boolean","required":false,"description":"Include the body as Markdown. false reads the properties alone, which is cheaper."},{"name":"include_transcript","type":"boolean","required":false,"description":"For a meeting-notes page, include the transcript."},{"name":"page","type":"string","required":true,"description":"The page: its id, or its Notion URL (a row of a database is a page too)."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":211},{"name":"replace_content","title":"Replace a page's body","description":"A page's whole body, replaced by this Markdown. Properties are untouched. Child pages and databases in the body are kept unless allow_deleting. An empty body needs clear: true. Answers with the page's title and how many blocks its body held before and after; check both. Prefer edit_content for a change to part of a page.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"allow_deleting","type":"boolean","required":false,"description":"Let the change remove child pages or databases inside the page. Off, Notion refuses such a change."},{"name":"clear","type":"boolean","required":false,"description":"Empty the body on purpose, with markdown \"\". Without it an empty markdown is refused, since it would erase the page."},{"name":"markdown","type":"string","required":true,"description":"Notion's Markdown: headings, lists, to-dos (- [ ]), quotes, code, tables, callouts. The page's new body; empty only with clear."},{"name":"page","type":"string","required":true,"description":"The page: its id, or its Notion URL (a row of a database is a page too)."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":237},{"name":"restore_page","title":"Restore a page","description":"Out of Notion's trash, back where it was. Notion's API cannot restore a page from the top level of a workspace (it answers a validation error); that one is restored from the Trash in Notion.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"page","type":"string","required":true,"description":"The page: its id, or its Notion URL (a row of a database is a page too)."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":112},{"name":"search","title":"Search","description":"Pages and databases by title, in every workspace at once unless account names one. Notion matches words in titles, not in page bodies. Each hit says its workspace, kind, id and parent; a database hit also carries the dataSourceId of its table. Only what is shared with the workspace's integration can be found. A workspace that fails is listed under failed, beside the others' hits.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"cursor","type":"string","required":false,"description":"nextCursor from the previous call, exactly as it came back, to read on."},{"name":"kind","type":"string","required":false,"description":"Only pages, or only databases."},{"name":"limit","type":"integer","required":false,"description":"Hits per workspace; across several workspaces, up to this many from each."},{"name":"query","type":"string","required":false,"description":"Words in the title. Leave it out to list everything, newest edit first."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":199},{"name":"trash_page","title":"Trash a page","description":"Into Notion's trash, with everything under it. Direct deletion of database templates is refused unless allow_template is explicit. Notion keeps trash 30 days; restore_page brings it back.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"allow_template","type":"boolean","required":false,"description":"Explicitly allow removing a database template after checking its role in list_database_templates."},{"name":"page","type":"string","required":true,"description":"The page: its id, or its Notion URL (a row of a database is a page too)."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":128},{"name":"update_page","title":"Update a page","description":"Change a page's properties (a row's columns, checked against the database's schema; a page's title as properties: {title: ...}) and its icon. Only the columns named change. Answers the page as read_page does, without the body. The body is changed with append_content, edit_content and replace_content.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"allow_new_options","type":"boolean","required":false,"description":"Let a select or multi-select value add an option the column does not have yet. A status can never be added."},{"name":"icon","type":null,"required":false,"description":"An emoji for the page's icon; null removes it."},{"name":"page","type":"string","required":true,"description":"The page: its id, or its Notion URL (a row of a database is a page too)."},{"name":"properties","type":"object","required":false,"description":"Column name -> value, as create_page's properties take them; only the columns named change. A page under a page: {title: ...}."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":217},{"name":"upload_file","title":"Upload a file to a page","description":"Upload a file to Notion and attach it to a page: to one of a row's files columns, or as a block at the end of the page's body (an image, PDF, video or sound shows as such). The file goes by path, never as text you type. Answers with its size and SHA-256 as sent: compare them with the source. A column's own Notion-hosted files are kept unless the API cannot write them back, which is refused unless replace says so; nothing is uploaded before every check passes.","inputs":[{"name":"account","type":"string","required":false,"description":"Workspace: a label list_accounts names (\"*\": every one). Rarely needed: an id or URL finds its own."},{"name":"column","type":"string","required":false,"description":"A files column of the row to add it to, after the files already there. Leave it out to put it in a block at the end of the page's body."},{"name":"file","type":"object","required":true,"description":"The file, up to 20 MiB (Notion's Free plan takes 5 MiB a file). Never type or paste a file's base64 yourself: a retyped file can arrive changed. Give the path of a file in your workspace folders (the…"},{"name":"name","type":"string","required":false,"description":"The name Notion shows. Default: the file's own name."},{"name":"page","type":"string","required":true,"description":"The page: its id, or its Notion URL (a row of a database is a page too)."},{"name":"replace","type":"boolean","required":false,"description":"With column: drop the column's Notion-hosted files, which the API cannot write back. Its external links are always kept."}],"outputs":[],"hasOutputSchema":false,"hasExamples":false,"tokenEstimate":360}],"toolsTruncatedAtCapture":false,"diagnostics":{"capturedAt":"2026-11-05T03:27:40.000Z","track":"package","endpoint":null,"declaredUrl":null,"truncated":false,"tls":null,"dnssec":null,"auth":null,"httpsRedirect":null,"transports":[],"provenance":{"outcome":"verified","label":"Verified","reason":"verified","reasonLabel":"Verified","discovery":"attestation_endpoint","discoveryLabel":"Registry attestation endpoint","sourceRepo":null,"attestationSkipped":null,"attestationSkippedLabel":null},"installScripts":[],"installScriptsTotal":null,"vulnerabilities":[],"vulnerabilitiesTotal":null,"dependencies":{"nodes":23,"partial":false,"deprecated":null,"stale":7,"noRepo":null}},"mismatches":[],"changelog":{"trackingSince":"2026-10-26","recent":[{"id":"chg_01a1a497-d30e-7d8b-b719-53c98e756979","kind":"score.total_changed","summary":"Trust score (82 → 83)","materiality":"functional","direction":"improvement","scoreDelta":1,"occurredOn":"2026-11-04","url":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion#chg-chg_01a1a497-d30e-7d8b-b719-53c98e756979"},{"id":"chg_01a19a42-59b0-7e4a-ba5b-ba546158c5c0","kind":"score.total_changed","summary":"Trust score (81 → 82)","materiality":"functional","direction":"improvement","scoreDelta":1,"occurredOn":"2026-11-02","url":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion#chg-chg_01a19a42-59b0-7e4a-ba5b-ba546158c5c0"},{"id":"chg_01a1951c-8ab4-78dd-a1fe-26091ccfa876","kind":"check.reverified","summary":"Malware scan (unverified → pass)","materiality":"security","direction":"improvement","scoreDelta":null,"occurredOn":"2026-11-01","url":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion#chg-chg_01a1951c-8ab4-78dd-a1fe-26091ccfa876"},{"id":"chg_01a1951c-8abd-716e-8444-6db03f25c814","kind":"score.total_changed","summary":"Trust score (66 → 81)","materiality":"functional","direction":"improvement","scoreDelta":15,"occurredOn":"2026-11-01","url":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion#chg-chg_01a1951c-8abd-716e-8444-6db03f25c814"},{"id":"chg_01a1922f-ccbf-78f9-809e-9ab6a5eab1ac","kind":"check.unverifiable","summary":"Malware scan (pass → unverified)","materiality":"security","direction":"regression","scoreDelta":null,"occurredOn":"2026-10-31","url":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion#chg-chg_01a1922f-ccbf-78f9-809e-9ab6a5eab1ac"},{"id":"chg_01a1922f-ccc1-7272-8290-5021fbe1df37","kind":"package.version_changed","summary":"Package version (0.1.0 → 0.1.1)","materiality":"functional","direction":"neutral","scoreDelta":null,"occurredOn":"2026-10-31","url":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion#chg-chg_01a1922f-ccc1-7272-8290-5021fbe1df37"},{"id":"chg_01a1922f-ccc1-79d4-9aa9-e1894fda2f69","kind":"score.total_changed","summary":"Trust score (81 → 66)","materiality":"functional","direction":"regression","scoreDelta":-15,"occurredOn":"2026-10-31","url":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion#chg-chg_01a1922f-ccc1-79d4-9aa9-e1894fda2f69"},{"id":"chg_01a18acd-72de-723e-a3e2-b051a69448bd","kind":"score.total_changed","summary":"Trust score (80 → 81)","materiality":"functional","direction":"improvement","scoreDelta":1,"occurredOn":"2026-10-30","url":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion#chg-chg_01a18acd-72de-723e-a3e2-b051a69448bd"},{"id":"chg_01a18080-3f9f-7a48-8026-4375a7dffd90","kind":"score.total_changed","summary":"Trust score (79 → 80)","materiality":"functional","direction":"improvement","scoreDelta":1,"occurredOn":"2026-10-28","url":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion#chg-chg_01a18080-3f9f-7a48-8026-4375a7dffd90"},{"id":"chg_01a176ff-28ca-7a63-96e2-38637ad59a0c","kind":"score.first_scored","summary":"First indexed and scored","materiality":"functional","direction":"neutral","scoreDelta":null,"occurredOn":"2026-10-26","url":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion#chg-chg_01a176ff-28ca-7a63-96e2-38637ad59a0c"},{"id":"chg_01a176d1-82a6-7c9c-a54c-4b34fb1ec5a3","kind":"score.first_scored","summary":"First indexed and scored","materiality":"functional","direction":"neutral","scoreDelta":null,"occurredOn":"2026-10-26","url":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion#chg-chg_01a176d1-82a6-7c9c-a54c-4b34fb1ec5a3"}],"truncated":false,"feedUrl":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion/changelog.json"},"links":{"html":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion","markdown":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion.md","changelogJson":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion/changelog.json","changelogRss":"https://verifymcp.io/servers/com-foreverworks-notion/foreverworks-mcp-notion.xml","external":[{"label":"npm package","href":"https://www.npmjs.com/package/@foreverworks/mcp-notion"},{"label":"Socket report","href":"https://socket.dev/npm/package/@foreverworks/mcp-notion"},{"label":"Repository","href":"https://github.com/foreverworks/mcps"},{"label":"Website","href":"https://foreverworks.github.io/mcps/servers/notion/"}]}}