Notion Knowledge Base MCP Server
# Building a Notion Knowledge Base MCP Server
This guide walks through the process of creating an MCP server that interfaces with a Notion knowledge base via the Dify API.
## Starting Point
We began with a Python example that demonstrated how to query the Dify API:
```python
def pull_dify_api_result_with_input(input_example="input_example"):
load_dotenv()
url = "https://dify.rickydata.com/v1/workflows/run"
headers = {
'Authorization': f"Bearer {os.getenv('DIFY_API_BACKEND_KEY')}",
'Content-Type': 'application/json'
}
payload = {
'inputs': {
'input_example': input_example
},
'response_mode': 'blocking',
'user': 'curation_agent_python'
}
response = requests.post(url, headers=headers, json=payload)
response_data = response.json()
if response_data.get('data', {}).get('outputs', {}):
return response_data['data']['outputs']
return response_data
```
## Implementation Steps
### 1. Project Setup
1. Create a new directory for the MCP server:
```bash
mkdir notion_mcp_server
cd notion_mcp_server
```
2. Create initial files:
- `.env` for API key
- `requirements.txt` for dependencies
- `notion_mcp_server.py` for server implementation
### 2. Dependencies
Set up required dependencies in `requirements.txt`:
```
fastmcp==0.4.1
python-dotenv
requests
```
### 3. Server Implementation
1. Create a FastMCP server with proper configuration:
```python
mcp = FastMCP(
name="Notion Knowledge Base",
description="MCP server for querying a Notion knowledge base",
version="0.1.0",
dependencies=["python-dotenv", "requests"]
)
```
2. Define data models using Pydantic:
```python
class NotionResponse(BaseModel):
answer: str = Field(default="")
notion_page_url: str = Field(default="")
notion_page_id: str = Field(default="")
```
3. Implement the question-asking tool:
```python
@mcp.tool()
def ask_notion_question(question: str, ctx: Context) -> Dict[str, Any]:
"""Ask a question about the Notion knowledge base."""
# Implementation details...
```
### 4. Error Handling and Logging
Add comprehensive error handling and logging:
```python
try:
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
except requests.RequestException as e:
error_msg = f"API request failed: {str(e)}"
ctx.error(error_msg)
raise ValueError(error_msg)
```
### 5. Testing
1. Test the basic Python implementation:
```bash
python3 notion_api.py
```
2. Test the MCP server:
```bash
fastmcp dev notion_mcp_server.py
```
### 6. Integration with Cline
1. Install the server in Cline:
```bash
fastmcp install notion_mcp_server.py
```
2. Configure the server in Cline's settings:
```json
{
"mcpServers": {
"notion-kb": {
"command": "uv",
"args": [
"run",
"--with", "fastmcp",
"--with", "python-dotenv",
"--with", "requests",
"fastmcp",
"run",
"/path/to/notion_mcp_server.py"
],
"env": {
"DIFY_API_BACKEND_KEY": "your-api-key"
}
}
}
}
```
## Key Learnings
1. **Synchronous vs Async**: Keep the implementation synchronous for simplicity and reliability.
2. **Proper Dependencies**: Use `uv run` with explicit dependencies for better isolation.
3. **Error Handling**: Implement comprehensive error handling and logging.
4. **Configuration**: Use environment variables for sensitive data.
5. **Testing**: Test thoroughly at each step of implementation.
## Troubleshooting
1. If the server hangs, ensure you're using `uv run` instead of `python3` directly.
2. If connection fails, verify the API key is properly set in environment variables.
3. For "Not connected" errors, ensure the server is properly configured in Cline settings.