Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/A-Point-Systems-ltd/ms-sql-mcp/llms.txt

Use this file to discover all available pages before exploring further.

The server’s security posture is primarily about credential management and SQL injection risk, because it executes T-SQL directly against a live database on every tool call. Understanding these risks is essential before deploying in any shared or production environment. The sections below cover the four main areas of concern: how credentials flow, which tools are explicitly flagged as destructive, where SQL injection exposure exists, and what database permissions the AI Insights layer requires.

Credential management

The CONNECTION_STRING environment variable is the only credential the server needs. It must be provided through the MCP client configuration env block and must never appear in source control.
{
  "mcpServers": {
    "MSSQL-MCP": {
      "type": "stdio",
      "command": "C:\\path\\to\\MssqlMcp.exe",
      "env": {
        "CONNECTION_STRING": "Server=.;Database=MyDb;Trusted_Connection=True;TrustServerCertificate=True"
      }
    }
  }
}
At startup, Program.cs logs a masked version of the connection string: any key whose name contains password or pwd (case-insensitive) is replaced with ***MASKED***, while all other fields remain visible in the log. This means secrets embedded in non-standard key names could still appear in log output. To minimise what is written to log files, prefer Windows Authentication (Trusted_Connection=True) or Microsoft Entra / Azure AD authentication rather than SQL login with a password.
Never commit real credentials to version control — including project-level MCP config files such as .cursor/mcp.json or .vscode/mcp.json. Add these files to .gitignore if they contain environment variables with real values.

Destructive tool flags

Three tools are explicitly marked Destructive = true and ReadOnly = false in their MCP metadata:
ToolMCP flagsRisk
ExecuteSQLwrite, destructiveRuns arbitrary DDL/DML — ALTER, DROP, TRUNCATE, DELETE, MERGE, EXEC, …
DropTablewrite, destructivePermanently removes a table and all its data
UpdateDatawrite, destructiveModifies existing rows; always requires a WHERE clause
MCP-aware clients that surface tool metadata should show confirmation prompts before invoking any of these tools. When building agents or workflows on top of the server, always confirm destructive intent with the user before calling these tools — never issue them speculatively or as a side-effect of another investigation.

SQL injection

ReadData and ExecuteSQL do not support parameterized queries. SQL statements are assembled as literals and sent directly to the database engine. This is by design — the tools are intended to accept agent-generated SQL, not arbitrary user input.
Never pass untrusted user input directly through ReadData or ExecuteSQL without sanitization. An adversary who can control the SQL string can read, modify, or delete any data the database user has access to. These tools are designed for agent-constructed queries where the agent controls the full SQL text.
If your deployment exposes the MCP server to multiple users or to a public-facing LLM, consider:
  • Running the server with a read-only SQL login when write tools are not needed
  • Restricting the database user to a specific schema or set of objects
  • Using a dedicated database that contains no sensitive production data

DDL trigger permissions

The AI Insights layer installs a database-level DDL trigger (DDL_Audit) via InstallInsightsLayer. Creating a database-level DDL trigger requires one of the following:
  • ALTER ANY DATABASE DDL TRIGGER permission (fine-grained, preferred)
  • Membership in the ddl_admin fixed database role
  • Membership in the sysadmin fixed server role
In production, grant only ALTER ANY DATABASE DDL TRIGGER to a dedicated service account or database role rather than elevating to ddl_admin or sysadmin. The trigger runs with database scope and captures DDL events (table creates, alters, drops) into dbo.DDL_AuditLog for freshness tracking. Install is idempotent — re-running InstallInsightsLayer after the trigger already exists is safe and will not duplicate objects.

Read/write routing

The SqlStatementClassifier enforces a strict split between read and write paths to prevent accidental destructive operations through the wrong tool:
  • ReadData — accepts only SELECT and read-only WITH … SELECT (CTEs that end in a SELECT). SELECT … INTO is rejected.
  • ExecuteSQL — accepts DDL and DML only. Any SELECT statement is rejected with a message directing the caller to ReadData.
This separation keeps all destructive operations behind a tool explicitly marked as destructive in MCP metadata, and prevents full-table reads from silently succeeding through the write path. Note that multi-batch GO-delimited scripts are not supported by ExecuteSQL — split them into individual statements before calling the tool.

Build docs developers (and LLMs) love