golf-mcp 0.1.20__py3-none-any.whl → 0.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of golf-mcp might be problematic. Click here for more details.

Files changed (123) hide show
  1. golf/__init__.py +9 -1
  2. golf/_endpoints.py +6 -0
  3. golf/_endpoints_fallback.py +10 -0
  4. golf/auth/__init__.py +235 -83
  5. golf/auth/api_key.py +6 -14
  6. golf/auth/factory.py +358 -0
  7. golf/auth/helpers.py +12 -42
  8. golf/auth/providers.py +446 -0
  9. golf/auth/registry.py +256 -0
  10. golf/cli/branding.py +192 -0
  11. golf/cli/main.py +28 -69
  12. golf/commands/__init__.py +2 -0
  13. golf/commands/build.py +4 -7
  14. golf/commands/init.py +30 -53
  15. golf/commands/run.py +50 -20
  16. golf/core/builder.py +355 -414
  17. golf/core/builder_auth.py +63 -144
  18. golf/core/builder_telemetry.py +26 -3
  19. golf/core/config.py +38 -59
  20. golf/core/parser.py +132 -139
  21. golf/core/platform.py +12 -10
  22. golf/core/telemetry.py +11 -19
  23. golf/core/transformer.py +38 -15
  24. golf/examples/__pycache__/__init__.cpython-311.pyc +0 -0
  25. golf/examples/basic/.coverage +0 -0
  26. golf/examples/basic/.env.example +8 -4
  27. golf/examples/basic/README.md +117 -45
  28. golf/examples/basic/__pycache__/auth.cpython-311.pyc +0 -0
  29. golf/examples/basic/auth.py +76 -0
  30. golf/examples/basic/golf.json +2 -5
  31. golf/examples/basic/htmlcov/.gitignore +2 -0
  32. golf/examples/basic/htmlcov/class_index.html +547 -0
  33. golf/examples/basic/htmlcov/coverage_html_cb_6fb7b396.js +733 -0
  34. golf/examples/basic/htmlcov/favicon_32_cb_58284776.png +0 -0
  35. golf/examples/basic/htmlcov/function_index.html +2091 -0
  36. golf/examples/basic/htmlcov/index.html +349 -0
  37. golf/examples/basic/htmlcov/keybd_closed_cb_ce680311.png +0 -0
  38. golf/examples/basic/htmlcov/status.json +1 -0
  39. golf/examples/basic/htmlcov/style_cb_8e611ae1.css +337 -0
  40. golf/examples/basic/htmlcov/z_1c9a91c0e91c8496___init___py.html +323 -0
  41. golf/examples/basic/htmlcov/z_1c9a91c0e91c8496_api_key_py.html +170 -0
  42. golf/examples/basic/htmlcov/z_1c9a91c0e91c8496_factory_py.html +430 -0
  43. golf/examples/basic/htmlcov/z_1c9a91c0e91c8496_helpers_py.html +288 -0
  44. golf/examples/basic/htmlcov/z_1c9a91c0e91c8496_providers_py.html +493 -0
  45. golf/examples/basic/htmlcov/z_1c9a91c0e91c8496_registry_py.html +353 -0
  46. golf/examples/basic/htmlcov/z_3ec3b3f490dc0950___init___py.html +120 -0
  47. golf/examples/basic/htmlcov/z_3ec3b3f490dc0950_instrumentation_py.html +1535 -0
  48. golf/examples/basic/htmlcov/z_4b8b9dd4ccccc5db___init___py.html +98 -0
  49. golf/examples/basic/htmlcov/z_4b8b9dd4ccccc5db_branding_py.html +289 -0
  50. golf/examples/basic/htmlcov/z_4b8b9dd4ccccc5db_main_py.html +476 -0
  51. golf/examples/basic/htmlcov/z_5a6c4e6bcc86fb2f___init___py.html +97 -0
  52. golf/examples/basic/htmlcov/z_6cadab9ec0df475d___init___py.html +102 -0
  53. golf/examples/basic/htmlcov/z_6cadab9ec0df475d_build_py.html +178 -0
  54. golf/examples/basic/htmlcov/z_6cadab9ec0df475d_init_py.html +387 -0
  55. golf/examples/basic/htmlcov/z_6cadab9ec0df475d_run_py.html +222 -0
  56. golf/examples/basic/htmlcov/z_6fcdee0582ba84e4___init___py.html +106 -0
  57. golf/examples/basic/htmlcov/z_6fcdee0582ba84e4__endpoints_fallback_py.html +107 -0
  58. golf/examples/basic/htmlcov/z_7ba499ed22986217___init___py.html +98 -0
  59. golf/examples/basic/htmlcov/z_7ba499ed22986217_builder_auth_py.html +306 -0
  60. golf/examples/basic/htmlcov/z_7ba499ed22986217_builder_metrics_py.html +329 -0
  61. golf/examples/basic/htmlcov/z_7ba499ed22986217_builder_py.html +1471 -0
  62. golf/examples/basic/htmlcov/z_7ba499ed22986217_builder_telemetry_py.html +186 -0
  63. golf/examples/basic/htmlcov/z_7ba499ed22986217_config_py.html +315 -0
  64. golf/examples/basic/htmlcov/z_7ba499ed22986217_parser_py.html +1149 -0
  65. golf/examples/basic/htmlcov/z_7ba499ed22986217_platform_py.html +279 -0
  66. golf/examples/basic/htmlcov/z_7ba499ed22986217_telemetry_py.html +589 -0
  67. golf/examples/basic/htmlcov/z_7ba499ed22986217_transformer_py.html +286 -0
  68. golf/examples/basic/htmlcov/z_7d7da37693a43688___init___py.html +107 -0
  69. golf/examples/basic/htmlcov/z_7d7da37693a43688_collector_py.html +417 -0
  70. golf/examples/basic/htmlcov/z_7d7da37693a43688_registry_py.html +109 -0
  71. golf/examples/basic/htmlcov/z_abe733142b40ad4e___init___py.html +109 -0
  72. golf/examples/basic/htmlcov/z_abe733142b40ad4e_context_py.html +150 -0
  73. golf/examples/basic/htmlcov/z_abe733142b40ad4e_elicitation_py.html +267 -0
  74. golf/examples/basic/htmlcov/z_abe733142b40ad4e_sampling_py.html +318 -0
  75. golf/examples/basic/prompts/__pycache__/welcome.cpython-311.pyc +0 -0
  76. golf/examples/basic/prompts/welcome.py +3 -5
  77. golf/examples/basic/resources/__pycache__/current_time.cpython-311.pyc +0 -0
  78. golf/examples/basic/resources/__pycache__/info.cpython-311.pyc +0 -0
  79. golf/examples/basic/resources/current_time.py +5 -13
  80. golf/examples/basic/resources/weather/__pycache__/common.cpython-311.pyc +0 -0
  81. golf/examples/basic/resources/weather/__pycache__/current.cpython-311.pyc +0 -0
  82. golf/examples/basic/resources/weather/__pycache__/forecast.cpython-311.pyc +0 -0
  83. golf/examples/basic/resources/weather/city.py +46 -0
  84. golf/examples/basic/resources/weather/common.py +4 -11
  85. golf/examples/basic/resources/weather/current.py +5 -5
  86. golf/examples/basic/resources/weather/forecast.py +5 -5
  87. golf/examples/basic/tools/__pycache__/calculator.cpython-311.pyc +0 -0
  88. golf/examples/basic/tools/calculator.py +94 -0
  89. golf/examples/basic/tools/say/__pycache__/hello.cpython-311.pyc +0 -0
  90. golf/examples/basic/tools/say/hello.py +65 -0
  91. golf/metrics/collector.py +100 -19
  92. golf/telemetry/__init__.py +4 -0
  93. golf/telemetry/instrumentation.py +484 -178
  94. golf/utilities/__init__.py +12 -0
  95. golf/utilities/context.py +53 -0
  96. golf/utilities/elicitation.py +170 -0
  97. golf/utilities/sampling.py +221 -0
  98. {golf_mcp-0.1.20.dist-info → golf_mcp-0.2.1.dist-info}/METADATA +51 -104
  99. golf_mcp-0.2.1.dist-info/RECORD +110 -0
  100. golf/auth/oauth.py +0 -861
  101. golf/auth/provider.py +0 -115
  102. golf/examples/api_key/.env +0 -2
  103. golf/examples/api_key/.env.example +0 -1
  104. golf/examples/api_key/README.md +0 -84
  105. golf/examples/api_key/golf.json +0 -8
  106. golf/examples/api_key/pre_build.py +0 -11
  107. golf/examples/api_key/tools/issues/create.py +0 -93
  108. golf/examples/api_key/tools/issues/list.py +0 -92
  109. golf/examples/api_key/tools/repos/list.py +0 -111
  110. golf/examples/api_key/tools/search/code.py +0 -106
  111. golf/examples/api_key/tools/users/get.py +0 -82
  112. golf/examples/basic/.env +0 -5
  113. golf/examples/basic/pre_build.py +0 -28
  114. golf/examples/basic/tools/github_user.py +0 -65
  115. golf/examples/basic/tools/hello.py +0 -34
  116. golf/examples/basic/tools/payments/charge.py +0 -70
  117. golf/examples/basic/tools/payments/common.py +0 -36
  118. golf/examples/basic/tools/payments/refund.py +0 -61
  119. golf_mcp-0.1.20.dist-info/RECORD +0 -60
  120. {golf_mcp-0.1.20.dist-info → golf_mcp-0.2.1.dist-info}/WHEEL +0 -0
  121. {golf_mcp-0.1.20.dist-info → golf_mcp-0.2.1.dist-info}/entry_points.txt +0 -0
  122. {golf_mcp-0.1.20.dist-info → golf_mcp-0.2.1.dist-info}/licenses/LICENSE +0 -0
  123. {golf_mcp-0.1.20.dist-info → golf_mcp-0.2.1.dist-info}/top_level.txt +0 -0
