Skip to content

v1.1.0 — truncation reporting, security tools, credential hardening

Latest

Choose a tag to compare

@nocentino nocentino released this 14 Sep 16:37
· 1 commit to main since this release

First tagged release of the SQL Server MCP demo: a custom DBA-monitoring MCP server (34 tools over SQL Server DMVs, multi-instance) alongside Data API Builder for application data, all in Docker Compose.

Highlights

  • Truncation is now reported, not silent. Every query tool caps its result set and tells you when it did: responses carry truncated and row_limit. Previously the flag could never be true, so an agent had no way to tell a complete result from a clipped one. execute_query now returns { rows, truncated, row_limit } instead of a bare array.
  • Four security & auditing tools: get_security_config_drift, get_sysadmin_members, get_failed_logins, get_orphaned_users.
  • Passwords come from .env, and stay off command lines. The dba_monitor and dab_app logins are created from MONITOR_PASSWORD / DAB_PASSWORD; every sqlcmd call uses SQLCMDPASSWORD; the MCP container receives only INSTANCES.

Fixes

MCP server

  • Row cap uses a sentinel row (SET ROWCOUNT limit+1) so truncated is observable; the old TOP (n) bypass, which never matched the server's own queries, is gone. A tool-level TOP and the cap now compose correctly, so get_cpu_history returns its full 256 samples instead of being clipped at 200.
  • get_index_usage_stats manages its own row cap so the temp-table load is never clipped before the final select.
  • fan_out_query runs the same read-only validation as execute_query.
  • Safety validation matches bare keywords (INSERT dbo.T, DELETE dbo.T, EXEC on a new line, SELECT … INTO dbo.T were all slipping through), while string literals are ignored so audit queries such as WHERE permission_name = 'DELETE' still run.
  • Default instance is the first one registered; instance_name is matched case-insensitively; unknown names return the available list instead of failing on a hard-coded default.
  • Concurrent first calls to one instance share a single connection pool.

Environment

  • Compose healthchecks use sqlcmd -b exit codes (no shell pipeline), shared via one anchor for both SQL Server containers.
  • Init containers run with -b, so a failed T-SQL batch fails the container instead of leaving a half-initialised database that downstream services start against.
  • start.sh uses docker compose up --wait, runs from any working directory, and fails fast on a missing SA_PASSWORD instead of hanging on a sqlcmd password prompt.
  • scripts/ag/setup-ag.sh reads the sa password from .env, surfaces sqlcmd errors instead of swallowing them, and no longer prints the password.
  • Removed a dead docker-entrypoint-initdb.d mount and a redundant 10-second sleep from the startup path.
  • Test scripts fixed and extended: the MCP protocol suite now covers all 34 tools plus truncation, safety, and instance-routing cases (44 checks).

Upgrading from an untagged checkout

  1. Add MONITOR_PASSWORD and DAB_PASSWORD to .env (see .env.example). MONITOR_PASSWORD must match the password fields in INSTANCES. Avoid single quotes and $( in these values.
  2. Run ./start.sh. Existing volumes are fine: the init scripts re-sync the login passwords to .env on every start.
  3. If you parse execute_query output, read rows from the returned object.

Verification

Fresh-stack run on macOS / Docker Compose v5: endpoint tests 8/8, T-SQL smoke tests 19/19, MCP protocol tests 44/44, Always On AG setup script end to end (TestAG synchronized on both replicas).