golf-mcp 0.2.0__tar.gz → 0.2.1__tar.gz
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.
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/PKG-INFO +1 -1
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/pyproject.toml +2 -2
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/__init__.py +1 -1
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/auth/__init__.py +48 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/auth/factory.py +25 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/auth/providers.py +50 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/core/builder_auth.py +1 -1
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf_mcp.egg-info/PKG-INFO +1 -1
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/.docs/docs.md +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/.docs/fastmcp-diff.md +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/.docs/mcp.md +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/LICENSE +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/MANIFEST.in +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/README.md +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/setup.cfg +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/setup.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/_endpoints_fallback.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/auth/api_key.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/auth/helpers.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/auth/registry.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/cli/__init__.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/cli/branding.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/cli/main.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/commands/__init__.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/commands/build.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/commands/init.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/commands/run.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/core/__init__.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/core/builder.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/core/builder_metrics.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/core/builder_telemetry.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/core/config.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/core/parser.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/core/platform.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/core/telemetry.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/core/transformer.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/__init__.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/.coverage +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/.env.example +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/README.md +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/auth.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/golf.json +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/.gitignore +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/class_index.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/coverage_html_cb_6fb7b396.js +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/favicon_32_cb_58284776.png +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/function_index.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/index.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/keybd_closed_cb_ce680311.png +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/status.json +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/style_cb_8e611ae1.css +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_1c9a91c0e91c8496___init___py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_1c9a91c0e91c8496_api_key_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_1c9a91c0e91c8496_factory_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_1c9a91c0e91c8496_helpers_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_1c9a91c0e91c8496_providers_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_1c9a91c0e91c8496_registry_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_3ec3b3f490dc0950___init___py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_3ec3b3f490dc0950_instrumentation_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_4b8b9dd4ccccc5db___init___py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_4b8b9dd4ccccc5db_branding_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_4b8b9dd4ccccc5db_main_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_5a6c4e6bcc86fb2f___init___py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_6cadab9ec0df475d___init___py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_6cadab9ec0df475d_build_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_6cadab9ec0df475d_init_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_6cadab9ec0df475d_run_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_6fcdee0582ba84e4___init___py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_6fcdee0582ba84e4__endpoints_fallback_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_7ba499ed22986217___init___py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_7ba499ed22986217_builder_auth_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_7ba499ed22986217_builder_metrics_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_7ba499ed22986217_builder_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_7ba499ed22986217_builder_telemetry_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_7ba499ed22986217_config_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_7ba499ed22986217_parser_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_7ba499ed22986217_platform_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_7ba499ed22986217_telemetry_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_7ba499ed22986217_transformer_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_7d7da37693a43688___init___py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_7d7da37693a43688_collector_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_7d7da37693a43688_registry_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_abe733142b40ad4e___init___py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_abe733142b40ad4e_context_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_abe733142b40ad4e_elicitation_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_abe733142b40ad4e_sampling_py.html +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/prompts/welcome.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/resources/current_time.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/resources/info.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/resources/weather/city.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/resources/weather/common.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/resources/weather/current.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/resources/weather/forecast.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/tools/calculator.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/tools/say/hello.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/metrics/__init__.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/metrics/collector.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/metrics/registry.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/telemetry/__init__.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/telemetry/instrumentation.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/utilities/__init__.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/utilities/context.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/utilities/elicitation.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/utilities/sampling.py +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf_mcp.egg-info/SOURCES.txt +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf_mcp.egg-info/dependency_links.txt +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf_mcp.egg-info/entry_points.txt +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf_mcp.egg-info/requires.txt +0 -0
- {golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf_mcp.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "golf-mcp"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.1"
|
|
8
8
|
description = "Framework for building MCP servers"
|
|
9
9
|
authors = [
|
|
10
10
|
{name = "Antoni Gmitruk", email = "antoni@golf.dev"}
|
|
@@ -66,7 +66,7 @@ golf = ["examples/**/*"]
|
|
|
66
66
|
|
|
67
67
|
[tool.poetry]
|
|
68
68
|
name = "golf-mcp"
|
|
69
|
-
version = "0.1
|
|
69
|
+
version = "0.2.1"
|
|
70
70
|
description = "Framework for building MCP servers with zero boilerplate"
|
|
71
71
|
authors = ["Antoni Gmitruk <antoni@golf.dev>"]
|
|
72
72
|
license = "Apache-2.0"
|
|
@@ -14,6 +14,7 @@ from .providers import (
|
|
|
14
14
|
StaticTokenConfig,
|
|
15
15
|
OAuthServerConfig,
|
|
16
16
|
RemoteAuthConfig,
|
|
17
|
+
OAuthProxyConfig,
|
|
17
18
|
)
|
|
18
19
|
from .factory import (
|
|
19
20
|
create_auth_provider,
|
|
@@ -44,6 +45,7 @@ __all__ = [
|
|
|
44
45
|
"configure_auth",
|
|
45
46
|
"configure_jwt_auth",
|
|
46
47
|
"configure_dev_auth",
|
|
48
|
+
"configure_oauth_proxy",
|
|
47
49
|
"get_auth_config",
|
|
48
50
|
# Provider configurations
|
|
49
51
|
"AuthConfig",
|
|
@@ -51,6 +53,7 @@ __all__ = [
|
|
|
51
53
|
"StaticTokenConfig",
|
|
52
54
|
"OAuthServerConfig",
|
|
53
55
|
"RemoteAuthConfig",
|
|
56
|
+
"OAuthProxyConfig",
|
|
54
57
|
# Factory functions
|
|
55
58
|
"create_auth_provider",
|
|
56
59
|
"create_simple_jwt_provider",
|
|
@@ -191,6 +194,51 @@ def configure_dev_auth(
|
|
|
191
194
|
configure_auth(config)
|
|
192
195
|
|
|
193
196
|
|
|
197
|
+
def configure_oauth_proxy(
|
|
198
|
+
upstream_authorization_endpoint: str,
|
|
199
|
+
upstream_token_endpoint: str,
|
|
200
|
+
upstream_client_id: str,
|
|
201
|
+
upstream_client_secret: str,
|
|
202
|
+
base_url: str,
|
|
203
|
+
token_verifier_config: JWTAuthConfig | StaticTokenConfig,
|
|
204
|
+
scopes_supported: list[str] | None = None,
|
|
205
|
+
upstream_revocation_endpoint: str | None = None,
|
|
206
|
+
redirect_path: str = "/oauth/callback",
|
|
207
|
+
) -> None:
|
|
208
|
+
"""Configure OAuth proxy authentication for non-DCR providers.
|
|
209
|
+
|
|
210
|
+
This sets up an OAuth proxy that bridges MCP clients (expecting DCR) with
|
|
211
|
+
traditional OAuth providers like GitHub, Google, Okta Web Apps that use
|
|
212
|
+
fixed client credentials.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
upstream_authorization_endpoint: Provider's authorization URL
|
|
216
|
+
upstream_token_endpoint: Provider's token endpoint URL
|
|
217
|
+
upstream_client_id: Your client ID registered with the provider
|
|
218
|
+
upstream_client_secret: Your client secret from the provider
|
|
219
|
+
base_url: This proxy server's public URL
|
|
220
|
+
token_verifier_config: JWT or static token config for token verification
|
|
221
|
+
scopes_supported: Scopes to advertise to MCP clients
|
|
222
|
+
upstream_revocation_endpoint: Optional token revocation endpoint
|
|
223
|
+
redirect_path: OAuth callback path (default: /oauth/callback)
|
|
224
|
+
|
|
225
|
+
Note:
|
|
226
|
+
Requires golf-mcp-enterprise package for implementation.
|
|
227
|
+
"""
|
|
228
|
+
config = OAuthProxyConfig(
|
|
229
|
+
upstream_authorization_endpoint=upstream_authorization_endpoint,
|
|
230
|
+
upstream_token_endpoint=upstream_token_endpoint,
|
|
231
|
+
upstream_client_id=upstream_client_id,
|
|
232
|
+
upstream_client_secret=upstream_client_secret,
|
|
233
|
+
upstream_revocation_endpoint=upstream_revocation_endpoint,
|
|
234
|
+
base_url=base_url,
|
|
235
|
+
redirect_path=redirect_path,
|
|
236
|
+
scopes_supported=scopes_supported or [],
|
|
237
|
+
token_verifier_config=token_verifier_config,
|
|
238
|
+
)
|
|
239
|
+
configure_auth(config)
|
|
240
|
+
|
|
241
|
+
|
|
194
242
|
def get_auth_config() -> AuthConfig | None:
|
|
195
243
|
"""Get the current auth configuration.
|
|
196
244
|
|
|
@@ -17,6 +17,7 @@ from .providers import (
|
|
|
17
17
|
StaticTokenConfig,
|
|
18
18
|
OAuthServerConfig,
|
|
19
19
|
RemoteAuthConfig,
|
|
20
|
+
OAuthProxyConfig,
|
|
20
21
|
)
|
|
21
22
|
from .registry import (
|
|
22
23
|
get_provider_registry,
|
|
@@ -55,6 +56,8 @@ def create_auth_provider(config: AuthConfig) -> "AuthProvider":
|
|
|
55
56
|
return _create_oauth_server_provider(config)
|
|
56
57
|
elif config.provider_type == "remote":
|
|
57
58
|
return _create_remote_provider(config)
|
|
59
|
+
elif config.provider_type == "oauth_proxy":
|
|
60
|
+
return _create_oauth_proxy_provider(config)
|
|
58
61
|
else:
|
|
59
62
|
raise ValueError(f"Unknown provider type: {config.provider_type}") from None
|
|
60
63
|
|
|
@@ -238,6 +241,11 @@ def _create_remote_provider(config: RemoteAuthConfig) -> "AuthProvider":
|
|
|
238
241
|
if not hasattr(token_verifier, "verify_token"):
|
|
239
242
|
raise ValueError(f"Remote auth provider requires a TokenVerifier, got {type(token_verifier).__name__}")
|
|
240
243
|
|
|
244
|
+
# Update token verifier's required_scopes to match our scopes_supported for PRM
|
|
245
|
+
# RemoteAuthProvider uses token_verifier.required_scopes for scopes_supported in PRM
|
|
246
|
+
if config.scopes_supported and hasattr(token_verifier, "required_scopes"):
|
|
247
|
+
token_verifier.required_scopes = list(config.scopes_supported)
|
|
248
|
+
|
|
241
249
|
return RemoteAuthProvider(
|
|
242
250
|
token_verifier=token_verifier,
|
|
243
251
|
authorization_servers=authorization_servers,
|
|
@@ -245,6 +253,21 @@ def _create_remote_provider(config: RemoteAuthConfig) -> "AuthProvider":
|
|
|
245
253
|
)
|
|
246
254
|
|
|
247
255
|
|
|
256
|
+
def _create_oauth_proxy_provider(config: OAuthProxyConfig) -> "AuthProvider":
|
|
257
|
+
"""Create OAuth proxy provider - requires enterprise package."""
|
|
258
|
+
try:
|
|
259
|
+
# Try to import from enterprise package
|
|
260
|
+
from golf_enterprise import create_oauth_proxy_provider
|
|
261
|
+
return create_oauth_proxy_provider(config)
|
|
262
|
+
except ImportError as e:
|
|
263
|
+
raise ImportError(
|
|
264
|
+
"OAuth Proxy requires golf-mcp-enterprise package. "
|
|
265
|
+
"This feature provides OAuth proxy functionality for non-DCR providers "
|
|
266
|
+
"(GitHub, Google, Okta Web Apps, etc.). "
|
|
267
|
+
"Contact sales@golf.dev for enterprise licensing."
|
|
268
|
+
) from e
|
|
269
|
+
|
|
270
|
+
|
|
248
271
|
def create_simple_jwt_provider(
|
|
249
272
|
*,
|
|
250
273
|
jwks_uri: str | None = None,
|
|
@@ -319,6 +342,7 @@ def register_builtin_providers() -> None:
|
|
|
319
342
|
- static: Static token verification (development)
|
|
320
343
|
- oauth_server: Full OAuth authorization server
|
|
321
344
|
- remote: Remote authorization server integration
|
|
345
|
+
- oauth_proxy: OAuth proxy for non-DCR providers (requires golf-mcp-enterprise)
|
|
322
346
|
"""
|
|
323
347
|
registry = get_provider_registry()
|
|
324
348
|
|
|
@@ -327,6 +351,7 @@ def register_builtin_providers() -> None:
|
|
|
327
351
|
registry.register_factory("static", _create_static_provider)
|
|
328
352
|
registry.register_factory("oauth_server", _create_oauth_server_provider)
|
|
329
353
|
registry.register_factory("remote", _create_remote_provider)
|
|
354
|
+
registry.register_factory("oauth_proxy", _create_oauth_proxy_provider)
|
|
330
355
|
|
|
331
356
|
|
|
332
357
|
# Register built-in providers when module is imported
|
|
@@ -299,6 +299,12 @@ class RemoteAuthConfig(BaseModel):
|
|
|
299
299
|
# This server's URL
|
|
300
300
|
resource_server_url: str = Field(..., description="URL of this resource server")
|
|
301
301
|
|
|
302
|
+
# Scopes this resource supports (advertised via /.well-known/oauth-protected-resource)
|
|
303
|
+
scopes_supported: list[str] = Field(
|
|
304
|
+
default_factory=list,
|
|
305
|
+
description="Scopes this resource supports (advertised via /.well-known/oauth-protected-resource)",
|
|
306
|
+
)
|
|
307
|
+
|
|
302
308
|
# Token verification (delegate to another config)
|
|
303
309
|
token_verifier_config: JWTAuthConfig | StaticTokenConfig = Field(
|
|
304
310
|
..., description="Configuration for the underlying token verifier"
|
|
@@ -362,6 +368,45 @@ class RemoteAuthConfig(BaseModel):
|
|
|
362
368
|
|
|
363
369
|
return url
|
|
364
370
|
|
|
371
|
+
@field_validator("scopes_supported")
|
|
372
|
+
@classmethod
|
|
373
|
+
def validate_scopes_supported(cls, v: list[str]) -> list[str]:
|
|
374
|
+
"""Validate scopes_supported format and security."""
|
|
375
|
+
if not v:
|
|
376
|
+
return v
|
|
377
|
+
|
|
378
|
+
cleaned_scopes = []
|
|
379
|
+
for scope in v:
|
|
380
|
+
scope = scope.strip()
|
|
381
|
+
if not scope:
|
|
382
|
+
raise ValueError("Scopes cannot be empty or whitespace-only")
|
|
383
|
+
|
|
384
|
+
# OAuth 2.0 scope format validation (RFC 6749)
|
|
385
|
+
if not all(32 < ord(c) < 127 and c not in ' "\\' for c in scope):
|
|
386
|
+
raise ValueError(
|
|
387
|
+
f"Invalid scope format: '{scope}' - must be ASCII printable without spaces, quotes, or backslashes"
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
# Reasonable length limit to prevent abuse
|
|
391
|
+
if len(scope) > 128:
|
|
392
|
+
raise ValueError(f"Scope too long: '{scope}' - maximum 128 characters")
|
|
393
|
+
|
|
394
|
+
# Warn about potentially dangerous scope names
|
|
395
|
+
dangerous_scopes = {"admin", "root", "superuser", "system", "*", "all"}
|
|
396
|
+
if scope.lower() in dangerous_scopes:
|
|
397
|
+
import warnings
|
|
398
|
+
|
|
399
|
+
warnings.warn(
|
|
400
|
+
f"Potentially dangerous scope detected: '{scope}'. "
|
|
401
|
+
"Consider using more specific, principle-of-least-privilege scopes.",
|
|
402
|
+
UserWarning,
|
|
403
|
+
stacklevel=2,
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
cleaned_scopes.append(scope)
|
|
407
|
+
|
|
408
|
+
return cleaned_scopes
|
|
409
|
+
|
|
365
410
|
@model_validator(mode="after")
|
|
366
411
|
def validate_token_verifier_compatibility(self) -> "RemoteAuthConfig":
|
|
367
412
|
"""Validate that the token verifier config is compatible with token verification."""
|
|
@@ -389,6 +434,11 @@ class RemoteAuthConfig(BaseModel):
|
|
|
389
434
|
if isinstance(config, StaticTokenConfig) and not config.tokens:
|
|
390
435
|
raise ValueError("Static token verifier config must provide at least one token")
|
|
391
436
|
|
|
437
|
+
# Convenience: if user didn't set scopes_supported, default to verifier.required_scopes
|
|
438
|
+
if not self.scopes_supported:
|
|
439
|
+
if hasattr(config, "required_scopes") and config.required_scopes:
|
|
440
|
+
self.scopes_supported = list(config.required_scopes)
|
|
441
|
+
|
|
392
442
|
return self
|
|
393
443
|
|
|
394
444
|
|
|
@@ -52,7 +52,7 @@ def generate_auth_code(
|
|
|
52
52
|
"import os",
|
|
53
53
|
"import sys",
|
|
54
54
|
"from golf.auth.factory import create_auth_provider",
|
|
55
|
-
"from golf.auth.providers import RemoteAuthConfig, JWTAuthConfig, StaticTokenConfig, OAuthServerConfig",
|
|
55
|
+
"from golf.auth.providers import RemoteAuthConfig, JWTAuthConfig, StaticTokenConfig, OAuthServerConfig, OAuthProxyConfig",
|
|
56
56
|
]
|
|
57
57
|
|
|
58
58
|
# Embed the auth configuration directly in the generated code
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/coverage_html_cb_6fb7b396.js
RENAMED
|
File without changes
|
{golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/favicon_32_cb_58284776.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/keybd_closed_cb_ce680311.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_1c9a91c0e91c8496_api_key_py.html
RENAMED
|
File without changes
|
{golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_1c9a91c0e91c8496_factory_py.html
RENAMED
|
File without changes
|
{golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_1c9a91c0e91c8496_helpers_py.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_4b8b9dd4ccccc5db_main_py.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_6cadab9ec0df475d_build_py.html
RENAMED
|
File without changes
|
{golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_6cadab9ec0df475d_init_py.html
RENAMED
|
File without changes
|
{golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_6cadab9ec0df475d_run_py.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_7ba499ed22986217_builder_py.html
RENAMED
|
File without changes
|
|
File without changes
|
{golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_7ba499ed22986217_config_py.html
RENAMED
|
File without changes
|
{golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_7ba499ed22986217_parser_py.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{golf_mcp-0.2.0 → golf_mcp-0.2.1}/src/golf/examples/basic/htmlcov/z_abe733142b40ad4e_context_py.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|