turtleYJ/notion-mcp-server
If you are the rightful owner of notion-mcp-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
The Model Context Protocol (MCP) server is a specialized server designed to facilitate communication and data exchange between different machine learning models and applications.
Notion MCP Server
Claude Desktopκ³Ό Notionμ μ°κ²°νλ MCP (Model Context Protocol) μλ²μ λλ€.
π― κΈ°λ₯
- read_page: Notion νμ΄μ§ λ΄μ© μ½κΈ° (νμ₯λ λ§ν¬λ€μ΄ ν¬λ§· μ§μ)
- create_page: μ Notion νμ΄μ§ μμ± (λμ©λ λ¬Έμ & λ§ν¬λ€μ΄ μμ μ§μ)
π μꡬμ¬ν
- Node.js 18+
- Notion Integration Token
- Claude Desktop
π λΉ λ₯Έ μμ
1. μ μ₯μ ν΄λ‘ λ° μμ‘΄μ± μ€μΉ
git clone https://github.com/your-username/notion-mcp-server.git
cd notion-mcp-server
npm install
2. Notion Integration μ€μ
- Notion Developer Console μ μ
- "New integration" ν΄λ¦
- κΈ°λ³Έ μ 보 μ
λ ₯:
- Name: "Claude MCP Integration"
- Associated workspace: λ³ΈμΈ μν¬μ€νμ΄μ€
- Type: Internal
- "Submit" ν΄λ¦ ν Integration Token 볡μ¬
- μ°κ²°ν νμ΄μ§μμ "..." β "Add connections" β Integration μ ν
3. Claude Desktop μ€μ
Claude Desktop μ€μ νμΌμ νΈμ§ν©λλ€:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%/Claude/claude_desktop_config.json
{
"mcpServers": {
"notion": {
"command": "node",
"args": ["/absolute/path/to/your/notion-mcp-server/server.js"],
"env": {
"NOTION_TOKEN": "YOUR_NOTION_TOKEN_HERE"
}
}
}
}
λλ config/claude_desktop_config.example.json
νμΌμ μ°Έκ³ νμ¬ μ€μ νμΈμ.
4. Claude Desktop μ¬μμ
Claude Desktopμ μμ ν μ’ λ£νκ³ λ€μ μμνλ©΄ MCP λκ΅¬κ° μ°κ²°λ©λλ€.
π§ μ¬μ©λ²
Claude Desktopμμ λ€μκ³Ό κ°μ΄ μμ²ν μ μμ΅λλ€:
νμ΄μ§ μ½κΈ°
"νμ΄μ§ ID 12345μ λ΄μ©μ μ½μ΄μ€"
νμ΄μ§ μμ±
"λΆλͺ¨ νμ΄μ§ 12345μ 'μ νλ‘μ νΈ κ³ν'μ΄λΌλ μ λͺ©μΌλ‘ νμ΄μ§λ₯Ό λ§λ€μ΄μ€"
π μλ μ리
MCP (Model Context Protocol)
MCPλ AI λͺ¨λΈκ³Ό μΈλΆ λꡬ κ°μ νμ€νλ ν΅μ νλ‘ν μ½μ λλ€.
βββββββββββββββββββ MCP Protocol βββββββββββββββββββ
β Claude β βββββββββββββββββββΊ β MCP Server β
β Desktop β (JSON-RPC) β (Notion) β
βββββββββββββββββββ βββββββββββββββββββ
β
βΌ
βββββββββββββββββββ
β Notion API β
βββββββββββββββββββ
ν΅μ νλ‘μ°
- Initialization: Claude Desktopμ΄ MCP μλ²μ μ°κ²°
- Capability Exchange: μλ²κ° μ 곡νλ λꡬ λͺ©λ‘ κ΅ν
- Tool Invocation: Claudeκ° λꡬ νΈμΆ μμ²
- Response: μλ²κ° κ²°κ³Ό λ°ν
νλ‘ν μ½ λ©μμ§
λꡬ λͺ©λ‘ μμ²:
{
"method": "tools/list",
"params": {},
"jsonrpc": "2.0",
"id": 1
}
λꡬ νΈμΆ μμ²:
{
"method": "tools/call",
"params": {
"name": "read_page",
"arguments": {
"page_id": "12345"
}
},
"jsonrpc": "2.0",
"id": 2
}
π§ νΈλ¬λΈμν
λ¬Έμ 1: MCP SDK νΈνμ± μ€λ₯
μ¦μ:
TypeError: Cannot read properties of undefined (reading 'method')
ν΄κ²°μ± :
@modelcontextprotocol/sdk
λ²μ μ 0.4.0μΌλ‘ κ³ μ CallToolRequestSchema
,ListToolsRequestSchema
import νμΈ- μμ‘΄μ± μ¬μ€μΉ:
npm install
λ¬Έμ 2: μλ² μ°κ²° μ€ν¨
μ¦μ: "Server disconnected" λ‘κ·Έ λ©μμ§
μ§λ¨ λͺ λ Ήμ΄:
# μλ² νλ‘μΈμ€ νμΈ
ps aux | grep "notion-mcp-server"
# λ‘κ·Έ νμΈ (macOS)
tail -f ~/Library/Logs/Claude/mcp-server-notion.log
ν΄κ²°μ± :
- Node.js λ²μ νμΈ (v18+ κΆμ₯)
- νμΌ μ λ κ²½λ‘ νμΈ
- μ€ν κΆν μ€μ :
chmod +x server.js
- νκ²½ λ³μ μ€μ νμΈ
λ¬Έμ 3: Notion API μ€λ₯
μ¦μ: "Error: API request failed"
ν΄κ²°μ± :
NOTION_TOKEN
μ¬νμΈ- Integration κΆνμ΄ νμ΄μ§μ μ°κ²°λμλμ§ νμΈ
- νμ΄μ§ ID νμ νμΈ (32μ리 μμ«μ)
λ¬Έμ 4: ν μ€νΈ κΈΈμ΄ μ ν (2000μ)
μ¦μ:
Error: body failed validation: body.children[0].paragraph.rich_text[0].text.content.length should be β€ `2000`, instead was `3094`
ν΄κ²°μ± : β μλ ν΄κ²°λ¨
- κΈ΄ ν μ€νΈλ₯Ό 1900μ λ¨μλ‘ μλ λΆν
- μμ ν λΆν μ μλ νμ§ (μ€λ°κΏ, λ¬Έμ₯ λ, λ¨μ΄ κ²½κ³)
λ¬Έμ 5: λΈλ‘ μ μ ν (100κ°)
μ¦μ:
Error: body failed validation: body.children.length should be β€ `100`, instead was `109`
ν΄κ²°μ± : β μλ ν΄κ²°λ¨
- λμ©λ λ¬Έμλ₯Ό 95κ° λΈλ‘μ© λ°°μΉ μ²λ¦¬
- 첫 λ°°μΉλ‘ νμ΄μ§ μμ± ν λλ¨Έμ§ λΈλ‘ μΆκ°
- μ΄ λΈλ‘ μ νΌλλ°± μ 곡
λ¬Έμ 6: λ§ν¬λ€μ΄ μμ λ―Έμ μ©
μ¦μ: **λ³Όλ**
ν
μ€νΈκ° κ·Έλλ‘ νμλ¨
ν΄κ²°μ± : β μλ ν΄κ²°λ¨
- λ³Όλ λ§ν¬λ€μ΄(
**text**
)μ Notion μμμΌλ‘ μλ λ³ν - Rich Text annotations μ μ©
- λͺ¨λ λΈλ‘ νμ μμ μμ μ§μ
λλ²κΉ ν
λ‘κ·Έ λͺ¨λν°λ§:
# macOS
tail -f ~/Library/Logs/Claude/mcp-server-notion.log ~/Library/Logs/Claude/mcp.log
μ§μ μλ² ν μ€νΈ:
# μλ² μ§μ μ€ν
NOTION_TOKEN=your_token node server.js
# νκ²½ λ³μ νμΈ
echo $NOTION_TOKEN
μ±λ₯ μ΅μ ν:
- λμ©λ λ¬Έμλ λ°°μΉ μ²λ¦¬λ‘ μΈν΄ μΆκ° μκ° μμ (λ°°μΉλΉ 1-2μ΄)
- λ§€μ° ν° λ¬Έμλ μ¬λ¬ νμ΄μ§λ‘ λΆν κΆμ₯
π 보μ κ³ λ €μ¬ν
ν ν° κ΄λ¦¬
- μ λ Gitμ ν ν° μ»€λ° κΈμ§:
.env
νμΌμ.gitignore
μ ν¬ν¨ - νκ²½ λ³μ μ¬μ©: Claude Desktop μ€μ μμ ν ν°μ νκ²½ λ³μλ‘ μ€μ
- ν ν° μ£ΌκΈ°μ κ°±μ : 보μμ μν΄ μ κΈ°μ μΌλ‘ ν ν° μ¬μμ±
.env.example
νμ©: μ€μ ν ν° μμ΄ μ€μ ν νλ¦Ώ μ 곡
κΆν μ μ΄
- μ΅μ κΆν μμΉ: Notion Integrationμ νμν μ΅μνμ κΆνλ§ λΆμ¬
- νμ΄μ§λ³ κΆν: νμν νμ΄μ§μλ§ Integration μ°κ²°
- μ κΈ°μ κΆν κ²ν : μ¬μ©νμ§ μλ Integration μ 리
κ°λ° νκ²½ 보μ
# λ‘컬 κ°λ° μ .env νμΌ μ¬μ©
cp .env.example .env
# .env νμΌμ μ€μ ν ν° μ
λ ₯ (Gitμ μΆκ°λμ§ μμ)
μλ¬ μ²λ¦¬
- λ―Όκ° μ 보 λ‘κΉ λ°©μ§: ν ν°μ΄λ κ°μΈμ λ³΄κ° λ‘κ·Έμ λ ΈμΆλμ§ μλλ‘ μ²λ¦¬
- μ μ ν λ‘κΉ μμ€: λλ²κΉ μ 보μ 보μ μ 보 ꡬλΆ
- μ¬μ©μ μΉνμ μ€λ₯ λ©μμ§: λ΄λΆ ꡬν μΈλΆμ¬ν λ ΈμΆ λ°©μ§
π§ κ°λ°
νλ‘μ νΈ κ΅¬μ‘°
notion-mcp-server/
βββ server.js # MCP μλ² λ©μΈ νμΌ
βββ package.json # νλ‘μ νΈ μ€μ λ° μμ‘΄μ±
βββ package-lock.json # μμ‘΄μ± μ κΈ νμΌ
βββ README.md # νλ‘μ νΈ λ¬Έμ
μ½λ ꡬ쑰
server.jsμ μ£Όμ κ΅¬μ± μμ:
-
Import λ° μ΄κΈ°ν
import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js"; import { Client } from "@notionhq/client";
-
ν΅μ¬ μ νΈλ¦¬ν° ν¨μλ€
function splitTextIntoBlocks(content, maxLength = 1900) // ν μ€νΈ λΆν function parseRichText(text) // λ§ν¬λ€μ΄ β Rich Text λ³ν function parseMarkdownToBlocks(content) // λ§ν¬λ€μ΄ β Notion λΈλ‘ λ³ν function richTextToMarkdown(richTextArray) // Rich Text β λ§ν¬λ€μ΄ λ³ν function blockToText(block) // Notion λΈλ‘ β ν μ€νΈ λ³ν
-
Notion Client μ€μ
const notion = new Client({ auth: process.env.NOTION_TOKEN, });
-
MCP Server μ΄κΈ°ν
const server = new Server({ name: "notion-mcp-server", version: "1.0.0", }, { capabilities: { tools: {} }, });
-
λꡬ λͺ©λ‘ νΈλ€λ¬
server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [/* λꡬ μ μ */] }; });
-
λꡬ νΈμΆ νΈλ€λ¬ (λ°°μΉ μ²λ¦¬ μ§μ)
server.setRequestHandler(CallToolRequestSchema, async (request) => { // read_page: νμ₯λ λΈλ‘ νμ μ§μ // create_page: λμ©λ λ¬Έμ λ°°μΉ μ²λ¦¬ });
-
STDIO ν΅μ μ€μ
async function run() { const transport = new StdioServerTransport(); await server.connect(transport); }
μ§μνλ Notion λΈλ‘ νμ
νμ¬ λ€μ λΈλ‘ νμ μ μ§μν©λλ€:
μ½κΈ° μ§μ (read_page)
paragraph
: μΌλ° ν μ€νΈ (λ³Όλ, μ΄ν€λ¦, μ½λ, μ·¨μμ , λ°μ€, λ§ν¬ μμ ν¬ν¨)heading_1/2/3
: μ λͺ© (# ## ### ννλ‘ λ³ν)bulleted_list_item
: λΆλ¦Ώ 리μ€νΈ (β’ νν, μ€μ²© μ§μ)numbered_list_item
: λ²νΈ 리μ€νΈ (1. νν, μ€μ²© μ§μ)code
: μ½λ λΈλ‘ (μΈμ΄λ³ ꡬ문 κ°μ‘°)quote
: μΈμ©κ΅¬ (> νν)divider
: ꡬλΆμ (---)callout
: μ½μμ (μ΄λͺ¨μ§ + κ°μ‘° ν μ€νΈ)toggle
: μ κΈ°/νΌμΉκΈ° μΉμ to_do
: 체ν¬λ°μ€ νλͺ©
μμ± μ§μ (create_page)
- λ§ν¬λ€μ΄ νμ±:
# ## ###
(μ λͺ©),- *
(λΆλ¦Ώ 리μ€νΈ),---
(ꡬλΆμ ) - ν
μ€νΈ μμ:
**λ³Όλ**
μλ λ³ν - λμ©λ λ¬Έμ: 100κ° μ΄μ λΈλ‘ μλ λ°°μΉ μ²λ¦¬
- κΈ΄ ν μ€νΈ: 2000μ μ΄μ μλ λΆν μ²λ¦¬
π νμ₯ κ°λ₯μ±
MCP νλ‘ν μ½μ ν΅ν΄ λ€μν μλΉμ€μ μ°λν μ μμ΅λλ€:
λ°μ΄ν°λ² μ΄μ€
- PostgreSQL, MongoDB
- Redis, Elasticsearch
ν΄λΌμ°λ μλΉμ€
- AWS (S3, Lambda, DynamoDB)
- GCP (BigQuery, Cloud Storage)
- Azure (Cosmos DB, Functions)
κ°λ° λꡬ
- GitHub (μ΄μ, PR κ΄λ¦¬)
- GitLab (CI/CD νμ΄νλΌμΈ)
- Jira (ν°μΌ κ΄λ¦¬)
μμ°μ± λꡬ
- Slack (λ©μμ§, μ±λ κ΄λ¦¬)
- Trello (보λ, μΉ΄λ κ΄λ¦¬)
- Google Workspace (Drive, Calendar)
π λΌμ΄μ μ€
MIT License
π€ κΈ°μ¬
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature
) - Commit your Changes (
git commit -m 'Add some AmazingFeature'
) - Push to the Branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
π μ§μ
λ¬Έμ κ° λ°μνκ±°λ μ§λ¬Έμ΄ μμΌμλ©΄:
- Issuesμ λ±λ‘
- λ‘κ·Έ νμΌκ³Ό ν¨κ» μμΈν μ¦μ μ€λͺ
- μ΄μ체μ , Node.js λ²μ μ 보 ν¬ν¨
π κ΄λ ¨ λ§ν¬
Note: μ΄ νλ‘μ νΈλ Anthropicμ MCP νλ‘ν μ½μ μ¬μ©νμ¬ Claude Desktopκ³Ό Notionμ μ°κ²°ν©λλ€. 곡μ μ§μμ΄ μλλ©°, κ°μΈ νλ‘μ νΈλ‘ κ°λ°λμμ΅λλ€.