golf-mcp 0.1.10__py3-none-any.whl → 0.1.12__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 (48) hide show
  1. golf/__init__.py +1 -1
  2. golf/auth/__init__.py +38 -26
  3. golf/auth/api_key.py +16 -23
  4. golf/auth/helpers.py +68 -54
  5. golf/auth/oauth.py +340 -277
  6. golf/auth/provider.py +58 -53
  7. golf/cli/__init__.py +1 -1
  8. golf/cli/main.py +202 -82
  9. golf/commands/__init__.py +1 -1
  10. golf/commands/build.py +31 -25
  11. golf/commands/init.py +119 -80
  12. golf/commands/run.py +14 -13
  13. golf/core/__init__.py +1 -1
  14. golf/core/builder.py +478 -353
  15. golf/core/builder_auth.py +115 -107
  16. golf/core/builder_telemetry.py +12 -9
  17. golf/core/config.py +62 -46
  18. golf/core/parser.py +174 -136
  19. golf/core/telemetry.py +169 -69
  20. golf/core/transformer.py +53 -55
  21. golf/examples/__init__.py +0 -1
  22. golf/examples/api_key/pre_build.py +2 -2
  23. golf/examples/api_key/tools/issues/create.py +35 -36
  24. golf/examples/api_key/tools/issues/list.py +42 -37
  25. golf/examples/api_key/tools/repos/list.py +50 -29
  26. golf/examples/api_key/tools/search/code.py +50 -37
  27. golf/examples/api_key/tools/users/get.py +21 -20
  28. golf/examples/basic/pre_build.py +4 -4
  29. golf/examples/basic/prompts/welcome.py +6 -7
  30. golf/examples/basic/resources/current_time.py +10 -9
  31. golf/examples/basic/resources/info.py +6 -5
  32. golf/examples/basic/resources/weather/common.py +16 -10
  33. golf/examples/basic/resources/weather/current.py +15 -11
  34. golf/examples/basic/resources/weather/forecast.py +15 -11
  35. golf/examples/basic/tools/github_user.py +19 -21
  36. golf/examples/basic/tools/hello.py +10 -6
  37. golf/examples/basic/tools/payments/charge.py +34 -25
  38. golf/examples/basic/tools/payments/common.py +8 -6
  39. golf/examples/basic/tools/payments/refund.py +29 -25
  40. golf/telemetry/__init__.py +6 -6
  41. golf/telemetry/instrumentation.py +781 -276
  42. {golf_mcp-0.1.10.dist-info → golf_mcp-0.1.12.dist-info}/METADATA +1 -1
  43. golf_mcp-0.1.12.dist-info/RECORD +55 -0
  44. {golf_mcp-0.1.10.dist-info → golf_mcp-0.1.12.dist-info}/WHEEL +1 -1
  45. golf_mcp-0.1.10.dist-info/RECORD +0 -55
  46. {golf_mcp-0.1.10.dist-info → golf_mcp-0.1.12.dist-info}/entry_points.txt +0 -0
  47. {golf_mcp-0.1.10.dist-info → golf_mcp-0.1.12.dist-info}/licenses/LICENSE +0 -0
  48. {golf_mcp-0.1.10.dist-info → golf_mcp-0.1.12.dist-info}/top_level.txt +0 -0
@@ -1,11 +1,9 @@
1
1
  """Welcome prompt for new users."""
2
2
 
3
- from typing import List, Dict
4
3
 
5
-
6
- async def welcome() -> List[Dict]:
4
+ async def welcome() -> list[dict]:
7
5
  """Provide a welcome prompt for new users.
8
-
6
+
9
7
  This is a simple example prompt that demonstrates how to define
10
8
  a prompt template in GolfMCP.
11
9
  """
@@ -15,16 +13,17 @@ async def welcome() -> List[Dict]:
15
13
  "content": (
16
14
  "You are an assistant for the {{project_name}} application. "
17
15
  "You help users understand how to interact with this system and its capabilities."
18
- )
16
+ ),
19
17
  },
20
18
  {
21
19
  "role": "user",
22
20
  "content": (
23
21
  "Welcome to {{project_name}}! This is a project built with GolfMCP. "
24
22
  "How can I get started?"
25
- )
23
+ ),
26
24
  },
27
25
  ]
