strava-activity-mcp-server 0.2.3__py3-none-any.whl → 0.2.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of strava-activity-mcp-server might be problematic. Click here for more details.
- strava_activity_mcp_server/__init__.py +3 -3
- strava_activity_mcp_server/strava_activity_mcp_server.py +100 -13
- {strava_activity_mcp_server-0.2.3.dist-info → strava_activity_mcp_server-0.2.5.dist-info}/METADATA +1 -1
- strava_activity_mcp_server-0.2.5.dist-info/RECORD +8 -0
- strava_activity_mcp_server-0.2.3.dist-info/RECORD +0 -8
- {strava_activity_mcp_server-0.2.3.dist-info → strava_activity_mcp_server-0.2.5.dist-info}/WHEEL +0 -0
- {strava_activity_mcp_server-0.2.3.dist-info → strava_activity_mcp_server-0.2.5.dist-info}/entry_points.txt +0 -0
- {strava_activity_mcp_server-0.2.3.dist-info → strava_activity_mcp_server-0.2.5.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from .strava_activity_mcp_server import mcp
|
|
2
|
-
def main() -> None:
|
|
3
|
-
"""Run the MCP server."""
|
|
1
|
+
from .strava_activity_mcp_server import mcp
|
|
2
|
+
def main() -> None:
|
|
3
|
+
"""Run the MCP server."""
|
|
4
4
|
mcp.run()
|
|
@@ -118,8 +118,22 @@ async def get_athlete_stats(
|
|
|
118
118
|
code: str,
|
|
119
119
|
client_id: int | None = None,
|
|
120
120
|
client_secret: str | None = None,
|
|
121
|
+
after: int | None = None,
|
|
122
|
+
before: int | None = None,
|
|
123
|
+
page: int | None = None,
|
|
124
|
+
per_page: int | None = None,
|
|
121
125
|
) -> dict:
|
|
122
|
-
"""Exchange an authorization code for access + refresh tokens and get athlete activities.
|
|
126
|
+
"""Exchange an authorization code for access + refresh tokens and get athlete activities with optional filters.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
code: Authorization code from Strava OAuth
|
|
130
|
+
client_id: Strava client ID
|
|
131
|
+
client_secret: Strava client secret
|
|
132
|
+
after: An epoch timestamp to use for filtering activities that have taken place after a certain time
|
|
133
|
+
before: An epoch timestamp to use for filtering activities that have taken place before a certain time
|
|
134
|
+
page: The page of activities (default=1)
|
|
135
|
+
per_page: How many activities per page (default=30)
|
|
136
|
+
"""
|
|
123
137
|
if not code:
|
|
124
138
|
return {"error": "authorization code is required"}
|
|
125
139
|
|
|
@@ -178,7 +192,24 @@ async def get_athlete_stats(
|
|
|
178
192
|
|
|
179
193
|
# return {"tokens": tokens, "access_token": access_token, "refresh_token": refresh_token}
|
|
180
194
|
|
|
181
|
-
|
|
195
|
+
# Build URL with query parameters
|
|
196
|
+
params = []
|
|
197
|
+
if after is not None:
|
|
198
|
+
params.append(f"after={after}")
|
|
199
|
+
if before is not None:
|
|
200
|
+
params.append(f"before={before}")
|
|
201
|
+
if page is not None:
|
|
202
|
+
params.append(f"page={page}")
|
|
203
|
+
if per_page is not None:
|
|
204
|
+
params.append(f"per_page={per_page}")
|
|
205
|
+
|
|
206
|
+
# Default per_page to 30 if not specified (Strava API default)
|
|
207
|
+
if per_page is None:
|
|
208
|
+
params.append("per_page=30")
|
|
209
|
+
|
|
210
|
+
query_string = "&".join(params) if params else ""
|
|
211
|
+
url = f"https://www.strava.com/api/v3/athlete/activities?{query_string}"
|
|
212
|
+
|
|
182
213
|
headers = {
|
|
183
214
|
"accept": "application/json",
|
|
184
215
|
"authorization": f"Bearer {access_token}"
|
|
@@ -196,15 +227,44 @@ async def get_athlete_stats(
|
|
|
196
227
|
"save": save_result
|
|
197
228
|
}
|
|
198
229
|
|
|
199
|
-
return response.json()
|
|
200
|
-
|
|
201
230
|
@mcp.tool("strava://athlete/stats-with-token")
|
|
202
|
-
async def get_athlete_stats_with_token(
|
|
203
|
-
|
|
231
|
+
async def get_athlete_stats_with_token(
|
|
232
|
+
access_token: str,
|
|
233
|
+
after: int | None = None,
|
|
234
|
+
before: int | None = None,
|
|
235
|
+
page: int | None = None,
|
|
236
|
+
per_page: int | None = None
|
|
237
|
+
) -> dict:
|
|
238
|
+
"""Get athlete activities using an existing access token with optional filters.
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
access_token: Strava access token
|
|
242
|
+
after: An epoch timestamp to use for filtering activities that have taken place after a certain time
|
|
243
|
+
before: An epoch timestamp to use for filtering activities that have taken place before a certain time
|
|
244
|
+
page: The page of activities (default=1)
|
|
245
|
+
per_page: How many activities per page (default=30)
|
|
246
|
+
"""
|
|
204
247
|
if not access_token:
|
|
205
248
|
return {"error": "access token is required"}
|
|
206
249
|
|
|
207
|
-
|
|
250
|
+
# Build URL with query parameters
|
|
251
|
+
params = []
|
|
252
|
+
if after is not None:
|
|
253
|
+
params.append(f"after={after}")
|
|
254
|
+
if before is not None:
|
|
255
|
+
params.append(f"before={before}")
|
|
256
|
+
if page is not None:
|
|
257
|
+
params.append(f"page={page}")
|
|
258
|
+
if per_page is not None:
|
|
259
|
+
params.append(f"per_page={per_page}")
|
|
260
|
+
|
|
261
|
+
# Default per_page to 30 if not specified (Strava API default)
|
|
262
|
+
if per_page is None:
|
|
263
|
+
params.append("per_page=30")
|
|
264
|
+
|
|
265
|
+
query_string = "&".join(params) if params else ""
|
|
266
|
+
url = f"https://www.strava.com/api/v3/athlete/activities?{query_string}"
|
|
267
|
+
|
|
208
268
|
headers = {
|
|
209
269
|
"accept": "application/json",
|
|
210
270
|
"authorization": f"Bearer {access_token}"
|
|
@@ -219,7 +279,12 @@ async def get_athlete_stats_with_token(access_token: str) -> dict:
|
|
|
219
279
|
except Exception as e:
|
|
220
280
|
return {"error": "API request failed", "status_code": response.status_code, "response": response.text, "error": str(e)}
|
|
221
281
|
|
|
222
|
-
|
|
282
|
+
activities_data = response.json()
|
|
283
|
+
return {
|
|
284
|
+
activities_data,
|
|
285
|
+
"count": len(activities_data) if isinstance(activities_data, list) else 0,
|
|
286
|
+
"status": "success"
|
|
287
|
+
}
|
|
223
288
|
|
|
224
289
|
@mcp.tool("strava://auth/save")
|
|
225
290
|
async def save_tokens(tokens: dict | None = None) -> dict:
|
|
@@ -241,8 +306,24 @@ async def load_tokens() -> dict:
|
|
|
241
306
|
return {"ok": True, "tokens": result.get("tokens"), "path": result.get("path")}
|
|
242
307
|
|
|
243
308
|
@mcp.tool("strava://athlete/refresh-and-stats")
|
|
244
|
-
async def refresh_and_get_stats(
|
|
245
|
-
|
|
309
|
+
async def refresh_and_get_stats(
|
|
310
|
+
client_id: int | None = None,
|
|
311
|
+
client_secret: str | None = None,
|
|
312
|
+
after: int | None = None,
|
|
313
|
+
before: int | None = None,
|
|
314
|
+
page: int | None = None,
|
|
315
|
+
per_page: int | None = None
|
|
316
|
+
) -> dict:
|
|
317
|
+
"""Load saved refresh token, refresh access token, save it, then fetch activities with optional filters.
|
|
318
|
+
|
|
319
|
+
Args:
|
|
320
|
+
client_id: Strava client ID
|
|
321
|
+
client_secret: Strava client secret
|
|
322
|
+
after: An epoch timestamp to use for filtering activities that have taken place after a certain time
|
|
323
|
+
before: An epoch timestamp to use for filtering activities that have taken place before a certain time
|
|
324
|
+
page: The page of activities (default=1)
|
|
325
|
+
per_page: How many activities per page (default=30)
|
|
326
|
+
"""
|
|
246
327
|
load_result = await load_tokens()
|
|
247
328
|
if not load_result.get("ok"):
|
|
248
329
|
return {"error": "no saved tokens", "details": load_result}
|
|
@@ -262,9 +343,15 @@ async def refresh_and_get_stats(client_id: int | None = None, client_secret: str
|
|
|
262
343
|
if not access_token:
|
|
263
344
|
return {"error": "no access_token after refresh"}
|
|
264
345
|
|
|
265
|
-
# Fetch activities with new token
|
|
266
|
-
activities = await get_athlete_stats_with_token(
|
|
267
|
-
|
|
346
|
+
# Fetch activities with new token and filters
|
|
347
|
+
activities = await get_athlete_stats_with_token(
|
|
348
|
+
access_token=access_token,
|
|
349
|
+
after=after,
|
|
350
|
+
before=before,
|
|
351
|
+
page=page,
|
|
352
|
+
per_page=per_page
|
|
353
|
+
)
|
|
354
|
+
return {activities, "tokens": refreshed}
|
|
268
355
|
|
|
269
356
|
@mcp.tool("strava://session/start")
|
|
270
357
|
async def start_session(client_id: int | None = None, client_secret: str | None = None) -> dict:
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
strava_activity_mcp_server/__init__.py,sha256=NgXC8CeBg0qFRHdZJJKjQlX9_RwSETJ9O6PNy0leOTI,107
|
|
2
|
+
strava_activity_mcp_server/__main__.py,sha256=SAdVoObdjb5UP4MY-Y2_uCXpnthB6hgxlb1KNVNgOrc,58
|
|
3
|
+
strava_activity_mcp_server/strava_activity_mcp_server.py,sha256=okLyst5OnoFFPzMiJwSAHFFyhcoIGNovBmxrUKt9gMc,14638
|
|
4
|
+
strava_activity_mcp_server-0.2.5.dist-info/METADATA,sha256=Btycrm8GjW7S8VIKcNHQ_v2nHaEMFvJudaynisePIGA,7665
|
|
5
|
+
strava_activity_mcp_server-0.2.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
6
|
+
strava_activity_mcp_server-0.2.5.dist-info/entry_points.txt,sha256=F6PO_DBSThhtmX2AC-tu2MIiCJkGi31LCaQJxfUzZ5g,79
|
|
7
|
+
strava_activity_mcp_server-0.2.5.dist-info/licenses/LICENSE,sha256=IwGE9guuL-ryRPEKi6wFPI_zOhg7zDZbTYuHbSt_SAk,35823
|
|
8
|
+
strava_activity_mcp_server-0.2.5.dist-info/RECORD,,
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
strava_activity_mcp_server/__init__.py,sha256=jaa1ZVuEJMwuVGzj67oqC_ESUUiwblVVH-NEtTiQQdQ,110
|
|
2
|
-
strava_activity_mcp_server/__main__.py,sha256=SAdVoObdjb5UP4MY-Y2_uCXpnthB6hgxlb1KNVNgOrc,58
|
|
3
|
-
strava_activity_mcp_server/strava_activity_mcp_server.py,sha256=hdk_t8IveOFvfm5K2irlzXb8GIHikvmFKIZQIqRn_OE,11488
|
|
4
|
-
strava_activity_mcp_server-0.2.3.dist-info/METADATA,sha256=cXIW5XIKPUzay262mC2uGFfjIPSj21FS0gh1FRITLzY,7665
|
|
5
|
-
strava_activity_mcp_server-0.2.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
6
|
-
strava_activity_mcp_server-0.2.3.dist-info/entry_points.txt,sha256=F6PO_DBSThhtmX2AC-tu2MIiCJkGi31LCaQJxfUzZ5g,79
|
|
7
|
-
strava_activity_mcp_server-0.2.3.dist-info/licenses/LICENSE,sha256=IwGE9guuL-ryRPEKi6wFPI_zOhg7zDZbTYuHbSt_SAk,35823
|
|
8
|
-
strava_activity_mcp_server-0.2.3.dist-info/RECORD,,
|
{strava_activity_mcp_server-0.2.3.dist-info → strava_activity_mcp_server-0.2.5.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|