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.
This commit is contained in:
ThomasTaroni 2025-06-21 20:17:59 +02:00
parent 1554d5e4ab
commit 8eda903185
2 changed files with 21 additions and 27 deletions

View file

@ -10,4 +10,6 @@ pydantic>=2.3.0
# Utility dependencies # Utility dependencies
loguru>=0.7.0 loguru>=0.7.0
requests~=2.32.3 requests~=2.32.3
aiohttp~=3.11.18
asyncio~=3.4.3

View file

@ -7,6 +7,8 @@ to conduct research and generate reports via the MCP protocol.
import os import os
import logging import logging
import aiohttp
import asyncio
import requests import requests
from dotenv import load_dotenv from dotenv import load_dotenv
from mcp.server.fastmcp import FastMCP from mcp.server.fastmcp import FastMCP
@ -24,30 +26,24 @@ logger = logging.getLogger(__name__)
# Initialize FastMCP server # Initialize FastMCP server
mcp = FastMCP("SMD Researcher", host="0.0.0.0", port=8000, timeout_keep_alive=720) mcp = FastMCP("SMD Researcher", host="0.0.0.0", port=8000, timeout_keep_alive=720)
async def smd_detail_article(article_id: str) -> dict: async def smd_detail_article(article_id):
"""
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
"""
url = f"https://api.swissdox.ch/api/documents/{article_id}" url = f"https://api.swissdox.ch/api/documents/{article_id}"
headers = { headers = {
"authorization": f"Bearer {os.getenv('SWISSDOX_BEARER_TOKEN', '')}", "authorization": f"Bearer {os.getenv('SWISSDOX_BEARER_TOKEN', '')}",
"content-type": "application/json", "content-type": "application/json",
} }
payload = {"filters": [], "pagination": {"pageSize": 1, "currentPage": 1}} payload = {"filters": [], "pagination": {"pageSize": 1, "currentPage": 1}}
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 200: async with aiohttp.ClientSession() as session:
return response.json() async with session.get(url, headers=headers, payload=payload) as response:
else: if response.status == 200:
return { return await response.json() # JSON asynchron lesen
"message": response.text else:
} return {
"message": await response.text(),
"article_id": article_id
}
@mcp.tool() @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: 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: if response.status_code == 200:
result = response.json() result = response.json()
# Artikel-Liste aus der `data`-Struktur der Antwort
articles = result.get("data", []) articles = result.get("data", [])
# Verschachtelte JSON-Resultate von `smd_detail_article` sammeln tasks = []
detailed_articles = []
for article in articles: for article in articles:
article_id = article.get("id") article_id = article.get("id")
if article_id: if article_id:
detailed_result = smd_detail_article(article_id) tasks.append(smd_detail_article(article_id))
detailed_articles.append(detailed_result) detailed_articles = await asyncio.gather(*tasks)
# Gesamtantwort mit kombinierter JSON-Struktur
return { return {
"search_result": result, "original_result": result,
"detailed_articles": detailed_articles "detailed_articles": detailed_articles
} }
else: else: