{
  "markdown": "<!-- mcp-name: io.github.tkmawarire/sql-sentinel -->\n# SQL Sentinel MCP Server\n\n[![NuGet](https://img.shields.io/nuget/v/Neofenyx.SqlSentinel.Mcp)](https://www.nuget.org/packages/Neofenyx.SqlSentinel.Mcp)\n[![Docker](https://img.shields.io/badge/ghcr.io-sql--sentinel--mcp-blue)](https://ghcr.io/tkmawarire/sql-sentinel-mcp)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n\nA production-ready MCP (Model Context Protocol) server for SQL Server monitoring, diagnostics, and database operations. Built with .NET 9 and Microsoft.Data.SqlClient for **native SQL Server connectivity — no ODBC drivers required**.\n\n## Features\n\n- **Session Management** — Create, start, stop, drop, and list Extended Events sessions\n- **Smart Filtering** — Filter by application, database, user, duration, host, and text patterns\n- **Query Fingerprinting** — Normalize and group similar queries differing only in literal values\n- **Sequence Analysis** — Trace execution order with timing gaps and cumulative duration\n- **Deadlock Detection** — Capture and analyze XML deadlock reports with victim/process details\n- **Blocking Analysis** — Monitor blocked process events with wait resource and SQL text\n- **Wait Stats** — Query `sys.dm_os_wait_stats` directly, categorized by type (CPU, I/O, Lock, Memory, etc.)\n- **Health Check** — Comprehensive server diagnostic: slow queries, deadlocks, blocking, wait stats, and insights\n- **Real-Time Streaming** — Stream captured events for a specified duration\n- **Production-Safe** — Auto-excludes noise (`sp_reset_connection`, `SET` statements, trace queries)\n- **Database Operations** — List tables, describe schemas, query data, insert, update, and drop tables\n- **AI-Optimized** — Structured JSON output with optional Markdown formatting\n\n## Requirements\n\n- SQL Server 2012+ with Extended Events enabled (default)\n- Required permissions:\n  ```sql\n  GRANT ALTER ANY EVENT SESSION TO [your_login];\n  GRANT VIEW SERVER STATE TO [your_login];\n  ```\n- For blocked process detection:\n  ```sql\n  EXEC sp_configure 'show advanced options', 1;\n  RECONFIGURE;\n  EXEC sp_configure 'blocked process threshold', 5;\n  RECONFIGURE;\n  ```\n\n## Installation\n\n### Option 1: Docker (Recommended)\n\nNo .NET SDK required. Works on any system with Docker installed.\n\n```bash\ndocker pull ghcr.io/tkmawarire/sql-sentinel-mcp:latest\n```\n\n#### Claude Desktop (`claude_desktop_config.json`)\n\n```json\n{\n  \"mcpServers\": {\n    \"sql-sentinel\": {\n      \"command\": \"docker\",\n      \"args\": [\"run\", \"-i\", \"--rm\", \"--network\", \"host\",\n               \"-e\", \"SQL_SENTINEL_CONNECTION_STRING=Server=localhost;Database=master;User Id=sa;Password=YourPassword;TrustServerCertificate=true\",\n               \"ghcr.io/tkmawarire/sql-sentinel-mcp:latest\"]\n    }\n  }\n}\n```\n\n#### Claude Code\n\n```bash\nclaude mcp add sql-sentinel \\\n  -e SQL_SENTINEL_CONNECTION_STRING=\"Server=localhost;Database=master;User Id=sa;Password=YourPassword;TrustServerCertificate=true\" \\\n  -- docker run -i --rm --network host \\\n  -e SQL_SENTINEL_CONNECTION_STRING \\\n  ghcr.io/tkmawarire/sql-sentinel-mcp:latest\n```\n\n> **Network access**: The `-i` flag is required for stdio transport. Use `--network host` so the container can reach SQL Server on your host machine. For remote SQL Server, omit `--network host` and use the accessible hostname in your connection string.\n>\n> **Connection string**: Set `SQL_SENTINEL_CONNECTION_STRING` via `-e`. All tools read the connection string from this environment variable.\n\n### Option 2: .NET Global Tool (NuGet)\n\nRequires .NET 9 SDK or later.\n\n```bash\ndotnet tool install -g Neofenyx.SqlSentinel.Mcp\n```\n\n```json\n{\n  \"mcpServers\": {\n    \"sql-sentinel\": {\n      \"command\": \"sql-sentinel-mcp\",\n      \"env\": {\n        \"SQL_SENTINEL_CONNECTION_STRING\": \"Server=localhost;Database=master;User Id=sa;Password=YourPassword;TrustServerCertificate=true\"\n      }\n    }\n  }\n}\n```\n\n### Option 3: Build from Source\n\n```bash\ngit clone https://github.com/tkmawarire/sql-sentinel.git\ncd sql-sentinel\ndotnet build\n```\n\nRun directly:\n\n```bash\ndotnet run --project SqlServer.Profiler.Mcp/\n```\n\nOr publish a self-contained single binary:\n\n```bash\n# Windows\ndotnet publish SqlServer.Profiler.Mcp/ -c Release -r win-x64 --self-contained\n\n# Linux\ndotnet publish SqlServer.Profiler.Mcp/ -c Release -r linux-x64 --self-contained\n\n# macOS (Apple Silicon)\ndotnet publish SqlServer.Profiler.Mcp/ -c Release -r osx-arm64 --self-contained\n\n# macOS (Intel)\ndotnet publish SqlServer.Profiler.Mcp/ -c Release -r osx-x64 --self-contained\n```\n\nOutput will be in `bin/Release/net9.0/{runtime}/publish/`\n\n## Connection Strings\n\nAll tools read the connection string from the `SQL_SENTINEL_CONNECTION_STRING` environment variable. Set it once before starting the server:\n\n```bash\nexport SQL_SENTINEL_CONNECTION_STRING=\"Server=localhost;Database=master;User Id=sa;Password=YourPassword;TrustServerCertificate=false;Encrypt=true\"\n```\n\n**SQL Authentication:**\n```\nServer=localhost;Database=master;User Id=sa;Password=YourPassword;TrustServerCertificate=false;Encrypt=true\n```\n\n**Windows Authentication:**\n```\nServer=localhost;Database=master;Integrated Security=true;TrustServerCertificate=false;Encrypt=true\n```\n\n> **Note:** Only use `TrustServerCertificate=true` in development environments with self-signed certificates.\n> For production, always use `TrustServerCertificate=false` with a valid SSL certificate.\n\n**Azure SQL:**\n```\nServer=yourserver.database.windows.net;Database=yourdb;User Id=user;Password=password;Encrypt=true\n```\n\n## MCP Tools Reference\n\n### Session Lifecycle\n\n| Tool | Description |\n|------|-------------|\n| `sqlsentinel_create_session` | Create an Extended Events session with filters (not started) |\n| `sqlsentinel_start_session` | Start capturing events for an existing session |\n| `sqlsentinel_stop_session` | Stop capturing; events are retained |\n| `sqlsentinel_drop_session` | Drop session and discard all events |\n| `sqlsentinel_list_sessions` | List all MCP-created sessions with state and buffer usage |\n| `sqlsentinel_quick_capture` | Create and start a session in one step |\n\n### Event Retrieval\n\n| Tool | Description |\n|------|-------------|\n| `sqlsentinel_get_events` | Retrieve captured events with filtering, sorting, and deduplication |\n| `sqlsentinel_get_stats` | Aggregate statistics grouped by fingerprint, database, app, or login |\n| `sqlsentinel_analyze_sequence` | Analyze query execution sequence with timing and gaps |\n| `sqlsentinel_get_connection_info` | List databases, applications, logins, sessions, and blocking info |\n| `sqlsentinel_stream_events` | Real-time event capture for a specified duration (1–300s) |\n\n### Diagnostics\n\n| Tool | Description |\n|------|-------------|\n| `sqlsentinel_get_deadlocks` | Retrieve deadlock events with victim, processes, locks, and SQL text |\n| `sqlsentinel_get_blocking` | Retrieve blocked process events with wait resources and SQL text |\n| `sqlsentinel_get_wait_stats` | Query `sys.dm_os_wait_stats` categorized by type (no session required) |\n| `sqlsentinel_health_check` | Comprehensive report: slow queries, deadlocks, blocking, wait stats, insights |\n\n### Permissions\n\n| Tool | Description |\n|------|-------------|\n| `sqlsentinel_check_permissions` | Check current login permissions and blocked process threshold config |\n| `sqlsentinel_grant_permissions` | Grant required permissions to a login (requires sysadmin) |\n\n### Database Operations\n\n| Tool | Description |\n|------|-------------|\n| `sqlsentinel_list_tables` | List all user tables in the database (schema-qualified) |\n| `sqlsentinel_describe_table` | Detailed table schema: columns, indexes, constraints, foreign keys |\n| `sqlsentinel_create_table` | Create a new table via CREATE TABLE statement |\n| `sqlsentinel_insert_data` | Insert data via INSERT statement |\n| `sqlsentinel_read_data` | Execute SELECT queries and return results |\n| `sqlsentinel_update_data` | Update data via UPDATE statement |\n| `sqlsentinel_drop_table` | Drop a table via DROP TABLE statement |\n\n## Usage Examples\n\n### Quick Debug Session\n\n```\nAgent: sqlsentinel_quick_capture(\n    sessionName: \"debug_api\",\n    applications: \"MyWebApp\",\n    minDurationMs: 100\n)\n\n// User triggers the slow operation\n\nAgent: sqlsentinel_get_events(\n    sessionName: \"debug_api\",\n    sortBy: \"DurationDesc\",\n    limit: 20\n)\n\nAgent: sqlsentinel_drop_session(sessionName: \"debug_api\")\n```\n\n### Find N+1 Queries\n\n```\nAgent: sqlsentinel_quick_capture(\n    sessionName: \"n_plus_one_check\",\n    databases: \"OrdersDB\"\n)\n\n// User loads a page\n\nAgent: sqlsentinel_get_stats(\n    sessionName: \"n_plus_one_check\",\n    groupBy: \"QueryFingerprint\"\n)\n\n// Look for queries with high execution counts\n```\n\n### Trace Specific Operation\n\n```\nAgent: sqlsentinel_analyze_sequence(\n    sessionName: \"my_session\",\n    correlationId: \"order-12345\",\n    responseFormat: \"Markdown\"\n)\n```\n\n### Deadlock Detection\n\n```\nAgent: sqlsentinel_quick_capture(\n    sessionName: \"deadlock_monitor\",\n    eventTypes: \"Deadlock\"\n)\n\n// Wait for deadlocks to occur\n\nAgent: sqlsentinel_get_deadlocks(\n    sessionName: \"deadlock_monitor\",\n    responseFormat: \"Markdown\"\n)\n```\n\n### Blocking Analysis\n\n```\nAgent: sqlsentinel_quick_capture(\n    sessionName: \"blocking_check\",\n    eventTypes: \"BlockedProcess\"\n)\n\n// Requires: sp_configure 'blocked process threshold', 5\n\nAgent: sqlsentinel_get_blocking(\n    sessionName: \"blocking_check\",\n    responseFormat: \"Markdown\"\n)\n```\n\n### Server Health Check\n\n```\nAgent: sqlsentinel_health_check(\n    sessionName: \"my_session\",\n    slowQueryThresholdMs: 1000,\n    responseFormat: \"Markdown\"\n)\n```\n\n### Database Operations\n\n```\nAgent: sqlsentinel_list_tables()\n\nAgent: sqlsentinel_describe_table(\n    name: \"dbo.Products\"\n)\n\nAgent: sqlsentinel_read_data(\n    sql: \"SELECT TOP 10 * FROM dbo.Products ORDER BY CreatedDate DESC\"\n)\n```\n\n### Wait Stats (No Session Required)\n\n```\nAgent: sqlsentinel_get_wait_stats(\n    topN: 20,\n    responseFormat: \"Markdown\"\n)\n```\n\n## Query Fingerprinting\n\nQueries are normalized to group similar ones:\n\n```sql\n-- These become one fingerprint:\nSELECT * FROM Users WHERE id = 123\nSELECT * FROM Users WHERE id = 456\n\n-- Fingerprint: abc123:SELECT * FROM Users WHERE id = ?\n-- Execution count: 2\n```\n\n## Noise Filtering\n\nDefault excluded patterns (when `excludeNoise=true`):\n\n- `sp_reset_connection` — Connection pool reset\n- `SET TRANSACTION ISOLATION LEVEL` — Session setup\n- `SET NOCOUNT`, `SET ANSI_*` — Client configuration\n- `sp_trace_*`, `fn_trace_*` — Trace system queries\n\n## Supported Event Types\n\n`SqlBatchCompleted`, `RpcCompleted`, `SqlStatementCompleted`, `SpStatementCompleted`, `Attention`, `ErrorReported`, `Deadlock`, `BlockedProcess`, `LoginEvent`, `SchemaChange`, `Recompile`, `AutoStats`\n\n## Project Structure\n\n```\nsql-profiler-mcp/\n├── .github/\n│   └── workflows/\n│       ├── docker.yml                     # Build & push multi-arch Docker images\n│       └── publish-mcp-registry.yml       # Publish NuGet + MCP registry\n├── .mcp/\n│   └── server.json                        # MCP manifest (NuGet + OCI packages)\n├── SqlServer.Profiler.Mcp/                # Main MCP server (stdio transport)\n│   ├── SqlServer.Profiler.Mcp.csproj\n│   ├── Program.cs                         # Entry point, DI setup, MCP config\n│   ├── Models/\n│   │   ├── ProfilerModels.cs              # Records, enums, data models\n│   │   └── DbOperationResult.cs           # Result model for CRUD operations\n│   ├── Services/\n│   │   ├── ProfilerService.cs             # Core Extended Events logic\n│   │   ├── QueryFingerprintService.cs     # SQL normalization & fingerprinting\n│   │   ├── WaitStatsService.cs            # DMV-based wait stats analysis\n│   │   ├── SessionConfigStore.cs          # In-memory session config storage\n│   │   └── EventStreamingService.cs       # Real-time event streaming\n│   ├── Utilities/\n│   │   └── SqlInputValidator.cs           # SQL input validation & escaping\n│   └── Tools/\n│       ├── SessionManagementTools.cs      # Session lifecycle tools (6)\n│       ├── EventRetrievalTools.cs         # Event retrieval tools (5)\n│       ├── DiagnosticTools.cs             # Diagnostic tools (4)\n│       ├── PermissionTools.cs             # Permission tools (2)\n│       └── DatabaseTools.cs               # Database CRUD tools (7)\n├── SqlServer.Profiler.Mcp.Api/            # Debug REST API (Swagger on port 5100)\n│   ├── SqlServer.Profiler.Mcp.Api.csproj\n│   ├── Program.cs\n│   ├── Controllers/\n│   │   └── ProfilerController.cs\n│   ├── Models/\n│   │   └── RequestModels.cs\n│   └── appsettings.json\n├── SqlServer.Profiler.Mcp.Cli/            # Debug CLI (REPL + script mode)\n│   ├── SqlServer.Profiler.Mcp.Cli.csproj\n│   └── Program.cs\n├── SqlServer.Profiler.Mcp.Tests/          # xUnit tests for core MCP library (228 tests)\n│   └── ...\n├── SqlServer.Profiler.Mcp.Api.Tests/      # xUnit tests for API project (29 tests)\n│   └── ...\n├── Dockerfile                             # Multi-stage build (bookworm-slim)\n├── .dockerignore\n├── SqlServer.Profiler.Mcp.slnx           # Solution file\n├── CLAUDE.md\n├── CONTRIBUTING.md\n└── README.md\n```\n\n## Development\n\n### Prerequisites\n\n- [.NET 9 SDK](https://dotnet.microsoft.com/download/dotnet/9.0)\n- SQL Server 2012+ instance (local, Docker, or remote)\n- Docker (optional, for container builds)\n\n### Clone & Build\n\n```bash\ngit clone https://github.com/tkmawarire/sql-sentinel.git\ncd sql-sentinel\ndotnet restore\ndotnet build\n```\n\n### Running the MCP Server Locally\n\n```bash\ndotnet run --project SqlServer.Profiler.Mcp/\n```\n\nThe server communicates over stdio using the MCP protocol. Connect it to an MCP client (Claude Desktop, Claude Code, etc.) for interactive use.\n\n### Using the Debug API\n\nThe API project provides a REST wrapper around all MCP tools with Swagger UI for manual testing.\n\n```bash\ndotnet run --project SqlServer.Profiler.Mcp.Api/\n```\n\n- Swagger UI: `http://localhost:5100/`\n- Configure the connection string via environment variable `SQL_SENTINEL_CONNECTION_STRING`\n\n### Using the Debug CLI\n\nThe CLI project provides an interactive REPL and script mode for testing tools directly.\n\n```bash\n# Interactive REPL mode\ndotnet run --project SqlServer.Profiler.Mcp.Cli/\n\n# List all available tools\ndotnet run --project SqlServer.Profiler.Mcp.Cli/ list\n\n# Get help for a specific tool\ndotnet run --project SqlServer.Profiler.Mcp.Cli/ help sqlsentinel_quick_capture\n\n# Execute a single tool\ndotnet run --project SqlServer.Profiler.Mcp.Cli/ call sqlsentinel_list_sessions\n```\n\nSet the `SQL_SENTINEL_CONNECTION_STRING` environment variable before running.\n\n### Docker Build\n\n```bash\ndocker build -t sql-sentinel-mcp:test .\ndocker run -i --rm --network host sql-sentinel-mcp:test\n```\n\n## Architecture\n\n### Key Patterns\n\n- **Dependency injection** via `Microsoft.Extensions.Hosting`\n- **stdio transport** — stdout is reserved for MCP protocol; all logging goes to stderr\n- **Tool auto-discovery** — MCP tools are discovered from the assembly via `WithToolsFromAssembly()`\n- **XE session prefix** — All created sessions are prefixed with `mcp_sentinel_`\n- **Two event shapes** — Standard events (query, login, recompile) with typed fields, and XML-payload events (deadlock, blocking) parsed from Extended Events XML\n\n### Adding a New MCP Tool\n\n1. Create a `public static` method in the appropriate file under `Tools/` (or create a new file)\n2. Decorate with `[McpServerTool(Name = \"sqlsentinel_your_tool\")]` and `[Description(\"...\")]`\n3. Add parameters with `[Description(\"...\")]` attributes — they become the tool's input schema\n4. Inject services via method parameters (e.g., `IProfilerService`, `IWaitStatsService`)\n5. Return a string (JSON or Markdown) — the framework handles MCP response wrapping\n\n```csharp\n[McpServerTool(Name = \"sqlsentinel_example\")]\n[Description(\"Description shown to AI agents\")]\npublic static async Task<string> Example(\n    IProfilerService profilerService,\n    [Description(\"Optional filter\")] string? filter = null)\n{\n    var connectionString = ConnectionStringResolver.Resolve();\n    // Implementation\n    return JsonSerializer.Serialize(result);\n}\n```\n\n## Troubleshooting\n\n### \"Permission denied\" creating session\n```sql\nGRANT ALTER ANY EVENT SESSION TO [your_login];\nGRANT VIEW SERVER STATE TO [your_login];\n```\n\n### \"Login failed\"\n- Check connection string credentials\n- For Windows auth, ensure process runs under correct user\n- For Azure SQL, ensure firewall allows your IP\n\n### No events captured\n1. Verify session is RUNNING (`sqlsentinel_list_sessions`)\n2. Check filters aren't too restrictive\n3. Verify target database/app is generating queries\n4. Check `minDurationMs` isn't filtering everything\n\n### No deadlock events\n- Ensure session was created with `eventTypes: \"Deadlock\"`\n- Deadlocks must actually occur while the session is running\n\n### No blocking events\n- Ensure `blocked process threshold` is configured: `sp_configure 'blocked process threshold', 5`\n- Ensure session was created with `eventTypes: \"BlockedProcess\"`\n- Blocking must exceed the configured threshold (seconds)\n\n### Timeout reading events\nLarge ring buffers with many events can be slow to parse. Use:\n- Time filters to narrow the window\n- Increase command timeout in code if needed\n\n## Security Notes\n\n- The `SQL_SENTINEL_CONNECTION_STRING` environment variable contains credentials — secure appropriately\n- Don't leave sessions running indefinitely on production\n- Query text may contain sensitive data\n- Grant minimum required permissions\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on submitting issues and pull requests.\n\n## License\n\nMIT\n",
  "bytes": 17567,
  "sha": "77faece397234650246532f902b3f93679fafac64bf9db521e923f4965e4e47d",
  "repo_slug": "tkmawarire/sql-sentinel",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_tkmawarire_sql_sentinel_d2ba9365/readme"
}