golf-mcp 0.1.6__tar.gz → 0.1.7__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 (67) hide show
  1. {golf_mcp-0.1.6/src/golf_mcp.egg-info → golf_mcp-0.1.7}/PKG-INFO +1 -1
  2. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/pyproject.toml +2 -2
  3. golf_mcp-0.1.7/src/golf/__init__.py +1 -0
  4. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/auth/api_key.py +19 -4
  5. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/core/builder_auth.py +10 -0
  6. golf_mcp-0.1.7/src/golf/examples/api_key/.env +2 -0
  7. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/api_key/README.md +21 -7
  8. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/api_key/pre_build.py +2 -1
  9. golf_mcp-0.1.7/src/golf/examples/basic/.env +5 -0
  10. {golf_mcp-0.1.6 → golf_mcp-0.1.7/src/golf_mcp.egg-info}/PKG-INFO +1 -1
  11. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf_mcp.egg-info/SOURCES.txt +1 -0
  12. golf_mcp-0.1.6/src/golf/__init__.py +0 -1
  13. golf_mcp-0.1.6/src/golf/examples/basic/.env +0 -3
  14. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/.docs/docs.md +0 -0
  15. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/.docs/fast-mcp.md +0 -0
  16. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/.docs/fastmcp-example-1.py +0 -0
  17. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/.docs/fastmcp-example-2.py +0 -0
  18. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/.docs/mcp.md +0 -0
  19. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/.docs/oauth-implementation.md +0 -0
  20. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/.docs/oauth.md +0 -0
  21. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/LICENSE +0 -0
  22. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/MANIFEST.in +0 -0
  23. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/README.md +0 -0
  24. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/setup.cfg +0 -0
  25. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/auth/__init__.py +0 -0
  26. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/auth/helpers.py +0 -0
  27. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/auth/oauth.py +0 -0
  28. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/auth/provider.py +0 -0
  29. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/cli/__init__.py +0 -0
  30. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/cli/main.py +0 -0
  31. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/commands/__init__.py +0 -0
  32. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/commands/build.py +0 -0
  33. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/commands/init.py +0 -0
  34. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/commands/run.py +0 -0
  35. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/core/__init__.py +0 -0
  36. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/core/builder.py +0 -0
  37. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/core/builder_telemetry.py +0 -0
  38. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/core/config.py +0 -0
  39. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/core/parser.py +0 -0
  40. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/core/telemetry.py +0 -0
  41. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/core/transformer.py +0 -0
  42. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/__init__.py +0 -0
  43. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/api_key/golf.json +0 -0
  44. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/api_key/tools/issues/create.py +0 -0
  45. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/api_key/tools/issues/list.py +0 -0
  46. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/api_key/tools/repos/list.py +0 -0
  47. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/api_key/tools/search/code.py +0 -0
  48. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/api_key/tools/users/get.py +0 -0
  49. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/basic/.env.example +0 -0
  50. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/basic/README.md +0 -0
  51. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/basic/golf.json +0 -0
  52. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/basic/pre_build.py +0 -0
  53. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/basic/prompts/welcome.py +0 -0
  54. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/basic/resources/current_time.py +0 -0
  55. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/basic/resources/info.py +0 -0
  56. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/basic/resources/weather/common.py +0 -0
  57. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/basic/resources/weather/current.py +0 -0
  58. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/basic/resources/weather/forecast.py +0 -0
  59. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/basic/tools/github_user.py +0 -0
  60. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/basic/tools/hello.py +0 -0
  61. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/basic/tools/payments/charge.py +0 -0
  62. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/basic/tools/payments/common.py +0 -0
  63. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf/examples/basic/tools/payments/refund.py +0 -0
  64. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf_mcp.egg-info/dependency_links.txt +0 -0
  65. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf_mcp.egg-info/entry_points.txt +0 -0
  66. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/src/golf_mcp.egg-info/requires.txt +0 -0
  67. {golf_mcp-0.1.6 → golf_mcp-0.1.7}/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.1.6
3
+ Version: 0.1.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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "golf-mcp"
7
- version = "0.1.6"
7
+ version = "0.1.7"
8
8
  description = "Framework for building MCP servers"
