@n24q02m/better-notion-mcp 1.1.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -0
- package/bin/cli.mjs +6 -112
- package/build/src/docs/blocks.md +41 -0
- package/build/src/docs/comments.md +30 -0
- package/build/src/docs/content_convert.md +23 -0
- package/build/src/docs/databases.md +56 -0
- package/build/src/docs/pages.md +51 -0
- package/build/src/docs/users.md +36 -0
- package/build/src/docs/workspace.md +38 -0
- package/build/src/init-server.d.ts.map +1 -1
- package/build/src/init-server.js +2 -1
- package/build/src/init-server.js.map +1 -1
- package/build/src/tools/registry.d.ts.map +1 -1
- package/build/src/tools/registry.js +78 -108
- package/build/src/tools/registry.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -77,6 +77,27 @@ Get your Notion token: <https://www.notion.so/my-integrations> → Create integr
|
|
|
77
77
|
|
|
78
78
|
---
|
|
79
79
|
|
|
80
|
+
## Token Optimization (v2)
|
|
81
|
+
|
|
82
|
+
**~77% token reduction** via tiered descriptions:
|
|
83
|
+
|
|
84
|
+
| Tier | Purpose | Token Cost |
|
|
85
|
+
|------|---------|------------|
|
|
86
|
+
| **Tier 1** | Compressed descriptions (always loaded) | ~340 tokens |
|
|
87
|
+
| **Tier 2** | Full docs via `help` tool (on-demand) | ~1,500 tokens |
|
|
88
|
+
| **Tier 3** | MCP Resources (for supported clients) | Same as Tier 2 |
|
|
89
|
+
|
|
90
|
+
**Usage:**
|
|
91
|
+
```json
|
|
92
|
+
{"name": "help", "tool_name": "pages"}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Client Compatibility:**
|
|
96
|
+
- Claude Desktop, VS Code Copilot: Full support (Tier 1 + 2 + 3)
|
|
97
|
+
- Cursor, Windsurf: Via `help` tool (Tier 1 + 2)
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
80
101
|
## Limitations
|
|
81
102
|
|
|
82
103
|
**Supported Block Types (Markdown Conversion):**
|
package/bin/cli.mjs
CHANGED
|
@@ -1,117 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'module';const require = createRequire(import.meta.url);
|
|
3
|
-
import{Server as
|
|
3
|
+
import{Server as ke}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as xe}from"@modelcontextprotocol/sdk/server/stdio.js";import{readFileSync as B}from"node:fs";import{dirname as _e,join as v}from"node:path";import{fileURLToPath as ge}from"node:url";import{CallToolRequestSchema as me,ListResourcesRequestSchema as fe,ListToolsRequestSchema as he,ReadResourceRequestSchema as ye}from"@modelcontextprotocol/sdk/types.js";import{Client as be}from"@notionhq/client";var c=class extends Error{constructor(t,r,i,o){super(t);this.code=r;this.suggestion=i;this.details=o;this.name="NotionMCPError"}toJSON(){return{error:this.name,code:this.code,message:this.message,suggestion:this.suggestion,details:this.details}}};function W(a){return a.code?z(a):a.message?.includes("ECONNREFUSED")||a.message?.includes("ENOTFOUND")?new c("Cannot connect to Notion API","NETWORK_ERROR","Check your internet connection and try again"):new c(a.message||"Unknown error occurred","UNKNOWN_ERROR","Please check your request and try again",a)}function z(a){let e=a.code,t=a.message||"Unknown Notion API error";switch(console.error("Notion API Error:",JSON.stringify({code:e,message:t,body:a.body,status:a.status},null,2)),e){case"unauthorized":return new c("Invalid or missing Notion API token","UNAUTHORIZED","Set NOTION_TOKEN environment variable with a valid integration token from https://www.notion.so/my-integrations");case"restricted_resource":return new c("Integration does not have access to this resource","RESTRICTED_RESOURCE","Share the page/database with your integration in Notion settings");case"object_not_found":return new c("Page or database not found","NOT_FOUND","Check that the ID is correct and the resource exists");case"validation_error":return new c("Invalid request parameters","VALIDATION_ERROR","Check the API documentation for valid parameter formats",a.details);case"rate_limited":return new c("Too many requests to Notion API","RATE_LIMITED","Wait a few seconds and try again. Consider batching operations.");case"conflict_error":return new c("Conflict with existing data","CONFLICT","The resource may have been modified. Refresh and try again.");case"service_unavailable":return new c("Notion API is temporarily unavailable","SERVICE_UNAVAILABLE","Wait a moment and try again. Check https://status.notion.so for updates.");default:return new c(t,e.toUpperCase(),"Check the Notion API documentation for this error code")}}function D(a){let e=`Error: ${a.message}`;return a.suggestion&&(e+=`
|
|
4
4
|
|
|
5
5
|
Suggestion: ${a.suggestion}`),a.details&&(e+=`
|
|
6
6
|
|
|
7
|
-
Details: ${JSON.stringify(a.details,null,2)}`),e}function f(a){return async(...e)=>{try{return await a(...e)}catch(t){throw
|
|
8
|
-
`),t=[],r=[],
|
|
9
|
-
`),d))}else if(
|
|
10
|
-
`)}function I(a){let e=[],t="",r=!1,o=!1,i=!1,s=!1;for(let d=0;d<a.length;d++){let n=a[d],u=a[d+1];if(n==="["){let p=a.indexOf("]",d),g=p!==-1?a.indexOf("(",p):-1,k=g!==-1?a.indexOf(")",g):-1;if(p!==-1&&g===p+1&&k!==-1){t&&(e.push(y(t,{bold:r,italic:o,code:i,strikethrough:s})),t="");let l=a.slice(d+1,p),w=a.slice(g+1,k);e.push({type:"text",text:{content:l,link:{url:w}},annotations:{bold:r,italic:o,strikethrough:s,underline:!1,code:i,color:"default"}}),d=k;continue}}if(n==="*"&&u==="*"){t&&(e.push(y(t,{bold:r,italic:o,code:i,strikethrough:s})),t=""),r=!r,d++;continue}else if(n==="*"&&u!=="*"){t&&(e.push(y(t,{bold:r,italic:o,code:i,strikethrough:s})),t=""),o=!o;continue}else if(n==="`"){t&&(e.push(y(t,{bold:r,italic:o,code:i,strikethrough:s})),t=""),i=!i;continue}else if(n==="~"&&u==="~"){t&&(e.push(y(t,{bold:r,italic:o,code:i,strikethrough:s})),t=""),s=!s,d++;continue}t+=n}return t&&e.push(y(t,{bold:r,italic:o,code:i,strikethrough:s})),e.length>0?e:[y(a)]}function b(a){return!a||!Array.isArray(a)?"":a.map(e=>{if(!e||!e.text)return"";let t=e.text.content||"",r=e.annotations||{};return r.bold&&(t=`**${t}**`),r.italic&&(t=`*${t}*`),r.code&&(t=`\`${t}\``),r.strikethrough&&(t=`~~${t}~~`),e.text.link&&(t=`[${t}](${e.text.link.url})`),t}).join("")}function y(a,e={}){return{type:"text",text:{content:a,link:null},annotations:{bold:e.bold||!1,italic:e.italic||!1,strikethrough:e.strikethrough||!1,underline:!1,code:e.code||!1,color:"default"}}}function v(a,e){let t=`heading_${a}`;return{object:"block",type:t,[t]:{rich_text:I(e),color:"default"}}}function V(a){return{object:"block",type:"paragraph",paragraph:{rich_text:I(a),color:"default"}}}function $(a){return{object:"block",type:"bulleted_list_item",bulleted_list_item:{rich_text:I(a),color:"default"}}}function H(a){return{object:"block",type:"numbered_list_item",numbered_list_item:{rich_text:I(a),color:"default"}}}function z(a,e){return{object:"block",type:"code",code:{rich_text:[y(a)],language:e||"plain text"}}}function G(a){return{object:"block",type:"quote",quote:{rich_text:I(a),color:"default"}}}function W(){return{object:"block",type:"divider",divider:{}}}function F(a){return a.match(/^[-*]\s/)!==null||a.match(/^\d+\.\s/)!==null}async function m(a,e={}){let{maxPages:t=0,pageSize:r=100}=e,o=[],i=null,s=0;do{let d=await a(i||void 0,r);if(o.push(...d.results),i=d.next_cursor,s++,t>0&&s>=t)break}while(i!==null);return o}async function O(a,e){return f(async()=>{if(!e.block_id)throw new c("block_id required","VALIDATION_ERROR","Provide block_id");switch(e.action){case"get":{let t=await a.blocks.retrieve({block_id:e.block_id});return{action:"get",block_id:t.id,type:t.type,has_children:t.has_children,archived:t.archived,block:t}}case"children":{let t=await m(o=>a.blocks.children.list({block_id:e.block_id,start_cursor:o,page_size:100})),r=x(t);return{action:"children",block_id:e.block_id,total_children:t.length,markdown:r,blocks:t}}case"append":{if(!e.content)throw new c("content required for append","VALIDATION_ERROR","Provide markdown content");let t=h(e.content);return await a.blocks.children.append({block_id:e.block_id,children:t}),{action:"append",block_id:e.block_id,appended_count:t.length}}case"update":{if(!e.content)throw new c("content required for update","VALIDATION_ERROR","Provide markdown content");let r=(await a.blocks.retrieve({block_id:e.block_id})).type,o=h(e.content);if(o.length===0)throw new c("Content must produce at least one block","VALIDATION_ERROR","Invalid markdown");let i=o[0],s={};if(["paragraph","heading_1","heading_2","heading_3","bulleted_list_item","numbered_list_item","quote"].includes(r))s[r]={rich_text:i[r]?.rich_text||[]};else throw new c(`Block type '${r}' cannot be updated`,"VALIDATION_ERROR","Only text blocks can be updated");return await a.blocks.update({block_id:e.block_id,...s}),{action:"update",block_id:e.block_id,type:r,updated:!0}}case"delete":return await a.blocks.delete({block_id:e.block_id}),{action:"delete",block_id:e.block_id,deleted:!0};default:throw new c(`Unknown action: ${e.action}`,"VALIDATION_ERROR","Supported actions: get, children, append, update, delete")}})()}function _(a){return{type:"text",text:{content:a,link:null},annotations:{bold:!1,italic:!1,strikethrough:!1,underline:!1,code:!1,color:"default"}}}function N(a){return a.map(e=>e.text.content).join("")}async function E(a,e){return f(async()=>{switch(e.action){case"list":{if(!e.page_id)throw new Error("page_id required for list action");let t=await m(async r=>await a.comments.list({block_id:e.page_id,start_cursor:r}));return{page_id:e.page_id,total_comments:t.length,comments:t.map(r=>({id:r.id,created_time:r.created_time,created_by:r.created_by,discussion_id:r.discussion_id,text:N(r.rich_text),parent:r.parent}))}}case"create":{if(!e.content)throw new Error("content required for create action");if(!e.page_id&&!e.discussion_id)throw new Error("Either page_id or discussion_id is required for create action");let t={rich_text:[_(e.content)]};e.discussion_id?t.discussion_id=e.discussion_id:t.parent={page_id:e.page_id};let r=await a.comments.create(t);return{comment_id:r.id,discussion_id:r.discussion_id,created:!0}}default:throw new Error(`Unsupported action: ${e.action}`)}})()}async function A(a){return f(async()=>{switch(a.direction){case"markdown-to-blocks":{if(typeof a.content!="string")throw new Error("Content must be a string for markdown-to-blocks");let e=h(a.content);return{direction:a.direction,block_count:e.length,blocks:e}}case"blocks-to-markdown":{let e=a.content;if(typeof e=="string")try{e=JSON.parse(e)}catch{throw new Error("Content must be a valid JSON array or array object for blocks-to-markdown")}if(!Array.isArray(e))throw new Error("Content must be an array for blocks-to-markdown");let t=x(e);return{direction:a.direction,char_count:t.length,markdown:t}}default:throw new Error(`Unsupported direction: ${a.direction}`)}})()}function R(a){let e={};for(let[t,r]of Object.entries(a)){if(r==null){e[t]=r;continue}typeof r=="string"?t==="Name"||t==="Title"||t.toLowerCase()==="title"?e[t]={title:[_(r)]}:e[t]={select:{name:r}}:typeof r=="number"?e[t]={number:r}:typeof r=="boolean"?e[t]={checkbox:r}:Array.isArray(r)&&r.length>0&&typeof r[0]=="string"?e[t]={multi_select:r.map(o=>({name:o}))}:e[t]=r}return e}async function D(a,e){return f(async()=>{switch(e.action){case"create":return await K(a,e);case"get":return await J(a,e);case"query":return await Q(a,e);case"create_page":return await Z(a,e);case"update_page":return await X(a,e);case"delete_page":return await Y(a,e);case"create_data_source":return await ee(a,e);case"update_data_source":return await te(a,e);case"update_database":return await ae(a,e);default:throw new c(`Unknown action: ${e.action}`,"VALIDATION_ERROR","Supported actions: create, get, query, create_page, update_page, delete_page, create_data_source, update_data_source, update_database")}})()}async function K(a,e){if(!e.parent_id||!e.title||!e.properties)throw new c("parent_id, title, and properties required for create action","VALIDATION_ERROR","Provide parent_id, title, and properties");let t={parent:{type:"page_id",page_id:e.parent_id},title:[_(e.title)],initial_data_source:{properties:e.properties}};e.description&&(t.description=[_(e.description)]),e.is_inline!==void 0&&(t.is_inline=e.is_inline);let r=await a.databases.create(t);return{action:"create",database_id:r.id,data_source_id:r.data_sources?.[0]?.id,url:r.url,created:!0}}async function J(a,e){if(!e.database_id)throw new c("database_id required for get action","VALIDATION_ERROR","Provide database_id");let t=await a.databases.retrieve({database_id:e.database_id}),r={},o=null;if(t.data_sources&&t.data_sources.length>0){let i=await a.dataSources.retrieve({data_source_id:t.data_sources[0].id});if(o={id:i.id,name:i.title?.[0]?.plain_text||t.data_sources[0].name},i.properties)for(let[s,d]of Object.entries(i.properties)){let n=d;r[s]={type:n.type,id:n.id},n.type==="select"&&n.select?.options?r[s].options=n.select.options.map(u=>u.name):n.type==="multi_select"&&n.multi_select?.options?r[s].options=n.multi_select.options.map(u=>u.name):n.type==="formula"&&n.formula&&(r[s].expression=n.formula.expression)}}return{action:"get",database_id:t.id,title:t.title?.[0]?.plain_text||"Untitled",description:t.description?.[0]?.plain_text||"",url:t.url,is_inline:t.is_inline,created_time:t.created_time,last_edited_time:t.last_edited_time,data_source:o,schema:r}}async function Q(a,e){if(!e.database_id)throw new c("database_id required for query action","VALIDATION_ERROR","Provide database_id");let t=await a.databases.retrieve({database_id:e.database_id});if(!t.data_sources||t.data_sources.length===0)throw new c("No data sources found in database","VALIDATION_ERROR","Database has no data sources");let r=t.data_sources[0].id,o=e.filters;if(e.search&&!o){let u=await a.dataSources.retrieve({data_source_id:r}),p=Object.entries(u.properties||{}).filter(([g,k])=>["title","rich_text"].includes(k.type)).map(([g])=>g);p.length>0&&(o={or:p.map(g=>({property:g,rich_text:{contains:e.search}}))})}let i={data_source_id:r};o&&(i.filter=o),e.sorts&&(i.sorts=e.sorts);let s=await m(async u=>{let p=await a.dataSources.query({...i,start_cursor:u,page_size:100});return{results:p.results,next_cursor:p.next_cursor,has_more:p.has_more}}),n=(e.limit?s.slice(0,e.limit):s).map(u=>{let p={page_id:u.id,url:u.url};for(let[g,k]of Object.entries(u.properties)){let l=k;l.type==="title"&&l.title?p[g]=l.title.map(w=>w.plain_text).join(""):l.type==="rich_text"&&l.rich_text?p[g]=l.rich_text.map(w=>w.plain_text).join(""):l.type==="select"&&l.select?p[g]=l.select.name:l.type==="multi_select"&&l.multi_select?p[g]=l.multi_select.map(w=>w.name):l.type==="number"?p[g]=l.number:l.type==="checkbox"?p[g]=l.checkbox:l.type==="url"?p[g]=l.url:l.type==="email"?p[g]=l.email:l.type==="phone_number"?p[g]=l.phone_number:l.type==="date"&&l.date&&(p[g]=l.date.start+(l.date.end?` to ${l.date.end}`:""))}return p});return{action:"query",database_id:e.database_id,data_source_id:r,total:n.length,results:n}}async function Z(a,e){if(!e.database_id)throw new c("database_id required","VALIDATION_ERROR","Provide database_id");let t=await a.databases.retrieve({database_id:e.database_id});if(!t.data_sources||t.data_sources.length===0)throw new c("No data sources found in database","VALIDATION_ERROR","Database has no data sources");let r=t.data_sources[0].id,o=e.pages||(e.page_properties?[{properties:e.page_properties}]:[]);if(o.length===0)throw new c("pages or page_properties required","VALIDATION_ERROR","Provide items to create");let i=[];for(let s of o){let d=R(s.properties),n=await a.pages.create({parent:{type:"data_source_id",data_source_id:r},properties:d});i.push({page_id:n.id,url:n.url,created:!0})}return{action:"create_page",database_id:e.database_id,data_source_id:r,processed:i.length,results:i}}async function X(a,e){let t=e.pages||(e.page_id&&e.page_properties?[{page_id:e.page_id,properties:e.page_properties}]:[]);if(t.length===0)throw new c("pages or page_id+page_properties required","VALIDATION_ERROR","Provide items to update");let r=[];for(let o of t){if(!o.page_id)throw new c("page_id required for each item","VALIDATION_ERROR","Provide page_id");let i=R(o.properties);await a.pages.update({page_id:o.page_id,properties:i}),r.push({page_id:o.page_id,updated:!0})}return{action:"update_page",processed:r.length,results:r}}async function Y(a,e){let t=e.page_ids||(e.page_id?[e.page_id]:[])||(e.pages?e.pages.map(o=>o.page_id).filter(Boolean):[]);if(t.length===0)throw new c("page_id or page_ids required","VALIDATION_ERROR","Provide page IDs to delete");let r=[];for(let o of t)await a.pages.update({page_id:o,archived:!0}),r.push({page_id:o,deleted:!0});return{action:"delete_page",processed:r.length,results:r}}async function ee(a,e){if(!e.database_id||!e.title||!e.properties)throw new c("database_id, title, and properties required","VALIDATION_ERROR","Provide database_id, title, and properties for new data source");let t={parent:{type:"database_id",database_id:e.database_id},title:[_(e.title)],properties:e.properties};return e.description&&(t.description=[_(e.description)]),{action:"create_data_source",data_source_id:(await a.dataSources.create(t)).id,database_id:e.database_id,created:!0}}async function te(a,e){if(!e.data_source_id)throw new c("data_source_id required","VALIDATION_ERROR","Provide data_source_id");let t={};if(e.title&&(t.title=[_(e.title)]),e.description&&(t.description=[_(e.description)]),e.properties&&(t.properties=e.properties),Object.keys(t).length===0)throw new c("No updates provided","VALIDATION_ERROR","Provide title, description, or properties to update");return await a.dataSources.update({data_source_id:e.data_source_id,...t}),{action:"update_data_source",data_source_id:e.data_source_id,updated:!0}}async function ae(a,e){if(!e.database_id)throw new c("database_id required","VALIDATION_ERROR","Provide database_id");let t={};if(e.parent_id&&(t.parent={type:"page_id",page_id:e.parent_id}),e.title&&(t.title=[_(e.title)]),e.description&&(t.description=[_(e.description)]),e.is_inline!==void 0&&(t.is_inline=e.is_inline),e.icon&&(t.icon={type:"emoji",emoji:e.icon}),e.cover&&(t.cover={type:"external",external:{url:e.cover}}),Object.keys(t).length===0)throw new c("No updates provided","VALIDATION_ERROR","Provide parent_id, title, description, is_inline, icon, or cover");return await a.databases.update({database_id:e.database_id,...t}),{action:"update_database",database_id:e.database_id,updated:!0}}async function C(a,e){return f(async()=>{switch(e.action){case"create":return await re(a,e);case"get":return await ie(a,e);case"update":return await oe(a,e);case"archive":case"restore":return await se(a,e);case"duplicate":return await ne(a,e);default:throw new c(`Unknown action: ${e.action}`,"VALIDATION_ERROR","Supported actions: create, get, update, archive, restore, move, duplicate")}})()}async function re(a,e){if(!e.title)throw new c("title is required for create action","VALIDATION_ERROR","Provide page title");if(!e.parent_id)throw new c("parent_id is required for page creation","VALIDATION_ERROR","Integration tokens cannot create workspace-level pages. Provide parent_id (database or page ID).");let t=e.parent_id.replace(/-/g,""),r;e.properties&&Object.keys(e.properties).length>0?r={type:"database_id",database_id:t}:r={type:"page_id",page_id:t};let o={};r.database_id?(o=R(e.properties||{}),!o.title&&!o.Name&&!o.Title&&(o.Name={title:[_(e.title)]})):o={title:{title:[_(e.title)]}};let i={parent:r,properties:o};e.icon&&(i.icon={type:"emoji",emoji:e.icon}),e.cover&&(i.cover={type:"external",external:{url:e.cover}});let s=await a.pages.create(i);if(e.content){let d=h(e.content);d.length>0&&await a.blocks.children.append({block_id:s.id,children:d})}return{action:"create",page_id:s.id,url:s.url,created:!0}}async function ie(a,e){if(!e.page_id)throw new c("page_id is required for get action","VALIDATION_ERROR","Provide page_id");let t=await a.pages.retrieve({page_id:e.page_id}),r=await m(s=>a.blocks.children.list({block_id:e.page_id,start_cursor:s,page_size:100})),o=x(r),i={};for(let[s,d]of Object.entries(t.properties)){let n=d;n.type==="title"&&n.title?i[s]=n.title.map(u=>u.plain_text).join(""):n.type==="rich_text"&&n.rich_text?i[s]=n.rich_text.map(u=>u.plain_text).join(""):n.type==="select"&&n.select?i[s]=n.select.name:n.type==="multi_select"&&n.multi_select?i[s]=n.multi_select.map(u=>u.name):n.type==="number"?i[s]=n.number:n.type==="checkbox"?i[s]=n.checkbox:n.type==="url"?i[s]=n.url:n.type==="email"?i[s]=n.email:n.type==="phone_number"?i[s]=n.phone_number:n.type==="date"&&n.date&&(i[s]=n.date.start+(n.date.end?` to ${n.date.end}`:""))}return{action:"get",page_id:t.id,url:t.url,created_time:t.created_time,last_edited_time:t.last_edited_time,archived:t.archived,properties:i,content:o,block_count:r.length}}async function oe(a,e){if(!e.page_id)throw new c("page_id is required for update action","VALIDATION_ERROR","Provide page_id");let t={};if(e.icon&&(t.icon={type:"emoji",emoji:e.icon}),e.cover&&(t.cover={type:"external",external:{url:e.cover}}),e.archived!==void 0&&(t.archived=e.archived),(e.properties||e.title)&&(t.properties={},e.title&&(t.properties.title={title:[_(e.title)]}),e.properties)){let r=R(e.properties);t.properties={...t.properties,...r}}if(Object.keys(t).length>0&&await a.pages.update({page_id:e.page_id,...t}),e.content||e.append_content||e.prepend_content){if(e.content){let r=await m(i=>a.blocks.children.list({block_id:e.page_id,start_cursor:i,page_size:100}));for(let i of r)await a.blocks.delete({block_id:i.id});let o=h(e.content);o.length>0&&await a.blocks.children.append({block_id:e.page_id,children:o})}else if(e.append_content){let r=h(e.append_content);r.length>0&&await a.blocks.children.append({block_id:e.page_id,children:r})}else if(e.prepend_content){let r=await m(i=>a.blocks.children.list({block_id:e.page_id,start_cursor:i,page_size:1})),o=h(e.prepend_content);o.length>0&&(r[0]?.id?await a.blocks.children.append({block_id:e.page_id,children:o,after:void 0}):await a.blocks.children.append({block_id:e.page_id,children:o}))}}return{action:"update",page_id:e.page_id,updated:!0}}async function se(a,e){let t=e.page_ids||(e.page_id?[e.page_id]:[]);if(t.length===0)throw new c("page_id or page_ids required","VALIDATION_ERROR","Provide at least one page ID");let r=e.action==="archive",o=[];for(let i of t)await a.pages.update({page_id:i,archived:r}),o.push({page_id:i,archived:r});return{action:e.action,processed:o.length,results:o}}async function ne(a,e){let t=e.page_ids||(e.page_id?[e.page_id]:[]);if(t.length===0)throw new c("page_id or page_ids required","VALIDATION_ERROR","Provide at least one page ID");let r=[];for(let o of t){let i=await a.pages.retrieve({page_id:o}),s=await m(n=>a.blocks.children.list({block_id:o,start_cursor:n,page_size:100})),d=await a.pages.create({parent:i.parent,properties:i.properties,icon:i.icon,cover:i.cover});s.length>0&&await a.blocks.children.append({block_id:d.id,children:s}),r.push({original_id:o,duplicate_id:d.id,url:d.url})}return{action:"duplicate",processed:r.length,results:r}}async function S(a,e){return f(async()=>{switch(e.action){case"list":{let t=await m(r=>a.users.list({start_cursor:r,page_size:100}));return{action:"list",total:t.length,users:t.map(r=>({id:r.id,type:r.type,name:r.name||"Unknown",avatar_url:r.avatar_url,email:r.type==="person"?r.person?.email:void 0}))}}case"get":{if(!e.user_id)throw new c("user_id required for get action","VALIDATION_ERROR","Provide user_id");let t=await a.users.retrieve({user_id:e.user_id});return{action:"get",id:t.id,type:t.type,name:t.name||"Unknown",avatar_url:t.avatar_url,email:t.type==="person"?t.person?.email:void 0}}case"me":{let t=await a.users.retrieve({user_id:"me"});return{action:"me",id:t.id,type:t.type,name:t.name||"Bot",bot:t.bot}}case"from_workspace":{let t=await a.search({filter:{property:"object",value:"page"},page_size:100}),r=new Map;for(let i of t.results)i.created_by&&r.set(i.created_by.id,{id:i.created_by.id,type:i.created_by.object,source:"page_metadata"}),i.last_edited_by&&r.set(i.last_edited_by.id,{id:i.last_edited_by.id,type:i.last_edited_by.object,source:"page_metadata"});let o=Array.from(r.values());return{action:"from_workspace",total:o.length,users:o,note:'Users extracted from accessible pages. Use "me" action for bot info, or share more pages for more users.'}}default:throw new c(`Unknown action: ${e.action}`,"VALIDATION_ERROR","Supported actions: list, get, me, from_workspace")}})()}async function q(a,e){return f(async()=>{switch(e.action){case"info":{let t=await a.users.retrieve({user_id:"me"});return{action:"info",bot:{id:t.id,name:t.name||"Bot",type:t.type,owner:t.bot?.owner}}}case"search":{let t={query:e.query||""};e.filter?.object&&(t.filter={value:e.filter.object,property:"object"}),e.sort&&(t.sort={direction:e.sort.direction||"descending",timestamp:e.sort.timestamp||"last_edited_time"});let r=await m(i=>a.search({...t,start_cursor:i,page_size:100})),o=e.limit?r.slice(0,e.limit):r;return{action:"search",query:e.query,total:o.length,results:o.map(i=>({id:i.id,object:i.object,title:i.object==="page"?i.properties?.title?.title?.[0]?.plain_text||i.properties?.Name?.title?.[0]?.plain_text||"Untitled":i.title?.[0]?.plain_text||"Untitled",url:i.url,last_edited_time:i.last_edited_time}))}}default:throw new c(`Unknown action: ${e.action}`,"VALIDATION_ERROR","Supported actions: info, search")}})()}var j=[{name:"pages",description:`Complete page lifecycle management. Handles creation, reading, updating, archiving, and duplication.
|
|
11
|
-
|
|
12
|
-
**IMPORTANT:** Integration tokens cannot create workspace-level pages. Always provide parent_id (page or database ID).
|
|
13
|
-
|
|
14
|
-
Actions: create, get, update, archive, restore, duplicate.
|
|
15
|
-
|
|
16
|
-
Maps to: POST/GET/PATCH /v1/pages + /v1/blocks/{id}/children
|
|
17
|
-
|
|
18
|
-
Examples:
|
|
19
|
-
- Create page: {action: "create", title: "Meeting Notes", parent_id: "xxx", content: "# Agenda
|
|
20
|
-
- Item 1
|
|
21
|
-
- Item 2"}
|
|
22
|
-
- Create in database: {action: "create", title: "Task", parent_id: "db-id", properties: {Status: "Todo", Priority: "High"}}
|
|
23
|
-
- Get with content: {action: "get", page_id: "xxx"} \u2192 Returns markdown content
|
|
24
|
-
- Update content: {action: "update", page_id: "xxx", append_content: "
|
|
25
|
-
## New Section"}
|
|
26
|
-
- Update metadata: {action: "update", page_id: "xxx", icon: "", cover: "https://..."}
|
|
27
|
-
- Archive: {action: "archive", page_ids: ["xxx", "yyy"]}
|
|
28
|
-
- Restore: {action: "restore", page_id: "xxx"}
|
|
29
|
-
- Duplicate: {action: "duplicate", page_id: "xxx"}`,inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","get","update","archive","restore","duplicate"],description:"Action to perform"},page_id:{type:"string",description:"Page ID (required for most actions)"},page_ids:{type:"array",items:{type:"string"},description:"Multiple page IDs for batch operations"},title:{type:"string",description:"Page title"},content:{type:"string",description:"Markdown content"},append_content:{type:"string",description:"Markdown to append"},prepend_content:{type:"string",description:"Markdown to prepend"},parent_id:{type:"string",description:"Parent page or database ID"},properties:{type:"object",description:"Page properties (for database pages)"},icon:{type:"string",description:"Emoji icon"},cover:{type:"string",description:"Cover image URL"},archived:{type:"boolean",description:"Archive status"}},required:["action"]}},{name:"databases",description:`Complete database & data source operations (Notion API 2025-09-03).
|
|
30
|
-
|
|
31
|
-
**ARCHITECTURE NOTE:**
|
|
32
|
-
Notion databases now support multiple data sources. A database is a container that holds one or more data sources. Each data source has its own schema (properties) and rows (pages).
|
|
33
|
-
|
|
34
|
-
**WORKFLOW:**
|
|
35
|
-
1. Create database \u2192 Creates database container + initial data source
|
|
36
|
-
2. Get database \u2192 Retrieves data_source_id for querying
|
|
37
|
-
3. Query/Create/Update pages \u2192 Use data_source_id (auto-fetched from database_id)
|
|
38
|
-
|
|
39
|
-
Actions: create, get, query, create_page, update_page, delete_page, create_data_source, update_data_source, update_database.
|
|
40
|
-
|
|
41
|
-
Maps to: /v1/databases + /v1/data_sources + /v1/pages
|
|
42
|
-
|
|
43
|
-
Examples:
|
|
44
|
-
- Create DB+datasource: {action: "create", parent_id: "xxx", title: "Tasks", properties: {Status: {select: {options: [{name: "Todo"}, {name: "Done"}]}}}}
|
|
45
|
-
- Get schema: {action: "get", database_id: "xxx"} \u2192 Returns data_source info
|
|
46
|
-
- Query data: {action: "query", database_id: "xxx", filters: {property: "Status", select: {equals: "Done"}}}
|
|
47
|
-
- Smart search: {action: "query", database_id: "xxx", search: "project"}
|
|
48
|
-
- Create rows: {action: "create_page", database_id: "xxx", pages: [{properties: {Name: "Task 1", Status: "Todo"}}]}
|
|
49
|
-
- Update rows: {action: "update_page", page_id: "yyy", page_properties: {Status: "Done"}}
|
|
50
|
-
- Delete rows: {action: "delete_page", page_ids: ["yyy", "zzz"]}
|
|
51
|
-
- Add 2nd datasource: {action: "create_data_source", database_id: "xxx", title: "Archive", properties: {...}}
|
|
52
|
-
- Update datasource schema: {action: "update_data_source", data_source_id: "yyy", properties: {NewField: {checkbox: {}}}}
|
|
53
|
-
- Move database: {action: "update_database", database_id: "xxx", parent_id: "new-page-id"}`,inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","get","query","create_page","update_page","delete_page","create_data_source","update_data_source","update_database"],description:"Action to perform"},database_id:{type:"string",description:"Database ID (container)"},data_source_id:{type:"string",description:"Data source ID (for update_data_source action)"},parent_id:{type:"string",description:"Parent page ID (for create/update_database)"},title:{type:"string",description:"Title (for database or data source)"},description:{type:"string",description:"Description"},properties:{type:"object",description:"Schema properties (for create/update data source)"},is_inline:{type:"boolean",description:"Display as inline (for create/update_database)"},icon:{type:"string",description:"Emoji icon (for update_database)"},cover:{type:"string",description:"Cover image URL (for update_database)"},filters:{type:"object",description:"Query filters (for query action)"},sorts:{type:"array",items:{type:"object"},description:"Query sorts"},limit:{type:"number",description:"Max query results"},search:{type:"string",description:"Smart search across text fields (for query)"},page_id:{type:"string",description:"Single page ID (for update_page)"},page_ids:{type:"array",items:{type:"string"},description:"Multiple page IDs (for delete_page)"},page_properties:{type:"object",description:"Page properties to update (for update_page)"},pages:{type:"array",items:{type:"object"},description:"Array of pages for bulk create/update"}},required:["action"]}},{name:"blocks",description:`Fine-grained content manipulation at block level. Use for precise edits within pages.
|
|
54
|
-
|
|
55
|
-
**When to use:** Editing specific paragraphs, headings, or sections. For full page content, use pages tool.
|
|
56
|
-
**Block ID:** Page IDs are also valid block IDs (page is the root block).
|
|
57
|
-
|
|
58
|
-
Actions: get, children, append, update, delete.
|
|
59
|
-
|
|
60
|
-
Maps to: GET/PATCH/DELETE /v1/blocks/{id} + /v1/blocks/{id}/children
|
|
61
|
-
|
|
62
|
-
Examples:
|
|
63
|
-
- Get block info: {action: "get", block_id: "xxx"}
|
|
64
|
-
- Read content: {action: "children", block_id: "xxx"} \u2192 Returns markdown of child blocks
|
|
65
|
-
- Add content: {action: "append", block_id: "page-id", content: "## New Section
|
|
66
|
-
Paragraph text"}
|
|
67
|
-
- Edit paragraph: {action: "update", block_id: "block-id", content: "Updated text"}
|
|
68
|
-
- Remove block: {action: "delete", block_id: "block-id"}`,inputSchema:{type:"object",properties:{action:{type:"string",enum:["get","children","append","update","delete"],description:"Action to perform"},block_id:{type:"string",description:"Block ID"},content:{type:"string",description:"Markdown content (for append/update)"}},required:["action","block_id"]}},{name:"users",description:`User information retrieval. Get bot info, list users, or extract users from workspace.
|
|
69
|
-
|
|
70
|
-
**PERMISSION NOTE:** list action may fail if integration lacks user read permissions. Use from_workspace as fallback - it extracts user IDs from accessible pages' metadata.
|
|
71
|
-
|
|
72
|
-
Actions: list, get, me, from_workspace.
|
|
73
|
-
|
|
74
|
-
Maps to: GET /v1/users + GET /v1/users/{id} + GET /v1/users/me
|
|
75
|
-
|
|
76
|
-
Examples:
|
|
77
|
-
- Get bot details: {action: "me"} \u2192 Integration info
|
|
78
|
-
- List all users: {action: "list"} \u2192 Requires user:read permission
|
|
79
|
-
- Get specific user: {action: "get", user_id: "xxx"}
|
|
80
|
-
- Bypass permissions: {action: "from_workspace"} \u2192 Extracts users from page metadata (created_by, last_edited_by)`,inputSchema:{type:"object",properties:{action:{type:"string",enum:["list","get","me","from_workspace"],description:"Action to perform"},user_id:{type:"string",description:"User ID (for get action)"}},required:["action"]}},{name:"workspace",description:`Workspace-level operations: get integration info and search across pages/data sources.
|
|
81
|
-
|
|
82
|
-
**Search:** Searches page/database titles. In API 2025-09-03, use filter object "data_source" to find databases. Returns only accessible content (shared with integration).
|
|
83
|
-
|
|
84
|
-
Actions: info, search.
|
|
85
|
-
|
|
86
|
-
Maps to: GET /v1/users/me + POST /v1/search
|
|
87
|
-
|
|
88
|
-
Examples:
|
|
89
|
-
- Get workspace info: {action: "info"} \u2192 Bot owner, workspace details
|
|
90
|
-
- Search pages: {action: "search", query: "meeting notes", filter: {object: "page"}, limit: 10}
|
|
91
|
-
- Search databases: {action: "search", query: "tasks", filter: {object: "data_source"}}
|
|
92
|
-
- Sort results: {action: "search", query: "project", sort: {direction: "ascending", timestamp: "last_edited_time"}}`,inputSchema:{type:"object",properties:{action:{type:"string",enum:["info","search"],description:"Action to perform"},query:{type:"string",description:"Search query"},filter:{type:"object",properties:{object:{type:"string",enum:["page","data_source"]}}},sort:{type:"object",properties:{direction:{type:"string",enum:["ascending","descending"]},timestamp:{type:"string",enum:["last_edited_time","created_time"]}}},limit:{type:"number",description:"Max results"}},required:["action"]}},{name:"comments",description:`Page discussion management. List comments on pages and add new comments or replies.
|
|
93
|
-
|
|
94
|
-
**Threading:** Use page_id for new discussion. Use discussion_id (from list response) to reply to existing thread.
|
|
95
|
-
|
|
96
|
-
Actions: list, create.
|
|
97
|
-
|
|
98
|
-
Maps to: GET /v1/comments + POST /v1/comments
|
|
99
|
-
|
|
100
|
-
Examples:
|
|
101
|
-
- List page comments: {action: "list", page_id: "xxx"}
|
|
102
|
-
- Start discussion: {action: "create", page_id: "xxx", content: "Great work on this page!"}
|
|
103
|
-
- Reply to thread: {action: "create", discussion_id: "thread-id", content: "I agree with your points"}`,inputSchema:{type:"object",properties:{page_id:{type:"string",description:"Page ID"},discussion_id:{type:"string",description:"Discussion ID (for replies)"},action:{type:"string",enum:["list","create"],description:"Action to perform"},content:{type:"string",description:"Comment content (for create)"}},required:["action"]}},{name:"content_convert",description:`Format conversion utility. Convert between human-readable Markdown and Notion's block format.
|
|
104
|
-
|
|
105
|
-
**Use cases:**
|
|
106
|
-
- Preview Notion blocks as Markdown before appending
|
|
107
|
-
- Test block structure from Markdown input
|
|
108
|
-
- Debug block formatting issues
|
|
109
|
-
|
|
110
|
-
**Note:** Most operations (pages, blocks) handle Markdown automatically. Use this for advanced preview/validation.
|
|
111
|
-
|
|
112
|
-
Examples:
|
|
113
|
-
- Parse Markdown: {direction: "markdown-to-blocks", content: "# Heading
|
|
114
|
-
Paragraph text
|
|
115
|
-
- List item"}
|
|
116
|
-
- Read blocks: {direction: "blocks-to-markdown", content: [{"type": "paragraph", "paragraph": {...}}]}`,inputSchema:{type:"object",properties:{direction:{type:"string",enum:["markdown-to-blocks","blocks-to-markdown"],description:"Conversion direction"},content:{description:"Content to convert (string or array/JSON string)"}},required:["direction","content"]}}];function L(a,e){let t=new le({auth:e,notionVersion:"2025-09-03"});a.setRequestHandler(de,async()=>({tools:j})),a.setRequestHandler(ce,async r=>{let{name:o,arguments:i}=r.params;if(!i)return{content:[{type:"text",text:"Error: No arguments provided"}],isError:!0};try{let s;switch(o){case"pages":s=await C(t,i);break;case"databases":s=await D(t,i);break;case"blocks":s=await O(t,i);break;case"users":s=await S(t,i);break;case"workspace":s=await q(t,i);break;case"comments":s=await E(t,i);break;case"content_convert":s=await A(i);break;default:throw new c(`Unknown tool: ${o}`,"UNKNOWN_TOOL",`Available tools: ${j.map(d=>d.name).join(", ")}`)}return{content:[{type:"text",text:JSON.stringify(s,null,2)}]}}catch(s){let d=s instanceof c?s:new c(s.message,"TOOL_ERROR","Check the error details and try again");return{content:[{type:"text",text:P(d)}],isError:!0}}})}async function U(){let a=process.env.NOTION_TOKEN;a||(console.error("NOTION_TOKEN environment variable is required"),console.error("Get your token from https://www.notion.so/my-integrations"),process.exit(1));let e=new pe({name:"@n24q02m/better-notion-mcp",version:"1.0.0"},{capabilities:{tools:{}}});L(e,a);let t=new ue;return await e.connect(t),e}async function ge(){try{await U(),process.on("SIGINT",()=>{console.error(`
|
|
117
|
-
Shutting down Better Notion MCP Server`),process.exit(0)})}catch(a){console.error("Failed to start server:",a),process.exit(1)}}ge();
|
|
7
|
+
Details: ${JSON.stringify(a.details,null,2)}`),e}function f(a){return async(...e)=>{try{return await a(...e)}catch(t){throw W(t)}}}function h(a){let e=a.split(`
|
|
8
|
+
`),t=[],r=[],i=null;for(let o=0;o<e.length;o++){let n=e[o];if(i&&!X(n)&&(t.push(...r),r=[],i=null),!!n.trim())if(n.startsWith("# "))t.push(P(1,n.slice(2)));else if(n.startsWith("## "))t.push(P(2,n.slice(3)));else if(n.startsWith("### "))t.push(P(3,n.slice(4)));else if(n.startsWith("```")){let d=n.slice(3).trim(),s=[];for(o++;o<e.length&&!e[o].startsWith("```");)s.push(e[o]),o++;t.push(G(s.join(`
|
|
9
|
+
`),d))}else if(n.match(/^[-*]\s/)){let d=n.slice(2);i="bulleted",r.push(J(d))}else if(n.match(/^\d+\.\s/)){let d=n.replace(/^\d+\.\s/,"");i="numbered",r.push(K(d))}else n.startsWith("> ")?t.push(Q(n.slice(2))):n.match(/^[-*]{3,}$/)?t.push(Z()):t.push(F(n))}return r.length>0&&t.push(...r),t}function x(a){let e=[];for(let t of a)switch(t.type){case"heading_1":e.push(`# ${y(t.heading_1.rich_text)}`);break;case"heading_2":e.push(`## ${y(t.heading_2.rich_text)}`);break;case"heading_3":e.push(`### ${y(t.heading_3.rich_text)}`);break;case"paragraph":e.push(y(t.paragraph.rich_text));break;case"bulleted_list_item":e.push(`- ${y(t.bulleted_list_item.rich_text)}`);break;case"numbered_list_item":e.push(`1. ${y(t.numbered_list_item.rich_text)}`);break;case"code":e.push(`\`\`\`${t.code.language||""}`),e.push(y(t.code.rich_text)),e.push("```");break;case"quote":e.push(`> ${y(t.quote.rich_text)}`);break;case"divider":e.push("---");break;default:break}return e.join(`
|
|
10
|
+
`)}function I(a){let e=[],t="",r=!1,i=!1,o=!1,n=!1;for(let d=0;d<a.length;d++){let s=a[d],u=a[d+1];if(s==="["){let p=a.indexOf("]",d),_=p!==-1?a.indexOf("(",p):-1,w=_!==-1?a.indexOf(")",_):-1;if(p!==-1&&_===p+1&&w!==-1){t&&(e.push(b(t,{bold:r,italic:i,code:o,strikethrough:n})),t="");let l=a.slice(d+1,p),k=a.slice(_+1,w);e.push({type:"text",text:{content:l,link:{url:k}},annotations:{bold:r,italic:i,strikethrough:n,underline:!1,code:o,color:"default"}}),d=w;continue}}if(s==="*"&&u==="*"){t&&(e.push(b(t,{bold:r,italic:i,code:o,strikethrough:n})),t=""),r=!r,d++;continue}else if(s==="*"&&u!=="*"){t&&(e.push(b(t,{bold:r,italic:i,code:o,strikethrough:n})),t=""),i=!i;continue}else if(s==="`"){t&&(e.push(b(t,{bold:r,italic:i,code:o,strikethrough:n})),t=""),o=!o;continue}else if(s==="~"&&u==="~"){t&&(e.push(b(t,{bold:r,italic:i,code:o,strikethrough:n})),t=""),n=!n,d++;continue}t+=s}return t&&e.push(b(t,{bold:r,italic:i,code:o,strikethrough:n})),e.length>0?e:[b(a)]}function y(a){return!a||!Array.isArray(a)?"":a.map(e=>{if(!e||!e.text)return"";let t=e.text.content||"",r=e.annotations||{};return r.bold&&(t=`**${t}**`),r.italic&&(t=`*${t}*`),r.code&&(t=`\`${t}\``),r.strikethrough&&(t=`~~${t}~~`),e.text.link&&(t=`[${t}](${e.text.link.url})`),t}).join("")}function b(a,e={}){return{type:"text",text:{content:a,link:null},annotations:{bold:e.bold||!1,italic:e.italic||!1,strikethrough:e.strikethrough||!1,underline:!1,code:e.code||!1,color:"default"}}}function P(a,e){let t=`heading_${a}`;return{object:"block",type:t,[t]:{rich_text:I(e),color:"default"}}}function F(a){return{object:"block",type:"paragraph",paragraph:{rich_text:I(a),color:"default"}}}function J(a){return{object:"block",type:"bulleted_list_item",bulleted_list_item:{rich_text:I(a),color:"default"}}}function K(a){return{object:"block",type:"numbered_list_item",numbered_list_item:{rich_text:I(a),color:"default"}}}function G(a,e){return{object:"block",type:"code",code:{rich_text:[b(a)],language:e||"plain text"}}}function Q(a){return{object:"block",type:"quote",quote:{rich_text:I(a),color:"default"}}}function Z(){return{object:"block",type:"divider",divider:{}}}function X(a){return a.match(/^[-*]\s/)!==null||a.match(/^\d+\.\s/)!==null}async function m(a,e={}){let{maxPages:t=0,pageSize:r=100}=e,i=[],o=null,n=0;do{let d=await a(o||void 0,r);if(i.push(...d.results),o=d.next_cursor,n++,t>0&&n>=t)break}while(o!==null);return i}async function E(a,e){return f(async()=>{if(!e.block_id)throw new c("block_id required","VALIDATION_ERROR","Provide block_id");switch(e.action){case"get":{let t=await a.blocks.retrieve({block_id:e.block_id});return{action:"get",block_id:t.id,type:t.type,has_children:t.has_children,archived:t.archived,block:t}}case"children":{let t=await m(i=>a.blocks.children.list({block_id:e.block_id,start_cursor:i,page_size:100})),r=x(t);return{action:"children",block_id:e.block_id,total_children:t.length,markdown:r,blocks:t}}case"append":{if(!e.content)throw new c("content required for append","VALIDATION_ERROR","Provide markdown content");let t=h(e.content);return await a.blocks.children.append({block_id:e.block_id,children:t}),{action:"append",block_id:e.block_id,appended_count:t.length}}case"update":{if(!e.content)throw new c("content required for update","VALIDATION_ERROR","Provide markdown content");let r=(await a.blocks.retrieve({block_id:e.block_id})).type,i=h(e.content);if(i.length===0)throw new c("Content must produce at least one block","VALIDATION_ERROR","Invalid markdown");let o=i[0],n={};if(["paragraph","heading_1","heading_2","heading_3","bulleted_list_item","numbered_list_item","quote"].includes(r))n[r]={rich_text:o[r]?.rich_text||[]};else throw new c(`Block type '${r}' cannot be updated`,"VALIDATION_ERROR","Only text blocks can be updated");return await a.blocks.update({block_id:e.block_id,...n}),{action:"update",block_id:e.block_id,type:r,updated:!0}}case"delete":return await a.blocks.delete({block_id:e.block_id}),{action:"delete",block_id:e.block_id,deleted:!0};default:throw new c(`Unknown action: ${e.action}`,"VALIDATION_ERROR","Supported actions: get, children, append, update, delete")}})()}function g(a){return{type:"text",text:{content:a,link:null},annotations:{bold:!1,italic:!1,strikethrough:!1,underline:!1,code:!1,color:"default"}}}function A(a){return a.map(e=>e.text.content).join("")}async function C(a,e){return f(async()=>{switch(e.action){case"list":{if(!e.page_id)throw new Error("page_id required for list action");let t=await m(async r=>await a.comments.list({block_id:e.page_id,start_cursor:r}));return{page_id:e.page_id,total_comments:t.length,comments:t.map(r=>({id:r.id,created_time:r.created_time,created_by:r.created_by,discussion_id:r.discussion_id,text:A(r.rich_text),parent:r.parent}))}}case"create":{if(!e.content)throw new Error("content required for create action");if(!e.page_id&&!e.discussion_id)throw new Error("Either page_id or discussion_id is required for create action");let t={rich_text:[g(e.content)]};e.discussion_id?t.discussion_id=e.discussion_id:t.parent={page_id:e.page_id};let r=await a.comments.create(t);return{comment_id:r.id,discussion_id:r.discussion_id,created:!0}}default:throw new Error(`Unsupported action: ${e.action}`)}})()}async function q(a){return f(async()=>{switch(a.direction){case"markdown-to-blocks":{if(typeof a.content!="string")throw new Error("Content must be a string for markdown-to-blocks");let e=h(a.content);return{direction:a.direction,block_count:e.length,blocks:e}}case"blocks-to-markdown":{let e=a.content;if(typeof e=="string")try{e=JSON.parse(e)}catch{throw new Error("Content must be a valid JSON array or array object for blocks-to-markdown")}if(!Array.isArray(e))throw new Error("Content must be an array for blocks-to-markdown");let t=x(e);return{direction:a.direction,char_count:t.length,markdown:t}}default:throw new Error(`Unsupported direction: ${a.direction}`)}})()}function R(a){let e={};for(let[t,r]of Object.entries(a)){if(r==null){e[t]=r;continue}typeof r=="string"?t==="Name"||t==="Title"||t.toLowerCase()==="title"?e[t]={title:[g(r)]}:e[t]={select:{name:r}}:typeof r=="number"?e[t]={number:r}:typeof r=="boolean"?e[t]={checkbox:r}:Array.isArray(r)&&r.length>0&&typeof r[0]=="string"?e[t]={multi_select:r.map(i=>({name:i}))}:e[t]=r}return e}async function S(a,e){return f(async()=>{switch(e.action){case"create":return await Y(a,e);case"get":return await ee(a,e);case"query":return await te(a,e);case"create_page":return await ae(a,e);case"update_page":return await re(a,e);case"delete_page":return await oe(a,e);case"create_data_source":return await ie(a,e);case"update_data_source":return await ne(a,e);case"update_database":return await se(a,e);default:throw new c(`Unknown action: ${e.action}`,"VALIDATION_ERROR","Supported actions: create, get, query, create_page, update_page, delete_page, create_data_source, update_data_source, update_database")}})()}async function Y(a,e){if(!e.parent_id||!e.title||!e.properties)throw new c("parent_id, title, and properties required for create action","VALIDATION_ERROR","Provide parent_id, title, and properties");let t={parent:{type:"page_id",page_id:e.parent_id},title:[g(e.title)],initial_data_source:{properties:e.properties}};e.description&&(t.description=[g(e.description)]),e.is_inline!==void 0&&(t.is_inline=e.is_inline);let r=await a.databases.create(t);return{action:"create",database_id:r.id,data_source_id:r.data_sources?.[0]?.id,url:r.url,created:!0}}async function ee(a,e){if(!e.database_id)throw new c("database_id required for get action","VALIDATION_ERROR","Provide database_id");let t=await a.databases.retrieve({database_id:e.database_id}),r={},i=null;if(t.data_sources&&t.data_sources.length>0){let o=await a.dataSources.retrieve({data_source_id:t.data_sources[0].id});if(i={id:o.id,name:o.title?.[0]?.plain_text||t.data_sources[0].name},o.properties)for(let[n,d]of Object.entries(o.properties)){let s=d;r[n]={type:s.type,id:s.id},s.type==="select"&&s.select?.options?r[n].options=s.select.options.map(u=>u.name):s.type==="multi_select"&&s.multi_select?.options?r[n].options=s.multi_select.options.map(u=>u.name):s.type==="formula"&&s.formula&&(r[n].expression=s.formula.expression)}}return{action:"get",database_id:t.id,title:t.title?.[0]?.plain_text||"Untitled",description:t.description?.[0]?.plain_text||"",url:t.url,is_inline:t.is_inline,created_time:t.created_time,last_edited_time:t.last_edited_time,data_source:i,schema:r}}async function te(a,e){if(!e.database_id)throw new c("database_id required for query action","VALIDATION_ERROR","Provide database_id");let t=await a.databases.retrieve({database_id:e.database_id});if(!t.data_sources||t.data_sources.length===0)throw new c("No data sources found in database","VALIDATION_ERROR","Database has no data sources");let r=t.data_sources[0].id,i=e.filters;if(e.search&&!i){let u=await a.dataSources.retrieve({data_source_id:r}),p=Object.entries(u.properties||{}).filter(([_,w])=>["title","rich_text"].includes(w.type)).map(([_])=>_);p.length>0&&(i={or:p.map(_=>({property:_,rich_text:{contains:e.search}}))})}let o={data_source_id:r};i&&(o.filter=i),e.sorts&&(o.sorts=e.sorts);let n=await m(async u=>{let p=await a.dataSources.query({...o,start_cursor:u,page_size:100});return{results:p.results,next_cursor:p.next_cursor,has_more:p.has_more}}),s=(e.limit?n.slice(0,e.limit):n).map(u=>{let p={page_id:u.id,url:u.url};for(let[_,w]of Object.entries(u.properties)){let l=w;l.type==="title"&&l.title?p[_]=l.title.map(k=>k.plain_text).join(""):l.type==="rich_text"&&l.rich_text?p[_]=l.rich_text.map(k=>k.plain_text).join(""):l.type==="select"&&l.select?p[_]=l.select.name:l.type==="multi_select"&&l.multi_select?p[_]=l.multi_select.map(k=>k.name):l.type==="number"?p[_]=l.number:l.type==="checkbox"?p[_]=l.checkbox:l.type==="url"?p[_]=l.url:l.type==="email"?p[_]=l.email:l.type==="phone_number"?p[_]=l.phone_number:l.type==="date"&&l.date&&(p[_]=l.date.start+(l.date.end?` to ${l.date.end}`:""))}return p});return{action:"query",database_id:e.database_id,data_source_id:r,total:s.length,results:s}}async function ae(a,e){if(!e.database_id)throw new c("database_id required","VALIDATION_ERROR","Provide database_id");let t=await a.databases.retrieve({database_id:e.database_id});if(!t.data_sources||t.data_sources.length===0)throw new c("No data sources found in database","VALIDATION_ERROR","Database has no data sources");let r=t.data_sources[0].id,i=e.pages||(e.page_properties?[{properties:e.page_properties}]:[]);if(i.length===0)throw new c("pages or page_properties required","VALIDATION_ERROR","Provide items to create");let o=[];for(let n of i){let d=R(n.properties),s=await a.pages.create({parent:{type:"data_source_id",data_source_id:r},properties:d});o.push({page_id:s.id,url:s.url,created:!0})}return{action:"create_page",database_id:e.database_id,data_source_id:r,processed:o.length,results:o}}async function re(a,e){let t=e.pages||(e.page_id&&e.page_properties?[{page_id:e.page_id,properties:e.page_properties}]:[]);if(t.length===0)throw new c("pages or page_id+page_properties required","VALIDATION_ERROR","Provide items to update");let r=[];for(let i of t){if(!i.page_id)throw new c("page_id required for each item","VALIDATION_ERROR","Provide page_id");let o=R(i.properties);await a.pages.update({page_id:i.page_id,properties:o}),r.push({page_id:i.page_id,updated:!0})}return{action:"update_page",processed:r.length,results:r}}async function oe(a,e){let t=e.page_ids||(e.page_id?[e.page_id]:[])||(e.pages?e.pages.map(i=>i.page_id).filter(Boolean):[]);if(t.length===0)throw new c("page_id or page_ids required","VALIDATION_ERROR","Provide page IDs to delete");let r=[];for(let i of t)await a.pages.update({page_id:i,archived:!0}),r.push({page_id:i,deleted:!0});return{action:"delete_page",processed:r.length,results:r}}async function ie(a,e){if(!e.database_id||!e.title||!e.properties)throw new c("database_id, title, and properties required","VALIDATION_ERROR","Provide database_id, title, and properties for new data source");let t={parent:{type:"database_id",database_id:e.database_id},title:[g(e.title)],properties:e.properties};return e.description&&(t.description=[g(e.description)]),{action:"create_data_source",data_source_id:(await a.dataSources.create(t)).id,database_id:e.database_id,created:!0}}async function ne(a,e){if(!e.data_source_id)throw new c("data_source_id required","VALIDATION_ERROR","Provide data_source_id");let t={};if(e.title&&(t.title=[g(e.title)]),e.description&&(t.description=[g(e.description)]),e.properties&&(t.properties=e.properties),Object.keys(t).length===0)throw new c("No updates provided","VALIDATION_ERROR","Provide title, description, or properties to update");return await a.dataSources.update({data_source_id:e.data_source_id,...t}),{action:"update_data_source",data_source_id:e.data_source_id,updated:!0}}async function se(a,e){if(!e.database_id)throw new c("database_id required","VALIDATION_ERROR","Provide database_id");let t={};if(e.parent_id&&(t.parent={type:"page_id",page_id:e.parent_id}),e.title&&(t.title=[g(e.title)]),e.description&&(t.description=[g(e.description)]),e.is_inline!==void 0&&(t.is_inline=e.is_inline),e.icon&&(t.icon={type:"emoji",emoji:e.icon}),e.cover&&(t.cover={type:"external",external:{url:e.cover}}),Object.keys(t).length===0)throw new c("No updates provided","VALIDATION_ERROR","Provide parent_id, title, description, is_inline, icon, or cover");return await a.databases.update({database_id:e.database_id,...t}),{action:"update_database",database_id:e.database_id,updated:!0}}async function j(a,e){return f(async()=>{switch(e.action){case"create":return await ce(a,e);case"get":return await de(a,e);case"update":return await le(a,e);case"archive":case"restore":return await pe(a,e);case"duplicate":return await ue(a,e);default:throw new c(`Unknown action: ${e.action}`,"VALIDATION_ERROR","Supported actions: create, get, update, archive, restore, move, duplicate")}})()}async function ce(a,e){if(!e.title)throw new c("title is required for create action","VALIDATION_ERROR","Provide page title");if(!e.parent_id)throw new c("parent_id is required for page creation","VALIDATION_ERROR","Integration tokens cannot create workspace-level pages. Provide parent_id (database or page ID).");let t=e.parent_id.replace(/-/g,""),r;e.properties&&Object.keys(e.properties).length>0?r={type:"database_id",database_id:t}:r={type:"page_id",page_id:t};let i={};r.database_id?(i=R(e.properties||{}),!i.title&&!i.Name&&!i.Title&&(i.Name={title:[g(e.title)]})):i={title:{title:[g(e.title)]}};let o={parent:r,properties:i};e.icon&&(o.icon={type:"emoji",emoji:e.icon}),e.cover&&(o.cover={type:"external",external:{url:e.cover}});let n=await a.pages.create(o);if(e.content){let d=h(e.content);d.length>0&&await a.blocks.children.append({block_id:n.id,children:d})}return{action:"create",page_id:n.id,url:n.url,created:!0}}async function de(a,e){if(!e.page_id)throw new c("page_id is required for get action","VALIDATION_ERROR","Provide page_id");let t=await a.pages.retrieve({page_id:e.page_id}),r=await m(n=>a.blocks.children.list({block_id:e.page_id,start_cursor:n,page_size:100})),i=x(r),o={};for(let[n,d]of Object.entries(t.properties)){let s=d;s.type==="title"&&s.title?o[n]=s.title.map(u=>u.plain_text).join(""):s.type==="rich_text"&&s.rich_text?o[n]=s.rich_text.map(u=>u.plain_text).join(""):s.type==="select"&&s.select?o[n]=s.select.name:s.type==="multi_select"&&s.multi_select?o[n]=s.multi_select.map(u=>u.name):s.type==="number"?o[n]=s.number:s.type==="checkbox"?o[n]=s.checkbox:s.type==="url"?o[n]=s.url:s.type==="email"?o[n]=s.email:s.type==="phone_number"?o[n]=s.phone_number:s.type==="date"&&s.date&&(o[n]=s.date.start+(s.date.end?` to ${s.date.end}`:""))}return{action:"get",page_id:t.id,url:t.url,created_time:t.created_time,last_edited_time:t.last_edited_time,archived:t.archived,properties:o,content:i,block_count:r.length}}async function le(a,e){if(!e.page_id)throw new c("page_id is required for update action","VALIDATION_ERROR","Provide page_id");let t={};if(e.icon&&(t.icon={type:"emoji",emoji:e.icon}),e.cover&&(t.cover={type:"external",external:{url:e.cover}}),e.archived!==void 0&&(t.archived=e.archived),(e.properties||e.title)&&(t.properties={},e.title&&(t.properties.title={title:[g(e.title)]}),e.properties)){let r=R(e.properties);t.properties={...t.properties,...r}}if(Object.keys(t).length>0&&await a.pages.update({page_id:e.page_id,...t}),e.content||e.append_content||e.prepend_content){if(e.content){let r=await m(o=>a.blocks.children.list({block_id:e.page_id,start_cursor:o,page_size:100}));for(let o of r)await a.blocks.delete({block_id:o.id});let i=h(e.content);i.length>0&&await a.blocks.children.append({block_id:e.page_id,children:i})}else if(e.append_content){let r=h(e.append_content);r.length>0&&await a.blocks.children.append({block_id:e.page_id,children:r})}else if(e.prepend_content){let r=await m(o=>a.blocks.children.list({block_id:e.page_id,start_cursor:o,page_size:1})),i=h(e.prepend_content);i.length>0&&(r[0]?.id?await a.blocks.children.append({block_id:e.page_id,children:i,after:void 0}):await a.blocks.children.append({block_id:e.page_id,children:i}))}}return{action:"update",page_id:e.page_id,updated:!0}}async function pe(a,e){let t=e.page_ids||(e.page_id?[e.page_id]:[]);if(t.length===0)throw new c("page_id or page_ids required","VALIDATION_ERROR","Provide at least one page ID");let r=e.action==="archive",i=[];for(let o of t)await a.pages.update({page_id:o,archived:r}),i.push({page_id:o,archived:r});return{action:e.action,processed:i.length,results:i}}async function ue(a,e){let t=e.page_ids||(e.page_id?[e.page_id]:[]);if(t.length===0)throw new c("page_id or page_ids required","VALIDATION_ERROR","Provide at least one page ID");let r=[];for(let i of t){let o=await a.pages.retrieve({page_id:i}),n=await m(s=>a.blocks.children.list({block_id:i,start_cursor:s,page_size:100})),d=await a.pages.create({parent:o.parent,properties:o.properties,icon:o.icon,cover:o.cover});n.length>0&&await a.blocks.children.append({block_id:d.id,children:n}),r.push({original_id:i,duplicate_id:d.id,url:d.url})}return{action:"duplicate",processed:r.length,results:r}}async function L(a,e){return f(async()=>{switch(e.action){case"list":{let t=await m(r=>a.users.list({start_cursor:r,page_size:100}));return{action:"list",total:t.length,users:t.map(r=>({id:r.id,type:r.type,name:r.name||"Unknown",avatar_url:r.avatar_url,email:r.type==="person"?r.person?.email:void 0}))}}case"get":{if(!e.user_id)throw new c("user_id required for get action","VALIDATION_ERROR","Provide user_id");let t=await a.users.retrieve({user_id:e.user_id});return{action:"get",id:t.id,type:t.type,name:t.name||"Unknown",avatar_url:t.avatar_url,email:t.type==="person"?t.person?.email:void 0}}case"me":{let t=await a.users.retrieve({user_id:"me"});return{action:"me",id:t.id,type:t.type,name:t.name||"Bot",bot:t.bot}}case"from_workspace":{let t=await a.search({filter:{property:"object",value:"page"},page_size:100}),r=new Map;for(let o of t.results)o.created_by&&r.set(o.created_by.id,{id:o.created_by.id,type:o.created_by.object,source:"page_metadata"}),o.last_edited_by&&r.set(o.last_edited_by.id,{id:o.last_edited_by.id,type:o.last_edited_by.object,source:"page_metadata"});let i=Array.from(r.values());return{action:"from_workspace",total:i.length,users:i,note:'Users extracted from accessible pages. Use "me" action for bot info, or share more pages for more users.'}}default:throw new c(`Unknown action: ${e.action}`,"VALIDATION_ERROR","Supported actions: list, get, me, from_workspace")}})()}async function U(a,e){return f(async()=>{switch(e.action){case"info":{let t=await a.users.retrieve({user_id:"me"});return{action:"info",bot:{id:t.id,name:t.name||"Bot",type:t.type,owner:t.bot?.owner}}}case"search":{let t={query:e.query||""};e.filter?.object&&(t.filter={value:e.filter.object,property:"object"}),e.sort&&(t.sort={direction:e.sort.direction||"descending",timestamp:e.sort.timestamp||"last_edited_time"});let r=await m(o=>a.search({...t,start_cursor:o,page_size:100})),i=e.limit?r.slice(0,e.limit):r;return{action:"search",query:e.query,total:i.length,results:i.map(o=>({id:o.id,object:o.object,title:o.object==="page"?o.properties?.title?.title?.[0]?.plain_text||o.properties?.Name?.title?.[0]?.plain_text||"Untitled":o.title?.[0]?.plain_text||"Untitled",url:o.url,last_edited_time:o.last_edited_time}))}}default:throw new c(`Unknown action: ${e.action}`,"VALIDATION_ERROR","Supported actions: info, search")}})()}var we=ge(import.meta.url),O=_e(we),V=O.endsWith("bin")?v(O,"..","build","src","docs"):v(O,"..","docs"),N=[{uri:"notion://docs/pages",name:"Pages Tool Docs",file:"pages.md"},{uri:"notion://docs/databases",name:"Databases Tool Docs",file:"databases.md"},{uri:"notion://docs/blocks",name:"Blocks Tool Docs",file:"blocks.md"},{uri:"notion://docs/users",name:"Users Tool Docs",file:"users.md"},{uri:"notion://docs/workspace",name:"Workspace Tool Docs",file:"workspace.md"},{uri:"notion://docs/comments",name:"Comments Tool Docs",file:"comments.md"},{uri:"notion://docs/content_convert",name:"Content Convert Tool Docs",file:"content_convert.md"}],M=[{name:"pages",description:"Page lifecycle: create, get, update, archive, restore, duplicate. Requires parent_id for create. Returns markdown content for get.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","get","update","archive","restore","duplicate"],description:"Action to perform"},page_id:{type:"string",description:"Page ID (required for most actions)"},page_ids:{type:"array",items:{type:"string"},description:"Multiple page IDs for batch operations"},title:{type:"string",description:"Page title"},content:{type:"string",description:"Markdown content"},append_content:{type:"string",description:"Markdown to append"},prepend_content:{type:"string",description:"Markdown to prepend"},parent_id:{type:"string",description:"Parent page or database ID"},properties:{type:"object",description:"Page properties (for database pages)"},icon:{type:"string",description:"Emoji icon"},cover:{type:"string",description:"Cover image URL"},archived:{type:"boolean",description:"Archive status"}},required:["action"]}},{name:"databases",description:"Database operations: create, get, query, create_page, update_page, delete_page, create_data_source, update_data_source, update_database. Databases contain data sources with schema and rows.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["create","get","query","create_page","update_page","delete_page","create_data_source","update_data_source","update_database"],description:"Action to perform"},database_id:{type:"string",description:"Database ID (container)"},data_source_id:{type:"string",description:"Data source ID (for update_data_source action)"},parent_id:{type:"string",description:"Parent page ID (for create/update_database)"},title:{type:"string",description:"Title (for database or data source)"},description:{type:"string",description:"Description"},properties:{type:"object",description:"Schema properties (for create/update data source)"},is_inline:{type:"boolean",description:"Display as inline (for create/update_database)"},icon:{type:"string",description:"Emoji icon (for update_database)"},cover:{type:"string",description:"Cover image URL (for update_database)"},filters:{type:"object",description:"Query filters (for query action)"},sorts:{type:"array",items:{type:"object"},description:"Query sorts"},limit:{type:"number",description:"Max query results"},search:{type:"string",description:"Smart search across text fields (for query)"},page_id:{type:"string",description:"Single page ID (for update_page)"},page_ids:{type:"array",items:{type:"string"},description:"Multiple page IDs (for delete_page)"},page_properties:{type:"object",description:"Page properties to update (for update_page)"},pages:{type:"array",items:{type:"object"},description:"Array of pages for bulk create/update"}},required:["action"]}},{name:"blocks",description:"Block-level content: get, children, append, update, delete. Page IDs are valid block IDs. Use for precise edits.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["get","children","append","update","delete"],description:"Action to perform"},block_id:{type:"string",description:"Block ID"},content:{type:"string",description:"Markdown content (for append/update)"}},required:["action","block_id"]}},{name:"users",description:"User info: list, get, me, from_workspace. Use from_workspace if list fails due to permissions.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["list","get","me","from_workspace"],description:"Action to perform"},user_id:{type:"string",description:"User ID (for get action)"}},required:["action"]}},{name:"workspace",description:"Workspace: info, search. Search returns pages/databases shared with integration. Use filter.object for type.",inputSchema:{type:"object",properties:{action:{type:"string",enum:["info","search"],description:"Action to perform"},query:{type:"string",description:"Search query"},filter:{type:"object",properties:{object:{type:"string",enum:["page","data_source"]}}},sort:{type:"object",properties:{direction:{type:"string",enum:["ascending","descending"]},timestamp:{type:"string",enum:["last_edited_time","created_time"]}}},limit:{type:"number",description:"Max results"}},required:["action"]}},{name:"comments",description:"Comments: list, create. Use page_id for new discussion, discussion_id for replies.",inputSchema:{type:"object",properties:{page_id:{type:"string",description:"Page ID"},discussion_id:{type:"string",description:"Discussion ID (for replies)"},action:{type:"string",enum:["list","create"],description:"Action to perform"},content:{type:"string",description:"Comment content (for create)"}},required:["action"]}},{name:"content_convert",description:"Convert: markdown-to-blocks, blocks-to-markdown. Most tools handle markdown automatically.",inputSchema:{type:"object",properties:{direction:{type:"string",enum:["markdown-to-blocks","blocks-to-markdown"],description:"Conversion direction"},content:{description:"Content to convert (string or array/JSON string)"}},required:["direction","content"]}},{name:"help",description:"Get full documentation for a tool. Use when compressed descriptions are insufficient.",inputSchema:{type:"object",properties:{tool_name:{type:"string",enum:["pages","databases","blocks","users","workspace","comments","content_convert"],description:"Tool to get documentation for"}},required:["tool_name"]}}];function $(a,e){let t=new be({auth:e,notionVersion:"2025-09-03"});a.setRequestHandler(he,async()=>({tools:M})),a.setRequestHandler(fe,async()=>({resources:N.map(r=>({uri:r.uri,name:r.name,mimeType:"text/markdown"}))})),a.setRequestHandler(ye,async r=>{let{uri:i}=r.params,o=N.find(d=>d.uri===i);if(!o)throw new c(`Resource not found: ${i}`,"RESOURCE_NOT_FOUND",`Available: ${N.map(d=>d.uri).join(", ")}`);let n=B(v(V,o.file),"utf-8");return{contents:[{uri:i,mimeType:"text/markdown",text:n}]}}),a.setRequestHandler(me,async r=>{let{name:i,arguments:o}=r.params;if(!o)return{content:[{type:"text",text:"Error: No arguments provided"}],isError:!0};try{let n;switch(i){case"pages":n=await j(t,o);break;case"databases":n=await S(t,o);break;case"blocks":n=await E(t,o);break;case"users":n=await L(t,o);break;case"workspace":n=await U(t,o);break;case"comments":n=await C(t,o);break;case"content_convert":n=await q(o);break;case"help":{let d=o.tool_name,s=`${d}.md`;try{let u=B(v(V,s),"utf-8");n={tool:d,documentation:u}}catch{throw new c(`Documentation not found for: ${d}`,"DOC_NOT_FOUND","Check tool_name")}break}default:throw new c(`Unknown tool: ${i}`,"UNKNOWN_TOOL",`Available tools: ${M.map(d=>d.name).join(", ")}`)}return{content:[{type:"text",text:JSON.stringify(n,null,2)}]}}catch(n){let d=n instanceof c?n:new c(n.message,"TOOL_ERROR","Check the error details and try again");return{content:[{type:"text",text:D(d)}],isError:!0}}})}async function H(){let a=process.env.NOTION_TOKEN;a||(console.error("NOTION_TOKEN environment variable is required"),console.error("Get your token from https://www.notion.so/my-integrations"),process.exit(1));let e=new ke({name:"@n24q02m/better-notion-mcp",version:"1.0.0"},{capabilities:{tools:{},resources:{}}});$(e,a);let t=new xe;return await e.connect(t),e}async function Re(){try{await H(),process.on("SIGINT",()=>{console.error(`
|
|
11
|
+
Shutting down Better Notion MCP Server`),process.exit(0)})}catch(a){console.error("Failed to start server:",a),process.exit(1)}}Re();
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Blocks Tool - Full Documentation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Block-level content: get, children, append, update, delete.
|
|
5
|
+
|
|
6
|
+
## Important
|
|
7
|
+
- **Page IDs are valid block IDs** (page is root block)
|
|
8
|
+
- Use for **precise edits** within pages
|
|
9
|
+
- For full page content, use pages tool instead
|
|
10
|
+
|
|
11
|
+
## Actions
|
|
12
|
+
|
|
13
|
+
### get
|
|
14
|
+
```json
|
|
15
|
+
{"action": "get", "block_id": "xxx"}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### children
|
|
19
|
+
```json
|
|
20
|
+
{"action": "children", "block_id": "xxx"}
|
|
21
|
+
```
|
|
22
|
+
Returns markdown of child blocks.
|
|
23
|
+
|
|
24
|
+
### append
|
|
25
|
+
```json
|
|
26
|
+
{"action": "append", "block_id": "page-id", "content": "## New Section\nParagraph text"}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### update
|
|
30
|
+
```json
|
|
31
|
+
{"action": "update", "block_id": "block-id", "content": "Updated text"}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### delete
|
|
35
|
+
```json
|
|
36
|
+
{"action": "delete", "block_id": "block-id"}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Parameters
|
|
40
|
+
- `block_id` - Block ID (required)
|
|
41
|
+
- `content` - Markdown content (for append/update)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Comments Tool - Full Documentation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Comments: list, create.
|
|
5
|
+
|
|
6
|
+
## Threading
|
|
7
|
+
- Use `page_id` for new discussion
|
|
8
|
+
- Use `discussion_id` (from list) for replies
|
|
9
|
+
|
|
10
|
+
## Actions
|
|
11
|
+
|
|
12
|
+
### list
|
|
13
|
+
```json
|
|
14
|
+
{"action": "list", "page_id": "xxx"}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### create (new discussion)
|
|
18
|
+
```json
|
|
19
|
+
{"action": "create", "page_id": "xxx", "content": "Great work!"}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### create (reply)
|
|
23
|
+
```json
|
|
24
|
+
{"action": "create", "discussion_id": "thread-id", "content": "I agree"}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Parameters
|
|
28
|
+
- `page_id` - Page ID
|
|
29
|
+
- `discussion_id` - Discussion ID (for replies)
|
|
30
|
+
- `content` - Comment content
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Content Convert Tool - Full Documentation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Convert: markdown-to-blocks, blocks-to-markdown.
|
|
5
|
+
|
|
6
|
+
## Note
|
|
7
|
+
Most tools (pages, blocks) handle markdown automatically. Use this for preview/validation only.
|
|
8
|
+
|
|
9
|
+
## Actions
|
|
10
|
+
|
|
11
|
+
### markdown-to-blocks
|
|
12
|
+
```json
|
|
13
|
+
{"direction": "markdown-to-blocks", "content": "# Heading\nParagraph\n- List item"}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### blocks-to-markdown
|
|
17
|
+
```json
|
|
18
|
+
{"direction": "blocks-to-markdown", "content": [{"type": "paragraph", "paragraph": {...}}]}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Parameters
|
|
22
|
+
- `direction` - "markdown-to-blocks" or "blocks-to-markdown"
|
|
23
|
+
- `content` - String (markdown) or array (blocks)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Databases Tool - Full Documentation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Database operations: create, get, query, create_page, update_page, delete_page, create_data_source, update_data_source, update_database.
|
|
5
|
+
|
|
6
|
+
## Architecture
|
|
7
|
+
- **Database** = container holding one or more data sources
|
|
8
|
+
- **Data Source** = has schema (properties) and rows (pages)
|
|
9
|
+
|
|
10
|
+
## Workflow
|
|
11
|
+
1. create → Creates database + initial data source
|
|
12
|
+
2. get → Retrieves data_source_id
|
|
13
|
+
3. query/create_page/update_page → Uses data_source_id (auto-fetched)
|
|
14
|
+
|
|
15
|
+
## Actions
|
|
16
|
+
|
|
17
|
+
### create
|
|
18
|
+
```json
|
|
19
|
+
{"action": "create", "parent_id": "xxx", "title": "Tasks", "properties": {"Status": {"select": {"options": [{"name": "Todo"}, {"name": "Done"}]}}}}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### get
|
|
23
|
+
```json
|
|
24
|
+
{"action": "get", "database_id": "xxx"}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### query
|
|
28
|
+
```json
|
|
29
|
+
{"action": "query", "database_id": "xxx", "filters": {"property": "Status", "select": {"equals": "Done"}}}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### create_page
|
|
33
|
+
```json
|
|
34
|
+
{"action": "create_page", "database_id": "xxx", "pages": [{"properties": {"Name": "Task 1", "Status": "Todo"}}]}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### update_page
|
|
38
|
+
```json
|
|
39
|
+
{"action": "update_page", "page_id": "yyy", "page_properties": {"Status": "Done"}}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### delete_page
|
|
43
|
+
```json
|
|
44
|
+
{"action": "delete_page", "page_ids": ["yyy", "zzz"]}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Parameters
|
|
48
|
+
- `database_id` - Database ID
|
|
49
|
+
- `data_source_id` - Data source ID
|
|
50
|
+
- `parent_id` - Parent page ID
|
|
51
|
+
- `title` - Title
|
|
52
|
+
- `properties` - Schema properties
|
|
53
|
+
- `filters` / `sorts` / `limit` - Query options
|
|
54
|
+
- `search` - Smart search across text fields
|
|
55
|
+
- `pages` - Array of pages for bulk operations
|
|
56
|
+
- `page_properties` - Properties to update
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Pages Tool - Full Documentation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Page lifecycle: create, get, update, archive, restore, duplicate.
|
|
5
|
+
|
|
6
|
+
## Important
|
|
7
|
+
- **parent_id required** for create (cannot create workspace-level pages)
|
|
8
|
+
- Returns **markdown content** for get action
|
|
9
|
+
|
|
10
|
+
## Actions
|
|
11
|
+
|
|
12
|
+
### create
|
|
13
|
+
```json
|
|
14
|
+
{"action": "create", "title": "Meeting Notes", "parent_id": "xxx", "content": "# Agenda\n- Item 1"}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### get
|
|
18
|
+
```json
|
|
19
|
+
{"action": "get", "page_id": "xxx"}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### update
|
|
23
|
+
```json
|
|
24
|
+
{"action": "update", "page_id": "xxx", "append_content": "\n## New Section"}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### archive
|
|
28
|
+
```json
|
|
29
|
+
{"action": "archive", "page_ids": ["xxx", "yyy"]}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### restore
|
|
33
|
+
```json
|
|
34
|
+
{"action": "restore", "page_id": "xxx"}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### duplicate
|
|
38
|
+
```json
|
|
39
|
+
{"action": "duplicate", "page_id": "xxx"}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Parameters
|
|
43
|
+
- `page_id` - Page ID (required for most actions)
|
|
44
|
+
- `page_ids` - Multiple page IDs for batch operations
|
|
45
|
+
- `title` - Page title
|
|
46
|
+
- `content` - Markdown content
|
|
47
|
+
- `append_content` / `prepend_content` - Markdown to add
|
|
48
|
+
- `parent_id` - Parent page or database ID
|
|
49
|
+
- `properties` - Page properties (for database pages)
|
|
50
|
+
- `icon` - Emoji icon
|
|
51
|
+
- `cover` - Cover image URL
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Users Tool - Full Documentation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
User info: list, get, me, from_workspace.
|
|
5
|
+
|
|
6
|
+
## Important
|
|
7
|
+
- `list` may fail without user:read permission
|
|
8
|
+
- Use `from_workspace` as fallback (extracts from page metadata)
|
|
9
|
+
|
|
10
|
+
## Actions
|
|
11
|
+
|
|
12
|
+
### me
|
|
13
|
+
```json
|
|
14
|
+
{"action": "me"}
|
|
15
|
+
```
|
|
16
|
+
Returns bot/integration info.
|
|
17
|
+
|
|
18
|
+
### list
|
|
19
|
+
```json
|
|
20
|
+
{"action": "list"}
|
|
21
|
+
```
|
|
22
|
+
Requires user:read permission.
|
|
23
|
+
|
|
24
|
+
### get
|
|
25
|
+
```json
|
|
26
|
+
{"action": "get", "user_id": "xxx"}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### from_workspace
|
|
30
|
+
```json
|
|
31
|
+
{"action": "from_workspace"}
|
|
32
|
+
```
|
|
33
|
+
Extracts users from created_by/last_edited_by in accessible pages.
|
|
34
|
+
|
|
35
|
+
## Parameters
|
|
36
|
+
- `user_id` - User ID (for get action)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Workspace Tool - Full Documentation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Workspace: info, search.
|
|
5
|
+
|
|
6
|
+
## Important
|
|
7
|
+
- Search returns only content **shared with integration**
|
|
8
|
+
- Use `filter.object = "data_source"` for databases
|
|
9
|
+
|
|
10
|
+
## Actions
|
|
11
|
+
|
|
12
|
+
### info
|
|
13
|
+
```json
|
|
14
|
+
{"action": "info"}
|
|
15
|
+
```
|
|
16
|
+
Returns bot owner, workspace details.
|
|
17
|
+
|
|
18
|
+
### search
|
|
19
|
+
```json
|
|
20
|
+
{"action": "search", "query": "meeting notes", "filter": {"object": "page"}, "limit": 10}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Search databases:
|
|
24
|
+
```json
|
|
25
|
+
{"action": "search", "query": "tasks", "filter": {"object": "data_source"}}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Sort results:
|
|
29
|
+
```json
|
|
30
|
+
{"action": "search", "query": "project", "sort": {"direction": "descending", "timestamp": "last_edited_time"}}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Parameters
|
|
34
|
+
- `query` - Search query
|
|
35
|
+
- `filter.object` - "page" or "data_source"
|
|
36
|
+
- `sort.direction` - "ascending" or "descending"
|
|
37
|
+
- `sort.timestamp` - "last_edited_time" or "created_time"
|
|
38
|
+
- `limit` - Max results
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init-server.d.ts","sourceRoot":"","sources":["../../src/init-server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAIlE,wBAAsB,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"init-server.d.ts","sourceRoot":"","sources":["../../src/init-server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAIlE,wBAAsB,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA+B/B"}
|
package/build/src/init-server.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init-server.js","sourceRoot":"","sources":["../../src/init-server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAEnD,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,oCAAoC;IACpC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAA;IAE5C,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAA;QAC9D,OAAO,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAA;QAC1E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,oBAAoB;IACpB,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB;QACE,IAAI,EAAE,4BAA4B;QAClC,OAAO,EAAE,OAAO;KACjB,EACD;QACE,YAAY,EAAE;YACZ,KAAK,EAAE,EAAE;
|
|
1
|
+
{"version":3,"file":"init-server.js","sourceRoot":"","sources":["../../src/init-server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAEnD,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,oCAAoC;IACpC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAA;IAE5C,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAA;QAC9D,OAAO,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAA;QAC1E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,oBAAoB;IACpB,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB;QACE,IAAI,EAAE,4BAA4B;QAClC,OAAO,EAAE,OAAO;KACjB,EACD;QACE,YAAY,EAAE;YACZ,KAAK,EAAE,EAAE;YACT,SAAS,EAAE,EAAE;SACd;KACF,CACF,CAAA;IAED,2BAA2B;IAC3B,aAAa,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;IAElC,0BAA0B;IAC1B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAA;IAC5C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IAC/B,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/tools/registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/tools/registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAoOvE;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,QAyHhE"}
|