ResearchMCP
Enables LLMs to search arXiv, extract and analyze paper content, and build a personal semantically-searchable research library with saved papers and notes.
README
ResearchMCP
An agentic research assistant that lets an LLM autonomously search arXiv, extract and analyze paper content, and build a personal semantically-searchable research library — built as a custom MCP server paired with a LangGraph agent.
What it does
Ask it something like:
"Search for papers about neighborhood attention transformers, save the top result to my library, then find related papers I've already saved."
The agent autonomously decides which tools to call, in what order, chaining multiple steps together without being told the exact sequence.
An interactive CLI (agent/cli.py) lets you have a real multi-turn conversation with the agent — it remembers context within a session, and persists conversation history to SQLite so sessions survive restarts.
Architecture
User query
↓
LangGraph ReAct Agent (Gemini 2.5 Flash)
↓ (decides which tool to call, loops until done)
ResearchMCP Server (9 tools over MCP protocol)
↓
┌─────────────┬──────────────┬─────────────────┐
│ arXiv API │ PDF extract │ SQLite + FAISS │
│ (search) │ (pymupdf) │ (personal library)│
└─────────────┴──────────────┴─────────────────┘
↓
Synthesized answer, grounded in real tool results
The MCP server and the agent are fully decoupled — the server is a standalone, protocol-compliant MCP server that works with any MCP client (Claude Desktop, other agents), not just the LangGraph agent built here.
Memory
The agent has two layers of memory, both backed by SQLite (separate from the research library database):
- Short-term (in-session): the full conversation history is passed to the agent on every turn, so follow-up questions ("what was the title of the paper you just saved?") can be answered directly from context without a redundant tool call.
- Long-term (persistent): every message is saved to
data/conversations.db. Closing and reopening the CLI resumes the most recent session automatically, with full prior context intact.
The agent is prompted to distinguish between two different kinds of questions: recalling what was discussed in the conversation (answered from memory) versus querying the actual state of the saved paper library (answered by calling list_saved_papers) — these pull from different sources of truth, and the agent correctly picks the right one.
Error handling: all tools return structured errors ({"error": "...", "status": "failed"}) instead of raising exceptions — so a bad paper ID, empty query, or failed download surfaces as a clear message the agent can reason about, rather than crashing the tool call.
Tools
| Tool | What it does |
|---|---|
| search_arxiv | Search arXiv by keyword, returns titles/authors/abstracts |
| get_paper | Full metadata for one paper by arXiv ID |
| extract_content | Downloads a paper's PDF, extracts and cleans the text (strips references) |
| save_to_library | Saves a paper to a personal SQLite + FAISS-indexed library |
| search_library | Semantic search over your saved papers — finds conceptually related work, not just keyword matches |
| save_note | Save a research note, optionally linked to a paper |
| list_saved_papers | List everything in your library |
| summarize_paper | Fetches a paper's content, formatted for the calling LLM to summarize |
| compare_papers | Fetches multiple papers' content side by side, formatted for the calling LLM to compare |
Design note: summarize_paper and compare_papers intentionally do not call an LLM internally — they return raw, structured data for the client (the LLM asking the question) to reason over. This keeps the server's responsibility scoped to retrieval, not reasoning, which is the correct separation of concerns for MCP tools and keeps the server reusable across any client.
Tech stack
- MCP server: Python, official
mcpSDK (FastMCP) - Paper search:
arxivpackage (arXiv API wrapper) - PDF extraction:
pymupdf - Personal library: SQLite (metadata) + FAISS (semantic search) +
sentence-transformers(all-MiniLM-L6-v2embeddings) - Agent: LangGraph (
create_react_agent) +langchain-mcp-adapters+ Gemini 2.5 Flash - CLI:
richfor formatted terminal output, SQLite for persistent conversation memory
Setup
# Clone and enter the repo
git clone https://github.com/Adityay009/ResearchMcp
cd researchmcp
# Create and activate a virtual environment
python3 -m venv venv
source venv/bin/activate
# Install MCP server dependencies
pip install -r requirements.txt
# Install agent dependencies
pip install -r agent/requirements.txt
# Add your Gemini API key
echo "GOOGLE_API_KEY=your_key_here" > .env
Testing
22 automated tests across 4 files, covering the core logic layer (text cleaning, database operations, mocked API calls, and vector search):
pip install -r requirements.txt # includes pytest
python -m pytest -v
| File | What it covers |
|---|---|
tests/test_content_tools.py |
PDF text cleaning and reference-section stripping (pure logic, no I/O) |
tests/test_db.py |
SQLite operations, using isolated temp databases per test |
tests/test_arxiv_tools.py |
arXiv API wrapper, with the network call mocked |
tests/test_vector_store.py |
FAISS indexing and semantic search, including a regression test for a duplicate-entry bug found during manual testing |
Database and vector-store tests use pytest's tmp_path fixture with monkeypatch to redirect storage paths — tests never touch the real data/ directory.
Running the MCP server standalone (with the official Inspector)
PYTHONPATH=. mcp dev mcp_server/server.py
Opens a local web UI to test each of the 9 tools individually.
Running the interactive CLI (recommended)
python -m agent.cli
Commands available inside the CLI:
/new— start a fresh conversation session/sessions— list all past sessions with message counts/exit— quit
Tool calls are displayed live as the agent executes them, providing visibility into the agent's actions and research workflow.
Running a single scripted query
python agent/graph.py
Edit the test_query variable in agent/graph.py to try your own one-off queries.
Known limitations
- PDF text extraction is imperfect on figure-heavy papers — captions, author affiliations, and diagram labels can bleed into the extracted body text (a known limitation of plain-text PDF extraction, not something specific to this project)
- Reference-section stripping uses a simple regex match on "References"/"Bibliography" headers — doesn't catch every paper's formatting (e.g. "Works Cited")
compare_paperstruncates each paper's content to keep tool responses within a reasonable context size, so very long papers are compared on excerpts (intro + methodology) rather than full text- FAISS (
IndexFlatL2) does exact brute-force search — fine at personal-library scale (hundreds of papers), would need a different index type (e.g. HNSW) at much larger scale
Environment notes
Built and tested on macOS (Apple Silicon/M1). If mcp dev fails with spawn uv ENOENT, it's because the Inspector shells out to uv regardless of your project setup — install it with curl -LsSf https://astral.sh/uv/install.sh | sh and make sure ~/.local/bin is on your PATH.
If you hit a RESOURCE_EXHAUSTED / limit: 0 error from Gemini even on a fresh API key, try a different model (e.g. gemini-2.5-flash instead of gemini-2.0-flash) — free-tier quota allocation varies by model.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。