28
26
 
27
+
29
28
  # Designate the entry point function
30
- export = welcome
29
+ export = welcome
@@ -1,22 +1,22 @@
1
1
  """Current time resource example."""
2
2
 
3
3
  from datetime import datetime
4
- from typing import Dict, Any
4
+ from typing import Any
5
5
 
6
6
  # The URI that clients will use to access this resource
7
7
  resource_uri = "system://time/{format}"
8
8
 
9
9
 
10
- async def current_time(format: str = "full") -> Dict[str, Any]:
10
+ async def current_time(format: str = "full") -> dict[str, Any]:
11
11
  """Provide the current time in various formats.
12
-
12
+
13
13
  This is a simple resource example that accepts a format parameter.
14
-
14
+
15
15
  Args:
16
16
  format: The format to return ('full', 'iso', 'unix' or 'rfc')
17
17
  """
18
18
  now = datetime.now()
19
-
19
+
20
20
  # Prepare all possible formats
21
21
  all_formats = {
22
22
  "iso": now.isoformat(),
@@ -25,10 +25,10 @@ async def current_time(format: str = "full") -> Dict[str, Any]:
25
25
  "formatted": {
26
26
  "date": now.strftime("%Y-%m-%d"),
27
27
  "time": now.strftime("%H:%M:%S"),
28
- "timezone": now.astimezone().tzname()
29
- }
28
+ "timezone": now.astimezone().tzname(),
29
+ },
30
30
  }
31
-
31
+
32
32
  # Return specific format or all formats
33
33
  if format == "full":
34
34
  return all_formats
@@ -37,5 +37,6 @@ async def current_time(format: str = "full") -> Dict[str, Any]:
37
37
  else:
38
38
  return {"error": f"Unknown format: {format}"}
39
39
 
40
+
40
41
  # Designate the entry point function
41
- export = current_time
42
+ export = current_time
@@ -2,14 +2,14 @@
2
2
 
3
3
  import platform
4
4
  from datetime import datetime
5
- from typing import Dict, Any
5
+ from typing import Any
6
6
 
7
7
  resource_uri = "info://system"
8
8
 
9
9
 
10
- async def info() -> Dict[str, Any]:
10
+ async def info() -> dict[str, Any]:
11
11
  """Provide system information as a resource.
12
-
12
+
13
13
  This is a simple example resource that demonstrates how to expose
14
14
  data to an LLM client through the MCP protocol.
15
15
  """
@@ -20,8 +20,9 @@ async def info() -> Dict[str, Any]:
20
20
  "system": platform.system(),
21
21
  "python_version": platform.python_version(),
22
22
  "architecture": platform.machine(),
23
- }
23
+ },
24
24
  }
25
25
 
26
+
26
27
  # Designate the entry point function
27
- export = info
28
+ export = info
@@ -1,6 +1,6 @@
1
1
  """Weather shared functionality.
2
2
 
3
- This common.py file demonstrates the recommended pattern for
3
+ This common.py file demonstrates the recommended pattern for
4
4
  sharing functionality across multiple resources in a directory.
5
5
  """
6
6
 
@@ -14,30 +14,36 @@ TEMPERATURE_UNIT = os.environ.get("WEATHER_TEMP_UNIT", "fahrenheit")
14
14
 
15
15
  class WeatherApiClient:
16
16
  """Mock weather API client."""
17
-
18
- def __init__(self, api_key: str = WEATHER_API_KEY, api_url: str = WEATHER_API_URL):
17
+
18
+ def __init__(
19
+ self, api_key: str = WEATHER_API_KEY, api_url: str = WEATHER_API_URL
20
+ ) -> None:
19
21
  self.api_key = api_key
20
22
  self.api_url = api_url
21
23
  self.unit = TEMPERATURE_UNIT
22
-
24
+
23
25
  async def get_forecast(self, city: str, days: int = 3):
24
26
  """Get weather forecast for a city (mock implementation)."""
25
27
  # This would make an API call in a real implementation
26
- print(f"Would call {self.api_url}/forecast/{city} with API key {self.api_key[:4]}...")
28
+ print(
29
+ f"Would call {self.api_url}/forecast/{city} with API key {self.api_key[:4]}..."
30
+ )
27
31
  return {
28
32
  "city": city,
29
33
  "unit": self.unit,
30
- "forecast": [{"day": i, "temp": 70 + i} for i in range(days)]
34
+ "forecast": [{"day": i, "temp": 70 + i} for i in range(days)],
31
35
  }
32
-
36
+
33
37
  async def get_current(self, city: str):
34
38
  """Get current weather for a city (mock implementation)."""
35
- print(f"Would call {self.api_url}/current/{city} with API key {self.api_key[:4]}...")
39
+ print(
40
+ f"Would call {self.api_url}/current/{city} with API key {self.api_key[:4]}..."
41
+ )
36
42
  return {
37
43
  "city": city,
38
44
  "unit": self.unit,
39
45
  "temperature": 72,
40
- "conditions": "Sunny"
46
+ "conditions": "Sunny",
41
47
  }
42
48
 
43
49
 
@@ -45,4 +51,4 @@ class WeatherApiClient:
45
51
  weather_client = WeatherApiClient()
46
52
 
47
53
  # This could also define shared models or other utilities
48
- # that would be common across weather-related resources
54
+ # that would be common across weather-related resources
@@ -1,16 +1,17 @@
1
1
  """Current weather resource example."""
2
2
 
3
3
  from datetime import datetime
4
- from typing import Dict, Any
4
+ from typing import Any
5
+
5
6
  from .common import weather_client
6
7
 
7
8
  # The URI that clients will use to access this resource
8
9
  resource_uri = "weather://current/{city}"
9
10
 
10
11
 
11
- async def current_weather(city: str) -> Dict[str, Any]:
12
+ async def current_weather(city: str) -> dict[str, Any]:
12
13
  """Provide current weather for the specified city.
13
-
14
+
14
15
  This example demonstrates:
15
16
  1. Nested resource organization (resources/weather/current.py)
16
17
  2. Dynamic URI parameters (city in this case)
@@ -18,15 +19,18 @@ async def current_weather(city: str) -> Dict[str, Any]:
18
19
  """
19
20
  # Use the shared weather client from common.py
20
21
  weather_data = await weather_client.get_current(city)
21
-
22
+
22
23
  # Add some additional data
23
- weather_data.update({
24
- "time": datetime.now().isoformat(),
25
- "source": "GolfMCP Weather API",
26
- "unit": "fahrenheit"
27
- })
28
-
24
+ weather_data.update(
25
+ {
26
+ "time": datetime.now().isoformat(),
27
+ "source": "GolfMCP Weather API",
28
+ "unit": "fahrenheit",
29
+ }
30
+ )
31
+
29
32
  return weather_data
30
33
 
34
+
31
35
  # Designate the entry point function
32
- export = current_weather
36
+ export = current_weather
@@ -1,16 +1,17 @@
1
1
  """Weather forecast resource example demonstrating nested resources."""
2
2
 
3
3
  from datetime import datetime
4
- from typing import Dict, Any
4
+ from typing import Any
5
+
5
6
  from .common import weather_client
6
7
 
7
8
  # The URI that clients will use to access this resource
8
9
  resource_uri = "weather://forecast/{city}"
9
10
 
10
11
 
11
- async def forecast_weather(city: str) -> Dict[str, Any]:
12
+ async def forecast_weather(city: str) -> dict[str, Any]:
12
13
  """Provide a weather forecast for the specified city.
13
-
14
+
14
15
  This example demonstrates:
15
16
  1. Nested resource organization (resources/weather/forecast.py)
16
17
  2. Dynamic URI parameters (city in this case)
@@ -18,15 +19,18 @@ async def forecast_weather(city: str) -> Dict[str, Any]:
18
19
  """
19
20
  # Use the shared weather client from common.py
20
21
  forecast_data = await weather_client.get_forecast(city, days=5)
21
-
22
+
22
23
  # Add some additional data
23
- forecast_data.update({
24
- "updated_at": datetime.now().isoformat(),
25
- "source": "GolfMCP Weather API",
26
- "unit": "fahrenheit"
27
- })
28
-
24
+ forecast_data.update(
25
+ {
26
+ "updated_at": datetime.now().isoformat(),
27
+ "source": "GolfMCP Weather API",
28
+ "unit": "fahrenheit",
29
+ }
30
+ )
31
+
29
32
  return forecast_data
30
33
 
34
+
31
35
  # Designate the entry point function
32
- export = forecast_weather
36
+ export = forecast_weather
@@ -1,25 +1,25 @@
1
1
  """Tool for fetching GitHub user information."""
2
2
 
3
- from typing import Optional
4
- from pydantic import BaseModel
5
3
  import httpx
4
+ from pydantic import BaseModel
5
+
6
6
  from golf.auth import get_provider_token
7
7
 
8
8
 
9
9
  class GitHubUserResponse(BaseModel):
10
10
  """Response model for GitHub user information."""
11
-
11
+
12
12
  login: str
13
13
  id: int
14
- name: Optional[str] = None
15
- email: Optional[str] = None
16
- avatar_url: Optional[str] = None
17
- location: Optional[str] = None
18
- bio: Optional[str] = None
14
+ name: str | None = None
15
+ email: str | None = None
16
+ avatar_url: str | None = None
17
+ location: str | None = None
18
+ bio: str | None = None
19
19
  public_repos: int = 0
20
20
  followers: int = 0
21
21
  following: int = 0
22
- message: Optional[str] = None
22
+ message: str | None = None
23
23
 
24
24
 
25
25
  async def get_github_user() -> GitHubUserResponse:
@@ -27,24 +27,24 @@ async def get_github_user() -> GitHubUserResponse:
27
27
  try:
28
28
  # Get GitHub token using our abstraction
29
29
  github_token = get_provider_token()
30
-
30
+
31
31
  if not github_token:
32
32
  return GitHubUserResponse(
33
33
  login="anonymous",
34
34
  id=0,
35
- message="Not authenticated. Please login first."
35
+ message="Not authenticated. Please login first.",
36
36
  )
37
-
37
+
38
38
  # Call GitHub API to get user info
39
39
  async with httpx.AsyncClient() as client:
40
40
  response = await client.get(
41
41
  "https://api.github.com/user",
42
42
  headers={
43
43
  "Authorization": f"Bearer {github_token}",
44
- "Accept": "application/vnd.github.v3+json"
45
- }
44
+ "Accept": "application/vnd.github.v3+json",
45
+ },
46
46
  )
47
-
47
+
48
48
  if response.status_code == 200:
49
49
  data = response.json()
50
50
  return GitHubUserResponse(**data)
@@ -52,16 +52,14 @@ async def get_github_user() -> GitHubUserResponse:
52
52
  return GitHubUserResponse(
53
53
  login="error",
54
54
  id=0,
55
- message=f"GitHub API error: {response.status_code} - {response.text[:100]}"
55
+ message=f"GitHub API error: {response.status_code} - {response.text[:100]}",
56
56
  )
57
-
57
+
58
58
  except Exception as e:
59
59
  return GitHubUserResponse(
60
- login="error",
61
- id=0,
62
- message=f"Error fetching GitHub data: {str(e)}"
60
+ login="error", id=0, message=f"Error fetching GitHub data: {str(e)}"
63
61
  )
64
62
 
65
63
 
66
64
  # Export the tool
67
- export = get_github_user
65
+ export = get_github_user
@@ -1,30 +1,34 @@
1
1
  """Hello World tool {{project_name}}."""
2
2
 
3
3
  from typing import Annotated
4
+
4
5
  from pydantic import BaseModel, Field
5
6
 
6
7
 
7
8
  class Output(BaseModel):
8
9
  """Response from the hello tool."""
9
-
10
+
10
11
  message: str
11
12
 
12
13
 
13
14
  async def hello(
14
- name: Annotated[str, Field(description="The name of the person to greet")] = "World",
15
- greeting: Annotated[str, Field(description="The greeting phrase to use")] = "Hello"
15
+ name: Annotated[
16
+ str, Field(description="The name of the person to greet")
17
+ ] = "World",
18
+ greeting: Annotated[str, Field(description="The greeting phrase to use")] = "Hello",
16
19
  ) -> Output:
17
20
  """Say hello to the given name.
18
-
21
+
19
22
  This is a simple example tool that demonstrates the basic structure
20
23
  of a tool implementation in GolfMCP.
21
24
  """
22
25
  # The framework will add a context object automatically
23
26
  # You can log using regular print during development
24
27
  print(f"{greeting} {name}...")
