awslabs.openapi-mcp-server 0.1.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.
Files changed (38) hide show
  1. awslabs/__init__.py +16 -0
  2. awslabs/openapi_mcp_server/__init__.py +69 -0
  3. awslabs/openapi_mcp_server/api/__init__.py +18 -0
  4. awslabs/openapi_mcp_server/api/config.py +200 -0
  5. awslabs/openapi_mcp_server/auth/__init__.py +27 -0
  6. awslabs/openapi_mcp_server/auth/api_key_auth.py +185 -0
  7. awslabs/openapi_mcp_server/auth/auth_cache.py +190 -0
  8. awslabs/openapi_mcp_server/auth/auth_errors.py +206 -0
  9. awslabs/openapi_mcp_server/auth/auth_factory.py +146 -0
  10. awslabs/openapi_mcp_server/auth/auth_protocol.py +63 -0
  11. awslabs/openapi_mcp_server/auth/auth_provider.py +160 -0
  12. awslabs/openapi_mcp_server/auth/base_auth.py +218 -0
  13. awslabs/openapi_mcp_server/auth/basic_auth.py +171 -0
  14. awslabs/openapi_mcp_server/auth/bearer_auth.py +108 -0
  15. awslabs/openapi_mcp_server/auth/cognito_auth.py +538 -0
  16. awslabs/openapi_mcp_server/auth/register.py +100 -0
  17. awslabs/openapi_mcp_server/patch/__init__.py +17 -0
  18. awslabs/openapi_mcp_server/prompts/__init__.py +18 -0
  19. awslabs/openapi_mcp_server/prompts/generators/__init__.py +22 -0
  20. awslabs/openapi_mcp_server/prompts/generators/operation_prompts.py +642 -0
  21. awslabs/openapi_mcp_server/prompts/generators/workflow_prompts.py +257 -0
  22. awslabs/openapi_mcp_server/prompts/models.py +70 -0
  23. awslabs/openapi_mcp_server/prompts/prompt_manager.py +150 -0
  24. awslabs/openapi_mcp_server/server.py +511 -0
  25. awslabs/openapi_mcp_server/utils/__init__.py +18 -0
  26. awslabs/openapi_mcp_server/utils/cache_provider.py +249 -0
  27. awslabs/openapi_mcp_server/utils/config.py +35 -0
  28. awslabs/openapi_mcp_server/utils/error_handler.py +349 -0
  29. awslabs/openapi_mcp_server/utils/http_client.py +263 -0
  30. awslabs/openapi_mcp_server/utils/metrics_provider.py +503 -0
  31. awslabs/openapi_mcp_server/utils/openapi.py +217 -0
  32. awslabs/openapi_mcp_server/utils/openapi_validator.py +253 -0
  33. awslabs_openapi_mcp_server-0.1.1.dist-info/METADATA +418 -0
  34. awslabs_openapi_mcp_server-0.1.1.dist-info/RECORD +38 -0
  35. awslabs_openapi_mcp_server-0.1.1.dist-info/WHEEL +4 -0
  36. awslabs_openapi_mcp_server-0.1.1.dist-info/entry_points.txt +2 -0
  37. awslabs_openapi_mcp_server-0.1.1.dist-info/licenses/LICENSE +175 -0
  38. awslabs_openapi_mcp_server-0.1.1.dist-info/licenses/NOTICE +2 -0
