golf-mcp 0.2.5__py3-none-any.whl → 0.2.7__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.

golf/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = "0.2.5"
1
+ __version__ = "0.2.7"
2
2
 
3
3
  # Import endpoints with fallback for dev mode
4
4
  try:
golf/auth/__init__.py CHANGED
@@ -35,6 +35,7 @@ from .helpers import (
35
35
  debug_api_key_context,
36
36
  extract_token_from_header,
37
37
  get_api_key,
38
+ get_auth_token,
38
39
  get_provider_token,
39
40
  set_api_key,
40
41
  )
@@ -72,6 +73,7 @@ __all__ = [
72
73
  "debug_api_key_context",
73
74
  "extract_token_from_header",
74
75
  "get_api_key",
76
+ "get_auth_token",
75
77
  "get_provider_token",
76
78
  "set_api_key",
77
79
  ]
@@ -195,14 +197,14 @@ def configure_dev_auth(
195
197
 
196
198
 
197
199
  def configure_oauth_proxy(
198
- upstream_authorization_endpoint: str,
199
- upstream_token_endpoint: str,
200
- upstream_client_id: str,
201
- upstream_client_secret: str,
200
+ authorization_endpoint: str,
201
+ token_endpoint: str,
202
+ client_id: str,
203
+ client_secret: str,
202
204
  base_url: str,
203
205
  token_verifier_config: JWTAuthConfig | StaticTokenConfig,
204
206
  scopes_supported: list[str] | None = None,
205
- upstream_revocation_endpoint: str | None = None,
207
+ revocation_endpoint: str | None = None,
206
208
  redirect_path: str = "/oauth/callback",
207
209
  ) -> None:
208
210
  """Configure OAuth proxy authentication for non-DCR providers.
@@ -212,25 +214,25 @@ def configure_oauth_proxy(
212
214
  fixed client credentials.
213
215
 
214
216
  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
217
+ authorization_endpoint: Provider's authorization URL
218
+ token_endpoint: Provider's token endpoint URL
219
+ client_id: Your client ID registered with the provider
220
+ client_secret: Your client secret from the provider
219
221
  base_url: This proxy server's public URL
220
222
  token_verifier_config: JWT or static token config for token verification
221
223
  scopes_supported: Scopes to advertise to MCP clients
222
- upstream_revocation_endpoint: Optional token revocation endpoint
224
+ revocation_endpoint: Optional token revocation endpoint
223
225
  redirect_path: OAuth callback path (default: /oauth/callback)
224
226
 
225
227
  Note:
226
228
  Requires golf-mcp-enterprise package for implementation.
227
229
  """
228
230
  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,
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,
234
236
  base_url=base_url,
235
237
  redirect_path=redirect_path,
236
238
  scopes_supported=scopes_supported or [],
golf/auth/helpers.py CHANGED
@@ -142,6 +142,72 @@ def get_api_key_from_request(request: Request) -> str | None:
142
142
  return _current_api_key.get()
143
143
 
144
144
 
145
+ def get_auth_token() -> str | None:
146
+ """Get the authorization token from the current request context.
147
+
148
+ This function should be used in tools to retrieve the authorization token
149
+ (typically a JWT or OAuth token) that was sent in the request headers.
150
+
151
+ Unlike get_api_key(), this function extracts the raw token from the Authorization
152
+ header without stripping any prefix, making it suitable for passing through
153
+ to upstream APIs that expect the full Authorization header value.
154
+
155
+ Returns:
156
+ The authorization token if available, None otherwise
157
+
158
+ Example:
159
+ # In a tool file
160
+ from golf.auth import get_auth_token
161
+
162
+ async def call_upstream_api():
163
+ auth_token = get_auth_token()
164
+ if not auth_token:
165
+ return {"error": "No authorization token provided"}
166
+
167
+ # Use the full token in upstream request
168
+ headers = {"Authorization": f"Bearer {auth_token}"}
169
+ async with httpx.AsyncClient() as client:
170
+ response = await client.get("https://api.example.com/data", headers=headers)
171
+ ...
172
+ """
173
+ # Try to get directly from HTTP request if available (FastMCP pattern)
174
+ try:
175
+ # This follows the FastMCP pattern for accessing HTTP requests
176
+ from fastmcp.server.dependencies import get_http_request
177
+
178
+ request = get_http_request()
179
+
180
+ if request and hasattr(request, "state") and hasattr(request.state, "auth_token"):
181
+ return request.state.auth_token
182
+
183
+ if request:
184
+ # Extract authorization token from Authorization header
185
+ auth_header = None
186
+ for k, v in request.headers.items():
187
+ if k.lower() == "authorization":
188
+ auth_header = v
189
+ break
190
+
191
+ if auth_header:
192
+ # Extract the token part (everything after "Bearer ")
193
+ token = extract_token_from_header(auth_header)
194
+ if token:
195
+ return token
196
+
197
+ # If not Bearer format, return the whole header value minus "Bearer " prefix if present
198
+ if auth_header.lower().startswith("bearer "):
199
+ return auth_header[7:] # Remove "Bearer " prefix
200
+ return auth_header
201
+
202
+ except (ImportError, RuntimeError):
203
+ # FastMCP not available or not in HTTP context
204
+ pass
205
+ except Exception:
206
+ pass
207
+
208
+ return None
209
+
210
+
145
211
  def debug_api_key_context() -> dict[str, Any]:
146
212
  """Debug function to inspect API key context.
147
213
 
golf/auth/providers.py CHANGED
@@ -458,12 +458,12 @@ class OAuthProxyConfig(BaseModel):
458
458
 
459
459
  provider_type: Literal["oauth_proxy"] = "oauth_proxy"
460
460
 
461
- # Upstream OAuth provider configuration
462
- upstream_authorization_endpoint: str = Field(..., description="Upstream provider's authorization endpoint URL")
463
- upstream_token_endpoint: str = Field(..., description="Upstream provider's token endpoint URL")
464
- upstream_client_id: str = Field(..., description="Your registered client ID with the upstream provider")
465
- upstream_client_secret: str = Field(..., description="Your registered client secret with the upstream provider")
466
- upstream_revocation_endpoint: str | None = Field(None, description="Optional upstream token revocation endpoint")
461
+ # OAuth provider configuration
462
+ authorization_endpoint: str = Field(..., description="OAuth provider's authorization endpoint URL")
463
+ token_endpoint: str = Field(..., description="OAuth provider's token endpoint URL")
464
+ client_id: str = Field(..., description="Your registered client ID with the OAuth provider")
465
+ client_secret: str = Field(..., description="Your registered client secret with the OAuth provider")
466
+ revocation_endpoint: str | None = Field(None, description="Optional token revocation endpoint")
467
467
 
468
468
  # This proxy server configuration
469
469
  base_url: str = Field(..., description="Public URL of this OAuth proxy server")
@@ -476,22 +476,18 @@ class OAuthProxyConfig(BaseModel):
476
476
  )
477
477
 
478
478
  # Environment variable names for runtime configuration
479
- upstream_authorization_endpoint_env_var: str | None = Field(
480
- None, description="Environment variable name for upstream authorization endpoint"
479
+ authorization_endpoint_env_var: str | None = Field(
480
+ None, description="Environment variable name for authorization endpoint"
481
481
  )
482
- upstream_token_endpoint_env_var: str | None = Field(
483
- None, description="Environment variable name for upstream token endpoint"
484
- )
485
- upstream_client_id_env_var: str | None = Field(None, description="Environment variable name for upstream client ID")
486
- upstream_client_secret_env_var: str | None = Field(
487
- None, description="Environment variable name for upstream client secret"
488
- )
489
- upstream_revocation_endpoint_env_var: str | None = Field(
490
- None, description="Environment variable name for upstream revocation endpoint"
482
+ token_endpoint_env_var: str | None = Field(None, description="Environment variable name for token endpoint")
483
+ client_id_env_var: str | None = Field(None, description="Environment variable name for client ID")
484
+ client_secret_env_var: str | None = Field(None, description="Environment variable name for client secret")
485
+ revocation_endpoint_env_var: str | None = Field(
486
+ None, description="Environment variable name for revocation endpoint"
491
487
  )
492
488
  base_url_env_var: str | None = Field(None, description="Environment variable name for base URL")
493
489
 
494
- @field_validator("upstream_authorization_endpoint", "upstream_token_endpoint", "base_url")
490
+ @field_validator("authorization_endpoint", "token_endpoint", "base_url")
495
491
  @classmethod
496
492
  def validate_required_urls(cls, v: str) -> str:
497
493
  """Validate required URLs are properly formatted."""
@@ -514,7 +510,7 @@ class OAuthProxyConfig(BaseModel):
514
510
 
515
511
  return url
516
512
 
517
- @field_validator("upstream_revocation_endpoint")
513
+ @field_validator("revocation_endpoint")
518
514
  @classmethod
519
515
  def validate_optional_url(cls, v: str | None) -> str | None:
520
516
  """Validate optional URLs are properly formatted."""
@@ -588,12 +584,12 @@ class OAuthProxyConfig(BaseModel):
588
584
 
589
585
  urls_to_check = [
590
586
  ("base_url", self.base_url),
591
- ("upstream_authorization_endpoint", self.upstream_authorization_endpoint),
592
- ("upstream_token_endpoint", self.upstream_token_endpoint),
587
+ ("authorization_endpoint", self.authorization_endpoint),
588
+ ("token_endpoint", self.token_endpoint),
593
589
  ]
594
590
 
595
- if self.upstream_revocation_endpoint:
596
- urls_to_check.append(("upstream_revocation_endpoint", self.upstream_revocation_endpoint))
591
+ if self.revocation_endpoint:
592
+ urls_to_check.append(("revocation_endpoint", self.revocation_endpoint))
597
593
 
598
594
  for field_name, url in urls_to_check:
599
595
  parsed = urlparse(url)
golf/core/builder.py CHANGED
@@ -170,6 +170,41 @@ class ManifestBuilder:
170
170
  console.print(f"[green]Manifest saved to {output_path}[/green]")
171
171
  return output_path
172
172
 
173
+ def _get_fastmcp_version(self) -> str | None:
174
+ """Get the installed FastMCP version.
175
+
176
+ Returns:
177
+ FastMCP version string (e.g., "2.12.0") or None if not available
178
+ """
179
+ try:
180
+ import fastmcp
181
+
182
+ return fastmcp.__version__
183
+ except (ImportError, AttributeError):
184
+ return None
185
+
186
+ def _is_fastmcp_version_gte(self, target_version: str) -> bool:
187
+ """Check if installed FastMCP version is >= target version.
188
+
189
+ Args:
190
+ target_version: Version string to compare against (e.g., "2.12.0")
191
+
192
+ Returns:
193
+ True if FastMCP version >= target_version, False otherwise
194
+ """
195
+ try:
196
+ from packaging import version
197
+
198
+ current_version = self._get_fastmcp_version()
199
+ if current_version is None:
200
+ # Default to older behavior for safety
201
+ return False
202
+
203
+ return version.parse(current_version) >= version.parse(target_version)
204
+ except (ImportError, ValueError):
205
+ # Default to older behavior for safety
206
+ return False
207
+
173
208
 
174
209
  def build_manifest(project_path: Path, settings: Settings) -> dict[str, Any]:
175
210
  """Build a FastMCP manifest from parsed components.
@@ -511,6 +546,41 @@ class CodeGenerator:
511
546
  and len(component.parameters) > 0
512
547
  )
