Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 32 additions & 3 deletions src/dynamodb-mcp-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@

The official MCP Server for interacting with AWS DynamoDB

This comprehensive server provides both operational DynamoDB management and expert design guidance, featuring 30+ operational tools for managing DynamoDB tables, items, indexes, backups, and more, expert data modeling guidance.
This comprehensive server provides both operational DynamoDB management and expert design guidance, featuring 30+ operational tools for managing DynamoDB tables, items, indexes, backups, and more, expert data modeling guidance and also MySQL query capabilities for database analysis and migration planning.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have we considered to add or change existing evals to include this new use case? Please also consider adding a comment to the CR to show an end-to-end trace where the tool is exercised within the modeling workflow.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 showing end-to-end trace, also keep add a task to add this to current evals.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, will include an end-to-end trace in the PR for better understanding of the workflow. Also, will plan for evals changes later once the actual MySQL data analysis tools are merged.


## Available MCP Tools

### Design & Modeling
- `dynamodb_data_modeling` - Retrieves the complete DynamoDB Data Modeling Expert prompt

### MySQL Integration
- `mysql_run_query` - Run SQL queries against MySQL databases for analysis and migration planning
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we really need to expose a free-from SQL query tool to the LLM. Have we considered having a parameterized SQL query to read the performance schema if that's our only use case?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels odd that the DynamoDB MCP server would expose a tool to run MySQL queries. Was there another option?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to be explicit that this currently uses Aurora/RDS only.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that's the only query (read the performance schema) we need to run. I think in the workflow I have seen, we need to do validation to check if users have enabled the performance schema, and also I think there are queries regarding getting the whole schema for a database. So there is a need for a tool that can run many such queries. The question is, is there a way to restrict the queries to only a few approved by us? Worth checking.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm working on calling the mysql_run_query method within our analysis tool to execute the required SQL instead of registering as a separate tool. This will avoid exposing the tool publicly or user runs random calls.


### Table Operations
- `create_table` - Creates a new DynamoDB table with optional secondary indexes
- `delete_table` - Deletes a table and all of its items
Expand Down Expand Up @@ -61,6 +64,22 @@ To use these tools, ensure you have proper AWS credentials configured with appro

All tools support an optional `region_name` parameter to specify which AWS region to operate in. If not provided, it will use the AWS_REGION environment variable or default to 'us-west-2'.

## MySQL Integration

The DynamoDB MCP server includes MySQL integration to run mysql queries within DynamoDB MCP server. When configured, it adds a `mysql_run_query` tool for database analysis and migration planning.

### MySQL Environment Variables

Add these environment variables to DynamoDB MCP Server configuration to enable MySQL integration:

- `MYSQL_CLUSTER_ARN`: RDS / Aurora MySQL cluster ARN
- `MYSQL_SECRET_ARN`: AWS Secrets Manager secret ARN with database credentials
- `MYSQL_DATABASE`: Database name to connect to
- `MYSQL_AWS_REGION`: AWS region for MySQL cluster (default: "us-west-2")
- `MYSQL_READONLY`: optional (default: "true")

**Note**: MySQL integration tool is available only when these variables are set.

## Prerequisites

1. Install `uv` from [Astral](https://docs.astral.sh/uv/getting-started/installation/) or the [GitHub README](https://github.com/astral-sh/uv#installation)
Expand All @@ -86,7 +105,12 @@ Add the MCP to your favorite agentic tools. (e.g. for Amazon Q Developer CLI MCP
"DDB-MCP-READONLY": "true",
"AWS_PROFILE": "default",
"AWS_REGION": "us-west-2",
"FASTMCP_LOG_LEVEL": "ERROR"
"FASTMCP_LOG_LEVEL": "ERROR",
"MYSQL_CLUSTER_ARN": "[your data]",
"MYSQL_SECRET_ARN": "[your data]",
"MYSQL_DATABASE": "[your data]",
"MYSQL_AWS_REGION": "us-west-2",
"MYSQL_READONLY": "true"
Comment on lines +108 to +113
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explain MYSQL_SECRET_ARN in the README and why its required. Don't use [your data], put place holder values that are dummy and more intuitive to understand.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, will explain that in readme

},
"disabled": false,
"autoApprove": []
Expand Down Expand Up @@ -116,7 +140,12 @@ For Windows users, the MCP server configuration format is slightly different:
"env": {
"FASTMCP_LOG_LEVEL": "ERROR",
"AWS_PROFILE": "your-aws-profile",
"AWS_REGION": "us-east-1"
"AWS_REGION": "us-east-1",,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whats the purpose of this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, we have DynamoDB API's using this particular AWS_REGION variable, we will remove that and use DB specific variables. It will help in case use resources (such as DB's) running on different regions.

"MYSQL_CLUSTER_ARN": "[your data]",
"MYSQL_SECRET_ARN": "[your data]",
"MYSQL_DATABASE": "[your data]",
"MYSQL_AWS_REGION": "us-west-2",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be place holder

"MYSQL_READONLY": "true"
}
}
}
Expand Down
42 changes: 40 additions & 2 deletions src/dynamodb-mcp-server/awslabs/dynamodb_mcp_server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,19 @@
from mcp.server.fastmcp import FastMCP
from pathlib import Path
from pydantic import Field
from typing import Any, Dict, List, Literal, Union
from typing import Any, Dict, List, Literal, Union, Optional, Annotated

from awslabs.mysql_mcp_server.server import DBConnectionSingleton, run_query as mysql_query


