strava-activity-mcp-server 0.2.0__py3-none-any.whl → 0.2.1__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.
@@ -7,7 +7,6 @@ import requests
7
7
  import urllib.parse
8
8
 
9
9
  @mcp.tool("strava://auth/url")
10
-
11
10
  def get_auth_url(client_id: int | None = None):
12
11
  """Return the Strava OAuth authorization URL. If client_id is not provided,
13
12
  read it from the STRAVA_CLIENT_ID environment variable."""
@@ -30,72 +29,148 @@ def get_auth_url(client_id: int | None = None):
30
29
  # Always return whole URL and not part of it
31
30
  return "https://www.strava.com/oauth/authorize?" + urllib.parse.urlencode(params)
32
31
 
32
+ @mcp.tool("strava://auth/refresh")
33
+ def refresh_access_token(
34
+ refresh_token: str,
35
+ client_id: int | None = None,
36
+ client_secret: str | None = None,
37
+ ) -> dict:
38
+ """Refresh an access token using a refresh token."""
39
+ if not refresh_token:
40
+ return {"error": "refresh token is required"}
41
+
42
+ if client_id is None:
43
+ client_id_env = os.getenv("STRAVA_CLIENT_ID")
44
+ if not client_id_env:
45
+ return {"error": "STRAVA_CLIENT_ID environment variable is not set"}
46
+ try:
47
+ client_id = int(client_id_env)
48
+ except ValueError:
49
+ return {"error": "STRAVA_CLIENT_ID must be an integer"}
33
50
 
51
+ if client_secret is None:
52
+ client_secret_env = os.getenv("STRAVA_CLIENT_SECRET")
53
+ if not client_secret_env:
54
+ return {"error": "STRAVA_CLIENT_SECRET environment variable is not set"}
55
+ try:
56
+ client_secret = str(client_secret_env)
57
+ except ValueError:
58
+ return {"error": "STRAVA_CLIENT_SECRET must be a string"}
59
+
60
+ resp = requests.post(
61
+ "https://www.strava.com/oauth/token",
62
+ data={
63
+ "client_id": client_id,
64
+ "client_secret": client_secret,
65
+ "refresh_token": refresh_token,
66
+ "grant_type": "refresh_token",
67
+ },
68
+ )
69
+
70
+ try:
71
+ resp.raise_for_status()
72
+ except requests.HTTPError:
73
+ return {"error": "token refresh failed", "status_code": resp.status_code, "response": resp.text}
74
+ except Exception as e:
75
+ return {"error": "token refresh failed", "status_code": resp.status_code, "response": resp.text, "error": str(e)}
76
+
77
+ tokens = resp.json()
78
+ print(tokens) # Print tokens for debugging (optional)
79
+
80
+ return {
81
+ "access_token": tokens.get("access_token"),
82
+ "refresh_token": tokens.get("refresh_token"),
83
+ "expires_at": tokens.get("expires_at"),
84
+ "expires_in": tokens.get("expires_in")
85
+ }
34
86
 
35
87
  @mcp.tool("strava://athlete/stats")
