Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Readwise MCP Serverfetch my daily review"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Readwise MCP Server
Minimal Python MCP server for Readwise integration - token-efficient, single-file implementation using FastMCP.
Features
Token-efficient: 8 essential tools (vs 13+ in Node.js version)
Single-file architecture: ~350 lines of code
Proven logic: Reuses battle-tested deduplication and pagination from backfill script
State compatibility: Preserves existing state file format
Smart optimization: Uses synced ranges to skip unnecessary API calls
Installation
1. Clone repository
2. Create virtual environment
3. Install dependencies
4. Configure environment variables
Set these in your .mcp.json file:
READWISE_TOKEN: Your Readwise API tokenVAULT_PATH: Path to your PARA vault (e.g.,/path/to/your/vault)
Configuration
Update .mcp.json
Add or update the readwise entry in your vault's .mcp.json:
Replace the paths with your actual installation locations.
Tools Reference
1. readwise_daily_review()
Fetch today's highlights and save to Daily Reviews directory.
Parameters: None
Returns:
Example:
2. readwise_import_recent(category="tweet", limit=20)
Import recent documents since last import with automatic deduplication.
Parameters:
category(string, optional): Document category (default: "tweet")limit(int, optional): Maximum documents to fetch (default: 20)
Returns:
Example:
3. readwise_backfill(target_date, category="tweet")
Paginate backwards to target date with synced range optimization.
Parameters:
target_date(string, required): Target date in YYYY-MM-DD formatcategory(string, optional): Document category (default: "tweet")
Returns:
Example:
4. readwise_book_highlights(title=None, book_id=None)
Get highlights for a specific book.
Parameters:
title(string, optional): Book title to search forbook_id(string, optional): Specific book ID
Returns:
Example:
5. readwise_search_highlights(query, limit=50)
Search highlights by text query.
Parameters:
query(string, required): Search querylimit(int, optional): Maximum results (default: 50)
Returns:
Example:
6. readwise_state_info()
Show current import state and synced ranges.
Parameters: None
Returns:
Example:
7. readwise_init_ranges()
Scan filesystem to build synced_ranges from existing documents.
Parameters: None
Returns:
Example:
8. readwise_reset_state(clear_ranges=False)
Clear state file (optionally preserve synced_ranges).
Parameters:
clear_ranges(bool, optional): Whether to clear synced ranges (default: False)
Returns:
Example:
State File Format
The server maintains state at .claude/state/readwise-import.json:
Testing
Run the test suite:
Test Categories
Unit Tests:
State file reading/writing
Synced range optimization logic
Filename sanitization
ID extraction from URLs
Document scanning for deduplication
Integration Tests:
API calls with mocked responses
Markdown formatting
Document saving with collision handling
Troubleshooting
Connection Issues
Check MCP connection:
/mcpShould show "Connected to readwise"
Verify environment variables are set correctly in
.mcp.jsonCheck logs in stderr output
State Issues
If state file appears corrupted:
View current state:
Call readwise_state_info()Reset state (preserve ranges):
Call readwise_reset_state()Rebuild ranges from filesystem:
Call readwise_init_ranges()
Deduplication Issues
If documents are being imported multiple times:
Rebuild synced ranges:
Call readwise_init_ranges()Check filesystem for duplicate filenames manually
Verify readwise_url frontmatter is present in existing documents
Architecture
Single-File Design
The server is intentionally kept to a single file (~350 lines) for:
Simplicity and maintainability
Easy deployment and updates
Minimal dependencies
Clear code organization
Reused Logic
Key functions reused from .claude/scripts/readwise-backfill.py:
load_state()/write_state()- State managementoptimize_backfill()- Synced range optimizationscan_existing_documents()- Filesystem deduplicationsanitize_filename()- Safe filename generationextract_id_from_url()- ID extraction
Token Efficiency
Optimizations for reduced token usage:
8 tools vs 13+ in Node.js version (38% reduction)
Combined operations (fetch + dedupe + save in one call)
Smart defaults minimize required parameters
Tool descriptions limited to 20-30 words
Returns structured summaries, not full markdown dumps
Estimated token overhead reduction: ~60%
Comparison with Node.js Version
Feature | Python MCP | Node.js MCP |
Lines of code | ~350 | ~6,749 |
Tool count | 8 | 13+ |
Dependencies | 4 | 10+ |
State compatibility | ✓ | ✓ |
Token efficiency | High | Medium |
Maintenance | Simple | Complex |
Development
Running locally for development
Adding new tools
Add tool function using
@mcp.tool()decoratorFollow existing patterns for error handling and logging
Return structured dict with
statusfieldAdd tests to
test_server.pyUpdate README.md with tool documentation
License
MIT
Credits
Built with FastMCP by Anthropic
Based on proven logic from
.claude/scripts/readwise-backfill.pyDesigned for token efficiency and simplicity