Mendeley Mcp — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Mendeley Mcp (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.
<p align="center"> <img src="https://raw.githubusercontent.com/pallaprolus/mendeley-mcp/main/mendeley-mcp.png" alt="Mendeley MCP Logo" width="200"> </p>
An MCP (Model Context Protocol) server that connects your Mendeley reference library to LLM applications like Claude Desktop, Cursor, and other MCP-compatible clients.
<a href="https://glama.ai/mcp/servers/@pallaprolus/mendeley-mcp"> <img width="380" height="200" src="https://glama.ai/mcp/servers/@pallaprolus/mendeley-mcp/badge" alt="Mendeley MCP server on Glama" /> </a>
http://localhost:8585/callbackpip install mendeley-mcpuv tool install mendeley-mcpIntel Macs. Thecryptographylibrary, pulled in by the MCP SDK, stopped publishing macOS x86_64 wheels at version 49. On Intel Macs this package pinscryptographybelow 49 so installation works without a Rust toolchain. That pinned version no longer receives upstream security fixes; Apple Silicon, Linux, and Windows are unaffected and get the latest release.
docker run -it \
-e MENDELEY_CLIENT_ID="your-client-id" \
-e MENDELEY_CLIENT_SECRET="your-client-secret" \
-e MENDELEY_REFRESH_TOKEN="your-refresh-token" \
ghcr.io/pallaprolus/mendeley-mcpOr build locally:
git clone https://github.com/pallaprolus/mendeley-mcp.git
cd mendeley-mcp
docker build -t mendeley-mcp .git clone https://github.com/pallaprolus/mendeley-mcp.git
cd mendeley-mcp
pip install -e .Run the authentication wizard:
mendeley-auth loginThis will:
Edit your Claude Desktop config file:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json Linux: ~/.config/Claude/claude_desktop_config.json Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"mendeley": {
"command": "mendeley-mcp"
}
}
}If installed with uv:
{
"mcpServers": {
"mendeley": {
"command": "uvx",
"args": ["mendeley-mcp"]
}
}
}The Mendeley tools should now be available in Claude.
| Tool | Description |
|---|---|
mendeley_search_library | Search documents in your library |
mendeley_get_document | Get full details of a specific document |
mendeley_list_documents | List documents, optionally filtered by folder |
mendeley_list_folders | List all folders/collections |
mendeley_search_catalog | Search Mendeley's global paper database |
mendeley_get_by_doi | Look up a paper by DOI |
mendeley_add_document | Add a new document to your library |
mendeley_update_document | Update bibliographic fields, tags, or keywords on an existing document |
mendeley_delete_document | Permanently delete a document from your library |
mendeley_create_folder | Create a folder in your library, optionally under a parent folder or group |
mendeley_rename_folder | Rename an existing folder |
mendeley_delete_folder | Delete an existing folder |
mendeley_add_document_to_folder | Add an existing document to an existing folder |
mendeley_remove_document_from_folder | Remove a document from a folder without deleting it |
mendeley_get_annotations | Get your PDF highlights and notes on a document |
mendeley_export_bibtex | Export a document or folder as BibTeX |
mendeley_get_file_content | Download the first attached file for a library or catalog document |
mendeley_get_document_text | Extract the full text of a document's attached PDF so the model can read the paper |
Besides the tools above, the server exposes two MCP resources. Resources take no arguments; a client that supports them lists them alongside the server and lets you attach one to a conversation as context, the way you would attach a file.
| Resource | Contents |
|---|---|
mendeley://library/recent | The 10 most recently modified documents, in the same format as mendeley_list_documents |
mendeley://library/folders | Every folder in the library with its id, name, and parent_id |
mendeley_search_libraryUse this when the paper should already exist in the user's library.
has_pdflimit results (default 20), paging through Mendeley's results as neededmendeley_get_documentUse this after you already know the library document_id.
mendeley_list_documentsUse this to browse the library instead of searching by keyword.
folder_idlast_modified, created, or titlelimit documents (default 50), paging through the library as needed, so a large limit returns the whole librarymendeley_list_foldersUse this to understand the collection hierarchy before listing documents by folder.
parent_id to reconstruct nestingmendeley_search_catalogUse this when the reference is not in the user's library or when you want broader discovery.
catalog_id, summary metadata, and truncated abstract textmendeley_search_library does not find a matchmendeley_get_by_doiUse this when a DOI is known and you want a higher-confidence lookup than free-text search.
catalog_id plus richer catalog metadatamendeley_add_document or mendeley_get_file_contentmendeley_add_documentUse this to create a library entry from metadata you already have.
mendeley_update_documentUse this to fix or enrich an existing library entry.
tags or keywords list replaces the existing list; pass [] to clear it. To add a tag, read the current tags with mendeley_get_document and pass the combined list. Mendeley stores tags as a set and returns them sorted, not in the order sentmendeley_delete_documentUse this to permanently remove a document from the library.
mendeley_remove_document_from_folderUse this to take a document out of a folder while keeping it in the library.
mendeley_add_document_to_folder — together they let you move documents between foldersmendeley_get_annotationsUse this to see what the user highlighted or noted in a paper's PDF.
mendeley_export_bibtexUse this when the user needs citations in a real reference format.
document_id for one entry or folder_id for a whole collection.bib filemendeley_get_file_contentUse this to try downloading the first file Mendeley exposes for a library document or catalog hit.
document_id or a catalog_idMENDELEY_MCP_MAX_FILE_BYTES environment variable)mendeley_get_document_text instead.mendeley_get_document_textUse this when the user wants the model to read, summarize, or answer questions about a paper's contents.
document_id or a catalog_idtext field. Clients that expose only structured content receive the same text (see #11). Both representations use the same truncation limit; the response carries the text twice for compatibility.message on every path, so explanations for missing files, scanned PDFs, and errors remain visible to structured-only clients.MENDELEY_MCP_MAX_TEXT_CHARS environment variable)Once configured, you can ask Claude things like:
For direct tool calls in an MCP client or inspector, the folder-management tools accept inputs like:
Create a root folder:
{
"name": "Systematic Review 2026"
}Create a subfolder:
{
"name": "Screening",
"parent_id": "folder-123"
}Rename a folder:
{
"folder_id": "folder-123",
"name": "Included Studies"
}Delete a folder:
{
"folder_id": "folder-999"
}Add a document to a folder:
{
"folder_id": "folder-123",
"document_id": "doc-789"
}mendeley_get_document_text accepts optional page_start and page_end (1-based, inclusive). Omitted bounds select the first or last PDF page. Existing calls still return full text; structured results also include bounded pages entries with page_number, start_offset, end_offset, and truncated, without another copy of the text. Offsets are zero-based Python character positions in the returned text; the end offset is exclusive. They account for trimming and the two-newline page separators. A page fully omitted by the output cap has both offsets at the end of the returned text and is flagged as truncated when its span in the canonical text was non-empty, including whitespace. The overall text limit applies to both compatibility representations. Page numbers refer to PDF positions, not printed page labels. Blank selected pages can have no extractable text.
Migration from 0.7.0 to 0.8.0: pages[].text is removed. Obtain a page's returned text from the top-level text and its offsets:
page_text = result["text"][page["start_offset"]:page["end_offset"]]JavaScript/TypeScript string indices count UTF-16 units; these offsets count Unicode code points, including each non-BMP character as one position. Use:
const characters = Array.from(result.text); // Reuse for every page in this result.
const pageText = characters.slice(page.start_offset, page.end_offset).join("");mendeley_search_document_text(document_id, query, limit=10, context_chars=200) searches every PDF page for a literal, case-insensitive phrase, including pages beyond the reading output limit. It returns source metadata, page-numbered passages, character offsets, total_matches, and explicit truncation flags. limit accepts 1–100; context_chars accepts 0–2000. Matching uses extracted text as-is, so phrases split across PDF line breaks may not match. Returned passages always contain the complete match: context is reduced first, and a passage is omitted if the remaining budget cannot hold the phrase. Total match counts still include omitted passages. Match and passage offsets index the original extracted page text, while reading offsets index the returned text. Download and extraction errors retain source metadata in both tools. Neither tool performs OCR or semantic search. Empty selected pages may be blank; they do not establish that the whole PDF requires OCR. Error results include document_id, error_stage, file_available, and text_available; file_available: null means availability was not determined. Output limits require a positive text limit and a file limit of zero or greater; zero disables file embedding while preserving file metadata. Invalid configuration is rejected at startup. These limits do not bound PDF download size or parsing work.
Example: search for "evaluation metrics", then read the matching PDF pages.
mendeley_create_folder requires a non-empty name. You can optionally provide parent_id for nested creation or group_id for a group-scoped folder.mendeley_rename_folder requires non-empty folder_id and name.mendeley_delete_folder requires a non-empty folder_id.mendeley_add_document_to_folder requires non-empty folder_id and document_id.parent_id and group_id values are trimmed when provided and then forwarded upstream without additional local business rules.mendeley_get_file_content accepts either a library document ID or a catalog_id. Catalog entries often do not have downloadable files, so a no-file result is expected in many cases.
If you prefer not to use mendeley-auth login, you can configure credentials via environment variables:
# Required
export MENDELEY_CLIENT_ID="your-client-id"
export MENDELEY_CLIENT_SECRET="your-client-secret"
# One of the following (refresh token recommended - access tokens expire quickly)
export MENDELEY_REFRESH_TOKEN="your-refresh-token"
# OR
export MENDELEY_ACCESS_TOKEN="your-access-token"Optional tuning variables:
# Max size of a file embedded by mendeley_get_file_content (default 10 MB)
export MENDELEY_MCP_MAX_FILE_BYTES="10485760"
# Max characters of extracted text returned by mendeley_get_document_text (default 200000)
export MENDELEY_MCP_MAX_TEXT_CHARS="200000"Or in your MCP config:
{
"mcpServers": {
"mendeley": {
"command": "mendeley-mcp",
"env": {
"MENDELEY_CLIENT_ID": "your-client-id",
"MENDELEY_CLIENT_SECRET": "your-client-secret",
"MENDELEY_REFRESH_TOKEN": "your-refresh-token"
}
}
}
}# Check authentication status
mendeley-auth status
# Show environment variables for manual config
mendeley-auth show-env
# Remove saved credentials
mendeley-auth logoutWhen a saved login's access token expires, the server refreshes it and writes the new tokens back to the same place the login was stored: the system keyring, or the credentials file, which is replaced atomically with private permissions. The next server start therefore begins with a valid token instead of a refresh round trip.
Credentials supplied through environment variables are never written anywhere; those deployments manage token durability themselves. If saving fails, the running session keeps its refreshed tokens and logs a warning without credential details, and the next start may need mendeley-auth login again.
git clone https://github.com/pallaprolus/mendeley-mcp.git
cd mendeley-mcp
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"# Run tests
pytest
# Run with coverage
pytest --cov=mendeley_mcp
# Type checking
mypy src/mendeley_mcp
# Linting
ruff check src/# Install MCP inspector
npm install -g @modelcontextprotocol/inspector
# Run your server with inspector
npx @modelcontextprotocol/inspector mendeley-mcp┌─────────────────┐ ┌──────────────────┐ ┌───────────────────┐
│ Claude Desktop │────▶│ mendeley-mcp │────▶│ Mendeley API │
│ (MCP Client) │◀────│ (MCP Server) │◀────│ api.mendeley.com │
└─────────────────┘ └──────────────────┘ └───────────────────┘
│
▼
┌──────────────────┐
│ Local Keyring │
│ (credentials) │
└──────────────────┘Important: This server runs locally on your machine. Your credentials and data never pass through any third-party servers - all communication is directly between your computer and Mendeley's API.
Credential Storage: When keyring support is available, OAuth tokens and the client secret are stored in your system's native keyring (macOS Keychain, Windows Credential Locker, or Linux Secret Service), and only the client ID is saved in ~/.config/mendeley-mcp/credentials.json. Without keyring support, credentials are saved in that file with private permissions. Signed download URL queries are redacted from HTTPX request logs and omitted from download error messages.
Mendeley API rate limits are per-user. If you hit rate limits:
Run mendeley-auth login to authenticate.
Your access token has expired. The server refreshes it automatically using your refresh token and saves the new token to your keyring or credentials file. If this fails, run mendeley-auth login again.
Your app may have been deauthorized. Re-authenticate with mendeley-auth login.
Contributions are welcome! Please:
MIT License - see LICENSE file.
This project is not affiliated with, endorsed by, or sponsored by Mendeley or Elsevier. Mendeley is a trademark of Elsevier B.V.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.