awslabs.redshift-mcp-server 0.0.6__py3-none-any.whl → 0.0.7__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.
@@ -14,4 +14,4 @@
14
14
 
15
15
  """awslabs.redshift-mcp-server"""
16
16
 
17
- __version__ = '0.0.6'
17
+ __version__ = '0.0.7'
@@ -14,13 +14,12 @@
14
14
 
15
15
  """Redshift MCP Server constants."""
16
16
 
17
- # Defaults
18
- DEFAULT_AWS_REGION = 'us-east-1'
17
+ # System
18
+ CLIENT_CONNECT_TIMEOUT = 60
19
+ CLIENT_READ_TIMEOUT = 600
20
+ CLIENT_RETRIES = {'max_attempts': 5, 'mode': 'adaptive'}
21
+ CLIENT_USER_AGENT_NAME = 'awslabs/mcp/redshift-mcp-server'
19
22
  DEFAULT_LOG_LEVEL = 'WARNING'
20
-
21
- # Timeouts (seconds), etc
22
- CLIENT_TIMEOUT = 60
23
- DATA_CLIENT_TIMEOUT = 60
24
23
  QUERY_TIMEOUT = 3600
25
24
  QUERY_POLL_INTERVAL = 2
26
25
 
@@ -29,11 +28,20 @@ QUERY_POLL_INTERVAL = 2
29
28
  CLIENT_BEST_PRACTICES = """
30
29
  ## AWS Client Best Practices
31
30
 
32
- ### Authentication
31
+ ### Authentication and Configuration
33
32
 
34
33
  - Default AWS credentials chain (IAM roles, ~/.aws/credentials, etc.).
35
34
  - AWS_PROFILE environment variable (if set).
36
- - AWS_REGION environment variable (if set).
35
+ - Region configuration (in order of precedence):
36
+ - AWS_REGION environment variable (highest priority)
37
+ - AWS_DEFAULT_REGION environment variable
38
+ - Region specified in AWS profile configuration
39
+
40
+ ### Error Handling
41
+
42
+ - Always print out AWS client errors in full to help diagnose configuration issues.
43
+ - For region-related errors, suggest checking AWS_REGION, AWS_DEFAULT_REGION, or AWS profile configuration.
44
+ - For credential errors, suggest verifying AWS credentials setup and permissions.
37
45
  """
38
46
 
39
47
  REDSHIFT_BEST_PRACTICES = """
@@ -20,8 +20,10 @@ import os
20
20
  import regex
21
21
  from awslabs.redshift_mcp_server import __version__
22
22
  from awslabs.redshift_mcp_server.consts import (
23
- CLIENT_TIMEOUT,
24
- DEFAULT_AWS_REGION,
23
+ CLIENT_CONNECT_TIMEOUT,
24
+ CLIENT_READ_TIMEOUT,
25
+ CLIENT_RETRIES,
26
+ CLIENT_USER_AGENT_NAME,
25
27
  QUERY_POLL_INTERVAL,
26
28
  QUERY_TIMEOUT,
27
29
  SUSPICIOUS_QUERY_REGEXP,
@@ -37,7 +39,9 @@ from loguru import logger
37
39
  class RedshiftClientManager:
38
40
  """Manages AWS clients for Redshift operations."""
39
41
 
40
- def __init__(self, config: Config, aws_region: str, aws_profile: str | None = None):
42
+ def __init__(
43
+ self, config: Config, aws_region: str | None = None, aws_profile: str | None = None
44
+ ):
41
45
  """Initialize the client manager."""
42
46
  self.aws_region = aws_region
43
47
  self.aws_profile = aws_profile
@@ -50,15 +54,12 @@ class RedshiftClientManager:
50
54
  """Get or create the Redshift client for provisioned clusters."""
51
55
  if self._redshift_client is None:
52
56
  try:
53
- if self.aws_profile:
54
- session = boto3.Session(profile_name=self.aws_profile)
55
- self._redshift_client = session.client('redshift', config=self._config)
56
- logger.info(f'Created Redshift client with profile: {self.aws_profile}')
57
- else:
58
- self._redshift_client = boto3.client(
59
- 'redshift', config=self._config, region_name=self.aws_region
60
- )
61
- logger.info('Created Redshift client with default credentials')
57
+ # Session works with None values - uses default credentials/region chain
58
+ session = boto3.Session(profile_name=self.aws_profile, region_name=self.aws_region)
59
+ self._redshift_client = session.client('redshift', config=self._config)
60
+ logger.info(
61
+ f'Created Redshift client with profile: {self.aws_profile or "default"}, region: {self.aws_region or "default"}'
62
+ )
62
63
  except Exception as e:
63
64
  logger.error(f'Error creating Redshift client: {str(e)}')
64
65
  raise
@@ -69,19 +70,14 @@ class RedshiftClientManager:
69
70
  """Get or create the Redshift Serverless client."""
70
71
  if self._redshift_serverless_client is None:
71
72
  try:
72
- if self.aws_profile:
73
- session = boto3.Session(profile_name=self.aws_profile)
74
- self._redshift_serverless_client = session.client(
75
- 'redshift-serverless', config=self._config
76
- )
77
- logger.info(
78
- f'Created Redshift Serverless client with profile: {self.aws_profile}'
79
- )
80
- else:
81
- self._redshift_serverless_client = boto3.client(
82
- 'redshift-serverless', config=self._config, region_name=self.aws_region
83
- )
84
- logger.info('Created Redshift Serverless client with default credentials')
73
+ # Session works with None values - uses default credentials/region chain
74
+ session = boto3.Session(profile_name=self.aws_profile, region_name=self.aws_region)
75
+ self._redshift_serverless_client = session.client(
76
+ 'redshift-serverless', config=self._config
77
+ )
78
+ logger.info(
79
+ f'Created Redshift Serverless client with profile: {self.aws_profile or "default"}, region: {self.aws_region or "default"}'
80
+ )
85
81
  except Exception as e:
86
82
  logger.error(f'Error creating Redshift Serverless client: {str(e)}')
87
83
  raise
@@ -92,19 +88,12 @@ class RedshiftClientManager:
92
88
  """Get or create the Redshift Data API client."""
93
89
  if self._redshift_data_client is None:
94
90
  try:
95
- if self.aws_profile:
96
- session = boto3.Session(profile_name=self.aws_profile)
97
- self._redshift_data_client = session.client(
98
- 'redshift-data', config=self._config
99
- )
100
- logger.info(
101
- f'Created Redshift Data API client with profile: {self.aws_profile}'
102
- )
103
- else:
104
- self._redshift_data_client = boto3.client(
105
- 'redshift-data', config=self._config, region_name=self.aws_region
106
- )
107
- logger.info('Created Redshift Data API client with default credentials')
91
+ # Session works with None values - uses default credentials/region chain
92
+ session = boto3.Session(profile_name=self.aws_profile, region_name=self.aws_region)
93
+ self._redshift_data_client = session.client('redshift-data', config=self._config)
94
+ logger.info(
95
+ f'Created Redshift Data API client with profile: {self.aws_profile or "default"}, region: {self.aws_region or "default"}'
96
+ )
108
97
  except Exception as e:
109
98
  logger.error(f'Error creating Redshift Data API client: {str(e)}')
110
99
  raise
@@ -193,19 +182,22 @@ async def execute_statement(
193
182
  )
194
183
 
195
184
  # Guard from executing read-write statements if not allowed
196
- protected_sqls = protect_sql(sql, allow_read_write)
197
- logger.debug(f'Protected SQL: {" ".join(protected_sqls)}')
185
+ sqls = protect_sql(sql, allow_read_write)
186
+ # Add application name and version
187
+ sqls = [f"SET application_name TO '{CLIENT_USER_AGENT_NAME}/{__version__}';"] + sqls
188
+
189
+ logger.debug(f'Protected and versioned SQL: {" ".join(sqls)}')
198
190
 
199
191
  # Execute the query using Data API
200
192
  if cluster_info['type'] == 'provisioned':
201
193
  logger.debug(f'Using ClusterIdentifier for provisioned cluster: {cluster_identifier}')
202
194
  response = data_client.batch_execute_statement(
203
- ClusterIdentifier=cluster_identifier, Database=database_name, Sqls=protected_sqls
195
+ ClusterIdentifier=cluster_identifier, Database=database_name, Sqls=sqls
204
196
  )
205
197
  elif cluster_info['type'] == 'serverless':
206
198
  logger.debug(f'Using WorkgroupName for serverless workgroup: {cluster_identifier}')
207
199
  response = data_client.batch_execute_statement(
208
- WorkgroupName=cluster_identifier, Database=database_name, Sqls=protected_sqls
200
+ WorkgroupName=cluster_identifier, Database=database_name, Sqls=sqls
209
201
  )
210
202
  else:
211
203
  raise Exception(f'Unknown cluster type: {cluster_info["type"]}')
@@ -237,9 +229,9 @@ async def execute_statement(
237
229
  raise Exception(f'Query timed out after {QUERY_TIMEOUT} seconds')
238
230
 
239
231
  # Get user query results
240
- subquery1_id = status_response['SubStatements'][1]['Id']
241
- results_response = data_client.get_statement_result(Id=subquery1_id)
242
- return results_response, subquery1_id
232
+ subquery2_id = status_response['SubStatements'][2]['Id']
233
+ results_response = data_client.get_statement_result(Id=subquery2_id)
234
+ return results_response, subquery2_id
243
235
 
244
236
 
245
237
  async def discover_clusters() -> list[dict]:
@@ -620,11 +612,11 @@ async def execute_query(cluster_identifier: str, database_name: str, sql: str) -
620
612
  # Global client manager instance
621
613
  client_manager = RedshiftClientManager(
622
614
  config=Config(
623
- connect_timeout=CLIENT_TIMEOUT,
624
- read_timeout=CLIENT_TIMEOUT,
625
- retries={'max_attempts': 3, 'mode': 'adaptive'},
626
- user_agent_extra=f'awslabs/mcp/redshift-mcp-server/{__version__}',
615
+ connect_timeout=CLIENT_CONNECT_TIMEOUT,
616
+ read_timeout=CLIENT_READ_TIMEOUT,
617
+ retries=CLIENT_RETRIES,
618
+ user_agent_extra=f'{CLIENT_USER_AGENT_NAME}/{__version__}',
627
619
  ),
628
- aws_region=os.environ.get('AWS_REGION', DEFAULT_AWS_REGION),
620
+ aws_region=os.environ.get('AWS_REGION'),
629
621
  aws_profile=os.environ.get('AWS_PROFILE'),
630
622
  )
@@ -85,7 +85,7 @@ This tool uses the Redshift Data API to run queries and return results.
85
85
 
86
86
  ## Getting Started
87
87
 
88
- 1. Ensure your AWS credentials are configured (via AWS_PROFILE or default credentials).
88
+ 1. Ensure your AWS configuration and credentials are configured (environment variables or profile configuration file).
89
89
  2. Use the list_clusters tool to discover available Redshift instances.
90
90
  3. Note the cluster identifiers for use with other tools (coming in future milestones).
91
91
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: awslabs.redshift-mcp-server
3
- Version: 0.0.6
3
+ Version: 0.0.7
4
4
  Summary: An AWS Labs Model Context Protocol (MCP) server for Redshift
5
5
  Project-URL: homepage, https://awslabs.github.io/mcp/
6
6
  Project-URL: docs, https://awslabs.github.io/mcp/servers/redshift-mcp-server/
@@ -52,7 +52,11 @@ This MCP server provides tools to discover, explore, and query Amazon Redshift c
52
52
  ### AWS Client Requirements
53
53
 
54
54
  1. **Credentials**: Configure AWS credentials via AWS CLI, or environment variables
55
- 2. **Permissions**: Ensure your AWS credentials have the required permissions (see [Permissions](#permissions) section)
55
+ 2. **Region**: Configure AWS region using one of the following (in order of precedence):
56
+ - `AWS_REGION` environment variable (highest priority)
57
+ - `AWS_DEFAULT_REGION` environment variable
58
+ - Region specified in your AWS profile configuration
59
+ 3. **Permissions**: Ensure your AWS credentials have the required permissions (see [Permissions](#permissions) section)
56
60
 
57
61
  ## Installation
58
62
 
@@ -70,7 +74,7 @@ Configure the MCP server in your MCP client configuration (e.g., for Amazon Q De
70
74
  "args": ["awslabs.redshift-mcp-server@latest"],
71
75
  "env": {
72
76
  "AWS_PROFILE": "default",
73
- "AWS_REGION": "us-east-1",
77
+ "AWS_DEFAULT_REGION": "us-east-1",
74
78
  "FASTMCP_LOG_LEVEL": "INFO"
75
79
  },
76
80
  "disabled": false,
@@ -79,6 +83,7 @@ Configure the MCP server in your MCP client configuration (e.g., for Amazon Q De
79
83
  }
80
84
  }
81
85
  ```
86
+
82
87
  ### Windows Installation
83
88
 
84
89
  For Windows users, the MCP server configuration format is slightly different:
@@ -99,16 +104,15 @@ For Windows users, the MCP server configuration format is slightly different:
99
104
  "awslabs.redshift-mcp-server.exe"
100
105
  ],
101
106
  "env": {
102
- "FASTMCP_LOG_LEVEL": "ERROR",
103
107
  "AWS_PROFILE": "your-aws-profile",
104
- "AWS_REGION": "us-east-1"
108
+ "AWS_DEFAULT_REGION": "us-east-1",
109
+ "FASTMCP_LOG_LEVEL": "ERROR"
105
110
  }
106
111
  }
107
112
  }
108
113
  }
109
114
  ```
110
115
 
111
-
112
116
  or docker after a successful `docker build -t awslabs/redshift-mcp-server:latest .`:
113
117
 
114
118
  ```json
@@ -122,7 +126,7 @@ or docker after a successful `docker build -t awslabs/redshift-mcp-server:latest
122
126
  "--interactive",
123
127
  "--env", "AWS_ACCESS_KEY_ID=[your data]",
124
128
  "--env", "AWS_SECRET_ACCESS_KEY=[your data]",
125
- "--env", "AWS_REGION=[your data]",
129
+ "--env", "AWS_DEFAULT_REGION=[your data]",
126
130
  "awslabs/redshift-mcp-server:latest"
127
131
  ]
128
132
  }
@@ -132,7 +136,8 @@ or docker after a successful `docker build -t awslabs/redshift-mcp-server:latest
132
136
 
133
137
  ### Environment Variables
134
138
 
135
- - `AWS_REGION`: AWS region to use (default: `us-east-1`)
139
+ - `AWS_REGION`: AWS region to use (overrides all other region settings)
140
+ - `AWS_DEFAULT_REGION`: Default AWS region (used if AWS_REGION not set and no region in profile)
136
141
  - `AWS_PROFILE`: AWS profile to use (optional, uses default if not specified)
137
142
  - `FASTMCP_LOG_LEVEL`: Logging level (`DEBUG`, `INFO`, `WARNING`, `ERROR`)
138
143
  - `LOG_FILE`: Path to log file (optional, logs to stdout if not specified)
@@ -0,0 +1,12 @@
1
+ awslabs/__init__.py,sha256=WuqxdDgUZylWNmVoPKiK7qGsTB_G4UmuXIrJ-VBwDew,731
2
+ awslabs/redshift_mcp_server/__init__.py,sha256=zubBv8l-CU0fO2qBX9BFtysTrX0q202KEIxSdlmACHk,673
3
+ awslabs/redshift_mcp_server/consts.py,sha256=0BElrreRZhjZ7sqbO7mtU5MkQP1NAupJp38MtKPfv64,4213
4
+ awslabs/redshift_mcp_server/models.py,sha256=p6oKcVz4xfaqQzXjJrZK9YlfuUnzMDCphXbTK1LT1k4,6437
5
+ awslabs/redshift_mcp_server/redshift.py,sha256=Hhb_t4ZJ61s42bIyHLXQviEuHu0Ngr8s8e8aXh5olCc,24314
6
+ awslabs/redshift_mcp_server/server.py,sha256=HL0stDv4BGWrqtKWvOfoONvZOxvl36TgwqU27g5Kdug,26131
7
+ awslabs_redshift_mcp_server-0.0.7.dist-info/METADATA,sha256=cegav5bZfvHNL_OoLI1QVYaRHvrCcrHIGIml7f846uY,16570
8
+ awslabs_redshift_mcp_server-0.0.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
9
+ awslabs_redshift_mcp_server-0.0.7.dist-info/entry_points.txt,sha256=o2G-onpmq80KMTQw2OrY1G07GmwPaurcJcIqfvMR9Sw,88
10
+ awslabs_redshift_mcp_server-0.0.7.dist-info/licenses/LICENSE,sha256=CeipvOyAZxBGUsFoaFqwkx54aPnIKEtm9a5u2uXxEws,10142
11
+ awslabs_redshift_mcp_server-0.0.7.dist-info/licenses/NOTICE,sha256=iIvfV8gFGERQ7xLtxV8bD_Lsrj9KOIPpvk49qp5-K0c,95
12
+ awslabs_redshift_mcp_server-0.0.7.dist-info/RECORD,,
@@ -1,12 +0,0 @@
1
- awslabs/__init__.py,sha256=WuqxdDgUZylWNmVoPKiK7qGsTB_G4UmuXIrJ-VBwDew,731
2
- awslabs/redshift_mcp_server/__init__.py,sha256=dSiLO85AiX9WDWinzOaxhO-qdzqjs6VvfOnDmD18-ec,673
3
- awslabs/redshift_mcp_server/consts.py,sha256=_r7BEcNEjW8bEOxMwcb6ScCv3w9aXR0vRmd7HzAokyI,3683
4
- awslabs/redshift_mcp_server/models.py,sha256=p6oKcVz4xfaqQzXjJrZK9YlfuUnzMDCphXbTK1LT1k4,6437
5
- awslabs/redshift_mcp_server/redshift.py,sha256=FfzCPi5njzUvehNURHqAaHZr9Lz60Z9bAFXveGHLZR4,24696
6
- awslabs/redshift_mcp_server/server.py,sha256=UNlBqgYS8KLhT9fFKKIPbszH1MtFTY5xCWbED_h-CJ8,26100
7
- awslabs_redshift_mcp_server-0.0.6.dist-info/METADATA,sha256=gIGrr8hnNi5DpDW3Ye-tLUtSTqnPsmjPupyt82rN4Mc,16184
8
- awslabs_redshift_mcp_server-0.0.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
9
- awslabs_redshift_mcp_server-0.0.6.dist-info/entry_points.txt,sha256=o2G-onpmq80KMTQw2OrY1G07GmwPaurcJcIqfvMR9Sw,88
10
- awslabs_redshift_mcp_server-0.0.6.dist-info/licenses/LICENSE,sha256=CeipvOyAZxBGUsFoaFqwkx54aPnIKEtm9a5u2uXxEws,10142
11
- awslabs_redshift_mcp_server-0.0.6.dist-info/licenses/NOTICE,sha256=iIvfV8gFGERQ7xLtxV8bD_Lsrj9KOIPpvk49qp5-K0c,95
12
- awslabs_redshift_mcp_server-0.0.6.dist-info/RECORD,,