golf-mcp 0.1.20__py3-none-any.whl → 0.2.0__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 golf-mcp might be problematic. Click here for more details.

Files changed (123) hide show
  1. golf/__init__.py +9 -1
  2. golf/_endpoints.py +6 -0
  3. golf/_endpoints_fallback.py +10 -0
  4. golf/auth/__init__.py +188 -84
  5. golf/auth/api_key.py +6 -14
  6. golf/auth/factory.py +333 -0
  7. golf/auth/helpers.py +12 -42
  8. golf/auth/providers.py +396 -0
  9. golf/auth/registry.py +256 -0
  10. golf/cli/branding.py +192 -0
  11. golf/cli/main.py +28 -69
  12. golf/commands/__init__.py +2 -0
  13. golf/commands/build.py +4 -7
  14. golf/commands/init.py +30 -53
  15. golf/commands/run.py +50 -20
  16. golf/core/builder.py +355 -414
  17. golf/core/builder_auth.py +63 -144
  18. golf/core/builder_telemetry.py +26 -3
  19. golf/core/config.py +38 -59
  20. golf/core/parser.py +132 -139
  21. golf/core/platform.py +12 -10
  22. golf/core/telemetry.py +11 -19
  23. golf/core/transformer.py +38 -15
  24. golf/examples/__pycache__/__init__.cpython-311.pyc +0 -0
  25. golf/examples/basic/.coverage +0 -0
  26. golf/examples/basic/.env.example +8 -4
  27. golf/examples/basic/README.md +117 -45
  28. golf/examples/basic/__pycache__/auth.cpython-311.pyc +0 -0
  29. golf/examples/basic/auth.py +76 -0
  30. golf/examples/basic/golf.json +2 -5
  31. golf/examples/basic/htmlcov/.gitignore +2 -0
  32. golf/examples/basic/htmlcov/class_index.html +547 -0
  33. golf/examples/basic/htmlcov/coverage_html_cb_6fb7b396.js +733 -0
  34. golf/examples/basic/htmlcov/favicon_32_cb_58284776.png +0 -0
  35. golf/examples/basic/htmlcov/function_index.html +2091 -0
  36. golf/examples/basic/htmlcov/index.html +349 -0
  37. golf/examples/basic/htmlcov/keybd_closed_cb_ce680311.png +0 -0
  38. golf/examples/basic/htmlcov/status.json +1 -0
  39. golf/examples/basic/htmlcov/style_cb_8e611ae1.css +337 -0
  40. golf/examples/basic/htmlcov/z_1c9a91c0e91c8496___init___py.html +323 -0
  41. golf/examples/basic/htmlcov/z_1c9a91c0e91c8496_api_key_py.html +170 -0
  42. golf/examples/basic/htmlcov/z_1c9a91c0e91c8496_factory_py.html +430 -0
  43. golf/examples/basic/htmlcov/z_1c9a91c0e91c8496_helpers_py.html +288 -0
  44. golf/examples/basic/htmlcov/z_1c9a91c0e91c8496_providers_py.html +493 -0
  45. golf/examples/basic/htmlcov/z_1c9a91c0e91c8496_registry_py.html +353 -0
  46. golf/examples/basic/htmlcov/z_3ec3b3f490dc0950___init___py.html +120 -0
  47. golf/examples/basic/htmlcov/z_3ec3b3f490dc0950_instrumentation_py.html +1535 -0
  48. golf/examples/basic/htmlcov/z_4b8b9dd4ccccc5db___init___py.html +98 -0
  49. golf/examples/basic/htmlcov/z_4b8b9dd4ccccc5db_branding_py.html +289 -0
  50. golf/examples/basic/htmlcov/z_4b8b9dd4ccccc5db_main_py.html +476 -0
  51. golf/examples/basic/htmlcov/z_5a6c4e6bcc86fb2f___init___py.html +97 -0
  52. golf/examples/basic/htmlcov/z_6cadab9ec0df475d___init___py.html +102 -0
  53. golf/examples/basic/htmlcov/z_6cadab9ec0df475d_build_py.html +178 -0
  54. golf/examples/basic/htmlcov/z_6cadab9ec0df475d_init_py.html +387 -0
  55. golf/examples/basic/htmlcov/z_6cadab9ec0df475d_run_py.html +222 -0
  56. golf/examples/basic/htmlcov/z_6fcdee0582ba84e4___init___py.html +106 -0
  57. golf/examples/basic/htmlcov/z_6fcdee0582ba84e4__endpoints_fallback_py.html +107 -0
  58. golf/examples/basic/htmlcov/z_7ba499ed22986217___init___py.html +98 -0
  59. golf/examples/basic/htmlcov/z_7ba499ed22986217_builder_auth_py.html +306 -0
  60. golf/examples/basic/htmlcov/z_7ba499ed22986217_builder_metrics_py.html +329 -0
  61. golf/examples/basic/htmlcov/z_7ba499ed22986217_builder_py.html +1471 -0
  62. golf/examples/basic/htmlcov/z_7ba499ed22986217_builder_telemetry_py.html +186 -0
  63. golf/examples/basic/htmlcov/z_7ba499ed22986217_config_py.html +315 -0
  64. golf/examples/basic/htmlcov/z_7ba499ed22986217_parser_py.html +1149 -0
  65. golf/examples/basic/htmlcov/z_7ba499ed22986217_platform_py.html +279 -0
  66. golf/examples/basic/htmlcov/z_7ba499ed22986217_telemetry_py.html +589 -0
  67. golf/examples/basic/htmlcov/z_7ba499ed22986217_transformer_py.html +286 -0
  68. golf/examples/basic/htmlcov/z_7d7da37693a43688___init___py.html +107 -0
  69. golf/examples/basic/htmlcov/z_7d7da37693a43688_collector_py.html +417 -0
  70. golf/examples/basic/htmlcov/z_7d7da37693a43688_registry_py.html +109 -0
  71. golf/examples/basic/htmlcov/z_abe733142b40ad4e___init___py.html +109 -0
  72. golf/examples/basic/htmlcov/z_abe733142b40ad4e_context_py.html +150 -0
  73. golf/examples/basic/htmlcov/z_abe733142b40ad4e_elicitation_py.html +267 -0
  74. golf/examples/basic/htmlcov/z_abe733142b40ad4e_sampling_py.html +318 -0
  75. golf/examples/basic/prompts/__pycache__/welcome.cpython-311.pyc +0 -0
  76. golf/examples/basic/prompts/welcome.py +3 -5
  77. golf/examples/basic/resources/__pycache__/current_time.cpython-311.pyc +0 -0
  78. golf/examples/basic/resources/__pycache__/info.cpython-311.pyc +0 -0
  79. golf/examples/basic/resources/current_time.py +5 -13
  80. golf/examples/basic/resources/weather/__pycache__/common.cpython-311.pyc +0 -0
  81. golf/examples/basic/resources/weather/__pycache__/current.cpython-311.pyc +0 -0
  82. golf/examples/basic/resources/weather/__pycache__/forecast.cpython-311.pyc +0 -0
  83. golf/examples/basic/resources/weather/city.py +46 -0
  84. golf/examples/basic/resources/weather/common.py +4 -11
  85. golf/examples/basic/resources/weather/current.py +5 -5
  86. golf/examples/basic/resources/weather/forecast.py +5 -5
  87. golf/examples/basic/tools/__pycache__/calculator.cpython-311.pyc +0 -0
  88. golf/examples/basic/tools/calculator.py +94 -0
  89. golf/examples/basic/tools/say/__pycache__/hello.cpython-311.pyc +0 -0
  90. golf/examples/basic/tools/say/hello.py +65 -0
  91. golf/metrics/collector.py +100 -19
  92. golf/telemetry/__init__.py +4 -0
  93. golf/telemetry/instrumentation.py +484 -178
  94. golf/utilities/__init__.py +12 -0
  95. golf/utilities/context.py +53 -0
  96. golf/utilities/elicitation.py +170 -0
  97. golf/utilities/sampling.py +221 -0
  98. {golf_mcp-0.1.20.dist-info → golf_mcp-0.2.0.dist-info}/METADATA +51 -104
  99. golf_mcp-0.2.0.dist-info/RECORD +110 -0
  100. golf/auth/oauth.py +0 -861
  101. golf/auth/provider.py +0 -115
  102. golf/examples/api_key/.env +0 -2
  103. golf/examples/api_key/.env.example +0 -1
  104. golf/examples/api_key/README.md +0 -84
  105. golf/examples/api_key/golf.json +0 -8
  106. golf/examples/api_key/pre_build.py +0 -11
  107. golf/examples/api_key/tools/issues/create.py +0 -93
  108. golf/examples/api_key/tools/issues/list.py +0 -92
  109. golf/examples/api_key/tools/repos/list.py +0 -111
  110. golf/examples/api_key/tools/search/code.py +0 -106
  111. golf/examples/api_key/tools/users/get.py +0 -82
  112. golf/examples/basic/.env +0 -5
  113. golf/examples/basic/pre_build.py +0 -28
  114. golf/examples/basic/tools/github_user.py +0 -65
  115. golf/examples/basic/tools/hello.py +0 -34
  116. golf/examples/basic/tools/payments/charge.py +0 -70
  117. golf/examples/basic/tools/payments/common.py +0 -36
  118. golf/examples/basic/tools/payments/refund.py +0 -61
  119. golf_mcp-0.1.20.dist-info/RECORD +0 -60
  120. {golf_mcp-0.1.20.dist-info → golf_mcp-0.2.0.dist-info}/WHEEL +0 -0
  121. {golf_mcp-0.1.20.dist-info → golf_mcp-0.2.0.dist-info}/entry_points.txt +0 -0
  122. {golf_mcp-0.1.20.dist-info → golf_mcp-0.2.0.dist-info}/licenses/LICENSE +0 -0
  123. {golf_mcp-0.1.20.dist-info → golf_mcp-0.2.0.dist-info}/top_level.txt +0 -0
