Spaces:
Sleeping
Sleeping
File size: 6,689 Bytes
2df36ec |
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 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
from typing import Any, List, Literal, Dict, Optional
import httpx
import traceback
from mcp.server.fastmcp import FastMCP
# Initialize FastMCP server
mcp = FastMCP("patent-problematic-generator-helper")
# API used
ARXIV_BASE = "https://om4r932-arxiv.hf.space"
DUCKDUCKGO_BASE = "https://ychkhan-ptt-endpoints.hf.space"
DOC3GPPFINDER_BASE = "https://organizedprogrammers-3gppdocfinder.hf.space"
# Request function
async def post_data_to_api(url, **kwargs):
data = dict(kwargs)
if data is None or data == {}:
return (None, "")
headers = {"Accept": "application/json"}
async with httpx.AsyncClient(verify=False, timeout=180) as client:
try:
response = await client.post(url, headers=headers, json=data)
print(response)
response.raise_for_status()
return response.json()
except Exception as e:
traceback.print_exception(e)
return (None, e)
async def fake_post_data_to_api(url, **kwargs):
params = dict(kwargs)
if params is None or params == {}:
return (None, "")
headers = {"Accept": "application/json"}
async with httpx.AsyncClient(verify=False, timeout=180) as client:
try:
response = await client.post(url, headers=headers, params=params)
print(response)
response.raise_for_status()
return response.json()
except Exception as e:
traceback.print_exception(e)
return (None, e)
async def get_data_from_api(url):
headers = {"Accept": "application/json"}
async with httpx.AsyncClient(verify=False, timeout=180) as client:
try:
response = await client.get(url, headers=headers)
print(response)
response.raise_for_status()
return response.json()
except Exception as e:
traceback.print_exception(e)
return (None, e)
# Tools
# arXiv
@mcp.tool()
async def get_arxiv_publications(keywords: str, limit: int):
"""
Search arXiv publications based on keywords and a limit of documents printed
Arguments available: keywords: string [mandatory], limit: integer [mandatory, default = 5]
"""
endpoint = ARXIV_BASE + "/search"
data = await post_data_to_api(endpoint, keyword=keywords, limit=limit)
if isinstance(data, tuple) and data[0] is None:
return f"An error has occured while getting publications: {data[1]}"
if data["error"]:
return data["message"]
if len(data) < 1:
return "No publications has been found"
results = data["message"]
output = []
for pub, metadata in results.items():
output.append(f"arXiv pub ID: {pub}\nTitle: {metadata['title']}\nAuthors: {metadata['authors']}\nPublished on: {metadata['date']}\nAbstract: {metadata['abstract']}\nPDF URL: {metadata['pdf']}\n")
return "-\n".join(output)
# 3GPP Doc Finder
@mcp.tool()
async def get_document_url(doc_id: str, release: int = None):
"""
Find 3GPP document (TSG docs, specifications or workshop files) only by their ID [note that it will only work with keywords] (and release if it's a specification only) and return their position via a URL (and a scope if it's a specification)
Arguments available: doc_id: string [mandatory], release: integer [optional for every case]
"""
endpoint = DOC3GPPFINDER_BASE + "/find"
data = await post_data_to_api(endpoint, doc_id=doc_id, release=release)
if isinstance(data, tuple) and data[0] is None:
return f"An error while searching publications: {data[1]}"
output = f'Document ID: {doc_id}\nURL: {data.get("url", "Not found !")}'
output += f'\nScope: {data["scope"]}' if data.get("scope", None) is not None else ""
return output
@mcp.tool()
async def search_specs(keywords: str, limit: int):
"""
Search 3GPP specifications only by their keywords [note that it will only work with keywords](and some filters [see kwargs field])
Arguments available: keywords: string [mandatory, separated by space], limit [mandatory, default = 5]
Kwargs available [optional]: (release: integer as string or 'Rel-xxx', wg: string = working group (S1, C4, SP, ...), spec_type: string (either TS or TR), mode: string (either 'and' or 'or') = search mode)
"""
endpoint = DOC3GPPFINDER_BASE + "/search-spec"
data = await post_data_to_api(endpoint, keywords=keywords)
if isinstance(data, tuple) and data[0] is None:
return f"An error has occured while searching specifications"
results = data['results'][:min(len(data['results'])-1, limit)]
output = []
for spec in results:
output.append(f"Specification ID: {spec['id']}\nTitle: {spec['title']}\nType: {spec['type']}\nRelease: {spec['release']}\nVersion: {spec['version']}\nWorking Group: {spec['working_group']}\nURL of spec: {spec['url']}\n")
return "-\n".join(output)
@mcp.tool()
async def get_multiple_documents_url(doc_ids: List[str], release: int = None):
"""
[BATCH] Search multiple 3GPP documents (TSG docs, specifications or workshop files) [note that it will only work with document ID] (and release if it's a specification only) and return only their position via a URL
Arguments available: doc_ids: list of string [mandatory], release: integer [optional for every case]
"""
endpoint = DOC3GPPFINDER_BASE + "/batch"
data = await post_data_to_api(endpoint, doc_ids=doc_ids, release=release)
if isinstance(data, tuple) and data[0] is None:
return f"An error while searching publications: {data[1]}"
results = data["results"]
output = []
for doc_id, url in results.items():
output.append(f'Document ID: {doc_id}\nURL: {url}\n')
return "-\n".join(output)
# PTT Endpoints
@mcp.tool()
async def search_documents_web(query: str, data_type: str = None, limit: int = 5):
"""
Search on the Web (thanks to DuckDuckGo) documents based on the user's query
Arguments available: query: string [mandatory], data_type: string [optional, either 'pdf', 'patent' or None (classic web search)], limit: integer [optional, default = 5]
"""
endpoint = DUCKDUCKGO_BASE + "/search"
data = await fake_post_data_to_api(endpoint, query=query, data_type=data_type, max_references=limit)
if isinstance(data, tuple) and data[0] is None:
return f"An error while searching publications: {data[1]}"
results = data["results"]
output = []
for ref in results:
output.append(f"Title: {ref['title']}\nBody: {ref['body']}\nURL: {ref['url']}")
return "-\n".join(output)
if __name__ == "__main__":
mcp.run(transport="stdio") |