@atikk-co-jp/notion-mcp-server 0.12.0 → 0.14.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.ja.md CHANGED
@@ -120,7 +120,9 @@ Notionのタスクデータベースから、特定の条件でタスクを取
120
120
  | | [Update block](https://developers.notion.com/reference/update-a-block) | `update-block` 📤 | JSON | `{id}` |
121
121
  | | | `update-block-simple` ⭐📤 | Markdown | `{id}` |
122
122
  | | [Delete block](https://developers.notion.com/reference/delete-a-block) | `delete-block` 📤 | JSON | `{id}` |
123
- | | [Retrieve block children](https://developers.notion.com/reference/get-block-children) | `get-block-children` | JSON | **markdown**/json |
123
+ | | | `delete-blocks-batch` 📤 | JSON | `{deleted_count, failed_count}` |
124
+ | | | `clear-page-content` 📤 | JSON | `{deleted_count, failed_count}` |
125
+ | | [Retrieve block children](https://developers.notion.com/reference/get-block-children) | `get-block-children` | JSON | **markdown**/simple/json |
124
126
  | | [Append block children](https://developers.notion.com/reference/patch-block-children) | `append-block-children` 📤 | JSON | `{block_ids}` |
125
127
  | | | `append-blocks-simple` ⭐📤 | Markdown | `{block_ids}` |
126
128
  | **ページコンテンツ** | | | | |
@@ -226,6 +228,7 @@ Markdownを使ってページを作成します。`create-page`と比較して**
226
228
  - ブックマーク: `[bookmark](url)` または `[bookmark:キャプション](url)`
227
229
  - カラム: `:::columns` / `:::column` / `:::`
228
230
  - メディア: `@[embed](url)`, `@[video](url)`, `@[audio](url)`, `@[file](url)`, `@[pdf](url)`
231
+ - 目次: `[TOC]`
229
232
 
230
233
  **子ページを作成:**
231
234
  ```json
@@ -409,8 +412,9 @@ Markdownを使ってページを作成します。`create-page`と比較して**
409
412
  - `block_id` (必須): 子ブロックを取得するブロックまたはページのID
410
413
  - `start_cursor` (任意): ページネーション用カーソル
411
414
  - `page_size` (任意): 返す結果の数 (1-100)
412
- - `format` (任意): 出力形式 - `"markdown"` (デフォルト) または `"json"`
415
+ - `format` (任意): 出力形式 - `"markdown"` (デフォルト)、`"simple"`、または `"json"`
413
416
  - `markdown`: トークン使用量を大幅に削減(約96%削減)した人間が読みやすいマークダウン形式
417
+ - `simple`: ID + タイプ + Markdownコンテンツ(軽量、削除対象選定用)
414
418
  - `json`: Notion APIのレスポンスをそのまま返す
415
419
  - `fetch_nested` (任意): `format="markdown"`の時、ネストされた子ブロックを再帰的に取得する(デフォルト: false)
416
420
 
@@ -422,6 +426,25 @@ Markdownを使ってページを作成します。`create-page`と比較して**
422
426
  }
423
427
  ```
424
428
 
429
+ **削除対象のブロックIDを取得:**
430
+ ```json
431
+ {
432
+ "block_id": "ページまたはブロックのUUID",
433
+ "format": "simple"
434
+ }
435
+ ```
436
+
437
+ レスポンス:
438
+ ```json
439
+ {
440
+ "blocks": [
441
+ { "id": "abc123", "type": "heading_1", "content": "# タイトル" },
442
+ { "id": "def456", "type": "paragraph", "content": "本文テキスト" }
443
+ ],
444
+ "has_more": false
445
+ }
446
+ ```
447
+
425
448
  ### append-block-children
426
449
 
427
450
  ページまたはブロックに新しいブロックを追加します。
@@ -529,6 +552,62 @@ Markdownを使ってブロックを追加します。`append-block-children`と
529
552
 
530
553
  **対象ブロックタイプ:** paragraph, heading_1/2/3, bulleted_list_item, numbered_list_item, to_do, quote, callout, toggle
531
554
 
555
+ ### delete-blocks-batch
556
+
557
+ 複数のブロックをIDで一括削除します。APIレート制限(3 req/s)を尊重して順次削除します。
558
+
559
+ **パラメータ:**
560
+ - `block_ids` (必須): 削除するブロックIDの配列(最大100件)
561
+
562
+ **使い分け:** 特定のブロックを選んで削除したい場合。事前に `get-block-children` で `format="simple"` を使ってブロックIDを取得してください。
563
+
564
+ ```json
565
+ {
566
+ "block_ids": ["block-uuid-1", "block-uuid-2", "block-uuid-3"]
567
+ }
568
+ ```
569
+
570
+ レスポンス:
571
+ ```json
572
+ {
573
+ "deleted_count": 3,
574
+ "failed_count": 0,
575
+ "deleted": ["block-uuid-1", "block-uuid-2", "block-uuid-3"]
576
+ }
577
+ ```
578
+
579
+ ### clear-page-content
580
+
581
+ ページの全コンテンツを削除します。デフォルトで `child_database` と `child_page` ブロックは保護されます。
582
+
583
+ **パラメータ:**
584
+ - `page_id` (必須): 削除するページのID
585
+ - `preserve_types` (任意): 保護するブロックタイプ(デフォルト: `["child_database", "child_page"]`)。`[]`を指定するとすべて削除。
586
+
587
+ **使い分け:** 個々のブロックを選択せずにページ全体のコンテンツを削除したい場合。
588
+
589
+ ```json
590
+ {
591
+ "page_id": "ページのUUID"
592
+ }
593
+ ```
594
+
595
+ **すべて削除(子データベース/ページも含む):**
596
+ ```json
597
+ {
598
+ "page_id": "ページのUUID",
599
+ "preserve_types": []
600
+ }
601
+ ```
602
+
603
+ レスポンス:
604
+ ```json
605
+ {
606
+ "deleted_count": 15,
607
+ "failed_count": 0
608
+ }
609
+ ```
610
+
532
611
  ### create-comment
533
612
 
534
613
  ページにコメントを追加します。
package/README.md CHANGED
@@ -120,7 +120,9 @@ That's it! Restart your AI client and start using Notion.
120
120
  | | [Update block](https://developers.notion.com/reference/update-a-block) | `update-block` 📤 | JSON | `{id}` |
121
121
  | | | `update-block-simple` ⭐📤 | Markdown | `{id}` |
122
122
  | | [Delete block](https://developers.notion.com/reference/delete-a-block) | `delete-block` 📤 | JSON | `{id}` |
123
- | | [Retrieve block children](https://developers.notion.com/reference/get-block-children) | `get-block-children` | JSON | **markdown**/json |
123
+ | | | `delete-blocks-batch` 📤 | JSON | `{deleted_count, failed_count}` |
124
+ | | | `clear-page-content` 📤 | JSON | `{deleted_count, failed_count}` |
125
+ | | [Retrieve block children](https://developers.notion.com/reference/get-block-children) | `get-block-children` | JSON | **markdown**/simple/json |
124
126
  | | [Append block children](https://developers.notion.com/reference/patch-block-children) | `append-block-children` 📤 | JSON | `{block_ids}` |
125
127
  | | | `append-blocks-simple` ⭐📤 | Markdown | `{block_ids}` |
126
128
  | | | `replace-page-content` ⭐📤 | Markdown | `{deleted_count, created_count}` |
@@ -225,6 +227,7 @@ Supports two parent types:
225
227
  - Bookmark: `[bookmark](url)` or `[bookmark:caption](url)`
226
228
  - Columns: `:::columns` / `:::column` / `:::`
227
229
  - Media: `@[embed](url)`, `@[video](url)`, `@[audio](url)`, `@[file](url)`, `@[pdf](url)`
230
+ - Table of contents: `[TOC]`
228
231
 
229
232
  **Create a child page:**
230
233
  ```json
@@ -408,8 +411,9 @@ Get the child blocks of a page or block.
408
411
  - `block_id` (required): The ID of the block or page to get children from
409
412
  - `start_cursor` (optional): Cursor for pagination
410
413
  - `page_size` (optional): Number of results to return (1-100)
411
- - `format` (optional): Output format - `"markdown"` (default) or `"json"`
414
+ - `format` (optional): Output format - `"markdown"` (default), `"simple"`, or `"json"`
412
415
  - `markdown`: Returns human-readable markdown with significantly reduced token usage (~96% reduction)
416
+ - `simple`: Returns ID + type + markdown content (lightweight, for deletion target selection)
413
417
  - `json`: Returns raw Notion API response
414
418
  - `fetch_nested` (optional): When `format="markdown"`, fetch nested children blocks recursively (default: false)
415
419
 
@@ -421,6 +425,25 @@ Get the child blocks of a page or block.
421
425
  }
422
426
  ```
423
427
 
428
+ **Get block IDs for deletion:**
429
+ ```json
430
+ {
431
+ "block_id": "page-or-block-uuid-here",
432
+ "format": "simple"
433
+ }
434
+ ```
435
+
436
+ Returns:
437
+ ```json
438
+ {
439
+ "blocks": [
440
+ { "id": "abc123", "type": "heading_1", "content": "# Title" },
441
+ { "id": "def456", "type": "paragraph", "content": "Some text" }
442
+ ],
443
+ "has_more": false
444
+ }
445
+ ```
446
+
424
447
  ### append-block-children
425
448
 
426
449
  Append new blocks to a page or block.
@@ -524,6 +547,62 @@ Find text in a page and replace it with new content. Supports regex patterns for
524
547
  }
525
548
  ```
526
549
 
550
+ ### delete-blocks-batch
551
+
552
+ Delete multiple blocks by their IDs. Blocks are deleted sequentially to respect API rate limits (3 req/s).
553
+
554
+ **Parameters:**
555
+ - `block_ids` (required): Array of block IDs to delete (max 100)
556
+
557
+ **Use when:** You want to delete specific blocks. Use `get-block-children` with `format="simple"` to get block IDs first.
558
+
559
+ ```json
560
+ {
561
+ "block_ids": ["block-uuid-1", "block-uuid-2", "block-uuid-3"]
562
+ }
563
+ ```
564
+
565
+ Returns:
566
+ ```json
567
+ {
568
+ "deleted_count": 3,
569
+ "failed_count": 0,
570
+ "deleted": ["block-uuid-1", "block-uuid-2", "block-uuid-3"]
571
+ }
572
+ ```
573
+
574
+ ### clear-page-content
575
+
576
+ Delete all content from a page. By default, preserves `child_database` and `child_page` blocks.
577
+
578
+ **Parameters:**
579
+ - `page_id` (required): The page ID to clear
580
+ - `preserve_types` (optional): Block types to preserve (default: `["child_database", "child_page"]`). Set to `[]` to delete all.
581
+
582
+ **Use when:** You want to delete all content from a page without selecting individual blocks.
583
+
584
+ ```json
585
+ {
586
+ "page_id": "page-uuid-here"
587
+ }
588
+ ```
589
+
590
+ **Delete everything (including child databases/pages):**
591
+ ```json
592
+ {
593
+ "page_id": "page-uuid-here",
594
+ "preserve_types": []
595
+ }
596
+ ```
597
+
598
+ Returns:
599
+ ```json
600
+ {
601
+ "deleted_count": 15,
602
+ "failed_count": 0
603
+ }
604
+ ```
605
+
527
606
  ### create-comment
528
607
 
529
608
  Add a comment to a page.
@@ -791,4 +791,32 @@ const x = 1
791
791
  expect(result[3].type).toBe('paragraph');
792
792
  });
793
793
  });
794
+ describe('table_of_contents', () => {
795
+ it('converts [TOC] to table_of_contents', () => {
796
+ const blocks = markdownToBlocks('[TOC]');
797
+ expect(blocks).toHaveLength(1);
798
+ expect(blocks[0].type).toBe('table_of_contents');
799
+ expect(getBlockProp(blocks[0], 'table_of_contents')).toEqual({ color: 'default' });
800
+ });
801
+ it('converts [toc] (lowercase) to table_of_contents', () => {
802
+ const blocks = markdownToBlocks('[toc]');
803
+ expect(blocks).toHaveLength(1);
804
+ expect(blocks[0].type).toBe('table_of_contents');
805
+ });
806
+ it('converts [Toc] (mixed case) to table_of_contents', () => {
807
+ const blocks = markdownToBlocks('[Toc]');
808
+ expect(blocks).toHaveLength(1);
809
+ expect(blocks[0].type).toBe('table_of_contents');
810
+ });
811
+ it('handles [TOC] with surrounding whitespace', () => {
812
+ const blocks = markdownToBlocks(' [TOC] ');
813
+ expect(blocks).toHaveLength(1);
814
+ expect(blocks[0].type).toBe('table_of_contents');
815
+ });
816
+ it('does not convert [TOC] inside text', () => {
817
+ const blocks = markdownToBlocks('See [TOC] for details');
818
+ expect(blocks).toHaveLength(1);
819
+ expect(blocks[0].type).toBe('paragraph');
820
+ });
821
+ });
794
822
  });
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-to-blocks.d.ts","sourceRoot":"","sources":["../../../src/converters/markdown-to-blocks.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAO7D;;GAEG;AACH,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE;QACJ,OAAO,EAAE,MAAM,CAAA;QACf,IAAI,CAAC,EAAE;YAAE,GAAG,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAA;KAC9B,CAAA;IACD,WAAW,CAAC,EAAE;QACZ,IAAI,CAAC,EAAE,OAAO,CAAA;QACd,MAAM,CAAC,EAAE,OAAO,CAAA;QAChB,aAAa,CAAC,EAAE,OAAO,CAAA;QACvB,SAAS,CAAC,EAAE,OAAO,CAAA;QACnB,IAAI,CAAC,EAAE,OAAO,CAAA;QACd,KAAK,CAAC,EAAE,MAAM,CAAA;KACf,CAAA;CACF;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,EAAE,CA6JnE;AAmBD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAqcvE"}
1
+ {"version":3,"file":"markdown-to-blocks.d.ts","sourceRoot":"","sources":["../../../src/converters/markdown-to-blocks.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAO7D;;GAEG;AACH,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE;QACJ,OAAO,EAAE,MAAM,CAAA;QACf,IAAI,CAAC,EAAE;YAAE,GAAG,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAA;KAC9B,CAAA;IACD,WAAW,CAAC,EAAE;QACZ,IAAI,CAAC,EAAE,OAAO,CAAA;QACd,MAAM,CAAC,EAAE,OAAO,CAAA;QAChB,aAAa,CAAC,EAAE,OAAO,CAAA;QACvB,SAAS,CAAC,EAAE,OAAO,CAAA;QACnB,IAAI,CAAC,EAAE,OAAO,CAAA;QACd,KAAK,CAAC,EAAE,MAAM,CAAA;KACf,CAAA;CACF;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,EAAE,CA6JnE;AAmBD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,EAAE,CA+cvE"}
@@ -232,6 +232,15 @@ export function markdownToBlocks(markdown) {
232
232
  i++;
233
233
  continue;
234
234
  }
235
+ // 目次: [TOC] (case-insensitive)
236
+ if (/^\[toc\]$/i.test(line.trim())) {
237
+ blocks.push({
238
+ type: 'table_of_contents',
239
+ table_of_contents: { color: 'default' },
240
+ });
241
+ i++;
242
+ continue;
243
+ }
235
244
  // 見出し: # ## ### (####以上はheading_3にフォールバック)
236
245
  const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
237
246
  if (headingMatch) {
@@ -54,7 +54,10 @@ export declare const Fields: {
54
54
  readonly desc: "Number of results (1-100)";
55
55
  };
56
56
  readonly format: {
57
- readonly desc: "Output format: 'simple' or 'json'";
57
+ readonly desc: {
58
+ readonly default: "Output format: 'simple' or 'json'";
59
+ readonly block_children: "Output format: 'markdown' (default, human-readable), 'simple' (ID + type + content, for deletion), 'json' (full API response)";
60
+ };
58
61
  };
59
62
  readonly properties: {
60
63
  readonly desc: {
@@ -149,6 +152,7 @@ export declare const F: { [K in keyof typeof Fields]: string; } & {
149
152
  data_source_id_target: string;
150
153
  properties_schema: string;
151
154
  properties_update: string;
155
+ format_block_children: string;
152
156
  filter_search: string;
153
157
  icon_emoji: string;
154
158
  markdown_syntax_short: string;
@@ -1 +1 @@
1
- {"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../../../src/schemas/descriptions/fields.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;CAC9D;AAED;;;GAGG;AACH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqL2B,CAAA;AAE9C;;;;;;;GAOG;AACH,eAAO,MAAM,CAAC,EAgBN,GAAG,CAAC,IAAI,MAAM,OAAO,MAAM,GAAG,MAAM,GAAE,GAAG;IAE/C,cAAc,EAAE,MAAM,CAAA;IACtB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,iBAAiB,EAAE,MAAM,CAAA;IACzB,iBAAiB,EAAE,MAAM,CAAA;IACzB,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,qBAAqB,EAAE,MAAM,CAAA;CAC9B,CAAA"}
1
+ {"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../../../src/schemas/descriptions/fields.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAA;CAC9D;AAED;;;GAGG;AACH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyL2B,CAAA;AAE9C;;;;;;;GAOG;AACH,eAAO,MAAM,CAAC,EAgBN,GAAG,CAAC,IAAI,MAAM,OAAO,MAAM,GAAG,MAAM,GAAE,GAAG;IAE/C,cAAc,EAAE,MAAM,CAAA;IACtB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,iBAAiB,EAAE,MAAM,CAAA;IACzB,iBAAiB,EAAE,MAAM,CAAA;IACzB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,qBAAqB,EAAE,MAAM,CAAA;CAC9B,CAAA"}
@@ -53,7 +53,10 @@ export const Fields = {
53
53
  // Format
54
54
  // ============================================
55
55
  format: {
56
- desc: "Output format: 'simple' or 'json'",
56
+ desc: {
57
+ default: "Output format: 'simple' or 'json'",
58
+ block_children: "Output format: 'markdown' (default, human-readable), 'simple' (ID + type + content, for deletion), 'json' (full API response)",
59
+ },
57
60
  },
58
61
  // ============================================
59
62
  // Properties
@@ -81,9 +84,9 @@ export const Fields = {
81
84
  desc: {
82
85
  default: 'Markdown: # headings, - lists, - [ ] checkboxes, ``` code, > quotes, | tables |, ![]() images, **bold**, *italic*, ~~strike~~, `code`, [links](). ' +
83
86
  'Extended: <details><summary> toggle, > [!NOTE/WARNING/TIP/IMPORTANT/CAUTION] callout, $$ equation, <u>/++ underline, {color:x}{/color}, {bg:x}{/bg}, ' +
84
- '[bookmark](), :::columns, @[embed/video/audio/file/pdf]().',
87
+ '[bookmark](), :::columns, @[embed/video/audio/file/pdf](), [TOC] table of contents.',
85
88
  short: '# headings, - lists, - [ ] checkboxes, ``` code, > quotes, | tables |, **bold**, *italic*, [links](), ' +
86
- '<details> toggle, > [!NOTE] callout, $$ equation.',
89
+ '<details> toggle, > [!NOTE] callout, $$ equation, [TOC] table of contents.',
87
90
  },
88
91
  },
89
92
  // ============================================
@@ -133,7 +133,7 @@ describe('Tool context size', () => {
133
133
  });
134
134
  });
135
135
  describe('Description length checks', () => {
136
- const MAX_DESCRIPTION_LENGTH = 500;
136
+ const MAX_DESCRIPTION_LENGTH = 600;
137
137
  it.each(toolNames)('%s description should be concise', (toolName) => {
138
138
  const tool = registeredTools[toolName];
139
139
  const descLength = tool.description?.length ?? 0;
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { type NotionClient } from '../notion-client.js';
3
+ export declare function registerClearPageContent(server: McpServer, notion: NotionClient): void;
4
+ //# sourceMappingURL=clear-page-content.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clear-page-content.d.ts","sourceRoot":"","sources":["../../../src/tools/clear-page-content.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAExE,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAcpE,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CAmEtF"}
@@ -0,0 +1,63 @@
1
+ import { z } from 'zod';
2
+ import { isFullBlock } from '../notion-client.js';
3
+ import { F } from '../schemas/descriptions/index.js';
4
+ import { formatSimpleResponse, handleError } from '../utils/index.js';
5
+ const inputSchema = {
6
+ page_id: z.string().describe(F.page_id),
7
+ preserve_types: z
8
+ .array(z.string())
9
+ .optional()
10
+ .describe('Block types to preserve (default: ["child_database", "child_page"]). Set to empty array [] to delete all.'),
11
+ };
12
+ export function registerClearPageContent(server, notion) {
13
+ server.registerTool('clear-page-content', {
14
+ description: 'Delete all content from a page. By default, preserves child_database and child_page blocks. ' +
15
+ 'Use preserve_types=[] to delete everything. ' +
16
+ 'For deleting specific blocks, use delete-blocks-batch instead. ' +
17
+ 'Blocks are deleted sequentially to respect API rate limits (3 req/s). ' +
18
+ 'Returns count of deleted blocks.',
19
+ inputSchema,
20
+ }, async ({ page_id, preserve_types = ['child_database', 'child_page'], }) => {
21
+ try {
22
+ // Collect all blocks to delete (handle pagination)
23
+ const blocksToDelete = [];
24
+ let cursor;
25
+ do {
26
+ const response = await notion.blocks.children.list({
27
+ block_id: page_id,
28
+ start_cursor: cursor,
29
+ });
30
+ const blocks = response.results.filter(isFullBlock);
31
+ for (const block of blocks) {
32
+ if (!preserve_types.includes(block.type)) {
33
+ blocksToDelete.push(block.id);
34
+ }
35
+ }
36
+ cursor = response.has_more ? (response.next_cursor ?? undefined) : undefined;
37
+ } while (cursor);
38
+ // Delete blocks
39
+ let deleted = 0;
40
+ const failed = [];
41
+ for (const id of blocksToDelete) {
42
+ try {
43
+ await notion.blocks.delete({ block_id: id });
44
+ deleted++;
45
+ }
46
+ catch (e) {
47
+ failed.push({
48
+ id,
49
+ error: e instanceof Error ? e.message : String(e),
50
+ });
51
+ }
52
+ }
53
+ return formatSimpleResponse({
54
+ deleted_count: deleted,
55
+ failed_count: failed.length,
56
+ failed: failed.length > 0 ? failed : undefined,
57
+ });
58
+ }
59
+ catch (error) {
60
+ return handleError(error);
61
+ }
62
+ });
63
+ }
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { NotionClient } from '../notion-client.js';
3
+ export declare function registerDeleteBlocksBatch(server: McpServer, notion: NotionClient): void;
4
+ //# sourceMappingURL=delete-blocks-batch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete-blocks-batch.d.ts","sourceRoot":"","sources":["../../../src/tools/delete-blocks-batch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAExE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAWvD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CAyCvF"}
@@ -0,0 +1,46 @@
1
+ import { z } from 'zod';
2
+ import { formatSimpleResponse, handleError } from '../utils/index.js';
3
+ const inputSchema = {
4
+ block_ids: z
5
+ .array(z.string())
6
+ .min(1)
7
+ .max(100)
8
+ .describe('Block IDs to delete (max 100). Use get-block-children with format="simple" to get IDs.'),
9
+ };
10
+ export function registerDeleteBlocksBatch(server, notion) {
11
+ server.registerTool('delete-blocks-batch', {
12
+ description: 'Delete multiple blocks by their IDs. Use this when you want to delete specific blocks. ' +
13
+ 'For deleting all content from a page, use clear-page-content instead. ' +
14
+ 'Blocks are deleted sequentially to respect API rate limits (3 req/s). ' +
15
+ 'Returns summary of deleted and failed blocks.',
16
+ inputSchema,
17
+ }, async ({ block_ids }) => {
18
+ try {
19
+ const results = {
20
+ deleted: [],
21
+ failed: [],
22
+ };
23
+ for (const id of block_ids) {
24
+ try {
25
+ await notion.blocks.delete({ block_id: id });
26
+ results.deleted.push(id);
27
+ }
28
+ catch (e) {
29
+ results.failed.push({
30
+ id,
31
+ error: e instanceof Error ? e.message : String(e),
32
+ });
33
+ }
34
+ }
35
+ return formatSimpleResponse({
36
+ deleted_count: results.deleted.length,
37
+ failed_count: results.failed.length,
38
+ deleted: results.deleted,
39
+ failed: results.failed.length > 0 ? results.failed : undefined,
40
+ });
41
+ }
42
+ catch (error) {
43
+ return handleError(error);
44
+ }
45
+ });
46
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"get-block-children.d.ts","sourceRoot":"","sources":["../../../src/tools/get-block-children.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAGxE,OAAO,EAAyC,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAY9F,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CA4CtF"}
1
+ {"version":3,"file":"get-block-children.d.ts","sourceRoot":"","sources":["../../../src/tools/get-block-children.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAGxE,OAAO,EAAyC,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAqB9F,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CA6DtF"}
@@ -2,12 +2,16 @@ import { z } from 'zod';
2
2
  import { blocksToMarkdown } from '../converters/index.js';
3
3
  import { isFullBlock } from '../notion-client.js';
4
4
  import { F } from '../schemas/descriptions/index.js';
5
- import { formatMarkdownResponse, formatPaginatedResponse, handleError } from '../utils/index.js';
5
+ import { formatMarkdownResponse, formatPaginatedResponse, formatSimpleResponse, handleError, } from '../utils/index.js';
6
6
  const inputSchema = {
7
7
  block_id: z.string().describe(F.block_id),
8
8
  start_cursor: z.string().optional().describe(F.start_cursor),
9
9
  page_size: z.number().min(1).max(100).optional().describe(F.page_size),
10
- format: z.enum(['json', 'markdown']).optional().default('markdown').describe(F.format),
10
+ format: z
11
+ .enum(['json', 'markdown', 'simple'])
12
+ .optional()
13
+ .default('markdown')
14
+ .describe(F.format_block_children),
11
15
  fetch_nested: z.boolean().optional().default(false).describe(F.fetch_nested),
12
16
  };
13
17
  export function registerGetBlockChildren(server, notion) {
@@ -39,6 +43,19 @@ export function registerGetBlockChildren(server, notion) {
39
43
  }
40
44
  return formatMarkdownResponse(markdown, response.has_more, response.next_cursor);
41
45
  }
46
+ if (format === 'simple') {
47
+ // Simple format: ID + type + markdown content (lightweight, for deletion target selection)
48
+ const simpleBlocks = await Promise.all(blocks.map(async (block) => ({
49
+ id: block.id,
50
+ type: block.type,
51
+ content: await blocksToMarkdown([block]),
52
+ })));
53
+ return formatSimpleResponse({
54
+ blocks: simpleBlocks,
55
+ has_more: response.has_more,
56
+ next_cursor: response.next_cursor,
57
+ });
58
+ }
42
59
  // JSON形式
43
60
  return formatPaginatedResponse(response.results, response.has_more, response.next_cursor);
44
61
  }
@@ -4,12 +4,14 @@ import { registerAppendBlockChildren } from './append-block-children.js';
4
4
  import { registerAppendBlocksSimple } from './append-blocks-simple.js';
5
5
  import { registerArchiveDatabase } from './archive-database.js';
6
6
  import { registerArchivePage } from './archive-page.js';
7
+ import { registerClearPageContent } from './clear-page-content.js';
7
8
  import { registerCreateComment } from './create-comment.js';
8
9
  import { registerCreateCommentSimple } from './create-comment-simple.js';
9
10
  import { registerCreateDatabase } from './create-database.js';
10
11
  import { registerCreatePage } from './create-page.js';
11
12
  import { registerCreatePageSimple } from './create-page-simple.js';
12
13
  import { registerDeleteBlock } from './delete-block.js';
14
+ import { registerDeleteBlocksBatch } from './delete-blocks-batch.js';
13
15
  import { registerFindAndReplaceInPage } from './find-and-replace-in-page.js';
14
16
  import { registerGetBlockChildren } from './get-block-children.js';
15
17
  import { registerListComments } from './list-comments.js';
@@ -31,5 +33,5 @@ import { registerUpdateDataSource } from './update-data-source.js';
31
33
  import { registerUpdateDatabase } from './update-database.js';
32
34
  import { registerUpdatePage } from './update-page.js';
33
35
  export declare function registerAllTools(server: McpServer, notion: NotionClient): void;
34
- export { registerRetrievePage, registerCreatePage, registerCreatePageSimple, registerUpdatePage, registerArchivePage, registerRetrievePageProperty, registerMovePage, registerCreateDatabase, registerUpdateDatabase, registerArchiveDatabase, registerRetrieveDatabase, registerRetrieveDataSource, registerQueryDataSource, registerUpdateDataSource, registerSearch, registerGetBlockChildren, registerAppendBlockChildren, registerAppendBlocksSimple, registerRetrieveBlock, registerUpdateBlock, registerUpdateBlockSimple, registerDeleteBlock, registerReplacePageContent, registerFindAndReplaceInPage, registerCreateComment, registerCreateCommentSimple, registerListComments, registerListUsers, registerRetrieveUser, registerRetrieveBotUser, };
36
+ export { registerRetrievePage, registerCreatePage, registerCreatePageSimple, registerUpdatePage, registerArchivePage, registerRetrievePageProperty, registerMovePage, registerCreateDatabase, registerUpdateDatabase, registerArchiveDatabase, registerRetrieveDatabase, registerRetrieveDataSource, registerQueryDataSource, registerUpdateDataSource, registerSearch, registerGetBlockChildren, registerAppendBlockChildren, registerAppendBlocksSimple, registerRetrieveBlock, registerUpdateBlock, registerUpdateBlockSimple, registerDeleteBlock, registerDeleteBlocksBatch, registerClearPageContent, registerReplacePageContent, registerFindAndReplaceInPage, registerCreateComment, registerCreateCommentSimple, registerListComments, registerListUsers, registerRetrieveUser, registerRetrieveBotUser, };
35
37
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAA;AACxE,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAA;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAA;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAA;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAA;AAC5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAA;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAA;AAChE,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAA;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAA;AAChE,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAA;AACtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAA;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAE,4BAA4B,EAAE,MAAM,6BAA6B,CAAA;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAA;AACpE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAA;AAClE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAErD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CA4C9E;AAED,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,wBAAwB,EACxB,kBAAkB,EAClB,mBAAmB,EACnB,4BAA4B,EAC5B,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,EACxB,0BAA0B,EAC1B,uBAAuB,EACvB,wBAAwB,EACxB,cAAc,EACd,wBAAwB,EACxB,2BAA2B,EAC3B,0BAA0B,EAC1B,qBAAqB,EACrB,mBAAmB,EACnB,yBAAyB,EACzB,mBAAmB,EACnB,0BAA0B,EAC1B,4BAA4B,EAC5B,qBAAqB,EACrB,2BAA2B,EAC3B,oBAAoB,EACpB,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,GACxB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/index.ts"],"names":[],"mappings":"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"}
@@ -2,12 +2,14 @@ import { registerAppendBlockChildren } from './append-block-children.js';
2
2
  import { registerAppendBlocksSimple } from './append-blocks-simple.js';
3
3
  import { registerArchiveDatabase } from './archive-database.js';
4
4
  import { registerArchivePage } from './archive-page.js';
5
+ import { registerClearPageContent } from './clear-page-content.js';
5
6
  import { registerCreateComment } from './create-comment.js';
6
7
  import { registerCreateCommentSimple } from './create-comment-simple.js';
7
8
  import { registerCreateDatabase } from './create-database.js';
8
9
  import { registerCreatePage } from './create-page.js';
9
10
  import { registerCreatePageSimple } from './create-page-simple.js';
10
11
  import { registerDeleteBlock } from './delete-block.js';
12
+ import { registerDeleteBlocksBatch } from './delete-blocks-batch.js';
11
13
  import { registerFindAndReplaceInPage } from './find-and-replace-in-page.js';
12
14
  import { registerGetBlockChildren } from './get-block-children.js';
13
15
  import { registerListComments } from './list-comments.js';
@@ -56,6 +58,8 @@ export function registerAllTools(server, notion) {
56
58
  registerUpdateBlock(server, notion);
57
59
  registerUpdateBlockSimple(server, notion);
58
60
  registerDeleteBlock(server, notion);
61
+ registerDeleteBlocksBatch(server, notion);
62
+ registerClearPageContent(server, notion);
59
63
  registerReplacePageContent(server, notion);
60
64
  registerFindAndReplaceInPage(server, notion);
61
65
  // Comment operations
@@ -67,4 +71,4 @@ export function registerAllTools(server, notion) {
67
71
  registerRetrieveUser(server, notion);
68
72
  registerRetrieveBotUser(server, notion);
69
73
  }
70
- export { registerRetrievePage, registerCreatePage, registerCreatePageSimple, registerUpdatePage, registerArchivePage, registerRetrievePageProperty, registerMovePage, registerCreateDatabase, registerUpdateDatabase, registerArchiveDatabase, registerRetrieveDatabase, registerRetrieveDataSource, registerQueryDataSource, registerUpdateDataSource, registerSearch, registerGetBlockChildren, registerAppendBlockChildren, registerAppendBlocksSimple, registerRetrieveBlock, registerUpdateBlock, registerUpdateBlockSimple, registerDeleteBlock, registerReplacePageContent, registerFindAndReplaceInPage, registerCreateComment, registerCreateCommentSimple, registerListComments, registerListUsers, registerRetrieveUser, registerRetrieveBotUser, };
74
+ export { registerRetrievePage, registerCreatePage, registerCreatePageSimple, registerUpdatePage, registerArchivePage, registerRetrievePageProperty, registerMovePage, registerCreateDatabase, registerUpdateDatabase, registerArchiveDatabase, registerRetrieveDatabase, registerRetrieveDataSource, registerQueryDataSource, registerUpdateDataSource, registerSearch, registerGetBlockChildren, registerAppendBlockChildren, registerAppendBlocksSimple, registerRetrieveBlock, registerUpdateBlock, registerUpdateBlockSimple, registerDeleteBlock, registerDeleteBlocksBatch, registerClearPageContent, registerReplacePageContent, registerFindAndReplaceInPage, registerCreateComment, registerCreateCommentSimple, registerListComments, registerListUsers, registerRetrieveUser, registerRetrieveBotUser, };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atikk-co-jp/notion-mcp-server",
3
- "version": "0.12.0",
3
+ "version": "0.14.0",
4
4
  "description": "MCP server for Notion API - Create, read, update pages and databases",
5
5
  "type": "module",
6
6
  "license": "MIT",