golf/auth/factory.py ADDED
@@ -0,0 +1,333 @@
1
+ """Factory functions for creating FastMCP authentication providers."""
2
+
3
+ import os
4
+ from typing import Any
5
+
6
+ # Import these at runtime to avoid import errors during Golf installation
7
+ from typing import TYPE_CHECKING
8
+
9
+ if TYPE_CHECKING:
10
+ from fastmcp.server.auth.auth import AuthProvider
11
+ from fastmcp.server.auth import JWTVerifier, StaticTokenVerifier
12
+ from mcp.server.auth.settings import RevocationOptions
13
+
14
+ from .providers import (
15
+ AuthConfig,
16
+ JWTAuthConfig,
17
+ StaticTokenConfig,
18
+ OAuthServerConfig,
19
+ RemoteAuthConfig,
20
+ )
21
+ from .registry import (
22
+ get_provider_registry,
23
+ create_auth_provider_from_registry,
24
+ )
25
+
26
+
27
+ def create_auth_provider(config: AuthConfig) -> "AuthProvider":
28
+ """Create a FastMCP AuthProvider from Golf auth configuration.
29
+
30
+ This function uses the provider registry system to allow extensibility.
31
+ Built-in providers are automatically registered, and custom providers
32
+ can be added via the registry system.
33
+
34
+ Args:
35
+ config: Golf authentication configuration
36
+
37
+ Returns:
38
+ Configured FastMCP AuthProvider instance
39
+
40
+ Raises:
41
+ ValueError: If configuration is invalid
42
+ ImportError: If required dependencies are missing
43
+ KeyError: If provider type is not registered
44
+ """
45
+ try:
46
+ return create_auth_provider_from_registry(config)
47
+ except KeyError:
48
+ # Fall back to legacy dispatch for backward compatibility
49
+ # This ensures existing code continues to work during transition
50
+ if config.provider_type == "jwt":
51
+ return _create_jwt_provider(config)
52
+ elif config.provider_type == "static":
53
+ return _create_static_provider(config)
54
+ elif config.provider_type == "oauth_server":
55
+ return _create_oauth_server_provider(config)
56
+ elif config.provider_type == "remote":
57
+ return _create_remote_provider(config)
58
+ else:
59
+ raise ValueError(f"Unknown provider type: {config.provider_type}") from None
60
+
61
+
62
+ def _create_jwt_provider(config: JWTAuthConfig) -> "JWTVerifier":
63
+ """Create JWT token verifier from configuration."""
64
+ # Resolve runtime values from environment variables
65
+ public_key = config.public_key
66
+ if config.public_key_env_var:
67
+ env_value = os.environ.get(config.public_key_env_var)
68
+ if env_value:
69
+ public_key = env_value
70
+
71
+ jwks_uri = config.jwks_uri
72
+ if config.jwks_uri_env_var:
73
+ env_value = os.environ.get(config.jwks_uri_env_var)
74
+ if env_value:
75
+ jwks_uri = env_value
76
+
77
+ issuer = config.issuer
78
+ if config.issuer_env_var:
79
+ env_value = os.environ.get(config.issuer_env_var)
80
+ if env_value:
81
+ issuer = env_value
82
+
83
+ audience = config.audience
84
+ if config.audience_env_var:
85
+ env_value = os.environ.get(config.audience_env_var)
86
+ if env_value:
87
+ # Handle both string and comma-separated list
88
+ if "," in env_value:
89
+ audience = [s.strip() for s in env_value.split(",")]
90
+ else:
91
+ audience = env_value
92
+
93
+ # Validate configuration
94
+ if not public_key and not jwks_uri:
95
+ raise ValueError("Either public_key or jwks_uri must be provided for JWT verification")
96
+
97
+ if public_key and jwks_uri:
98
+ raise ValueError("Provide either public_key or jwks_uri, not both")
99
+
100
+ try:
101
+ from fastmcp.server.auth import JWTVerifier
102
+ except ImportError as e:
103
+ raise ImportError("JWTVerifier not available. Please install fastmcp>=2.11.0") from e
104
+
105
+ return JWTVerifier(
106
+ public_key=public_key,
107
+ jwks_uri=jwks_uri,
108
+ issuer=issuer,
109
+ audience=audience,
110
+ algorithm=config.algorithm,
111
+ required_scopes=config.required_scopes,
112
+ )
113
+
114
+
115
+ def _create_static_provider(config: StaticTokenConfig) -> "StaticTokenVerifier":
116
+ """Create static token verifier from configuration."""
117
+ if not config.tokens:
118
+ raise ValueError("Static token provider requires at least one token")
119
+
120
+ try:
121
+ from fastmcp.server.auth import StaticTokenVerifier
122
+ except ImportError as e:
123
+ raise ImportError("StaticTokenVerifier not available. Please install fastmcp>=2.11.0") from e
124
+
125
+ return StaticTokenVerifier(
126
+ tokens=config.tokens,
127
+ required_scopes=config.required_scopes,
128
+ )
129
+
130
+
131
+ def _create_oauth_server_provider(config: OAuthServerConfig) -> "AuthProvider":
132
+ """Create OAuth authorization server provider from configuration."""
133
+ try:
134
+ from fastmcp.server.auth import OAuthProvider
135
+ except ImportError as e:
136
+ raise ImportError(
137
+ "OAuthProvider not available in this FastMCP version. Please upgrade to FastMCP 2.11.0 or later."
138
+ ) from e
139
+
140
+ # Resolve runtime values from environment variables with validation
141
+ base_url = config.base_url
142
+ if config.base_url_env_var:
143
+ env_value = os.environ.get(config.base_url_env_var)
144
+ if env_value:
145
+ # Apply the same validation as the config field to env var value
146
+ try:
147
+ from urllib.parse import urlparse
148
+
149
+ env_value = env_value.strip()
150
+ parsed = urlparse(env_value)
151
+
152
+ if not parsed.scheme or not parsed.netloc:
153
+ raise ValueError(
154
+ f"Invalid base URL from environment variable {config.base_url_env_var}: '{env_value}'"
155
+ )
156
+
157
+ if parsed.scheme not in ("http", "https"):
158
+ raise ValueError(f"Base URL from environment must use http/https: '{env_value}'")
159
+
160
+ # Production HTTPS check
161
+ is_production = (
162
+ os.environ.get("GOLF_ENV", "").lower() in ("prod", "production")
163
+ or os.environ.get("NODE_ENV", "").lower() == "production"
164
+ or os.environ.get("ENVIRONMENT", "").lower() in ("prod", "production")
165
+ )
166
+
167
+ if is_production and parsed.scheme == "http":
168
+ raise ValueError(f"Base URL must use HTTPS in production: '{env_value}'")
169
+
170
+ base_url = env_value
171
+
172
+ except Exception as e:
173
+ raise ValueError(f"Invalid base URL from environment variable {config.base_url_env_var}: {e}") from e
174
+
175
+ # Additional security validations before creating provider
176
+ from urllib.parse import urlparse
177
+
178
+ # Validate final base_url
179
+ parsed_base = urlparse(base_url)
180
+ if not parsed_base.scheme or not parsed_base.netloc:
181
+ raise ValueError(f"Invalid base URL: '{base_url}'")
182
+
183
+ # Security check: prevent localhost in production
184
+ is_production = (
185
+ os.environ.get("GOLF_ENV", "").lower() in ("prod", "production")
186
+ or os.environ.get("NODE_ENV", "").lower() == "production"
187
+ or os.environ.get("ENVIRONMENT", "").lower() in ("prod", "production")
188
+ )
189
+
190
+ if is_production and parsed_base.hostname in ("localhost", "127.0.0.1", "0.0.0.0"):
191
+ raise ValueError(f"Cannot use localhost/loopback addresses in production: '{base_url}'")
192
+
193
+ # Client registration options - always disabled for security
194
+ client_reg_options = None
195
+
196
+ # Create revocation options
197
+ revocation_options = None
198
+ if config.allow_token_revocation:
199
+ revocation_options = RevocationOptions(enabled=True)
200
+
201
+ return OAuthProvider(
202
+ base_url=base_url,
203
+ issuer_url=config.issuer_url,
204
+ service_documentation_url=config.service_documentation_url,
205
+ client_registration_options=client_reg_options,
206
+ revocation_options=revocation_options,
207
+ required_scopes=config.required_scopes,
208
+ )
209
+
210
+
211
+ def _create_remote_provider(config: RemoteAuthConfig) -> "AuthProvider":
212
+ """Create remote auth provider from configuration."""
213
+ try:
214
+ from fastmcp.server.auth import RemoteAuthProvider
215
+ except ImportError as e:
216
+ raise ImportError(
217
+ "RemoteAuthProvider not available in this FastMCP version. Please upgrade to FastMCP 2.11.0 or later."
218
+ ) from e
219
+
220
+ # Resolve runtime values from environment variables
221
+ authorization_servers = config.authorization_servers
222
+ if config.authorization_servers_env_var:
223
+ env_value = os.environ.get(config.authorization_servers_env_var)
224
+ if env_value:
225
+ # Split comma-separated values and strip whitespace
226
+ authorization_servers = [s.strip() for s in env_value.split(",")]
227
+
228
+ resource_server_url = config.resource_server_url
229
+ if config.resource_server_url_env_var:
230
+ env_value = os.environ.get(config.resource_server_url_env_var)
231
+ if env_value:
232
+ resource_server_url = env_value
233
+
234
+ # Create the underlying token verifier
235
+ token_verifier = create_auth_provider(config.token_verifier_config)
236
+
237
+ # Ensure it's actually a TokenVerifier
238
+ if not hasattr(token_verifier, "verify_token"):
239
+ raise ValueError(f"Remote auth provider requires a TokenVerifier, got {type(token_verifier).__name__}")
240
+
241
+ return RemoteAuthProvider(
242
+ token_verifier=token_verifier,
243
+ authorization_servers=authorization_servers,
244
+ resource_server_url=resource_server_url,
245
+ )
246
+
247
+
248
+ def create_simple_jwt_provider(
249
+ *,
250
+ jwks_uri: str | None = None,
251
+ public_key: str | None = None,
252
+ issuer: str | None = None,
253
+ audience: str | list[str] | None = None,
254
+ required_scopes: list[str] | None = None,
255
+ ) -> "JWTVerifier":
256
+ """Create a simple JWT provider for common use cases.
257
+
258
+ This is a convenience function for creating JWT providers without
259
+ having to construct the full configuration objects.
260
+
261
+ Args:
262
+ jwks_uri: JWKS URI for key fetching
263
+ public_key: Static public key (PEM format)
264
+ issuer: Expected issuer claim
265
+ audience: Expected audience claim(s)
266
+ required_scopes: Required scopes for all requests
267
+
268
+ Returns:
269
+ Configured JWTVerifier instance
270
+ """
271
+ config = JWTAuthConfig(
272
+ jwks_uri=jwks_uri,
273
+ public_key=public_key,
274
+ issuer=issuer,
275
+ audience=audience,
276
+ required_scopes=required_scopes or [],
277
+ )
278
+ return _create_jwt_provider(config)
279
+
280
+
281
+ def create_dev_token_provider(
282
+ tokens: dict[str, Any] | None = None,
283
+ required_scopes: list[str] | None = None,
284
+ ) -> "StaticTokenVerifier":
285
+ """Create a static token provider for development.
286
+
287
+ Args:
288
+ tokens: Token dictionary or None for default dev tokens
289
+ required_scopes: Required scopes for all requests
290
+
291
+ Returns:
292
+ Configured StaticTokenVerifier instance
293
+ """
294
+ if tokens is None:
295
+ # Default development tokens
296
+ tokens = {
297
+ "dev-token-123": {
298
+ "client_id": "dev-client",
299
+ "scopes": ["read", "write"],
300
+ },
301
+ "admin-token-456": {
302
+ "client_id": "admin-client",
303
+ "scopes": ["read", "write", "admin"],
304
+ },
305
+ }
306
+
307
+ config = StaticTokenConfig(
308
+ tokens=tokens,
309
+ required_scopes=required_scopes or [],
310
+ )
311
+ return _create_static_provider(config)
312
+
313
+
314
+ def register_builtin_providers() -> None:
315
+ """Register built-in authentication providers in the registry.
316
+
317
+ This function registers the standard Golf authentication providers:
318
+ - jwt: JWT token verification
319
+ - static: Static token verification (development)
320
+ - oauth_server: Full OAuth authorization server
321
+ - remote: Remote authorization server integration
322
+ """
323
+ registry = get_provider_registry()
324
+
325
+ # Register built-in provider factories
326
+ registry.register_factory("jwt", _create_jwt_provider)
327
+ registry.register_factory("static", _create_static_provider)
328
+ registry.register_factory("oauth_server", _create_oauth_server_provider)
329
+ registry.register_factory("remote", _create_remote_provider)
330
+
331
+
332
+ # Register built-in providers when module is imported
333
+ register_builtin_providers()
golf/auth/helpers.py CHANGED
@@ -3,48 +3,22 @@
3
3
  from contextvars import ContextVar
