107 lines
3.5 KiB
Python
107 lines
3.5 KiB
Python
"""
|
||
Server Info Tool
|
||
|
||
Exposes server version, capabilities, and metadata as an MCP tool
|
||
so that LLM clients can query the server's current state.
|
||
"""
|
||
|
||
import importlib.metadata
|
||
import os
|
||
from datetime import datetime, timezone
|
||
|
||
from mcp.server.fastmcp import FastMCP
|
||
from mcp.types import EmbeddedResource, TextResourceContents
|
||
|
||
from strava_mcp_server.strava_client import StravaClient
|
||
|
||
|
||
def _get_version() -> str:
|
||
try:
|
||
return importlib.metadata.version("strava-mcp-server-hnrx")
|
||
except importlib.metadata.PackageNotFoundError:
|
||
return "dev"
|
||
|
||
|
||
def register(mcp: FastMCP, strava: StravaClient) -> None:
|
||
|
||
@mcp.tool(
|
||
name="get_server_info",
|
||
description=(
|
||
"Returns metadata about this MCP server instance: version, available tools, "
|
||
"transport mode, and connection status. Call this first to understand the "
|
||
"server's capabilities and current configuration."
|
||
),
|
||
)
|
||
async def get_server_info() -> list:
|
||
version = _get_version()
|
||
transport = os.getenv("MCP_TRANSPORT", "stdio")
|
||
host = os.getenv("HOST", "0.0.0.0")
|
||
port = os.getenv("PORT", "8000")
|
||
has_token = bool(os.getenv("STRAVA_REFRESH_TOKEN"))
|
||
queried_at = datetime.now(timezone.utc).isoformat()
|
||
|
||
# Human-readable summary
|
||
status = (
|
||
"✅ Authenticated" if has_token else "⚠️ Unauthenticated (no REFRESH_TOKEN)"
|
||
)
|
||
endpoint = f"http://{host}:{port}/mcp" if transport == "http" else "stdio"
|
||
|
||
markdown = f"""## Strava MCP Server
|
||
|
||
| Field | Value |
|
||
|---------------|-------------------------------|
|
||
| **Version** | `{version}` |
|
||
| **Transport** | `{transport}` → `{endpoint}` |
|
||
| **Status** | {status} |
|
||
| **Queried** | {queried_at} |
|
||
|
||
### Available Tool Categories
|
||
- 🏃 **Athlete** – Profile, stats, heart rate zones
|
||
- 🚴 **Activities** – List, detail, laps, streams, comments
|
||
- 🏆 **Segments** – Popular segments, starred segments, efforts
|
||
- 🛣️ **Routes** – Athlete routes
|
||
- 🏟️ **Clubs** – Membership, club activities
|
||
- ⚙️ **Gear** – Bikes and shoes with mileage
|
||
|
||
### Quick Links
|
||
- [Repository](https://git.hnrx.net/hnrx/strava-mcp-server)
|
||
- [Website](https://strava-mcp.web.s3.hnrx.net)
|
||
- [PyPI](https://pypi.org/project/strava-mcp-server-hnrx/)
|
||
"""
|
||
|
||
data = {
|
||
"server": "strava-mcp-server-hnrx",
|
||
"version": version,
|
||
"transport": transport,
|
||
"endpoint": endpoint,
|
||
"authenticated": has_token,
|
||
"queried_at": queried_at,
|
||
"tool_categories": [
|
||
"athlete",
|
||
"activities",
|
||
"segments",
|
||
"routes",
|
||
"clubs",
|
||
"gear",
|
||
],
|
||
"links": {
|
||
"repository": "https://git.hnrx.net/hnrx/strava-mcp-server",
|
||
"website": "https://strava-mcp.web.s3.hnrx.net",
|
||
"pypi": "https://pypi.org/project/strava-mcp-server-hnrx/",
|
||
},
|
||
}
|
||
|
||
import json
|
||
|
||
return [
|
||
{"type": "text", "text": markdown},
|
||
EmbeddedResource(
|
||
type="resource",
|
||
resource=TextResourceContents(
|
||
uri="strava://server/info",
|
||
mimeType="application/json",
|
||
text=json.dumps(data, indent=2),
|
||
),
|
||
),
|
||
]
|