golf-mcp 0.2.16__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.
Files changed (52) hide show
  1. golf/__init__.py +1 -0
  2. golf/auth/__init__.py +277 -0
  3. golf/auth/api_key.py +73 -0
  4. golf/auth/factory.py +360 -0
  5. golf/auth/helpers.py +175 -0
  6. golf/auth/providers.py +586 -0
  7. golf/auth/registry.py +256 -0
  8. golf/cli/__init__.py +1 -0
  9. golf/cli/branding.py +191 -0
  10. golf/cli/main.py +377 -0
  11. golf/commands/__init__.py +5 -0
  12. golf/commands/build.py +81 -0
  13. golf/commands/init.py +290 -0
  14. golf/commands/run.py +137 -0
  15. golf/core/__init__.py +1 -0
  16. golf/core/builder.py +1884 -0
  17. golf/core/builder_auth.py +209 -0
  18. golf/core/builder_metrics.py +221 -0
  19. golf/core/builder_telemetry.py +99 -0
  20. golf/core/config.py +199 -0
  21. golf/core/parser.py +1085 -0
  22. golf/core/telemetry.py +492 -0
  23. golf/core/transformer.py +231 -0
  24. golf/examples/__init__.py +0 -0
  25. golf/examples/basic/.env.example +4 -0
  26. golf/examples/basic/README.md +133 -0
  27. golf/examples/basic/auth.py +76 -0
  28. golf/examples/basic/golf.json +5 -0
  29. golf/examples/basic/prompts/welcome.py +27 -0
  30. golf/examples/basic/resources/current_time.py +34 -0
  31. golf/examples/basic/resources/info.py +28 -0
  32. golf/examples/basic/resources/weather/city.py +46 -0
  33. golf/examples/basic/resources/weather/client.py +48 -0
  34. golf/examples/basic/resources/weather/current.py +36 -0
  35. golf/examples/basic/resources/weather/forecast.py +36 -0
  36. golf/examples/basic/tools/calculator.py +94 -0
  37. golf/examples/basic/tools/say/hello.py +65 -0
  38. golf/metrics/__init__.py +10 -0
  39. golf/metrics/collector.py +320 -0
  40. golf/metrics/registry.py +12 -0
  41. golf/telemetry/__init__.py +23 -0
  42. golf/telemetry/instrumentation.py +1402 -0
  43. golf/utilities/__init__.py +12 -0
  44. golf/utilities/context.py +53 -0
  45. golf/utilities/elicitation.py +170 -0
  46. golf/utilities/sampling.py +221 -0
  47. golf_mcp-0.2.16.dist-info/METADATA +262 -0
  48. golf_mcp-0.2.16.dist-info/RECORD +52 -0
  49. golf_mcp-0.2.16.dist-info/WHEEL +5 -0
  50. golf_mcp-0.2.16.dist-info/entry_points.txt +2 -0
  51. golf_mcp-0.2.16.dist-info/licenses/LICENSE +201 -0
  52. golf_mcp-0.2.16.dist-info/top_level.txt +1 -0
golf/__init__.py ADDED
@@ -0,0 +1 @@
1
+ __version__ = "0.2.16"
golf/auth/__init__.py ADDED
@@ -0,0 +1,277 @@
1
+ """Modern authentication for Golf MCP servers using FastMCP 2.11+ providers.
2
+
3
+ This module provides authentication configuration and utilities for Golf servers,
4
+ leveraging FastMCP's built-in authentication system with JWT verification,
5
+ OAuth providers, and token management.
6
+ """
7
+
8
+ from typing import Any
9
+
10
+ # Modern auth provider configurations and factory functions
11
+ from .providers import (
12
+ AuthConfig,
13
+ JWTAuthConfig,
14
+ StaticTokenConfig,
15
+ OAuthServerConfig,
16
+ RemoteAuthConfig,
17
+ OAuthProxyConfig,
18
+ )
19
+ from .factory import (
20
+ create_auth_provider,
21
+ create_simple_jwt_provider,
22
+ create_dev_token_provider,
23
+ )
24
+ from .registry import (
25
+ BaseProviderPlugin,
26
+ AuthProviderFactory,
27
+ get_provider_registry,
28
+ register_provider_factory,
29
+ register_provider_plugin,
30
+ )
31
+
32
+ # Re-export for backward compatibility
33
+ from .api_key import configure_api_key, get_api_key_config, is_api_key_configured
34
+ from .helpers import (
35
+ extract_token_from_header,
36
+ get_api_key,
37
+ get_auth_token,
38
+ set_api_key,
39
+ )
40
+
41
+ # Public API
42
+ __all__ = [
43
+ # Main configuration functions
44
+ "configure_auth",
45
+ "configure_jwt_auth",
46
+ "configure_dev_auth",
47
+ "configure_oauth_proxy",
48
+ "get_auth_config",
49
+ # Provider configurations
50
+ "AuthConfig",
51
+ "JWTAuthConfig",
52
+ "StaticTokenConfig",
53
+ "OAuthServerConfig",
54
+ "RemoteAuthConfig",
55
+ "OAuthProxyConfig",
56
+ # Factory functions
57
+ "create_auth_provider",
58
+ "create_simple_jwt_provider",
59
+ "create_dev_token_provider",
60
+ # Provider registry and plugins
61
+ "BaseProviderPlugin",
62
+ "AuthProviderFactory",
63
+ "get_provider_registry",
64
+ "register_provider_factory",
65
+ "register_provider_plugin",
66
+ # API key functions (backward compatibility)
67
+ "configure_api_key",
68
+ "get_api_key_config",
69
+ "is_api_key_configured",
70
+ # Helper functions
71
+ "extract_token_from_header",
72
+ "get_api_key",
73
+ "get_auth_token",
74
+ "set_api_key",
75
+ ]
76
+
77
+ # Global storage for auth configuration
78
+ _auth_config: AuthConfig | None = None
79
+
80
+
81
+ def configure_auth(config: AuthConfig) -> None:
82
+ """Configure authentication for the Golf server.
83
+
84
+ This function should be called in auth.py to set up authentication
85
+ using FastMCP's modern auth providers.
86
+
87
+ Args:
88
+ config: Authentication configuration (JWT, OAuth, Static, or Remote)
89
+ The required_scopes should be specified in the config itself.
90
+
91
+ Examples:
92
+ # JWT authentication with Auth0
93
+ from golf.auth import configure_auth, JWTAuthConfig
94
+
95
+ configure_auth(
96
+ JWTAuthConfig(
97
+ jwks_uri="https://your-domain.auth0.com/.well-known/jwks.json",
98
+ issuer="https://your-domain.auth0.com/",
99
+ audience="https://your-api.example.com",
100
+ required_scopes=["read:data"],
101
+ )
102
+ )
103
+
104
+ # Development with static tokens
105
+ from golf.auth import configure_auth, StaticTokenConfig
106
+
107
+ configure_auth(
108
+ StaticTokenConfig(
109
+ tokens={
110
+ "dev-token-123": {
111
+ "client_id": "dev-client",
112
+ "scopes": ["read", "write"],
113
+ }
114
+ },
115
+ required_scopes=["read"],
116
+ )
117
+ )
118
+
119
+ # Full OAuth server
120
+ from golf.auth import configure_auth, OAuthServerConfig
121
+
122
+ configure_auth(
123
+ OAuthServerConfig(
124
+ base_url="https://your-server.example.com",
125
+ valid_scopes=["read", "write", "admin"],
126
+ default_scopes=["read"],
127
+ required_scopes=["read"],
128
+ )
129
+ )
130
+ """
131
+ global _auth_config
132
+ _auth_config = config
133
+
134
+
135
+ def configure_jwt_auth(
136
+ *,
137
+ jwks_uri: str | None = None,
138
+ public_key: str | None = None,
139
+ issuer: str | None = None,
140
+ audience: str | list[str] | None = None,
141
+ required_scopes: list[str] | None = None,
142
+ **env_vars: str,
143
+ ) -> None:
144
+ """Convenience function to configure JWT authentication.
145
+
146
+ Args:
147
+ jwks_uri: JWKS URI for key fetching
148
+ public_key: Static public key (PEM format)
149
+ issuer: Expected issuer claim
150
+ audience: Expected audience claim(s)
151
+ required_scopes: Required scopes for all requests
152
+ **env_vars: Environment variable names (public_key_env_var,
153
+ jwks_uri_env_var, etc.)
154
+ """
155
+ config = JWTAuthConfig(
156
+ jwks_uri=jwks_uri,
157
+ public_key=public_key,
158
+ issuer=issuer,
159
+ audience=audience,
160
+ required_scopes=required_scopes or [],
161
+ **env_vars,
162
+ )
163
+ configure_auth(config)
164
+
165
+
166
+ def configure_dev_auth(
167
+ tokens: dict[str, Any] | None = None,
168
+ required_scopes: list[str] | None = None,
169
+ ) -> None:
170
+ """Convenience function to configure development authentication.
171
+
172
+ Args:
173
+ tokens: Token dictionary or None for defaults
174
+ required_scopes: Required scopes for all requests
175
+ """
176
+ if tokens is None:
177
+ tokens = {
178
+ "dev-token-123": {
179
+ "client_id": "dev-client",
180
+ "scopes": ["read", "write"],
181
+ },
182
+ "admin-token-456": {
183
+ "client_id": "admin-client",
184
+ "scopes": ["read", "write", "admin"],
185
+ },
186
+ }
187
+
188
+ config = StaticTokenConfig(
189
+ tokens=tokens,
190
+ required_scopes=required_scopes or [],
191
+ )
192
+ configure_auth(config)
193
+
194
+
195
+ def configure_oauth_proxy(
196
+ authorization_endpoint: str,
197
+ token_endpoint: str,
198
+ client_id: str,
199
+ client_secret: str,
200
+ base_url: str,
201
+ token_verifier_config: JWTAuthConfig | StaticTokenConfig,
202
+ scopes_supported: list[str] | None = None,
203
+ revocation_endpoint: str | None = None,
204
+ redirect_path: str = "/oauth/callback",
205
+ **env_vars: str,
206
+ ) -> None:
207
+ """Configure OAuth proxy authentication for non-DCR providers.
208
+
209
+ This sets up an OAuth proxy that bridges MCP clients (expecting DCR) with
210
+ traditional OAuth providers like GitHub, Google, Okta Web Apps that use
211
+ fixed client credentials.
212
+
213
+ Args:
214
+ authorization_endpoint: Provider's authorization URL
215
+ token_endpoint: Provider's token endpoint URL
216
+ client_id: Your client ID registered with the provider
217
+ client_secret: Your client secret from the provider
218
+ base_url: This proxy server's public URL
219
+ token_verifier_config: JWT or static token config for token verification
220
+ scopes_supported: Scopes to advertise to MCP clients
221
+ revocation_endpoint: Optional token revocation endpoint
222
+ redirect_path: OAuth callback path (default: /oauth/callback)
223
+ **env_vars: Environment variable names (authorization_endpoint_env_var,
224
+ token_endpoint_env_var, client_id_env_var, client_secret_env_var,
225
+ base_url_env_var, revocation_endpoint_env_var)
226
+
227
+ Note:
228
+ Requires golf-mcp-enterprise package for implementation.
229
+ """
230
+ config = OAuthProxyConfig(
231
+ authorization_endpoint=authorization_endpoint,
232
+ token_endpoint=token_endpoint,
233
+ client_id=client_id,
234
+ client_secret=client_secret,
235
+ revocation_endpoint=revocation_endpoint,
236
+ base_url=base_url,
237
+ redirect_path=redirect_path,
238
+ scopes_supported=scopes_supported,
239
+ token_verifier_config=token_verifier_config,
240
+ **env_vars,
241
+ )
242
+ configure_auth(config)
243
+
244
+
245
+ def get_auth_config() -> AuthConfig | None:
246
+ """Get the current auth configuration.
247
+
248
+ Returns:
249
+ AuthConfig if configured, None otherwise
250
+ """
251
+ return _auth_config
252
+
253
+
254
+ def is_auth_configured() -> bool:
255
+ """Check if authentication is configured.
256
+
257
+ Returns:
258
+ True if authentication is configured, False otherwise
259
+ """
260
+ return _auth_config is not None
261
+
262
+
263
+ # Breaking change in Golf 0.2.x: Legacy auth system removed
264
+ # Users must migrate to modern auth configurations
265
+
266
+
267
+ def create_auth_provider_from_config() -> object | None:
268
+ """Create an auth provider from the current configuration.
269
+
270
+ Returns:
271
+ FastMCP AuthProvider instance or None if not configured
272
+ """
273
+ config = get_auth_config()
274
+ if not config:
275
+ return None
276
+
277
+ return create_auth_provider(config)
golf/auth/api_key.py ADDED
@@ -0,0 +1,73 @@
1
+ """API Key authentication support for Golf MCP servers.
2
+
3
+ This module provides a simple API key pass-through mechanism for Golf servers,
4
+ allowing tools to access API keys from request headers and forward them to
5
+ upstream services.
6
+ """
7
+
8
+ from pydantic import BaseModel, Field
9
+
10
+
11
+ class ApiKeyConfig(BaseModel):
12
+ """Configuration for API key authentication."""
13
+
14
+ header_name: str = Field("X-API-Key", description="Name of the header containing the API key")
15
+ header_prefix: str = Field(
16
+ "",
17
+ description="Optional prefix to strip from the header value (e.g., 'Bearer ')",
18
+ )
19
+ required: bool = Field(True, description="Whether API key is required for all requests")
20
+
21
+
22
+ # Global configuration storage
23
+ _api_key_config: ApiKeyConfig | None = None
24
+
25
+
26
+ def configure_api_key(header_name: str = "X-API-Key", header_prefix: str = "", required: bool = True) -> None:
27
+ """Configure API key extraction from request headers.
28
+
29
+ This function should be called in auth.py to set up API key handling.
30
+
31
+ Args:
32
+ header_name: Name of the header containing the API key (default: "X-API-Key")
33
+ header_prefix: Optional prefix to strip from the header value (e.g., "Bearer ")
34
+ required: Whether API key is required for all requests (default: True)
35
+
36
+ Example:
37
+ # In auth.py
38
+ from golf.auth.api_key import configure_api_key
39
+
40
+ # Require API key for all requests
41
+ configure_api_key(
42
+ header_name="Authorization",
43
+ header_prefix="Bearer ",
44
+ required=True
45
+ )
46
+
47
+ # Or make API key optional (pass-through mode)
48
+ configure_api_key(
49
+ header_name="Authorization",
50
+ header_prefix="Bearer ",
51
+ required=False
52
+ )
53
+ """
54
+ global _api_key_config
55
+ _api_key_config = ApiKeyConfig(header_name=header_name, header_prefix=header_prefix, required=required)
56
+
57
+
58
+ def get_api_key_config() -> ApiKeyConfig | None:
59
+ """Get the current API key configuration.
60
+
61
+ Returns:
62
+ The API key configuration if set, None otherwise
63
+ """
64
+ return _api_key_config
65
+
66
+
67
+ def is_api_key_configured() -> bool:
68
+ """Check if API key authentication is configured.
69
+
70
+ Returns:
71
+ True if API key authentication is configured, False otherwise
72
+ """
73
+ return _api_key_config is not None