awslabs.redshift-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.
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,17 @@
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
+ """awslabs.redshift-mcp-server"""
16
+
17
+ __version__ = '0.0.1'
@@ -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
+ """Redshift MCP Server constants."""
16
+
17
+ # Defaults
18
+ DEFAULT_AWS_REGION = 'us-east-1'
19
+ DEFAULT_LOG_LEVEL = 'WARNING'
20
+
21
+ # Timeouts (seconds), etc
22
+ CLIENT_TIMEOUT = 60
23
+ DATA_CLIENT_TIMEOUT = 60
24
+ QUERY_TIMEOUT = 3600
25
+ QUERY_POLL_INTERVAL = 2
26
+
27
+ # Best practices
28
+
29
+ CLIENT_BEST_PRACTICES = """
30
+ ## AWS Client Best Practices
31
+
32
+ ### Authentication
33
+
34
+ - Default AWS credentials chain (IAM roles, ~/.aws/credentials, etc.).
35
+ - AWS_PROFILE environment variable (if set).
36
+ - AWS_REGION environment variable (if set).
37
+ """
38
+
39
+ REDSHIFT_BEST_PRACTICES = """
40
+ ## Amazon Redshift Best Practices
41
+
42
+ ### Query Guidelines
43
+
44
+ - Always specify the database and schema when referencing objects to avoid ambiguity.
45
+ - Leverage distribution in WHERE and JOIN predicates and sort keys in ORDER BY for optimal query performance.
46
+ - Use LIMIT clauses for exploratory queries to avoid large result sets.
47
+ - Analyze table to update table statistics if it is not updated or too off before making a decision on the query structure.
48
+ - Prefer explicitly specifying columns in SELECT over "*" for better performance.
49
+
50
+ ### Connection Guidelines
51
+
52
+ - We are use the Redshift API and Redshift Data API.
53
+ - Leverage IAM authentication when possible instead of secrets (database passwords).
54
+ """
55
+
56
+ # SQL queries
57
+
58
+ SVV_REDSHIFT_DATABASES_QUERY = """
59
+ SELECT
60
+ database_name,
61
+ database_owner,
62
+ database_type,
63
+ database_acl,
64
+ database_options,
65
+ database_isolation_level
66
+ FROM pg_catalog.svv_redshift_databases
67
+ ORDER BY database_name;
68
+ """
69
+
70
+ SVV_ALL_SCHEMAS_QUERY = """
71
+ SELECT
72
+ database_name,
73
+ schema_name,
74
+ schema_owner,
75
+ schema_type,
76
+ schema_acl,
77
+ source_database,
78
+ schema_option
79
+ FROM pg_catalog.svv_all_schemas
80
+ WHERE database_name = {}
81
+ ORDER BY schema_name;
82
+ """
83
+
84
+ SVV_ALL_TABLES_QUERY = """
85
+ SELECT
86
+ database_name,
87
+ schema_name,
88
+ table_name,
89
+ table_acl,
90
+ table_type,
91
+ remarks
92
+ FROM pg_catalog.svv_all_tables
93
+ WHERE database_name = {} AND schema_name = {}
94
+ ORDER BY table_name;
95
+ """
96
+
97
+ SVV_ALL_COLUMNS_QUERY = """
98
+ SELECT
99
+ database_name,
100
+ schema_name,
101
+ table_name,
102
+ column_name,
103
+ ordinal_position,
104
+ column_default,
105
+ is_nullable,
106
+ data_type,
107
+ character_maximum_length,
108
+ numeric_precision,
109
+ numeric_scale,
110
+ remarks
111
+ FROM pg_catalog.svv_all_columns
112
+ WHERE database_name = {} AND schema_name = {} AND table_name = {}
113
+ ORDER BY ordinal_position;
114
+ """
115
+
116
+ # SQL guardrails
117
+
118
+ # Single-lines comments.
119
+ re_slc = r'--.*?$'
120
+
121
+
122
+ def re_mlc(g: int) -> str:
123
+ """Multi-line comments, considering balanced recursion."""
124
+ return rf'(?P<mlc{g}>(?:\/\*)(?:[^\/\*]|\/[^\*]|\*[^\/]|(?P>mlc{g}))*(?:\*\/))'
125
+
126
+
127
+ def re_sp(g: int) -> str:
128
+ """Whitespaces, comments, semicolons which can occur between words."""
129
+ return rf'({re_slc}|{re_mlc(g)}|\s|;)'
130
+
131
+
132
+ # We consider `(END|COMMIT|ROLLBACK|ABORT) [WORK|TRANSACTION]` as a breaker for the `BEGIN READ ONLY; {sql}; END;`
133
+ # guarding wrapper, having there might be variations of whitespaces and comments in the construct.
134
+ SUSPICIOUS_QUERY_REGEXP = (
135
+ rf'(?im)^{re_sp(1)}*(END|COMMIT|ROLLBACK|ABORT)({re_sp(2)}+(WORK|TRANSACTION))?{re_sp(3)}*;'
136
+ )
@@ -0,0 +1,141 @@
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
+ """Redshift MCP Server Pydantic models."""
16
+
17
+ from datetime import datetime
18
+ from pydantic import BaseModel, Field
19
+ from typing import Dict, Optional
20
+
21
+
22
+ class RedshiftCluster(BaseModel):
23
+ """Information about a Redshift cluster or serverless workgroup."""
24
+
25
+ identifier: str = Field(..., description='Unique identifier for the cluster/workgroup')
26
+ type: str = Field(..., description='Type of cluster (provisioned or serverless)')
27
+ status: str = Field(..., description='Current status of the cluster')
28
+ database_name: str = Field(..., description='Default database name')
29
+ endpoint: Optional[str] = Field(None, description='Connection endpoint')
30
+ port: Optional[int] = Field(None, description='Connection port')
31
+ vpc_id: Optional[str] = Field(None, description='VPC ID where the cluster resides')
32
+ node_type: Optional[str] = Field(None, description='Node type (provisioned only)')
33
+ number_of_nodes: Optional[int] = Field(None, description='Number of nodes (provisioned only)')
34
+ creation_time: Optional[datetime] = Field(None, description='When the cluster was created')
35
+ master_username: Optional[str] = Field(None, description='Master username for the cluster')
36
+ publicly_accessible: Optional[bool] = Field(None, description='Whether publicly accessible')
37
+ encrypted: Optional[bool] = Field(None, description='Whether the cluster is encrypted')
38
+ tags: Optional[Dict[str, str]] = Field(
39
+ default_factory=dict, description='Tags associated with the cluster'
40
+ )
41
+
42
+
43
+ class RedshiftDatabase(BaseModel):
44
+ """Information about a database in a Redshift cluster.
45
+
46
+ Based on the SVV_REDSHIFT_DATABASES system view.
47
+ """
48
+
49
+ database_name: str = Field(..., description='The name of the database')
50
+ database_owner: Optional[int] = Field(None, description='The database owner user ID')
51
+ database_type: Optional[str] = Field(
52
+ None, description='The type of database (local or shared)'
53
+ )
54
+ database_acl: Optional[str] = Field(
55
+ None, description='Access control information (for internal use)'
56
+ )
57
+ database_options: Optional[str] = Field(None, description='The properties of the database')
58
+ database_isolation_level: Optional[str] = Field(
59
+ None,
60
+ description='The isolation level of the database (Snapshot Isolation or Serializable)',
61
+ )
62
+
63
+
64
+ class RedshiftSchema(BaseModel):
65
+ """Information about a schema in a Redshift database.
66
+
67
+ Based on the SVV_ALL_SCHEMAS system view.
68
+ """
69
+
70
+ database_name: str = Field(..., description='The name of the database where the schema exists')
71
+ schema_name: str = Field(..., description='The name of the schema')
72
+ schema_owner: Optional[int] = Field(None, description='The user ID of the schema owner')
73
+ schema_type: Optional[str] = Field(
74
+ None, description='The type of the schema (external, local, or shared)'
75
+ )
76
+ schema_acl: Optional[str] = Field(
77
+ None, description='The permissions for the specified user or user group for the schema'
78
+ )
79
+ source_database: Optional[str] = Field(
80
+ None, description='The name of the source database for external schema'
81
+ )
82
+ schema_option: Optional[str] = Field(
83
+ None, description='The options of the schema (external schema attribute)'
84
+ )
85
+
86
+
87
+ class RedshiftTable(BaseModel):
88
+ """Information about a table in a Redshift database.
89
+
90
+ Based on the SVV_ALL_TABLES system view.
91
+ """
92
+
93
+ database_name: str = Field(..., description='The name of the database where the table exists')
94
+ schema_name: str = Field(..., description='The schema name for the table')
95
+ table_name: str = Field(..., description='The name of the table')
96
+ table_acl: Optional[str] = Field(
97
+ None, description='The permissions for the specified user or user group for the table'
98
+ )
99
+ table_type: Optional[str] = Field(
100
+ None,
101
+ description='The type of the table (views, base tables, external tables, shared tables)',
102
+ )
103
+ remarks: Optional[str] = Field(None, description='Remarks about the table')
104
+
105
+
106
+ class RedshiftColumn(BaseModel):
107
+ """Information about a column in a Redshift table.
108
+
109
+ Based on the SVV_ALL_COLUMNS system view.
110
+ """
111
+
112
+ database_name: str = Field(..., description='The name of the database')
113
+ schema_name: str = Field(..., description='The name of the schema')
114
+ table_name: str = Field(..., description='The name of the table')
115
+ column_name: str = Field(..., description='The name of the column')
116
+ ordinal_position: Optional[int] = Field(
117
+ None, description='The position of the column in the table'
118
+ )
119
+ column_default: Optional[str] = Field(None, description='The default value of the column')
120
+ is_nullable: Optional[str] = Field(
121
+ None, description='Whether the column is nullable (yes or no)'
122
+ )
123
+ data_type: Optional[str] = Field(None, description='The data type of the column')
124
+ character_maximum_length: Optional[int] = Field(
125
+ None, description='The maximum number of characters in the column'
126
+ )
127
+ numeric_precision: Optional[int] = Field(None, description='The numeric precision')
128
+ numeric_scale: Optional[int] = Field(None, description='The numeric scale')
129
+ remarks: Optional[str] = Field(None, description='Remarks about the column')
130
+
131
+
132
+ class QueryResult(BaseModel):
133
+ """Result of a SQL query execution."""
134
+
135
+ columns: list[str] = Field(..., description='List of column names in the result set')
136
+ rows: list[list] = Field(..., description='List of rows, where each row is a list of values')
137
+ row_count: int = Field(..., description='Number of rows returned')
138
+ execution_time_ms: Optional[int] = Field(
139
+ None, description='Query execution time in milliseconds'
140
+ )
141
+ query_id: str = Field(..., description='Unique identifier for the query execution')