MCP Evernote
Evernote note management with OAuth and ENML conversion
Open source Open in the app JSON README (API)
About
Evernote note management with OAuth and ENML conversion
Details
- Kind
- MCP servers
- Topic
- Security & identity
- Publisher
- verygoodplugins
- Origin
- official
- Category
- ferramentas
- Transport
- local
- Version
- 1.2.3
- Stars
- 32
- Forks
- 11
- Open pull requests
- 2
- Last push
- 2026-09-03T18:15:01Z
- Repository state
- ativo
- Language
- TypeScript
- License
- NOASSERTION
- Added
- 2026-08-29 04:01:38
- Updated
- 2026-08-29 04:01:38
- Origin id
io.github.verygoodplugins/mcp-evernote
README
# MCP Evernote Server
[](https://www.npmjs.com/package/@verygoodplugins/mcp-evernote)
[](LICENSE)
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.
## ⚠️ No API Key? Use Browser Cookie Auth
> **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](#cookie-based-authentication-no-api-key-needed) instead — no API key required.
## Installation Requirements
### Node.js
**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](MIGRATION.md).
### For Claude Desktop Users:
- **OAuth Authentication Required**: Yes, run the auth command once (prompts for API keys)
- **Repository Download**: No, you can use npx directly from npm
- **API Credentials**: The auth script will prompt you for your Evernote API keys
- **Simple Setup**: Just one command to authenticate and configure
### For Claude Code Users:
- **OAuth Authentication**: Handled automatically via `/mcp` command
- **Repository Download**: Not required
- **Setup**: Single command installation
## Current Status
### ✅ Working Features
- 🔐 **OAuth Authentication** - Interactive setup for Claude Desktop, automatic for Claude Code
- 📝 **Note Operations**
- Create notes with plain text or markdown content
- Read and retrieve note contents
- Update existing notes
- Delete notes
- Automatic Markdown ↔ ENML conversion (GFM + local attachments)
- 📚 **Notebook Management**
- List all notebooks
- Create new notebooks
- Organize with stacks
- 🏷️ **Tag System**
- List all tags
- Create new tags
- Hierarchical tag support
- 🔍 **Advanced Search** - Full Evernote search syntax support
- 👤 **User Info** - Get account details and quota usage
- 🤖 **Smart Setup** - Interactive credential prompts and environment detection
## Quick Start
### Installation Methods
#### Option 1: Using NPX (No Installation Required)
The simplest way - no need to install anything globally:
```bash
# 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"
```
## Change Notifications
### Polling for Changes
The server can poll Evernote for changes and send webhook notifications when notes are created, updated, or deleted.
#### Configuration
```env
# 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:
```json
{
"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 manually
- `polling({action:"stop"})` - Stop polling
- `polling({action:"poll"})` - Check for changes immediately
- `polling({action:"status"})` - Get polling configuration and status
### Evernote Webhooks (Real-time)
For real-time notifications, Evernote supports webhooks but requires manual registration:
1. Email `devsupport@evernote.com` with:
- Your Consumer Key
- Webhook URL endpoint
- Any filters (optional)
2. They'll configure your webhook to receive HTTP GET requests on note create/update events.
---
#### Option 2: Global Installation
Install once, use anywhere:
```bash
# 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:
```bash
# Clone and install
git clone https://github.com/verygoodplugins/mcp-evernote.git
cd mcp-evernote
npm install
# Run setup wizard
npm run setup
```
## Configuration
### 1. Get Evernote API Credentials
> **Note:** 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](#cookie-based-authentication-no-api-key-needed) instead.
1. Visit [Evernote Developers](https://dev.evernote.com/)
2. Create a new application
3. Copy your Consumer Key and Consumer Secret
### 2. Authentication Options
#### Interactive Setup (Recommended)
The auth script will prompt you for credentials if not found:
```bash
# 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:
```env
# 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 edits
```
On 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.
### 3. Configure Your Client
<details>
<summary><b>Claude Code Configuration</b></summary>
#### Quick Setup (Using NPX)
```bash
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
1. In Claude Code, type `/mcp`
2. Select "Evernote"
3. Choose "Authenticate"
4. Follow the browser OAuth flow
5. Tokens are stored and refreshed automatically by Claude Code
**Note:** 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):
```bash
npx -y -p @verygoodplugins/mcp-evernote mcp-evernote-auth
```
The auth script will:
1. Prompt for your API credentials (if not in environment)
2. Open your browser for OAuth authentication
3. Save a compatible token file to `.evernote-token.json`
4. Display the access token so you can use `EVERNOTE_ACCESS_TOKEN` instead
Or if installed globally:
```bash
mcp-evernote-auth
```
#### Step 2: Add to Configuration
**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
```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:
```json
{
"mcpServers": {
"evernote": {
"command": "mcp-evernote",
"env": {
"EVERNOTE_CONSUMER_KEY": "your-consumer-key",
"EVERNOTE_CONSUMER_SECRET": "your-consumer-secret"
}
}
}
}
```
</details>
## Cookie-Based Authentication (No API Key Needed)
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](https://github.com/verygoodplugins/mcp-evernote/issues/49))
### Step 1: Extract the Cookie
1. Log in to [www.evernote.com](https://www.evernote.com) in your browser
2. Open DevTools: **F12** (Windows/Linux) or **Cmd+Option+I** (Mac)
3. Navigate to the **Application** tab → **Cookies** → `www.evernote.com`
4. Find the cookie named **`clipper-sso`**
5. Copy its **Value** — it looks like:
```
S=s101:U=XXX:XXXXX:C=XXXX:P=XXX:A=en-chrome-clipper-xauth-new:V=2:H=XXXXX
```
### Step 2: Configure Your Client
**Claude Code:**
```bash
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):
```json
{
"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.
### Caveats
- **Token expiry**: The `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](https://www.evernote.com), re-extract the cookie, and update `EVERNOTE_ACCESS_TOKEN`.
- **Browser session**: The cookie is tied to your browser login session. Logging out of the Evernote web app will invalidate the token.
- **Production only**: This uses your live Evernote account. There is no sandbox equivalent for this method.
## Authentication Methods
**Recommended for new users:** [Cookie-Based Authentication (No API Key Needed)](#cookie-based-authentication-no-api-key-needed).
### 1. Claude Code (Automatic)
Claude Code handles OAuth automatically via the `/mcp` command. Tokens are managed by Claude Code.
### 2. Claude Desktop (Manual)
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`.
### 3. Environment Variables (CI/CD)
```env
EVERNOTE_ACCESS_TOKEN=your-token
EVERNOTE_NOTESTORE_URL=your-notestore-url
EVERNOTE_ALLOWED_FILE_ROOTS=/Users/you/Documents:/Users/you/Projects
```
### 4. Direct Token (Advanced)
```json
{
"env": {
"EVERNOTE_ACCESS_TOKEN": "your-access-token",
"EVERNOTE_NOTESTORE_URL": "your-notestore-url"
}
}
```
## Available Tools
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](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`.
## Markdown Support
This server automatically converts between Markdown and Evernote's ENML format:
- Create/update: Markdown input is rendered to ENML-safe HTML inside `<en-note>`.
- GFM task lists `- [ ]` map to Evernote checkboxes `<en-todo/>`.
- Checked tasks `- [x]` map to `<en-todo checked="true"/>`.
- - Local Markdown images/files (`` or `file://...`) are uploaded as Evernote resources automatically.
- - Existing attachments are preserved by referencing `evernote-resource:<hash>` in Markdown.
- - Remote `http(s)` images remain links (download locally if you want them embedded).
- - Common Markdown elements (headings, lists, code blocks, tables, emphasis, links) are preserved.
- Retrieve: ENML content is converted back to Markdown (GFM), including task lists and attachments.
- Embedded images become `` and other files become `[file](evernote-resource:<hash>)` so you can round-trip them safely.
Limitations:
- Remote URLs are not fetched automatically; save them locally and reference the file to embed.
- Keep the `evernote-resource:<hash>` references in Markdown if you want existing attachments to survive edits.
- Some exotic HTML not supported by ENML will be sanitized/removed.
### Note Operations
#### `evernote_create_note`
Create a new note in Evernote.
**Parameters:**
- `title` (required): Note title
- `content` (required): Note content (plain text or markdown)
- `notebookName` (optional): Target notebook name
- `tags` (optional): Array of tag names
**Example:**
```
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 notebook
- `maxResults` (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 `enml`
- `includePreview` (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 text
- `guids`: 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 `enml`
- `includeContent` (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 GUID
- `title` (optional): New title
- `content` (optional): New content (Markdown supported)
- `notebookName` (optional): Move the note to this notebook
- `tags` (optional): New tags (replaces existing)
**Patch mode parameter** (replaces the old `evernote_patch_note`):
- `replacements` (optional): Array of `{find, replace, replaceAll?}` find-and-replace
edits 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
### Notebook Operations
#### `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 name
- `stack` (optional): Stack name for organization
#### `evernote_update_notebook`
Rename a notebook or move it between stacks.
**Parameters:**
- `guid` (required): Notebook GUID
- `name` (optional): New notebook name
- `stack` (optional): Stack name — pass an empty string to remove it from its stack
### Tag Operations
#### `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 name
- `parentTagName` (optional): Parent tag for hierarchy
#### `evernote_update_tag`
Rename a tag or re-parent it.
**Parameters:**
- `guid` (required): Tag GUID
- `name` (optional): New tag name
- `parentTagName` (optional): Parent tag name — pass an empty string to remove the parent
### Attachments & Resources
#### `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 to
Evernote'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 GUID
- `filePath` (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
### Connection & Account
#### `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). Pass
`verbose: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
```
### Polling Operations
#### `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 changes
```
## Search Syntax
Evernote supports advanced search operators:
- `intitle:keyword` - Search in titles
- `notebook:name` - Search in specific notebook
- `tag:tagname` - Search by tag
- `created:20240101` - Search by creation date
- `updated:day-1` - Recently updated notes
- `resource:image/*` - Notes with images
- `todo:true` - Notes with checkboxes
- `-tag:archive` - Exclude archived notes
## Integration with Claude Automation Hub
This MCP server works seamlessly with the Claude Automation Hub for workflow automation:
```javascript
// 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']
}
};
}
};
```
## Memory Service Integration
To enable synchronization with MCP memory service:
1. Set the memory service URL in your environment:
```env
MCP_MEMORY_SERVICE_URL=http://localhost:8765
```
2. Use the sync tools to persist important notes to memory:
```
Sync my "Important Concepts" notebook to memory for long-term retention
```
## Connection Resilience
The server includes automatic recovery from connection issues:
### Automatic Features
- **Auto-retry**: Failed connections automatically retry after 30 seconds
- **Token validation**: Expired tokens are detected proactively
- **Graceful degradation**: Server stays alive during failures
- **Clear error messages**: Actionable feedback on connection issues
### "Not Connected" Errors
If you see "Not connected" errors, the server will usually recover automatically. You can also:
1. **Try the reconnect tool** (fastest):
```
Reconnect to Evernote
```
2. **Check server health**:
```
Check Evernote connection health with verbose details
```
3. **Re-authenticate if needed**:
- Claude Code: `/mcp` → Evernote → Authenticate
- Claude Desktop: `npx -p @verygoodplugins/mcp-evernote mcp-evernote-auth`
For detailed information about connection issues and recovery, see [CONNECTION_TROUBLESHOOTING.md](CONNECTION_TROUBLESHOOTING.md).
## Troubleshooting
### Authentication Issues
#### "Authentication required" error in Claude Desktop
This means you haven't authenticated yet. Run the authentication script:
```bash
npx -p @verygoodplugins/mcp-evernote mcp-evernote-auth
```
Or if installed globally:
```bash
mcp-evernote-auth
```
#### OAuth callback fails
If the OAuth callback doesn't work:
1. Make sure port 3000 is available (or set `OAUTH_CALLBACK_PORT` in `.env`)
2. Check your firewall settings
3. Try using a different browser
#### Token expired
If your token expires, the server will now detect this automatically and prompt you to re-authenticate:
1. In Claude Code: Use `/mcp` command to re-authenticate
2. In Claude Desktop: Run `npx -p @verygoodplugins/mcp-evernote mcp-evernote-auth`
Or use the reconnect tool to force immediate retry:
```
Reconnect to Evernote
```
### Connection Errors
The server now handles most connection errors automatically:
- **Transient failures**: Auto-retry after 30 seconds
- **Token expiry**: Clear error message with re-auth instructions
- **Network issues**: Server stays alive and retries
If issues persist:
- Check your API credentials are correct
- Verify you're using the right environment (sandbox vs production)
- See [CONNECTION_TROUBLESHOOTING.md](CONNECTION_TROUBLESHOOTING.md) for detailed guidance
### Rate Limiting
Evernote API has rate limits. If you encounter limits:
- Reduce the frequency of requests
- Use batch operations where possible
- Implement caching for frequently accessed data
## Development
### Building from Source
```bash
npm install
npm run build
```
### Running in Development Mode
```bash
npm run dev
```
### Testing
```bash
npm test
```
### Linting
```bash
npm run lint
npm run format
```
## Security
- Token lookup prefers `EVERNOTE_ACCESS_TOKEN`, then Claude Code OAuth env, then `.evernote-token.json`
- Never commit token files to version control
- Use environment variables for sensitive configuration
- Local file attachments are restricted to `EVERNOTE_ALLOWED_FILE_ROOTS`; by default this is your home directory and the current working directory
- Tokens expire after one year by default
## Contributing
Contributions are welcome! Please:
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests if applicable
5. Submit a pull request against `main`
## License
GPL-3.0 - See [LICENSE](LICENSE) file for details.
## Support
- **Issues**: [GitHub Issues](https://github.com/verygoodplugins/mcp-evernote/issues)
## Acknowledgments
- Built with [Model Context Protocol SDK](https://github.com/anthropics/model-context-protocol)
- Powered by [Evernote API](https://dev.evernote.com/)
- Part of the [Very Good Plugins](https://verygoodplugins.com?utm_source=github) ecosystem
## Roadmap
### Near Term
- [ ] **Tag Management** - Add/remove tags from existing notes
- [x] **ENML ↔ Markdown Converter** - Bidirectional conversion between Evernote's ENML format and Markdown
- [ ] **Real-time Sync Hooks** - Detect changes made via Evernote desktop/mobile apps
- [ ] **Database Monitoring** - Watch Evernote DB service for live updates
### Future Enhancements
- [ ] Web clipper functionality
- [ ] Rich text editing support
- [ ] File attachment handling
- [ ] Shared notebook support
- [ ] Business account features
- [ ] Template system
- [ ] Bulk operations
- [ ] Export/Import tools
- [ ] Advanced filtering options
- [ ] Reminder management