Back to the catalog

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

[![Version](https://img.shields.io/npm/v/@verygoodplugins/mcp-evernote)](https://www.npmjs.com/package/@verygoodplugins/mcp-evernote)
[![License](https://img.shields.io/npm/l/@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 (`![alt](./path.png)` 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 `![alt](evernote-resource:<hash>)` 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

More