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.