William Easton commited on
Commit
0cc2dbe
·
unverified ·
2 Parent(s): ba278e6b1f9630

Fix type-checking error with OAuth

Browse files
docs/docs.json CHANGED
@@ -122,7 +122,10 @@
122
  {
123
  "group": "Essentials",
124
  "icon": "cube",
125
- "pages": ["clients/client", "clients/transports"]
 
 
 
126
  },
127
  {
128
  "group": "Core Operations",
@@ -148,7 +151,10 @@
148
  {
149
  "group": "Authentication",
150
  "icon": "user-shield",
151
- "pages": ["clients/auth/oauth", "clients/auth/bearer"]
 
 
 
152
  }
153
  ]
154
  },
@@ -194,12 +200,17 @@
194
  },
195
  {
196
  "anchor": "What's New",
197
- "pages": ["updates", "changelog"]
 
 
 
198
  },
199
  {
200
  "anchor": "Community",
201
  "icon": "users",
202
- "pages": ["community/showcase"]
 
 
203
  }
204
  ]
205
  },
 
122
  {
123
  "group": "Essentials",
124
  "icon": "cube",
125
+ "pages": [
126
+ "clients/client",
127
+ "clients/transports"
128
+ ]
129
  },
130
  {
131
  "group": "Core Operations",
 
151
  {
152
  "group": "Authentication",
153
  "icon": "user-shield",
154
+ "pages": [
155
+ "clients/auth/oauth",
156
+ "clients/auth/bearer"
157
+ ]
158
  }
159
  ]
160
  },
 
200
  },
201
  {
202
  "anchor": "What's New",
203
+ "pages": [
204
+ "updates",
205
+ "changelog"
206
+ ]
207
  },
208
  {
209
  "anchor": "Community",
210
  "icon": "users",
211
+ "pages": [
212
+ "community/showcase"
213
+ ]
214
  }
215
  ]
216
  },
docs/python-sdk/fastmcp-client-auth-oauth.mdx CHANGED
@@ -7,13 +7,13 @@ sidebarTitle: oauth
7
 
8
  ## Functions
9
 
10
- ### `default_cache_dir` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L34" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
11
 
12
  ```python
13
  default_cache_dir() -> Path
14
  ```
15
 
16
- ### `check_if_auth_required` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L152" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
17
 
18
  ```python
19
  check_if_auth_required(mcp_url: str, httpx_kwargs: dict[str, Any] | None = None) -> bool
@@ -28,7 +28,7 @@ Check if the MCP endpoint requires authentication by making a test request.
28
 
29
  ## Classes
30
 
31
- ### `FileTokenStorage` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L38" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
32
 
33
 
34
  File-based token storage implementation for OAuth credentials and tokens.
@@ -39,7 +39,7 @@ Each instance is tied to a specific server URL for proper token isolation.
39
 
40
  **Methods:**
41
 
42
- #### `get_base_url` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L53" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
43
 
44
  ```python
45
  get_base_url(url: str) -> str
@@ -48,7 +48,7 @@ get_base_url(url: str) -> str
48
  Extract the base URL (scheme + host) from a URL.
49
 
50
 
51
- #### `get_cache_key` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L58" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
52
 
53
  ```python
54
  get_cache_key(self) -> str
@@ -57,7 +57,7 @@ get_cache_key(self) -> str
57
  Generate a safe filesystem key from the server's base URL.
58
 
59
 
60
- #### `get_tokens` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L73" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
61
 
62
  ```python
63
  get_tokens(self) -> OAuthToken | None
@@ -66,7 +66,7 @@ get_tokens(self) -> OAuthToken | None
66
  Load tokens from file storage.
67
 
68
 
69
- #### `set_tokens` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L90" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
70
 
71
  ```python
72
  set_tokens(self, tokens: OAuthToken) -> None
@@ -75,7 +75,7 @@ set_tokens(self, tokens: OAuthToken) -> None
75
  Save tokens to file storage.
76
 
77
 
78
- #### `get_client_info` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L96" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
79
 
80
  ```python
81
  get_client_info(self) -> OAuthClientInformationFull | None
@@ -84,7 +84,7 @@ get_client_info(self) -> OAuthClientInformationFull | None
84
  Load client information from file storage.
85
 
86
 
87
- #### `set_client_info` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L124" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
88
 
89
  ```python
90
  set_client_info(self, client_info: OAuthClientInformationFull) -> None
@@ -93,7 +93,7 @@ set_client_info(self, client_info: OAuthClientInformationFull) -> None
93
  Save client information to file storage.
94
 
95
 
96
- #### `clear` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L130" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
97
 
98
  ```python
99
  clear(self) -> None
@@ -102,7 +102,7 @@ clear(self) -> None
102
  Clear all cached data for this server.
103
 
104
 
105
- #### `clear_all` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L139" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
106
 
107
  ```python
108
  clear_all(cls, cache_dir: Path | None = None) -> None
@@ -111,7 +111,7 @@ clear_all(cls, cache_dir: Path | None = None) -> None
111
  Clear all cached data for all servers.
112
 
113
 
114
- ### `OAuth` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L182" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
115
 
116
 
117
  OAuth client provider for MCP servers with browser-based authentication.
@@ -122,7 +122,7 @@ a browser for user authorization and running a local callback server.
122
 
123
  **Methods:**
124
 
125
- #### `redirect_handler` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L248" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
126
 
127
  ```python
128
  redirect_handler(self, authorization_url: str) -> None