36
88
  def get_athlete_stats(
37
89
  code: str,
38
90
  client_id: int | None = None,
39
- client_secret: str | None = None,) -> dict:
40
-
41
- #'''Exchange an authorization code for access + refresh tokens.'''
42
- if not code:
43
- return {"error": "authorization code is required"}
44
-
45
- if client_id is None:
46
- client_id_env = os.getenv("STRAVA_CLIENT_ID")
47
- if not client_id_env:
48
- return {"error": "STRAVA_CLIENT_ID environment variable is not set"}
49
- try:
50
- client_id = int(client_id_env)
51
- except ValueError:
52
- return {"error": "STRAVA_CLIENT_ID must be an integer"}
53
-
54
- if client_secret is None:
55
- client_secret_env = os.getenv("STRAVA_CLIENT_SECRET")
56
- if not client_secret_env:
57
- return {"error": "STRAVA_CLIENT_SECRET environment variable is not set"}
58
- try:
59
- client_secret = str(client_secret_env)
60
- except ValueError:
61
- return {"error": "STRAVA_CLIENT_SECRET must be a string"}
62
-
63
-
64
- resp = requests.post(
65
- "https://www.strava.com/oauth/token",
66
- data={
91
+ client_secret: str | None = None,
92
+ ) -> dict:
93
+ """Exchange an authorization code for access + refresh tokens and get athlete activities."""
94
+ if not code:
95
+ return {"error": "authorization code is required"}
96
+
97
+ if client_id is None:
98
+ client_id_env = os.getenv("STRAVA_CLIENT_ID")
99
+ if not client_id_env:
100
+ return {"error": "STRAVA_CLIENT_ID environment variable is not set"}
101
+ try:
102
+ client_id = int(client_id_env)
103
+ except ValueError:
104
+ return {"error": "STRAVA_CLIENT_ID must be an integer"}
105
+
106
+ if client_secret is None:
107
+ client_secret_env = os.getenv("STRAVA_CLIENT_SECRET")
108
+ if not client_secret_env:
109
+ return {"error": "STRAVA_CLIENT_SECRET environment variable is not set"}
110
+ try:
111
+ client_secret = str(client_secret_env)
112
+ except ValueError:
113
+ return {"error": "STRAVA_CLIENT_SECRET must be a string"}
114
+
115
+ resp = requests.post(
116
+ "https://www.strava.com/oauth/token",
117
+ data={
67
118
  "client_id": client_id,
68
119
  "client_secret": client_secret,
69
120
  "code": code,
70
121
  "grant_type": "authorization_code",
71
122
  },
72
123
  )
73
- try:
74
- resp.raise_for_status()
75
- except requests.HTTPError:
76
- return {"error": "token request failed", "status_code": resp.status_code, "response": resp.text}
77
- except Exception as e:
78
- return {"error": "token request failed", "status_code": resp.status_code, "response": resp.text, "error": str(e)}
79
-
80
- tokens = resp.json()
124
+
125
+ try:
126
+ resp.raise_for_status()
127
+ except requests.HTTPError:
128
+ return {"error": "token request failed", "status_code": resp.status_code, "response": resp.text}
129
+ except Exception as e:
130
+ return {"error": "token request failed", "status_code": resp.status_code, "response": resp.text, "error": str(e)}
131
+
132
+ tokens = resp.json()
81
133
  # Print tokens for debugging (optional)
82
- print(tokens)
134
+ print(tokens)
135
+
136
+ access_token = tokens.get("access_token")
137
+ refresh_token = tokens.get("refresh_token")
83
138
 
84
- access_token = tokens.get("access_token")
85
- refresh_token = tokens.get("refresh_token")
139
+ # return {"tokens": tokens, "access_token": access_token, "refresh_token": refresh_token}
86
140
 
141
+ url = "https://www.strava.com/api/v3/athlete/activities?per_page=60"
142
+ headers = {
143
+ "accept": "application/json",
144
+ "authorization": f"Bearer {access_token}"
145
+ }
87
146
 
88
- #return {"tokens": tokens, "access_token": access_token, "refresh_token": refresh_token}
147
+ response = requests.get(url, headers=headers)
89
148
 
90
- url = "https://www.strava.com/api/v3/athlete/activities?per_page=60"
91
- headers = {
92
- "accept": "application/json",
93
- "authorization": f"Bearer {access_token}"
94
- }
149
+ return response.json()
150
+
151
+ @mcp.tool("strava://athlete/stats-with-token")
152
+ def get_athlete_stats_with_token(access_token: str) -> dict:
153
+ """Get athlete activities using an existing access token."""
154
+ if not access_token:
155
+ return {"error": "access token is required"}
156
+
157
+ url = "https://www.strava.com/api/v3/athlete/activities?per_page=60"
158
+ headers = {
159
+ "accept": "application/json",
160
+ "authorization": f"Bearer {access_token}"
161
+ }
162
+
163
+ response = requests.get(url, headers=headers)
164
+
165
+ try:
166
+ response.raise_for_status()
167
+ except requests.HTTPError:
168
+ return {"error": "API request failed", "status_code": response.status_code, "response": response.text}
169
+ except Exception as e:
170
+ return {"error": "API request failed", "status_code": response.status_code, "response": response.text, "error": str(e)}
95
171
 
96
- response = requests.get(url, headers=headers)
172
+ return response.json()
97
173
 
98
- return response.json()
99
174
 
100
175
  if __name__ == "__main__":
101
176
  mcp.run(transport="stdio") # Run the server, using standard input/output for communication
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: strava-activity-mcp-server
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: STRAVA ACTIVITY MCP SERVER
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.10
@@ -118,10 +118,10 @@ Any MCP-capable client can launch the server using a config similar to the follo
118
118
  To quickly test the server using the Model Context Protocol inspector tool, run:
119
119
 
120
120
  ```powershell
121
- npx @modelcontextprotocol/inspector uvx strava-mcp-server
121
+ npx @modelcontextprotocol/inspector uvx strava-activity-mcp-server
122
122
  ```
123
123
 
124
- This will attempt to start the server with the `uvx` transport and connect the inspector to the running MCP server instance named `strava-mcp-server`.
124
+ This will attempt to start the server with the `uvx` transport and connect the inspector to the running MCP server instance named `strava-activity-mcp-server`.
125
125
 
126
126
 
127
127
  ## Contributing
@@ -0,0 +1,8 @@
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=3qxN4c8cLlVlv4R1e90c8AOsw6WaCOy4PMz2GwXsCwE,6515
4
+ strava_activity_mcp_server-0.2.1.dist-info/METADATA,sha256=5XqxiNyEzQmiF26Fh_NrDfTtGJMZSu-e4MSstL9-dNM,5270
5
+ strava_activity_mcp_server-0.2.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
6
+ strava_activity_mcp_server-0.2.1.dist-info/entry_points.txt,sha256=F6PO_DBSThhtmX2AC-tu2MIiCJkGi31LCaQJxfUzZ5g,79
7
+ strava_activity_mcp_server-0.2.1.dist-info/licenses/LICENSE,sha256=IwGE9guuL-ryRPEKi6wFPI_zOhg7zDZbTYuHbSt_SAk,35823
8
+ strava_activity_mcp_server-0.2.1.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=kwQMEbZqmrT14JgUWBu5B6Xn7eQw0dehallfLUnERuo,3779
4
- strava_activity_mcp_server-0.2.0.dist-info/METADATA,sha256=sRcgvZnKwR9Nyf5Zfn6bLSZkr7fowYi5XmC7wwkEdts,5252
5
- strava_activity_mcp_server-0.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
6
- strava_activity_mcp_server-0.2.0.dist-info/entry_points.txt,sha256=F6PO_DBSThhtmX2AC-tu2MIiCJkGi31LCaQJxfUzZ5g,79
7
- strava_activity_mcp_server-0.2.0.dist-info/licenses/LICENSE,sha256=IwGE9guuL-ryRPEKi6wFPI_zOhg7zDZbTYuHbSt_SAk,35823
8
- strava_activity_mcp_server-0.2.0.dist-info/RECORD,,