Skip to main content

AWS Labs MCP Server for Microsoft SQL Server

An AWS Labs Model Context Protocol (MCP) server for Microsoft SQL Server on AWS RDS.

Features

  • Direct SQL Server connections via password authentication (AWS Secrets Manager)
  • SQL injection detection and mutating keyword blocking
  • Read-only mode enforcement
  • Connection pool management with automatic credential refresh

Tools

  • run_query — Execute SQL queries against SQL Server
  • get_table_schema — Fetch table column information from INFORMATION_SCHEMA
  • connect_to_database — Connect to a SQL Server RDS instance
  • is_database_connected — Check if a connection exists
  • get_database_connection_info — List all cached connections

Usage

awslabs.mssql-mcp-server \
  --connection_method MSSQL_PASSWORD \
  --instance_identifier my-sqlserver-instance \
  --db_endpoint my-instance.xxxx.rds.amazonaws.com \
  --region us-east-1 \
  --database master \
  --port 1433

Connection Methods

  • MSSQL_PASSWORD — Uses credentials from AWS Secrets Manager (MasterUserSecret by default)

Using a custom Secrets Manager secret

By default the server discovers the RDS instance's MasterUserSecret by calling describe_db_instances. To connect as a different database user, create your own secret in AWS Secrets Manager and pass its ARN with --secret_arn:

awslabs.mssql-mcp-server \
  --connection_method MSSQL_PASSWORD \
  --instance_identifier my-sqlserver-instance \
  --db_endpoint my-instance.xxxx.rds.amazonaws.com \
  --region us-east-1 \
  --database master \
  --secret_arn arn:aws:secretsmanager:us-east-1:123456789012:secret:my-readonly-user-AbCdEf

The secret must be a JSON object with the following keys (case variations accepted):

Key Accepted variants
username username, user, Username
password password, Password

Example secret value:

{
  "username": "mcp_readonly",
  "password": "UseAStrongPassword"
}

Secrets are configured exclusively at startup via --secret_arn; the flag is not exposed as an MCP tool parameter, so the LLM cannot select an arbitrary secret ARN.

The --secret_arn flag may be repeated to bind different secrets to different instances:

  • --secret_arn <instance_identifier>=<arn> — bind an ARN to a specific RDS instance (matched against the instance_identifier supplied to connect_to_database).
  • --secret_arn <arn> — a bare ARN used as the default for any instance not pinned explicitly (at most one allowed).

Resolution order: per-target ARN > bare default ARN > the instance's RDS-managed MasterUserSecret. The RDS MasterUserSecret is consulted for a given instance only when that instance has no per-target ARN and no bare default is configured.

TLS / SSL

By default the server connects with --ssl_encryption require, which encrypts the connection and validates the server certificate against the system CA store.

RDS SQL Server certificates are signed by the Amazon RDS CA, which is not included in the default system trust store. If you see a certificate validation error on first connection, install the Amazon RDS CA bundle:

Windows (PowerShell, run as Administrator)

# Download the global RDS CA bundle
Invoke-WebRequest -Uri https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem `
  -OutFile global-bundle.pem

# Import all certificates in the bundle into the Trusted Root store
certutil -addstore "Root" global-bundle.pem

macOS

# Download the global RDS CA bundle
curl -O https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem

# Import into the macOS system keychain (requires sudo)
sudo security add-trusted-cert -d -r trustRoot \
  -k /Library/Keychains/System.keychain global-bundle.pem

Linux (Debian/Ubuntu)

curl -O https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem
sudo cp global-bundle.pem /usr/local/share/ca-certificates/amazon-rds-ca.crt
sudo update-ca-certificates

Linux (RHEL/Amazon Linux)

curl -O https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem
sudo cp global-bundle.pem /etc/pki/ca-trust/source/anchors/amazon-rds-ca.pem
sudo update-ca-trust

After installing the CA cert, restart the MCP server.

SSH Tunnel

When connecting through an SSH tunnel, the transport is already encrypted end-to-end. You can disable TLS at the pymssql layer to avoid certificate validation failures:

awslabs.mssql-mcp-server \
  --connection_method MSSQL_PASSWORD \
  --instance_identifier my-sqlserver-instance \
  --db_endpoint my-instance.xxxx.rds.amazonaws.com \
  --region us-east-1 \
  --ssl_encryption off

Read-Only Mode

By default the server runs in read-only mode. It applies several layers of protection before a query reaches the database:

  1. Mutating keyword blocking — rejects queries containing DML/DDL keywords (INSERT, UPDATE, DELETE, DROP, CREATE, ALTER, MERGE, TRUNCATE, EXEC, GRANT, etc.)
  2. SQL injection pattern detection — blocks common injection vectors such as stacked queries, UNION SELECT, tautologies, WAITFOR DELAY, and calls to system / extended / RDS stored procedures (sp_*, xp_*, rds_*).
  3. Transaction isolation — sets READ COMMITTED isolation level.
  4. Autocommit disabled + forced rollback — in read-only mode, autocommit is off and every query is followed by a rollback, so any mutation that slips past the keyword filter is never committed.

Limitations of application-level read-only mode

The keyword and pattern checks are a best-effort safeguard, not a security boundary. They cannot guarantee that no mutation ever reaches the database because:

  • A stored procedure that performs writes internally could be invoked via a SELECT that doesn't contain any blocked keywords (e.g. SELECT dbo.my_func_that_writes()).
  • Future T-SQL syntax or edge-case encodings might bypass the regex-based detector.

For true read-only enforcement, use a database user that only has read permissions. See Recommended: database-level read-only user below.

Write mode

To allow write queries, pass --allow_write_query:

awslabs.mssql-mcp-server \
  --connection_method MSSQL_PASSWORD \
  --instance_identifier my-sqlserver-instance \
  --db_endpoint my-instance.xxxx.rds.amazonaws.com \
  --region us-east-1 \
  --database master \
  --allow_write_query

Recommended: database-level read-only user

For production use, create a dedicated SQL Server login with only read permissions and store its credentials in Secrets Manager. This provides a hard security boundary that cannot be bypassed at the application layer.

1. Create the login and user in SQL Server

Connect to your RDS instance as the master user and run:

-- Create a server-level login
CREATE LOGIN mcp_readonly WITH PASSWORD = 'UseAStrongPassword';  -- pragma: allowlist secret

-- Switch to the target database
USE my_database;

-- Create a database user mapped to the login
CREATE USER mcp_readonly FOR LOGIN mcp_readonly;

-- Grant read-only access
ALTER ROLE db_datareader ADD MEMBER mcp_readonly;

-- (Optional) Allow the user to view definitions (table schemas, view text, etc.)
GRANT VIEW DEFINITION TO mcp_readonly;

This user can run SELECT queries and read INFORMATION_SCHEMA but cannot INSERT, UPDATE, DELETE, CREATE, DROP, or execute stored procedures.

2. Store the credentials in Secrets Manager

aws secretsmanager create-secret \
  --name mcp/mssql/readonly \
  --description "Read-only SQL Server credentials for MCP server" \
  --secret-string '{"username":"mcp_readonly","password":"UseAStrongPassword"}'  # pragma: allowlist secret

Note the ARN in the output.

3. Start the MCP server with the custom secret

awslabs.mssql-mcp-server \
  --connection_method MSSQL_PASSWORD \
  --instance_identifier my-sqlserver-instance \
  --db_endpoint my-instance.xxxx.rds.amazonaws.com \
  --region us-east-1 \
  --database my_database \
  --secret_arn arn:aws:secretsmanager:us-east-1:123456789012:secret:mcp/mssql/readonly-AbCdEf

With this setup you get defense in depth: the application-level keyword blocker catches mistakes early and provides clear error messages, while the database-level permissions prevent any mutation even if a query slips past the detector.

Notes

  • Default port: 1433
  • Default TLS mode: require (validates server certificate)
  • Connection pools expire after 30 minutes and are automatically refreshed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

awslabs_mssql_mcp_server-0.1.3.tar.gz (163.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

awslabs_mssql_mcp_server-0.1.3-py3-none-any.whl (31.0 kB view details)

Uploaded Python 3

File details

Details for the file awslabs_mssql_mcp_server-0.1.3.tar.gz.

File metadata

  • Download URL: awslabs_mssql_mcp_server-0.1.3.tar.gz
  • Upload date:
  • Size: 163.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for awslabs_mssql_mcp_server-0.1.3.tar.gz
Algorithm Hash digest
SHA256 a6b73a6d681f61b06d79d946be2a6e5d9433a94559aaf88d9923a75e8994135c
MD5 3c2adb8264b0fa243d5dbb44c15893e1
BLAKE2b-256 57706a6fb3ba71b8d16a00e72e60959fb6105033b49aaf74afacebc9045d8c40

See more details on using hashes here.

Provenance

The following attestation bundles were made for awslabs_mssql_mcp_server-0.1.3.tar.gz:

Publisher: release.yml on awslabs/mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file awslabs_mssql_mcp_server-0.1.3-py3-none-any.whl.

File metadata

File hashes

Hashes for awslabs_mssql_mcp_server-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 ea0c3f2fea4908054f43d846c896adcb2835e0370e83d87dfda379c85e63660b
MD5 1c7811d04f4abdc7a6340ff4ebe09b33
BLAKE2b-256 5fd5af877a0afc3a86c45919dc57dd401015c84bbc13429c759528ec3a29f158

See more details on using hashes here.

Provenance

The following attestation bundles were made for awslabs_mssql_mcp_server-0.1.3-py3-none-any.whl:

Publisher: release.yml on awslabs/mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.1.5

2 files

0.1.4

2 files

This release

0.1.3 This release

2 files

0.1.2

2 files

0.1.1

2 files

0.0.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page