awslabs.s3-tables-mcp-server 0.0.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.
@@ -0,0 +1,136 @@
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
+ """Table Bucket Management tools for S3 Tables MCP Server."""
16
+
17
+ from .models import (
18
+ TableBucketMaintenanceConfigurationValue,
19
+ TableBucketMaintenanceType,
20
+ )
21
+ from .utils import get_s3tables_client, handle_exceptions
22
+ from typing import Any, Dict, Optional
23
+
24
+
25
+ @handle_exceptions
26
+ async def create_table_bucket(
27
+ name: str,
28
+ region_name: Optional[str] = None,
29
+ ) -> Dict[str, Any]:
30
+ """Create a new S3 Tables bucket."""
31
+ client = get_s3tables_client(region_name)
32
+
33
+ # Prepare parameters for create_table_bucket
34
+ params = {'name': name}
35
+
36
+ response = client.create_table_bucket(**params)
37
+ return dict(response)
38
+
39
+
40
+ @handle_exceptions
41
+ async def delete_table_bucket(
42
+ table_bucket_arn: str, region_name: Optional[str] = None
43
+ ) -> Dict[str, Any]:
44
+ """Delete a table bucket.
45
+
46
+ Permissions:
47
+ You must have the s3tables:DeleteTableBucket permission to use this operation.
48
+ """
49
+ client = get_s3tables_client(region_name)
50
+ response = client.delete_table_bucket(tableBucketARN=table_bucket_arn)
51
+ return dict(response)
52
+
53
+
54
+ @handle_exceptions
55
+ async def put_table_bucket_maintenance_configuration(
56
+ table_bucket_arn: str,
57
+ maintenance_type: TableBucketMaintenanceType,
58
+ value: TableBucketMaintenanceConfigurationValue,
59
+ region_name: Optional[str] = None,
60
+ ) -> Dict[str, Any]:
61
+ """Create or replace a maintenance configuration for a table bucket.
62
+
63
+ Permissions:
64
+ You must have the s3tables:PutTableBucketMaintenanceConfiguration permission to use this operation.
65
+ """
66
+ client = get_s3tables_client(region_name)
67
+ response = client.put_table_bucket_maintenance_configuration(
68
+ tableBucketARN=table_bucket_arn,
69
+ type=maintenance_type.value,
70
+ value=value.model_dump(by_alias=True, exclude_none=True),
71
+ )
72
+ return dict(response)
73
+
74
+
75
+ @handle_exceptions
76
+ async def get_table_bucket(
77
+ table_bucket_arn: str, region_name: Optional[str] = None
78
+ ) -> Dict[str, Any]:
79
+ """Get details about a table bucket.
80
+
81
+ Gets details on a table bucket.
82
+
83
+ Permissions:
84
+ You must have the s3tables:GetTableBucket permission to use this operation.
85
+ """
86
+ client = get_s3tables_client(region_name)
87
+ response = client.get_table_bucket(tableBucketARN=table_bucket_arn)
88
+ return dict(response)
89
+
90
+
91
+ @handle_exceptions
92
+ async def get_table_bucket_maintenance_configuration(
93
+ table_bucket_arn: str, region_name: Optional[str] = None
94
+ ) -> Dict[str, Any]:
95
+ """Get details about a maintenance configuration for a table bucket.
96
+
97
+ Gets details about a maintenance configuration for a given table bucket.
98
+
99
+ Permissions:
100
+ You must have the s3tables:GetTableBucketMaintenanceConfiguration permission to use this operation.
101
+ """
102
+ client = get_s3tables_client(region_name)
103
+ response = client.get_table_bucket_maintenance_configuration(tableBucketARN=table_bucket_arn)
104
+ return dict(response)
105
+
106
+
107
+ @handle_exceptions
108
+ async def get_table_bucket_policy(
109
+ table_bucket_arn: str, region_name: Optional[str] = None
110
+ ) -> Dict[str, Any]:
111
+ """Get details about a table bucket policy.
112
+
113
+ Gets details about a table bucket policy.
114
+
115
+ Permissions:
116
+ You must have the s3tables:GetTableBucketPolicy permission to use this operation.
117
+ """
118
+ client = get_s3tables_client(region_name)
119
+ response = client.get_table_bucket_policy(tableBucketARN=table_bucket_arn)
120
+ return dict(response)
121
+
122
+
123
+ @handle_exceptions
124
+ async def delete_table_bucket_policy(
125
+ table_bucket_arn: str, region_name: Optional[str] = None
126
+ ) -> Dict[str, Any]:
127
+ """Delete a table bucket policy.
128
+
129
+ Deletes a table bucket policy.
130
+
131
+ Permissions:
132
+ You must have the s3tables:DeleteTableBucketPolicy permission to use this operation.
133
+ """
134
+ client = get_s3tables_client(region_name)
135
+ response = client.delete_table_bucket_policy(tableBucketARN=table_bucket_arn)
136
+ return dict(response)
@@ -0,0 +1,307 @@
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
+ """Table Management tools for S3 Tables MCP Server."""
16
+
17
+ from .models import (
18
+ OpenTableFormat,
19
+ TableMaintenanceConfigurationValue,
20
+ TableMaintenanceType,
21
+ TableMetadata,
22
+ )
23
+ from .utils import get_s3tables_client, handle_exceptions
24
+ from typing import Any, Dict, Optional
25
+
26
+
27
+ @handle_exceptions
28
+ async def create_table(
29
+ table_bucket_arn: str,
30
+ namespace: str,
31
+ name: str,
32
+ format: OpenTableFormat = OpenTableFormat.ICEBERG,
33
+ metadata: Optional[TableMetadata] = None,
34
+ region_name: Optional[str] = None,
35
+ ) -> Dict[str, Any]:
36
+ """Create a new table associated with the given namespace in a table bucket.
37
+
38
+ Permissions:
39
+ You must have the s3tables:CreateTable permission to use this operation.
40
+ If using metadata parameter, you must have the s3tables:PutTableData permission.
41
+ """
42
+ client = get_s3tables_client(region_name)
43
+
44
+ # Prepare parameters for create_table
45
+ params: Dict[str, Any] = {
46
+ 'tableBucketARN': table_bucket_arn,
47
+ 'namespace': namespace,
48
+ 'name': name,
49
+ 'format': format.value,
50
+ }
51
+
52
+ # Add metadata if provided
53
+ if metadata:
54
+ params['metadata'] = metadata.model_dump(by_alias=True, exclude_none=True)
55
+
56
+ response = client.create_table(**params)
57
+ return dict(response)
58
+
59
+
60
+ @handle_exceptions
61
+ async def delete_table(
62
+ table_bucket_arn: str,
63
+ namespace: str,
64
+ name: str,
65
+ version_token: Optional[str] = None,
66
+ region_name: Optional[str] = None,
67
+ ) -> Dict[str, Any]:
68
+ """Delete a table.
69
+
70
+ Permissions:
71
+ You must have the s3tables:DeleteTable permission to use this operation.
72
+ """
73
+ client = get_s3tables_client(region_name)
74
+
75
+ # Prepare parameters for delete_table
76
+ params: Dict[str, Any] = {
77
+ 'tableBucketARN': table_bucket_arn,
78
+ 'namespace': namespace,
79
+ 'name': name,
80
+ }
81
+
82
+ # Add version token if provided
83
+ if version_token:
84
+ params['versionToken'] = version_token
85
+
86
+ response = client.delete_table(**params)
87
+ return dict(response)
88
+
89
+
90
+ @handle_exceptions
91
+ async def get_table(
92
+ table_bucket_arn: str, namespace: str, name: str, region_name: Optional[str] = None
93
+ ) -> Dict[str, Any]:
94
+ """Get details about a table.
95
+
96
+ Gets details about a table.
97
+
98
+ Permissions:
99
+ You must have the s3tables:GetTable permission to use this operation.
100
+ """
101
+ client = get_s3tables_client(region_name)
102
+ response = client.get_table(tableBucketARN=table_bucket_arn, namespace=namespace, name=name)
103
+ return dict(response)
104
+
105
+
106
+ @handle_exceptions
107
+ async def delete_table_policy(
108
+ table_bucket_arn: str, namespace: str, name: str, region_name: Optional[str] = None
109
+ ) -> Dict[str, Any]:
110
+ """Delete a table policy.
111
+
112
+ Deletes a table policy.
113
+
114
+ Permissions:
115
+ You must have the s3tables:DeleteTablePolicy permission to use this operation.
116
+ """
117
+ client = get_s3tables_client(region_name)
118
+ response = client.delete_table_policy(
119
+ tableBucketARN=table_bucket_arn, namespace=namespace, name=name
120
+ )
121
+ return dict(response)
122
+
123
+
124
+ @handle_exceptions
125
+ async def get_table_maintenance_configuration(
126
+ table_bucket_arn: str, namespace: str, name: str, region_name: Optional[str] = None
127
+ ) -> Dict[str, Any]:
128
+ """Get details about the maintenance configuration of a table.
129
+
130
+ Gets details about the maintenance configuration of a table. For more information, see S3 Tables maintenance in the Amazon Simple Storage Service User Guide.
131
+
132
+ Permissions:
133
+ You must have the s3tables:GetTableMaintenanceConfiguration permission to use this operation.
134
+ """
135
+ client = get_s3tables_client(region_name)
136
+ response = client.get_table_maintenance_configuration(
137
+ tableBucketARN=table_bucket_arn, namespace=namespace, name=name
138
+ )
139
+ return dict(response)
140
+
141
+
142
+ @handle_exceptions
143
+ async def get_table_maintenance_job_status(
144
+ table_bucket_arn: str, namespace: str, name: str, region_name: Optional[str] = None
145
+ ) -> Dict[str, Any]:
146
+ """Get the status of a maintenance job for a table.
147
+
148
+ Gets the status of a maintenance job for a table. For more information, see S3 Tables maintenance in the Amazon Simple Storage Service User Guide.
149
+
150
+ Permissions:
151
+ You must have the s3tables:GetTableMaintenanceJobStatus permission to use this operation.
152
+ """
153
+ client = get_s3tables_client(region_name)
154
+ response = client.get_table_maintenance_job_status(
155
+ tableBucketARN=table_bucket_arn, namespace=namespace, name=name
156
+ )
157
+ return dict(response)
158
+
159
+
160
+ @handle_exceptions
161
+ async def get_table_metadata_location(
162
+ table_bucket_arn: str, namespace: str, name: str, region_name: Optional[str] = None
163
+ ) -> Dict[str, Any]:
164
+ """Get the location of the table metadata.
165
+
166
+ Gets the location of the table metadata.
167
+
168
+ Permissions:
169
+ You must have the s3tables:GetTableMetadataLocation permission to use this operation.
170
+ """
171
+ client = get_s3tables_client(region_name)
172
+ response = client.get_table_metadata_location(
173
+ tableBucketARN=table_bucket_arn, namespace=namespace, name=name
174
+ )
175
+ return dict(response)
176
+
177
+
178
+ @handle_exceptions
179
+ async def get_table_policy(
180
+ table_bucket_arn: str, namespace: str, name: str, region_name: Optional[str] = None
181
+ ) -> Dict[str, Any]:
182
+ """Get details about a table policy.
183
+
184
+ Gets details about a table policy. For more information, see Viewing a table policy in the Amazon Simple Storage Service User Guide.
185
+
186
+ Permissions:
187
+ You must have the s3tables:GetTablePolicy permission to use this operation.
188
+ """
189
+ client = get_s3tables_client(region_name)
190
+ response = client.get_table_policy(
191
+ tableBucketARN=table_bucket_arn, namespace=namespace, name=name
192
+ )
193
+ return dict(response)
194
+
195
+
196
+ @handle_exceptions
197
+ async def put_table_maintenance_configuration(
198
+ table_bucket_arn: str,
199
+ namespace: str,
200
+ name: str,
201
+ maintenance_type: TableMaintenanceType,
202
+ value: TableMaintenanceConfigurationValue,
203
+ region_name: Optional[str] = None,
204
+ ) -> Dict[str, Any]:
205
+ """Create or replace a maintenance configuration for a table.
206
+
207
+ Creates a new maintenance configuration or replaces an existing maintenance configuration for a table.
208
+ For more information, see S3 Tables maintenance in the Amazon Simple Storage Service User Guide.
209
+
210
+ Permissions:
211
+ You must have the s3tables:PutTableMaintenanceConfiguration permission to use this operation.
212
+ """
213
+ client = get_s3tables_client(region_name)
214
+
215
+ # Prepare parameters for put_table_maintenance_configuration
216
+ params: Dict[str, Any] = {
217
+ 'tableBucketARN': table_bucket_arn,
218
+ 'namespace': namespace,
219
+ 'name': name,
220
+ 'type': maintenance_type.value,
221
+ 'value': value.model_dump(by_alias=True, exclude_none=True),
222
+ }
223
+
224
+ response = client.put_table_maintenance_configuration(**params)
225
+ return dict(response)
226
+
227
+
228
+ @handle_exceptions
229
+ async def rename_table(
230
+ table_bucket_arn: str,
231
+ namespace: str,
232
+ name: str,
233
+ new_name: Optional[str] = None,
234
+ new_namespace_name: Optional[str] = None,
235
+ version_token: Optional[str] = None,
236
+ region_name: Optional[str] = None,
237
+ ) -> Dict[str, Any]:
238
+ """Rename a table or a namespace.
239
+
240
+ Renames a table or a namespace. For more information, see S3 Tables in the Amazon Simple Storage Service User Guide.
241
+
242
+ Args:
243
+ table_bucket_arn: The Amazon Resource Name (ARN) of the table bucket.
244
+ namespace: The namespace associated with the table.
245
+ name: The current name of the table.
246
+ new_name: Optional new name for the table.
247
+ new_namespace_name: Optional new name for the namespace.
248
+ version_token: Optional version token of the table.
249
+ region_name: Optional AWS region name.
250
+
251
+ Returns:
252
+ Dict containing the response from the rename operation.
253
+
254
+ Permissions:
255
+ You must have the s3tables:RenameTable permission to use this operation.
256
+ """
257
+ client = get_s3tables_client(region_name)
258
+
259
+ # Prepare parameters for rename_table
260
+ params: Dict[str, Any] = {
261
+ 'tableBucketARN': table_bucket_arn,
262
+ 'namespace': namespace,
263
+ 'name': name,
264
+ }
265
+
266
+ # Add optional parameters if provided
267
+ if new_name:
268
+ params['newName'] = new_name
269
+ if new_namespace_name:
270
+ params['newNamespaceName'] = new_namespace_name
271
+ if version_token:
272
+ params['versionToken'] = version_token
273
+
274
+ response = client.rename_table(**params)
275
+ return dict(response)
276
+
277
+
278
+ @handle_exceptions
279
+ async def update_table_metadata_location(
280
+ table_bucket_arn: str,
281
+ namespace: str,
282
+ name: str,
283
+ metadata_location: str,
284
+ version_token: str,
285
+ region_name: Optional[str] = None,
286
+ ) -> Dict[str, Any]:
287
+ """Update the metadata location for a table.
288
+
289
+ Updates the metadata location for a table. The metadata location of a table must be an S3 URI that begins with the table's warehouse location.
290
+ The metadata location for an Apache Iceberg table must end with .metadata.json, or if the metadata file is Gzip-compressed, .metadata.json.gz.
291
+
292
+ Permissions:
293
+ You must have the s3tables:UpdateTableMetadataLocation permission to use this operation.
294
+ """
295
+ client = get_s3tables_client(region_name)
296
+
297
+ # Prepare parameters for update_table_metadata_location
298
+ params: Dict[str, Any] = {
299
+ 'tableBucketARN': table_bucket_arn,
300
+ 'namespace': namespace,
301
+ 'name': name,
302
+ 'metadataLocation': metadata_location,
303
+ 'versionToken': version_token,
304
+ }
305
+
306
+ response = client.update_table_metadata_location(**params)
307
+ return dict(response)
@@ -0,0 +1,139 @@
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
+ """Common utilities and helpers for S3 Tables MCP Server."""
16
+
17
+ import boto3
18
+ import os
19
+ from . import __version__
20
+ from botocore.client import BaseClient
21
+ from botocore.config import Config
22
+ from functools import wraps
23
+ from typing import Optional
24
+
25
+
26
+ _user_agent_mode = 'ro' # Default to read-only
27
+
28
+
29
+ def set_user_agent_mode(allow_write: bool):
30
+ """Set the user agent mode to 'rw' (read-write) or 'ro' (read-only)."""
31
+ global _user_agent_mode
32
+ _user_agent_mode = 'rw' if allow_write else 'ro'
33
+
34
+
35
+ def _user_agent_extra():
36
+ return f'awslabs/mcp/s3-tables-mcp-server/{__version__}/{_user_agent_mode}'
37
+
38
+
39
+ def handle_exceptions(func):
40
+ """Decorator to handle exceptions consistently across tools."""
41
+
42
+ @wraps(func)
43
+ async def wrapper(*args, **kwargs):
44
+ try:
45
+ return await func(*args, **kwargs)
46
+ except Exception as e:
47
+ return {'error': str(e), 'tool': func.__name__}
48
+
49
+ return wrapper
50
+
51
+
52
+ def get_s3tables_client(region_name: Optional[str] = None) -> BaseClient:
53
+ """Create a boto3 S3 Tables client.
54
+
55
+ Args:
56
+ region_name: Optional AWS region name. If not provided, uses AWS_REGION environment variable
57
+ or defaults to 'us-east-1'.
58
+
59
+ Returns:
60
+ boto3.client: Configured S3 Tables client
61
+ """
62
+ region = region_name or os.getenv('AWS_REGION') or 'us-east-1'
63
+ config = Config(user_agent_extra=_user_agent_extra())
64
+ session = boto3.Session()
65
+ return session.client('s3tables', region_name=region, config=config)
66
+
67
+
68
+ def get_s3_client(region_name: Optional[str] = None) -> BaseClient:
69
+ """Create a boto3 S3 client.
70
+
71
+ Args:
72
+ region_name: Optional AWS region name. If not provided, uses AWS_REGION environment variable
73
+ or defaults to 'us-east-1'.
74
+
75
+ Returns:
76
+ boto3.client: Configured S3 client
77
+ """
78
+ region = region_name or os.getenv('AWS_REGION') or 'us-east-1'
79
+ config = Config(user_agent_extra=_user_agent_extra())
80
+ session = boto3.Session()
81
+ return session.client('s3', region_name=region, config=config)
82
+
83
+
84
+ def get_sts_client(region_name: Optional[str] = None) -> BaseClient:
85
+ """Create a boto3 STS client.
86
+
87
+ Args:
88
+ region_name: Optional AWS region name. If not provided, uses AWS_REGION environment variable
89
+ or defaults to 'us-east-1'.
90
+
91
+ Returns:
92
+ boto3.client: Configured STS client
93
+ """
94
+ region = region_name or os.getenv('AWS_REGION') or 'us-east-1'
95
+ config = Config(user_agent_extra=_user_agent_extra())
96
+ session = boto3.Session()
97
+ return session.client('sts', region_name=region, config=config)
98
+
99
+
100
+ def get_athena_client(region_name: Optional[str] = None) -> BaseClient:
101
+ """Create a boto3 Athena client.
102
+
103
+ Args:
104
+ region_name: Optional AWS region name. If not provided, uses AWS_REGION environment variable
105
+ or defaults to 'us-east-1'.
106
+
107
+ Returns:
108
+ boto3.client: Configured Athena client
109
+ """
110
+ region = region_name or os.getenv('AWS_REGION') or 'us-east-1'
111
+ config = Config(user_agent_extra=_user_agent_extra())
112
+ session = boto3.Session()
113
+ return session.client('athena', region_name=region, config=config)
114
+
115
+
116
+ def pyiceberg_load_catalog(
117
+ catalog_name: str,
118
+ warehouse: str,
119
+ uri: str,
120
+ region: str,
121
+ rest_signing_name: str = 's3tables',
122
+ rest_sigv4_enabled: str = 'true',
123
+ ):
124
+ """Load a PyIceberg catalog with the given parameters."""
125
+ from pyiceberg.catalog import load_catalog
126
+
127
+ catalog = load_catalog(
128
+ catalog_name,
129
+ **{
130
+ 'type': 'rest',
131
+ 'warehouse': warehouse,
132
+ 'uri': uri,
133
+ 'rest.sigv4-enabled': rest_sigv4_enabled,
134
+ 'rest.signing-name': rest_signing_name,
135
+ 'rest.signing-region': region,
136
+ },
137
+ )
138
+ catalog._session.headers['User-Agent'] = _user_agent_extra() # type: ignore[attr-defined]
139
+ return catalog