brentmid/evernote-mcp-server
If you are the rightful owner of evernote-mcp-server 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 Evernote MCP Server is a local server that connects Claude Desktop or any MCP-compatible LLM with your Evernote account, enabling contextual queries and searches over your notes using natural language.
createSearch
Search notes using natural language queries
getSearch
Retrieve cached search results
getNote
Get detailed metadata for a specific note
getNoteContent
Retrieve full note content in text, HTML, or ENML format
Evernote MCP Server
A local MCP server that connects Claude Desktop (or any MCP-compatible LLM) with your Evernote account, allowing contextual queries and searches over your notes using natural language.
π― Project Goal
Enable local, secure AI-assisted access to your Evernote notes. For example:
"Summarize all my Evernotes regarding my Sea Pro boat."
This project allows the LLM to send MCP calls like createSearch
, getNote
, and getNoteContent
, which are translated into API calls to Evernote. The response is returned to the LLM in a structured format.
β Features
- Supports read-only Evernote access (searching, reading, and listing notes)
- OAuth 1.0a authentication with browser auto-launch for secure authorization
- Uses macOS Keychain to securely store access tokens
- π v1.1.0: Automatic token expiration detection - Server checks token validity on startup
- π v1.1.0: Interactive re-authentication prompts - User-friendly prompts when tokens expire
- π v1.1.0: Enhanced error handling - Specific EDAMUserException error code reporting
- π v1.1.0: Proactive token management - Prevents API failures from expired credentials
- HTTPS-only server with self-signed certificates for local development
- Designed to work with Claude Desktop MCP integrations, with future-proofing for other LLMs (e.g., ChatGPT Desktop)
- Configurable debug logging via
DEV_MODE
environment variable with automatic token redaction for security - Easy to extend later for note creation, updates, or deletion
π§° Tech Stack
- Node.js + Express with HTTPS
- Evernote API (OAuth 1.0a + REST)
- macOS Keychain via
keytar
- MCP protocol compliance
- GitHub Copilot and 1Password SSH signing for development
ποΈ Authentication
Evernote uses OAuth 1.0a (not OAuth 2.0) for API authentication:
- First-time setup: Browser-based OAuth 1.0a flow with automatic token exchange
- Token storage: Access tokens stored securely in macOS Keychain via
keytar
- Automatic reuse: Stored tokens are automatically used for subsequent API calls
- Production environment: Uses Evernote production API (sandbox decommissioned)
- (Planned) Future support for file-based token store for Linux/Windows
π» Setup
Requirements
- macOS with Node.js 18+ installed via Homebrew (
node --version
) - OpenSSL for SSL certificate generation
- Evernote developer account and API credentials
- Claude Desktop app (for MCP integration)
- GitHub SSH key configured via 1Password (for development)
- Visual Studio Code with GitHub Copilot and Copilot Chat extensions (for development)
Clone & Setup
git clone git@github.com:brentmid/evernote-mcp-server.git
cd evernote-mcp-server
npm install
Get Evernote API Credentials
- Register your application at Evernote Developers
- Create a new app and note your Consumer Key and Consumer Secret
- Set callback URL to
https://localhost:3443/oauth/callback
Configure Environment Variables
Set your Evernote API credentials:
# Add to your shell profile (.zshrc, .bashrc, etc.)
export EVERNOTE_CONSUMER_KEY="your-consumer-key-here"
export EVERNOTE_CONSUMER_SECRET="your-consumer-secret-here"
# Optional: Enable detailed debug logging for development
export DEV_MODE=true
# Reload your shell or run:
source ~/.zshrc
Generate SSL Certificates
The server runs over HTTPS and requires SSL certificates for local development:
# Create certificate directory
mkdir cert
# Generate self-signed certificate (valid for 365 days)
openssl req -x509 -newkey rsa:4096 -keyout cert/localhost.key -out cert/localhost.crt -days 365 -nodes -subj "/C=US/ST=Local/L=Local/O=Local/OU=Local/CN=localhost"
Start the Server
npx node index.js
The server will start on https://localhost:3443
. Your browser will show a security warning for the self-signed certificate - this is normal for local development.
β° Token Expiration Handling (v1.1.0+)
The server now automatically checks for expired authentication tokens on startup:
For Valid Tokens:
π Starting Evernote MCP Server...
π Token status: Token valid until 8/21/2025, 1:20:00 AM
β
Using existing valid authentication tokens
β
Authentication ready
π Evernote MCP Server listening on HTTPS port 3443
For Expired Tokens:
π Starting Evernote MCP Server...
π Token status: Token expired on 6/16/2025, 9:55:49 PM
β οΈ Your Evernote authentication tokens have expired.
Would you like to re-authenticate now? (y/N): y
π§Ή Re-authenticating with Evernote...
π Starting Evernote OAuth flow...
If you choose N
(no), the server will exit gracefully with instructions to restart and choose y
when ready to re-authenticate.
First Run & OAuth Flow
- Generate SSL certificates (see setup instructions above)
- Set environment variables with your Evernote API credentials
- Start the server:
npx node index.js
- Complete OAuth authentication:
- Server automatically opens your browser to Evernote's authorization page
- Accept the self-signed certificate warning in your browser
- Log in to your Evernote account and authorize the application
- You'll be redirected back to the server with a success message
- Access token is automatically stored in macOS Keychain for future use
OAuth Flow Details
The server implements Evernote's OAuth 1.0a flow:
- Request Token: Server generates temporary request token
- User Authorization: Browser opens Evernote authorization URL
- Callback: User authorizes app, Evernote redirects to callback URL
- Access Token: Server exchanges request token for permanent access token
- Storage: Access token stored securely in macOS Keychain
Note: The server uses Evernote's production environment (sandbox has been decommissioned by Evernote).
π Claude Desktop Integration
After completing the server setup above, you need to configure Claude Desktop to connect to your MCP server.
Step 1: Locate Claude Desktop Configuration
Claude Desktop stores its configuration at:
~/Library/Application Support/Claude/claude_desktop_config.json
Step 2: Configure MCP Server
Edit the Claude Desktop configuration file to include your Evernote MCP server:
{
"mcpServers": {
"evernote": {
"command": "node",
"args": ["/path/to/your/evernote-mcp-server/mcp-server.js"],
"env": {
"EVERNOTE_CONSUMER_KEY": "your-actual-consumer-key",
"EVERNOTE_CONSUMER_SECRET": "your-actual-consumer-secret"
}
}
}
}
Important: Replace the placeholder values with your actual Evernote API credentials.
Step 3: Restart Claude Desktop
- Quit Claude Desktop completely (β+Q or right-click dock icon β Quit)
- Reopen Claude Desktop
- Verify connection: You should see Evernote tools available in the interface
Step 4: Test Integration
Try asking Claude to search your Evernote notes:
"Search my Evernote for notes about project planning"
"Find my most recent meeting notes in Evernote"
"Show me all Evernote notes tagged with 'important'"
Available Claude Desktop Tools
Once connected, Claude Desktop will have access to these Evernote tools:
createSearch
: Search notes using natural language queriesgetSearch
: Retrieve cached search resultsgetNote
: Get detailed metadata for a specific notegetNoteContent
: Retrieve full note content in text, HTML, or ENML format
Troubleshooting Claude Desktop Connection
Connection fails with "upstream connect error":
- Restart Claude Desktop completely (β+Q then reopen)
- Check credentials are correctly set in
claude_desktop_config.json
- Ensure the server path in
args
is absolute and correct (mcp-server.js
notindex.js
) - Test MCP server standalone:
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | node mcp-server.js
Tools not visible:
- Wait a few seconds after Claude Desktop restart
- Check Claude Desktop console for error messages
- Verify OAuth authentication completed successfully by running
node index.js
first
Authentication errors:
- Complete OAuth flow by running the HTTPS server standalone first:
node index.js
- π v1.1.0: Server now automatically detects expired tokens and prompts for re-authentication
- Check tokens are stored in macOS Keychain (
Keychain Access.app
) - Verify Evernote API credentials are valid and active
- π v1.1.0: If you get
EDAMUserException
errors, restart the server to check token expiration
Configuration Alternatives
Option 1: Environment Variables (Recommended)
Set credentials in your shell environment and remove the env
section from Claude Desktop config:
# In your ~/.zshrc or ~/.bashrc
export EVERNOTE_CONSUMER_KEY="your-consumer-key"
export EVERNOTE_CONSUMER_SECRET="your-consumer-secret"
Then use this simpler Claude Desktop configuration:
{
"mcpServers": {
"evernote": {
"command": "node",
"args": ["/path/to/your/evernote-mcp-server/mcp-server.js"]
}
}
}
Option 2: Launch from Terminal Open Claude Desktop from a terminal where environment variables are set:
# Set credentials
export EVERNOTE_CONSUMER_KEY="your-key"
export EVERNOTE_CONSUMER_SECRET="your-secret"
# Launch Claude Desktop
open -a "Claude"
π Debug & Development
Debug Logging
The server supports detailed debug logging via the DEV_MODE
environment variable:
# Enable detailed debug logging
export DEV_MODE=true
# Or run with debug mode for a single session
DEV_MODE=true npx node index.js
Debug Features:
- MCP Tool Invocations: Detailed logging of all tool calls with timestamps
- Evernote API Requests: Full request payloads and parameters
- Evernote API Responses: Response summaries and error details
- Token Redaction: Automatic redaction of sensitive information (tokens, secrets, keys)
- Error Details: Enhanced error logging with raw response data
- Stderr Logging: All debug messages go to stderr to avoid interfering with JSON-RPC protocol
Normal vs Debug Mode:
- Normal: Basic logging with key information only (to stderr)
- Debug: Detailed JSON logging with redacted sensitive data (to stderr)
Important: All emoji-based debug messages are sent to stderr, not stdout, ensuring clean JSON-RPC communication with Claude Desktop.
Example debug output:
π§ [2025-06-17T00:07:56.351Z] MCP Tool Invocation: createSearch
π₯ Args: {
"query": "Sea Pro boat",
"authenticationToken": "[REDACTED:19chars]"
}
π [2025-06-17T00:07:57.123Z] Evernote API Request: /findNotesMetadata
π€ Request: {
"filter": { "words": "Sea Pro boat" },
"authenticationToken": "[REDACTED:19chars]"
}
π§ͺ Testing
The project includes a comprehensive test suite with 38 tests covering all critical functionality:
Test Commands
# Run all tests
npm test
# Run tests with coverage report
npm run test:coverage
# Run tests in watch mode (for development)
npm run test:watch
Test Structure
tests/
βββ auth.test.js # OAuth 1.0a authentication tests
βββ server.test.js # Express server route tests
βββ integration.test.js # End-to-end workflow tests
βββ setup.js # Global test configuration
βββ jest.config.js # Jest configuration
Test Coverage Details
π auth.test.js - OAuth Authentication (12 tests)
- OAuth Parameter Generation: Validates required OAuth 1.0a parameters
- HMAC-SHA1 Signature Generation: Tests cryptographic signatures with known test vectors
- Keychain Integration: Store/retrieve tokens in macOS Keychain
- Authentication Flow: Existing token reuse vs new OAuth flow initiation
- Configuration Validation: Evernote endpoints and environment variables
- Error Handling: Network failures and keychain access errors
π server.test.js - Express Server Routes (15 tests)
- Health Check (
GET /
): Server status and JSON responses - OAuth Callback (
GET /oauth/callback
):- Successful token exchange
- Missing parameter validation
- Invalid OAuth state handling
- Error scenarios
- MCP Endpoint (
POST /mcp
):- Authenticated request handling
- Unauthenticated request rejection (401)
- JSON body parsing
- Internal error handling
- Content-Type Handling: JSON validation and malformed request handling
- Route Validation: 404 errors for unknown routes and wrong HTTP methods
π integration.test.js - End-to-End Workflows (11 tests)
- Complete OAuth Flow: Simulated request token β authorization β access token exchange
- OAuth State Management: State preservation between request and callback phases
- Browser Integration: System browser launching for authorization
- Error Scenarios: Network failures, invalid responses, keychain errors
- Configuration Validation: Endpoint URLs and credential validation
- Token Lifecycle: Storage, retrieval, and reuse patterns
Coverage Requirements
The test suite maintains high coverage standards:
- Branches: 70% minimum coverage
- Functions: 80% minimum coverage
- Lines: 80% minimum coverage
- Statements: 80% minimum coverage
Test Features
- Comprehensive Mocking: All external dependencies (Keychain, browser, SSL, network)
- Environment Isolation: Test-specific environment variables prevent interference
- Real Crypto Testing: Actual HMAC-SHA1 signature validation with known test vectors
- Error Scenario Coverage: Network failures, malformed responses, access denials
- Integration Validation: Full OAuth workflow simulation without external API calls
Running Specific Tests
# Run only authentication tests
npm test auth.test.js
# Run only server tests
npm test server.test.js
# Run only integration tests
npm test integration.test.js
# Run tests matching a pattern
npm test -- --testNamePattern="OAuth"
The test suite ensures OAuth 1.0a implementation correctness, validates all server endpoints, and provides confidence in the authentication flow without requiring actual Evernote API calls or SSL certificates during testing. Claude Desktop can also be used to validate that your MCP server responds correctly to natural language prompts.
π Changelog
v1.1.0 (Latest)
π New Features:
- Automatic token expiration detection - Server checks token validity on startup
- Interactive re-authentication prompts - User-friendly prompts for expired tokens
- Enhanced error handling - Specific EDAMUserException error code reporting
- Proactive token management - Prevents API failures from expired credentials
π§ Technical Improvements:
- Added
checkTokenExpiration()
function with comprehensive validation - Added
askUserConfirmation()
for interactive user prompts - Added
clearStoredTokens()
for safe token cleanup - Enhanced server startup flow with expiration checks
- Improved error messaging throughout authentication flow
π§ͺ Testing:
- All 38 existing tests continue to pass
- Token expiration functionality tested and validated
v1.0.0
- Initial release with full OAuth 1.0a implementation
- Complete Apache Thrift protocol integration
- Four MCP tools: createSearch, getSearch, getNote, getNoteContent
- Comprehensive test suite (38 tests)
- Claude Desktop MCP integration
- macOS Keychain token storage
- HTTPS server with self-signed certificates
π Security
- No third-party data sent anywhere except to Evernote via HTTPS.
- Authentication tokens stored using OS-native secure storage.
- Signing key usage (SSH-based GPG) is enforced on all commits.
π License
Licensed under the MIT License. See LICENSE
file for full terms.
πββοΈ Author
Maintained by @brentmid.
This project is both a functional integration and an educational experience in MCP, Evernoteβs API, GitHub workflows, and modern Node.js practices.
Pull requests and contributions are welcome after MVP completion. Check the Issues tab for known tasks.