Motivation
As a daily Cursor IDE user, I'm constantly looking for ways to enhance my development workflow. I love how Cursor's AI capabilities help me code faster, but I wanted to take it further by integrating the tools I use every day directly into my IDE. Notion has become an essential part of my documentation and knowledge management process, so building an MCP server to connect it with Cursor felt like a natural next step.
This project gave me a perfect opportunity to practice building MCP servers while adding real value to my development environment. I wanted to share my experience creating this integration, hoping it helps others looking to extend their Cursor IDE capabilities.
Implementation
Let's walk through building a production-ready MCP server for Notion API integration. I'll break down the key implementation steps and share the actual code patterns I used.
Project Structure
First, I set up the project structure:
mcp-server/
├── src/
│ ├── server.ts
│ └── main.ts
├── package.json
├── tsconfig.json
└── .env
Installing Dependencies
The core dependencies needed for the MCP server:
{
"dependencies": {
"@cursor/mcp-server": "^1.0.0",
"axios": "^1.6.2",
"zod": "^3.22.4",
"dotenv": "^16.3.1"
},
"devDependencies": {
"typescript": "^5.3.3",
"@types/node": "^20.10.4"
}
}
Environment Configuration
In server.ts
, I started with environment setup:
import { config } from 'dotenv';
import { z } from 'zod';
config();
const envSchema = z.object({
NOTION_API_KEY: z.string(),
NOTION_API_VERSION: z.string().default('2022-06-28')
});
const env = envSchema.parse(process.env);
Creating the Notion Client
I created an axios client with proper authentication and versioning:
import axios from 'axios';
const notionClient = axios.create({
baseURL: 'https://api.notion.com',
headers: {
'Authorization': `Bearer ${env.NOTION_API_KEY}`,
'Notion-Version': env.NOTION_API_VERSION,
'Content-Type': 'application/json'
}
});
Setting Up the MCP Server
Next, I initialized the MCP server instance:
import { McpServer } from '@cursor/mcp-server';
const mcpServer = new McpServer({
name: 'notion-mcp',
version: '1.0.0'
});
Implementing Tools
Here's an example tool implementation for searching pages:
const searchSchema = z.object({
query: z.string(),
limit: z.number().optional().default(10)
});
mcpServer.tool({
name: 'search_pages',
description: 'Search Notion pages by title',
parameters: searchSchema,
handler: async ({ query, limit }) => {
const response = await notionClient.post('/v1/search', {
query,
filter: { property: 'object', value: 'page' },
page_size: limit
});
return response.data.results.map(page => ({
id: page.id,
title: page.properties.title?.title[0]?.plain_text || 'Untitled',
url: page.url
}));
}
});
Entry Point
Finally, in main.ts
, I created the server entry point:
import { server } from './server';
const port = process.env.PORT || 3000;
server.listen(port, () => {
console.log(`Notion MCP server running on port ${port}`);
});
Usage
Let's look at how to set up and use the Notion MCP server with Cursor IDE.
Installation
Install the package globally:
npm install -g @sargonpiraev/notion-mcp
Configuration
Add the server to your Cursor IDE's mcp.json
:
{
"servers": [
{
"name": "notion-mcp",
"command": "notion-mcp",
"env": {
"NOTION_API_KEY": "your-api-key-here"
}
}
]
}
Example Prompts
Here are some practical examples of using the Notion integration:
- "Search my Notion pages for project documentation"
Using notion_mcp.search_pages to find relevant pages...
Found 3 matching pages:
- Project Overview (https://notion.so/...)
- Technical Specs (https://notion.so/...)
- Implementation Guide (https://notion.so/...)
- "Create a new page for today's meeting notes"
Using notion_mcp.create_page to create a new page...
Created page "Team Meeting - 2024-01-09"
URL: https://notion.so/...
- "Update the status of my current project task"
Using notion_mcp.update_page to modify properties...
Updated status to "In Progress"
Page URL: https://notion.so/...
How It Works
Here's a visualization of how the Notion MCP server integrates with Cursor IDE:
Rendering diagram...
This flow shows how user requests in Cursor IDE are transformed into API calls through the MCP server, with results formatted and returned to enhance the IDE experience.