In this blog post, we explore how to build a modular, agent-compatible MCP (Model Context Protocol) server that automates the discovery, storage, and retrieval of research papers from arXiv. By leveraging the FastMCP framework, we expose tool-like interfaces that can be invoked by agents, UIs, or even chat interfaces for smarter academic workflows.
What is an MCP Server?
An MCP (Model Context Protocol) Server is a lightweight, modular service that exposes tools or functions in a standard interface so they can be used by AI agents, workflows, or external systems. Built on the FastMCP framework, it allows developers to quickly register Python functions as callable tools over stdin, REST, or other transports — enabling LLM-driven automation, tool use, and orchestration.
What is FastMCP?
FastMCP is a lightweight Python framework that lets you wrap functions as tools inside an MCP-compatible agent server. Think of it as an easier way to define callable capabilities (e.g., “search papers”, “get status”) that can be used by AI agents, other tools, or event-driven workflows.
Project Goals
- Create a tool to search research papers from arXiv based on a topic
- Store paper metadata (title, authors, summary, etc.) locally per topic
- Create another tool to query the research paper information using arXiv ID
- Expose this functionality using FastMCP so it can be called by LLM agents or CLI tools
Github
https://github.com/juggarnautss/mcp_server_fastmcp_arxiv
Key Dependencies
pip install arxiv mcp
Directory Structure
mcp_server/
├── research_server.py # Main server file
└── research_papers/ # Stores metadata per topic
Tool 1 : Search and Store Papers (search_arxiv
)
This tool performs a search on arXiv for a given topic, processes the results, and stores them in a local JSON file under a directory named after the topic.
@mcp.tool()
def search_arxiv(topic: str, max_results: int = 5) -> List[str]:
"""
Search for research papers on arXiv based on a topic ans store the information
Args:
topic (str): topic to search for in arXiv.
max_results (int): Maximum number of results to return.
Returns:
List[dict]: A list of dictionaries containing paper information.
"""
client = arxiv.Client()
search_papers = arxiv.Search(
query=topic,
max_results=max_results,
sort_by=arxiv.SortCriterion.Relevance
)
research_papers = client.results(search_papers)
#Create a directory for the topic
path = os.path.join(RESEARCH_PAPER_DIR, topic.lower().replace(" ", "_"))
os.makedirs(path, exist_ok=True)
# Get the file path
file_path = os.path.join(path, "research_papers_info.json")
#Load the files
try:
with open(file_path, "r") as json_file:
papers_info = json.load(json_file)
except (FileNotFoundError, json.JSONDecodeError):
papers_info = {}
#Process each paper and add the paper information to the dictionary
papers_ids = []
for paper in research_papers:
papers_ids.append(paper.get_short_id())
paper_info = {
"title": paper.title,
"summary": paper.summary,
"authors": [author.name for author in paper.authors],
"summary": paper.summary,
"published": paper.published.isoformat(),
"pdf_url": paper.pdf_url
}
papers_info[paper.get_short_id()] = paper_info
# Save the updated information back to the file
with open(file_path, "w") as json_file:
json.dump(papers_info, json_file, indent=2)
print(f"Research papers information saved to {file_path}")
# Return the list of paper IDs
return papers_ids
The @mcp.tool() decorator is part of the FastMCP framework. It is used to register a Python function as a callable “tool” that can be exposed by the MCP server for use by external clients or agents (like an LLM).
Tool 2: Retrieve Paper Info by ID (get_paper_info
)
This tool searches across all locally stored topics and retrieves metadata of a paper using its arXiv ID (e.g., 2507.14912v1
).
@mcp.tool()
def get_paper_info(paper_id: str) -> str:
"""
Get information about a specific research paper by its ID accross all topic directories.
Args:
paper_id (str): The ID of the research paper to retrieve information for.
Returns:
JSON object: A JSON object containing the paper information.
"""
for object in os.listdir(RESEARCH_PAPER_DIR):
object_path = os.path.join(RESEARCH_PAPER_DIR, object)
if os.path.isdir(object_path):
file_path = os.path.join(object_path, "research_papers_info.json")
if os.path.isfile(file_path):
try:
with open(file_path, "r") as json_file:
papers_info = json.load(json_file)
if paper_id in papers_info:
return json.dumps(papers_info[paper_id], indent=4)
except (FileNotFoundError, json.JSONDecodeError) as e:
print(f"Error decoding JSON in {file_path}")
continue
return f"Paper with ID {paper_id} not found in any topic directory."
Run the MCP Server
if __name__ == "__main__":
mcp.run(transport="stdio")
We have using the transport protocol as “stdio” ie standard input-ouput as we are running the mcp server locally. The client(mcp inspector) will communicate with local mcp server over standard input-ouput
Incase you want to run the mcp server remotely, then transport protocol shall be “Streamable HTTP”.
For more details – https://modelcontextprotocol.io/specification/2025-06-18/basic/transports
Setting up your Environment to test the Server
- Clone the github repository
uv init
uv venv
- source .venv/bin/activate
- uv pip install -r requirments.txt
- Launch the MCP inspector (a sandbox environment to test the mcp server without the need of a mcp client)
npx @modelcontextprotocol/inspector uv run research_server.py
MCP server testing using MCP Inspector
Inspector landing page

List the tools

Run the tool – search_arxiv

Run the tool – get_paper_info

Conclusion
By combining the power of the arXiv API, FastMCP, and the modular structure of an MCP Server, we’ve can quickly build a lightweight yet extensible system to automate research discovery and paper management. With just a few lines of code, our tools can now be invoked by AI agents, UIs, or scripts — enabling smarter workflows for academics, developers, and research teams.
This is just tip of the iceberg. The MCP architecture opens the door to building tool-rich, agent-driven systems where each function is reusable, inspectable, and callable — much like a Swiss Army knife for AI-powered automation.
References
Author Profile

- AI | Amplifying Impact
- Talks about AI | GenAI | Machine Learning | Cloud | Kubernetes
Latest entries
AgenticAIAugust 12, 2025Pipeline Companion – an AWS Strands Agent for Data Pipeline Monitoring
AgenticAIAugust 7, 2025AWS Strand Agent – integration with Researcher MCP server
AgenticAIAugust 5, 2025Building an MCP Server Using FastMCP and arXiv
AgenticAIAugust 3, 2025Building a Resume Question-Answering System Using LlamaIndex, OpenAI, and LlamaParse