Notion
Workspace integration for pages, databases, and content management.
Provider: Notion
Authentication: OAuth (Integration Token)
Category: Productivity & Workspace
Credit Cost: 1 credit per operation
Overview
Notion tools enable AI agents to search, create, read, and manage content in your Notion workspace. Perfect for knowledge management, content creation, task tracking, and building automated workflows with your Notion data.
Key Concepts
Databases and Data Sources
With Notion's API version 2025-09-03:
- Database: A container that holds one or more data sources
- Data Source: A table/view within a database with its own schema (properties)
- Page: A document that can exist standalone or as a row in a data source
Typical workflow:
- Use
get_databaseto get the list of data sources in a database - Use
retrieve_data_sourceto get the schema (properties) of a data source - Use
query_data_sourceto query pages orcreate_pageto add entries
Setup
Get Notion Integration Token
- Go to Notion Integrations
- Click "New integration"
- Fill in:
- Name: Reeva MCP
- Associated workspace: Select your workspace
- Capabilities: Enable needed permissions (Read, Update, Insert)
- Click Submit
- Copy the Internal Integration Token (starts with
secret_)
Share Pages with Integration
Important: Your integration can only access pages you explicitly share with it.
- Open the Notion page or database you want to access
- Click Share in the top right
- Click "Invite"
- Search for your integration name and select it
- Click "Invite"
Add to Reeva
- Dashboard → Accounts → Add Account
- Select Notion
- Paste your Integration Token
- Click Save
Available Tools
Search Pages
Search for pages and data sources across your Notion workspace.
Tool ID: search_pages
Credit Cost: 1 credit
Parameters:
query(string, optional): Search query string- Default:
""(returns all accessible items)
- Default:
object_filter(string, optional): Filter by object type- Options:
"page","data_source"
- Options:
page_size(integer, optional): Number of results to return- Default: 10
- Maximum: 100
start_cursor(string, optional): Pagination cursor from previous response
Response:
{
"results": [
{
"id": "abc123-def456",
"title": "Project Notes",
"url": "https://www.notion.so/Project-Notes-abc123",
"type": "page",
"created_time": "2025-11-22T10:30:00.000Z",
"last_edited_time": "2025-11-22T15:45:00.000Z"
}
],
"has_more": false,
"next_cursor": null
}
Example Usage:
# Python - Search for pages
response = client.call_tool(
name="search_pages",
arguments={
"query": "meeting notes",
"page_size": 20
}
)
for result in response["results"]:
print(f"{result['title']}: {result['url']}")
// TypeScript - Find databases only
const response = await client.callTool({
name: "search_pages",
arguments: {
query: "tasks",
object_filter: "data_source",
page_size: 10
}
});
Use Cases:
- Find specific pages by keyword
- Discover databases in workspace
- Build page navigation
- Search before creating duplicates
Get Page
Retrieve page properties and metadata.
Tool ID: get_page
Credit Cost: 1 credit
Parameters:
page_id(string, required): The ID of the page to retrieve
Response:
{
"id": "abc123-def456",
"object": "page",
"created_time": "2025-11-22T10:30:00.000Z",
"last_edited_time": "2025-11-22T15:45:00.000Z",
"properties": {
"Name": {
"title": [{"plain_text": "My Page Title"}]
},
"Status": {
"status": {"name": "In Progress"}
}
},
"url": "https://www.notion.so/My-Page-abc123"
}
Example Usage:
# Python - Get page properties
response = client.call_tool(
name="get_page",
arguments={"page_id": "abc123-def456-ghi789"}
)
title = response["properties"]["Name"]["title"][0]["plain_text"]
print(f"Page: {title}")
Use Cases:
- Read page properties
- Check page status
- Get page metadata
- Validate page exists
Get Page Content
Retrieve complete page content including all blocks.
Tool ID: get_page_content
Credit Cost: 1 credit
Parameters:
page_id(string, required): The ID of the page to retrieve content from
Response:
{
"page_id": "abc123-def456",
"blocks": [
{
"type": "heading_1",
"heading_1": {
"rich_text": [{"plain_text": "Welcome"}]
}
},
{
"type": "paragraph",
"paragraph": {
"rich_text": [{"plain_text": "This is the content..."}]
}
}
],
"markdown": "# Welcome\n\nThis is the content...",
"block_count": 2
}
Example Usage:
# Python - Get page as markdown
response = client.call_tool(
name="get_page_content",
arguments={"page_id": "abc123-def456"}
)
# Use the markdown representation
markdown_content = response["markdown"]
print(f"Content ({response['block_count']} blocks):")
print(markdown_content)
// TypeScript - Read and process content
const response = await client.callTool({
name: "get_page_content",
arguments: {
page_id: "abc123-def456"
}
});
// Process individual blocks
response.blocks.forEach(block => {
console.log(`Block type: ${block.type}`);
});
Use Cases:
- Read full page content
- Extract text for analysis
- Convert Notion to markdown
- Build content pipelines
Create Page
Create a new page under a parent page or in a data source.
Tool ID: create_page
Credit Cost: 1 credit
Parameters:
title(string, required): Title for the new pageparent_page_id(string, optional): ID of parent pageparent_data_source_id(string, optional): ID of parent data source (for database entries)content(string, optional): Markdown content for the pageproperties(object, optional): Page properties (for data source entries)template_type(string, optional): Template type- Options:
"none","default","template_id" - Default:
"none"
- Options:
template_id(string, optional): Template ID (whentemplate_typeis"template_id")
Response:
{
"id": "new-page-id",
"url": "https://www.notion.so/New-Page-newpageid"
}
Example Usage:
# Python - Create a simple page under a parent
response = client.call_tool(
name="create_page",
arguments={
"title": "Meeting Notes - Nov 22",
"parent_page_id": "parent-page-id",
"content": "# Agenda\n\n- Review Q4 goals\n- Discuss roadmap\n\n# Action Items\n\n- [ ] Follow up with team"
}
)
print(f"Created: {response['url']}")
// TypeScript - Add entry to database
const response = await client.callTool({
name: "create_page",
arguments: {
title: "New Task",
parent_data_source_id: "data-source-id",
properties: {
"Status": {
"status": {"name": "To Do"}
},
"Priority": {
"select": {"name": "High"}
},
"Due Date": {
"date": {"start": "2025-11-30"}
}
}
}
});
# cURL - Create page with template
curl -X POST https://api.joinreeva.com/mcp/server_YOUR_ID \
-H "Authorization: Bearer mcpk_your_key" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "create_page",
"arguments": {
"title": "Weekly Report",
"parent_data_source_id": "reports-ds-id",
"template_type": "default"
}
},
"id": 1
}'
Use Cases:
- Create documentation pages
- Add tasks to databases
- Store research findings
- Log events and data
Get Database
Retrieve database metadata and list of data sources.
Tool ID: get_database
Credit Cost: 1 credit
Parameters:
database_id(string, required): ID of the database to retrieve
Response:
{
"id": "database-id",
"object": "database",
"title": [{"plain_text": "Project Tracker"}],
"data_sources": [
{
"id": "data-source-id-1",
"name": "Tasks"
},
{
"id": "data-source-id-2",
"name": "Milestones"
}
]
}
Example Usage:
# Python - Get database data sources
response = client.call_tool(
name="get_database",
arguments={"database_id": "your-database-id"}
)
print(f"Database: {response['title'][0]['plain_text']}")
print("Data Sources:")
for ds in response["data_sources"]:
print(f" - {ds['name']} ({ds['id']})")
Use Cases:
- Discover data sources in a database
- Get data source IDs for querying
- Understand database structure
Retrieve Data Source
Get the full schema (properties) of a data source.
Tool ID: retrieve_data_source
Credit Cost: 1 credit
Parameters:
data_source_id(string, required): ID of the data source to retrieve
Response:
{
"id": "data-source-id",
"object": "data_source",
"properties": {
"Name": {
"id": "title",
"type": "title",
"title": {}
},
"Status": {
"id": "status",
"type": "status",
"status": {
"options": [
{"name": "To Do", "color": "gray"},
{"name": "In Progress", "color": "blue"},
{"name": "Done", "color": "green"}
]
}
},
"Priority": {
"id": "priority",
"type": "select",
"select": {
"options": [
{"name": "High", "color": "red"},
{"name": "Medium", "color": "yellow"},
{"name": "Low", "color": "green"}
]
}
}
}
}
Example Usage:
# Python - Get data source schema
response = client.call_tool(
name="retrieve_data_source",
arguments={"data_source_id": "data-source-id"}
)
print("Available properties:")
for prop_name, prop_info in response["properties"].items():
print(f" {prop_name}: {prop_info['type']}")
Use Cases:
- Understand database schema before creating pages
- Get available status/select options
- Validate property names
- Build dynamic forms
Query Data Source
Query pages from a data source with filtering and sorting.
Tool ID: query_data_source
Credit Cost: 1 credit
Parameters:
data_source_id(string, required): ID of the data source to queryfilter(string, optional): JSON string representing filter criteriasorts(string, optional): JSON string or array of sort objectspage_size(integer, optional): Number of results (1-100)- Default: 10
start_cursor(string, optional): Pagination cursorfilter_properties(array, optional): Property names to include in results
Response:
{
"results": [
{
"id": "page-id-1",
"properties": {
"Name": {"title": [{"plain_text": "Task 1"}]},
"Status": {"status": {"name": "In Progress"}}
}
}
],
"has_more": true,
"next_cursor": "cursor-string"
}
Example Usage:
# Python - Query with filter
response = client.call_tool(
name="query_data_source",
arguments={
"data_source_id": "tasks-ds-id",
"filter": '{"property": "Status", "status": {"equals": "In Progress"}}',
"page_size": 20
}
)
for page in response["results"]:
title = page["properties"]["Name"]["title"][0]["plain_text"]
print(f"Task: {title}")
// TypeScript - Query with sorting
const response = await client.callTool({
name: "query_data_source",
arguments: {
data_source_id: "tasks-ds-id",
filter: JSON.stringify({
"and": [
{"property": "Status", "status": {"does_not_equal": "Done"}},
{"property": "Priority", "select": {"equals": "High"}}
]
}),
sorts: JSON.stringify([
{"property": "Due Date", "direction": "ascending"}
]),
page_size: 50
}
});
Filter Examples:
// Equals
{"property": "Status", "status": {"equals": "Done"}}
// Contains text
{"property": "Name", "title": {"contains": "meeting"}}
// Date filter
{"property": "Due Date", "date": {"before": "2025-12-01"}}
// Checkbox
{"property": "Completed", "checkbox": {"equals": true}}
// AND condition
{
"and": [
{"property": "Status", "status": {"equals": "In Progress"}},
{"property": "Priority", "select": {"equals": "High"}}
]
}
// OR condition
{
"or": [
{"property": "Status", "status": {"equals": "To Do"}},
{"property": "Status", "status": {"equals": "In Progress"}}
]
}
Use Cases:
- List tasks by status
- Find overdue items
- Search database entries
- Build filtered views
Create Database
Create a new database with an initial data source.
Tool ID: create_database
Credit Cost: 1 credit
Parameters:
parent_page_id(string, optional): ID of parent pageparent_workspace(boolean, optional): Set to true for workspace-leveltitle(string, optional): Database titledescription(string, optional): Database descriptioninitial_data_source_properties(object, optional): Schema for initial data sourceicon(object, optional): Icon objectcover(object, optional): Cover image object
Response:
{
"id": "new-database-id",
"object": "database",
"data_sources": [
{
"id": "initial-ds-id",
"name": "My Database"
}
]
}
Example Usage:
# Python - Create task database
response = client.call_tool(
name="create_database",
arguments={
"parent_page_id": "parent-page-id",
"title": "Project Tasks",
"initial_data_source_properties": {
"Task Name": {"title": {}},
"Status": {"status": {}},
"Priority": {
"select": {
"options": [
{"name": "High", "color": "red"},
{"name": "Medium", "color": "yellow"},
{"name": "Low", "color": "green"}
]
}
},
"Due Date": {"date": {}},
"Assignee": {"people": {}}
}
}
)
print(f"Created database: {response['id']}")
Use Cases:
- Create project trackers
- Set up content calendars
- Build CRM databases
- Create structured data stores
Update Database
Update database-level properties.
Tool ID: update_database
Credit Cost: 1 credit
Parameters:
database_id(string, required): ID of database to updatetitle(string, optional): New titledescription(string, optional): New descriptionicon(object, optional): New iconcover(object, optional): New cover imageparent_page_id(string, optional): Move to new parentis_inline(boolean, optional): Toggle inline/full-page modein_trash(boolean, optional): Archive/unarchive
Example Usage:
# Python - Update database title
response = client.call_tool(
name="update_database",
arguments={
"database_id": "database-id",
"title": "Updated Project Tracker",
"description": "Tracking all Q4 projects"
}
)
Create Data Source
Add a new data source to an existing database.
Tool ID: create_data_source
Credit Cost: 1 credit
Parameters:
database_id(string, required): ID of parent databaseproperties(object, required): Schema for the data sourcetitle(string, optional): Data source titleicon(object, optional): Icon object
Example Usage:
# Python - Add new data source
response = client.call_tool(
name="create_data_source",
arguments={
"database_id": "database-id",
"title": "Bug Tracker",
"properties": {
"Bug Title": {"title": {}},
"Severity": {
"select": {
"options": [
{"name": "Critical", "color": "red"},
{"name": "Major", "color": "orange"},
{"name": "Minor", "color": "yellow"}
]
}
},
"Reported Date": {"date": {}},
"Fixed": {"checkbox": {}}
}
}
)
Update Data Source
Update data source schema and properties.
Tool ID: update_data_source
Credit Cost: 1 credit
Parameters:
data_source_id(string, required): ID of data source to updateproperties(object, optional): Property updates (set to null to remove)title(string, optional): New titleicon(object, optional): New iconin_trash(boolean, optional): Archive/unarchiveparent_database_id(string, optional): Move to different database
Example Usage:
# Python - Add and remove properties
response = client.call_tool(
name="update_data_source",
arguments={
"data_source_id": "data-source-id",
"properties": {
"New Field": {"rich_text": {}}, # Add new
"Old Field": None # Remove
}
}
)
List Data Source Templates
List available templates for a data source.
Tool ID: list_data_source_templates
Credit Cost: 1 credit
Parameters:
data_source_id(string, required): ID of the data sourcename(string, optional): Filter templates by namepage_size(integer, optional): Number of results (default: 100)start_cursor(string, optional): Pagination cursor
Response:
{
"templates": [
{
"id": "template-id",
"name": "Weekly Report Template",
"is_default": true
}
],
"has_more": false,
"next_cursor": null
}
Use Cases:
- Discover available templates
- Get template IDs for page creation
- List custom templates
Common Patterns
Complete Database Query Workflow
# Step 1: Get database and find data source
database = client.call_tool(
name="get_database",
arguments={"database_id": "your-database-id"}
)
data_source_id = database["data_sources"][0]["id"]
# Step 2: Get schema to understand properties
schema = client.call_tool(
name="retrieve_data_source",
arguments={"data_source_id": data_source_id}
)
print("Available properties:", list(schema["properties"].keys()))
# Step 3: Query with filter
results = client.call_tool(
name="query_data_source",
arguments={
"data_source_id": data_source_id,
"filter": '{"property": "Status", "status": {"equals": "In Progress"}}',
"page_size": 50
}
)
print(f"Found {len(results['results'])} items")
Content Pipeline
# Scrape content and store in Notion
def save_to_notion(url, parent_page_id):
# Scrape the content
content = client.call_tool(
name="web_scraper_Get_Website_Markdown",
arguments={"url": url}
)
# Create Notion page
page = client.call_tool(
name="create_page",
arguments={
"title": content["title"],
"parent_page_id": parent_page_id,
"content": content["markdown"]
}
)
return page["url"]
Task Management
# Create task and track in database
def create_task(title, priority, due_date, data_source_id):
return client.call_tool(
name="create_page",
arguments={
"title": title,
"parent_data_source_id": data_source_id,
"properties": {
"Status": {"status": {"name": "To Do"}},
"Priority": {"select": {"name": priority}},
"Due Date": {"date": {"start": due_date}}
}
}
)
# Get overdue tasks
def get_overdue_tasks(data_source_id):
today = datetime.now().strftime("%Y-%m-%d")
return client.call_tool(
name="query_data_source",
arguments={
"data_source_id": data_source_id,
"filter": json.dumps({
"and": [
{"property": "Due Date", "date": {"before": today}},
{"property": "Status", "status": {"does_not_equal": "Done"}}
]
})
}
)
Property Types Reference
| Type | Description | Example Value |
|---|---|---|
title | Main title field | {"title": [{"text": {"content": "Name"}}]} |
rich_text | Text content | {"rich_text": [{"text": {"content": "Text"}}]} |
number | Numeric value | {"number": 42} |
select | Single option | {"select": {"name": "Option"}} |
multi_select | Multiple options | {"multi_select": [{"name": "A"}, {"name": "B"}]} |
date | Date/time | {"date": {"start": "2025-11-22"}} |
checkbox | Boolean | {"checkbox": true} |
status | Status field | {"status": {"name": "In Progress"}} |
people | User references | {"people": [{"id": "user-id"}]} |
url | URL link | {"url": "https://example.com"} |
email | Email address | {"email": "user@example.com"} |
Best Practices
Access Control
- Only share specific pages/databases with your integration
- Use least-privilege access
- Regularly audit shared content
Performance
- Use
filter_propertiesto limit returned data - Implement pagination for large result sets
- Cache data source schemas
Data Integrity
- Validate property values match schema
- Handle missing properties gracefully
- Check status/select options exist before using
Error Handling
- Handle "page not found" for deleted pages
- Check for rate limiting
- Validate IDs before operations
Troubleshooting
"Object not found" Error
Cause: Page/database not shared with integration
Solutions:
- Share the page/database with your integration
- Check the ID is correct
- Verify integration has access
"Invalid property" Error
Cause: Property name doesn't exist or wrong type
Solutions:
- Use
retrieve_data_sourceto check schema - Verify property name spelling and case
- Ensure property type matches expected format
"Validation error" Error
Cause: Property value format incorrect
Solutions:
- Check property type requirements
- Verify date formats (ISO 8601)
- Ensure select options exist
Related Tools
- Jira - Project management integration
- Supabase - Database storage alternative
- Web Scraper - Extract content for Notion
- Perplexity - Research to add to Notion
See Also
- Creating Custom Tools - Pre-configure Notion settings
- Managing Credentials - Store Notion token
- All Tools - Complete tool catalog