From 8eda9031859db97e31197a724f33f6ac3a4817dd Mon Sep 17 00:00:00 2001 From: ThomasTaroni Date: Sat, 21 Jun 2025 20:17:59 +0200 Subject: [PATCH] Switch to aiohttp for async HTTP requests in server logic Replaced synchronous requests with aiohttp to enable non-blocking, async HTTP requests. Updated `smd_detail_article` and `smd_research` to utilize asyncio for parallel execution, significantly improving efficiency for handling multiple API calls. Added aiohttp and asyncio dependencies to requirements.txt. --- requirements.txt | 4 ++- src/phoenix_technologies/smd/server.py | 44 +++++++++++--------------- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/requirements.txt b/requirements.txt index bf0dfdc..486c004 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,4 +10,6 @@ pydantic>=2.3.0 # Utility dependencies loguru>=0.7.0 -requests~=2.32.3 \ No newline at end of file +requests~=2.32.3 +aiohttp~=3.11.18 +asyncio~=3.4.3 \ No newline at end of file diff --git a/src/phoenix_technologies/smd/server.py b/src/phoenix_technologies/smd/server.py index fa89fc0..d04f544 100644 --- a/src/phoenix_technologies/smd/server.py +++ b/src/phoenix_technologies/smd/server.py @@ -7,6 +7,8 @@ to conduct research and generate reports via the MCP protocol. import os import logging +import aiohttp +import asyncio import requests from dotenv import load_dotenv from mcp.server.fastmcp import FastMCP @@ -24,30 +26,24 @@ logger = logging.getLogger(__name__) # Initialize FastMCP server mcp = FastMCP("SMD Researcher", host="0.0.0.0", port=8000, timeout_keep_alive=720) -async def smd_detail_article(article_id: str) -> dict: - """ - Get the Details of an article found by the tool smd_research based on the article_id. - Use this tool after smd_research is executed to get all the details of the articles in the result. - - Args: - article_id: The ID of the article to get the details for - - Returns: - String containing the details of the article - """ +async def smd_detail_article(article_id): url = f"https://api.swissdox.ch/api/documents/{article_id}" headers = { "authorization": f"Bearer {os.getenv('SWISSDOX_BEARER_TOKEN', '')}", "content-type": "application/json", } payload = {"filters": [], "pagination": {"pageSize": 1, "currentPage": 1}} - response = requests.post(url, headers=headers, json=payload) - if response.status_code == 200: - return response.json() - else: - return { - "message": response.text - } + + async with aiohttp.ClientSession() as session: + async with session.get(url, headers=headers, payload=payload) as response: + if response.status == 200: + return await response.json() # JSON asynchron lesen + else: + return { + "message": await response.text(), + "article_id": article_id + } + @mcp.tool() async def smd_research(search_query: str = "Bundesrat", date_from: str = "2024-05-30T22:00:00.000Z", date_to: str = "2025-05-31T21:59:59.999Z") -> dict: @@ -99,20 +95,16 @@ async def smd_research(search_query: str = "Bundesrat", date_from: str = "2024-0 if response.status_code == 200: result = response.json() - # Artikel-Liste aus der `data`-Struktur der Antwort articles = result.get("data", []) - # Verschachtelte JSON-Resultate von `smd_detail_article` sammeln - detailed_articles = [] + tasks = [] for article in articles: article_id = article.get("id") if article_id: - detailed_result = smd_detail_article(article_id) - detailed_articles.append(detailed_result) - - # Gesamtantwort mit kombinierter JSON-Struktur + tasks.append(smd_detail_article(article_id)) + detailed_articles = await asyncio.gather(*tasks) return { - "search_result": result, + "original_result": result, "detailed_articles": detailed_articles } else: