golf-mcp 0.1.16__py3-none-any.whl → 0.1.17__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/core/platform.py ADDED
@@ -0,0 +1,180 @@
1
+ """Platform registration for Golf MCP projects."""
2
+
3
+ import os
4
+ from datetime import datetime
5
+ from pathlib import Path
6
+ from typing import Any
7
+
8
+ import httpx
9
+ from rich.console import Console
10
+
11
+ from golf import __version__
12
+ from golf.core.config import Settings
13
+ from golf.core.parser import ComponentType, ParsedComponent
14
+
15
+ console = Console()
16
+
17
+
18
+ async def register_project_with_platform(
19
+ project_path: Path,
20
+ settings: Settings,
21
+ components: dict[ComponentType, list[ParsedComponent]],
22
+ ) -> bool:
23
+ """Register project with Golf platform during prod build.
24
+
25
+ Args:
26
+ project_path: Path to the project root
27
+ settings: Project settings
28
+ components: Parsed components dictionary
29
+
30
+ Returns:
31
+ True if registration succeeded or was skipped, False if failed
32
+ """
33
+ # Check if platform integration is enabled
34
+ api_key = os.getenv("GOLF_API_KEY")
35
+ if not api_key:
36
+ return True # Skip silently if no API key
37
+
38
+ # Require explicit server ID
39
+ server_id = os.getenv("GOLF_SERVER_ID")
40
+ if not server_id:
41
+ console.print(
42
+ "[yellow]Warning: Platform registration skipped - GOLF_SERVER_ID environment variable required[/yellow]"
43
+ )
44
+ return True # Skip registration but don't fail build
45
+
46
+ # Build metadata payload
47
+ metadata = {
48
+ "project_name": settings.name,
49
+ "description": settings.description,
50
+ "server_id": server_id,
51
+ "components": _build_component_list(components, project_path),
52
+ "build_timestamp": datetime.utcnow().isoformat(),
53
+ "golf_version": __version__,
54
+ "component_counts": _get_component_counts(components),
55
+ "server_config": {
56
+ "host": settings.host,
57
+ "port": settings.port,
58
+ "transport": settings.transport,
59
+ "auth_enabled": bool(settings.auth),
60
+ "telemetry_enabled": settings.opentelemetry_enabled,
61
+ "health_check_enabled": settings.health_check_enabled,
62
+ },
63
+ }
64
+
65
+ try:
66
+ async with httpx.AsyncClient(timeout=10.0) as client:
67
+ response = await client.post(
68
+ "http://localhost:8000/api/resources",
69
+ json=metadata,
70
+ headers={
71
+ "X-Golf-Key": api_key,
72
+ "Content-Type": "application/json",
73
+ "User-Agent": f"Golf-MCP/{__version__}",
74
+ },
75
+ )
76
+ response.raise_for_status()
77
+
78
+ console.print("[green]✓[/green] Registered with Golf platform")
79
+ return True
80
+
81
+ except httpx.TimeoutException:
82
+ console.print("[yellow]Warning: Platform registration timed out[/yellow]")
83
+ return False
84
+ except httpx.HTTPStatusError as e:
85
+ if e.response.status_code == 401:
86
+ console.print(
87
+ "[yellow]Warning: Platform registration failed - invalid API key[/yellow]"
88
+ )
89
+ elif e.response.status_code == 403:
90
+ console.print(
91
+ "[yellow]Warning: Platform registration failed - access denied[/yellow]"
92
+ )
93
+ else:
94
+ console.print(
95
+ f"[yellow]Warning: Platform registration failed - HTTP {e.response.status_code}[/yellow]"
96
+ )
97
+ return False
98
+ except Exception as e:
99
+ console.print(f"[yellow]Warning: Platform registration failed: {e}[/yellow]")
100
+ return False # Don't fail the build
101
+
102
+
103
+ def _build_component_list(
104
+ components: dict[ComponentType, list[ParsedComponent]],
105
+ project_path: Path,
106
+ ) -> list[dict[str, Any]]:
107
+ """Convert parsed components to platform format.
108
+
109
+ Args:
110
+ components: Dictionary of parsed components by type
111
+ project_path: Path to the project root
112
+
113
+ Returns:
114
+ List of component metadata dictionaries
115
+ """
116
+ result = []
117
+
118
+ for comp_type, comp_list in components.items():
119
+ for comp in comp_list:
120
+ # Start with basic component data
121
+ component_data = {
122
+ "name": comp.name,
123
+ "type": comp_type.value,
124
+ "description": comp.docstring,
125
+ "entry_function": comp.entry_function,
126
+ "parent_module": comp.parent_module,
127
+ }
128
+
129
+ # Add file path relative to project root if available
130
+ if comp.file_path:
131
+ try:
132
+ file_path = Path(comp.file_path)
133
+ # Use the provided project_path for relative calculation
134
+ rel_path = file_path.relative_to(project_path)
135
+ component_data["file_path"] = str(rel_path)
136
+ except ValueError:
137
+ # If relative_to fails, try to find a common path or use filename
138
+ component_data["file_path"] = Path(comp.file_path).name
139
+
140
+ # Add schema information only if available and not None
141
+ if hasattr(comp, "input_schema") and comp.input_schema:
142
+ component_data["input_schema"] = comp.input_schema
143
+ if hasattr(comp, "output_schema") and comp.output_schema:
144
+ component_data["output_schema"] = comp.output_schema
145
+
146
+ # Add component-specific fields only if they have values
147
+ if comp_type == ComponentType.RESOURCE:
148
+ if hasattr(comp, "uri_template") and comp.uri_template:
149
+ component_data["uri_template"] = comp.uri_template
150
+
151
+ elif comp_type == ComponentType.TOOL:
152
+ if hasattr(comp, "annotations") and comp.annotations:
153
+ component_data["annotations"] = comp.annotations
154
+
155
+ # Add parameters only if they exist and are not empty
156
+ if hasattr(comp, "parameters") and comp.parameters:
157
+ component_data["parameters"] = comp.parameters
158
+
159
+ result.append(component_data)
160
+
161
+ return result
162
+
163
+
164
+ def _get_component_counts(
165
+ components: dict[ComponentType, list[ParsedComponent]],
166
+ ) -> dict[str, int]:
167
+ """Get component counts by type.
168
+
169
+ Args:
170
+ components: Dictionary of parsed components by type
171
+
172
+ Returns:
173
+ Dictionary with counts for each component type
174
+ """
175
+ return {
176
+ "tools": len(components.get(ComponentType.TOOL, [])),
177
+ "resources": len(components.get(ComponentType.RESOURCE, [])),
178
+ "prompts": len(components.get(ComponentType.PROMPT, [])),
179
+ "total": sum(len(comp_list) for comp_list in components.values()),
180
+ }
golf/core/telemetry.py CHANGED
@@ -109,9 +109,9 @@ def is_telemetry_enabled() -> bool:
109
109
  _telemetry_enabled = saved_preference