513
548
 
549
+ def _get_fastmcp_version(self) -> str | None:
550
+ """Get the installed FastMCP version.
551
+
552
+ Returns:
553
+ FastMCP version string (e.g., "2.12.0") or None if not available
554
+ """
555
+ try:
556
+ import fastmcp
557
+
558
+ return fastmcp.__version__
559
+ except (ImportError, AttributeError):
560
+ return None
561
+
562
+ def _is_fastmcp_version_gte(self, target_version: str) -> bool:
563
+ """Check if installed FastMCP version is >= target version.
564
+
565
+ Args:
566
+ target_version: Version string to compare against (e.g., "2.12.0")
567
+
568
+ Returns:
569
+ True if FastMCP version >= target_version, False otherwise
570
+ """
571
+ try:
572
+ from packaging import version
573
+
574
+ current_version = self._get_fastmcp_version()
575
+ if current_version is None:
576
+ # Default to older behavior for safety
577
+ return False
578
+
579
+ return version.parse(current_version) >= version.parse(target_version)
580
+ except (ImportError, ValueError):
581
+ # Default to older behavior for safety
582
+ return False
583
+
514
584
  def _generate_server(self) -> None:
515
585
  """Generate the main server entry point."""
516
586
  server_file = self.output_dir / "server.py"
