golf-mcp 0.2.14__tar.gz → 0.2.15__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.

Files changed (59) hide show
  1. {golf_mcp-0.2.14/src/golf_mcp.egg-info → golf_mcp-0.2.15}/PKG-INFO +1 -1
  2. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/pyproject.toml +1 -1
  3. golf_mcp-0.2.15/src/golf/__init__.py +1 -0
  4. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/core/builder.py +11 -4
  5. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/core/transformer.py +47 -17
  6. {golf_mcp-0.2.14 → golf_mcp-0.2.15/src/golf_mcp.egg-info}/PKG-INFO +1 -1
  7. golf_mcp-0.2.14/src/golf/__init__.py +0 -1
  8. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/LICENSE +0 -0
  9. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/MANIFEST.in +0 -0
  10. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/README.md +0 -0
  11. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/setup.cfg +0 -0
  12. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/auth/__init__.py +0 -0
  13. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/auth/api_key.py +0 -0
  14. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/auth/factory.py +0 -0
  15. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/auth/helpers.py +0 -0
  16. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/auth/providers.py +0 -0
  17. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/auth/registry.py +0 -0
  18. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/cli/__init__.py +0 -0
  19. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/cli/branding.py +0 -0
  20. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/cli/main.py +0 -0
  21. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/commands/__init__.py +0 -0
  22. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/commands/build.py +0 -0
  23. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/commands/init.py +0 -0
  24. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/commands/run.py +0 -0
  25. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/core/__init__.py +0 -0
  26. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/core/builder_auth.py +0 -0
  27. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/core/builder_metrics.py +0 -0
  28. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/core/builder_telemetry.py +0 -0
  29. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/core/config.py +0 -0
  30. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/core/parser.py +0 -0
  31. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/core/telemetry.py +0 -0
  32. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/examples/__init__.py +0 -0
  33. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/examples/basic/.env.example +0 -0
  34. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/examples/basic/README.md +0 -0
  35. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/examples/basic/auth.py +0 -0
  36. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/examples/basic/golf.json +0 -0
  37. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/examples/basic/prompts/welcome.py +0 -0
  38. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/examples/basic/resources/current_time.py +0 -0
  39. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/examples/basic/resources/info.py +0 -0
  40. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/examples/basic/resources/weather/city.py +0 -0
  41. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/examples/basic/resources/weather/client.py +0 -0
  42. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/examples/basic/resources/weather/current.py +0 -0
  43. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/examples/basic/resources/weather/forecast.py +0 -0
  44. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/examples/basic/tools/calculator.py +0 -0
  45. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/examples/basic/tools/say/hello.py +0 -0
  46. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/metrics/__init__.py +0 -0
  47. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/metrics/collector.py +0 -0
  48. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/metrics/registry.py +0 -0
  49. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/telemetry/__init__.py +0 -0
  50. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/telemetry/instrumentation.py +0 -0
  51. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/utilities/__init__.py +0 -0
  52. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/utilities/context.py +0 -0
  53. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/utilities/elicitation.py +0 -0
  54. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf/utilities/sampling.py +0 -0
  55. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf_mcp.egg-info/SOURCES.txt +0 -0
  56. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf_mcp.egg-info/dependency_links.txt +0 -0
  57. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf_mcp.egg-info/entry_points.txt +0 -0
  58. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf_mcp.egg-info/requires.txt +0 -0
  59. {golf_mcp-0.2.14 → golf_mcp-0.2.15}/src/golf_mcp.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: golf-mcp
3
- Version: 0.2.14
3
+ Version: 0.2.15
4
4
  Summary: Framework for building MCP servers
5
5
  Author-email: Antoni Gmitruk <antoni@golf.dev>
6
6
  License-Expression: Apache-2.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "golf-mcp"
7
- version = "0.2.14"
7
+ version = "0.2.15"
8
8
  description = "Framework for building MCP servers"