110
110
  return saved_preference
111
111
 
112
- # Default to enabled (opt-out model)
113
- _telemetry_enabled = True
114
- return True
112
+ # Default to disabled (opt-in model)
113
+ _telemetry_enabled = False
114
+ return False
115
115
 
116
116
 
117
117
  def set_telemetry_enabled(enabled: bool, persist: bool = True) -> None:
@@ -209,13 +209,24 @@ def initialize_telemetry() -> None:
209
209
  posthog.disabled = False
210
210
  posthog.debug = False
211
211
 
212
+ # Disable IP collection and GeoIP enrichment at the SDK level
213
+ posthog.set_global_event_properties(
214
+ {
215
+ "$ip": "0", # Override IP with dummy value to prevent collection
216
+ "$geoip_disable": True, # Disable all GeoIP enrichment
217
+ }
218
+ )
219
+
212
220
  except Exception:
213
221
  # Telemetry should never break the application
214
222
  pass
215
223
 
216
224
 
217
225
  def track_event(event_name: str, properties: dict[str, Any] | None = None) -> None:
218
- """Track an anonymous event with minimal data.
226
+ """Track an anonymous event with NO IP address or geolocation data.
227
+
228
+ IP collection and GeoIP enrichment are disabled at the SDK level to ensure
229
+ complete privacy protection. No IP addresses or location data ever reach PostHog.
219
230
 
220
231
  Args:
221
232
  event_name: Name of the event (e.g., "cli_init", "cli_build")
@@ -257,8 +268,16 @@ def track_event(event_name: str, properties: dict[str, Any] | None = None) -> No
257
268
  }
258
269
  }
259
270
 
260
- # Identify the user with properties
261
- posthog.identify(distinct_id=anonymous_id, properties=person_properties)
271
+ # Identify the user with properties (IP tracking disabled)
272
+ posthog.identify(
273
+ distinct_id=anonymous_id,
274
+ properties={
275
+ **person_properties,
276
+ # Explicitly disable IP tracking in identify call
277
+ "$ip": "0",
278
+ "$geoip_disable": True,
279
+ },
280
+ )
262
281
 
263
282
  _user_identified = True
264
283
 
@@ -267,8 +286,9 @@ def track_event(event_name: str, properties: dict[str, Any] | None = None) -> No
267
286
  "golf_version": __version__,
268
287
  "python_version": f"{platform.python_version_tuple()[0]}.{platform.python_version_tuple()[1]}",
269
288
  "os": platform.system(),
270
- # Explicitly disable IP tracking
271
- "$ip": None,
289
+ # Explicitly disable IP tracking and GeoIP enrichment
290
+ "$ip": "0", # Override IP to prevent collection
291
+ "$geoip_disable": True, # Disable GeoIP enrichment
272
292
  }
273
293
 
274
294
  # Filter properties to only include safe ones
@@ -1,5 +1 @@
1
- GOLF_CLIENT_ID="default-client-id"
2
- GOLF_CLIENT_SECRET="default-secret"
3
- JWT_SECRET="example-jwt-secret-for-development-only"
4
- OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318/v1/traces"
5
- OTEL_SERVICE_NAME="golf-mcp"
1
+ #GOLF_API_KEY=<your-api-key>
@@ -7,26 +7,26 @@ This example demonstrates how to build a GitHub API MCP server using Golf's API
7
7
  This MCP server provides tools for:
8
8
 
9
9
  - **Repository Management**
10
- - `list-repos` - List repositories for users, organizations, or the authenticated user
10
+ - `list_repos` - List repositories for users, organizations, or the authenticated user
11
11
 
12
12
  - **Issue Management**
13
- - `create-issues` - Create new issues with labels
14
- - `list-issues` - List and filter issues by state and labels
13
+ - `create_issues` - Create new issues with labels
14
+ - `list_issues` - List and filter issues by state and labels
15
15
 
16
16
  - **Code Search**
17
- - `code-search` - Search for code across GitHub with language and repository filters
17
+ - `code_search` - Search for code across GitHub with language and repository filters
18
18
 
19
19
  - **User Information**
20
- - `get-users` - Get user profiles or verify authentication
20
+ - `get_users` - Get user profiles or verify authentication
21
21
 
22
22
  ## Tool Naming Convention
23
23
 
24
24
  Golf automatically derives tool names from the file structure:
25
- - `tools/issues/create.py` → `create-issues`
26
- - `tools/issues/list.py` → `list-issues`
27
- - `tools/repos/list.py` → `list-repos`
28
- - `tools/search/code.py` → `code-search`
29
- - `tools/users/get.py` → `get-users`
25
+ - `tools/issues/create.py` → `create_issues`
26
+ - `tools/issues/list.py` → `list_issues`
27
+ - `tools/repos/list.py` → `list_repos`
28
+ - `tools/search/code.py` → `code_search`
29
+ - `tools/users/get.py` → `get_users`
30
30
 
31
31
  ## Configuration
32
32
 
@@ -4,9 +4,5 @@
4
4
  "host": "127.0.0.1",
5
5
  "port": 3000,
6
6
  "transport": "sse",
7
- "health_check_enabled": false,
8
- "health_check_path": "/health",
9
- "health_check_response": "OK",
10
- "opentelemetry_enabled": true,
11
- "opentelemetry_default_exporter": "otlp_http"
7
+ "opentelemetry_enabled": false
12
8
  }
@@ -1,5 +1,4 @@
1
- GOLF_CLIENT_ID="default-client-id"
2
- GOLF_CLIENT_SECRET="default-secret"
1
+ GITHUB_CLIENT_ID="default-client-id"
2
+ GITHUB_CLIENT_SECRET="default-secret"
3
3
  JWT_SECRET="example-jwt-secret-for-development-only"
4
- OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318/v1/traces"
5
- OTEL_SERVICE_NAME="golf-mcp"
4
+ #GOLF_API_KEY=<your-api-key>
@@ -4,9 +4,5 @@
4
4
  "host": "127.0.0.1",
5
5
  "port": 3000,
6
6
  "transport": "sse",
7
- "health_check_enabled": false,
8
- "health_check_path": "/health",
9
- "health_check_response": "OK",
10
- "opentelemetry_enabled": true,
11
- "opentelemetry_default_exporter": "otlp_http"
7
+ "opentelemetry_enabled": false
12
8
  }
@@ -29,6 +29,15 @@ def init_telemetry(service_name: str = "golf-mcp-server") -> TracerProvider | No
29
29
  """
30
30
  global _provider
31
31
 
32
+ # Check for Golf platform integration first
33
+ golf_api_key = os.environ.get("GOLF_API_KEY")
34
+ if golf_api_key and not os.environ.get("OTEL_EXPORTER_OTLP_ENDPOINT"):
35
+ # Auto-configure for Golf platform
36
+ os.environ["OTEL_TRACES_EXPORTER"] = "otlp_http"
37
+ os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "http://localhost:8000/api/v1/otel"
38
+ os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = f"X-Golf-Key={golf_api_key}"
39
+ print("[INFO] Auto-configured OpenTelemetry for Golf platform ingestion")
40
+
32
41
  # Check for required environment variables based on exporter type
33
42
  exporter_type = os.environ.get("OTEL_TRACES_EXPORTER", "console").lower()
34
43
 
@@ -37,7 +46,8 @@ def init_telemetry(service_name: str = "golf-mcp-server") -> TracerProvider | No
37
46
  endpoint = os.environ.get("OTEL_EXPORTER_OTLP_ENDPOINT")
38
47
  if not endpoint:
39
48
  print(
40
- "[WARNING] OpenTelemetry tracing is disabled: OTEL_EXPORTER_OTLP_ENDPOINT is not set for OTLP HTTP exporter"
49
+ "[WARNING] OpenTelemetry tracing is disabled: "
50
+ "OTEL_EXPORTER_OTLP_ENDPOINT is not set for OTLP HTTP exporter"
41
51
  )
42
52
  return None
43
53
 
@@ -47,6 +57,14 @@ def init_telemetry(service_name: str = "golf-mcp-server") -> TracerProvider | No
47
57
  "service.version": os.environ.get("SERVICE_VERSION", "1.0.0"),
48
58
  "service.instance.id": os.environ.get("SERVICE_INSTANCE_ID", "default"),
49
59
  }
60
+
61
+ # Add Golf-specific attributes if available
62
+ if golf_api_key:
63
+ golf_server_id = os.environ.get("GOLF_SERVER_ID")
64
+ if golf_server_id:
65
+ resource_attributes["golf.server.id"] = golf_server_id
66
+ resource_attributes["golf.platform.enabled"] = "true"
67
+
50
68
  resource = Resource.create(resource_attributes)
51
69
 
52
70
  # Create provider
@@ -71,6 +89,10 @@ def init_telemetry(service_name: str = "golf-mcp-server") -> TracerProvider | No
71
89
  exporter = OTLPSpanExporter(
72
90
  endpoint=endpoint, headers=header_dict if header_dict else None
73
91
  )
92
+
93
+ # Log successful configuration for Golf platform
94
+ if golf_api_key:
95
+ print(f"[INFO] OpenTelemetry configured for Golf platform: {endpoint}")
74
96
  else:
75
97
  # Default to console exporter
76
98
  exporter = ConsoleSpanExporter(out=sys.stderr)
@@ -113,21 +135,6 @@ def init_telemetry(service_name: str = "golf-mcp-server") -> TracerProvider | No
113
135
  traceback.print_exc()
114
136
  raise
115
137
 
116
- # Create a test span to verify everything is working
117
- try:
118
- test_tracer = provider.get_tracer("golf.telemetry.test", "1.0.0")
119
- with test_tracer.start_as_current_span("startup.test") as span:
120
- span.set_attribute("test", True)
121
- span.set_attribute("service.name", service_name)
122
- span.set_attribute("exporter.type", exporter_type)
123
- span.set_attribute(
124
- "endpoint", os.environ.get("OTEL_EXPORTER_OTLP_ENDPOINT", "not set")
125
- )
126
- except Exception:
127
- import traceback
128
-
129
- traceback.print_exc()
130
-
131
138
  return provider
132
139
 
133
140
 
@@ -154,15 +161,8 @@ def instrument_tool(func: Callable[..., T], tool_name: str) -> Callable[..., T]:
154
161
 
155
162
  tracer = get_tracer()
156
163
 
157
- # Add debug logging
158
- print(
159
- f"[TELEMETRY DEBUG] Instrumenting tool: {tool_name} (function: {func.__name__})"
160
- )
161
-
162
164
  @functools.wraps(func)
163
165
  async def async_wrapper(*args, **kwargs):
164
- print(f"[TELEMETRY DEBUG] Executing async tool: {tool_name}")
165
-
166
166
  # Create a more descriptive span name
167
167
  span_name = f"mcp.tool.{tool_name}.execute"
168
168
 
@@ -247,10 +247,6 @@ def instrument_tool(func: Callable[..., T], tool_name: str) -> Callable[..., T]:
247
247
  # Add event for tool execution start
248
248
  span.add_event("tool.execution.started", {"tool.name": tool_name})
249
249
 
250
- print(
251
- f"[TELEMETRY DEBUG] Tool span created: {span_name} (span_id: {span.get_span_context().span_id:016x})"
252
- )
253
-
254
250
  try:
255
251
  result = await func(*args, **kwargs)
256
252
  span.set_status(Status(StatusCode.OK))
@@ -288,9 +284,6 @@ def instrument_tool(func: Callable[..., T], tool_name: str) -> Callable[..., T]:
288
284
  # For any result, record its type
289
285
  span.set_attribute("mcp.tool.result.class", type(result).__name__)
290
286
 
291
- print(
292
- f"[TELEMETRY DEBUG] Tool execution completed successfully: {tool_name}"
293
- )
294
287
  return result
295
288
  except Exception as e:
296
289
  span.record_exception(e)
@@ -305,13 +298,10 @@ def instrument_tool(func: Callable[..., T], tool_name: str) -> Callable[..., T]:
305
298
  "error.message": str(e),
306
299
  },
307
300
  )
308
- print(f"[TELEMETRY DEBUG] Tool execution failed: {tool_name} - {e}")
309
301
  raise
310
302
 
311
303
  @functools.wraps(func)
312
304
  def sync_wrapper(*args, **kwargs):
313
- print(f"[TELEMETRY DEBUG] Executing sync tool: {tool_name}")
314
-
315
305
  # Create a more descriptive span name
316
306
  span_name = f"mcp.tool.{tool_name}.execute"
317
307
 
@@ -396,10 +386,6 @@ def instrument_tool(func: Callable[..., T], tool_name: str) -> Callable[..., T]:
396
386
  # Add event for tool execution start
397
387
  span.add_event("tool.execution.started", {"tool.name": tool_name})
398
388
 
399
- print(
400
- f"[TELEMETRY DEBUG] Tool span created: {span_name} (span_id: {span.get_span_context().span_id:016x})"
401
- )
402
-
403
389
  try:
404
390
  result = func(*args, **kwargs)
405
391
  span.set_status(Status(StatusCode.OK))
@@ -437,9 +423,6 @@ def instrument_tool(func: Callable[..., T], tool_name: str) -> Callable[..., T]:
437
423
  # For any result, record its type
438
424
  span.set_attribute("mcp.tool.result.class", type(result).__name__)
439
425
 
440
- print(
441
- f"[TELEMETRY DEBUG] Tool execution completed successfully: {tool_name}"
442
- )
443
426
  return result
444
427
  except Exception as e:
445
428
  span.record_exception(e)
@@ -454,7 +437,6 @@ def instrument_tool(func: Callable[..., T], tool_name: str) -> Callable[..., T]:
454
437
  "error.message": str(e),
455
438
  },
456
439
  )
457
- print(f"[TELEMETRY DEBUG] Tool execution failed: {tool_name} - {e}")
458
440
  raise
459
441
 
460
442
  # Return appropriate wrapper based on function type
@@ -1004,16 +986,13 @@ async def telemetry_lifespan(mcp_instance):
1004
986
  app = getattr(mcp_instance, "app", getattr(mcp_instance, "_app", None))
1005
987
  if app and hasattr(app, "add_middleware"):
1006
988
  app.add_middleware(SessionTracingMiddleware)
1007
- print("[TELEMETRY DEBUG] Added SessionTracingMiddleware to FastMCP app")
1008
989
 
1009
990
  # Also try to instrument FastMCP's internal handlers
1010
991
  if hasattr(mcp_instance, "_tool_manager") and hasattr(
1011
992
  mcp_instance._tool_manager, "tools"
1012
993
  ):
1013
- print(
1014
- f"[TELEMETRY DEBUG] Found {len(mcp_instance._tool_manager.tools)} tools in FastMCP"
1015
- )
1016
994
  # The tools should already be instrumented when they were registered
995
+ pass
1017
996
 
1018
997
  # Try to patch FastMCP's request handling to ensure context propagation
1019
998
  if hasattr(mcp_instance, "handle_request"):
@@ -1026,10 +1005,9 @@ async def telemetry_lifespan(mcp_instance):
1026
1005
  return await original_handle_request(*args, **kwargs)
1027
1006
 
1028
1007
  mcp_instance.handle_request = traced_handle_request
1029
- print("[TELEMETRY DEBUG] Patched FastMCP handle_request method")
1030
1008
 
1031
- except Exception as e:
1032
- print(f"[TELEMETRY DEBUG] Error setting up telemetry middleware: {e}")
1009
+ except Exception:
1010
+ # Silently continue if middleware setup fails
1033
1011
  import traceback
1034
1012
 
1035
1013
  traceback.print_exc()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: golf-mcp
3
- Version: 0.1.16
3
+ Version: 0.1.17
4
4
  Summary: Framework for building MCP servers
5
5
  Author-email: Antoni Gmitruk <antoni@golf.dev>
6
6
  License-Expression: Apache-2.0
@@ -21,7 +21,7 @@ Description-Content-Type: text/markdown
21
21
  License-File: LICENSE
22
22
  Requires-Dist: typer>=0.15.4
23
23
  Requires-Dist: rich>=14.0.0
24
- Requires-Dist: fastmcp>=2.0.0
24
+ Requires-Dist: fastmcp<2.6.0,>=2.0.0
25
25
  Requires-Dist: pydantic>=2.11.0
26
26
  Requires-Dist: python-dotenv>=1.1.0
27
27
  Requires-Dist: black>=24.10.0
@@ -128,7 +128,7 @@ A Golf project initialized with `golf init` will have a structure similar to thi
128
128
 
129
129
  - **`golf.json`**: Configures server name, port, transport, telemetry, and other build settings.
130
130
  - **`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.
131
- - 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 hyphens).
131
+ - 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).
132
132
  - **`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.
133
133
 
134
134
  ## Example: Defining a Tool
@@ -178,6 +178,10 @@ The `golf.json` file is the heart of your Golf project configuration. Here's wha
178
178
  // - "streamable-http": HTTP with streaming support
179
179
  // - "stdio": Standard I/O (for CLI integration)
180
180
 
181
+ // HTTP Transport Configuration (optional)
182
+ "stateless_http": false, // Make streamable-http transport stateless (new session per request)
183
+ // When true, server restarts won't break existing client connections
184
+
181
185
  // Health Check Configuration (optional)
182
186
  "health_check_enabled": false, // Enable health check endpoint for Kubernetes/load balancers
183
187
  "health_check_path": "/health", // HTTP path for health check endpoint
@@ -198,6 +202,7 @@ The `golf.json` file is the heart of your Golf project configuration. Here's wha
198
202
  - `"streamable-http"` provides HTTP streaming for traditional API clients
199
203
  - `"stdio"` enables integration with command-line tools and scripts
200
204
  - **`host` & `port`**: Control where your server listens. Use `"127.0.0.1"` for local development or `"0.0.0.0"` to accept external connections.
205
+ - **`stateless_http`**: When true, makes the streamable-http transport stateless by creating a new session for each request. This ensures that server restarts don't break existing client connections, making the server truly stateless.
201
206
  - **`health_check_enabled`**: When true, enables a health check endpoint for Kubernetes readiness/liveness probes and load balancers
202
207
  - **`health_check_path`**: Customizable path for the health check endpoint (defaults to "/health")
203
208
  - **`health_check_response`**: Customizable response text for successful health checks (defaults to "OK")
@@ -1,28 +1,29 @@
1
- golf/__init__.py,sha256=yF88-8vL8keLe6gCTumymw0UoMkWkSrJnzLru4zBCLQ,23
1
+ golf/__init__.py,sha256=BzIjnki8Bz3evNWo6bjGxxpLhy_tN9MRYhtM0MnDiWs,23
2
2
  golf/auth/__init__.py,sha256=Rj4yUngJklk6xrDCrxqLTtoDAMzF1HcTvy_l8wREeao,4103
3
3
  golf/auth/api_key.py,sha256=LiIraLiH2v7s3yavidaI6BDlAEfK8XnWF15QmaJn9G4,2378
4
4
  golf/auth/helpers.py,sha256=ZogdcHM7J2PN6cL6F6OLZ3gyoUR3dwAFDxOJQ2DW_bc,6526
5
5
  golf/auth/oauth.py,sha256=-TYcMA4ULWNQacmUvzek2uQVMJpRT3hXC_d5D2k9c44,31156
6
6
  golf/auth/provider.py,sha256=3loeYrkNwIRDvyUkf8gbcCRJSiKiVXgE_rMGCSCr5mk,3802
7
7
  golf/cli/__init__.py,sha256=R8Y8KdD2C8gDo24fXGq-fdWWNeaq3MYjrbaSB8Hb-Hg,45
8
- golf/cli/main.py,sha256=izB2DW4uLtY-twcacMjsBDtywbXaAIhV1EQdgiso2LE,13495
8
+ golf/cli/main.py,sha256=3qexjKNL8vYg-48ATYcwW4-Wv45l3VxntW-mSqDAbEc,13958
9
9
  golf/commands/__init__.py,sha256=GKtIEm7EPQWRgot73RPZPWegwN7Zm0bHtUJbR63FNiw,83
10
10
  golf/commands/build.py,sha256=jhdxB5EwwCC_8PgqdXLUKuBpnycjh0gft3_7EuTo6ro,2319
11
- golf/commands/init.py,sha256=0QoiDt5ERErh2X7l1EozkMgX4voFk4EMY7BDyI7s-vc,8186
11
+ golf/commands/init.py,sha256=DUAvGqOUapWdF2cgWPscqHRvyOZDiajR0F0Wkn_jm-k,10355
12
12
  golf/commands/run.py,sha256=xsiG5LZw4qVt3cRTTfIoWP4Bf4AxNBBJKx0NNfoua40,2884
13
13
  golf/core/__init__.py,sha256=4bKeskJ2fPaZqkz2xQScSa3phRLLrmrczwSL632jv-o,52
14
- golf/core/builder.py,sha256=EUYGGWM7aMGTe5W8ronstrXxA5ej1mURh3RzD2frZ1U,52560
14
+ golf/core/builder.py,sha256=9TCtZIUaywxMsC3FIj3VFFgEA7sfrER5WaM4BfYAUS8,55807
15
15
  golf/core/builder_auth.py,sha256=6oGw1HsHdtAjfbJKoyakBrFp2v6FgrO1hFuLR9thiY4,13821
16
16
  golf/core/builder_telemetry.py,sha256=jobFgRSspLQLuitL4ytk6asSUdTqYcDxGY3sTjkrZd4,2654
17
- golf/core/config.py,sha256=GhR9TFzkHbPTPF27-VkoFlI5_anNYyHFW2-dpJeGIzE,7009
18
- golf/core/parser.py,sha256=Yq4mXUwRub4iC7wOUiei8PUnb2TdcnzGHE_BW5PhkT8,21583
19
- golf/core/telemetry.py,sha256=xehArzw3-MVXGA6L1JaxSiX5XIDWDpKfhQUZhX1zjiM,14895
17
+ golf/core/config.py,sha256=B_GcPDjf2PuOemZNaFMOEuzqtnCchQaJCQkYAuULUgQ,7184
18
+ golf/core/parser.py,sha256=BQRus1O9zmzSmyavwLVfN8BpYFkbrWUDrgQ7yrYfAKw,42457
19
+ golf/core/platform.py,sha256=Z2yEi6ilmQCLC_uAD_oZdVO0WvkL4tsyw7sx0vHhysI,6440
20
+ golf/core/telemetry.py,sha256=CjZ7urbizaRjyFiVBjfGW8V4PmNCG1_quk3FvbVTcjw,15772
20
21
  golf/core/transformer.py,sha256=_0nM42M41oM9zw_XxPVVS6MErdBSw2B5lULC7_UFLfU,5287
21
22
  golf/examples/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
23
  golf/examples/api_key/.env,sha256=15dewTdeJEMAIuzQmh1SFc1zEN6PwryWgAc14IV02lY,90
23
- golf/examples/api_key/.env.example,sha256=zKXwnfCHdmycsESR8z5b8-rvYnaN3SagxrwL6B_VGjA,215
24
- golf/examples/api_key/README.md,sha256=nuc4YIspX_eokoArylBv6rKPv5P8BTq__2YaInidrUk,2892
25
- golf/examples/api_key/golf.json,sha256=y8I43-28eqYW5x2CTdNsb7FaYaDsfcXiUzbyyKF7qto,362
24
+ golf/examples/api_key/.env.example,sha256=fvM_r9xLoiJ_41ZbcDc_EQ48uyxwb7zf0gP_bhQroEY,29
25
+ golf/examples/api_key/README.md,sha256=wRcgwYArwiRcjL6GKEOkPVQal7L37WnREa_rwhrIE10,2892
26
+ golf/examples/api_key/golf.json,sha256=V7atsB5T706bBlkZ5iVBPIhAA6_3Ba3dN6NOyVaV06g,214
26
27
  golf/examples/api_key/pre_build.py,sha256=-12HGLV70sQcPhgN51zx25uN2o48JeFvTByzF2ayYp4,471
27
28
  golf/examples/api_key/tools/issues/create.py,sha256=51X0uGaisUMfMkmJCskArpefpnxZ4fnT4T_f7HhqQdU,2721
28
29
  golf/examples/api_key/tools/issues/list.py,sha256=Egl2o1YVSU8Iigu8XO_iK1-Pn1OnFL3j6LOzaG10rTI,2720
@@ -30,9 +31,9 @@ golf/examples/api_key/tools/repos/list.py,sha256=9JTRLFzA7GwMYAaLjpOD85uXxv0JI4H
30
31
  golf/examples/api_key/tools/search/code.py,sha256=3quEIzrl0i_DM1fjszTcrzaAqMC7p0TZY99NL5GceKY,2993
31
32
  golf/examples/api_key/tools/users/get.py,sha256=VF-hdUkba2_DqKSC_F7vqtbx0EXAK06wUFBEluKqLIA,2470
32
33
  golf/examples/basic/.env,sha256=CqdcvPXopWppurJ3bBjT2dODlKUrLv629BHnOy8zBkM,247
33
- golf/examples/basic/.env.example,sha256=k_wpsqp0oRLLRw520NL3VrbJx4KDZclczYBW1YUgjvw,214
34
+ golf/examples/basic/.env.example,sha256=fqMyaQ7pc9KHFcT4vChBO4AEGrbW7PVXOfqbrCO6j9Q,157
34
35
  golf/examples/basic/README.md,sha256=-mY3R6AAnkXT9FPkALDrJtdf9IyKDvuqjsrLAMTLRYI,2663
35
- golf/examples/basic/golf.json,sha256=wHG_00A4a8IX0nDkZNi08DN0Ax7VHgVtKOOViXgPBu0,314
36
+ golf/examples/basic/golf.json,sha256=8DiRIXmWolrILmbHzEG2tK-ZVwu1W2qBXRLz75XEjAs,166
36
37
  golf/examples/basic/pre_build.py,sha256=AG1N_sKd1UUtHPL7sw1v3YGOcZPQvoa9xcL79S9qjGI,1037
37
38
  golf/examples/basic/prompts/welcome.py,sha256=Qs_OsXdyPNw_cDZU7cnG4a0ZMzka6LF7vmPfax4cmKM,790
38
39
  golf/examples/basic/resources/current_time.py,sha256=hxhV7vGoiOv-DMXVNSVax_jkPoYR3CR9q5PpWYkdliI,1157
@@ -46,10 +47,10 @@ golf/examples/basic/tools/payments/charge.py,sha256=PIYdFV90hu35H1veLI8ueuYwebzr
46
47
  golf/examples/basic/tools/payments/common.py,sha256=hfyuQRIjrQfSqGjyY55W6pZSD5jL6O0geCE0DGx0v10,1302
47
48
  golf/examples/basic/tools/payments/refund.py,sha256=Qpl4GWvUw-L06oGQMbBzG8pikfCWfBCFcpkRiDOzmyQ,1607
48
49
  golf/telemetry/__init__.py,sha256=ESGCg5HKwTCIfID1e_K7EE0bOWkSzMidlLtdqQgBd0w,396
49
- golf/telemetry/instrumentation.py,sha256=_p26XYLylpH42m7ztJSreqjZRUiXF1GmPPsOtksIQ28,44483
50
- golf_mcp-0.1.16.dist-info/licenses/LICENSE,sha256=5_j2f6fTJmvfmUewzElhkpAaXg2grVoxKouOA8ihV6E,11348
51
- golf_mcp-0.1.16.dist-info/METADATA,sha256=gpn7ea7CCDSDeDQwX3AQD5dEQYRQleMWVaimhrC7wK0,12361
52
- golf_mcp-0.1.16.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
53
- golf_mcp-0.1.16.dist-info/entry_points.txt,sha256=5y7rHYM8jGpU-nfwdknCm5XsApLulqsnA37MO6BUTYg,43
54
- golf_mcp-0.1.16.dist-info/top_level.txt,sha256=BQToHcBUufdyhp9ONGMIvPE40jMEtmI20lYaKb4hxOg,5
55
- golf_mcp-0.1.16.dist-info/RECORD,,
50
+ golf/telemetry/instrumentation.py,sha256=2B0R918-OLpRdyXMTpHuerfc_4osuSi7Lrh9Y2luXfs,43575
51
+ golf_mcp-0.1.17.dist-info/licenses/LICENSE,sha256=5_j2f6fTJmvfmUewzElhkpAaXg2grVoxKouOA8ihV6E,11348
52
+ golf_mcp-0.1.17.dist-info/METADATA,sha256=-OBF6l8aFo-QYVpnf2c2Uas-8obFK5KYp0EaRvlr_7E,12871
53
+ golf_mcp-0.1.17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
54
+ golf_mcp-0.1.17.dist-info/entry_points.txt,sha256=5y7rHYM8jGpU-nfwdknCm5XsApLulqsnA37MO6BUTYg,43
55
+ golf_mcp-0.1.17.dist-info/top_level.txt,sha256=BQToHcBUufdyhp9ONGMIvPE40jMEtmI20lYaKb4hxOg,5
56
+ golf_mcp-0.1.17.dist-info/RECORD,,