# Define server instructions and dependencies
SERVER_INSTRUCTIONS = """The official MCP Server for interacting with AWS DynamoDB

This server provides comprehensive DynamoDB capabilities with over 30 operational tools for managing DynamoDB tables,
items, indexes, backups, and more, plus expert data modeling guidance through DynamoDB data modeling expert prompt
items, indexes, backups, and more, plus expert data modeling guidance through DynamoDB data modeling expert prompt.

MySQL Integration: This server also includes MySQL query capabilities through the run_query tool, enabling database
analysis and migration planning from MySQL to DynamoDB.
Comment on lines +65 to +66
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For Aurora/RDS


IMPORTANT: DynamoDB Attribute Value Format
-----------------------------------------
Expand Down Expand Up @@ -942,6 +947,39 @@ async def list_imports(
}


@app.tool()
@handle_exceptions
async def mysql_run_query(
sql: Annotated[str, Field(description='The SQL query to run')],
query_parameters: Annotated[
Optional[List[Dict[str, Any]]], Field(description='Parameters for the SQL query')
] = None,
) -> list[dict]:
"""Run a SQL query against a MySQL database for analysis and migration planning."""

if all([os.getenv('MYSQL_CLUSTER_ARN'), os.getenv('MYSQL_SECRET_ARN'), os.getenv('MYSQL_DATABASE')]):

cluster_arn = os.getenv('MYSQL_CLUSTER_ARN')
secret_arn = os.getenv('MYSQL_SECRET_ARN')
database = os.getenv('MYSQL_DATABASE')
region = os.getenv('AWS_REGION', 'us-west-2')
readonly = os.getenv('MYSQL_READONLY', 'true').lower() == 'true'

try:
DBConnectionSingleton.initialize(cluster_arn, secret_arn, database, region, readonly)
except Exception as e:
return [{'error': f'MySQL initialization failed: {str(e)}'}]
else:
return [{'error': 'MySQL configuration not properly configured or available'}]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1/ This error is vague, most users don't read documentation. Should we make it
clearer what's misconfigured?
2/ Should we log errors with logging?
3/ Should we log the error in the MCP context?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, will do


class DummyContext:
async def error(self, message): pass

try:
return await mysql_query(sql, DummyContext(), None, query_parameters)
except Exception as e:
return [{'error': f'MySQL query failed: {str(e)}'}]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my previous comment about error handling


def main():
"""Main entry point for the MCP server application."""
app.run()
Expand Down
3 changes: 2 additions & 1 deletion src/dynamodb-mcp-server/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ dependencies = [
"pydantic==2.11.7",
"typing-extensions==4.14.1",
"strands-agents>=1.5.0",
"dspy-ai>=2.6.27"
"dspy-ai>=2.6.27",
"awslabs-mysql-mcp-server>=1.0.5",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be dependent on other MCP servers. When we need to extend support to other databases, or on-prem how do we handle that. Take a dependence on N number of MCP's doesn't seem like a viable approach.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now MySQL package is focused on Aurora MySQL, PR (1246) is yet to merge which will support both AWS and on-prem mysql. so this 1 package will eventually take care of entire MySQL databases. We will have to find / use similar packages for other databases.

]
license = {text = "Apache-2.0"}
license-files = ["LICENSE", "NOTICE" ]
Expand Down
44 changes: 44 additions & 0 deletions src/dynamodb-mcp-server/tests/test_mysql_integration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import os
import pytest
import pytest_asyncio
from awslabs.dynamodb_mcp_server.server import mysql_run_query


class TestMySQLIntegration:
"""Test MySQL integration functionality."""

@pytest.mark.asyncio
async def test_mysql_connection_and_query(self, monkeypatch):
"""Test MySQL connection initialization and query execution."""
# Set environment variables using monkeypatch
monkeypatch.setenv('MYSQL_CLUSTER_ARN', 'arn:aws:rds:us-west-2:123456789012:cluster:test-cluster')
monkeypatch.setenv('MYSQL_SECRET_ARN', 'arn:aws:secretsmanager:us-west-2:123456789012:secret:test-secret')
monkeypatch.setenv('MYSQL_DATABASE', 'test_database')
monkeypatch.setenv('MYSQL_AWS_REGION', 'us-west-2')
monkeypatch.setenv('MYSQL_READONLY', 'true')

# Mock the MySQL functions using monkeypatch
def mock_initialize(*args, **kwargs):
return True

async def mock_query(*args, **kwargs):
return [{'id': 1, 'name': 'test'}]

monkeypatch.setattr('awslabs.dynamodb_mcp_server.server.DBConnectionSingleton.initialize', mock_initialize)
monkeypatch.setattr('awslabs.dynamodb_mcp_server.server.mysql_query', mock_query)

result = await mysql_run_query("SELECT * FROM users")

assert result == [{'id': 1, 'name': 'test'}]

@pytest.mark.asyncio
async def test_mysql_missing_config(self, monkeypatch):
"""Test MySQL query when configuration is missing."""
# Clear MySQL env vars using monkeypatch
monkeypatch.delenv('MYSQL_CLUSTER_ARN', raising=False)
monkeypatch.delenv('MYSQL_SECRET_ARN', raising=False)
monkeypatch.delenv('MYSQL_DATABASE', raising=False)

result = await mysql_run_query("SELECT * FROM users")
assert 'error' in result[0]
assert 'MySQL configuration not properly configured' in result[0]['error']
18 changes: 18 additions & 0 deletions src/dynamodb-mcp-server/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading