SKILL.md
SQL MCP Server (Data API Builder MCP)
This skill powers GitHub Copilot assistance for SQL MCP Server, a feature of Data API Builder (DAB) version 1.7+ that exposes databases to AI agents via the Model Context Protocol (MCP). It provides conversational guidance for configuring, deploying, and securing SQL MCP Server for AI-powered database workflows.
Core Mental Model
SQL MCP Server enables AI agents to interact with databases through a secure, typed interface. It's Data API Builder with MCP capabilities, not a separate product. Users who need MCP capabilities but have never heard of DAB should be guided through the complete setup.
What SQL MCP Server Provides
- MCP endpoint at
/mcpthat exposes database entities as MCP tools - Six DML tools for agents:
describeentities,createrecord,readrecords,updaterecord,deleterecord,executeentity - Security through abstraction - agents never touch SQL directly, only work through DAB's entity layer
- Deterministic queries - no NL2SQL, only NL2DAB (safe, predictable SQL generation)
- RBAC enforcement - role-based access control applies to every tool operation
- Built-in caching - automatic result caching for
read_recordsoperations - Full observability - OpenTelemetry tracing, health checks, Azure monitoring
Key Architecture
AI Agent (VS Code, Foundry, Custom)
→ MCP Protocol
→ SQL MCP Server (/mcp endpoint)
→ DAB Entity Abstraction Layer
→ Database (SQL Server, PostgreSQL, MySQL, etc.)
Configuration Approach
SQL MCP Server uses the same dab-config.json as regular DAB:
data-source: Database connection settingsruntime.mcp: MCP-specific settings (enabled, path, tool controls)entities: Exposed tables/views/stored procedures with descriptions and permissions
MCP is enabled by default when you have DAB 1.7+. You only need to configure it when you want to restrict what agents can do.
Understanding MCP vs Data API Builder
Common User Starting Points
Scenario 1: User comes with MCP needs
- User: "I want to give my AI agent access to my database via MCP"
- Approach: Explain SQL MCP Server is DAB's MCP feature, guide through full setup
Scenario 2: User knows DAB, wants MCP
- User: "I have a DAB config, how do I enable MCP?"
- Approach: Just upgrade to v1.7+ - MCP is enabled by default
Scenario 3: User confused about naming
- User: "Is SQL MCP Server different from Data API Builder?"
- Approach: Clarify it's DAB 1.7+ with MCP capabilities enabled
Terminology Guide
| Term | What It Means |
|---|---|
| SQL MCP Server | Marketing name for DAB's MCP capabilities |
| Data API Builder (DAB) | The underlying engine that powers everything |
| MCP | Model Context Protocol - standard for AI agent tool discovery |
| DML Tools | The six CRUD+execute operations exposed via MCP |
| Entity abstraction | DAB's security layer that protects your database schema |
Installation & Prerequisites
Version Requirements
Critical: SQL MCP Server requires Data API builder 1.7+ (currently in preview/RC).
Install DAB CLI (Prerelease)
dotnet tool install microsoft.dataapibuilder --prerelease
Or update existing:
dotnet tool update microsoft.dataapibuilder --prerelease
Verify Installation
dab --version
# Should show 1.7.x or higher
Prerequisites Checklist
- .NET 9.0+ installed
- DAB CLI 1.7+ installed
- Database access (SQL Server, PostgreSQL, MySQL, Cosmos DB)
- Environment variable support (for connection strings)
- VS Code or MCP client for testing
Quick Start Workflow
For Users New to Both MCP and DAB
Recommended Path:
- Install DAB CLI (prerelease)
- Create database and sample table
- Initialize DAB config with MCP enabled (default)
- Add entities with semantic descriptions
- Start SQL MCP Server locally
- Connect from VS Code or other MCP client
- Test with agent prompts
Example: 5-Minute Setup
# 1. Initialize config (MCP enabled by default)
dab init \
--database-type mssql \
--connection-string "@env('DATABASE_CONNECTION_STRING')" \
--host-mode Development \
--config dab-config.json
# 2. Add entity with description
dab add Products \
--source dbo.Products \
--permissions "anonymous:read" \
--description "Product catalog with pricing, inventory, and supplier information"
# 3. Add field descriptions (critical for AI understanding)
dab update Products \
--fields.name ProductID \
--fields.description "Unique product identifier" \
--fields.primary-key true
dab update Products \
--fields.name ProductName \
--fields.description "Display name of the product"
dab update Products \
--fields.name UnitPrice \
--fields.description "Retail price per unit in USD"
# 4. Validate and start
dab validate && dab start
Connect from VS Code: Create .vscode/mcp.json:
{
"servers": {
"sql-mcp-server": {
"type": "http",
"url": "http://localhost:5000/mcp"
}
}
}
Configuration Reference
MCP Runtime Settings
Default behavior: MCP is enabled with all tools active. Only configure when restricting.
{
"runtime": {
"mcp": {
"enabled": true, // default: true
"path": "/mcp", // default: /mcp
"description": "Optional server description for clients",
"dml-tools": {
"describe-entities": true, // default: true
"create-record": true, // default: true
"read-records": true, // default: true
"update-record": true, // default: true
"delete-record": true, // default: true
"execute-entity": true // default: true
}
}
}
}
CLI Configuration Commands
# Enable/disable MCP globally
dab configure --runtime.mcp.enabled true
dab configure --runtime.mcp.path "/mcp"
# Disable specific tools globally (restrict all agents)
dab configure --runtime.mcp.dml-tools.delete-record false
dab configure --runtime.mcp.dml-tools.create-record false
# Add server description (shown to MCP clients)
dab configure --runtime.mcp.description "Production inventory database MCP endpoint"
Entity-Level MCP Control
Default: Entities participate in MCP automatically. Only configure to exclude or restrict.
{
"entities": {
"Products": {
"mcp": {
"dml-tools": true // default: true (all tools allowed per runtime settings)
}
},
"SensitiveData": {
"mcp": {
"dml-tools": false // exclude this entity from MCP completely
}
},
"AuditLogs": {
"mcp": {
"dml-tools": {
"create-record": true, // allow create
"read-records": true, // allow read
"update-record": false, // prevent updates
"delete-record": false // prevent deletes
}
}
}
}
}
The Six DML Tools
SQL MCP Server exposes exactly six tools to AI agents:
1. describe_entities
Purpose: Returns all entities the current role can access, including fields, types, descriptions, and allowed operations.
Key Points:
- Doesn't query the database - reads from in-memory config
- Shows only entities/fields the current role can see
- Critical first step for agents to understand available data
- Includes semantic descriptions you add via
--descriptionflags
Example Response:
{
"entities": [
{
"name": "Products",
"description": "Product catalog with pricing and inventory",
"fields": [
{
"name": "ProductId",
"type": "int",
"isKey": true,
"description": "Unique product identifier"
},
{
"name": "UnitPrice",
"type": "decimal",
"description": "Retail price in USD"
}
],
"operations": ["read_records", "update_record"]
}
]
}
2. create_record
Purpose: Insert new rows into tables.
Requirements:
- Entity must have
createpermission for current role - Validates against entity schema
- Enforces create policies
- Returns created record with generated values (e.g., auto-increment IDs)
3. read_records
Purpose: Query tables and views with filtering, sorting, pagination, and field selection.
Features:
- Builds deterministic SQL from structured parameters (NL2DAB, not NL2SQL)
- Applies read permissions and field projections
- Enforces row-level security policies
- Automatic caching - results cached per DAB caching config
4. update_record
Purpose: Modify existing rows.
Requirements:
- Requires primary key and fields to update
- Validates PK exists
- Enforces update permissions and policies
- Only updates fields current role can modify
5. delete_record
Purpose: Remove existing rows.
Requirements:
- Requires primary key
- Validates PK exists
- Enforces delete permissions and policies
Warning: Many production deployments disable this tool globally to prevent accidental data loss.
6. execute_entity
Purpose: Execute stored procedures.
Features:
- Supports input parameters and output results
- Validates parameters against procedure signature
- Enforces execute permissions
- Passes parameters safely (prevents SQL injection)
Semantic Descriptions (Critical for AI)
Why descriptions matter: AI agents rely on context. Without descriptions, agents only see technical names like ProductID. With descriptions, they understand it's "Unique identifier for each product in the catalog."
Entity Descriptions
# Add during creation
dab add Products \
--source dbo.Products \
--permissions "anonymous:*" \
--description "Product catalog with pricing, inventory, and supplier information"
# Update existing entity
dab update Products \
--description "Product catalog with pricing, inventory, and supplier information"
Field Descriptions
# Single field
dab update Products \
--fields.name UnitPrice \
--fields.description "Retail price per unit in USD"
# Multiple fields (call multiple times)
dab update Products \
--fields.name ProductID \
--fields.description "Unique identifier for each product" \
--fields.primary-key true
dab update Products \
--fields.name UnitsInStock \
--fields.description "Current inventory count available for purchase"
Stored Procedure Parameter Descriptions
dab add GetOrdersByDateRange \
--source dbo.usp_GetOrdersByDateRange \
--source.type stored-procedure \
--permissions "authenticated:execute" \
--description "Retrieves all orders placed within a specified date range" \
--parameters.name "StartDate,EndDate,CustomerID" \
--parameters.description "Beginning of date range (inclusive),End of date range (inclusive),Optional customer ID filter (null returns all customers)" \
--parameters.required "true,true,false" \
--parameters.default ",,null"
Description Best Practices
Do:
- Be specific: "Customer shipping address" not "Address"
- Include units: "Price in USD", "Weight in kilograms"
- Mention formats: "ISO 8601 date format", "E.164 phone format"
- Explain business rules: "Negative values indicate credit balance"
- Note optional fields: "Optional; null returns all results"
Don't:
- Use only technical jargon
- Duplicate field names: "ProductID is the product ID" adds no value
- Write novels - keep to 1-2 sentences
- Ignore nullable fields - mention when null has special meaning
Security & Authentication
Two Authentication Directions
Inbound (Client → SQL MCP Server): How AI agents authenticate to your MCP endpoint Outbound (SQL MCP Server → Database): How DAB authenticates to your database
Outbound Authentication (to Database)
Option 1: SQL User/Password (Development)
dab init \
--database-type mssql \
--connection-string "@env('SQL_CONNECTION_STRING')"
Environment variable:
SQL_CONNECTION_STRING=Server=tcp:myserver.database.windows.net,1433;Database=mydb;User ID=myuser;Password=mypass;Encrypt=True;
Option 2: Managed Identity (Recommended for Azure)
Server=tcp:myserver.database.windows.net,1433;Database=mydb;Authentication=Active Directory Managed Identity;
For User-Assigned Managed Identity (UAMI):
Server=tcp:myserver.database.windows.net,1433;Database=mydb;Authentication=Active Directory Managed Identity;User Id=<uami-client-id>;
Inbound Authentication (from Clients)
Option 1: Anonymous (Development Only)
# No auth config needed - defaults to anonymous
# Agents use only what 'anonymous' role permits
dab configure --runtime.host.authentication.provider AppService
Option 2: Microsoft Entra ID / JWT (Production)
dab configure \
--runtime.host.authentication.provider EntraId
dab configure \
--runtime.host.authentication.jwt.audience "api://<app-id>"
dab configure \
--runtime.host.authentication.jwt.issuer "https://login.microsoftonline.com/<tenant-id>/v2.0"
# Grant permissions for authenticated users
dab update Products --permissions "authenticated:read"
Option 3: API Gateway (Key-Based)
- SQL MCP Server doesn't support API keys directly
- Front the
/mcpendpoint with Azure API Management or similar gateway - Gateway handles key validation, forwards to SQL MCP Server
RBAC (Role-Based Access Control)
Every DML tool operation enforces RBAC rules:
- Which entities are visible
- Which operations are allowed (create/read/update/delete/execute)
- Which fields are included/excluded
- Whether row-level policies apply
# Anonymous can only read specific fields
dab add Products --source dbo.Products --permissions "anonymous:read"
dab update Products --fields.exclude "Cost,Margin,SupplierID"
# Authenticated users can CRUD
dab update Products --permissions "authenticated:*"
# Admin can see everything
dab update Products --permissions "admin:*"
Deployment Scenarios
Local Development (VS Code)
Steps:
- Run
dab startin terminal - Create
.vscode/mcp.jsonin workspace - Configure MCP server in VS Code
- Test with Copilot Chat
MCP Config:
{
"servers": {
"sql-mcp-server": {
"type": "http",
"url": "http://localhost:5000/mcp"
}
}
}
Azure Container Apps
Key Steps:
- Create Azure SQL Database
- Configure
dab-config.json - Create Dockerfile with embedded config
- Build and push to Azure Container Registry
- Deploy to Container Apps with connection string secret
- Get public MCP endpoint URL
Dockerfile:
FROM mcr.microsoft.com/azure-databases/data-api-builder:1.7.83-rc
COPY dab-config.json /App/dab-config.json
⚠️ ANTI-PATTERN: Never use Azure Files, storage accounts, or volume mounts for
dab-config.json. Always build a custom Docker image with the config embedded and push to ACR. Storage mounts add latency, failure modes, and unnecessary complexity.
Deploy:
az containerapp create \
--name sql-mcp-server \
--resource-group rg-sql-mcp \
--environment sql-mcp-env \
--image <acr>.azurecr.io/sql-mcp-server:1 \
--target-port 5000 \
--ingress external \
--secrets "mssql-connection-string=<connection-string>" \
--env-vars "MSSQL_CONNECTION_STRING=secretref:mssql-connection-string"
.NET Aspire
Integration Pattern:
- Add DAB as Aspire component
- Configure via
appsettings.jsonor environment - MCP endpoint available within Aspire service mesh
- Use with Aspire-hosted AI agents
Microsoft AI Foundry
Connection Steps:
- Deploy SQL MCP Server (Container Apps or other hosting)
- In Foundry project: Add a tool → Custom → Model Context Protocol
- Set remote MCP endpoint URL
- Configure authentication (Unauthenticated, Entra ID, or OAuth passthrough)
- Test with agent prompts
Common Conversational Patterns
User: "I want to give my AI agent database access"
Ask:
- Do you have a database set up?
- Have you heard of Data API Builder (DAB)?
- What database type? (SQL Server, PostgreSQL, MySQL, Cosmos DB)
- Where will the agent run? (VS Code, Azure AI Foundry, custom client)
- What tables/views should the agent access?
Guide through:
- Install DAB CLI 1.7+ (prerelease)
- Initialize config with database connection
- Add entities with descriptions
- Start locally for testing
- Deploy to Azure if needed
User: "How do I enable MCP on my existing DAB config?"
Answer:
- MCP is enabled by default in DAB 1.7+
- Just upgrade:
dotnet tool update microsoft.dataapibuilder --prerelease - Restart with
dab start-/mcpendpoint is live - Only configure if you want to restrict tools or entities
User: "My agent can't see my tables"
Troubleshoot:
- Is entity added to config? (
dab add) - Does current role have permissions? (check
--permissions) - Is entity excluded from MCP? (check
mcp.dml-tools: false) - Is tool disabled globally? (check
runtime.mcp.dml-tools) - Did agent call
describe_entitiesfirst?
User: "How do I prevent agents from deleting data?"
Options:
- Global:
dab configure --runtime.mcp.dml-tools.delete-record false - Per-entity: Set
mcp.dml-tools.delete-record: falsein entity config - RBAC: Don't grant
deleteaction to agent's role
User: "Can agents write raw SQL?"
Answer:
- No. SQL MCP Server intentionally doesn't support NL2SQL.
- Agents use structured DML tools that generate deterministic SQL via DAB's query builder.
- This prevents SQL injection and ensures safety/predictability.
- Think of it as NL2DAB (natural language → DAB API → safe SQL).
User: "How do I add descriptions for better AI understanding?"
Guide:
- Entity level: Use
--descriptionindab addordab update - Field level: Use
--fields.nameand--fields.descriptionindab update - Parameters: Use
--parameters.nameand--parameters.descriptionfor stored procedures - Include units, formats, business rules, and context
Example:
dab update Products \
--fields.name UnitPrice \
--fields.description "Retail price per unit in USD (includes tax)"
User: "How do I deploy to production?"
Recommend:
- Azure Container Apps (simplest Azure hosting)
- Azure App Service (alternative)
- Kubernetes (advanced)
Key considerations:
- Use managed identity for database auth
- Enable Microsoft Entra ID for inbound auth
- Disable
delete-recordtool if appropriate - Configure CORS and rate limiting
- Enable Application Insights monitoring
- Store connection strings in Azure Key Vault
Validation & Testing
Validate Config Before Starting
dab validate && dab start
Validation checks:
- JSON schema correctness
- Entity configuration validity
- Database connectivity
- Environment variable resolution
- Permissions and policies
Test MCP Endpoint
Health check:
curl http://localhost:5000/health
List tools:
# Use MCP Inspector or VS Code MCP extension
# Connect to http://localhost:5000/mcp
# Verify 6 tools appear: describe_entities, create_record, read_records, update_record, delete_record, execute_entity
Test with AI Agent
VS Code Copilot Chat Examples:
"Which products have low inventory?"
"Show me all products under $50"
"What categories do we have?"
"How many units of Product X are in stock?"
Monitoring & Observability
Built-in Features
OpenTelemetry Tracing:
- Every DML tool operation is traced
- Correlate across distributed systems
- Export to Application Insights, Jaeger, etc.
Health Checks:
/healthendpoint for liveness/readiness- Per-entity health validation
- Performance threshold monitoring
Logging:
- Structured logs to Azure Log Analytics
- Application Insights integration
- Local file logs in containers
Enable Application Insights
dab configure --runtime.telemetry.application-insights.connection-string "@env('APPLICATIONINSIGHTS_CONNECTION_STRING')"
Migration & Upgrade Paths
Upgrading Existing DAB to MCP
Steps:
- Upgrade CLI:
dotnet tool update microsoft.dataapibuilder --prerelease - Update config file version (if needed)
- Add entity/field descriptions for AI context
- Test MCP endpoint:
dab start - Connect from MCP client
No breaking changes - MCP is additive to existing REST/GraphQL endpoints.
From Other MCP Database Solutions
Key differences:
- SQL MCP Server uses entity abstraction (safer than direct schema exposure)
- No NL2SQL - deterministic query generation only
- Built-in RBAC, caching, monitoring
- Single config for REST/GraphQL/MCP
Migration approach:
- Map existing schema to DAB entities
- Add semantic descriptions
- Configure equivalent permissions
- Test agent workflows
- Switch MCP client connection
Troubleshooting Guide
Problem: "MCP endpoint returns 404"
Checks:
- Is DAB version 1.7+? Run
dab --version - Is MCP enabled? Check
runtime.mcp.enabled: true - Correct path? Default is
/mcp, checkruntime.mcp.path - Did you restart after config changes?
Problem: "Agent can't see any entities"
Checks:
- Are entities added? Run
dab validate - Does role have permissions? Check entity
permissionsconfig - Are entities excluded from MCP? Check
mcp.dml-tools: false - Did agent call
describe_entitiesfirst?
Problem: "Connection string not resolving"
Checks:
- Is environment variable set? Check
echo $DATABASECONNECTIONSTRING - Using correct syntax?
@env('VAR_NAME') - Is
.envfile in working directory? (local dev) - For Azure: Are secrets configured in Container Apps settings?
Problem: "Validation fails with database error"
Checks:
- Can you connect to database with connection string?
- Are tables/views/stored procedures spelled correctly?
- Do they exist in the specified schema? (e.g.,
dbo.Products) - For views: Did you specify
--source.key-fields?
Problem: "Agent queries are slow"
Solutions:
- Enable caching:
dab update <entity> --cache.enabled true --cache.ttl 300 - Add database indexes on frequently queried columns
- Review Application Insights for slow queries
- Consider scaling up Container Apps CPU/memory
Problem: "Authentication fails from Foundry"
Checks:
- Does auth mode match? (Foundry setting vs DAB
runtime.host.authentication) - For Entra ID: Are
audienceandissuercorrect? - Is token being passed correctly?
- Check Container Apps logs for auth errors
Quick Reference: CLI Commands
Initialization
dab init --database-type mssql --connection-string "@env('CONNECTION_STRING')" --host-mode Development
Add Entities
# Table
dab add Products --source dbo.Products --permissions "anonymous:read" --description "Product catalog"
# View
dab add ProductSummary --source dbo.vw_ProductSummary --source.type view --source.key-fields "ProductId" --permissions "anonymous:read"
# Stored Procedure
dab add GetProducts --source dbo.usp_GetProducts --source.type stored-procedure --permissions "anonymous:execute" --graphql.operation query
Add Descriptions
# Entity
dab update Products --description "Product catalog with pricing and inventory"
# Fields
dab update Products --fields.name UnitPrice --fields.description "Retail price in USD"
dab update Products --fields.name ProductID --fields.description "Unique identifier" --fields.primary-key true
# Stored Procedure Parameters
dab add GetOrdersByDate \
--source dbo.usp_GetOrdersByDate \
--source.type stored-procedure \
--permissions "authenticated:execute" \
--parameters.name "StartDate,EndDate" \
--parameters.description "Start date (inclusive),End date (inclusive)" \
--parameters.required "true,true"
Configure MCP
# Enable/disable globally
dab configure --runtime.mcp.enabled true
dab configure --runtime.mcp.path "/mcp"
# Disable specific tools
dab configure --runtime.mcp.dml-tools.delete-record false
# Add server description
dab configure --runtime.mcp.description "Production inventory MCP endpoint"
Configure Authentication
# Entra ID
dab configure --runtime.host.authentication.provider EntraId
dab configure --runtime.host.authentication.jwt.audience "api://<app-id>"
dab configure --runtime.host.authentication.jwt.issuer "https://login.microsoftonline.com/<tenant-id>/v2.0"
# Update permissions for authenticated users
dab update Products --permissions "authenticated:*"
Validation & Start
dab validate
dab start
dab start --verbose
dab start --LogLevel Debug
Key Differences from Regular DAB
| Aspect | Regular DAB | SQL MCP Server |
|---|---|---|
| Primary Use | REST/GraphQL APIs | AI agent database access |
| Client Type | Web apps, mobile apps | AI agents, copilots |
| Protocol | HTTP REST, GraphQL | MCP over HTTP or stdio |
| Version | 1.0+ | 1.7+ (preview) |
| Endpoint | /api, /graphql |
/mcp |
| Query Method | OData filters, GraphQL queries | DML tool calls |
| Descriptions | Optional | Critical for AI understanding |
| Default State | REST + GraphQL enabled | REST + GraphQL + MCP enabled |
When to Recommend SQL MCP Server
Good fit:
- User wants AI agents to access database safely
- User needs controlled CRUD operations for agents
- User requires RBAC for agent database access
- User wants caching and monitoring built-in
- User needs MCP-compatible database endpoint
Not a good fit:
- User needs raw SQL execution from agents (use NL2SQL tools instead)
- User needs schema modification (DDL) from agents
- User only needs REST or GraphQL APIs (use regular DAB)
Migration candidates:
- Existing DAB users adding AI agent capabilities
- Custom MCP database servers wanting enterprise features
- NL2SQL implementations wanting deterministic queries
References & Resources
Official Documentation
Quickstarts
- VS Code Quickstart
- Azure Container Apps Deployment
- .NET Aspire Integration
- Azure AI Foundry Integration
DAB Core Documentation
Related Skills
- See
data-api-builder.mdfor comprehensive DAB CLI guidance - See
dab-cli.skill.mdfor detailed command reference
Consistency Rules
- Always install prerelease version for v1.7+ features
- Require
.gitignorewith.env,\bin, and\objentries before adding secrets - Descriptions are critical for AI agent success - always recommend adding them
- MCP is enabled by default - only configure when restricting
- Security first - recommend managed identity + Entra ID for production
- Use entity abstraction - never recommend exposing raw schema to agents
- Validate before start - always
dab validate && dab start - Environment variables for secrets - use
@env('VAR_NAME')pattern - No NL2SQL - explain the NL2DAB deterministic approach
- RBAC applies to all tools - every operation respects role permissions
- Stdio for local, HTTP for remote - use appropriate transport
Version Notes
Current State (v1.7.x-rc):
- SQL MCP Server is in preview
- Must use
--prereleaseflag to install - Documentation and implementation may change
- Not yet in
:latestDocker tag
When GA releases:
- Will be included in stable releases
:latestDocker tag will include MCP- May have config schema changes
Always check: dab --version to confirm 1.7+