Skip to main content
Glama

Notion MCP Server

by tkc
server.ts10.1 kB
import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequest, CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import { NotionClientWrapper } from './client'; import { allNotionTools } from './tools'; import * as Types from './types'; import { logger } from './utils/logger'; /** * Main function to start the Notion MCP Server */ export async function startNotionServer(apiToken: string) { logger.info('Starting Notion MCP Server...'); // Check if API token is provided if (!apiToken) { logger.error('Notion API token not provided'); throw new Error('Notion API token is required'); } // Create server instance const server = new Server( { name: 'Notion MCP Server', version: '1.0.0', }, { capabilities: { tools: {}, }, }, ); // Initialize Notion client with provided API token const notionClient = new NotionClientWrapper(apiToken); // Set up tool request handler server.setRequestHandler( CallToolRequestSchema, async (request: CallToolRequest) => { logger.debug('Received CallToolRequest', { requestId: request.id, tool: request.params.name, }); try { if (!request.params.arguments) { throw new Error('No arguments provided'); } // Handle different tool requests switch (request.params.name) { // Block operations case 'notion_append_block_children': { const args = request.params .arguments as unknown as Types.AppendBlockChildrenArgs; const response = await notionClient.appendBlockChildren(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } case 'notion_retrieve_block': { const args = request.params .arguments as unknown as Types.RetrieveBlockArgs; const response = await notionClient.retrieveBlock(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } case 'notion_retrieve_block_children': { const args = request.params .arguments as unknown as Types.RetrieveBlockChildrenArgs; const response = await notionClient.retrieveBlockChildren(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } case 'notion_update_block': { const args = request.params .arguments as unknown as Types.UpdateBlockArgs; const response = await notionClient.updateBlock(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } case 'notion_delete_block': { const args = request.params .arguments as unknown as Types.DeleteBlockArgs; const response = await notionClient.deleteBlock(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } // Page operations case 'notion_retrieve_page': { const args = request.params .arguments as unknown as Types.RetrievePageArgs; const response = await notionClient.retrievePage(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } case 'notion_update_page_properties': { const args = request.params .arguments as unknown as Types.UpdatePagePropertiesArgs; const response = await notionClient.updatePageProperties(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } // User operations case 'notion_list_all_users': { const args = request.params .arguments as unknown as Types.ListAllUsersArgs; const response = await notionClient.listAllUsers(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } case 'notion_retrieve_user': { const args = request.params .arguments as unknown as Types.RetrieveUserArgs; const response = await notionClient.retrieveUser(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } case 'notion_retrieve_bot_user': { const response = await notionClient.retrieveBotUser(); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } // Database operations case 'notion_create_database': { const args = request.params .arguments as unknown as Types.CreateDatabaseArgs; const response = await notionClient.createDatabase(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } case 'notion_query_database': { const args = request.params .arguments as unknown as Types.QueryDatabaseArgs; const response = await notionClient.queryDatabase(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } case 'notion_retrieve_database': { const args = request.params .arguments as unknown as Types.RetrieveDatabaseArgs; const response = await notionClient.retrieveDatabase(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } case 'notion_update_database': { const args = request.params .arguments as unknown as Types.UpdateDatabaseArgs; const response = await notionClient.updateDatabase(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } case 'notion_create_database_item': { const args = request.params .arguments as unknown as Types.CreateDatabaseItemArgs; const response = await notionClient.createDatabaseItem(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } // Comment operations case 'notion_create_comment': { const args = request.params .arguments as unknown as Types.CreateCommentArgs; const response = await notionClient.createComment(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } case 'notion_retrieve_comments': { const args = request.params .arguments as unknown as Types.RetrieveCommentsArgs; const response = await notionClient.retrieveComments(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } // Search case 'notion_search': { const args = request.params .arguments as unknown as Types.SearchArgs; const response = await notionClient.search(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } // Custom operations case 'notion_create_workflow': { const args = request.params .arguments as unknown as Types.CreateWorkflowArgs; const response = await notionClient.createWorkflow(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } case 'notion_import_from_csv': { const args = request.params .arguments as unknown as Types.ImportFromCSVArgs; const response = await notionClient.importFromCSV(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } case 'notion_export_to_csv': { const args = request.params .arguments as unknown as Types.ExportToCSVArgs; const response = await notionClient.exportToCSV(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } case 'notion_create_recurring_task': { const args = request.params .arguments as unknown as Types.CreateRecurringTaskArgs; const response = await notionClient.createRecurringTask(args); return { content: [{ type: 'text', text: JSON.stringify(response) }], }; } default: logger.warn(`Unknown tool requested: ${request.params.name}`); throw new Error(`Unknown tool: ${request.params.name}`); } } catch (error) { logger.error('Error executing tool', { tool: request.params.name, error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined, }); return { content: [ { type: 'text', text: JSON.stringify({ error: error instanceof Error ? error.message : String(error), }), }, ], }; } }, ); // Set up tools listing handler server.setRequestHandler(ListToolsRequestSchema, async () => { logger.debug('Received ListToolsRequest'); return { tools: allNotionTools, }; }); // Connect server using stdio transport const transport = new StdioServerTransport(); try { await server.connect(transport); logger.info('Notion MCP Server started successfully'); } catch (error) { logger.error('Failed to start server', { error: error instanceof Error ? error.message : String(error), }); throw error; } }

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/tkc/notion-mcp'

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