@@ -131,7 +131,7 @@ redirect_handler(self, authorization_url: str) -> None
131
  Open browser for authorization.
132
 
133
 
134
- #### `callback_handler` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L253" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
135
 
136
  ```python
137
  callback_handler(self) -> tuple[str, str | None]
 
7
 
8
  ## Functions
9
 
10
+ ### `default_cache_dir` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L36" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
11
 
12
  ```python
13
  default_cache_dir() -> Path
14
  ```
15
 
16
+ ### `check_if_auth_required` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L154" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
17
 
18
  ```python
19
  check_if_auth_required(mcp_url: str, httpx_kwargs: dict[str, Any] | None = None) -> bool
 
28
 
29
  ## Classes
30
 
31
+ ### `FileTokenStorage` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L40" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
32
 
33
 
34
  File-based token storage implementation for OAuth credentials and tokens.
 
39
 
40
  **Methods:**
41
 
42
+ #### `get_base_url` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L55" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
43
 
44
  ```python
45
  get_base_url(url: str) -> str
 
48
  Extract the base URL (scheme + host) from a URL.
49
 
50
 
51
+ #### `get_cache_key` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L60" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
52
 
53
  ```python
54
  get_cache_key(self) -> str
 
57
  Generate a safe filesystem key from the server's base URL.
58
 
59
 
60
+ #### `get_tokens` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L75" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
61
 
62
  ```python
63
  get_tokens(self) -> OAuthToken | None
 
66
  Load tokens from file storage.
67
 
68
 
69
+ #### `set_tokens` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L92" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
70
 
71
  ```python
72
  set_tokens(self, tokens: OAuthToken) -> None
 
75
  Save tokens to file storage.
76
 
77
 
78
+ #### `get_client_info` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L98" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
79
 
80
  ```python
81
  get_client_info(self) -> OAuthClientInformationFull | None
 
84
  Load client information from file storage.
85
 
86
 
87
+ #### `set_client_info` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L126" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
88
 
89
  ```python
90
  set_client_info(self, client_info: OAuthClientInformationFull) -> None
 
93
  Save client information to file storage.
94
 
95
 
96
+ #### `clear` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L132" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
97
 
98
  ```python
99
  clear(self) -> None
 
102
  Clear all cached data for this server.
103
 
104
 
105
+ #### `clear_all` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L141" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
106
 
107
  ```python
108
  clear_all(cls, cache_dir: Path | None = None) -> None
 
111
  Clear all cached data for all servers.
112
 
113
 
114
+ ### `OAuth` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L184" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
115
 
116
 
117
  OAuth client provider for MCP servers with browser-based authentication.
 
122
 
123
  **Methods:**
124
 
125
+ #### `redirect_handler` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L250" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
126
 
127
  ```python
128
  redirect_handler(self, authorization_url: str) -> None
 
131
  Open browser for authorization.
132
 
133
 
134
+ #### `callback_handler` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L255" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
135
 
136
  ```python
137
  callback_handler(self) -> tuple[str, str | None]
src/fastmcp/client/auth/oauth.py CHANGED
@@ -3,6 +3,7 @@ from __future__ import annotations
3
  import asyncio
4
  import json
5
  import webbrowser
 
6
  from pathlib import Path
7
  from typing import Any, Literal
8
  from urllib.parse import urlparse
@@ -18,6 +19,7 @@ from mcp.shared.auth import (
18
  OAuthToken as OAuthToken,
19
  )
20
  from pydantic import AnyHttpUrl, ValidationError
 
21
 
22
  from fastmcp import settings as fastmcp_global_settings
23
  from fastmcp.client.oauth_callback import (
@@ -253,10 +255,10 @@ class OAuth(OAuthClientProvider):
253
  async def callback_handler(self) -> tuple[str, str | None]:
254
  """Handle OAuth callback and return (auth_code, state)."""
255
  # Create a future to capture the OAuth response
256
- response_future = asyncio.get_running_loop().create_future()
257
 
258
  # Create server with the future
259
- server = create_oauth_callback_server(
260
  port=self.redirect_port,
261
  server_url=self.server_base_url,
262
  response_future=response_future,
@@ -280,3 +282,5 @@ class OAuth(OAuthClientProvider):
280
  server.should_exit = True
281
  await asyncio.sleep(0.1) # Allow server to shutdown gracefully
282
  tg.cancel_scope.cancel()
 
 
 
3
  import asyncio
4
  import json
5
  import webbrowser
6
+ from asyncio import Future
7
  from pathlib import Path
8
  from typing import Any, Literal
9
  from urllib.parse import urlparse
 
19
  OAuthToken as OAuthToken,
20
  )
21
  from pydantic import AnyHttpUrl, ValidationError
22
+ from uvicorn.server import Server
23
 
24
  from fastmcp import settings as fastmcp_global_settings
25
  from fastmcp.client.oauth_callback import (
 
255
  async def callback_handler(self) -> tuple[str, str | None]:
256
  """Handle OAuth callback and return (auth_code, state)."""
257
  # Create a future to capture the OAuth response
258
+ response_future: Future[Any] = asyncio.get_running_loop().create_future()
259
 
260
  # Create server with the future
261
+ server: Server = create_oauth_callback_server(
262
  port=self.redirect_port,
263
  server_url=self.server_base_url,
264
  response_future=response_future,
 
282
  server.should_exit = True
283
  await asyncio.sleep(0.1) # Allow server to shutdown gracefully
284
  tg.cancel_scope.cancel()
285
+
286
+ raise RuntimeError("OAuth callback handler could not be started")