Mcp Evernote — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Mcp Evernote (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
A Model Context Protocol (MCP) server that provides seamless integration with Evernote for note management, organization, and knowledge capture. Works with both Claude Code and Claude Desktop.
Evernote stopped issuing new developer API keys. If you are a new user and cannot obtain a Consumer Key/Secret, skip the standard OAuth setup and use the cookie-based authentication method instead — no API key required.
Supported Node.js: `>=20.16.0 <21` or `>=22.3.0`. In practice that means Node 20.16+, 22.3+, 24, or newer — the two gaps are Node 21.x and Node 22.0–22.2. This is not an arbitrary floor: it mirrors the engines range that the PDF attachment extraction path (pdf-parse, and its pdfjs-dist transitive dependency) actually declares, and the range is genuinely disjoint.
Check with node --version. On Node 18 or 21, or on 22.0–22.2, upgrade before installing — Node 21 reached end-of-life in June 2024, and 22.3+ supersedes the early 22 patches.
Upgrading from 1.x? 2.0.0 raises the Node requirement from 18.18.0 and changes evernote_get_resource to return extracted text by default instead of binary data. The tool surface was also consolidated from 27 tools to 15 — the retired names still work as deprecated aliases, so existing calls keep running. See MIGRATION.md./mcp command#### Option 1: Using NPX (No Installation Required)
The simplest way - no need to install anything globally:
# For Claude Desktop - Run authentication
npx -y -p @verygoodplugins/mcp-evernote mcp-evernote-auth
# For Claude Code - Just add the server
claude mcp add evernote "npx -y -p @verygoodplugins/mcp-evernote mcp-evernote"The server can poll Evernote for changes and send webhook notifications when notes are created, updated, or deleted.
#### Configuration
# Enable auto-start polling (default: false)
EVERNOTE_POLLING_ENABLED=true
# Poll interval in milliseconds (default: 3600000 = 1 hour, min: 900000 = 15 min)
EVERNOTE_POLL_INTERVAL=3600000
# Webhook URL to receive change notifications
EVERNOTE_WEBHOOK_URL=https://your-endpoint.com/webhooks/evernote#### Webhook Payload
When changes are detected, a POST request is sent to your webhook URL:
{
"source": "mcp-evernote",
"timestamp": "2025-12-15T10:30:00.000Z",
"changes": [
{
"type": "note_created",
"guid": "abc123...",
"title": "My New Note",
"notebookGuid": "def456...",
"timestamp": "2025-12-15T10:29:55.000Z"
}
]
}#### Manual Control
Use the evernote_polling tool to control polling:
polling({action:"start"}) - Start polling manuallypolling({action:"stop"}) - Stop pollingpolling({action:"poll"}) - Check for changes immediatelypolling({action:"status"}) - Get polling configuration and statusFor real-time notifications, Evernote supports webhooks but requires manual registration:
[email protected] with:#### Option 2: Global Installation
Install once, use anywhere:
# Install globally
npm install -g @verygoodplugins/mcp-evernote
# For Claude Desktop - Run authentication
mcp-evernote-auth
# For Claude Code - Add the server
claude mcp add evernote "mcp-evernote"#### Option 3: Local Development
For contributing or customization:
# Clone and install
git clone https://github.com/verygoodplugins/mcp-evernote.git
cd mcp-evernote
npm install
# Run setup wizard
npm run setupNote: Evernote has stopped issuing new developer API keys to new applicants. If you are a new user, skip this section and use the cookie-based authentication method instead.
#### Interactive Setup (Recommended)
The auth script will prompt you for credentials if not found:
# Run authentication - prompts for API keys if needed
npx -p @verygoodplugins/mcp-evernote mcp-evernote-auth#### Environment Variables (Optional)
For automation, you can set credentials via environment variables:
# Create .env file (optional)
EVERNOTE_CONSUMER_KEY=your-consumer-key
EVERNOTE_CONSUMER_SECRET=your-consumer-secret
EVERNOTE_ENVIRONMENT=production # or 'sandbox'
OAUTH_CALLBACK_PORT=3000 # Default: 3000
# Polling configuration (optional)
EVERNOTE_POLLING_ENABLED=true # Auto-start polling
EVERNOTE_POLL_INTERVAL=3600000 # 1 hour (min: 900000 = 15 min)
EVERNOTE_WEBHOOK_URL=https://your-endpoint.com/webhooks/evernote # Webhook for change notifications
# Rate-limit transport (optional)
EVERNOTE_MAX_CONCURRENCY=3 # Max simultaneous NoteStore RPCs (default: 3)
EVERNOTE_RATE_LIMIT_AUTO_RETRY_SECONDS=15 # Auto-retry a rate-limited call once if the wait is <= this many seconds; 0 = off
EVERNOTE_MAX_RESPONSE_CHARS=60000 # Total note-body chars per multi-note response; bodies past this are dropped with truncated:true
# Note body cache (optional)
EVERNOTE_NOTE_CACHE_SIZE=200 # Max notes held in the USN-keyed body cache; 0 disables
EVERNOTE_NOTE_CACHE_SYNC_TTL_MS=30000 # How long a getSyncState result is trusted before re-checking for external editsOn the hourly rate limit, tool errors return JSON with error: "rate_limited" and retryAfterSeconds (Evernote's exact backoff window). Bounding concurrency smooths bursts but cannot restore quota — the quota is a per-token hourly call count, so the durable fixes are fewer calls and honoring the backoff.
Re-reading the same notes is served from an in-memory, USN-keyed body cache instead of re-spending getNote calls — the direct fix for the hourly limit tripping on repeat corpus reads. Notes you edit through this server are evicted immediately; edits made elsewhere are picked up within EVERNOTE_NOTE_CACHE_SYNC_TTL_MS via a sync-state probe. Extracted OCR / attachment text is always re-read live, never cached.
<details> <summary><b>Claude Code Configuration</b></summary>
#### Quick Setup (Using NPX)
claude mcp add evernote "npx -y -p @verygoodplugins/mcp-evernote -c mcp-evernote" \
--env EVERNOTE_CONSUMER_KEY=your-key \
--env EVERNOTE_CONSUMER_SECRET=your-secret#### OAuth Authentication
/mcpNote: Claude Code handles OAuth automatically - no manual token management needed!
</details>
<details> <summary><b>Claude Desktop Configuration</b></summary>
#### Step 1: Authenticate
Using NPX (no installation required):
npx -y -p @verygoodplugins/mcp-evernote mcp-evernote-authThe auth script will:
.evernote-token.jsonEVERNOTE_ACCESS_TOKEN insteadOr if installed globally:
mcp-evernote-auth#### Step 2: Add to Configuration
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"evernote": {
"command": "npx",
"args": ["-y", "-p", "@verygoodplugins/mcp-evernote", "-c", "mcp-evernote"],
"env": {
"EVERNOTE_CONSUMER_KEY": "your-consumer-key",
"EVERNOTE_CONSUMER_SECRET": "your-consumer-secret",
"EVERNOTE_ACCESS_TOKEN": "your-access-token",
"EVERNOTE_ENVIRONMENT": "production"
}
}
}
}Or if installed globally:
{
"mcpServers": {
"evernote": {
"command": "mcp-evernote",
"env": {
"EVERNOTE_CONSUMER_KEY": "your-consumer-key",
"EVERNOTE_CONSUMER_SECRET": "your-consumer-secret"
}
}
}
}</details>
Since Evernote stopped issuing developer API keys to new applicants, new users can authenticate using the clipper-sso browser cookie from the Evernote web UI. This cookie carries the same format as a developer-issued access token and works directly as EVERNOTE_ACCESS_TOKEN — no Consumer Key or Consumer Secret required.
Security warning: Treat this value like a password. Anyone with it can access your Evernote account. Never commit it to git, paste it into chat logs, or share it publicly.
Credit: Discovered by community member @tdrayson. (Issue #49)
www.evernote.com S=s101:U=XXX:XXXXX:C=XXXX:P=XXX:A=en-chrome-clipper-xauth-new:V=2:H=XXXXXClaude Code:
claude mcp add evernote "npx -y -p @verygoodplugins/mcp-evernote -c mcp-evernote" \
--env EVERNOTE_ACCESS_TOKEN="S=s101:U=XXX:..."Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%\Claude\claude_desktop_config.json on Windows):
{
"mcpServers": {
"evernote": {
"command": "npx",
"args": ["-y", "-p", "@verygoodplugins/mcp-evernote", "-c", "mcp-evernote"],
"env": {
"EVERNOTE_ACCESS_TOKEN": "S=s101:U=XXX:..."
}
}
}
}Note: EVERNOTE_NOTESTORE_URL is not required when using the cookie token — the server fetches it automatically at startup.clipper-sso token typically expires after roughly one year, or when you explicitly log out of Evernote in your browser. When it expires, log back in to www.evernote.com, re-extract the cookie, and update EVERNOTE_ACCESS_TOKEN.Recommended for new users: Cookie-Based Authentication (No API Key Needed).
Claude Code handles OAuth automatically via the /mcp command. Tokens are managed by Claude Code.
Run npx -y -p @verygoodplugins/mcp-evernote mcp-evernote-auth to authenticate via browser. The script saves .evernote-token.json for compatibility and also prints a token you can set as EVERNOTE_ACCESS_TOKEN.
EVERNOTE_ACCESS_TOKEN=your-token
EVERNOTE_NOTESTORE_URL=your-notestore-url
EVERNOTE_ALLOWED_FILE_ROOTS=/Users/you/Documents:/Users/you/Projects{
"env": {
"EVERNOTE_ACCESS_TOKEN": "your-access-token",
"EVERNOTE_NOTESTORE_URL": "your-notestore-url"
}
}The server exposes 15 tools (consolidated from 27). Retired tool names still work as deprecated aliases and can be re-listed with EVERNOTE_LEGACY_TOOLS=true — see MIGRATION.md for the full old→new mapping. Highlights: get_resource({guid, as}) projects an attachment (text/binary/recognition/metadata); list_notebooks/list_tags return one entity when passed a name/guid; update_note takes replacements[] for patch-style edits; and the polling and connection tools dispatch on an action.
This server automatically converts between Markdown and Evernote's ENML format:
<en-note>.- [ ] map to Evernote checkboxes <en-todo/>.- [x] map to <en-todo checked="true"/>. or file://...) are uploaded as Evernote resources automatically.evernote-resource:<hash> in Markdown.http(s) images remain links (download locally if you want them embedded). and other files become [file](evernote-resource:<hash>) so you can round-trip them safely.Limitations:
evernote-resource:<hash> references in Markdown if you want existing attachments to survive edits.#### evernote_create_note Create a new note in Evernote.
Parameters:
title (required): Note titlecontent (required): Note content (plain text or markdown)notebookName (optional): Target notebook nametags (optional): Array of tag namesExample:
Create a note titled "Meeting Notes" with content "Discussed Q4 planning" in notebook "Work" with tags ["meetings", "planning"]#### evernote_search_notes Search for notes using Evernote's search syntax. Returns note metadata plus totalNotes; page with offset/nextOffset.
Parameters:
query (required): Search query (use "*" to match all notes)notebookName (optional): Limit to specific notebookmaxResults (optional): Results per page (default: 20, max: 100; capped at 25 when includeContent is true)offset (optional): Result offset for paging (default: 0)includeContent (optional): Include each note's full body in content, one API call per note (default: false)format (optional): Body projection when includeContent is true — markdown (default), text, or enmlincludePreview (optional): Include a ~300-char plain-text preview per note (ignored when includeContent is true)Export a whole notebook as text without a dedicated tool: query: "*", set notebookName + includeContent, and page with offset until hasMore is false.
Example:
Search for notes containing "project roadmap" in the "Work" notebook#### evernote_get_note Retrieve one note (full detail) or a batch of up to 25 (body-focused).
Parameters: provide exactly one of guid or guids.
guid: single note GUID — full detail, including PDF/image-OCR attachment textguids: array of up to 25 GUIDs — metadata + content only (no attachment text; use a single guid for that). Returns { notes, failed?, aborted? }; on a mid-batch rate limit it stops with partial results plus the guids left to resume.format (optional): body projection — markdown (default), text, or enmlincludeContent (optional): include note content (default: true)includeAttachmentText (optional, single-note only): extract PDF/OCR attachment text (default: true)Returned Markdown represents embedded resources with evernote-resource:<hash> URLs. Leave those references intact so attachments stay linked when you edit the note.#### evernote_update_note Update an existing note. Two mutually exclusive modes:
Full-update mode parameters:
guid (required): Note GUIDtitle (optional): New titlecontent (optional): New content (Markdown supported)notebookName (optional): Move the note to this notebooktags (optional): New tags (replaces existing)Patch mode parameter (replaces the old evernote_patch_note):
replacements (optional): Array of {find, replace, replaceAll?} find-and-replaceedits applied to the note body, preserving title, tags, notebook, and attachments. Cannot be combined with the full-update fields above.
#### evernote_delete_note Delete a note.
Parameters:
guid (required): Note GUID#### evernote_list_notebooks List all notebooks in your account, or get one notebook's full detail by passing its name or guid (absorbs the old evernote_get_notebook).
#### evernote_create_notebook Create a new notebook.
Parameters:
name (required): Notebook namestack (optional): Stack name for organization#### evernote_update_notebook Rename a notebook or move it between stacks.
Parameters:
guid (required): Notebook GUIDname (optional): New notebook namestack (optional): Stack name — pass an empty string to remove it from its stack#### evernote_list_tags List all tags in your account, or get one tag's full detail by passing its name or guid (absorbs the old evernote_get_tag).
#### evernote_create_tag Create a new tag.
Parameters:
name (required): Tag nameparentTagName (optional): Parent tag for hierarchy#### evernote_update_tag Rename a tag or re-parent it.
Parameters:
guid (required): Tag GUIDname (optional): New tag nameparentTagName (optional): Parent tag name — pass an empty string to remove the parent#### evernote_get_resource Read one attachment, projected through one of four views.
⚠️ Breaking change in 2.0.0. This tool used to return base64 binary data by default. It now returns extracted text by default. Pass as: "binary" to get the old behavior.Parameters:
guid (required): Resource GUID (from a note's resources[], via evernote_get_note)as (optional, default "text"): How to project the attachment"text" — extracted text. PDFs go through the text layer, falling back toEvernote's OCR data for scanned documents; images use OCR.
"binary" — base64-encoded file body."recognition" — raw Evernote OCR recognition data."metadata" — filename, MIME type, size, hash, and hasRecognition.includeData (optional, deprecated): true maps to as:"binary", false to as:"metadata".There is no separate tool to list a note's attachments — evernote_get_note returns them in resources[].
Example:
Get the text of the PDF attached to that invoice note#### evernote_add_resource_to_note Attach a local file to an existing note.
Parameters:
noteGuid (required): Target note GUIDfilePath (required): Path to the local file. Must sit under an allowed root —see EVERNOTE_ALLOWED_FILE_ROOTS (defaults to your home directory and the current working directory).
filename (optional): Override the attachment's display name#### evernote_connection Manage the Evernote connection and account. Dispatches on action (replaces the old health_check, get_user_info, reconnect, revoke_auth):
action:"status" — health/diagnostic check (server + auth state). Passverbose:true for detailed diagnostics.
action:"user" — current user information and quota usage.action:"reconnect" — force reconnection (useful on "Not connected" errors).action:"revoke" — revoke the stored authentication token.Example:
Check Evernote connection health with verbose details#### evernote_polling Manage background polling for changes (detected changes are sent to the configured webhook). Dispatches on action (replaces the old start_polling, stop_polling, poll_now, polling_status):
action:"start" — begin polling on the configured interval.action:"stop" — halt polling.action:"poll" — check for changes immediately; returns detected changes.action:"status" — current polling configuration and state (running, interval,webhook URL, last poll time, error count).
Example:
Start polling for Evernote changesEvernote supports advanced search operators:
intitle:keyword - Search in titlesnotebook:name - Search in specific notebooktag:tagname - Search by tagcreated:20240101 - Search by creation dateupdated:day-1 - Recently updated notesresource:image/* - Notes with imagestodo:true - Notes with checkboxes-tag:archive - Exclude archived notesThis MCP server works seamlessly with the Claude Automation Hub for workflow automation:
// Example workflow tool
export default {
name: 'capture-idea',
description: 'Capture an idea to Evernote',
handler: async ({ idea, category }) => {
// The MCP server handles the Evernote integration
return {
tool: 'evernote_create_note',
args: {
title: `Idea: ${new Date().toISOString().split('T')[0]}`,
content: idea,
notebookName: 'Ideas',
tags: [category, 'automated']
}
};
}
};To enable synchronization with MCP memory service:
MCP_MEMORY_SERVICE_URL=http://localhost:8765Sync my "Important Concepts" notebook to memory for long-term retentionThe server includes automatic recovery from connection issues:
If you see "Not connected" errors, the server will usually recover automatically. You can also:
Reconnect to Evernote Check Evernote connection health with verbose details/mcp → Evernote → Authenticatenpx -p @verygoodplugins/mcp-evernote mcp-evernote-authFor detailed information about connection issues and recovery, see CONNECTION_TROUBLESHOOTING.md.
#### "Authentication required" error in Claude Desktop This means you haven't authenticated yet. Run the authentication script:
npx -p @verygoodplugins/mcp-evernote mcp-evernote-authOr if installed globally:
mcp-evernote-auth#### OAuth callback fails If the OAuth callback doesn't work:
OAUTH_CALLBACK_PORT in .env)#### Token expired If your token expires, the server will now detect this automatically and prompt you to re-authenticate:
/mcp command to re-authenticatenpx -p @verygoodplugins/mcp-evernote mcp-evernote-authOr use the reconnect tool to force immediate retry:
Reconnect to EvernoteThe server now handles most connection errors automatically:
If issues persist:
Evernote API has rate limits. If you encounter limits:
npm install
npm run buildnpm run devnpm testnpm run lint
npm run formatEVERNOTE_ACCESS_TOKEN, then Claude Code OAuth env, then .evernote-token.jsonEVERNOTE_ALLOWED_FILE_ROOTS; by default this is your home directory and the current working directoryContributions are welcome! Please:
mainGPL-3.0 - See LICENSE file for details.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.