4
4
  from typing import Any
5
5
 
6
- # Re-export get_access_token from the MCP SDK
7
- from mcp.server.auth.middleware.auth_context import get_access_token
8
-
9
- from .oauth import GolfOAuthProvider
10
-
11
- # Context variable to store the active OAuth provider
12
- _active_golf_oauth_provider: GolfOAuthProvider | None = None
6
+ from starlette.requests import Request
13
7
 
14
8
  # Context variable to store the current request's API key
15
9
  _current_api_key: ContextVar[str | None] = ContextVar("current_api_key", default=None)
16
10
 
17
11
 
18
- def _set_active_golf_oauth_provider(provider: GolfOAuthProvider) -> None:
19
- """
20
- Sets the active GolfOAuthProvider instance.
21
- Should only be called once during server startup.
22
- """
23
- global _active_golf_oauth_provider
24
- _active_golf_oauth_provider = provider
25
-
26
-
27
12
  def get_provider_token() -> str | None:
28
13
  """
29
- Get a provider token (e.g., GitHub token) associated with the current
30
- MCP session's access token.
14
+ Get a provider token (legacy function - no longer supported in Golf 0.2.x).
31
15
 
32
- This relies on _set_active_golf_oauth_provider being called at server startup.
16
+ In Golf 0.2.x, use FastMCP's built-in auth providers for OAuth flows.
17
+ This function returns None and is kept for backwards compatibility.
33
18
  """