25
-
28
+
26
29
  # Create and return the response
27
30
  return Output(message=f"{greeting}, {name}!")
28
31
 
32
+
29
33
  # Designate the entry point function
30
- export = hello
34
+ export = hello
@@ -1,40 +1,50 @@
1
1
  """Charge payment tool"""
2
2
 
3
3
  from typing import Annotated
4
+
4
5
  from pydantic import BaseModel, Field
6
+
5
7
  from .common import payment_client
6
8
 
7
9
 
8
10
  class Output(BaseModel):
9
11
  """Response from the charge payment tool."""
10
-
12
+
11
13
  success: bool
12
14
  charge_id: str
13
15
  message: str
14
16
 
15
17
 
16
18
  async def charge(
17
- amount: Annotated[float, Field(
18
- description="Amount to charge in USD",
19
- gt=0, # Must be greater than 0
20
- le=10000 # Maximum charge limit
21
- )],
22
- card_token: Annotated[str, Field(
23
- description="Tokenized payment card identifier",
24
- pattern=r"^tok_[a-zA-Z0-9]+$" # Validate token format
25
- )],
26
- description: Annotated[str, Field(
27
- description="Optional payment description for the charge",
28
- max_length=200
29
- )] = ""
19
+ amount: Annotated[
20
+ float,
21
+ Field(
22
+ description="Amount to charge in USD",
23
+ gt=0, # Must be greater than 0
24
+ le=10000, # Maximum charge limit
25
+ ),
26
+ ],
27
+ card_token: Annotated[
28
+ str,
29
+ Field(
30
+ description="Tokenized payment card identifier",
31
+ pattern=r"^tok_[a-zA-Z0-9]+$", # Validate token format
32
+ ),
33
+ ],
34
+ description: Annotated[
35
+ str,
36
+ Field(
37
+ description="Optional payment description for the charge", max_length=200
38
+ ),
39
+ ] = "",
30
40
  ) -> Output:
31
41
  """Process a payment charge.
32
-
42
+
33
43
  This example demonstrates nested directory organization where related tools
34
44
  are grouped in subdirectories (tools/payments/charge.py).
35
-
45
+
36
46
  The resulting tool ID will be: charge-payments
37
-
47
+
38
48
  Args:
39
49
  amount: Amount to charge in USD
40
50
  card_token: Tokenized payment card
@@ -43,19 +53,18 @@ async def charge(
43
53
  # The framework will add a context object automatically
44
54
  # You can log using regular print during development
45
55
  print(f"Processing charge for ${amount:.2f}...")
46
-
56
+
47
57
  # Use the shared payment client from common.py
48
58
  charge_result = await payment_client.create_charge(
49
- amount=amount,
50
- token=card_token,
51
- description=description
59
+ amount=amount, token=card_token, description=description
52
60
  )
53
-
61
+
54
62
  # Create and return the response
55
63
  return Output(
56
64
  success=True,
57
65
  charge_id=charge_result["id"],
58
- message=f"Successfully charged ${amount:.2f}"
59
- )
66
+ message=f"Successfully charged ${amount:.2f}",
67
+ )
68
+
60
69
 
61
- export = charge
70
+ export = charge
@@ -1,6 +1,6 @@
1
1
  """Payments shared functionality.
2
2
 
3
- This common.py file demonstrates the recommended pattern for
3
+ This common.py file demonstrates the recommended pattern for
4
4
  sharing functionality across multiple tools in a directory.
5
5
  """
6
6
 
@@ -13,17 +13,19 @@ PAYMENT_API_URL = os.environ.get("PAYMENT_API_URL", "https://api.example.com/pay
13
13
 
14
14
  class PaymentClient:
15
15
  """Mock payment provider client."""
16
-
17
- def __init__(self, api_key: str = PAYMENT_API_KEY, api_url: str = PAYMENT_API_URL):
16
+
17
+ def __init__(
18
+ self, api_key: str = PAYMENT_API_KEY, api_url: str = PAYMENT_API_URL
19
+ ) -> None:
18
20
  self.api_key = api_key
19
21
  self.api_url = api_url
20
-
22
+
21
23
  async def create_charge(self, amount: float, token: str, **kwargs):
22
24
  """Create a charge (mock implementation)."""
23
25
  # In a real implementation, this would make an API request
24
26
  # using the configured API key and URL
25
27
  return {"id": f"ch_{int(amount * 100)}_{hash(token) % 10000:04d}"}
26
-
28
+
27
29
  async def create_refund(self, charge_id: str, amount: float, **kwargs):
28
30
  """Create a refund (mock implementation)."""
29
31
  # In a real implementation, this would make an API request
@@ -31,4 +33,4 @@ class PaymentClient:
31
33
 
32
34
 
33
35
  # Create a shared payment client that can be imported by all tools in this directory
34
- payment_client = PaymentClient()
36
+ payment_client = PaymentClient()
@@ -1,57 +1,61 @@
1
1
  """Refund payment tool"""
2
2
 
3
- from typing import Annotated, Optional
3
+ from typing import Annotated
4
+
4
5
  from pydantic import BaseModel, Field
6
+
5
7
  from .common import payment_client
6
8
 
7
9
 
8
10
  class Output(BaseModel):
9
11
  """Response from the refund payment tool."""
10
-
12
+
11
13
  success: bool
12
14
  refund_id: str
13
15
  message: str
14
16
 
15
17
 
16
18
  async def refund(
17
- charge_id: Annotated[str, Field(
18
- description="The ID of the charge to refund",
19
- pattern=r"^ch_[a-zA-Z0-9]+$"
20
- )],
21
- amount: Annotated[Optional[float], Field(
22
- description="Amount to refund in USD. If not specified, refunds the full charge amount",
23
- gt=0,
24
- default=None
25
- )] = None,
26
- reason: Annotated[str, Field(
27
- description="Reason for the refund",
28
- min_length=3,
29
- max_length=200
30
- )] = "Customer request"
19
+ charge_id: Annotated[
20
+ str,
21
+ Field(
22
+ description="The ID of the charge to refund", pattern=r"^ch_[a-zA-Z0-9]+$"
23
+ ),
24
+ ],
25
+ amount: Annotated[
26
+ float | None,
27
+ Field(
28
+ description="Amount to refund in USD. If not specified, refunds the full charge amount",
29
+ gt=0,
30
+ default=None,
31
+ ),
32
+ ] = None,
33
+ reason: Annotated[
34
+ str, Field(description="Reason for the refund", min_length=3, max_length=200)
35
+ ] = "Customer request",
31
36
  ) -> Output:
32
37
  """Process a payment refund.
33
-
38
+
34
39
  This example demonstrates nested directory organization where related tools
35
40
  are grouped in subdirectories (tools/payments/refund.py).
36
-
41
+
37
42
  The resulting tool ID will be: refund-payments
38
43
  """
39
44
  # The framework will add a context object automatically
40
45
  # You can log using regular print during development
41
46
  print(f"Processing refund for charge {charge_id}...")
42
-
47
+
43
48
  # Use the shared payment client from common.py
44
49
  refund_result = await payment_client.create_refund(
45
- charge_id=charge_id,
46
- amount=amount,
47
- reason=reason
50
+ charge_id=charge_id, amount=amount, reason=reason
48
51
  )
49
-
52
+
50
53
  # Create and return the response
51
54
  return Output(
52
55
  success=True,
53
56
  refund_id=refund_result["id"],
54
- message=f"Successfully refunded charge {charge_id}"
57
+ message=f"Successfully refunded charge {charge_id}",
55
58
  )
56
59
 
57
- export = refund
60
+
61
+ export = refund
@@ -1,19 +1,19 @@
1
1
  """Golf telemetry module for OpenTelemetry instrumentation."""
2
2
 
3
3
  from golf.telemetry.instrumentation import (
4
- instrument_tool,
5
- instrument_resource,
4
+ get_tracer,
5
+ init_telemetry,
6
6
  instrument_prompt,
7
+ instrument_resource,
8
+ instrument_tool,
7
9
  telemetry_lifespan,
8
- init_telemetry,
9
- get_tracer,
10
10
  )
11
11
 
12
12
  __all__ = [
13
13
  "instrument_tool",
14
- "instrument_resource",
14
+ "instrument_resource",
15
15
  "instrument_prompt",
16
16
  "telemetry_lifespan",
17
17
  "init_telemetry",
18
18
  "get_tracer",
19
- ]
19
+ ]