-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.py
More file actions
126 lines (92 loc) · 4.03 KB
/
server.py
File metadata and controls
126 lines (92 loc) · 4.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
from mcp.server.auth.settings import AuthSettings
from mcp.server.fastmcp import FastMCP
from pydantic import AnyHttpUrl
from authentication.jwt_verifier import JWTTokenVerifier
from dotenv import load_dotenv
import os
import arxiv
from typing import List, Dict
import logging
from tavily import TavilyClient
from mcp.server.auth.middleware.auth_context import get_access_token
logger = logging.getLogger(__name__)
load_dotenv()
AUTH_ISSUER = os.getenv("AUTH_ISSUER")
CLIENT_ID = os.getenv("CLIENT_ID")
JWKS_URL = os.getenv("JWKS_URL")
mcp = FastMCP(
"MCP server",
token_verifier=JWTTokenVerifier(JWKS_URL, AUTH_ISSUER, CLIENT_ID),
auth=AuthSettings(
issuer_url=AnyHttpUrl(AUTH_ISSUER),
resource_server_url=AnyHttpUrl("http://localhost:8000"),
),
)
@mcp.tool()
def get_research_paper_details(query: str, max_results: int = 5) -> List[Dict]:
"""
Fetches paper details including title, authors, abstract, PDF URL from arXiv API.
Args:
query: Search query
max_results: Max number of results
Returns:
List of dicts with paper details
"""
logger.info(f"Starting arXiv search for query: '{query}' with max_results={max_results}")
access_token = get_access_token()
logger.info(f"Access token scopes in tool ARXIV: {access_token.scopes if access_token else 'No access token'}")
if not access_token or "arxiv_search_tool" not in access_token.scopes:
logger.error(f"Access denied. Required scope: arxiv_search_tool")
raise PermissionError("Insufficient permissions. Missing scope: arxiv_search_tool")
try:
client = arxiv.Client()
search = arxiv.Search(query=query, max_results=max_results)
papers = []
for i, result in enumerate(client.results(search)):
logger.debug(f"Processing paper {i+1}: {result.title[:100]}...")
paper_info = {
'title': result.title,
'authors': [author.name for author in result.authors],
'abstract': result.summary,
'pdf_url': result.pdf_url,
'published': str(result.published),
'categories': result.categories
}
papers.append(paper_info)
logger.info(f"Successfully fetched {len(papers)} papers for query '{query}'")
return papers
except Exception as e:
logger.error(f"Error fetching papers for '{query}': {str(e)}", exc_info=True)
raise
@mcp.tool()
def web_search(query: str, search_depth: str = "basic", max_results: int = 5) -> str:
"""
Conduct web search using Tavily API. Returns formatted results
Args:
query: Search query
search_depth: "basic" or "advanced"
max_results: Maxnumber of results to return
Returns:
Formatted string with summary and results
"""
access_token = get_access_token()
logger.info(f"Access token scopes in tool WEB_SEARCH: {access_token.scopes if access_token else 'No access token'}")
if not access_token or "web_search" not in access_token.scopes:
logger.error(f"Access denied. Required scope: web_search")
raise PermissionError("Insufficient permissions. Missing scope: web_search")
try:
tavily = TavilyClient(api_key=os.getenv("TAVILY_API_KEY"))
response = tavily.search(query=query, search_depth=search_depth, max_results=max_results, include_answer=True)
results = response.get("results", [])
if not results:
return "No results."
out = f"Summary: {response.get('answer', 'N/A')}\n\n"
for i, r in enumerate(results, 1):
out += f"[{i}] {r['title']} ({r['score']:.2f})\n{r['url']}\n{r['content'][:200]}...\n\n"
logger.info(f"Got {len(results)} results")
return out
except Exception as e:
logger.error(f"Search failed: {e}")
return f"Error: {e}"
if __name__ == "__main__":
mcp.run(transport="streamable-http")