34
- mcp_access_token = get_access_token() # From MCP SDK, uses its own ContextVar
35
- if not mcp_access_token:
36
- # No active MCP session token.
37
- return None
38
-
39
- provider = _active_golf_oauth_provider
40
- if not provider:
41
- return None
42
-
43
- if not hasattr(provider, "get_provider_token"):
44
- return None
45
-
46
- # Call the get_provider_token method on the actual GolfOAuthProvider instance
47
- return provider.get_provider_token(mcp_access_token.token)
19
+ # Legacy OAuth provider support removed in Golf 0.2.x
20
+ # Use FastMCP 2.11+ auth providers instead
21
+ return None
48
22
 
49
23
 
50
24
  def extract_token_from_header(auth_header: str) -> str | None:
@@ -149,7 +123,7 @@ def get_api_key() -> str | None:
149
123
  return None
150
124
 
151
125
 
152
- def get_api_key_from_request(request) -> str | None:
126
+ def get_api_key_from_request(request: Request) -> str | None:
153
127
  """Get the API key from a specific request object.
154
128
 
155
129
  This is useful when you have direct access to the request object.
@@ -199,23 +173,19 @@ def debug_api_key_context() -> dict[str, Any]:
199
173
  if task:
200
174
  debug_info["has_async_task"] = True
201
175
  debug_info["task_id"] = id(task)
202
- except:
176
+ except Exception:
203
177
  pass
204
178
 
205
179
  try:
206
180
  main_module = sys.modules.get("__main__")
207
181
  if main_module:
208
- debug_info["main_module_has_storage"] = hasattr(
209
- main_module, "api_key_storage"
210
- )
211
- debug_info["main_module_has_context"] = hasattr(
212
- main_module, "request_id_context"
213
- )
182
+ debug_info["main_module_has_storage"] = hasattr(main_module, "api_key_storage")
183
+ debug_info["main_module_has_context"] = hasattr(main_module, "request_id_context")
214
184
 
215
185
  if hasattr(main_module, "request_id_context"):
216
186
  request_id_context = main_module.request_id_context
217
187
  debug_info["request_id_from_context"] = request_id_context.get()
218
- except:
188
+ except Exception:
219
189
  pass
220
190
 
221
191
  return debug_info