Created by Gabriel Lawrence
A Go-based Model Context Protocol (MCP) server that provides seamless integration with Microsoft OneNote via the Microsoft Graph API. This server enables AI assistants and other MCP clients to read, create, update, and manage OneNote notebooks, sections, pages, and embedded content with AI safety features including notebook-scoped authorization, caching, and intelligent content processing.
For the longest time, I've been dumping information into OneNote with the vision that eventually AI will be able to organize and synthesize it into useful, searchable content. This project represents the realization of that vision - giving AI direct access to OneNote through the Model Context Protocol (MCP) so it can finally help organize, search, and make sense of years of accumulated information.
This project serves as both a practical tool for AI-powered knowledge management and a learning playground for understanding the Model Context Protocol and AI-assisted development.
This software is licensed under the MIT License and is provided "AS IS" without warranty of any kind.
π¨ EARLY/TESTING SOFTWARE WARNING: This is early-stage software that exposes your OneNote data to AI agents who may autonomously create, update, move, or delete your data based on their interpretation of instructions.
π‘οΈ CRITICAL SAFETY PRECAUTIONS:
- Backup your OneNote data regularly before using this software
- Use the authorization system to restrict AI agent access to specific notebooks
- Carefully review and approve AI tool actions before execution, especially write operations
- Start with read-only permissions and gradually expand access as you gain confidence
- Test with non-critical data first to understand how AI agents interact with your content
Recommended Authorization Setup for Safety:
{
"authorization": {
"enabled": true,
"default_notebook_permissions": "none",
"notebook_permissions": {
"AI Test Notebook": "write"
}
}
}By using this software, you acknowledge that you understand these risks and have taken appropriate precautions to protect your data.
- QuickNote Tool: Rapid note-taking with automatic timestamping and format detection (HTML/Markdown/ASCII)
- Complete OneNote Operations: Full notebook, section, section group, and page management
- Advanced Page Updates: Command-based targeting with data-id attributes for precise content modifications
- Content Management: Rich HTML support with automatic format conversion and image optimization
- MCP Resources: Hierarchical URI-based resource discovery (
onenote://notebooks,onenote://sections, etc.)
- Notebook-Scoped Authorization: Simple permission system (none/read/write) to prevent AI accidents
- Multi-Layer Caching: Page metadata, search results, and notebook lookups with 5-minute expiration
- Progress Notifications: Real-time updates for long-running operations via MCP streaming
- OAuth 2.0 PKCE Flow: Secure authentication with non-blocking startup
- Audit Logging: Authorization decision logging for safety monitoring
- Multi-Mode Support: stdio (default) and HTTP protocols with SSE streaming
- Docker Ready: Multi-stage builds with security-first design and non-root execution
- Flexible Configuration: Environment variables, JSON files, or defaults
# 1. Clone the repository
git clone https://github.com/gebl/onenote-mcp-server.git
cd onenote-mcp-server
# 2. Set up configuration
cp configs/example-config.json docker/configs/config.json
# Edit docker/configs/config.json with your Azure app credentials
# 3. Build Docker image
docker build -f docker/Dockerfile -t onenote-mcp-server .
# 4. Install mcptools for interactive testing
# Windows: winget install mcptools
# macOS: brew install mcptools
# Linux: wget https://github.com/pyroprompts/mcptools/releases/latest/download/mcptools-linux-amd64
# 5. Run interactive MCP shell
cd docker
mcptools shell docker run \
-e ONENOTE_MCP_CONFIG="/configs/config.json" \
-v ./configs:/configs \
-i onenote-mcp-server
# 6. In the MCP shell, authenticate and start using OneNote
mcp > call initiateAuth
mcp > call listNotebooks
mcp > call selectNotebook "My Notebook"
mcp > call quickNote "Hello from OneNote MCP!"# 1. Clone and build
git clone <repository-url>
cd MCP-OneNote-golang
go build -o onenote-mcp-server ./cmd/onenote-mcp-server
# 2. Set environment variables
export ONENOTE_CLIENT_ID="your-azure-app-client-id"
export ONENOTE_TENANT_ID="your-azure-tenant-id"
export ONENOTE_REDIRECT_URI="http://localhost:8080/callback"
# 3. Run server
./onenote-mcp-server # stdio mode (default)
./onenote-mcp-server -mode=http # HTTP mode on port 8080
./onenote-mcp-server -mode=http -port=8181 # HTTP mode on custom port- Create an app registration in Azure Portal
- Configure OAuth 2.0 redirect URI (e.g.,
http://localhost:8181/callback) - Grant
Notes.ReadWriteAPI permissions (Delegated) - No client secret needed (uses PKCE flow)
- Go 1.21 or later
- Git for version control
- Docker Engine 20.10 or later
- Docker Compose (optional, for HTTP mode)
- mcptools (recommended for testing)
stdio Mode (Default) - ./onenote-mcp-server or ./onenote-mcp-server -mode=stdio
- Standard input/output communication
- Best for: CLI tools, direct process communication, development
HTTP Mode - ./onenote-mcp-server -mode=http [-port=8181]
- HTTP-based communication with Server-Sent Events (SSE) streaming
- Best for: Web applications, remote access, Claude Desktop integration
- Features: SSE streaming, optional Bearer token authentication, OAuth callback endpoint
| Variable | Description | Required | Default |
|---|---|---|---|
| Core Configuration | |||
ONENOTE_CLIENT_ID |
Azure App Registration Client ID | Yes | - |
ONENOTE_TENANT_ID |
Azure Tenant ID (use "common" for multi-tenant) | Yes | - |
ONENOTE_REDIRECT_URI |
OAuth2 redirect URI | Yes | - |
ONENOTE_DEFAULT_NOTEBOOK_NAME |
Default notebook name | No | - |
ONENOTE_MCP_CONFIG |
Path to JSON configuration file | No | - |
| QuickNote Configuration | |||
QUICKNOTE_NOTEBOOK_NAME |
Target notebook for quick notes | No | Falls back to default |
QUICKNOTE_PAGE_NAME |
Target page for quick notes | No | - |
QUICKNOTE_DATE_FORMAT |
Go time format for timestamps | No | Default format |
| Authorization Configuration | |||
AUTHORIZATION_ENABLED |
Enable authorization system | No | false |
AUTHORIZATION_DEFAULT_NOTEBOOK_PERMISSIONS |
Default notebook permission level | No | read |
| MCP Authentication (HTTP mode) | |||
MCP_AUTH_ENABLED |
Enable bearer token auth for HTTP mode | No | false |
MCP_BEARER_TOKEN |
Bearer token for HTTP authentication | No | - |
| Logging Configuration | |||
LOG_LEVEL |
General logging level (DEBUG/INFO/WARN/ERROR) | No | INFO |
LOG_FORMAT |
Log format (text/json) | No | text |
MCP_LOG_FILE |
Path to log file | No | Console only |
CONTENT_LOG_LEVEL |
Content logging verbosity (DEBUG/INFO/WARN/ERROR/OFF) | No | INFO |
Create configs/config.json:
{
"client_id": "your-azure-app-client-id",
"tenant_id": "your-azure-tenant-id",
"redirect_uri": "http://localhost:8181/callback",
"notebook_name": "My Default Notebook",
"quicknote": {
"notebook_name": "Personal Notes",
"page_name": "Daily Journal",
"date_format": "January 2, 2006 - 3:04 PM"
},
"authorization": {
"enabled": true,
"default_notebook_permissions": "read",
"notebook_permissions": {
"Personal Notes": "write",
"Work Notes": "read",
"AI Sandbox": "write",
"Private Thoughts": "none"
}
},
"mcp_auth": {
"enabled": true,
"bearer_token": "your-secret-bearer-token"
},
"log_level": "INFO",
"content_log_level": "INFO"
}The server uses OAuth 2.0 PKCE (Proof Key for Code Exchange) with non-blocking startup.
- Server Starts Immediately: No waiting for authentication
- Check Status: Use
auth_statustool to check current state - Initiate Auth: Use
auth_initiatetool to start OAuth flow - Browser Login: Visit provided Microsoft login URL
- Auto Refresh: Tokens automatically refreshed before expiration
auth_status: Check current authentication state and token informationauth_initiate: Start OAuth flow - returns browser URLauth_refresh: Manually refresh tokens to extend sessionauth_clear: Logout and clear all stored tokens
# Start server (immediate, no blocking)
./onenote-mcp-server
# Check authentication status
mcp > call auth_status
# Response: {"authenticated": false, "message": "No authentication tokens found"}
# Initiate authentication
mcp > call auth_initiate
# Response: {"authUrl": "https://login.microsoftonline.com/...", ...}
# User visits URL in browser, completes OAuth flow
# Verify authentication
mcp > call auth_status
# Response: {"authenticated": true, "tokenExpiresIn": "59 minutes", ...}
# Use OneNote operations
mcp > call listNotebooksRapid note-taking with intelligent format detection and automatic timestamping.
Features:
- Automatic timestamp heading (configurable format)
- Smart format detection (HTML/Markdown/ASCII)
- Configurable target notebook and page
- Append-only operation preserving existing content
- Multi-layer caching for fast operations
Usage:
{"name": "quick_note", "arguments": {"content": "# Meeting Notes\n\n- Action: Review API\n- **Deadline**: EOW"}}Simplified notebook-scoped permission system designed as a safety mechanism, not a security feature.
Permission Levels:
none: Notebook not accessible/selectable by AI agentsread: Read-only access - prevents create/update/delete operationswrite: Full access including create/update/delete operations
How It Works:
listNotebooksreturns only notebooks withreadorwritepermissionsselectNotebookvalidates notebook has non-nonepermission- All subsequent operations inherit the selected notebook's permission level
- Write operations blocked on read-only notebooks
- Cross-notebook access prevented by scoping
Safety Philosophy: Real security comes from Microsoft Graph API, OAuth 2.0, and Azure Active Directory. This authorization system provides AI agent safety guardrails to prevent accidental access to sensitive notebooks.
Notebook Operations
notebooks- List all notebooksnotebook_select- Select active notebook by name/IDnotebook_current- Get currently selected notebooksections- Get hierarchical sections and section groups
Section Operations
section_create- Create section in notebook/section groupsection_group_create- Create section group in notebook/section group
Page Operations
pages- List pages in sectionpage_create- Create new page with title and contentpage_update- Update entire page contentpage_update_advanced- Update specific page parts using commands (preferred)page_delete- Delete page by IDpage_copy- Copy page to different section (async)page_move- Move page to different section
Content Operations
page_content- Get page HTML (useforUpdate=truefor data-id attributes)page_items- List embedded items (images, files)page_item_content- Get page item data with base64 content
Special Tools
quick_note- Rapid note-taking with auto-timestampingcache_clear- Clear all cached data
Authentication Tools
auth_status- Check authentication stateauth_initiate- Start OAuth flowauth_refresh- Refresh tokensauth_clear- Logout
For detailed tool documentation, see docs/api.md.
Hierarchical URI-based resources for data discovery:
Notebooks
onenote://notebooks- All notebooks with metadataonenote://notebooks/{name}- Specific notebook detailsonenote://notebooks/{name}/sections- Notebook sections tree
Sections
onenote://sections- Global sections across notebooksonenote://notebooks/{name}/sections- Notebook-specific sections
Pages
onenote://pages/{sectionId}- Pages in sectiononenote://page/{pageId}- Page HTML with data-id attributes
# Build from project root
docker build -f docker/Dockerfile -t onenote-mcp-server .Using mcptools (recommended):
cd docker
mcptools shell docker run \
-e ONENOTE_MCP_CONFIG="/configs/config.json" \
-v ./configs:/configs \
-i onenote-mcp-serverUsing Docker Compose:
cd docker
docker-compose build --no-cache # Build fresh image
docker-compose up -d # Start in background
docker-compose logs -f # View logs
docker-compose down # Stop and removeThe Docker Compose setup:
- Runs on port 8181 by default
- Mounts config from
docker/configs/config.json - Supports Traefik labels for reverse proxy
- Runs as non-root user (mcpuser) for security
- OAuth callbacks handled at
http://localhost:8181/callback
# stdio mode
docker run -it \
-e ONENOTE_MCP_CONFIG="/configs/config.json" \
-v ./docker/configs:/configs \
onenote-mcp-server
# HTTP mode
docker run -d \
-p 8181:8181 \
-e ONENOTE_MCP_CONFIG="/configs/config.json" \
-v ./docker/configs:/configs \
onenote-mcp-server -mode=http -port=8181MCP-OneNote-golang/
βββ cmd/onenote-mcp-server/ # Main application entry point
β βββ main.go # Server initialization, mode selection
β βββ *Tools.go # MCP tool handlers
β βββ *Resources.go # MCP resource providers
βββ internal/ # Domain-specific modules
β βββ auth/ # OAuth2 authentication
β βββ authorization/ # Notebook-scoped permissions
β βββ config/ # Multi-source configuration
β βββ graph/ # Microsoft Graph SDK integration
β βββ notebooks/ # Notebook domain operations
β βββ pages/ # Page domain operations
β βββ sections/ # Section domain operations
β βββ utils/ # Shared utilities
β βββ logging/ # Structured logging
βββ configs/ # Configuration files
βββ docker/ # Docker deployment
βββ docs/ # Documentation
βββ CLAUDE.md # AI development guidance
- Modular MCP Server: Clear separation between entry point, domain logic, and configuration
- Client Composition: Specialized domain clients (NotebookClient, PageClient, SectionClient) sharing HTTP/auth
- Multi-Layer Caching: Thread-safe caching with 5-minute expiration and automatic invalidation
- Progressive Enhancement: Starts with basic MCP functionality, adds enterprise features
# Build server
go build -o onenote-mcp-server.exe ./cmd/onenote-mcp-server
# Run tests
go test ./...
# Generate coverage report
go test ./... -coverprofile=coverage.out
go tool cover -html=coverage.out -o coverage.html
# Test specific packages
go test ./internal/notebooks -v
go test ./internal/pages -v
go test ./internal/sections -vmcptools provides an interactive shell for testing MCP servers:
Installation:
# Windows: winget install mcptools
# macOS: brew install mcptools
# Linux: wget https://github.com/pyroprompts/mcptools/releases/latest/download/mcptools-linux-amd64Common Commands:
/h or /help # Show help
/tools # List all available tools
/resources # List all available resources
/q or /quit # Exit shell
call toolName arg1 arg2 # Call tool
call createPage "Title" "sectionId" # Example- API Documentation: docs/api.md
- Setup Guide: docs/setup.md
- Authorization Guide: docs/authorization-integration.md
- AI Development Notes: CLAUDE.md
- Model Context Protocol: https://modelcontextprotocol.io
MIT License - See LICENSE file for details.
Built with the Model Context Protocol and Microsoft Graph API.