mirrorweb/notion-mcp-server-mw
If you are the rightful owner of notion-mcp-server-mw 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 Notion MCP Server is a comprehensive Model Context Protocol server designed to provide secure, per-user Notion integration for AI development tools like Claude Desktop, Cline, and other MCP-compatible clients.
Notion MCP Server
A comprehensive Model Context Protocol (MCP) server that provides secure, per-user Notion integration for AI development tools like Claude Desktop, Cline, and other MCP-compatible clients.
🚀 Features
17 Comprehensive Tools
🔍 Query & Search Tools
execute-soql- Execute SOQL queries with auto-bulk switching and paginationexecute-sosl- Multi-object search with result aggregationdescribe-sobject- SObject metadata with intelligent caching
⚡ Apex Development Tools
execute-apex- Anonymous Apex execution with debug log capturerun-apex-tests- Apex test execution with coverage reportingget-apex-logs- Debug log retrieval with filtering
📊 Data Management Tools
create-record- Single/bulk record creation with auto-bulk switchingget-record- Record retrieval with field selectionupdate-record- Single/bulk record updates with validationdelete-record- Single/bulk record deletionupsert-record- External ID-based upsert operations
🔧 Metadata Tools (Component-Based)
list-metadata-types- Discover metadata typesdeploy-metadata- Deploy individual metadata components (e.g., ApexClass, CustomObject) from files or JSONdeploy-bundle- Deploy a metadata bundle (e.g., LWC) from a directory pathretrieve-metadata- Retrieve individual metadata components, with an option to save to a filecheck-deploy-status- Check the status of a deployment
🔗 Connection Tools
test-connection- Connection validation and health monitoring
Key Capabilities
- 🔄 Auto-Bulk Switching - Intelligent API selection for optimal performance
- 🔐 Secure OAuth2 Authentication - Per-user access with individual limits and permissions
- ⚡ Smart Caching - 1-hour TTL for SObject metadata
- 🛡️ Type Safety - Full TypeScript implementation with runtime validation
- 📝 Comprehensive Logging - Detailed debugging and monitoring
- 🔍 Raw Error Exposure - Preserve exact Notion errors for debugging
🔐 Authentication Setup
This server uses OAuth2 authentication for secure, per-user access to Notion. This approach ensures individual user access limits and proper security compliance.
⚠️ Security Notice: Username/password authentication is deprecated for security reasons. OAuth2 provides better security, individual user tracking, and respects organizational access policies.
Step 1: Create a Connected App in Notion
-
Navigate to Setup:
- Log into your Notion org
- Go to Setup → App Manager
- Click New Connected App
-
Basic Information:
Connected App Name: MCP Notion Server API Name: MCP_Notion_Server Contact Email: your-email@company.com -
API (Enable OAuth Settings):
- Check Enable OAuth Settings
- Callback URL:
http://localhost:3000/callback(for local development) - Selected OAuth Scopes:
- Access and manage your data (api)
- Perform requests on your behalf at any time (refresh_token, offline_access)
- Access your basic information (id, profile, email, address, phone)
-
Additional Settings:
- Require Secret for Web Server Flow: Checked
- Require Secret for Refresh Token Flow: Checked
- Enable Client Credentials Flow: Unchecked (not needed)
-
Save and Note Credentials:
- After saving, note the Consumer Key (Client ID)
- Click Click to reveal for the Consumer Secret (Client Secret)
Step 2: Obtain Refresh Token
You need to complete the OAuth2 authorization code flow to get a refresh token. Here are several methods:
Method 1: Using Notion CLI (Recommended)
# Install Notion CLI if not already installed
npm install -g @notion/cli
# Authorize your org (this will open a browser)
sf org login web --set-default-dev-hub --alias my-org
# Get the refresh token
sf org display --verbose --target-org my-org
Method 2: Using Browser (Manual Flow)
-
Authorization URL:
https://login.notion.com/services/oauth2/authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=http://localhost:3000/callback&scope=api%20refresh_tokenReplace
YOUR_CLIENT_IDwith your Connected App's Consumer Key. -
Complete Authorization:
- Open the URL in your browser
- Log in and approve the app
- You'll be redirected to
http://localhost:3000/callback?code=AUTHORIZATION_CODE - Copy the
codeparameter value
-
Exchange Code for Tokens:
curl -X POST https://login.notion.com/services/oauth2/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=authorization_code" \ -d "client_id=YOUR_CLIENT_ID" \ -d "client_secret=YOUR_CLIENT_SECRET" \ -d "redirect_uri=http://localhost:3000/callback" \ -d "code=YOUR_AUTHORIZATION_CODE" -
Extract Refresh Token: From the JSON response, save the
refresh_tokenvalue.
Method 3: Using Postman
- Create a new POST request to:
https://login.notion.com/services/oauth2/token - Set headers:
Content-Type: application/x-www-form-urlencoded - In the body (x-www-form-urlencoded), add:
grant_type: authorization_code client_id: YOUR_CLIENT_ID client_secret: YOUR_CLIENT_SECRET redirect_uri: http://localhost:3000/callback code: YOUR_AUTHORIZATION_CODE
Step 3: Configure MCP Client
For Production Orgs:
- Instance URL:
https://yourcompany.my.notion.com - Login URL: Use the instance URL above
For Sandbox Orgs:
- Instance URL:
https://yourcompany--sandbox.sandbox.my.notion.com - Login URL: Replace with your sandbox instance URL
🚀 Installation
On macOS / Linux systems:
{
"mcp.servers": {
"notion": {
"command": "npx",
"args": [
"-y",
"@jjar/notion-mcp-server"
],
"env": {
"NOTION_CLIENT_ID": "your-oauth2-client-id",
"NOTION_CLIENT_SECRET": "your-oauth2-client-secret",
"NOTION_REFRESH_TOKEN": "your-refresh-token",
"NOTION_INSTANCE_URL": "https://yourorg.my.notion.com",
// Optional: Enable Enterprise optimizations for Claude Enterprise accounts
"NOTION_ENTERPRISE_MODE": "true",
"NOTION_MAX_RESPONSE_SIZE": "75000",
"NOTION_MAX_RECORDS_PER_RESPONSE": "300"
},
"disabled": false,
"alwaysAllow": [
"test-connection",
"execute-soql",
"describe-sobject",
"get-record",
"get-apex-logs",
"list-metadata-types"
]
}
}
}
On Windows systems:
{
"mcp.servers": {
"notion": {
"command": "cmd",
"args": [
"/c",
"npx",
"-y",
"@jjar/notion-mcp-server"
],
"env": {
"NOTION_CLIENT_ID": "your-oauth2-client-id",
"NOTION_CLIENT_SECRET": "your-oauth2-client-secret",
"NOTION_REFRESH_TOKEN": "your-refresh-token",
"NOTION_INSTANCE_URL": "https://yourorg.my.notion.com",
// Optional: Enable Enterprise optimizations for Claude Enterprise accounts
"NOTION_ENTERPRISE_MODE": "true",
"NOTION_MAX_RESPONSE_SIZE": "75000",
"NOTION_MAX_RECORDS_PER_RESPONSE": "300"
},
"disabled": false,
"alwaysAllow": [
"test-connection",
"execute-soql",
"describe-sobject",
"get-record",
"get-apex-logs",
"list-metadata-types"
]
}
}
}
Configuration File Locations
Claude Desktop
- Windows:
%APPDATA%\Claude\claude_desktop_config.json - macOS:
~/Library/Application Support/Claude/claude_desktop_config.json
Cline (VS Code)
- Windows:
%APPDATA%\Code\User\globalStorage\saoudrizwan.claude-dev\settings\cline_mcp_settings.json - macOS:
~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json - Linux:
~/.config/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json
⚠️ Important: After adding or modifying the MCP server configuration, you must restart VS Code for the changes to take effect.
Cursor
- Windows:
%USERPROFILE%\.cursor\mcp.json - macOS:
~/.cursor/mcp.json - Linux:
~/.cursor/mcp.json
🏢 Enterprise Configuration
For Claude Enterprise accounts with 200K+ token context windows, this MCP server includes specialized optimizations to maximize data throughput while preventing context overflow.
Enterprise Benefits
- 75K character responses (vs 4K standard) - 18x larger responses
- 300 records per response (vs 25-50 standard) - 6-12x more data
- Intelligent response optimization - Automatic size management for Enterprise context windows
- Enhanced bulk operations - Higher thresholds for bulk API usage
- Auto-aggregation support - Intelligent data consolidation for complex queries
Enable Enterprise Mode
Add these environment variables to your MCP configuration:
{
"mcp.servers": {
"notion": {
"env": {
"NOTION_CLIENT_ID": "your-oauth2-client-id",
"NOTION_REFRESH_TOKEN": "your-refresh-token",
"NOTION_INSTANCE_URL": "https://yourorg.my.notion.com",
// Enterprise Optimization
"NOTION_ENTERPRISE_MODE": "true",
"NOTION_MAX_RESPONSE_SIZE": "75000",
"NOTION_MAX_RECORDS_PER_RESPONSE": "300",
"NOTION_BULK_QUERY_THRESHOLD": "5000",
"NOTION_BULK_DML_THRESHOLD": "500",
"NOTION_ENABLE_AUTO_AGGREGATION": "true"
}
}
}
}
Enterprise Response Optimization
When Enterprise mode is enabled:
- Smart Record Limiting: Automatically balances record count vs response size
- Context Window Monitoring: Real-time estimation of context usage
- Priority Field Optimization: Configurable field prioritization for large objects
- Bulk API Intelligence: Higher thresholds trigger bulk operations earlier
- Response Metadata: Detailed optimization information included in responses
Performance Characteristics
| Mode | Max Response Size | Max Records | Bulk Query Threshold | Bulk DML Threshold |
|---|---|---|---|---|
| Standard | 4,000 chars | 50 records | 2,000 records | 200 records |
| Enterprise | 75,000 chars | 300 records | 5,000 records | 500 records |
Enterprise Features in Action
// Enterprise mode automatically optimizes responses:
{
"records": [...], // Up to 300 records
"totalDisplayed": 300,
"totalOriginal": 1500,
"truncated": true,
"truncationReason": "Limited to 300 records for Enterprise context optimization",
"contextWindowUsage": "~65,000 chars (~16,250 tokens)",
"_enterpriseOptimization": {
"enabled": true,
"contextOptimized": "Optimized for Claude Enterprise 200K+ context window"
}
}
🔧 Environment Variables
| Variable | Required | Description | Example |
|---|---|---|---|
NOTION_CLIENT_ID | ✅ | Consumer Key from Connected App | 3MVG9PE4Q... |
NOTION_CLIENT_SECRET | ✅ | Consumer Secret from Connected App | A1B2C3D4E5... |
NOTION_REFRESH_TOKEN | ✅ | OAuth2 refresh token | 5Aep861TSESvWeug_w... |
NOTION_INSTANCE_URL | ✅ | Your Notion instance URL | https://mycompany.my.notion.com |
NOTION_ALLOW_WRITE | ⚠️ | Enable write operations (default: false) | true |
Enterprise Environment Variables
| Variable | Required | Description | Default | Enterprise Default |
|---|---|---|---|---|
NOTION_ENTERPRISE_MODE | 🏢 | Enable Enterprise optimizations | false | true |
NOTION_MAX_RESPONSE_SIZE | 🏢 | Maximum response size in characters | 4000 | 75000 |
NOTION_MAX_RECORDS_PER_RESPONSE | 🏢 | Maximum records per response | 50 | 300 |
NOTION_BULK_QUERY_THRESHOLD | 🏢 | Records threshold for bulk queries | 2000 | 5000 |
NOTION_BULK_DML_THRESHOLD | 🏢 | Records threshold for bulk DML | 200 | 500 |
NOTION_ENABLE_AUTO_AGGREGATION | 🏢 | Enable automatic data aggregation | false | true |
NOTION_API_VERSION | ⚙️ | Notion API version | 59.0 | 59.0 |
NOTION_TIMEOUT | ⚙️ | Request timeout in milliseconds | 120000 | 120000 |
Benefits of OAuth2 Authentication
- Individual User Access: Each user authenticates with their own credentials
- Granular Permissions: Respects user permissions and organizational policies
- Audit Trail: All actions are tracked under the specific user
- Security Compliance: Meets enterprise security requirements
- Token Management: Refresh tokens can be revoked if compromised
- No Password Exposure: Passwords are never stored or transmitted
🔒 Read-Only Mode (Default)
By default, the server runs in read-only mode for enhanced security. This means:
- ✅ Allowed: Query data, describe objects, retrieve metadata, get debug logs
- ❌ Blocked: Create, update, delete records, execute Apex, deploy metadata
Enabling Write Operations
To enable write operations, set the NOTION_ALLOW_WRITE environment variable:
NOTION_ALLOW_WRITE=true
Write operations include:
create-record,update-record,delete-record,upsert-recordexecute-apex,run-apex-testsdeploy-metadata,deploy-bundle
Security Considerations
- Read-only mode prevents accidental data modification
- Ideal for analytics, reporting, and development environments
- Enable write operations only when necessary and with appropriate user permissions
- All write operations still respect Notion user permissions and organizational policies
🛡️ Tool Safety Levels
✅ Safe for Auto-Approval (alwaysAllow)
test-connection- Connection validation (read-only)execute-soql- SOQL queries (read-only)describe-sobject- Metadata inspection (read-only)get-record- Single record retrieval (read-only)get-apex-logs- Debug log access (read-only)list-metadata-types- Metadata type discovery (read-only)
⚠️ Requires Manual Approval
create-record,update-record,delete-record,upsert-record- Data modificationdeploy-metadata- Metadata deploymentexecute-apex,run-apex-tests- Code executionexecute-sosl- Search operations (can be resource-intensive)retrieve-metadata- Metadata retrieval (can be large)
🔍 Troubleshooting
Common OAuth Issues
-
Invalid Client ID/Secret:
- Verify the Connected App credentials
- Ensure the app is deployed and active
-
Invalid Refresh Token:
- Re-generate the refresh token using the authorization flow
- Check token expiration in Connected App settings
-
Instance URL Mismatch:
- Use the exact instance URL from your Notion org
- For sandboxes, include the full sandbox URL
-
Permission Issues:
- Verify OAuth scopes in the Connected App
- Check user permissions for specific operations
Testing Your Configuration
Use the test-connection tool to verify your setup:
# The MCP server will use this tool automatically when you ask about connection status
# Example: "Test my Notion connection"
🏗️ Architecture
Core Components
- OAuth2 Authentication Manager - Secure token-based authentication
- Connection Manager - Singleton pattern with health monitoring
- Tool Classes - Organized by functionality (Query, Apex, Data, Metadata)
- Error Handler - Comprehensive error formatting with context
- Cache Manager - TTL-based caching for performance optimization
Performance Features
- Auto-Bulk Switching - Automatically uses Bulk API for large operations
- Intelligent Caching - SObject metadata cached for 1 hour
- Connection Reuse - Single connection across all operations
- Polling Optimization - Efficient monitoring of long-running operations
🧪 Testing
# Test individual tools
node tests/test-query-tools.js
node tests/test-data-tools.js
node tests/test-apex-tools.js
node tests/test-metadata-tools.js
🤝 Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
🔗 Related Projects
- Model Context Protocol - The protocol this server implements
- jsforce - Notion API library used in this project
- Claude Desktop - AI assistant that supports MCP servers
- Cline - VS Code extension for AI-assisted development
👨💻 Author
Jarosław Jaworski
🤖 Development Credits
Part of this implementation was developed with assistance from Claude Sonnet 4 using the Cline VS Code extension, demonstrating the power of AI-assisted development in creating comprehensive developer tools.
📄 License
This project is licensed under the MIT License - see the file for details.
⚠️ Deprecated: Username/Password Authentication
Security Warning: Username/password authentication is deprecated and not recommended for production use. Please migrate to OAuth2 authentication for better security and compliance.
For legacy systems that require username/password authentication, the following environment variables were supported:
NOTION_USERNAME- Notion usernameNOTION_PASSWORD- Notion passwordNOTION_SECURITY_TOKEN- Security token (if required)NOTION_LOGIN_URL- Login URL (production or sandbox)
Migration Path: Follow the OAuth2 setup instructions above to upgrade to secure authentication.
🚀 Kandji Deployment
This project includes automated deployment to Kandji MDM for macOS environments. The deployment workflow automatically uploads PKG installers to Kandji when releases are published.
Prerequisites
Configure the following GitHub Secrets:
MW_KANDJI_API_TOKEN- Kandji API token (Settings > Integrations > API Token)MW_KANDJI_API_URL- Kandji API URL (e.g.,https://<tenant>.api.kandji.io)MW_SLACK_BOT_TOKEN(optional) - Slack bot token for deployment notifications
Automatic Deployment
The workflow triggers automatically when:
- A GitHub release is published
- Manual trigger via
workflow_dispatch
Manual Deployment
To deploy a specific release to Kandji:
- Go to the Actions tab in GitHub
- Select "Push PKG to Kandji" workflow
- Click "Run workflow"
- Configure options:
- Release tag: Specific version (e.g.,
v1.1.0) or leave empty for latest - App name: Custom name for Kandji (default: "Notion MCP Server")
- Enforcement: Deployment policy (
install_and_enforce,install_once, orself_service) - Category: Self-service category (default: "Productivity")
- Release tag: Specific version (e.g.,
Deployment Features
- 📦 Automatic PKG Download - Retrieves signed PKG from GitHub releases
- 🔄 Dynamic Lookup - Updates existing Kandji Custom Apps or creates new ones
- 🛡️ Version Management - Follows
NAME-VERSION.pkgnaming convention - 📱 Slack Notifications - Optional deployment success notifications
- 🔍 Validation - PKG signature verification and integrity checks
Kandji Configuration
After deployment:
- New Custom Apps: Must be manually assigned to Blueprints in Kandji
- Updated Apps: Retain existing Blueprint assignments
- Enforcement Policies: Configured via workflow parameters
- Self-Service Categories: Organized for end-user discovery
Troubleshooting
- HTTP 503 Errors: kpkg automatically retries with delays
- Version Conflicts: Use dynamic lookup to update existing apps
- Blueprint Assignment: New apps require manual Blueprint configuration in Kandji
- Quarantine Issues: Workflow automatically clears quarantine attributes
For detailed logs, check the GitHub Actions workflow run output.
🔄 Automated Release System
This project features a fully automated release system that ensures consistent versioning and seamless deployment:
Automatic Releases
When you update package.json version (in a commit to master):
- 🤖 Auto-release workflow detects version changes
- 🏷️ Creates GitHub release with proper tag
- 📦 Triggers build workflow to create PKG installer
- 🚀 Deploys to Kandji automatically (5-minute delay for build completion)
Manual Version Management
# Bump version and trigger automated release
./scripts/bump-version.sh patch # 1.1.2 → 1.1.3
./scripts/bump-version.sh minor # 1.1.2 → 1.2.0
./scripts/bump-version.sh major # 1.1.2 → 2.0.0
# Fix current version situation (create missing release)
./scripts/create-missing-release.sh
# Sync versions across all files manually
./scripts/sync-version.sh [version]
Release Workflow Features
- 🔍 Version Detection - Automatic detection of
package.jsonchanges - 📝 Auto-Generated Release Notes - Dynamic release content based on version
- 🏗️ PKG Build Integration - Seamless integration with existing build workflow
- ⚙️ Kandji Auto-Deployment - Automatic MDM deployment after successful build
- 🔄 Version Synchronization - Keeps all files in sync (package.json, Xcode, etc.)
Version Consistency
The system maintains version consistency across:
- 📄
package.json- Primary version source - 🔒
package-lock.json- Automatically synced - 💻
src/index.ts- Server version reporting - 🍎 Xcode project
MARKETING_VERSION- macOS app versioning - 🏷️ Git tags - Release tagging
- 📝 GitHub release notes - Dynamic version references
Current Status: v1.1.2
We're currently transitioning to this automated system. The project is at v1.1.2 in package.json, with automated workflows in place for future releases.
📚 Documentation
Complete documentation is available in the directory:
- 🚀 - OAuth 2.0 configuration
- 🚢 - Installation and packaging
- 🛠️ - Technical implementation guides
- 📖 - Usage examples and patterns
- 🔧 - Issue resolution guides
👉 Start with the for a complete overview.