About Kas Fastmcp
Kas Fastmcp is an MCP server in the Productivity category: kas Notion MCP.
Install
git clone https://github.com/kascoded/kas-fastmcpThis server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.
Ask AI
Ask AI about Kas Fastmcp
Powered by Claude · Grounded in docs
Security checks
- ✓README presentThe repository ships documentation.
5 checks have not been run yet.
README
Notion MCP Server
A production-grade Model Context Protocol (MCP) server for Notion, providing comprehensive database operations with schema validation and intelligent property handling.
Features
- 🔧 Full CRUD Operations - Create, read, update pages across Notion databases
- 🔍 Smart Search & Query - Powerful filtering and search capabilities
- 📊 Schema Management - Automatic schema fetching and validation
- 🎨 Content Formatting - Markdown ↔ Notion blocks conversion
- ⚡ Async Architecture - High-performance async operations
- 🛡️ Type Safety - Comprehensive property validation
- 🔄 API 2025-09-03 - Uses latest Notion API with data sources
Architecture
kas-fastmcp/
├── main.py # Entry point
├── config.py # NotionConfig, loads databases.yaml
├── notion_server/
│ ├── server.py # FastMCP("KasNotionMCP") instance
│ ├── deps.py # Shared NotionClient + SchemaManager singletons
│ ├── core/
│ │ ├── client.py # NotionClient (httpx wrapper, 429 retry, connection pool)
│ │ ├── schema.py # SchemaManager (10-min TTL, disk cache)
│ │ └── formatters.py # PropertyFormatter, BlockFormatter (markdown <-> blocks)
│ ├── tools/
│ │ ├── query.py # notion_query, notion_find_page_by_name, notion_search, notion_list_data_sources, notion_discover_databases
│ │ ├── pages.py # notion_get_page, notion_get_data_source, notion_create_item, notion_update_item
│ │ ├── content.py # notion_get_page_content, notion_append_content, notion_replace_content
│ │ └── schema_sync.py # notion_sync_schemas, notion_validate_config
│ └── utils/
│ └── validators.py # PropertyValidator
└── databases.yaml # Database configuration
Design Principles
- Separation of Concerns - Core logic separated from MCP layer
- No Circular Dependencies - Clean, linear dependency flow
- Immutable Configuration - Config is never mutated at runtime
- Schema-First - Validate against actual Notion schemas
- Testable - Each layer can be tested independently
Installation
Prerequisites
- Python 3.10+
- Notion Integration with API access
- Notion databases with integration added
Setup
- Clone the repository
git clone <your-repo-url>
cd kas-fastmcp
- Install dependencies
uv sync
- Configure environment
cp .env.example .env
# Edit .env and add your NOTION_TOKEN
- Configure databases
cp databases.yaml.example databases.yaml
# Edit databases.yaml and add your database configurations
Getting Your Notion Credentials
-
Create Integration
- Go to https://www.notion.so/my-integrations
- Click "New integration"
- Give it a name and select your workspace
- Copy the "Internal Integration Token"
-
Get Data Source IDs
- Open your database in Notion
- Click "..." menu → Settings
- Manage data sources → Copy data source ID
- Add to
databases.yaml
-
Add Integration to Databases
- Open each database in Notion
- Click "..." menu → Connections
- Add your integration
Configuration
databases.yaml
Define all your Notion databases:
zettelkasten:
data_source_id: "your-data-source-id-here"
database_id: "your-database-id-here"
title_property: "title"
description: "Personal knowledge management"
habits:
data_source_id: "your-data-source-id-here"
database_id: "your-database-id-here"
title_property: "title"
description: "Habit tracking"
.env
NOTION_TOKEN=ntn_your_token_here
NOTION_API_VERSION=2025-09-03
Usage
Running the Server
Development:
python main.py
With FastMCP CLI:
fastmcp run main.py
Claude Desktop Integration
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"kas-notion": {
"command": "python",
"args": ["/path/to/kas-fastmcp/main.py"]
}
}
}
Available Tools (15 total)
Query Tools (query.py)
notion_query- Query pages from a databasenotion_find_page_by_name- Find page by exact titlenotion_search- Workspace-wide searchnotion_list_data_sources- List data sources for a databasenotion_discover_databases- Discover all accessible databases
Page Tools (pages.py)
notion_get_page- Get page with properties (fully paginated wheninclude_content=True)notion_get_data_source- Get database schemanotion_create_item- Create new pagenotion_update_item- Update page properties
Content Tools (content.py)
notion_get_page_content- Get page content as markdownnotion_append_content- Append blocks to pagenotion_replace_content- Clear all blocks on a page and write new markdown content
Schema Tools (schema_sync.py)
notion_sync_schemas- Sync schemas from Notion and optionally update confignotion_validate_config- Validate current database configuration
Available Resources
notion://databases- Lists all configured databases as JSONnotion://databases/{source_name}/schema- Returns the cached schema for a specific database
Testing
Connection Testing
Quick token verification:
python connection_testing/token_verification.py
Full connection test:
python connection_testing/test_connection.py
This will:
- Validate your configuration
- Test API connectivity
- Check database access
- Fetch schemas
Validation Testing
Test the property validator directly:
python test_validation.py
Development
Adding a New Database
- Add to
databases.yaml:
my_database:
data_source_id: "your-id"
database_id: "your-id"
title_property: "Name"
description: "My new database"
- No code changes needed! The server automatically loads all databases from the YAML file.
Adding a New Tool
- Choose the appropriate module (
query.py,pages.py, orcontent.py) - Use the
@mcp.tooldecorator - Import and use core modules
- Document with clear docstrings
Example:
from notion_server.server import mcp
from notion_server.deps import _client # shared singleton — do not instantiate a new one
@mcp.tool
async def my_new_tool(param: str) -> dict:
"""
Tool description.
Args:
param: Parameter description
Returns:
Result description
"""
result = await _client.get(f"endpoint/{param}")
return result
Project Structure Explained
core/ - Pure business logic, no MCP dependencies
- Testable independently
- Reusable in other projects
- No side effects
tools/ - MCP tool definitions
- Thin wrappers around core modules
- Handle MCP-specific concerns
- Minimal business logic
utils/ - Shared utilities
- Validators
- Helpers
- Common functions
Validation System
How It Works
Properties are validated against Notion's schema before API calls:
# Automatic validation
notion_create_item(
source_name="zettelkasten",
properties={
"title": {"title": [{"text": {"content": "My Note"}, "type": "text"}]},
"nonexistent": {"rich_text": [...]} # ❌ Validation error!
}
)
What Gets Validated
✅ Property exists in schema
✅ Property type matches
✅ Select options are valid
✅ Read-only properties rejected
✅ Required properties present (strict mode)
Direct Validation
Use the validator directly in your code:
from notion_server.core import SchemaManager, NotionClient
from notion_server.utils import PropertyValidator
client = NotionClient()
schema_manager = SchemaManager(client)
schema = await schema_manager.get_schema("zettelkasten")
validator = PropertyValidator(schema)
is_valid, errors = validator.validate_properties(properties)
Troubleshooting
Common Issues
"NOTION_TOKEN not found"
- Create
.envfile from.env.example - Add your token from https://www.notion.so/my-integrations
"Database not found (404)"
- Check database_id in
databases.yaml - Ensure integration is added to the database
- Verify integration has access
"No databases configured"
- Create
databases.yamlfromdatabases.yaml.example - Add at least one database configuration
"Property validation failed"
- Check property names match your schema
- Ensure values are in correct Notion format
- Verify select options are valid
Debug Mode
Enable detailed logging by checking server output:
python main.py 2>&1 | tee server.log
API Reference
NotionClient
client = NotionClient(token=None, api_version=None)
await client.get(endpoint)
await client.post(endpoint, payload)
await client.patch(endpoint, payload)
SchemaManager
schema_manager = SchemaManager(client)
schema = await schema_manager.get_schema(source_name)
data_source_id = await schema_manager.get_data_source_id(source_name)
config = schema_manager.get_source_config(source_name)
PropertyFormatter
formatter = PropertyFormatter()
title = formatter.extract_title(properties)
formatted = formatter.format_for_display(properties)
BlockFormatter
formatter = BlockFormatter()
markdown = formatter.to_markdown(blocks)
blocks = formatter.from_markdown(markdown)
Contributing
Code Style
- Use type hints
- Write docstrings
- Keep functions focused
- Follow separation of concerns
Testing
- Test core modules independently
- Test tools through MCP protocol
- Validate against real Notion databases
License
MIT
Acknowledgments
- Built with FastMCP
- Uses Notion API 2025-09-03
- Developed for AI-powered productivity workflows
See CHANGELOG.md for version history.
Support
For issues, questions, or contributions, please open an issue on GitHub.
Built with ❤️ for AI-powered productivity
README copy captured when this server was indexed; it may lag the repository. The original is authoritative.