notion-mcp-server 2.9.0 → 2.10.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.
@@ -53,6 +53,34 @@ register({
53
53
  return { ok: true, data: slimDataSource(ds, verbose ?? false) };
54
54
  }),
55
55
  });
56
+ const ListDataSourceTemplatesParams = z.object({
57
+ data_source_id: z.string().describe("Data source ID to list templates for."),
58
+ name: z.string().optional().describe("Case-insensitive substring filter on template name."),
59
+ start_cursor: z.string().optional(),
60
+ page_size: z.number().int().min(1).max(100).optional(),
61
+ });
62
+ register({
63
+ name: "list_data_source_templates",
64
+ access: "read",
65
+ domain: "data_sources",
66
+ description: "List the page templates available for a data source. Returns {id, name, is_default} per template. Pass a returned id as template.template_id to create_page to apply it.",
67
+ batchable: false,
68
+ schema: ListDataSourceTemplatesParams,
69
+ example: { data_source_id: "<data-source-id>" },
70
+ handler: tryHandler(async ({ data_source_id, name, start_cursor, page_size }) => {
71
+ const notion = await getClient();
72
+ const res = await notion.dataSources.listTemplates({
73
+ data_source_id,
74
+ ...(name !== undefined ? { name } : {}),
75
+ ...(start_cursor !== undefined ? { start_cursor } : {}),
76
+ ...(page_size !== undefined ? { page_size } : {}),
77
+ });
78
+ return {
79
+ ok: true,
80
+ data: { data_source_id, templates: res.templates },
81
+ };
82
+ }),
83
+ });
56
84
  const UpdateDataSourceParams = z.object({
57
85
  data_source_id: z.string(),
58
86
  title: z.array(z.unknown()).optional().describe("Rich text array for the data source title."),
@@ -47,12 +47,26 @@ const CreatePageParams = z
47
47
  properties: z.record(z.string(), PROPERTY_VALUE_SCHEMA).optional(),
48
48
  markdown: z.string().optional().describe("Page body as markdown. Parsed server-side."),
49
49
  children: z.array(z.unknown()).optional().describe("Structured Notion blocks. Mutually exclusive with markdown."),
50
+ template: z
51
+ .object({
52
+ type: z.enum(["default", "none", "template_id"]).describe("`template_id` to apply a specific template, `default` for the data source's default template, `none` for no template."),
53
+ template_id: z.string().optional().describe("Required when type is 'template_id'. Discover IDs via list_data_source_templates."),
54
+ timezone: z.string().optional().describe("IANA tz (e.g. 'Asia/Hong_Kong') controlling @now/@today resolution inside the template."),
55
+ })
56
+ .optional()
57
+ .describe("Create the page from a Notion template. The API forbids `markdown`/`children` alongside a template; only data_source_id parents support templates."),
50
58
  icon: ICON_SCHEMA.nullable().optional(),
51
59
  cover: FILE_SCHEMA.nullable().optional(),
52
60
  verbose: VERBOSE,
53
61
  })
54
62
  .refine((v) => !(v.markdown && v.children), {
55
63
  message: "Pass either `markdown` or `children`, not both.",
64
+ })
65
+ .refine((v) => !(v.template && (v.markdown || v.children)), {
66
+ message: "Pass either a `template` or body content (`markdown`/`children`), not both — the Notion API rejects children alongside a template.",
67
+ })
68
+ .refine((v) => !(v.template?.type === "template_id" && !v.template.template_id), {
69
+ message: "template.template_id is required when template.type is 'template_id'.",
56
70
  });
57
71
  register({
58
72
  name: "create_page",
@@ -100,14 +114,18 @@ register({
100
114
  title: [{ type: "text", text: { content: params.title } }],
101
115
  };
102
116
  }
103
- const children = params.markdown
104
- ? parseMarkdownToBlocks(params.markdown)
105
- : params.children;
117
+ // A template and explicit body content are mutually exclusive (API rule).
118
+ const children = params.template
119
+ ? undefined
120
+ : params.markdown
121
+ ? parseMarkdownToBlocks(params.markdown)
122
+ : params.children;
106
123
  const notion = await getClient();
107
124
  const body = {
108
125
  parent,
109
126
  properties,
110
127
  ...(children && children.length ? { children } : {}),
128
+ ...(params.template ? { template: params.template } : {}),
111
129
  ...(params.icon !== undefined ? { icon: params.icon } : {}),
112
130
  ...(params.cover !== undefined ? { cover: params.cover } : {}),
113
131
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "notion-mcp-server",
3
- "version": "2.9.0",
3
+ "version": "2.10.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "notion-mcp-server": "build/index.js"