From better-notion-mcp
Transforms unstructured Notion pages into structured databases with correct property types, schema design, and migration via Notion API actions.
npx claudepluginhub n24q02m/claude-plugins --plugin better-notion-mcpThis skill uses the workspace's default tool permissions.
Transform unstructured Notion pages into a well-designed, queryable database.
Transforms unstructured Notion pages into structured databases with correct property types, schema design, and migration via Notion API actions.
Migrates data to/from Notion databases or between workspaces with property mapping, validation, rate limiting. For CSV/JSON imports, exports, syncing, ETL pipelines.
Automates Notion operations like creating/updating pages, querying/managing databases, blocks, comments, users via Rube MCP and Composio tools. Requires Rube MCP connection and Notion OAuth.
Share bugs, ideas, or general feedback.
Transform unstructured Notion pages into a well-designed, queryable database.
Choose the right property type -- LLMs frequently pick the wrong one:
| Data pattern | Correct type | Wrong choice (common mistake) |
|---|---|---|
| Fixed categories (status, priority) | select | rich_text (loses filtering) |
| Multiple tags per item | multi_select | select (only allows one) |
| References to other DBs | relation | rich_text (breaks linking) |
| Computed from relations | rollup | formula (can't aggregate across DBs) |
| True/false flags | checkbox | select with Yes/No (over-engineered) |
| Long-form content | Page body (blocks) | rich_text property (2000 char limit) |
Every property value MUST use the correct nested format. The Notion API rejects flat values.
// WRONG -- flat values (API will error or silently fail)
{
"Tags": "engineering",
"Status": "In Progress",
"Description": "Some text"
}
// CORRECT -- properly typed nested objects
{
"Tags": { "multi_select": [{ "name": "engineering" }] },
"Status": { "select": { "name": "In Progress" } },
"Description": { "rich_text": [{ "text": { "content": "Some text" } }] },
"Name": { "title": [{ "text": { "content": "Page title" } }] },
"Done": { "checkbox": true },
"Due Date": { "date": { "start": "2026-03-23" } },
"URL": { "url": "https://example.com" },
"Count": { "number": 42 },
"Contact": { "email": "user@example.com" }
}
Key gotcha: rich_text is an ARRAY of text objects, never a plain string.
Audit existing content -- find the pages to organize:
pages(action="search", query="<topic>") to locate scattered pagesDesign schema -- create the database with identified properties:
databases(action="create", parent_id="<parent_page_id>", title="...", properties={
"Name": { "title": {} },
"Category": { "select": { "options": [{ "name": "..." }] } },
"Tags": { "multi_select": { "options": [{ "name": "..." }] } },
...
})
select for status/category -- it enables Notion's board view.Bulk-create pages from existing content:
pages(action="create", parent_id="<database_id>", properties={...}, content=[...])Archive old pages (only after user confirms migration looks correct):
blocks(action="delete", block_id="<old_page_block_id>") or move to archive pageVerify the new database:
databases(action="query", database_id="<id>") to list all entries