Skip to main content
Glama

databases

Manage Notion databases by creating, querying, updating, and deleting databases, data sources, and pages with schema control and bulk operations.

Instructions

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.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionYesAction to perform
database_idNoDatabase ID (container)
data_source_idNoData source ID (for update_data_source action)
parent_idNoParent page ID (for create/update_database)
titleNoTitle (for database or data source)
descriptionNoDescription
propertiesNoSchema properties (for create/update data source)
is_inlineNoDisplay as inline (for create/update_database)
iconNoEmoji icon (for update_database)
coverNoCover image URL (for update_database)
filtersNoQuery filters (for query action)
sortsNoQuery sorts
limitNoMax query results
searchNoSmart search across text fields (for query)
page_idNoSingle page ID (for update_page)
page_idsNoMultiple page IDs (for delete_page)
page_propertiesNoPage properties to update (for update_page)
pagesNoArray of pages for bulk create/update

Implementation Reference

  • Primary exported handler function for the 'databases' tool. Dispatches to sub-handlers based on the 'action' input parameter.
    export async function databases(notion: Client, input: DatabasesInput): Promise<any> { return withErrorHandling(async () => { switch (input.action) { case 'create': return await createDatabase(notion, input) case 'get': return await getDatabase(notion, input) case 'query': return await queryDatabase(notion, input) case 'create_page': return await createDatabasePages(notion, input) case 'update_page': return await updateDatabasePages(notion, input) case 'delete_page': return await deleteDatabasePages(notion, input) case 'create_data_source': return await createDataSource(notion, input) case 'update_data_source': return await updateDataSource(notion, input) case 'update_database': return await updateDatabaseContainer(notion, input) default: throw new NotionMCPError( `Unknown action: ${input.action}`, 'VALIDATION_ERROR', 'Supported actions: create, get, query, create_page, update_page, delete_page, create_data_source, update_data_source, update_database' ) } })() }
  • TypeScript interface defining the input shape for the databases tool, including all supported actions and parameters.
    export interface DatabasesInput { action: | 'create' | 'get' | 'query' | 'create_page' | 'update_page' | 'delete_page' | 'create_data_source' | 'update_data_source' | 'update_database' // Common params database_id?: string data_source_id?: string // Create database params parent_id?: string title?: string description?: string properties?: Record<string, any> is_inline?: boolean icon?: string cover?: string // Query params filters?: any sorts?: any[] limit?: number search?: string // Page operations params (create/update/delete database items) page_id?: string page_ids?: string[] page_properties?: Record<string, any> // Bulk operations pages?: Array<{ page_id?: string properties: Record<string, any> }> }
  • MCP tool registration in the TOOLS array, including name, description, and JSON inputSchema for validation.
    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'] }
  • Dispatch in the CallToolRequestSchema handler that invokes the databases tool function.
    case 'databases': result = await databases(notion, args as any) break
  • Example helper function for 'query' action, demonstrating database querying with filters, sorting, and pagination.
    async function queryDatabase(notion: Client, input: DatabasesInput): Promise<any> { if (!input.database_id) { throw new NotionMCPError('database_id required for query action', 'VALIDATION_ERROR', 'Provide database_id') } // First, get data source ID from database const database: any = await notion.databases.retrieve({ database_id: input.database_id }) if (!database.data_sources || database.data_sources.length === 0) { throw new NotionMCPError('No data sources found in database', 'VALIDATION_ERROR', 'Database has no data sources') } const dataSourceId = database.data_sources[0].id let filter = input.filters // Smart search across text properties if (input.search && !filter) { const dataSource: any = await (notion as any).dataSources.retrieve({ data_source_id: dataSourceId }) const textProps = Object.entries(dataSource.properties || {}) .filter(([_, prop]: [string, any]) => ['title', 'rich_text'].includes(prop.type)) .map(([name]) => name) if (textProps.length > 0) { filter = { or: textProps.map((propName) => ({ property: propName, rich_text: { contains: input.search } })) } } } const queryParams: any = { data_source_id: dataSourceId } if (filter) queryParams.filter = filter if (input.sorts) queryParams.sorts = input.sorts // Fetch with pagination const allResults = await autoPaginate(async (cursor) => { const response: any = await (notion as any).dataSources.query({ ...queryParams, start_cursor: cursor, page_size: 100 }) return { results: response.results, next_cursor: response.next_cursor, has_more: response.has_more } }) // Limit results if specified const results = input.limit ? allResults.slice(0, input.limit) : allResults // Format results const formattedResults = results.map((page: any) => { const props: any = { page_id: page.id, url: page.url } for (const [key, prop] of Object.entries(page.properties)) { const p = prop as any if (p.type === 'title' && p.title) { props[key] = p.title.map((t: any) => t.plain_text).join('') } else if (p.type === 'rich_text' && p.rich_text) { props[key] = p.rich_text.map((t: any) => t.plain_text).join('') } else if (p.type === 'select' && p.select) { props[key] = p.select.name } else if (p.type === 'multi_select' && p.multi_select) { props[key] = p.multi_select.map((s: any) => s.name) } else if (p.type === 'number') { props[key] = p.number } else if (p.type === 'checkbox') { props[key] = p.checkbox } else if (p.type === 'url') { props[key] = p.url } else if (p.type === 'email') { props[key] = p.email } else if (p.type === 'phone_number') { props[key] = p.phone_number } else if (p.type === 'date' && p.date) { props[key] = p.date.start + (p.date.end ? ` to ${p.date.end}` : '') } } return props }) return { action: 'query', database_id: input.database_id, data_source_id: dataSourceId, total: formattedResults.length, results: formattedResults } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/n24q02m/better-notion-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server