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