diff --git a/server/mcp_server_askecho_search_infinity/README.md b/server/mcp_server_askecho_search_infinity/README.md index 0c565033..486ff52a 100644 --- a/server/mcp_server_askecho_search_infinity/README.md +++ b/server/mcp_server_askecho_search_infinity/README.md @@ -1,8 +1,8 @@ # 联网搜索API MCP Server ## 版本信息 -v0.1.0 +v0.2.0 ## 产品描述 -火山引擎联网搜索API,提供网页与图片搜索能力,帮助大模型获取更准确、更新鲜的外部信息。 +火山引擎联网搜索API,提供豆包搜索 Custom 版网页与基础图片搜索能力,帮助大模型获取更准确、更新鲜的外部信息。 ## 分类 火山引擎云原生 ## 标签 @@ -16,7 +16,7 @@ v0.1.0 #### 类型 saas #### 详细描述 -根据用户输入问题,返回联网搜索结果,支持网页和图片搜索 +根据用户输入问题,返回联网搜索结果,支持网页与基础图片搜索。 #### 调试所需的输入参数: 输入: ```json @@ -32,7 +32,7 @@ saas "type": "string" }, "Count": { - "description": "返回条数;web 最多 50 条,image 最多 5 条,不传默认 10 条", + "description": "返回条数;web 默认 10 条、最多 50 条,image 默认且最多 5 条", "type": "number" }, "SearchType": { @@ -46,6 +46,34 @@ saas "AuthLevel": { "description": "权威等级过滤,0 为默认,1 为非常权威", "type": "number" + }, + "NeedContent": { + "description": "是否返回网页正文,仅支持 web", + "type": "boolean" + }, + "NeedUrl": { + "description": "是否返回网页 URL,仅支持 web", + "type": "boolean" + }, + "Sites": { + "description": "仅搜索指定站点,以 | 分隔,最多 20 个,仅支持 web", + "type": "string" + }, + "BlockHosts": { + "description": "排除指定站点,以 | 分隔,最多 5 个,仅支持 web", + "type": "string" + }, + "Industry": { + "description": "行业搜索,可选 finance、game 或 gov,仅支持 web", + "type": "string" + }, + "QueryRewrite": { + "description": "是否启用查询改写", + "type": "boolean" + }, + "ContentFormats": { + "description": "网页正文格式,可选 text 或 markdown,仅支持 web", + "type": "string" } } }, @@ -61,9 +89,10 @@ saas #### 最容易被唤起的 Prompt示例 联网搜索北京周边游攻略 ## 可适配平台 -Trae,Cursor,Python +Claude Code, Codex, Trae,Cursor等支持MCP协议的AI工具 ## 服务开通链接 (整体产品) 登录火山控制台,开通【联网搜索API】,服务开通链接:https://console.volcengine.com/search-infinity/web-search + API Key 创建链接:https://console.volcengine.com/search-infinity/api-key ## 鉴权方式 - API Key鉴权 @@ -71,7 +100,6 @@ API Key 创建链接:https://console.volcengine.com/search-infinity/api-key ## 安装部署 ### 前置准备 - Python 3.12 / 3.13 -- 当前不支持 Python 3.14 beta,`mcp` / `pydantic` 依赖链在该版本上仍存在兼容性问题 - UV **Linux/macOS:** ```bash @@ -99,6 +127,33 @@ uv run mcp-server-askecho-search-infinity -t streamable-http ## 部署 ### UVX 鉴权信息,火山引擎 AK/SK 与 `ASK_ECHO_SEARCH_INFINITY_API_KEY` 二选一即可 + +#### 推荐:从 PyPI 或已配置的火山镜像源安装 + +该方式不依赖 GitHub,`>=0.2.0` 会自动使用可获取的最新发布版本。 + +```json +{ + "mcpServers": { + "mcp-server-askecho-search-infinity": { + "command": "uvx", + "args": [ + "--from", + "mcp-server-askecho-search-infinity>=0.2.0", + "mcp-server-askecho-search-infinity" + ], + "env": { + "VOLCENGINE_ACCESS_KEY": "", + "VOLCENGINE_SECRET_KEY": "", + "ASK_ECHO_SEARCH_INFINITY_API_KEY": "" + } + } + } +} +``` + +#### 备用:从 GitHub 源码安装 + ```json { "mcpServers": { diff --git a/server/mcp_server_askecho_search_infinity/pyproject.toml b/server/mcp_server_askecho_search_infinity/pyproject.toml index e0026d70..0b34e2f0 100644 --- a/server/mcp_server_askecho_search_infinity/pyproject.toml +++ b/server/mcp_server_askecho_search_infinity/pyproject.toml @@ -1,11 +1,11 @@ [project] name = "mcp-server-askecho-search-infinity" -version = "0.1.0" +version = "0.2.0" description = "Web Search API MCP Server" readme = "README.md" requires-python = ">=3.12,<3.14" dependencies = [ - "mcp>=1.9.4", + "mcp>=1.29.0,<2.0.0", "aiohttp>=3.9.0", ] @@ -14,4 +14,4 @@ mcp-server-askecho-search-infinity = "mcp_server_askecho_search_infinity:main" [build-system] requires = ["setuptools>=61.0", "wheel"] -build-backend = "setuptools.build_meta" \ No newline at end of file +build-backend = "setuptools.build_meta" diff --git a/server/mcp_server_askecho_search_infinity/src/mcp_server_askecho_search_infinity/api/api_key_auth.py b/server/mcp_server_askecho_search_infinity/src/mcp_server_askecho_search_infinity/api/api_key_auth.py index 6704a4f4..b0a0a3ea 100644 --- a/server/mcp_server_askecho_search_infinity/src/mcp_server_askecho_search_infinity/api/api_key_auth.py +++ b/server/mcp_server_askecho_search_infinity/src/mcp_server_askecho_search_infinity/api/api_key_auth.py @@ -4,6 +4,7 @@ Host = "open.feedcoopapi.com" ContentType = "application/json" +REQUEST_TIMEOUT_SECONDS = 30 async def web_search_api_key_auth(api_key: str, req: WebSearchRequest, tool_name: str): @@ -17,12 +18,10 @@ async def web_search_api_key_auth(api_key: str, req: WebSearchRequest, tool_name async with session.post( url=f"https://{Host}/search_api/web_search", headers=header, - timeout=aiohttp.ClientTimeout(total=3000), + timeout=aiohttp.ClientTimeout(total=REQUEST_TIMEOUT_SECONDS), data=json.dumps(req.to_payload()) ) as response: # 在上下文内读取所有数据,避免连接关闭问题 response.raise_for_status() # 手动调用 data = await response.json() return data - return None - return None diff --git a/server/mcp_server_askecho_search_infinity/src/mcp_server_askecho_search_infinity/api/volcengine_auth.py b/server/mcp_server_askecho_search_infinity/src/mcp_server_askecho_search_infinity/api/volcengine_auth.py index cd9a9153..7852ca1c 100644 --- a/server/mcp_server_askecho_search_infinity/src/mcp_server_askecho_search_infinity/api/volcengine_auth.py +++ b/server/mcp_server_askecho_search_infinity/src/mcp_server_askecho_search_infinity/api/volcengine_auth.py @@ -12,6 +12,7 @@ Region = "cn-beijing" Host = "mercury.volcengineapi.com" ContentType = "application/json" +REQUEST_TIMEOUT_SECONDS = 30 async def web_search_volcengine_auth(ak: str, sk: str, req: WebSearchRequest, tool_name: str): @@ -122,7 +123,7 @@ async def volcengine_auth_request(method, date, query, header, ak, sk, action, b method=method, url=f"https://{request_param['host']}{request_param['path']}", headers=header, - timeout=aiohttp.ClientTimeout(total=600), + timeout=aiohttp.ClientTimeout(total=REQUEST_TIMEOUT_SECONDS), params=request_param["query"], data=request_param["body"] ) as response: @@ -130,5 +131,3 @@ async def volcengine_auth_request(method, date, query, header, ak, sk, action, b response.raise_for_status() # 手动调用 data = await response.json() return data - return None - return None diff --git a/server/mcp_server_askecho_search_infinity/src/mcp_server_askecho_search_infinity/model.py b/server/mcp_server_askecho_search_infinity/src/mcp_server_askecho_search_infinity/model.py index e8f019de..8f7aea1c 100644 --- a/server/mcp_server_askecho_search_infinity/src/mcp_server_askecho_search_infinity/model.py +++ b/server/mcp_server_askecho_search_infinity/src/mcp_server_askecho_search_infinity/model.py @@ -6,30 +6,10 @@ TIME_RANGE_SHORTCUTS = {"OneDay", "OneWeek", "OneMonth", "OneYear"} DATE_RANGE_PATTERN = re.compile(r"^(\d{4}-\d{2}-\d{2})\.\.(\d{4}-\d{2}-\d{2})$") SUPPORTED_SEARCH_TYPES = {"web", "image"} - - -@dataclass -class Error: - message: str - type: str - code: str - - def to_dict(self): - return { - "message": self.message, - "type": self.type, - "code": self.code - } - - -@dataclass -class ResponseError: - error: Error - - def to_dict(self): - return { - "error": self.error.to_dict(), - } +SUPPORTED_INDUSTRIES = {"finance", "game", "gov"} +SUPPORTED_CONTENT_FORMATS = {"text", "markdown"} +MAX_SITE_COUNT = 20 +MAX_BLOCK_HOST_COUNT = 5 @dataclass @@ -38,8 +18,9 @@ class WebSearchRequest: SearchType: str = "web" Count: int = 10 Filter: Optional[dict] = None - NeedSummary: Optional[bool] = None TimeRange: Optional[str] = None + QueryControl: Optional[dict] = None + ContentFormats: Optional[str] = None def to_payload(self): payload = { @@ -47,12 +28,14 @@ def to_payload(self): "SearchType": self.SearchType, "Count": self.Count, } - if self.SearchType == "web": - payload["NeedSummary"] = True - if self.Filter: - payload["Filter"] = self.Filter - if self.TimeRange: - payload["TimeRange"] = self.TimeRange + if self.Filter: + payload["Filter"] = self.Filter + if self.TimeRange: + payload["TimeRange"] = self.TimeRange + if self.QueryControl: + payload["QueryControl"] = self.QueryControl + if self.ContentFormats: + payload["ContentFormats"] = self.ContentFormats return payload @@ -101,12 +84,35 @@ def validate_time_range(time_range: Optional[str]) -> Optional[str]: return time_range +def validate_host_list(value: Optional[str], field_name: str, max_count: int) -> Optional[str]: + if value is None: + return None + + normalized_value = value.strip() + if not normalized_value: + return None + + items = [item.strip() for item in normalized_value.split("|")] + if not items or any(not item for item in items): + raise ValueError(f"{field_name} 需为以 | 分隔的非空域名列表。") + if len(items) > max_count: + raise ValueError(f"{field_name} 最多支持 {max_count} 个域名。") + return "|".join(items) + + def build_web_search_request( query: str, - count: int = 10, + count: Optional[int] = None, search_type: str = "web", time_range: Optional[str] = None, auth_level: int = 0, + need_content: Optional[bool] = None, + need_url: Optional[bool] = None, + sites: Optional[str] = None, + block_hosts: Optional[str] = None, + industry: Optional[str] = None, + query_rewrite: Optional[bool] = None, + content_formats: Optional[str] = None, ) -> WebSearchRequest: normalized_query = (query or "").strip() if not normalized_query: @@ -114,26 +120,73 @@ def build_web_search_request( if len(normalized_query) > 100: raise ValueError("Query 长度需为 1~100 个字符。") - if search_type not in SUPPORTED_SEARCH_TYPES: + normalized_search_type = (search_type or "").strip().lower() + if normalized_search_type not in SUPPORTED_SEARCH_TYPES: raise ValueError("SearchType 仅支持 web 或 image。") + if count is None: + count = 10 if normalized_search_type == "web" else 5 if count < 1: raise ValueError("Count 需大于等于 1。") - max_count = 50 if search_type == "web" else 5 + max_count = 50 if normalized_search_type == "web" else 5 if count > max_count: - raise ValueError(f"{search_type} 类型最多返回 {max_count} 条。") + raise ValueError(f"{normalized_search_type} 类型最多返回 {max_count} 条。") if auth_level not in {0, 1}: raise ValueError("AuthLevel 仅支持 0 或 1。") - normalized_time_range = validate_time_range(time_range) if search_type == "web" else None - filters = {"AuthInfoLevel": auth_level} if search_type == "web" and auth_level > 0 else None + normalized_industry = industry.strip().lower() if industry else None + if normalized_industry and normalized_industry not in SUPPORTED_INDUSTRIES: + raise ValueError("Industry 仅支持 finance、game 或 gov。") + + normalized_content_formats = content_formats.strip().lower() if content_formats else None + if normalized_content_formats and normalized_content_formats not in SUPPORTED_CONTENT_FORMATS: + raise ValueError("ContentFormats 仅支持 text 或 markdown。") + + if normalized_search_type == "image": + web_only_args = { + "TimeRange": time_range, + "AuthLevel": auth_level if auth_level else None, + "NeedContent": need_content, + "NeedUrl": need_url, + "Sites": sites, + "BlockHosts": block_hosts, + "Industry": normalized_industry, + "ContentFormats": normalized_content_formats, + } + unsupported_fields = [name for name, value in web_only_args.items() if value is not None] + if unsupported_fields: + raise ValueError(f"{', '.join(unsupported_fields)} 仅支持 web 搜索。") + return WebSearchRequest( + Query=normalized_query, + SearchType=normalized_search_type, + Count=count, + QueryControl={"QueryRewrite": query_rewrite} if query_rewrite is not None else None, + ) + + filters = {} + if auth_level > 0: + filters["AuthInfoLevel"] = auth_level + if need_content is not None: + filters["NeedContent"] = need_content + if need_url is not None: + filters["NeedUrl"] = need_url + + normalized_sites = validate_host_list(sites, "Sites", MAX_SITE_COUNT) + if normalized_sites: + filters["Sites"] = normalized_sites + normalized_block_hosts = validate_host_list(block_hosts, "BlockHosts", MAX_BLOCK_HOST_COUNT) + if normalized_block_hosts: + filters["BlockHosts"] = normalized_block_hosts + if normalized_industry: + filters["Industry"] = normalized_industry return WebSearchRequest( Query=normalized_query, - SearchType=search_type, + SearchType=normalized_search_type, Count=count, - Filter=filters, - NeedSummary=True if search_type == "web" else None, - TimeRange=normalized_time_range, + Filter=filters or None, + TimeRange=validate_time_range(time_range), + QueryControl={"QueryRewrite": query_rewrite} if query_rewrite is not None else None, + ContentFormats=normalized_content_formats, ) diff --git a/server/mcp_server_askecho_search_infinity/src/mcp_server_askecho_search_infinity/server.py b/server/mcp_server_askecho_search_infinity/src/mcp_server_askecho_search_infinity/server.py index 8b886a15..a8cbae37 100644 --- a/server/mcp_server_askecho_search_infinity/src/mcp_server_askecho_search_infinity/server.py +++ b/server/mcp_server_askecho_search_infinity/src/mcp_server_askecho_search_infinity/server.py @@ -1,7 +1,7 @@ import logging import argparse from mcp.server import FastMCP -from typing import Dict, Any +from typing import Dict, Any, Optional from .model import * from .config import * @@ -20,19 +20,33 @@ @mcp.tool() async def web_search( Query: str, - Count: int = 10, + Count: Optional[int] = None, SearchType: str = "web", TimeRange: str = "", AuthLevel: int = 0, + NeedContent: Optional[bool] = None, + NeedUrl: Optional[bool] = None, + Sites: Optional[str] = None, + BlockHosts: Optional[str] = None, + Industry: Optional[str] = None, + QueryRewrite: Optional[bool] = None, + ContentFormats: Optional[str] = None, ) -> Dict[str, Any]: """ 联网搜索 API 调用,支持网页和图片搜索 Args: Query (str): 搜索 query,1~100 个字符 - Count (int): 返回条数,web 最多 50 条,image 最多 5 条 + Count (int): 返回条数;默认 web 为 10 条,image 为 5 条;web 最多 50 条,image 最多 5 条 SearchType (str): 搜索类型,仅支持 web 或 image TimeRange (str): web 搜索时间范围,可选 OneDay/OneWeek/OneMonth/OneYear 或日期区间 AuthLevel (int): 权威等级过滤,0 为默认,1 为非常权威 + NeedContent (bool): 是否返回网页正文,仅支持 web + NeedUrl (bool): 是否返回网页 URL,仅支持 web + Sites (str): 仅搜索指定站点,以 | 分隔,最多 20 个,仅支持 web + BlockHosts (str): 排除指定站点,以 | 分隔,最多 5 个,仅支持 web + Industry (str): 行业搜索,可选 finance、game 或 gov,仅支持 web + QueryRewrite (bool): 是否启用查询改写 + ContentFormats (str): 网页正文格式,可选 text 或 markdown,仅支持 web Returns: 联网搜索结果返回结构 """ @@ -48,22 +62,22 @@ async def web_search( search_type=SearchType, time_range=TimeRange or None, auth_level=AuthLevel, + need_content=NeedContent, + need_url=NeedUrl, + sites=Sites, + block_hosts=BlockHosts, + industry=Industry, + query_rewrite=QueryRewrite, + content_formats=ContentFormats, ) if config.api_key is not None and len(config.api_key) > 0: return await web_search_api_key_auth(config.api_key, req, "web_search") else: return await web_search_volcengine_auth(config.volcengine_ak, config.volcengine_sk, req, "web_search") - except Exception as e: - logger.error(f"Error in web_search tool: {e}") - resp_error = ResponseError( - error=Error( - message=str(e), - type="mcp_server_ask_echo_search_infinity_error", - code="mcp_server_ask_echo_search_infinity_error", - ) - ) - return resp_error.to_dict() + except Exception: + logger.exception("web_search tool failed") + raise def main(): diff --git a/server/mcp_server_askecho_search_infinity/tests/test_model.py b/server/mcp_server_askecho_search_infinity/tests/test_model.py new file mode 100644 index 00000000..3aefd2c9 --- /dev/null +++ b/server/mcp_server_askecho_search_infinity/tests/test_model.py @@ -0,0 +1,74 @@ +import unittest + +from mcp_server_askecho_search_infinity.model import build_web_search_request + + +class BuildWebSearchRequestTest(unittest.TestCase): + def test_web_payload_includes_custom_controls(self): + request = build_web_search_request( + query=" OpenAI ", + count=3, + time_range="OneWeek", + auth_level=1, + need_content=True, + need_url=False, + sites="openai.com | example.com", + block_hosts="spam.example", + industry="finance", + query_rewrite=True, + content_formats="markdown", + ) + + self.assertEqual( + request.to_payload(), + { + "Query": "OpenAI", + "SearchType": "web", + "Count": 3, + "Filter": { + "AuthInfoLevel": 1, + "NeedContent": True, + "NeedUrl": False, + "Sites": "openai.com|example.com", + "BlockHosts": "spam.example", + "Industry": "finance", + }, + "TimeRange": "OneWeek", + "QueryControl": {"QueryRewrite": True}, + "ContentFormats": "markdown", + }, + ) + self.assertNotIn("NeedSummary", request.to_payload()) + + def test_image_uses_image_default_count(self): + request = build_web_search_request(query="mountain", search_type="image") + + self.assertEqual( + request.to_payload(), + {"Query": "mountain", "SearchType": "image", "Count": 5}, + ) + + def test_image_rejects_web_only_controls(self): + with self.assertRaisesRegex(ValueError, "仅支持 web 搜索"): + build_web_search_request( + query="mountain", + search_type="image", + need_content=True, + ) + + def test_host_lists_enforce_documented_limits(self): + sites = "|".join(f"site-{index}.example" for index in range(21)) + + with self.assertRaisesRegex(ValueError, "Sites 最多支持 20 个域名"): + build_web_search_request(query="OpenAI", sites=sites) + + def test_invalid_custom_values_are_rejected(self): + with self.assertRaisesRegex(ValueError, "Industry"): + build_web_search_request(query="OpenAI", industry="news") + + with self.assertRaisesRegex(ValueError, "ContentFormats"): + build_web_search_request(query="OpenAI", content_formats="html") + + +if __name__ == "__main__": + unittest.main() diff --git a/server/mcp_server_askecho_search_infinity/uv.lock b/server/mcp_server_askecho_search_infinity/uv.lock index f8f2392e..dc1208eb 100644 --- a/server/mcp_server_askecho_search_infinity/uv.lock +++ b/server/mcp_server_askecho_search_infinity/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.12, <3.14" [[package]] @@ -116,6 +116,43 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4f/52/34c6cf5bb9285074dc3531c437b3919e825d976fde097a7a73f79e726d03/certifi-2025.7.14-py3-none-any.whl", hash = "sha256:6b31f564a415d79ee77df69d757bb49a5bb53bd9f756cbbe24394ffd6fc1f4b2", size = 162722, upload-time = "2025-07-14T03:29:26.863Z" }, ] +[[package]] +name = "cffi" +version = "2.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9e/ef/008a1939e372c06329a3fce4279c02f328488f3526744906eeec3da7ad5f/cffi-2.1.1.tar.gz", hash = "sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be", size = 530807, upload-time = "2026-08-03T21:21:18.939Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/69/43965eccfdead3b9220015fd1320e117be8c6ed01a62ffab76eeb752f5d5/cffi-2.1.1-cp312-cp312-macosx_10_15_x86_64.whl", hash = "sha256:c8c69575568085ba0b1b10c0249d779a214aea6f6522e949a0fc9fb0fcb449d0", size = 184821, upload-time = "2026-08-03T21:19:44.887Z" }, + { url = "https://files.pythonhosted.org/packages/54/7d/16e5a096677b5e313ca80cd5e5170efa3ea44624a82bb111925522da64b1/cffi-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f81b3b8f3d4e343550fa4baa0e479bba9f2d29ce9c2e9b51d1ce1718d7442fcf", size = 184719, upload-time = "2026-08-03T21:19:46.129Z" }, + { url = "https://files.pythonhosted.org/packages/56/e6/8941622732edec876dd17d0453dce07317ae96db34f2ec1436c9d3785986/cffi-2.1.1-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:811bd1e21d32de12efca32393a0ab3f5133b54fce9bd44b8bd77ab07da14bf6a", size = 214799, upload-time = "2026-08-03T21:19:47.218Z" }, + { url = "https://files.pythonhosted.org/packages/44/de/f98430906df1545ffde0d543dd124a7a439bc2cd32b36b9c53f805df7333/cffi-2.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:68e62fe11f30d5ca8289242866f0a5291402d8529ca2178ab8afc5c9694ae890", size = 222389, upload-time = "2026-08-03T21:19:48.331Z" }, + { url = "https://files.pythonhosted.org/packages/6a/5b/717f1526b9957b34456313c31645c5b82b8fb5c3fe9e4752999be7128bfc/cffi-2.1.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:4a7c934f7360e8cd64fe9efadcbd10c7c6364f531e432b9a4bf5ccbc9e0e8b50", size = 210249, upload-time = "2026-08-03T21:19:49.543Z" }, + { url = "https://files.pythonhosted.org/packages/64/b3/f8aa4f3e34986c7e4ec45072d1b1b9dd295b6b18007b45518d79726dd725/cffi-2.1.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:3143d81e29e1e20a9ce10901ec369012947876596f75a222235965f2b7ae832e", size = 208775, upload-time = "2026-08-03T21:19:50.918Z" }, + { url = "https://files.pythonhosted.org/packages/b1/db/dceb9dd5b231e1da801793f8acc9f3c52a7e1afe40bb1aae37e02b0faad5/cffi-2.1.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c1453022f490d2459a11819d83ad1d586e9ff65a12ac3e705ffebd46d3685dcf", size = 221822, upload-time = "2026-08-03T21:19:52.054Z" }, + { url = "https://files.pythonhosted.org/packages/a0/d2/6cd24ae3be000a634109c247d1475d62e5616d0dc78c82770942ec384248/cffi-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:208f941bb9d18e768138677f0a6d2ce01f590df56043dda1df1535ac57c88517", size = 225232, upload-time = "2026-08-03T21:19:53.109Z" }, + { url = "https://files.pythonhosted.org/packages/cb/52/3fa190537004dd7f0ab860a6dc7c0175b8667f68d1e618a46f5498d30250/cffi-2.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:210019b6c7cf07f081b4c54635c8cf744377001350e29cc0f81c4377b4797735", size = 223597, upload-time = "2026-08-03T21:19:54.515Z" }, + { url = "https://files.pythonhosted.org/packages/80/fb/0bb75b7039588c074b37ae99f40d9bfddf990ecb2fbc346ebccd2e56b9be/cffi-2.1.1-cp312-cp312-win32.whl", hash = "sha256:046bfc24911b37851ee1b51aab8bffe713d89c68c6a057b09484ce9fd5f69b4e", size = 175292, upload-time = "2026-08-03T21:19:55.566Z" }, + { url = "https://files.pythonhosted.org/packages/d9/79/615cc094e2fb508cade7de88d3b4f6c4ec2bab695c97bce9153dc65aadf5/cffi-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:f53e442b08449d42821fa4a4fba000095af9f62742a500f978a9f557ec44339a", size = 185919, upload-time = "2026-08-03T21:19:56.89Z" }, + { url = "https://files.pythonhosted.org/packages/70/c6/d0ea84713fe46b243a436a18fcd47d639732747e21635c8a27191b06dc30/cffi-2.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:7bde5e4cc5c10140859842b9d383af292b22639a4dffb725314baf45968cef80", size = 180093, upload-time = "2026-08-03T21:19:58.155Z" }, + { url = "https://files.pythonhosted.org/packages/9d/f4/035513d4117049066b4779dc3b7c0c0fdad175fa13731c9f4003f1cd1478/cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:b5bdfd1c873d4e093aabc0ca84c4ca6dbc4f752afb5c86f146d9742580c9da2e", size = 194248, upload-time = "2026-08-03T21:19:59.399Z" }, + { url = "https://files.pythonhosted.org/packages/76/af/2aeb4dbb5fc41a04161ae9ff1518de7cec08e164f44a8ce6a4cf7fd2cd1d/cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:31348097ff5bbe827ccc41795d4dd099d9f0625e7def00ee653c137a490c2a6c", size = 196908, upload-time = "2026-08-03T21:20:00.746Z" }, + { url = "https://files.pythonhosted.org/packages/a7/46/2e5fdde8555706dd98139a910ca11be02809f3f605ce956f655d0214e100/cffi-2.1.1-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:9d2055050ea716bd38b7f7f1579c275386646b4894c155a3e2f3cd62ed41b7c6", size = 184805, upload-time = "2026-08-03T21:20:02.02Z" }, + { url = "https://files.pythonhosted.org/packages/55/41/4c7042f317b9217502988f0873af87e16ad606dc20f84e546e3e6ce9764c/cffi-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19ee6127ee34de7d83ce3d371ebc5ed91addbdcc39f9ab15ce4eb35a4e534971", size = 184764, upload-time = "2026-08-03T21:20:03.141Z" }, + { url = "https://files.pythonhosted.org/packages/43/1f/1c3d90d91811c8f86ced9ed637956c54bfe5b79ca98fe976d7f8c8979f6b/cffi-2.1.1-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:6a8dddef476fab96d066d578fc88526767b836ab5ab21754e1d5bf3879c31c7c", size = 214722, upload-time = "2026-08-03T21:20:04.377Z" }, + { url = "https://files.pythonhosted.org/packages/37/6f/3b5ce4c3b2192d250f04908f2bfd91ef34552ec8f7716a5d4abdb8d67bb2/cffi-2.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f16c709686a78c727bbbf059f92b0bf41c6fc60deec706d2dc19f529175a6125", size = 222369, upload-time = "2026-08-03T21:20:05.544Z" }, + { url = "https://files.pythonhosted.org/packages/02/10/4b3c75dde3d9663c9e02ba05c2668b954f671d4bbe346413ca8c696b295a/cffi-2.1.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:fcd22650c908d7b7da162bbfaab594a1227a15d1643a98c68b122ac642fa2264", size = 210175, upload-time = "2026-08-03T21:20:06.75Z" }, + { url = "https://files.pythonhosted.org/packages/df/62/14f74b9543e605d17701dc797b815958b8bb70b7624ce1b832ddad48ed6c/cffi-2.1.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:aa9511c62d14da7aacc9b4bf51f3f697a621e83b2d6919008243c3aad168eea3", size = 208670, upload-time = "2026-08-03T21:20:08.04Z" }, + { url = "https://files.pythonhosted.org/packages/95/95/86342356ff5953b3fb06f7ef7c5bee212d45e770abc7218d451b9148313c/cffi-2.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a931079504ecc49efed7744c476a5c343a92fabf66dec2db95edb1b2fdc770e2", size = 221824, upload-time = "2026-08-03T21:20:09.274Z" }, + { url = "https://files.pythonhosted.org/packages/eb/ff/7b3429ff53aafe931ed8a5fc69f481bbef7ba6de87ddcbb63d08f483f613/cffi-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a2d7755bef5a12ed488f4ef1f1b69ee9191d7396083b755a5d2295f6edb4768b", size = 225148, upload-time = "2026-08-03T21:20:10.7Z" }, + { url = "https://files.pythonhosted.org/packages/34/34/a95870b9221e09cf4f2ce3178b1a210abdfe63a1bd357da940418d7b8d15/cffi-2.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e0bcb7e0f677f543555d2adff3bf19c05f66cdb4796e5ff602442ab2fe3c4ef7", size = 223564, upload-time = "2026-08-03T21:20:12.165Z" }, + { url = "https://files.pythonhosted.org/packages/70/ea/839b50531021a647fb5e929f72cf97bc1ff702b5472166164b5b6e76b851/cffi-2.1.1-cp313-cp313-win32.whl", hash = "sha256:334644fbac4eff73d985a17a91226df55d0f394160c4cfb880e084c8f7161cac", size = 175263, upload-time = "2026-08-03T21:20:13.559Z" }, + { url = "https://files.pythonhosted.org/packages/60/a6/8b149b2c3f2e11aaa1618ef64500b45f50f22c57a977a4dff1aff1f91042/cffi-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:1aa5645c30469b09530c4ebca77ebf8f17618293c58f8549cb1a543a50236e7d", size = 185688, upload-time = "2026-08-03T21:20:14.69Z" }, + { url = "https://files.pythonhosted.org/packages/01/9a/11f687cb39d6a3504060d5242f04f48c735afb4d3d533958a20594890cb2/cffi-2.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:63bbfd5ded17c4840ac07cd8f1c21ba9d9708141f840b324f422f41b207e3973", size = 180078, upload-time = "2026-08-03T21:20:15.917Z" }, +] + [[package]] name = "click" version = "8.2.1" @@ -137,6 +174,43 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] +[[package]] +name = "cryptography" +version = "50.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/de/41/6cbdcf9142d00fe82836fbb51e503e58088575cf7a0fe1dbff6695bf0840/cryptography-50.0.0.tar.gz", hash = "sha256:eeac2acb5a20ed25e0ad6d1df9891a520b78b404266b6d11778f25d5d691a6c9", size = 880201, upload-time = "2026-07-31T14:25:10.11Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/5c/59086b4aac5e879d38ddbcf74e4be7ade89cebc3eb199a55da998c3bb46a/cryptography-50.0.0-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:031e2d5dd4bb9caa3ca9c82e5a197fd8ae680232cee62603d1a813f3f07e3d03", size = 4001252, upload-time = "2026-07-31T14:23:33.331Z" }, + { url = "https://files.pythonhosted.org/packages/57/ef/8f2df13c7216bcad3e1c74e07f6e193d93e998e114f524a53877c9af27ad/cryptography-50.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fd9192b7b70c573d7f214eb1ae35e00d359f6f5e4b27c7e21e30de1fc6204645", size = 4719554, upload-time = "2026-07-31T14:23:35.611Z" }, + { url = "https://files.pythonhosted.org/packages/d9/41/029086c34d91052fc3b88bcc8056f709a7c915c7a23b235a54eb800b1c97/cryptography-50.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:06a32a980526a6ab9a4b9bf8f7385800791e2bb960903cb6b530e4817509a3b7", size = 4702130, upload-time = "2026-07-31T14:23:37.635Z" }, + { url = "https://files.pythonhosted.org/packages/7d/ff/b6ce0954962e7f7b969f850a883744197bb3910bdfd7b6da162eab7d9f68/cryptography-50.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:a1b30560f2acc95aa8b2e06e716a13dbfc97314747b80d9707e307f77b40d6b3", size = 4725244, upload-time = "2026-07-31T14:23:39.471Z" }, + { url = "https://files.pythonhosted.org/packages/06/1e/63a1027cb7fec360a182208e1b7767d5aa1fe57be3d6aa856e69a321edc0/cryptography-50.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:8d89f3976b10b4ce31118de72329025f70d2c6ead14a8217c5514dd2c6d5a78f", size = 5342265, upload-time = "2026-07-31T14:23:41.286Z" }, + { url = "https://files.pythonhosted.org/packages/6b/72/a1116d683a6d7ece94590013882515de087edf9ef0e6292aae615a44df73/cryptography-50.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:b42a28c1844fd9de8f3f7d540e36b66f3a9c83fceac7170ebc7a6a19edd9dcae", size = 4734609, upload-time = "2026-07-31T14:23:43.139Z" }, + { url = "https://files.pythonhosted.org/packages/15/37/36a9c479bbe49acea2636c7fd3360d20f7b7e079c300352011c44850b181/cryptography-50.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:900131fafd8aead39ac7dd3a7e833be754c17a95cfd91221636949fe4eb0aa8a", size = 4356517, upload-time = "2026-07-31T14:23:44.939Z" }, + { url = "https://files.pythonhosted.org/packages/32/98/8a151d64367204cbc63ec65d37502f1d9c53cf4bfc6ec3c532614dbec60d/cryptography-50.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:07949c449a1abcf60d1ee6e88956d89404c7df3c8258f46589e912988e551987", size = 4724529, upload-time = "2026-07-31T14:23:46.93Z" }, + { url = "https://files.pythonhosted.org/packages/22/f6/ec13b470172126464a86bf54d2294a46d29837fc51ba3e45d4047946fb5e/cryptography-50.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:f89831ef99dd7dd169ab06d63a831adb9e20a87aac6d380266bbda5823349169", size = 5299852, upload-time = "2026-07-31T14:23:48.851Z" }, + { url = "https://files.pythonhosted.org/packages/da/3a/f05e32c99d440c9bb891ea0e36c9091891e36be5a9a87ab2ee6ea20729f6/cryptography-50.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:82148ec5bddac30b51a5b3c1945075f896fa022cb93f8e4a01e9f6ee95292c5f", size = 4734462, upload-time = "2026-07-31T14:23:50.861Z" }, + { url = "https://files.pythonhosted.org/packages/ca/dc/bd72b26be8953f80625f63151efd38eee71c76ca6cf591c08ff34615a79e/cryptography-50.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1489e263a8048bb8b6a8bac662eb2d402ea5d2b7b4699b72f385f1e2772db105", size = 4852708, upload-time = "2026-07-31T14:23:52.715Z" }, + { url = "https://files.pythonhosted.org/packages/27/20/c930314a2ab476d15dec966ec87e2e9637bb02b06106b12c0396c57bb603/cryptography-50.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7cec5b856506da6defb290f30c9ee687d5f5e8cb0bd3f6459dde43b0b4fa40ef", size = 5004179, upload-time = "2026-07-31T14:23:54.887Z" }, + { url = "https://files.pythonhosted.org/packages/32/2e/c9db68a0c4bfa28e310707527c0ee3a2bd254104d2e02e68f368e197aa4c/cryptography-50.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:bd1c592e4d5974f0d08d4888e432157adba757c66da0246918e43677fafa2d30", size = 3840395, upload-time = "2026-07-31T14:23:56.677Z" }, + { url = "https://files.pythonhosted.org/packages/03/37/73d005be173aff344af30e9fd2a576575cb2391a7101d9cd3842e1fa8cce/cryptography-50.0.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ccdc4a71a4dabae05de219404f9f4abc38e3b58422177ff93d0da05967dafa07", size = 4036009, upload-time = "2026-07-31T14:24:24.122Z" }, + { url = "https://files.pythonhosted.org/packages/ff/c6/7a6202a534e32103a285b7834a120869557fe198d51d7cfe59754c8bda9c/cryptography-50.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:910e1d2668e7de9648f2bcee30e180db2a6b15c30f887d7c4c93ddf96e3992e3", size = 4745252, upload-time = "2026-07-31T14:24:26.118Z" }, + { url = "https://files.pythonhosted.org/packages/85/4f/0fa8c2f4428198f15d9ff8d63400e27afbf94ce833f6108da1eb3753f945/cryptography-50.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a91296cb61e8df6f86d0c19cc4068228da256bf59bf86049fbd821084565327f", size = 4728939, upload-time = "2026-07-31T14:24:27.994Z" }, + { url = "https://files.pythonhosted.org/packages/d1/63/54dd723490ba2dc09b299682c10b38db38f159728bcaae8c591b8af2f22d/cryptography-50.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e722f16708d854fe924790e051061f6704a472c3bac347b6fd88033ea8dd0dc5", size = 4748483, upload-time = "2026-07-31T14:24:30.254Z" }, + { url = "https://files.pythonhosted.org/packages/1d/dd/7c77d26285cc7f6991efce64a0f5b4f9383bfa5dd8c5033003eaf7db4cdb/cryptography-50.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:d764dcf130c428ef66786f866dd750f53182bc608813489915e9fc106bb0c82f", size = 5367599, upload-time = "2026-07-31T14:24:32.457Z" }, + { url = "https://files.pythonhosted.org/packages/46/c9/f60aed34c013f317f92817b6c171c2d22a78270fa41109bd4b08af26b194/cryptography-50.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:105110f43a471dbd0060b9c9516cb8a6a79233631a04cc2ba16f28323ac6e025", size = 4762647, upload-time = "2026-07-31T14:24:34.599Z" }, + { url = "https://files.pythonhosted.org/packages/be/f3/f9a0173b139372c3a48ed98154b45cc6b9de17c789d5ab552e621c293609/cryptography-50.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:828743d939e9629bc267b8e2d08d8bb67cd4319c771a33d4b18b22dd8fb7440a", size = 4385197, upload-time = "2026-07-31T14:24:36.647Z" }, + { url = "https://files.pythonhosted.org/packages/d8/36/83bb81f6e569bc38e1e4a7bc80f29b46bb9601920bc455fc8e888f5d5742/cryptography-50.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:2a8183b489dc1f7f80f135780fadc1108f14b31b8a40411c7a5b17425f65f28b", size = 4748095, upload-time = "2026-07-31T14:24:39.493Z" }, + { url = "https://files.pythonhosted.org/packages/6b/16/d3008eff98c764979865834c3d386d4fd041b5f52e7f34fc29ac1a5eb515/cryptography-50.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:6e7d61120573a7f2cd94cc095f9e81f6967c61ccdf194285aa143ecec8e0b708", size = 5325948, upload-time = "2026-07-31T14:24:41.556Z" }, + { url = "https://files.pythonhosted.org/packages/9c/f8/d97f9603efda3888187bfdb893f26c41be4735c10631d05d284ee6b047c4/cryptography-50.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:37fdb0d0111f1e2ff07139dfb79f1b49531f8e213c46f1163dd7642979b58c47", size = 4762400, upload-time = "2026-07-31T14:24:43.636Z" }, + { url = "https://files.pythonhosted.org/packages/64/a2/4615c8f7d81a00b1d6e6afe19f694e1543582349fb5f4076f6cb5dc36485/cryptography-50.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87f62a3d3b9888ed0fdde100ec06aa61ca9cd44bad9057d1dff9a516b5f5bb9", size = 4878208, upload-time = "2026-07-31T14:24:45.522Z" }, + { url = "https://files.pythonhosted.org/packages/d2/1a/efcfb02f91407149a0dacffffab791f7e19bf6385f63b3666dc8b5e5c9c8/cryptography-50.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:65c2c3add92b45fd0709db8594536aea39c2a67af0e27ffcf049c498501140b7", size = 5037050, upload-time = "2026-07-31T14:24:47.697Z" }, + { url = "https://files.pythonhosted.org/packages/57/30/4a22984d4f1bdfb8c054f07a92bc176b97a3134cc1d6c4b3bffb1f3688b4/cryptography-50.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:d24fead1d4d076e1bfb006dcec392074a3cd8d7b4fc8a595aa64073b2b7a96ba", size = 3874135, upload-time = "2026-07-31T14:24:50.085Z" }, +] + [[package]] name = "frozenlist" version = "1.7.0" @@ -281,7 +355,7 @@ wheels = [ [[package]] name = "mcp" -version = "1.12.2" +version = "1.29.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, @@ -290,20 +364,23 @@ dependencies = [ { name = "jsonschema" }, { name = "pydantic" }, { name = "pydantic-settings" }, + { name = "pyjwt", extra = ["crypto"] }, { name = "python-multipart" }, { name = "pywin32", marker = "sys_platform == 'win32'" }, { name = "sse-starlette" }, { name = "starlette" }, + { name = "typing-extensions" }, + { name = "typing-inspection" }, { name = "uvicorn", marker = "sys_platform != 'emscripten'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/66/85/f36d538b1286b7758f35c1b69d93f2719d2df90c01bd074eadd35f6afc35/mcp-1.12.2.tar.gz", hash = "sha256:a4b7c742c50ce6ed6d6a6c096cca0e3893f5aecc89a59ed06d47c4e6ba41edcc", size = 426202, upload-time = "2025-07-24T18:29:05.175Z" } +sdist = { url = "https://files.pythonhosted.org/packages/30/d3/f9acc21dfc886e4f78e2add1a47db46ce16884346afde53f8a064c02c891/mcp-1.29.0.tar.gz", hash = "sha256:52d01f334de1868cc3bb2d6604931126a67631f99a6c5d3b82ba47290315ec36", size = 643148, upload-time = "2026-07-28T13:41:41.939Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/cf/3fd38cfe43962452e4bfadc6966b2ea0afaf8e0286cb3991c247c8c33ebd/mcp-1.12.2-py3-none-any.whl", hash = "sha256:b86d584bb60193a42bd78aef01882c5c42d614e416cbf0480149839377ab5a5f", size = 158473, upload-time = "2025-07-24T18:29:03.419Z" }, + { url = "https://files.pythonhosted.org/packages/01/c8/248b201f6d753d69fd5d6506011abbb35a946d9142b2ae311a948fd0be3d/mcp-1.29.0-py3-none-any.whl", hash = "sha256:f5a075bb611f23d6f4d080c6a1699fa62772eebc562ba9e66b306ddde1c755f7", size = 223436, upload-time = "2026-07-28T13:41:40.337Z" }, ] [[package]] name = "mcp-server-askecho-search-infinity" -version = "0.1.0" +version = "0.2.0" source = { editable = "." } dependencies = [ { name = "aiohttp" }, @@ -313,7 +390,7 @@ dependencies = [ [package.metadata] requires-dist = [ { name = "aiohttp", specifier = ">=3.9.0" }, - { name = "mcp", specifier = ">=1.9.4" }, + { name = "mcp", specifier = ">=1.29.0,<2.0.0" }, ] [[package]] @@ -436,6 +513,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cc/35/cc0aaecf278bb4575b8555f2b137de5ab821595ddae9da9d3cd1da4072c7/propcache-0.3.2-py3-none-any.whl", hash = "sha256:98f1ec44fb675f5052cccc8e609c46ed23a35a1cfd18545ad4e29002d858a43f", size = 12663, upload-time = "2025-06-09T22:56:04.484Z" }, ] +[[package]] +name = "pycparser" +version = "3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, +] + [[package]] name = "pydantic" version = "2.11.7" @@ -507,6 +593,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/58/f0/427018098906416f580e3cf1366d3b1abfb408a0652e9f31600c24a1903c/pydantic_settings-2.10.1-py3-none-any.whl", hash = "sha256:a60952460b99cf661dc25c29c0ef171721f98bfcb52ef8d9ea4c943d7c8cc796", size = 45235, upload-time = "2025-06-24T13:26:45.485Z" }, ] +[[package]] +name = "pyjwt" +version = "2.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/81/58d0ac84e1ef3a3843791d6954d94c0b33d526c75eeb1efbce9d0a4c4077/pyjwt-2.13.0.tar.gz", hash = "sha256:41571c89ca91598c79e8ef18a2d07367d4810fbbd6f637794879baf1b7703423", size = 107515, upload-time = "2026-05-21T19:54:36.618Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/5e/ecf12fdb62546d64385c158514e9b2b671f7832108ef2ecd2020ce0af2d1/pyjwt-2.13.0-py3-none-any.whl", hash = "sha256:66adcc2aff09b3f1bbd95fc1e1577df8ac8723c978552fd43304c8a290ac5728", size = 31274, upload-time = "2026-05-21T19:54:35.362Z" }, +] + +[package.optional-dependencies] +crypto = [ + { name = "cryptography" }, +] + [[package]] name = "python-dotenv" version = "1.1.1"