Skip to main content
Glama
gqy20

Europe PMC Literature Search MCP Server

api_utils.py6.46 kB
""" 统一的API调用工具 - Linus风格:简单直接 """ import logging from functools import lru_cache from typing import Any import requests from requests.adapters import HTTPAdapter from requests.packages.urllib3.util.retry import Retry class UnifiedAPIClient: """统一的API客户端 - 简单直接""" def __init__(self, logger: logging.Logger | None = None): self.logger = logger or logging.getLogger(__name__) self.session = self._create_session() self.timeout = 30 def _create_session(self) -> requests.Session: """创建带重试的会话""" session = requests.Session() # 统一的重试策略 retry_strategy = Retry( total=3, # 最多重试3次 backoff_factor=1, # 1, 2, 4秒指数退避 status_forcelist=[429, 500, 502, 503, 504], allowed_methods=["GET", "POST"], ) adapter = HTTPAdapter(max_retries=retry_strategy) session.mount("http://", adapter) session.mount("https://", adapter) # 统一的请求头 session.headers.update( { "User-Agent": "Article-MCP/2.0", "Accept": "application/json", "Accept-Encoding": "gzip, deflate", } ) return session def get( self, url: str, params: dict | None = None, headers: dict | None = None, timeout: int | None = None, ) -> dict[str, Any]: """ 统一的GET请求 - 一个方法搞定所有GET请求 Args: url: 请求URL params: 查询参数 headers: 额外请求头 timeout: 超时时间 Returns: 统一格式的响应 """ try: request_headers = self.session.headers.copy() if headers: request_headers.update(headers) response = self.session.get( url, params=params, headers=request_headers, timeout=timeout or self.timeout ) response.raise_for_status() return { "success": True, "status_code": response.status_code, "data": response.json() if response.content else {}, "headers": dict(response.headers), "url": response.url, } except requests.exceptions.Timeout: return {"success": False, "error": "请求超时", "error_type": "timeout", "url": url} except requests.exceptions.RequestException as e: self.logger.error(f"GET请求失败 {url}: {e}") return {"success": False, "error": str(e), "error_type": "request_error", "url": url} except Exception as e: self.logger.error(f"GET请求异常 {url}: {e}") return {"success": False, "error": str(e), "error_type": "unknown_error", "url": url} def post( self, url: str, data: dict | str | None = None, json: dict | None = None, headers: dict | None = None, timeout: int | None = None, ) -> dict[str, Any]: """ 统一的POST请求 - 一个方法搞定所有POST请求 Args: url: 请求URL data: 表单数据 json: JSON数据 headers: 额外请求头 timeout: 超时时间 Returns: 统一格式的响应 """ try: request_headers = self.session.headers.copy() if headers: request_headers.update(headers) response = self.session.post( url, data=data, json=json, headers=request_headers, timeout=timeout or self.timeout ) response.raise_for_status() return { "success": True, "status_code": response.status_code, "data": response.json() if response.content else {}, "headers": dict(response.headers), "url": response.url, } except requests.exceptions.Timeout: return {"success": False, "error": "请求超时", "error_type": "timeout", "url": url} except requests.exceptions.RequestException as e: self.logger.error(f"POST请求失败 {url}: {e}") return {"success": False, "error": str(e), "error_type": "request_error", "url": url} except Exception as e: self.logger.error(f"POST请求异常 {url}: {e}") return {"success": False, "error": str(e), "error_type": "unknown_error", "url": url} def close(self): """关闭会话""" if hasattr(self.session, "close"): self.session.close() # 全局API客户端实例 _api_client: UnifiedAPIClient | None = None def get_api_client(logger: logging.Logger | None = None) -> UnifiedAPIClient: """获取统一的API客户端""" global _api_client if _api_client is None: _api_client = UnifiedAPIClient(logger) return _api_client @lru_cache(maxsize=5000) def cached_get(url: str, params: str | None = None) -> dict[str, Any]: """ 带缓存的GET请求 - 简单直接 Args: url: 请求URL params: 序列化的查询参数 Returns: API响应 """ api_client = get_api_client() # 反序列化参数 query_params = eval(params) if params else None return api_client.get(url, query_params) def make_api_request(method: str, url: str, **kwargs) -> dict[str, Any]: """ 统一的API请求接口 - 简单直接 Args: method: HTTP方法 ("GET" 或 "POST") url: 请求URL **kwargs: 其他请求参数 Returns: 统一格式的响应 """ api_client = get_api_client() if method.upper() == "GET": return api_client.get(url, **kwargs) elif method.upper() == "POST": return api_client.post(url, **kwargs) else: return { "success": False, "error": f"不支持的HTTP方法: {method}", "error_type": "invalid_method", } # 便捷函数 def simple_get(url: str, **params) -> dict[str, Any]: """简单的GET请求""" return get_api_client().get(url, params) def simple_post(url: str, **kwargs) -> dict[str, Any]: """简单的POST请求""" return get_api_client().post(url, **kwargs)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/gqy20/article-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server