9
9
  authors = [
10
10
  {name = "Antoni Gmitruk", email = "antoni@golf.dev"}
@@ -64,7 +64,7 @@ golf = ["examples/**/*"]
64
64
 
65
65
  [tool.poetry]
66
66
  name = "golf-mcp"
67
- version = "0.1.6"
67
+ version = "0.1.7"
68
68
  description = "Framework for building MCP servers with zero boilerplate"
69
69
  authors = ["Antoni Gmitruk <antoni@golf.dev>"]
70
70
  license = "Apache-2.0"
@@ -0,0 +1 @@
1
+ __version__ = "0.1.7"
@@ -20,6 +20,10 @@ class ApiKeyConfig(BaseModel):
20
20
  "",
21
21
  description="Optional prefix to strip from the header value (e.g., 'Bearer ')"
22
22
  )
23
+ required: bool = Field(
24
+ True,
25
+ description="Whether API key is required for all requests"
26
+ )
23
27
 
24
28
 
25
29
  # Global configuration storage
@@ -28,7 +32,8 @@ _api_key_config: Optional[ApiKeyConfig] = None
28
32
 
29
33
  def configure_api_key(
30
34
  header_name: str = "X-API-Key",
31
- header_prefix: str = ""
35
+ header_prefix: str = "",
36
+ required: bool = True
32
37
  ) -> None:
33
38
  """Configure API key extraction from request headers.
34
39
 
@@ -37,21 +42,31 @@ def configure_api_key(
37
42
  Args:
38
43
  header_name: Name of the header containing the API key (default: "X-API-Key")
39
44
  header_prefix: Optional prefix to strip from the header value (e.g., "Bearer ")
40
- case_sensitive: Whether header name matching should be case-sensitive
45
+ required: Whether API key is required for all requests (default: True)
41
46
 
42
47
  Example:
43
48
  # In pre_build.py
44
49
  from golf.auth.api_key import configure_api_key
45
50
 
51
+ # Require API key for all requests
52
+ configure_api_key(
53
+ header_name="Authorization",
54
+ header_prefix="Bearer ",
55
+ required=True
56
+ )
57
+
58
+ # Or make API key optional (pass-through mode)
46
59
  configure_api_key(
47
60
  header_name="Authorization",
48
- header_prefix="Bearer "
61
+ header_prefix="Bearer ",
62
+ required=False
49
63
  )
50
64
  """
51
65
  global _api_key_config
52
66
  _api_key_config = ApiKeyConfig(
53
67
  header_name=header_name,
54
- header_prefix=header_prefix
68
+ header_prefix=header_prefix,
69
+ required=required
55
70
  )
56
71
 
57
72
 
@@ -136,6 +136,7 @@ def generate_api_key_auth_code(server_name: str) -> str:
136
136
  "from golf.auth.api_key import get_api_key_config",
137
137
  "from starlette.middleware.base import BaseHTTPMiddleware",
138
138
  "from starlette.requests import Request",
139
+ "from starlette.responses import JSONResponse",
139
140
  "",
140
141
  f"mcp = FastMCP({repr(server_name)})",
141
142
  "",
@@ -147,6 +148,7 @@ def generate_api_key_auth_code(server_name: str) -> str:
147
148
  " # Extract API key from the configured header",
148
149
  " header_name = api_key_config.header_name",
149
150
  " header_prefix = api_key_config.header_prefix",
151
+ " is_required = api_key_config.required",
150
152
  " ",
151
153
  " # Case-insensitive header lookup",
152
154
  " api_key = None",
@@ -159,6 +161,14 @@ def generate_api_key_auth_code(server_name: str) -> str:
159
161
  " if api_key and header_prefix and api_key.startswith(header_prefix):",
160
162
  " api_key = api_key[len(header_prefix):]",
161
163
  " ",
164
+ " # Check if API key is required but not provided",
165
+ " if is_required and not api_key:",
166
+ " return JSONResponse(",
167
+ " {\"error\": \"API key required\"},",
168
+ " status_code=401,",
169
+ f" headers={{\"WWW-Authenticate\": f'{{header_name}} realm=\"API Key Required\"'}}",
170
+ " )",
171
+ " ",
162
172
  " # Store the API key in context for tools to access",
163
173
  " set_api_key(api_key)",