awslabs/__init__.py ADDED
@@ -0,0 +1,16 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # This file is part of the awslabs namespace.
16
+ # It is intentionally minimal to support PEP 420 namespace packages.
@@ -0,0 +1,69 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """
15
+ OpenAPI MCP Server - A server that dynamically creates MCP tools and resources from OpenAPI specifications.
16
+ """
17
+
18
+ __version__ = '0.1.0'
19
+
20
+
21
+ import inspect
22
+ import sys
23
+
24
+ from loguru import logger
25
+
26
+ # Remove default loguru handler
27
+ logger.remove()
28
+
29
+
30
+ def get_format():
31
+ return '<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>'
32
+
33
+
34
+ # Set up enhanced logging format to include function name, line number, and logger name
35
+ # Fixed the whitespace issue after log level by removing padding
36
+ logger.add(
37
+ sys.stdout,
38
+ format=get_format(),
39
+ level='INFO',
40
+ )
41
+
42
+
43
+ def get_caller_info():
44
+ """Get information about the caller of a function.
45
+
46
+ Returns:
47
+ str: A string containing information about the caller
48
+ """
49
+ # Get the current frame
50
+ current_frame = inspect.currentframe()
51
+ if not current_frame:
52
+ return 'unknown'
53
+
54
+ # Go up one frame
55
+ parent_frame = current_frame.f_back
56
+ if not parent_frame:
57
+ return 'unknown'
58
+
59
+ # Go up another frame to find the caller
60
+ caller_frame = parent_frame.f_back
61
+ if not caller_frame:
62
+ return 'unknown'
63
+
64
+ # Get filename, function name, and line number
65
+ caller_info = inspect.getframeinfo(caller_frame)
66
+ return f'{caller_info.filename}:{caller_info.function}:{caller_info.lineno}'
67
+
68
+
69
+ __all__ = ['__version__', 'logger', 'get_caller_info']
@@ -0,0 +1,18 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """API handling modules for OpenAPI MCP Server."""
15
+
16
+ from awslabs.openapi_mcp_server.api.config import Config, load_config
17
+
18
+ __all__ = ['Config', 'load_config']
@@ -0,0 +1,200 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """Configuration module for the OpenAPI MCP Server."""
15
+
16
+ import os
17
+ from awslabs.openapi_mcp_server import get_caller_info, logger
18
+ from dataclasses import dataclass
19
+ from typing import Any
20
+
21
+
22
+ @dataclass
23
+ class Config:
24
+ """Configuration for the OpenAPI MCP Server."""
25
+
26
+ # API information
27
+ api_name: str = 'awslabs-openapi-mcp-server'
28
+ api_base_url: str = 'https://localhost:8000'
29
+ api_spec_url: str = ''
30
+ api_spec_path: str = ''
31
+
32
+ # Authentication
33
+ auth_type: str = 'none' # none, basic, bearer, api_key, cognito
34
+ auth_username: str = ''
35
+ auth_password: str = ''
36
+ auth_token: str = ''
37
+ auth_api_key: str = ''
38
+ auth_api_key_name: str = 'api_key'
39
+ auth_api_key_in: str = 'header' # header, query, cookie
40
+
41
+ # Cognito authentication
42
+ auth_cognito_client_id: str = ''
43
+ auth_cognito_username: str = ''
44
+ auth_cognito_password: str = ''
45
+ auth_cognito_user_pool_id: str = ''
46
+ auth_cognito_region: str = 'us-east-1'
47
+
48
+ # Server configuration
49
+ port: int = 8000
50
+ # Default to localhost for security; use SERVER_HOST env var to override when needed (e.g. in Docker)
51
+ host: str = '127.0.0.1'
52
+ debug: bool = False
53
+ transport: str = 'stdio' # stdio only
54
+ message_timeout: int = 60
55
+ version: str = '0.1.0'
56
+
57
+
58
+ def load_config(args: Any = None) -> Config:
59
+ """Load configuration from arguments and environment variables.
60
+
61
+ Args:
62
+ args: Command line arguments
63
+
64
+ Returns:
65
+ Config: Configuration object
66
+
67
+ """
68
+ logger.debug('Loading configuration')
69
+
70
+ # Get caller information for debugging
71
+ caller_info = get_caller_info()
72
+ logger.debug(f'Called from {caller_info}')
73
+
74
+ # Create default config
75
+ config = Config()
76
+
77
+ # Load from environment variables
78
+ env_vars = {
79
+ # API information
80
+ 'API_NAME': (lambda v: setattr(config, 'api_name', v)),
81
+ 'API_BASE_URL': (lambda v: setattr(config, 'api_base_url', v)),
82
+ 'API_SPEC_URL': (lambda v: setattr(config, 'api_spec_url', v)),
83
+ 'API_SPEC_PATH': (lambda v: setattr(config, 'api_spec_path', v)),
84
+ # Authentication
85
+ 'AUTH_TYPE': (lambda v: setattr(config, 'auth_type', v)),
86
+ 'AUTH_USERNAME': (lambda v: setattr(config, 'auth_username', v)),
87
+ 'AUTH_PASSWORD': (lambda v: setattr(config, 'auth_password', v)),
88
+ 'AUTH_TOKEN': (lambda v: setattr(config, 'auth_token', v)),
89
+ 'AUTH_API_KEY': (lambda v: setattr(config, 'auth_api_key', v)),
90
+ 'AUTH_API_KEY_NAME': (lambda v: setattr(config, 'auth_api_key_name', v)),
91
+ 'AUTH_API_KEY_IN': (lambda v: setattr(config, 'auth_api_key_in', v)),
92
+ # Cognito authentication environment variables
93
+ 'AUTH_COGNITO_CLIENT_ID': (lambda v: setattr(config, 'auth_cognito_client_id', v)),
94
+ 'AUTH_COGNITO_USERNAME': (lambda v: setattr(config, 'auth_cognito_username', v)),
95
+ 'AUTH_COGNITO_PASSWORD': (lambda v: setattr(config, 'auth_cognito_password', v)),
96
+ 'AUTH_COGNITO_USER_POOL_ID': (lambda v: setattr(config, 'auth_cognito_user_pool_id', v)),
97
+ 'AUTH_COGNITO_REGION': (lambda v: setattr(config, 'auth_cognito_region', v)),
98
+ # Server configuration
99
+ 'SERVER_PORT': (lambda v: setattr(config, 'port', int(v))),
100
+ 'SERVER_HOST': (lambda v: setattr(config, 'host', v)),
101
+ 'SERVER_DEBUG': (lambda v: setattr(config, 'debug', v.lower() == 'true')),
102
+ 'SERVER_TRANSPORT': (lambda v: setattr(config, 'transport', v)),
103
+ 'SERVER_MESSAGE_TIMEOUT': (lambda v: setattr(config, 'message_timeout', int(v))),
104
+ }
105
+
106
+ # Load environment variables
107
+ env_loaded = {}
108
+ for key, setter in env_vars.items():
109
+ if key in os.environ:
110
+ env_value = os.environ[key]
111
+ setter(env_value)
112
+ env_loaded[key] = env_value
113
+
114
+ if env_loaded:
115
+ logger.debug(
116
+ f'Loaded {len(env_loaded)} environment variables: {", ".join(env_loaded.keys())}'
117
+ )
118
+
119
+ # Load from arguments
120
+ if args:
121
+ if hasattr(args, 'api_name') and args.api_name:
122
+ logger.debug(f'Setting API name from arguments: {args.api_name}')
123
+ config.api_name = args.api_name
124
+
125
+ if hasattr(args, 'api_url') and args.api_url:
126
+ logger.debug(f'Setting API base URL from arguments: {args.api_url}')
127
+ config.api_base_url = args.api_url
128
+
129
+ if hasattr(args, 'spec_url') and args.spec_url:
130
+ logger.debug(f'Setting API spec URL from arguments: {args.spec_url}')
131
+ config.api_spec_url = args.spec_url
132
+
133
+ if hasattr(args, 'spec_path') and args.spec_path:
134
+ logger.debug(f'Setting API spec path from arguments: {args.spec_path}')
135
+ config.api_spec_path = args.spec_path
136
+
137
+ if hasattr(args, 'port') and args.port:
138
+ logger.debug(f'Setting port from arguments: {args.port}')
139
+ config.port = args.port
140
+
141
+ if hasattr(args, 'debug') and args.debug:
142
+ logger.debug('Setting debug mode from arguments')
143
+ config.debug = True
144
+
145
+ # Authentication arguments
146
+ if hasattr(args, 'auth_type') and args.auth_type:
147
+ logger.debug(f'Setting auth type from arguments: {args.auth_type}')
148
+ config.auth_type = args.auth_type
149
+
150
+ if hasattr(args, 'auth_username') and args.auth_username:
151
+ logger.debug('Setting auth username from arguments')
152
+ config.auth_username = args.auth_username
153
+
154
+ if hasattr(args, 'auth_password') and args.auth_password:
155
+ logger.debug('Setting auth password from arguments')
156
+ config.auth_password = args.auth_password
157
+
158
+ if hasattr(args, 'auth_token') and args.auth_token:
159
+ logger.debug('Setting auth token from arguments')
160
+ config.auth_token = args.auth_token
161
+
162
+ if hasattr(args, 'auth_api_key') and args.auth_api_key:
163
+ logger.debug('Setting auth API key from arguments')
164
+ config.auth_api_key = args.auth_api_key
165
+
166
+ if hasattr(args, 'auth_api_key_name') and args.auth_api_key_name:
167
+ logger.debug(f'Setting auth API key name from arguments: {args.auth_api_key_name}')
168
+ config.auth_api_key_name = args.auth_api_key_name
169
+
170
+ if hasattr(args, 'auth_api_key_in') and args.auth_api_key_in:
171
+ logger.debug(f'Setting auth API key location from arguments: {args.auth_api_key_in}')
172
+ config.auth_api_key_in = args.auth_api_key_in
173
+
174
+ # Cognito authentication arguments
175
+ if hasattr(args, 'auth_cognito_client_id') and args.auth_cognito_client_id:
176
+ logger.debug('Setting Cognito client ID from arguments')
177
+ config.auth_cognito_client_id = args.auth_cognito_client_id
178
+
179
+ if hasattr(args, 'auth_cognito_username') and args.auth_cognito_username:
180
+ logger.debug('Setting Cognito username from arguments')
181
+ config.auth_cognito_username = args.auth_cognito_username
182
+
183
+ if hasattr(args, 'auth_cognito_password') and args.auth_cognito_password:
184
+ logger.debug('Setting Cognito password from arguments')
185
+ config.auth_cognito_password = args.auth_cognito_password
186
+
187
+ if hasattr(args, 'auth_cognito_user_pool_id') and args.auth_cognito_user_pool_id:
188
+ logger.debug('Setting Cognito user pool ID from arguments')
189
+ config.auth_cognito_user_pool_id = args.auth_cognito_user_pool_id
190
+
191
+ if hasattr(args, 'auth_cognito_region') and args.auth_cognito_region:
192
+ logger.debug(f'Setting Cognito region from arguments: {args.auth_cognito_region}')
193
+ config.auth_cognito_region = args.auth_cognito_region
194
+
195
+ # Log final configuration details
196
+ logger.info(
197
+ f'Configuration loaded: API name={config.api_name}, transport={config.transport}, port={config.port}'
198
+ )
199
+
200
+ return config
@@ -0,0 +1,27 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """Authentication package for OpenAPI MCP Server."""
15
+
16
+ # Import register module to auto-register providers
17
+ import awslabs.openapi_mcp_server.auth.register # noqa: F401
18
+ from awslabs.openapi_mcp_server.auth.auth_factory import get_auth_provider, is_auth_type_available
19
+ from awslabs.openapi_mcp_server.auth.auth_provider import AuthProvider, NullAuthProvider
20
+
21
+ # Define public exports
22
+ __all__ = [
23
+ 'get_auth_provider',
24
+ 'is_auth_type_available',
25
+ 'AuthProvider',
26
+ 'NullAuthProvider',
27
+ ]
@@ -0,0 +1,185 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """API Key authentication provider."""
15
+
16
+ import bcrypt
17
+ from awslabs.openapi_mcp_server import logger
18
+ from awslabs.openapi_mcp_server.api.config import Config
19
+ from awslabs.openapi_mcp_server.auth.auth_cache import cached_auth_data
20
+ from awslabs.openapi_mcp_server.auth.auth_errors import (
21
+ ConfigurationError,
22
+ MissingCredentialsError,
23
+ )
24
+ from awslabs.openapi_mcp_server.auth.base_auth import BaseAuthProvider
25
+ from typing import Dict
26
+
27
+
28
+ class ApiKeyAuthProvider(BaseAuthProvider):
29
+ """API Key authentication provider.
30
+
31
+ This provider adds an API key to requests, either in a header,
32
+ query parameter, or cookie.
33
+ """
34
+
35
+ def __init__(self, config: Config):
36
+ """Initialize with configuration.
37
+
38
+ Args:
39
+ config: Application configuration
40
+
41
+ """
42
+ # Store configuration values before calling super().__init__
43
+ # so they're available during validation
44
+ self._api_key = config.auth_api_key
45
+ self._api_key_name = config.auth_api_key_name or 'api_key'
46
+ self._api_key_in = config.auth_api_key_in or 'header'
47
+ self._api_key_hash = None
48
+
49
+ # Call parent initializer which will validate and initialize auth
50
+ super().__init__(config)
51
+
52
+ def _validate_config(self) -> bool:
53
+ """Validate the configuration.
54
+
55
+ Returns:
56
+ bool: True if API key is provided, False otherwise
57
+
58
+ Raises:
59
+ MissingCredentialsError: If API key is missing
60
+ ConfigurationError: If API key location is invalid
61
+
62
+ """
63
+ if not self._api_key:
64
+ raise MissingCredentialsError(
65
+ 'API Key authentication requires a valid API key',
66
+ {
67
+ 'help': 'Provide it using --auth-api-key command line argument or AUTH_API_KEY environment variable'
68
+ },
69
+ )
70
+
71
+ if self._api_key_in not in ('header', 'query', 'cookie'):
72
+ raise ConfigurationError(
73
+ f'Invalid API key location: {self._api_key_in}',
74
+ {
75
+ 'valid_locations': ['header', 'query', 'cookie'],
76
+ 'help': 'Provide a valid location using --auth-api-key-in command line argument or AUTH_API_KEY_IN environment variable',
77
+ },
78
+ )
79
+
80
+ # Create a hash of the API key for caching
81
+ self._api_key_hash = self._hash_api_key(self._api_key)
82
+ return True
83
+
84
+ def _handle_validation_error(self) -> None:
85
+ """Handle validation error."""
86
+ # This should not be called since we raise exceptions in _validate_config
87
+ # But we implement it for completeness
88
+ self._validation_error = MissingCredentialsError(
89
+ 'API Key authentication requires a valid API key',
90
+ {
91
+ 'help': 'Provide it using --auth-api-key command line argument or AUTH_API_KEY environment variable'
92
+ },
93
+ )
94
+ self._log_auth_error(self._validation_error)
95
+
96
+ def _initialize_auth(self) -> None:
97
+ """Initialize authentication data after validation."""
98
+ # Use cached methods to generate auth data based on location
99
+ if self._api_key_in == 'header':
100
+ self._auth_headers = self._generate_auth_headers(self._api_key_hash, self._api_key_name)
101
+ elif self._api_key_in == 'query':
102
+ self._auth_params = self._generate_auth_params(self._api_key_hash, self._api_key_name)
103
+ elif self._api_key_in == 'cookie':
104
+ self._auth_cookies = self._generate_auth_cookies(self._api_key_hash, self._api_key_name)
105
+
106
+ @staticmethod
107
+ def _hash_api_key(api_key: str) -> str:
108
+ """Create a hash of the API key for caching.
109
+
110
+ Args:
111
+ api_key: API key
112
+
113
+ Returns:
114
+ str: Hash of the API key
115
+
116
+ """
117
+ # Create a hash of the API key to use as a cache key
118
+ return bcrypt.hashpw(api_key.encode('utf-8'), bcrypt.gensalt(rounds=10)).hex()
119
+
120
+ @cached_auth_data(ttl=3600) # Cache for 1 hour by default
121
+ def _generate_auth_headers(self, api_key_hash: str, api_key_name: str) -> Dict[str, str]:
122
+ """Generate authentication headers.
123
+
124
+ This method is cached to avoid regenerating headers for the same API key.
125
+
126
+ Args:
127
+ api_key_hash: Hash of the API key
128
+ api_key_name: Name of the API key header
129
+
130
+ Returns:
131
+ Dict[str, str]: Authentication headers
132
+
133
+ """
134
+ logger.debug(f'Generating new API key headers with name: {api_key_name}')
135
+ # Log key length for debugging without exposing the key
136
+ logger.debug(f'API key length: {len(self._api_key) if self._api_key else 0} characters')
137
+ return {api_key_name: self._api_key}
138
+
139
+ @cached_auth_data(ttl=3600) # Cache for 1 hour by default
140
+ def _generate_auth_params(self, api_key_hash: str, api_key_name: str) -> Dict[str, str]:
141
+ """Generate authentication query parameters.
142
+
143
+ This method is cached to avoid regenerating parameters for the same API key.
144
+
145
+ Args:
146
+ api_key_hash: Hash of the API key
147
+ api_key_name: Name of the API key parameter
148
+
149
+ Returns:
150
+ Dict[str, str]: Authentication query parameters
151
+
152
+ """
153
+ logger.debug(f'Generating new API key query parameters with name: {api_key_name}')
154
+ # Log key length for debugging without exposing the key
155
+ logger.debug(f'API key length: {len(self._api_key) if self._api_key else 0} characters')
156
+ return {api_key_name: self._api_key}
157
+
158
+ @cached_auth_data(ttl=3600) # Cache for 1 hour by default
159
+ def _generate_auth_cookies(self, api_key_hash: str, api_key_name: str) -> Dict[str, str]:
160
+ """Generate authentication cookies.
161
+
162
+ This method is cached to avoid regenerating cookies for the same API key.
163
+
164
+ Args:
165
+ api_key_hash: Hash of the API key
166
+ api_key_name: Name of the API key cookie
167
+
168
+ Returns:
169
+ Dict[str, str]: Authentication cookies
170
+
171
+ """
172
+ logger.debug(f'Generating new API key cookies with name: {api_key_name}')
173
+ # Log key length for debugging without exposing the key
174
+ logger.debug(f'API key length: {len(self._api_key) if self._api_key else 0} characters')
175
+ return {api_key_name: self._api_key}
176
+
177
+ @property
178
+ def provider_name(self) -> str:
179
+ """Get the name of the authentication provider.
180
+
181
+ Returns:
182
+ str: Name of the authentication provider
183
+
184
+ """
185
+ return 'api_key'