Updates for Prompt deep-paper-analysis workflow.

This commit is contained in:
blazickjp
2025-03-10 19:18:16 -07:00
parent 151ce3a60f
commit 36007fb874
8 changed files with 520 additions and 199 deletions

1
.gitignore vendored
View File

@@ -20,6 +20,7 @@ wheels/
.installed.cfg
*.egg
*.coverage
*.DS_Store
# Virtual Environment
venv/

View File

@@ -0,0 +1,78 @@
"""Deep research analysis prompt for the arXiv MCP server."""
# Consolidated comprehensive paper analysis prompt
PAPER_ANALYSIS_PROMPT = """
You are an AI research assistant tasked with analyzing academic papers from arXiv. You have access to several tools to help with this analysis:
AVAILABLE TOOLS:
1. read_paper: Use this tool to retrieve the full content of the paper with the provided arXiv ID
2. download_paper: If the paper is not already available locally, use this tool to download it first
3. search_papers: Find related papers on the same topic to provide context
4. list_papers: Check which papers are already downloaded and available for reading
WORKFLOW FOR PAPER ANALYSIS:
1. PREPARATION:
- First, use the list_papers tool to check if the paper is already downloaded
- If not found, use the download_paper tool to retrieve it
- Then use the read_paper tool with the paper_id to get the full content
2. COMPREHENSIVE ANALYSIS (after reading the paper):
- Executive Summary (2-3 sentences):
* Core contribution and significance at a glance
- Research Context (1 paragraph):
* Research area and specific problem addressed
* Key prior approaches and their limitations
* How this paper aims to advance the field
- Methodology Analysis:
* Step-by-step breakdown of the approach
* Key innovations in the methodology
* Theoretical foundations and assumptions
* Technical implementation details
* Algorithmic complexity and performance characteristics
- Results Analysis:
* Experimental setup (datasets, benchmarks, metrics)
* Main experimental results and their significance
* Statistical validity and robustness of results
* How results support or challenge the paper's claims
* Comparison to state-of-the-art approaches
- Practical Implications:
* How could this be implemented or applied?
* Required resources and potential challenges
* Available code, datasets, or resources
- Theoretical Implications:
* How this work advances fundamental understanding
* New concepts or paradigms introduced
* Challenges to existing theories or assumptions
* Open questions raised
- Future Directions:
* Limitations that future work could address
* Promising follow-up research questions
* Potential for integration with other approaches
* Long-term research agenda this work enables
- Broader Impact (when relevant):
* Societal, ethical, or policy implications
* Environmental or economic considerations
* Potential real-world applications and timeframe
3. OPTIONAL EXTENSIONS:
- Use the search_papers tool to find related work or papers building on this work
- Cross-reference findings with other papers you've analyzed
- Create diagrams or pseudocode to illustrate key concepts
- Summarize key results in tables for easy reference
Structure your analysis with clear headings, maintain technical accuracy while being accessible, and include your critical assessment where appropriate. Your analysis should be comprehensive but concise. Be sure to critically evaluate the statistical significance and reproducibility of any reported results.
"""
# For backward compatibility
CONCISE_PAPER_ANALYSIS = PAPER_ANALYSIS_PROMPT
DEEP_PAPER_ANALYSIS = PAPER_ANALYSIS_PROMPT
METHODOLOGY_FOCUS = PAPER_ANALYSIS_PROMPT
RESULTS_FOCUS = PAPER_ANALYSIS_PROMPT
IMPLICATIONS_FOCUS = PAPER_ANALYSIS_PROMPT

View File

@@ -1,23 +1,80 @@
"""Handlers for prompt-related requests."""
"""Handlers for prompt-related requests with paper analysis functionality."""
from typing import List, Dict
from mcp.types import (
Prompt,
PromptMessage,
TextContent,
GetPromptResult
)
from typing import List, Dict, Optional
from mcp.types import Prompt, PromptMessage, TextContent, GetPromptResult
from .prompts import PROMPTS
from .deep_research_analysis_prompt import PAPER_ANALYSIS_PROMPT
from .prompt_manager import (
get_research_session,
create_research_session,
update_session_from_prompt,
)
# Legacy global research context - used as fallback when no session_id is provided
class ResearchContext:
"""Maintains context throughout a research session."""
def __init__(self):
self.expertise_level = "intermediate" # default
self.explored_papers = {} # paper_id -> basic metadata
self.paper_analyses = {} # paper_id -> analysis focus and summary
def update_from_arguments(self, args: Dict[str, str]) -> None:
"""Update context based on new arguments."""
if "expertise_level" in args:
self.expertise_level = args["expertise_level"]
if "paper_id" in args and args["paper_id"] not in self.explored_papers:
self.explored_papers[args["paper_id"]] = {"id": args["paper_id"]}
# Global research context for backward compatibility
_research_context = ResearchContext()
# Citation and evidence standards by domain
CITATION_STANDARDS = {
"computer_science": "Include specific section numbers and algorithm references",
"physics": "Reference equations and experimental results by number",
"biology": "Include methodology details and statistical significance",
"default": "Reference specific findings and methodologies from the papers",
}
# Output structure for deep paper analysis
OUTPUT_STRUCTURE = """
Present your analysis with the following structure:
1. Executive Summary: 3-5 sentence overview of key contributions
2. Detailed Analysis: Following the specific focus requested
3. Visual Breakdown: Describe key figures/tables and their significance
4. Related Work Map: Position this paper within the research landscape
5. Implementation Notes: Practical considerations for applying these findings
"""
async def list_prompts() -> List[Prompt]:
"""Handle prompts/list request."""
return list(PROMPTS.values())
# Filter to only include deep-paper-analysis
return [PROMPTS["deep-paper-analysis"]] if "deep-paper-analysis" in PROMPTS else []
async def get_prompt(name: str, arguments: Dict[str, str] | None = None) -> GetPromptResult:
"""Handle prompts/get request."""
if name not in PROMPTS:
async def get_prompt(
name: str, arguments: Dict[str, str] | None = None, session_id: Optional[str] = None
) -> GetPromptResult:
"""Handle prompts/get request for paper analysis.
Args:
name: The name of the prompt to get
arguments: The arguments to use with the prompt
session_id: Optional user session ID for context persistence
Returns:
GetPromptResult: The resulting prompt with messages
Raises:
ValueError: If prompt not found or arguments invalid
"""
if name != "deep-paper-analysis":
raise ValueError(f"Prompt not found: {name}")
prompt = PROMPTS[name]
if arguments is None:
raise ValueError(f"No arguments provided for prompt: {name}")
@@ -26,66 +83,67 @@ async def get_prompt(name: str, arguments: Dict[str, str] | None = None) -> GetP
for arg in prompt.arguments:
if arg.required and (arg.name not in arguments or not arguments.get(arg.name)):
raise ValueError(f"Missing required argument: {arg.name}")
if name == "research-discovery":
topic = arguments.get("topic", "")
expertise = arguments.get("expertise_level", "intermediate")
time_period = arguments.get("time_period", "")
guide = {
"beginner": "I'll explain key concepts and methodologies.",
"intermediate": "We'll focus on recent developments.",
"expert": "We'll dive deep into technical details."
}.get(expertise, "We'll focus on recent developments.")
return GetPromptResult(
messages=[
PromptMessage(
role="user",
content=TextContent(
type="text",
text=f"Help me explore research papers on {topic}. "
f"{f'Time period: {time_period}. ' if time_period else ''}"
f"{guide}\n\nWhat specific aspects interest you most?"
)
)
]
)
elif name == "paper-analysis":
paper_id = arguments.get("paper_id", "")
focus = arguments.get("focus_area", "complete")
return GetPromptResult(
messages=[
PromptMessage(
role="user",
content=TextContent(
type="text",
text=f"Analyze paper {paper_id} with a focus on {focus}. "
f"Please provide a detailed breakdown of the paper's content, "
f"methodology, and key findings."
)
)
# Get research context - either from session or fallback to global
context = None
if session_id:
try:
# Try to get existing session
session_data = get_research_session(session_id)
context = session_data
except ValueError:
# Create new session if it doesn't exist
create_research_session(session_id, arguments)
context = get_research_session(session_id)
# Update session with current prompt info
update_session_from_prompt(session_id, name, arguments)
else:
# Fallback to global context for backward compatibility
_research_context.update_from_arguments(arguments)
context = _research_context
# Determine domain-specific guidance
domain = "default" # Default domain since it's no longer required
citation_guidance = CITATION_STANDARDS.get(domain, CITATION_STANDARDS["default"])
# Process deep-paper-analysis prompt
paper_id = arguments.get("paper_id", "")
# Add context from previous papers if available
previous_papers_context = ""
if session_id:
# Get papers from session
papers = context.get("papers", {})
if len(papers) > 1:
previous_ids = [pid for pid in papers.keys() if pid != paper_id]
if previous_ids:
previous_papers_context = f"\nI've previously analyzed papers: {', '.join(previous_ids)}. If relevant, note connections to these works."
else:
# Use global context
if len(_research_context.explored_papers) > 1:
previous_ids = [
pid
for pid in _research_context.explored_papers.keys()
if pid != paper_id
]
)
elif name == "literature-synthesis":
paper_ids = arguments.get("paper_ids", "")
synthesis_type = arguments.get("synthesis_type", "comprehensive")
return GetPromptResult(
messages=[
PromptMessage(
role="user",
content=TextContent(
type="text",
text=f"Synthesize the findings from these papers: {paper_ids}. "
f"Focus on creating a {synthesis_type} analysis that highlights "
f"key themes, methodological approaches, and research implications."
)
)
]
)
raise ValueError("Prompt implementation not found")
if previous_ids:
previous_papers_context = f"\nI've previously analyzed papers: {', '.join(previous_ids)}. If relevant, note connections to these works."
# Track this analysis in context (for global context only, session is updated above)
if not session_id:
_research_context.paper_analyses[paper_id] = {"analysis": "complete"}
return GetPromptResult(
messages=[
PromptMessage(
role="user",
content=TextContent(
type="text",
text=f"Analyze paper {paper_id}.{previous_papers_context}\n\n"
f"{citation_guidance}\n\n{OUTPUT_STRUCTURE}\n\n{PAPER_ANALYSIS_PROMPT}",
),
)
]
)

View File

@@ -1,29 +1,240 @@
"""Prompt management for the arXiv MCP server."""
"""Research journey prompt management for the arXiv MCP server."""
from typing import Optional
from .base import PromptManager
from .templates.discovery import research_discovery_prompts
from .templates.analysis import paper_analysis_prompts
from .templates.synthesis import knowledge_synthesis_prompts
from .templates.workflow import research_workflow_prompts
from typing import Dict, Optional, List, Any
from mcp.types import Prompt, PromptMessage, TextContent
from .prompts import PROMPTS
# Global prompt manager instance
_prompt_manager: Optional[PromptManager] = None
_prompt_manager: Optional[Dict[str, Prompt]] = None
# Research session tracking for associating prompts with a user session
_research_sessions: Dict[str, Dict[str, Any]] = {}
def get_prompt_manager() -> PromptManager:
"""Get or create the global PromptManager instance."""
def get_prompt_manager() -> Dict[str, Prompt]:
"""Get or create the global prompt manager dictionary.
Returns:
Dict[str, Prompt]: Dictionary of available prompts
"""
global _prompt_manager
if _prompt_manager is None:
_prompt_manager = PromptManager()
# Register all prompts
for prompt in research_discovery_prompts:
_prompt_manager.register_template(prompt)
for prompt in paper_analysis_prompts:
_prompt_manager.register_template(prompt)
for prompt in knowledge_synthesis_prompts:
_prompt_manager.register_template(prompt)
for prompt in research_workflow_prompts:
_prompt_manager.register_template(prompt)
_prompt_manager = PROMPTS
return _prompt_manager
def register_prompt(prompt: Prompt) -> None:
"""Register a new prompt in the prompt manager.
Args:
prompt (Prompt): The prompt to register
"""
manager = get_prompt_manager()
manager[prompt.name] = prompt
def create_research_session(
session_id: str, initial_metadata: Optional[Dict[str, Any]] = None
) -> None:
"""Create a new research session to track context across prompts.
Args:
session_id: Unique identifier for the user session
initial_metadata: Optional initial metadata for the session
"""
global _research_sessions
if session_id in _research_sessions:
return # Session already exists
_research_sessions[session_id] = {
"domain": initial_metadata.get("domain") if initial_metadata else None,
"expertise_level": (
initial_metadata.get("expertise_level", "intermediate")
if initial_metadata
else "intermediate"
),
"topics": [],
"papers": {}, # paper_id -> metadata
"analyses": {}, # paper_id -> analysis info
"research_questions": [],
"prompt_history": [], # List of prompts used in this session
}
def get_research_session(session_id: str) -> Dict[str, Any]:
"""Get research session data for a given session ID.
Args:
session_id: Unique identifier for the user session
Returns:
Session data dictionary
Raises:
ValueError: If session doesn't exist
"""
if session_id not in _research_sessions:
raise ValueError(f"Research session not found: {session_id}")
return _research_sessions[session_id]
def update_session_from_prompt(
session_id: str, prompt_name: str, arguments: Dict[str, str]
) -> None:
"""Update research session with data from a prompt.
Args:
session_id: Unique identifier for the user session
prompt_name: Name of the prompt being used
arguments: Arguments provided to the prompt
Raises:
ValueError: If session doesn't exist
"""
if session_id not in _research_sessions:
create_research_session(session_id)
session = _research_sessions[session_id]
# Track prompt usage
session["prompt_history"].append(
{
"name": prompt_name,
"arguments": arguments,
"timestamp": __import__("datetime").datetime.now().isoformat(),
}
)
# Update research metadata based on prompt type and arguments
if "expertise_level" in arguments:
session["expertise_level"] = arguments["expertise_level"]
if "domain" in arguments:
session["domain"] = arguments["domain"]
if prompt_name == "research-discovery" and "topic" in arguments:
topic = arguments["topic"]
if topic and topic not in session["topics"]:
session["topics"].append(topic)
elif prompt_name == "deep-paper-analysis" and "paper_id" in arguments:
paper_id = arguments["paper_id"]
focus = arguments.get("focus_area", "complete")
if paper_id not in session["papers"]:
session["papers"][paper_id] = {"id": paper_id}
if paper_id not in session["analyses"]:
session["analyses"][paper_id] = {"focus": focus}
elif prompt_name == "literature-synthesis" and "paper_ids" in arguments:
paper_ids = arguments["paper_ids"].split(",")
for paper_id in paper_ids:
paper_id = paper_id.strip()
if paper_id and paper_id not in session["papers"]:
session["papers"][paper_id] = {"id": paper_id}
elif prompt_name == "research-question" and "topic" in arguments:
topic = arguments["topic"]
if topic and topic not in session["topics"]:
session["topics"].append(topic)
def update_session_with_research_questions(
session_id: str, questions: List[str]
) -> None:
"""Update a research session with newly generated research questions.
Args:
session_id: Unique identifier for the user session
questions: List of research questions to add
Raises:
ValueError: If session doesn't exist
"""
if session_id not in _research_sessions:
raise ValueError(f"Research session not found: {session_id}")
session = _research_sessions[session_id]
# Add new questions, avoiding duplicates
for question in questions:
if question not in session["research_questions"]:
session["research_questions"].append(question)
def suggest_next_prompts(session_id: str) -> List[Dict[str, Any]]:
"""Suggest relevant next prompts based on session context.
Args:
session_id: Unique identifier for the user session
Returns:
List of suggested prompts with prefilled arguments
Raises:
ValueError: If session doesn't exist
"""
if session_id not in _research_sessions:
raise ValueError(f"Research session not found: {session_id}")
session = _research_sessions[session_id]
suggestions = []
# If user has explored topics but no papers, suggest paper analysis
if session["topics"] and not session["papers"]:
suggestions.append(
{
"prompt": "deep-paper-analysis",
"message": "Analyze a specific paper on one of your topics of interest",
"prefill": {
"domain": session["domain"],
"expertise_level": session["expertise_level"],
},
}
)
# If user has analyzed at least one paper, suggest literature synthesis
if len(session["papers"]) >= 1:
suggestions.append(
{
"prompt": "literature-synthesis",
"message": "Synthesize findings across the papers you've explored",
"prefill": {
"paper_ids": ",".join(session["papers"].keys()),
"domain": session["domain"],
"expertise_level": session["expertise_level"],
},
}
)
# If user has analyzed multiple papers, suggest research questions
if len(session["papers"]) >= 2:
suggestions.append(
{
"prompt": "research-question",
"message": "Generate research questions based on your explored papers",
"prefill": {
"paper_ids": ",".join(session["papers"].keys()),
"topic": session["topics"][-1] if session["topics"] else "",
"domain": session["domain"],
"expertise_level": session["expertise_level"],
},
}
)
# Always suggest exploring a new topic
suggestions.append(
{
"prompt": "research-discovery",
"message": "Explore a new research topic",
"prefill": {
"domain": session["domain"],
"expertise_level": session["expertise_level"],
},
}
)
return suggestions

View File

@@ -1,11 +1,8 @@
"""Prompt definitions for arXiv MCP server."""
"""Prompt definitions for arXiv MCP server with research journey support."""
from mcp.types import (
Prompt,
Prompt,
PromptArgument,
PromptMessage,
TextContent,
GetPromptResult
)
# Define all prompts
@@ -14,25 +11,69 @@ PROMPTS = {
name="research-discovery",
description="Begin research exploration on a specific topic",
arguments=[
PromptArgument(name="topic", description="Research topic or question", required=True),
PromptArgument(name="expertise_level", description="User's familiarity (beginner/intermediate/expert)", required=False),
PromptArgument(name="time_period", description="Time period for search (e.g., '2023-present')", required=False)
]
PromptArgument(
name="topic", description="Research topic or question", required=True
),
PromptArgument(
name="expertise_level",
description="User's familiarity (beginner/intermediate/expert)",
required=False,
),
PromptArgument(
name="time_period",
description="Time period for search (e.g., '2023-present')",
required=False,
),
PromptArgument(
name="domain",
description="Academic domain (e.g., computer_science/physics/biology)",
required=False,
),
],
),
"paper-analysis": Prompt(
name="paper-analysis",
description="Analyze a specific paper",
"deep-paper-analysis": Prompt(
name="deep-paper-analysis",
description="Analyze a specific paper in detail",
arguments=[
PromptArgument(name="paper_id", description="arXiv paper ID", required=True),
PromptArgument(name="focus_area", description="Focus area (methodology/results/implications)", required=False)
]
PromptArgument(
name="paper_id", description="arXiv paper ID", required=True
),
],
),
"literature-synthesis": Prompt(
name="literature-synthesis",
description="Synthesize findings across papers",
description="Synthesize findings across multiple papers",
arguments=[
PromptArgument(name="paper_ids", description="List of arXiv paper IDs", required=True),
PromptArgument(name="synthesis_type", description="Synthesis type (themes/methods/timeline/gaps)", required=False)
]
)
}
PromptArgument(
name="paper_ids", description="Comma-separated list of arXiv paper IDs", required=True
),
PromptArgument(
name="synthesis_type",
description="Synthesis type (themes/methods/timeline/gaps/comprehensive)",
required=False,
),
PromptArgument(
name="domain",
description="Academic domain (e.g., computer_science/physics/biology)",
required=False,
),
],
),
"research-question": Prompt(
name="research-question",
description="Formulate research questions based on literature",
arguments=[
PromptArgument(
name="paper_ids", description="Comma-separated list of arXiv paper IDs", required=True
),
PromptArgument(
name="topic", description="Research topic or question", required=True
),
PromptArgument(
name="domain",
description="Academic domain (e.g., computer_science/physics/biology)",
required=False,
),
],
),
}

View File

@@ -1,13 +1,13 @@
"""Integration tests for prompt functionality."""
import pytest
from arxiv_mcp_server.server import server
from arxiv_mcp_server.prompts.handlers import list_prompts, get_prompt
@pytest.mark.asyncio
async def test_server_list_prompts():
"""Test server list_prompts endpoint."""
prompts = await server.list_prompts()
assert len(prompts) == 3
prompts = await list_prompts()
assert len(prompts) == 1
# Check that all prompts have required fields
for prompt in prompts:
@@ -15,57 +15,27 @@ async def test_server_list_prompts():
assert prompt.description
assert prompt.arguments is not None
@pytest.mark.asyncio
async def test_server_get_research_prompt():
"""Test server get_prompt endpoint with research prompt."""
result = await server.get_prompt(
name="research-discovery",
arguments={"topic": "machine learning", "expertise_level": "expert"}
)
assert len(result.messages) == 1
message = result.messages[0]
assert message.role == "user"
assert "machine learning" in message.content.text
assert "dive deep" in message.content.text.lower()
@pytest.mark.asyncio
async def test_server_get_analysis_prompt():
"""Test server get_prompt endpoint with analysis prompt."""
result = await server.get_prompt(
name="paper-analysis",
arguments={"paper_id": "2401.00123", "focus_area": "implications"}
result = await get_prompt(
"deep-paper-analysis",
{"paper_id": "2401.00123"}
)
assert len(result.messages) == 1
message = result.messages[0]
assert message.role == "user"
assert "2401.00123" in message.content.text
assert "implications" in message.content.text.lower()
@pytest.mark.asyncio
async def test_server_get_synthesis_prompt():
"""Test server get_prompt endpoint with synthesis prompt."""
paper_ids = "2401.00123, 2401.00124"
result = await server.get_prompt(
name="literature-synthesis",
arguments={"paper_ids": paper_ids, "synthesis_type": "timeline"}
)
assert len(result.messages) == 1
message = result.messages[0]
assert message.role == "user"
assert paper_ids in message.content.text
assert "timeline" in message.content.text.lower()
@pytest.mark.asyncio
async def test_server_get_prompt_invalid_name():
"""Test server get_prompt endpoint with invalid prompt name."""
with pytest.raises(ValueError, match="Prompt not found"):
await server.get_prompt(name="invalid-prompt", arguments={})
await get_prompt("invalid-prompt", {})
@pytest.mark.asyncio
async def test_server_get_prompt_missing_args():
"""Test server get_prompt endpoint with missing required arguments."""
with pytest.raises(ValueError, match="Missing required argument"):
await server.get_prompt(name="research-discovery", arguments={})
await get_prompt("deep-paper-analysis", {})

View File

@@ -9,36 +9,18 @@ from mcp.types import GetPromptResult, PromptMessage, TextContent
async def test_list_prompts():
"""Test listing available prompts."""
prompts = await list_prompts()
assert len(prompts) == 3
assert len(prompts) == 1
prompt_names = {p.name for p in prompts}
expected_names = {"research-discovery", "paper-analysis", "literature-synthesis"}
expected_names = {"deep-paper-analysis"}
assert prompt_names == expected_names
@pytest.mark.asyncio
async def test_get_research_discovery_prompt():
"""Test getting research discovery prompt."""
result = await get_prompt(
"research-discovery",
{"topic": "quantum computing", "expertise_level": "beginner"}
)
assert isinstance(result, GetPromptResult)
assert len(result.messages) == 1
message = result.messages[0]
assert isinstance(message, PromptMessage)
assert message.role == "user"
assert isinstance(message.content, TextContent)
assert "quantum computing" in message.content.text
assert "explain key concepts" in message.content.text.lower()
@pytest.mark.asyncio
async def test_get_paper_analysis_prompt():
"""Test getting paper analysis prompt."""
result = await get_prompt(
"paper-analysis",
{"paper_id": "2401.00123", "focus_area": "methodology"}
"deep-paper-analysis",
{"paper_id": "2401.00123"}
)
assert isinstance(result, GetPromptResult)
@@ -49,26 +31,6 @@ async def test_get_paper_analysis_prompt():
assert message.role == "user"
assert isinstance(message.content, TextContent)
assert "2401.00123" in message.content.text
assert "methodology" in message.content.text.lower()
@pytest.mark.asyncio
async def test_get_literature_synthesis_prompt():
"""Test getting literature synthesis prompt."""
paper_ids = "2401.00123, 2401.00124"
result = await get_prompt(
"literature-synthesis",
{"paper_ids": paper_ids, "synthesis_type": "themes"}
)
assert isinstance(result, GetPromptResult)
assert len(result.messages) == 1
message = result.messages[0]
assert isinstance(message, PromptMessage)
assert message.role == "user"
assert isinstance(message.content, TextContent)
assert paper_ids in message.content.text
assert "themes" in message.content.text.lower()
@pytest.mark.asyncio
async def test_get_prompt_with_invalid_name():
@@ -80,10 +42,10 @@ async def test_get_prompt_with_invalid_name():
async def test_get_prompt_with_no_arguments():
"""Test getting prompt with no arguments."""
with pytest.raises(ValueError, match="No arguments provided"):
await get_prompt("research-discovery", None)
await get_prompt("deep-paper-analysis", None)
@pytest.mark.asyncio
async def test_get_prompt_with_missing_required_argument():
"""Test getting prompt with missing required argument."""
with pytest.raises(ValueError, match="Missing required argument"):
await get_prompt("research-discovery", {})
await get_prompt("deep-paper-analysis", {})

4
uv.lock generated
View File

@@ -144,7 +144,7 @@ wheels = [
[[package]]
name = "arxiv-mcp-server"
version = "0.2.5"
version = "0.2.6"
source = { editable = "." }
dependencies = [
{ name = "aiofiles" },
@@ -270,7 +270,7 @@ name = "click"
version = "8.1.7"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "colorama", marker = "sys_platform == 'win32'" },
{ name = "colorama", marker = "platform_system == 'Windows'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 }
wheels = [