164
174
  " ",
@@ -0,0 +1,2 @@
1
+ OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318/v1/traces"
2
+ OTEL_SERVICE_NAME="golf-mcp"
@@ -35,30 +35,44 @@ The server is configured in `pre_build.py` to extract GitHub tokens from the `Au
35
35
  ```python
36
36
  configure_api_key(
37
37
  header_name="Authorization",
38
- header_prefix="Bearer "
38
+ header_prefix="Bearer ",
39
+ required=True # Reject requests without a valid API key
39
40
  )
40
41
  ```
41
42
 
42
- This configuration handles GitHub's token format: `Authorization: Bearer ghp_xxxxxxxxxxxx`
43
+ This configuration:
44
+ - Handles GitHub's token format: `Authorization: Bearer ghp_xxxxxxxxxxxx`
45
+ - **Enforces authentication**: When `required=True` (default), requests without a valid API key will be rejected with a 401 Unauthorized error
46
+ - For optional authentication (pass-through mode), set `required=False`
43
47
 
44
48
  ## How It Works
45
49
 
46
50
  1. **Client sends request** with GitHub token in the Authorization header
47
- 2. **Golf middleware** extracts the token based on your configuration
48
- 3. **Tools retrieve token** using `get_api_key()`
49
- 4. **Token is forwarded** to GitHub API in the appropriate format
50
- 5. **GitHub validates** the token and returns results
51
+ 2. **Golf middleware** checks if API key is required and present
52
+ 3. **If required and missing**, the request is rejected with 401 Unauthorized
53
+ 4. **If present**, the token is extracted based on your configuration
54
+ 5. **Tools retrieve token** using `get_api_key()`
55
+ 6. **Token is forwarded** to GitHub API in the appropriate format
56
+ 7. **GitHub validates** the token and returns results
51
57
 
52
58
  ## Running the Server
53
59
 
54
60
  1. Build and run:
55
61
  ```bash
56
- golf build dev
62
+ golf build
57
63
  golf run
58
64
  ```
59
65
 
60
66
  2. The server will start on `http://127.0.0.1:3000` (configurable in `golf.json`)
61
67
 
68
+ 3. Test authentication enforcement:
69
+ ```bash
70
+ # This will fail with 401 Unauthorized
71
+ curl http://localhost:3000/mcp
72
+
73
+ # This will succeed
74
+ curl -H "Authorization: Bearer ghp_your_token_here" http://localhost:3000/mcp
75
+ ```
62
76
 
63
77
  ## GitHub Token Permissions
64
78
 
@@ -6,5 +6,6 @@ from golf.auth import configure_api_key
6
6
  # GitHub expects: Authorization: Bearer ghp_xxxx or Authorization: token ghp_xxxx
7
7
  configure_api_key(
8
8
  header_name="Authorization",
9
- header_prefix="Bearer " # Will handle both "Bearer " and "token " prefixes
9
+ header_prefix="Bearer ", # Will handle both "Bearer " and "token " prefixes
10
+ required=True # Reject requests without a valid API key
10
11
  )
@@ -0,0 +1,5 @@
1
+ GITHUB_CLIENT_ID="Ov23liPVrFkEzGhXro5A"
2
+ GITHUB_CLIENT_SECRET="4f050336d569559705963d88cf8ec8b3ce10441a"
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: golf-mcp
3
- Version: 0.1.6
3
+ Version: 0.1.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
@@ -30,6 +30,7 @@ src/golf/core/parser.py
30
30
  src/golf/core/telemetry.py
31
31
  src/golf/core/transformer.py
32
32
  src/golf/examples/__init__.py
33
+ src/golf/examples/api_key/.env
33
34
  src/golf/examples/api_key/README.md
34
35
  src/golf/examples/api_key/golf.json
35
36
  src/golf/examples/api_key/pre_build.py
@@ -1 +0,0 @@
1
- __version__ = "0.1.6"
@@ -1,3 +0,0 @@
1
- GITHUB_CLIENT_ID="Ov23liPVrFkEzGhXro5A"
2
- GITHUB_CLIENT_SECRET="4f050336d569559705963d88cf8ec8b3ce10441a"
3
- JWT_SECRET="example-jwt-secret-for-development-only"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes