refactor: enhance tool outputs by returning formatted markdown and JSON resources for structured display
CI/CD Pipeline / Lint & Check (push) Failing after 10s
CI/CD Pipeline / Build & Push Docker Image (push) Has been skipped

This commit is contained in:
2026-05-12 23:36:37 +02:00
parent 7c089d90c5
commit 40b5d004b1
6 changed files with 319 additions and 52 deletions
+48 -6
View File
@@ -1,6 +1,20 @@
import json
from mcp.server.fastmcp import FastMCP
from mcp.types import TextContent, Annotations, EmbeddedResource, TextResourceContents
from strava_mcp_server.strava_client import StravaClient
def _resource(uri: str, data) -> EmbeddedResource:
return EmbeddedResource(
type="resource",
resource=TextResourceContents(uri=uri, mimeType="application/json", text=json.dumps(data, indent=2)),
annotations=Annotations(audience=["assistant"]),
)
def _user_text(text: str) -> TextContent:
return TextContent(type="text", text=text, annotations=Annotations(audience=["user"]))
def register(mcp: FastMCP, strava: StravaClient) -> None:
@mcp.tool()
async def list_athlete_clubs():
@@ -10,7 +24,7 @@ def register(mcp: FastMCP, strava: StravaClient) -> None:
"""
try:
clubs = await strava.get_athlete_clubs()
return [
data = [
{
"id": c.get("id"),
"name": c.get("name"),
@@ -22,8 +36,18 @@ def register(mcp: FastMCP, strava: StravaClient) -> None:
}
for c in clubs
]
if not data:
md = "### 🏘️ Keine Clubs gefunden."
else:
md = f"### 🏘️ Clubs ({len(data)})\n"
md += "| Name | Sport | Mitglieder | Ort |\n"
md += "|------|-------|------------|-----|\n"
for c in data:
loc = ", ".join(filter(None, [c["city"], c["country"]])) or "N/A"
md += f"| {c['name']} | {c['sport_type'] or 'N/A'} | {c['member_count']} | {loc} |\n"
return [_user_text(md.strip()), _resource("internal://clubs/list", data)]
except Exception as e:
return f"Error fetching clubs: {str(e)}"
return [TextContent(type="text", text=f"Error fetching clubs: {str(e)}")]
@mcp.tool()
async def get_club(club_id: int):
@@ -45,7 +69,7 @@ def register(mcp: FastMCP, strava: StravaClient) -> None:
"""
try:
activities = await strava.get_club_activities(club_id, per_page=limit)
return [
data = [
{
"name": a.get("name"),
"sport_type": a.get("sport_type") or a.get("type"),
@@ -56,8 +80,17 @@ def register(mcp: FastMCP, strava: StravaClient) -> None:
}
for a in activities
]
if not data:
md = "### 🚴 Keine Club-Aktivitäten gefunden."
else:
md = f"### 🚴 Club-Aktivitäten ({len(data)})\n"
md += "| Athlet | Sport | Name | Distanz | Zeit |\n"
md += "|--------|-------|------|---------|------|\n"
for a in data:
md += f"| {a['athlete']} | {a['sport_type']} | {a['name']} | {a['distance']} | {a['moving_time']} |\n"
return [_user_text(md.strip()), _resource(f"internal://clubs/{club_id}/activities", data)]
except Exception as e:
return f"Error fetching club activities: {str(e)}"
return [TextContent(type="text", text=f"Error fetching club activities: {str(e)}")]
@mcp.tool()
async def get_club_members(club_id: int, limit: int = 30):
@@ -68,7 +101,7 @@ def register(mcp: FastMCP, strava: StravaClient) -> None:
"""
try:
members = await strava.get_club_members(club_id, per_page=limit)
return [
data = [
{
"id": m.get("id"),
"name": f"{m.get('firstname')} {m.get('lastname')}",
@@ -77,5 +110,14 @@ def register(mcp: FastMCP, strava: StravaClient) -> None:
}
for m in members
]
if not data:
md = "### 👥 Keine Mitglieder gefunden."
else:
md = f"### 👥 Mitglieder ({len(data)})\n"
md += "| Name | Ort |\n|------|-----|\n"
for m in data:
loc = ", ".join(filter(None, [m["city"], m["country"]])) or "N/A"
md += f"| {m['name']} | {loc} |\n"
return [_user_text(md.strip()), _resource(f"internal://clubs/{club_id}/members", data)]
except Exception as e:
return f"Error fetching club members: {str(e)}"
return [TextContent(type="text", text=f"Error fetching club members: {str(e)}")]