@@ -956,23 +1026,40 @@ class CodeGenerator:
956
1026
  main_code.extend(middleware_setup)
957
1027
  main_code.append(f" middleware = [{', '.join(middleware_list)}]")
958
1028
  main_code.append("")
959
- main_code.extend(
960
- [
961
- " # Run SSE server with middleware using FastMCP's run method",
962
- f' mcp.run(transport="sse", host=host, port=port, '
963
- f'path="{endpoint_path}", log_level="info", '
964
- f"middleware=middleware, show_banner=False)",
965
- ]
966
- )
1029
+ if self._is_fastmcp_version_gte("2.12.0"):
1030
+ main_code.extend(
1031
+ [
1032
+ " # Run SSE server with middleware using FastMCP's run method",
1033
+ ' mcp.run(transport="sse", host=host, port=port, '
1034
+ 'log_level="info", middleware=middleware, show_banner=False)',
1035
+ ]
1036
+ )
1037
+ else:
1038
+ main_code.extend(
1039
+ [
1040
+ " # Run SSE server with middleware using FastMCP's run method",
1041
+ f' mcp.run(transport="sse", host=host, port=port, '
1042
+ f'path="{endpoint_path}", log_level="info", '
1043
+ f"middleware=middleware, show_banner=False)",
1044
+ ]
1045
+ )
967
1046
  else:
968
- main_code.extend(
969
- [
970
- " # Run SSE server using FastMCP's run method",
971
- f' mcp.run(transport="sse", host=host, port=port, '
972
- f'path="{endpoint_path}", log_level="info", '
973
- f"show_banner=False)",
974
- ]
975
- )
1047
+ if self._is_fastmcp_version_gte("2.12.0"):
1048
+ main_code.extend(
1049
+ [
1050
+ " # Run SSE server using FastMCP's run method",
1051
+ ' mcp.run(transport="sse", host=host, port=port, log_level="info", show_banner=False)',
1052
+ ]
1053
+ )
1054
+ else:
1055
+ main_code.extend(
1056
+ [
1057
+ " # Run SSE server using FastMCP's run method",
1058
+ f' mcp.run(transport="sse", host=host, port=port, '
1059
+ f'path="{endpoint_path}", log_level="info", '
1060
+ f"show_banner=False)",
1061
+ ]
1062
+ )
976
1063
 
977
1064
  elif self.settings.transport in ["streamable-http", "http"]:
978
1065
  # Check if we need middleware for streamable-http
@@ -999,23 +1086,41 @@ class CodeGenerator:
999
1086
  main_code.extend(middleware_setup)
1000
1087
  main_code.append(f" middleware = [{', '.join(middleware_list)}]")
1001
1088
  main_code.append("")
1002
- main_code.extend(
1003
- [
1004
- " # Run HTTP server with middleware using FastMCP's run method",
1005
- f' mcp.run(transport="streamable-http", host=host, '
1006
- f'port=port, path="{endpoint_path}", log_level="info", '
1007
- f"middleware=middleware, show_banner=False)",
1008
- ]
1009
- )
1089
+ if self._is_fastmcp_version_gte("2.12.0"):
1090
+ main_code.extend(
1091
+ [
1092
+ " # Run HTTP server with middleware using FastMCP's run method",
1093
+ ' mcp.run(transport="streamable-http", host=host, '
1094
+ 'port=port, log_level="info", middleware=middleware, show_banner=False)',
1095
+ ]
1096
+ )
1097
+ else:
1098
+ main_code.extend(
1099
+ [
1100
+ " # Run HTTP server with middleware using FastMCP's run method",
1101
+ f' mcp.run(transport="streamable-http", host=host, '
1102
+ f'port=port, path="{endpoint_path}", log_level="info", '
1103
+ f"middleware=middleware, show_banner=False)",
1104
+ ]
1105
+ )
1010
1106
  else:
1011
- main_code.extend(
1012
- [
1013
- " # Run HTTP server using FastMCP's run method",
1014
- f' mcp.run(transport="streamable-http", host=host, '
1015
- f'port=port, path="{endpoint_path}", log_level="info", '
1016
- f"show_banner=False)",
1017
- ]
1018
- )
1107
+ if self._is_fastmcp_version_gte("2.12.0"):
1108
+ main_code.extend(
1109
+ [
1110
+ " # Run HTTP server using FastMCP's run method",
1111
+ ' mcp.run(transport="streamable-http", host=host, '
1112
+ 'port=port, log_level="info", show_banner=False)',
1113
+ ]
1114
+ )
1115
+ else:
1116
+ main_code.extend(
1117
+ [
1118
+ " # Run HTTP server using FastMCP's run method",
1119
+ f' mcp.run(transport="streamable-http", host=host, '
1120
+ f'port=port, path="{endpoint_path}", log_level="info", '
1121
+ f"show_banner=False)",
1122
+ ]
1123
+ )
1019
1124
  else:
1020
1125
  # For stdio transport, use mcp.run()
1021
1126
  main_code.extend([" # Run with stdio transport", ' mcp.run(transport="stdio", show_banner=False)'])
@@ -45,4 +45,4 @@ class WeatherApiClient:
45
45
  weather_client = WeatherApiClient()
46
46
 
47
47
  # This could also define shared models or other utilities
48
- # that would be common across weather-related resources
48
+ # that would be common across weather-related resources
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: golf-mcp
3
- Version: 0.2.5
3
+ Version: 0.2.7
4
4
  Summary: Framework for building MCP servers
5
5
  Author-email: Antoni Gmitruk <antoni@golf.dev>
6
6
  License-Expression: Apache-2.0
@@ -132,7 +132,6 @@ A Golf project initialized with `golf init` will have a structure similar to thi
132
132
  - **`auth.py`**: Dedicated authentication configuration file (new in v0.2.0, breaking change from v0.1.x authentication API) for JWT, OAuth Server, API key, or development authentication.
133
133
  - **`tools/`**, **`resources/`**, **`prompts/`**: Contain your Python files, each defining a single component. These directories can also contain nested subdirectories to further organize your components (e.g., `tools/payments/charge.py`). The module docstring of each file serves as the component's description.
134
134
  - Component IDs are automatically derived from their file path. For example, `tools/hello.py` becomes `hello`, and a nested file like `tools/payments/submit.py` would become `submit_payments` (filename, followed by reversed parent directories under the main category, joined by underscores).
135
- - **`common.py`** (not shown, but can be placed in subdirectories like `tools/payments/common.py`): Used to share code (clients, models, etc.) among components in the same subdirectory.
136
135
 
137
136
  ## Example: Defining a Tool
138
137
 
@@ -1,12 +1,12 @@
1
- golf/__init__.py,sha256=pjc5BpzhL3Rn_QfzuqOyLUq-KgJ0p4QvvBcMgLuFU8I,306
1
+ golf/__init__.py,sha256=6vytM_ZxcMhG5rXftdEzDMmvD941REm-UGAitD-fBss,306
2
2
  golf/_endpoints.py,sha256=-mvAmjx3YtqfAdajO13Kv7LKVBMdqsKqX0_3aCmCK4I,317
3
3
  golf/_endpoints.py.in,sha256=MeqcSF6xinnPknpBGF26xA9FYmSYKSWqCFXOSDlXiOA,216
4
4
  golf/_endpoints_fallback.py,sha256=CD6m45Ams1A9HVKowY8dCFUDMiFmJ8ZWSwHCENvU5u4,386
5
- golf/auth/__init__.py,sha256=EGCGcxHjTaEClYqXWa5os1hxv0p6IkqYmwJ7LyNm6LY,8165
5
+ golf/auth/__init__.py,sha256=u-6_EFTvfs91B2Jko39swp3tCpHkj3r9wDQzQBmfxn0,8027
6
6
  golf/auth/api_key.py,sha256=OonqTlG6USJxqK8TlPviJTv7sgYmTVfCxG_JsEjnEM4,2320
7
7
  golf/auth/factory.py,sha256=3-il1GbjjZlQfvWUZs-09r61Y_-b5cYEegWF7sY_cUs,13128
8
- golf/auth/helpers.py,sha256=ElyX5iyDLfjFIFzE2psavWA3I1_QG1lcuNWsQ2G9bw0,5672
9
- golf/auth/providers.py,sha256=N3klWpAwCjZQw0ecCiCantjrd9FxQv29iQVgeZOwEGA,26233
8
+ golf/auth/helpers.py,sha256=WoYyjUAQwgDnLvJDvyhuEOmm8w0fQ-ZDqaYxs_lC8nw,8127
9
+ golf/auth/providers.py,sha256=qgybeHtrb0MojUsXZm813gzT4zBCNxCiSCWvxKG2iis,25950
10
10
  golf/auth/registry.py,sha256=Rjj7LnWvzEsI1GCnFbFcxpRllrVanD9bumWPaJ1giFQ,7960
11
11
  golf/cli/__init__.py,sha256=R8Y8KdD2C8gDo24fXGq-fdWWNeaq3MYjrbaSB8Hb-Hg,45
12
12
  golf/cli/branding.py,sha256=ndpy2kVxBzqr4fwsAlh_fbhxqgRPoF6kM3ufP9hg5QI,6896
@@ -16,7 +16,7 @@ golf/commands/build.py,sha256=sLq9lSW4naq2vIlBreKI5SGnviQrhBWw13zfOZOKhuM,2293
16
16
  golf/commands/init.py,sha256=KkAg_3-KxBDFOcZqUHqcPAkDipykFVaLWpQ2tydnVPk,9617
17
17
  golf/commands/run.py,sha256=a8GSwLt6E2cUJespv-u3jbD-rNUMHqF3VArD1uXV-Vk,4299
18
18
  golf/core/__init__.py,sha256=4bKeskJ2fPaZqkz2xQScSa3phRLLrmrczwSL632jv-o,52
19
- golf/core/builder.py,sha256=Ghm9YUDIWnUc0bIxfKD75OZIa-h0B61iC26OEmfA4ug,62214
19
+ golf/core/builder.py,sha256=Tx6AtWnnasY_Rfu1CEdhE7y3hZdN0RuhwLevJU9vZgo,66355
20
20
  golf/core/builder_auth.py,sha256=SXPCpc5ipntoNqIAIA2ZCeGmEua6QVs7yC3MDtGKAro,8224
21
21
  golf/core/builder_metrics.py,sha256=j6Gtgd867o46JbDfSNGNsHt1QtV1XHKUJs1z8r4siQM,8830
22
22
  golf/core/builder_telemetry.py,sha256=86bp7UlMUN6JyQRrZ5EizovP6AJ_q65OANJTeJXDIKc,3421
@@ -34,7 +34,7 @@ golf/examples/basic/prompts/welcome.py,sha256=xyW4pwvpcPQi0_H9tP7OX53Kv62R1aCYcV
34
34
  golf/examples/basic/resources/current_time.py,sha256=bJMrRZQ0WPgnQxMl_4-4ynZyq7ki-wGMbMFpaYOH7PY,859
35
35
  golf/examples/basic/resources/info.py,sha256=LxHzg_TmwonSu1vSkuNcpUq5JrBu-9yzoGaARE1f2KU,727
36
36
  golf/examples/basic/resources/weather/city.py,sha256=pRgceEP4ZRDVFEJA4kQf54n0pb37TMdFLgqFL1cHZZs,1278
37
- golf/examples/basic/resources/weather/client.py,sha256=Qyj72OeRFaPtb0tLUerPgIhNuENeqb_u36wSzqP3Nuc,1678
37
+ golf/examples/basic/resources/weather/client.py,sha256=E6250OfgjSLcRSK14B0LFth8siKNRhN8yRwjy0LuO9A,1679
38
38
  golf/examples/basic/resources/weather/current.py,sha256=muT77pUxnHQJSnrX5x4itzrjTSzK_hPbbkjVh3LGlh4,933
39
39
  golf/examples/basic/resources/weather/forecast.py,sha256=xhSpK71gWsCIpyzYyqY7KhoUHn38xpR6srZ-2Vqww8Q,990
40
40
  golf/examples/basic/tools/calculator.py,sha256=QTDvE7ItMol2eIR1mgc6moRhhl3p-q63bgieWr5yF5c,3070
@@ -48,9 +48,9 @@ golf/utilities/__init__.py,sha256=X9iY9yi3agz1GVcn8-qWeOCt8CSSsruHxqPNtiF63TY,53
48
48
  golf/utilities/context.py,sha256=DGGvhVe---QMhy0wtdWhNp-_WVk1NvAcOFn0uBKBpYo,1579
49
49
  golf/utilities/elicitation.py,sha256=MParZZZsY45s70-KXduHa6IvpWXnLW2FCPfrGijMaHs,5223
50
50
  golf/utilities/sampling.py,sha256=88nDv-trBE4gZQbcnMjXl3LW6TiIhv5zR_cuEIGjaIM,7233
51
- golf_mcp-0.2.5.dist-info/licenses/LICENSE,sha256=5_j2f6fTJmvfmUewzElhkpAaXg2grVoxKouOA8ihV6E,11348
52
- golf_mcp-0.2.5.dist-info/METADATA,sha256=LBA45kjycZuDRt4HHmhH770mcj9yqugCv_FsEaomoGU,9558
53
- golf_mcp-0.2.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
54
- golf_mcp-0.2.5.dist-info/entry_points.txt,sha256=5y7rHYM8jGpU-nfwdknCm5XsApLulqsnA37MO6BUTYg,43
55
- golf_mcp-0.2.5.dist-info/top_level.txt,sha256=BQToHcBUufdyhp9ONGMIvPE40jMEtmI20lYaKb4hxOg,5
56
- golf_mcp-0.2.5.dist-info/RECORD,,
51
+ golf_mcp-0.2.7.dist-info/licenses/LICENSE,sha256=5_j2f6fTJmvfmUewzElhkpAaXg2grVoxKouOA8ihV6E,11348
52
+ golf_mcp-0.2.7.dist-info/METADATA,sha256=5F9gLHC0HqScjtaPXvIWJ30JfX4CSFIkVRvXQYYl5cI,9370
53
+ golf_mcp-0.2.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
54
+ golf_mcp-0.2.7.dist-info/entry_points.txt,sha256=5y7rHYM8jGpU-nfwdknCm5XsApLulqsnA37MO6BUTYg,43
55
+ golf_mcp-0.2.7.dist-info/top_level.txt,sha256=BQToHcBUufdyhp9ONGMIvPE40jMEtmI20lYaKb4hxOg,5
56
+ golf_mcp-0.2.7.dist-info/RECORD,,