@n24q02m/better-notion-mcp 1.1.0 → 2.0.0

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 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 pe}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as ue}from"@modelcontextprotocol/sdk/server/stdio.js";import{CallToolRequestSchema as ce,ListToolsRequestSchema as de}from"@modelcontextprotocol/sdk/types.js";import{Client as le}from"@notionhq/client";var c=class extends Error{constructor(t,r,o,i){super(t);this.code=r;this.suggestion=o;this.details=i;this.name="NotionMCPError"}toJSON(){return{error:this.name,code:this.code,message:this.message,suggestion:this.suggestion,details:this.details}}};function M(a){return a.code?B(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 B(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 P(a){let e=`Error: ${a.message}`;return a.suggestion&&(e+=`
3
+ import{Server as ke}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as xe}from"@modelcontextprotocol/sdk/server/stdio.js";import{readFileSync as U}from"node:fs";import{dirname as ue,join as O}from"node:path";import{fileURLToPath as _e}from"node:url";import{CallToolRequestSchema as ge,ListResourcesRequestSchema as me,ListToolsRequestSchema as fe,ReadResourceRequestSchema as he}from"@modelcontextprotocol/sdk/types.js";import{Client as ye}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 H(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 N(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 M(t)}}}function h(a){let e=a.split(`
8
- `),t=[],r=[],o=null;for(let i=0;i<e.length;i++){let s=e[i];if(o&&!F(s)&&(t.push(...r),r=[],o=null),!!s.trim())if(s.startsWith("# "))t.push(v(1,s.slice(2)));else if(s.startsWith("## "))t.push(v(2,s.slice(3)));else if(s.startsWith("### "))t.push(v(3,s.slice(4)));else if(s.startsWith("```")){let d=s.slice(3).trim(),n=[];for(i++;i<e.length&&!e[i].startsWith("```");)n.push(e[i]),i++;t.push(z(n.join(`
9
- `),d))}else if(s.match(/^[-*]\s/)){let d=s.slice(2);o="bulleted",r.push($(d))}else if(s.match(/^\d+\.\s/)){let d=s.replace(/^\d+\.\s/,"");o="numbered",r.push(H(d))}else s.startsWith("> ")?t.push(G(s.slice(2))):s.match(/^[-*]{3,}$/)?t.push(W()):t.push(V(s))}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(`# ${b(t.heading_1.rich_text)}`);break;case"heading_2":e.push(`## ${b(t.heading_2.rich_text)}`);break;case"heading_3":e.push(`### ${b(t.heading_3.rich_text)}`);break;case"paragraph":e.push(b(t.paragraph.rich_text));break;case"bulleted_list_item":e.push(`- ${b(t.bulleted_list_item.rich_text)}`);break;case"numbered_list_item":e.push(`1. ${b(t.numbered_list_item.rich_text)}`);break;case"code":e.push(`\`\`\`${t.code.language||""}`),e.push(b(t.code.rich_text)),e.push("```");break;case"quote":e.push(`> ${b(t.quote.rich_text)}`);break;case"divider":e.push("---");break;default:break}return e.join(`
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 H(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&&!Z(n)&&(t.push(...r),r=[],i=null),!!n.trim())if(n.startsWith("# "))t.push(v(1,n.slice(2)));else if(n.startsWith("## "))t.push(v(2,n.slice(3)));else if(n.startsWith("### "))t.push(v(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(K(s.join(`
9
+ `),d))}else if(n.match(/^[-*]\s/)){let d=n.slice(2);i="bulleted",r.push(F(d))}else if(n.match(/^\d+\.\s/)){let d=n.replace(/^\d+\.\s/,"");i="numbered",r.push(J(d))}else n.startsWith("> ")?t.push(G(n.slice(2))):n.match(/^[-*]{3,}$/)?t.push(Q()):t.push(W(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 v(a,e){let t=`heading_${a}`;return{object:"block",type:t,[t]:{rich_text:I(e),color:"default"}}}function W(a){return{object:"block",type:"paragraph",paragraph:{rich_text:I(a),color:"default"}}}function F(a){return{object:"block",type:"bulleted_list_item",bulleted_list_item:{rich_text:I(a),color:"default"}}}function J(a){return{object:"block",type:"numbered_list_item",numbered_list_item:{rich_text:I(a),color:"default"}}}function K(a,e){return{object:"block",type:"code",code:{rich_text:[b(a)],language:e||"plain text"}}}function G(a){return{object:"block",type:"quote",quote:{rich_text:I(a),color:"default"}}}function Q(){return{object:"block",type:"divider",divider:{}}}function Z(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 D(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 E(a){return a.map(e=>e.text.content).join("")}async function A(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:E(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 C(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 q(a,e){return f(async()=>{switch(e.action){case"create":return await X(a,e);case"get":return await Y(a,e);case"query":return await ee(a,e);case"create_page":return await te(a,e);case"update_page":return await ae(a,e);case"delete_page":return await re(a,e);case"create_data_source":return await oe(a,e);case"update_data_source":return await ie(a,e);case"update_database":return await ne(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 X(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 Y(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 ee(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 te(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 ae(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 re(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 oe(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 ie(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 ne(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 S(a,e){return f(async()=>{switch(e.action){case"create":return await se(a,e);case"get":return await ce(a,e);case"update":return await de(a,e);case"archive":case"restore":return await le(a,e);case"duplicate":return await pe(a,e);default:throw new c(`Unknown action: ${e.action}`,"VALIDATION_ERROR","Supported actions: create, get, update, archive, restore, move, duplicate")}})()}async function se(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 ce(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 de(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 le(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 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=[];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 j(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 L(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 be=_e(import.meta.url),we=ue(be),B=O(we,"..","docs"),P=[{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"}],V=[{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 M(a,e){let t=new ye({auth:e,notionVersion:"2025-09-03"});a.setRequestHandler(fe,async()=>({tools:V})),a.setRequestHandler(me,async()=>({resources:P.map(r=>({uri:r.uri,name:r.name,mimeType:"text/markdown"}))})),a.setRequestHandler(he,async r=>{let{uri:i}=r.params,o=P.find(d=>d.uri===i);if(!o)throw new c(`Resource not found: ${i}`,"RESOURCE_NOT_FOUND",`Available: ${P.map(d=>d.uri).join(", ")}`);let n=U(O(B,o.file),"utf-8");return{contents:[{uri:i,mimeType:"text/markdown",text:n}]}}),a.setRequestHandler(ge,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 S(t,o);break;case"databases":n=await q(t,o);break;case"blocks":n=await D(t,o);break;case"users":n=await j(t,o);break;case"workspace":n=await L(t,o);break;case"comments":n=await A(t,o);break;case"content_convert":n=await C(o);break;case"help":{let d=o.tool_name,s=`${d}.md`;try{let u=U(O(B,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: ${V.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:N(d)}],isError:!0}}})}async function $(){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:{}}});M(e,a);let t=new xe;return await e.connect(t),e}async function Re(){try{await $(),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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA8B/B"}
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"}
@@ -19,7 +19,8 @@ export async function initServer() {
19
19
  version: '1.0.0'
20
20
  }, {
21
21
  capabilities: {
22
- tools: {}
22
+ tools: {},
23
+ resources: {}
23
24
  }
24
25
  });
25
26
  // Register composite tools
@@ -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;SACV;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
+ {"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;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAyRvE;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,QAmFhE"}
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;AAgOvE;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,QAyHhE"}