golf/commands/init.py CHANGED
@@ -7,6 +7,13 @@ from rich.console import Console
7
7
  from rich.progress import Progress, SpinnerColumn, TextColumn
8
8
  from rich.prompt import Confirm
9
9
 
10
+ from golf.cli.branding import (
11
+ create_success_message,
12
+ create_info_panel,
13
+ STATUS_ICONS,
14
+ GOLF_ORANGE,
15
+ )
16
+
10
17
  from golf.core.telemetry import (
11
18
  track_command,
12
19
  track_event,
@@ -20,35 +27,21 @@ console = Console()
20
27
  def initialize_project(
21
28
  project_name: str,
22
29
  output_dir: Path,
23
- template: str = "basic",
24
30
  ) -> None:
25
- """Initialize a new GolfMCP project with the specified template.
31
+ """Initialize a new GolfMCP project.
26
32
 
27
33
  Args:
28
34
  project_name: Name of the project
29
35
  output_dir: Directory where the project will be created
30
- template: Template to use (basic or api_key)
31
36
  """
32
37
  try:
33
- # Validate template
34
- valid_templates = ("basic", "api_key")
35
- if template not in valid_templates:
36
- console.print(f"[bold red]Error:[/bold red] Unknown template '{template}'")
37
- console.print(f"Available templates: {', '.join(valid_templates)}")
38
- track_command(
39
- "init",
40
- success=False,
41
- error_type="InvalidTemplate",
42
- error_message=f"Unknown template: {template}",
43
- )
44
- return
38
+ # Use the basic template by default
39
+ template = "basic"
45
40
 
46
41
  # Check if directory exists
47
42
  if output_dir.exists():
48
43
  if not output_dir.is_dir():
49
- console.print(
50
- f"[bold red]Error:[/bold red] '{output_dir}' exists but is not a directory."
51
- )
44
+ console.print(f"[bold red]Error:[/bold red] '{output_dir}' exists but is not a directory.")
52
45
  track_command(
53
46
  "init",
54
47
  success=False,
@@ -78,9 +71,7 @@ def initialize_project(
78
71
  template_dir = package_init_file.parent / "examples" / template
79
72
 
80
73
  if not template_dir.exists():
81
- console.print(
82
- f"[bold red]Error:[/bold red] Could not find template '{template}'"
83
- )
74
+ console.print(f"[bold red]Error:[/bold red] Could not find template '{template}'")
84
75
  track_command(
85
76
  "init",
86
77
  success=False,
@@ -92,7 +83,9 @@ def initialize_project(
92
83
  # Copy template files
93
84
  with Progress(
94
85
  SpinnerColumn(),
95
- TextColumn("[bold green]Creating project structure...[/bold green]"),
86
+ TextColumn(
87
+ f"[bold {GOLF_ORANGE}]{STATUS_ICONS['building']} Creating project structure...[/bold {GOLF_ORANGE}]"
88
+ ),
96
89
  transient=True,
97
90
  ) as progress:
98
91
  progress.add_task("copying", total=None)
@@ -103,11 +96,13 @@ def initialize_project(
103
96
  # Ask for telemetry consent
104
97
  _prompt_for_telemetry_consent()
105
98
 
106
- # Create virtual environment
107
- console.print("[bold green]Project initialized successfully![/bold green]")
108
- console.print("\nTo get started, run:")
109
- console.print(f" cd {output_dir.name}")
110
- console.print(" golf build dev")
99
+ # Show success message
100
+ console.print()
101
+ create_success_message("Project initialized successfully!", console)
102
+
103
+ # Show next steps
104
+ next_steps = f"cd {output_dir.name}\ngolf build dev\ngolf run"
105
+ create_info_panel("Next Steps", next_steps, console)
111
106
 
112
107
  # Track successful initialization
113
108
  track_event("cli_init_success", {"success": True, "template": template})
@@ -116,12 +111,8 @@ def initialize_project(
116
111
  error_type = type(e).__name__
117
112
  error_message = str(e)
118
113
 
119
- console.print(
120
- f"[bold red]Error during initialization:[/bold red] {error_message}"
121
- )
122
- track_command(
123
- "init", success=False, error_type=error_type, error_message=error_message
124
- )
114
+ console.print(f"[bold red]Error during initialization:[/bold red] {error_message}")
115
+ track_command("init", success=False, error_type=error_type, error_message=error_message)
125
116
 
126
117
  # Re-raise to maintain existing behavior
127
118
  raise
@@ -160,9 +151,7 @@ def _copy_template(source_dir: Path, target_dir: Path, project_name: str) -> Non
160
151
 
161
152
  # Replace template variables
162
153
  content = content.replace("{{project_name}}", project_name)
163
- content = content.replace(
164
- "{{project_name_lowercase}}", project_name.lower()
165
- )
154
+ content = content.replace("{{project_name_lowercase}}", project_name.lower())
166
155
 
167
156
  with open(target_path, "w", encoding="utf-8") as f:
168
157
  f.write(content)
@@ -170,13 +159,6 @@ def _copy_template(source_dir: Path, target_dir: Path, project_name: str) -> Non
170
159
  # Binary file, just copy
171
160
  shutil.copy2(source_path, target_path)
172
161
 
173
- # Create .env file
174
- env_file = target_dir / ".env"
175
- with open(env_file, "w", encoding="utf-8") as f:
176
- f.write(f"GOLF_NAME={project_name}\n")
177
- f.write("GOLF_HOST=127.0.0.1\n")
178
- f.write("GOLF_PORT=3000\n")
179
-
180
162
  # Create a .gitignore if it doesn't exist
181
163
  gitignore_file = target_dir / ".gitignore"
182
164
  if not gitignore_file.exists():
@@ -219,7 +201,8 @@ def _prompt_for_telemetry_consent() -> None:
219
201
  """Prompt user for telemetry consent and save their preference."""
220
202
  import os
221
203
 
222
- # Skip prompt in test mode, when telemetry is explicitly disabled, or if preference already exists
204
+ # Skip prompt in test mode, when telemetry is explicitly disabled, or if
205
+ # preference already exists
223
206
  if os.environ.get("GOLF_TEST_MODE", "").lower() in ("1", "true", "yes", "on"):
224
207
  return
225
208
 
@@ -235,9 +218,7 @@ def _prompt_for_telemetry_consent() -> None:
235
218
  console.print()
236
219
  console.rule("[bold blue]Anonymous usage analytics[/bold blue]", style="blue")
237
220
  console.print()
238
- console.print(
239
- "Golf can collect [bold]anonymous usage analytics[/bold] to help improve the tool."
240
- )
221
+ console.print("Golf can collect [bold]anonymous usage analytics[/bold] to help improve the tool.")
241
222
  console.print()
242
223
  console.print("[dim]What we collect:[/dim]")
243
224
  console.print(" • Command usage (init, build, run)")
@@ -251,14 +232,10 @@ def _prompt_for_telemetry_consent() -> None:
251
232
  console.print(" • Personal information")
252
233
  console.print(" • IP addresses")
253
234
  console.print()
254
- console.print(
255
- "You can change this anytime by setting GOLF_TELEMETRY=0 in your environment."
256
- )
235
+ console.print("You can change this anytime by setting GOLF_TELEMETRY=0 in your environment.")
257
236
  console.print()
258
237
 
259
- enable_telemetry = Confirm.ask(
260
- "[bold]Enable anonymous usage analytics?[/bold]", default=False
261
- )
238
+ enable_telemetry = Confirm.ask("[bold]Enable anonymous usage analytics?[/bold]", default=False)
262
239
 
263
240
  set_telemetry_enabled(enable_telemetry, persist=True)
264
241
 
golf/commands/run.py CHANGED
@@ -6,7 +6,11 @@ import sys
6
6
  from pathlib import Path
7
7
 
8
8
  from rich.console import Console
9
+ from rich.panel import Panel
10
+ from rich.align import Align
11
+ from rich.text import Text
9
12
 
13
+ from golf.cli.branding import create_command_header, get_status_text, STATUS_ICONS, GOLF_BLUE, GOLF_GREEN, GOLF_ORANGE
10
14
  from golf.core.config import Settings
11
15
 
12
16
  console = Console()
@@ -24,7 +28,8 @@ def run_server(
24
28
  Args:
25
29
  project_path: Path to the project root
26
30
  settings: Project settings
27
- dist_dir: Path to the directory containing the built server (defaults to project_path/dist)
31
+ dist_dir: Path to the directory containing the built server
32
+ (defaults to project_path/dist)
28
33
  host: Host to bind the server to (overrides settings)
29
34
  port: Port to bind the server to (overrides settings)
30
35
 
@@ -38,11 +43,41 @@ def run_server(
38
43
  # Check if server file exists
39
44
  server_path = dist_dir / "server.py"
40
45
  if not server_path.exists():
41
- console.print(
42
- f"[bold red]Error: Server file {server_path} not found.[/bold red]"
43
- )
46
+ console.print(get_status_text("error", f"Server file {server_path} not found"))
44
47
  return 1
45
48
 
49
+ # Display server startup header
50
+ create_command_header("Starting Server", f"{settings.name}", console)
51
+
52
+ # Show server info with flashy styling
53
+ server_host = host or settings.host or "localhost"
54
+ server_port = port or settings.port or 3000
55
+
56
+ server_content = Text()
57
+ server_content.append("🚀 ", style=f"bold {GOLF_ORANGE}")
58
+ server_content.append(f"{STATUS_ICONS['server']} Server starting on ", style=f"bold {GOLF_BLUE}")
59
+ server_content.append(f"http://{server_host}:{server_port}", style=f"bold {GOLF_GREEN}")
60
+ server_content.append(" 🚀", style=f"bold {GOLF_ORANGE}")
61
+ server_content.append("\n")
62
+
63
+ # Add telemetry status indicator
64
+ if settings.opentelemetry_enabled:
65
+ server_content.append("📊 Golf telemetry enabled", style=f"dim {GOLF_BLUE}")
66
+ server_content.append("\n")
67
+
68
+ server_content.append("⚡ Press Ctrl+C to stop ⚡", style=f"dim {GOLF_ORANGE}")
69
+
70
+ console.print(
71
+ Panel(
72
+ Align.center(server_content),
73
+ border_style=GOLF_BLUE,
74
+ padding=(1, 2),
75
+ title="[bold]🌐 SERVER READY 🌐[/bold]",
76
+ title_align="center",
77
+ )
78
+ )
79
+ console.print()
80
+
46
81
  # Prepare environment variables
47
82
  env = os.environ.copy()
48
83
  if host is not None:
@@ -65,31 +100,26 @@ def run_server(
65
100
  )
66
101
 
67
102
  # Provide more context about the exit
103
+ console.print()
68
104
  if process.returncode == 0:
69
- console.print("[green]Server stopped successfully[/green]")
105
+ console.print(get_status_text("success", "Server stopped successfully"))
70
106
  elif process.returncode == 130:
71
- console.print("[yellow]Server stopped by user interrupt (Ctrl+C)[/yellow]")
107
+ console.print(get_status_text("info", "Server stopped by user interrupt (Ctrl+C)"))
72
108
  elif process.returncode == 143:
73
- console.print(
74
- "[yellow]Server stopped by SIGTERM (graceful shutdown)[/yellow]"
75
- )
109
+ console.print(get_status_text("info", "Server stopped by SIGTERM (graceful shutdown)"))
76
110
  elif process.returncode == 137:
77
- console.print(
78
- "[yellow]Server stopped by SIGKILL (forced shutdown)[/yellow]"
79
- )
111
+ console.print(get_status_text("warning", "Server stopped by SIGKILL (forced shutdown)"))
80
112
  elif process.returncode in [1, 2]:
81
- console.print(
82
- f"[red]Server exited with error code {process.returncode}[/red]"
83
- )
113
+ console.print(get_status_text("error", f"Server exited with error code {process.returncode}"))
84
114
  else:
85
- console.print(
86
- f"[orange]Server exited with code {process.returncode}[/orange]"
87
- )
115
+ console.print(get_status_text("warning", f"Server exited with code {process.returncode}"))
88
116
 
89
117
  return process.returncode
90
118
  except KeyboardInterrupt:
91
- console.print("\n[yellow]Server stopped by user (Ctrl+C)[/yellow]")
119
+ console.print()
120
+ console.print(get_status_text("info", "Server stopped by user (Ctrl+C)"))
92
121
  return 130 # Standard exit code for SIGINT
93
122
  except Exception as e:
94
- console.print(f"\n[bold red]Error running server:[/bold red] {e}")
123
+ console.print()
124
+ console.print(get_status_text("error", f"Error running server: {e}"))
95
125
  return 1