Skip to content

Commit f8a00f7

Browse files
fix(dynamodb-mcp-server): use explicit workspace_dir parameter for validation file paths (#1844)
* fix(dynamodb-mcp-server): use explicit workspace_dir parameter for validation file paths * fix(dynamodb-mcp-server): use explicit workspace_dir parameter for validation file paths/remove ctx parameter from the tools --------- Co-authored-by: Laith Al-Saadoon <[email protected]>
1 parent 9d126b1 commit f8a00f7

File tree

4 files changed

+141
-218
lines changed

4 files changed

+141
-218
lines changed

src/dynamodb-mcp-server/awslabs/dynamodb_mcp_server/model_validation_utils.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -819,18 +819,6 @@ def insert_items(dynamodb_client, items: dict) -> Dict[str, Any]:
819819
return item_insertion_response
820820

821821

822-
def get_user_working_directory() -> str:
823-
"""Get the current working directory where the user launched the application.
824-
825-
Uses PWD environment variable (Unix/Linux/macOS) or CD environment variable (Windows)
826-
to determine the directory where the user launched the application.
827-
828-
Returns:
829-
str: The user's current working directory path
830-
"""
831-
return os.environ.get('PWD') or os.environ.get('CD') or os.getcwd()
832-
833-
834822
def get_validation_result_transform_prompt() -> str:
835823
"""Provides transformation prompt for converting DynamoDB access pattern validation result to markdown format.
836824

src/dynamodb-mcp-server/awslabs/dynamodb_mcp_server/server.py

Lines changed: 54 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,14 @@
2424
)
2525
from awslabs.dynamodb_mcp_server.model_validation_utils import (
2626
create_validation_resources,
27-
get_user_working_directory,
2827
get_validation_result_transform_prompt,
2928
setup_dynamodb_local,
3029
)
3130
from loguru import logger
3231
from mcp.server.fastmcp import Context, FastMCP
3332
from pathlib import Path
3433
from pydantic import Field
35-
from typing import Optional
34+
from typing import Any, Dict, List, Optional
3635

3736

3837
DATA_MODEL_JSON_FILE = 'dynamodb_data_model.json'
@@ -291,14 +290,12 @@ async def source_db_analyzer(
291290
async def execute_dynamodb_command(
292291
command: str = Field(description="AWS CLI DynamoDB command (must start with 'aws dynamodb')"),
293292
endpoint_url: Optional[str] = Field(default=None, description='DynamoDB endpoint URL'),
294-
ctx: Optional[Context] = Field(default=None, description='Execution context'),
295293
):
296294
"""Execute AWSCLI DynamoDB commands.
297295
298296
Args:
299297
command: AWS CLI command string (e.g., "aws dynamodb query --table-name MyTable")
300298
endpoint_url: DynamoDB endpoint URL
301-
ctx: Execution context
302299
303300
Returns:
304301
AWS CLI command execution results or error response
@@ -317,60 +314,15 @@ async def execute_dynamodb_command(
317314
command += f' --endpoint-url {endpoint_url}'
318315

319316
try:
320-
return await call_aws(command, ctx)
317+
return await call_aws(command, Context())
321318
except Exception as e:
322319
return e
323320

324321

325-
async def execute_access_patterns(
326-
access_patterns, endpoint_url: Optional[str] = None, ctx: Optional[Context] = None
327-
) -> dict:
328-
"""Execute all data model validation access patterns operations.
329-
330-
Args:
331-
access_patterns: List of access patterns to test
332-
endpoint_url: DynamoDB endpoint URL
333-
ctx: Execution context
334-
335-
Returns:
336-
Dictionary with all execution results
337-
"""
338-
try:
339-
results = []
340-
for pattern in access_patterns:
341-
if 'implementation' not in pattern:
342-
results.append(pattern)
343-
continue
344-
345-
command = pattern['implementation']
346-
result = await execute_dynamodb_command(command, endpoint_url, ctx)
347-
results.append(
348-
{
349-
'pattern_id': pattern.get('pattern'),
350-
'description': pattern.get('description'),
351-
'dynamodb_operation': pattern.get('dynamodb_operation'),
352-
'command': command,
353-
'response': result if isinstance(result, dict) else str(result),
354-
}
355-
)
356-
357-
validation_response = {'validation_response': results}
358-
359-
user_dir = get_user_working_directory()
360-
output_file = os.path.join(user_dir, DATA_MODEL_VALIDATION_RESULT_JSON_FILE)
361-
with open(output_file, 'w') as f:
362-
json.dump(validation_response, f, indent=2)
363-
364-
return validation_response
365-
except Exception as e:
366-
logger.error(f'Failed to execute access patterns validation: {e}')
367-
return {'validation_response': [], 'error': str(e)}
368-
369-
370322
@app.tool()
371323
@handle_exceptions
372324
async def dynamodb_data_model_validation(
373-
ctx: Optional[Context] = Field(default=None, description='Execution context'),
325+
workspace_dir: str = Field(description='Absolute path of the workspace directory'),
374326
) -> str:
375327
"""Validates and tests DynamoDB data models against DynamoDB Local.
376328
@@ -399,15 +351,14 @@ async def dynamodb_data_model_validation(
399351
- Transforms results to markdown format for comprehensive review
400352
401353
Args:
402-
ctx: Execution context
354+
workspace_dir: Absolute path of the workspace directory
403355
404356
Returns:
405357
JSON generation guide (if file missing) or validation results with transformation prompt (if file exists)
406358
"""
407359
try:
408360
# Step 1: Get current working directory reliably
409-
user_dir = get_user_working_directory()
410-
data_model_path = os.path.join(user_dir, DATA_MODEL_JSON_FILE)
361+
data_model_path = os.path.join(workspace_dir, DATA_MODEL_JSON_FILE)
411362

412363
if not os.path.exists(data_model_path):
413364
# Return the JSON generation guide to help users create the required file
@@ -444,7 +395,9 @@ async def dynamodb_data_model_validation(
444395

445396
# Step 5: Execute access patterns
446397
logger.info('Executing access patterns')
447-
await execute_access_patterns(data_model.get('access_patterns', []), endpoint_url, ctx)
398+
await _execute_access_patterns(
399+
workspace_dir, data_model.get('access_patterns', []), endpoint_url
400+
)
448401

449402
# Step 6: Transform validation results to markdown
450403
return get_validation_result_transform_prompt()
@@ -462,5 +415,51 @@ def main():
462415
app.run()
463416

464417

418+
async def _execute_access_patterns(
419+
workspace_dir: str,
420+
access_patterns: List[Dict[str, Any]],
421+
endpoint_url: Optional[str] = None,
422+
) -> dict:
423+
"""Execute all data model validation access patterns operations.
424+
425+
Args:
426+
workspace_dir: Absolute path of the workspace directory
427+
access_patterns: List of access patterns to test
428+
endpoint_url: DynamoDB endpoint URL
429+
430+
Returns:
431+
Dictionary with all execution results
432+
"""
433+
try:
434+
results = []
435+
for pattern in access_patterns:
436+
if 'implementation' not in pattern:
437+
results.append(pattern)
438+
continue
439+
440+
command = pattern['implementation']
441+
result = await execute_dynamodb_command(command, endpoint_url)
442+
results.append(
443+
{
444+
'pattern_id': pattern.get('pattern'),
445+
'description': pattern.get('description'),
446+
'dynamodb_operation': pattern.get('dynamodb_operation'),
447+
'command': command,
448+
'response': result if isinstance(result, dict) else str(result),
449+
}
450+
)
451+
452+
validation_response = {'validation_response': results}
453+
454+
output_file = os.path.join(workspace_dir, DATA_MODEL_VALIDATION_RESULT_JSON_FILE)
455+
with open(output_file, 'w') as f:
456+
json.dump(validation_response, f, indent=2)
457+
458+
return validation_response
459+
except Exception as e:
460+
logger.error(f'Failed to execute access patterns validation: {e}')
461+
return {'validation_response': [], 'error': str(e)}
462+
463+
465464
if __name__ == '__main__':
466465
main()

0 commit comments

Comments
 (0)