9
9
  authors = [
10
10
  {name = "Antoni Gmitruk", email = "antoni@golf.dev"}
@@ -0,0 +1 @@
1
+ __version__ = "0.2.15"
@@ -341,6 +341,13 @@ class CodeGenerator:
341
341
  self.manifest = {}
342
342
  self.shared_files = {}
343
343
  self.import_map = {}
344
+ self._root_files_cache = None # Cache for discovered root files
345
+
346
+ def _get_cached_root_files(self) -> dict[str, Path]:
347
+ """Get cached root files, discovering them only once."""
348
+ if self._root_files_cache is None:
349
+ self._root_files_cache = discover_root_files(self.project_path)
350
+ return self._root_files_cache
344
351
 
345
352
  def generate(self) -> None:
346
353
  """Generate the FastMCP application code."""
@@ -386,7 +393,7 @@ class CodeGenerator:
386
393
  def _generate_root_file_imports(self) -> list[str]:
387
394
  """Generate import statements for automatically discovered root files."""
388
395
  root_file_imports = []
389
- discovered_files = discover_root_files(self.project_path)
396
+ discovered_files = self._get_cached_root_files()
390
397
 
391
398
  if discovered_files:
392
399
  root_file_imports.append("# Import root-level Python files")
@@ -401,7 +408,7 @@ class CodeGenerator:
401
408
 
402
409
  def _get_root_file_modules(self) -> set[str]:
403
410
  """Get set of root file module names for import transformation."""
404
- discovered_files = discover_root_files(self.project_path)
411
+ discovered_files = self._get_cached_root_files()
405
412
  return {Path(filename).stem for filename in discovered_files.keys()}
406
413
 
407
414
  def _create_directory_structure(self) -> None:
@@ -1612,8 +1619,8 @@ def build_project(
1612
1619
  shutil.copy2(health_path, output_dir)
1613
1620
  console.print(get_status_text("success", "Health script copied to build directory"))
1614
1621
 
1615
- # Copy any additional Python files from project root
1616
- discovered_root_files = discover_root_files(project_path)
1622
+ # Copy any additional Python files from project root (reuse cached discovery from generator)
1623
+ discovered_root_files = generator._get_cached_root_files()
1617
1624
 
1618
1625
  for filename, file_path in discovered_root_files.items():
1619
1626
  dest_path = output_dir / filename
@@ -37,26 +37,53 @@ class ImportTransformer(ast.NodeTransformer):
37
37
  self.project_root = project_root
38
38
  self.root_file_modules = root_file_modules or set()
39
39
 
40
+ def _calculate_import_depth(self) -> int:
41
+ """Calculate the relative import depth needed to reach build root from component location."""
42
+ try:
43
+ # Get component path relative to project root
44
+ relative_path = self.target_path.relative_to(self.project_root)
45
+
46
+ # Count directory levels: components/tools/weather.py = 2 levels, needs level=2
47
+ # components/tools/api/handler.py = 3 levels, needs level=3
48
+ # Build root contains the root files, so depth = number of path parts
49
+ return len(relative_path.parts) - 1 # Subtract 1 for the filename itself
50
+
51
+ except ValueError:
52
+ # Fallback to level=3 if path calculation fails
53
+ return 3
54
+
40
55
  def visit_Import(self, node: ast.Import) -> Any:
41
56
  """Transform import statements."""
42
- # Check if any of the imported names are root file modules
43
57
  new_names = []
58
+
44
59
  for alias in node.names:
45
60
  module_name = alias.name
46
61
 
47
- # If this is a root file module, we need to adjust the import path
48
62
  if module_name in self.root_file_modules:
49
- # Components are in components/tools/, components/resources/, etc.
50
- # Root files are in the build root, so we need to go up directories
51
- # to reach them: ../../module_name
52
- new_names.append(ast.alias(name=f"...{module_name}", asname=alias.asname))
63
+ # Calculate dynamic depth based on component location
64
+ depth = self._calculate_import_depth()
65
+
66
+ # Convert to from-import: import config -> from ...config import config
67
+ # Or if there's an asname: import config as cfg -> from ...config import config as cfg
68
+ if alias.asname:
69
+ # import config as cfg -> from ...config import config as cfg
70
+ import_name = module_name
71
+ asname = alias.asname
72
+ else:
73
+ # import config -> from ...config import config
74
+ import_name = module_name
75
+ asname = None
76
+
77
+ # Return a from-import instead of continuing with import
78
+ return ast.ImportFrom(
79
+ module=module_name, names=[ast.alias(name=import_name, asname=asname)], level=depth
80
+ )
53
81
  else:
54
82
  new_names.append(alias)
55
83
 
56
- # If we made any changes, return a new node
57
- if any(alias.name != orig_alias.name for alias, orig_alias in zip(new_names, node.names, strict=False)):
84
+ # If no root modules, return original or modified import
85
+ if new_names != list(node.names):
58
86
  return ast.Import(names=new_names)
59
-
60
87
  return node
61
88
 
62
89
  def visit_ImportFrom(self, node: ast.ImportFrom) -> Any:
@@ -66,8 +93,9 @@ class ImportTransformer(ast.NodeTransformer):
66
93
 
67
94
  # Check if this is importing from a root file module
68
95
  if node.level == 0 and node.module in self.root_file_modules:
69
- # Convert to relative import: from env import API_KEY -> from ...env import API_KEY
70
- return ast.ImportFrom(module=node.module, names=node.names, level=3)
96
+ # Calculate dynamic depth instead of using hardcoded level=3
97
+ depth = self._calculate_import_depth()
98
+ return ast.ImportFrom(module=node.module, names=node.names, level=depth)
71
99
 
72
100
  # Handle relative imports
73
101
  if node.level > 0:
@@ -175,13 +203,10 @@ def transform_component(
175
203
  if isinstance(node, ast.Import | ast.ImportFrom):
176
204
  imports.append(node)
177
205
 
178
- # Generate the transformed code
179
- transformed_imports = ast.unparse(ast.Module(body=imports, type_ignores=[]))
180
-
181
- # Build full transformed code
182
- transformed_code = transformed_imports + "\n\n"
206
+ # Build full transformed code - start with docstring first (Python convention)
207
+ transformed_code = ""
183
208
 
184
- # Add docstring if present, using proper triple quotes for multi-line docstrings
209
+ # Add docstring first if present, using proper triple quotes for multi-line docstrings
185
210
  if docstring:
186
211
  # Check if docstring contains newlines
187
212
  if "\n" in docstring:
@@ -191,6 +216,11 @@ def transform_component(
191
216
  # Use single quotes for single-line docstrings
192
217
  transformed_code += f'"{docstring}"\n\n'
193
218
 
219
+ # Add transformed imports after docstring
220
+ if imports:
221
+ transformed_imports = ast.unparse(ast.Module(body=imports, type_ignores=[]))
222
+ transformed_code += transformed_imports + "\n\n"
223
+
194
224
  # Add the rest of the code except imports and the original docstring
195
225
  remaining_nodes = []
196
226
  for node in tree.body:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: golf-mcp
3
- Version: 0.2.14
3
+ Version: 0.2.15
4
4
  Summary: Framework for building MCP servers
5
5
  Author-email: Antoni Gmitruk <antoni@golf.dev>
6
6
  License-Expression: Apache-2.0
@@ -1 +0,0 @@
1
- __version__ = "0.2.14"
File without changes
File without changes
File without changes
File without changes