@esasiyun17/mssql-mcp
v1.0.1
Published
Security-first, read-only MCP (Model Context Protocol) server for Microsoft SQL Server. Verifies the database user is read-only at startup and applies query-level defense in depth.
Maintainers
Readme
MSSQL-MCP
Microsoft SQL Server için güvenlik öncelikli, salt-okunur MCP (Model Context Protocol) sunucusu.
Security-first, read-only MCP (Model Context Protocol) server for Microsoft SQL Server.
🇹🇷 Türkçe
Bu proje nedir?
MSSQL-MCP, LLM'leri (Claude gibi) kurumsal Microsoft SQL Server veritabanlarına güvenle bağlamak için tasarlanmış bir MCP sunucusudur. LLM doğal dil sorusunu SQL'e çevirir, MSSQL-MCP bu SQL'i katmanlı güvenlik filtrelerinden geçirip yalnızca okuma amaçlıysa çalıştırır.
Neden? — LLM'i veritabanına doğrudan bağlamanın riskleri
Bir LLM'e veritabanı erişimi vermek güçlüdür ama tehlikelidir:
- LLM yanlışlıkla (veya prompt injection ile kasıtlı olarak)
DELETE,UPDATE,DROPgibi yıkıcı sorgular üretebilir. - "Salt-okunur olduğunu varsaydığınız" kullanıcı, fark etmediğiniz bir
GRANTyüzünden yazma yetkisine sahip olabilir. - Sınırsız bir
SELECTbile milyonlarca satır çekip sunucuyu kilitleyebilir. xp_cmdshell,OPENROWSETgibi kapılar veritabanının çok ötesine geçer.
Güvenlik felsefesi: salt-okunur doğrulama + savunma derinliği
MSSQL-MCP tek bir güvenlik katmanına güvenmez:
Katman 1 — Başlangıçta aktif salt-okunurluk doğrulaması. Sunucu açılırken bağlanan kullanıcının salt-okunur olduğunu aktif olarak kanıtlamasını ister. Üç bağımsız kontrolün TÜMÜ geçmelidir:
| Kontrol | Nasıl | Neden |
|---|---|---|
| Sunucu rolleri | IS_SRVROLEMEMBER: sysadmin, serveradmin, dbcreator, securityadmin | Sunucu yöneticisi hesaplar her şeyi yapabilir |
| Veritabanı rolleri | IS_ROLEMEMBER: db_owner, db_datawriter, db_ddladmin, db_securityadmin | Yazma/DDL yetkisi veren standart roller |
| Efektif izinler | sys.fn_my_permissions(NULL, 'DATABASE') içinde INSERT, UPDATE, DELETE, ALTER, CREATE TABLE, EXECUTE, CONTROL aranır | Rol üyeliği olmadan doğrudan GRANT ile verilmiş yazma izinlerini yalnızca bu kontrol yakalar |
Doğrulama başarısızsa sunucu hiçbir sorgu aracı açmaz; hangi yetkilerin sorun olduğunu listeleyen, yol gösterici bir hata döner (yalnızca verify_connection aracı kalır).
Katman 2 — Sorgu seviyesinde savunma derinliği. Kullanıcı salt-okunur olsa BİLE her sorgu şu filtrelerden geçer:
- Tek statement: Noktalı virgülle ayrılmış çoklu statement reddedilir. String literal içindeki
;yanlış pozitif üretmez — düz regex değil, string/yorum/köşeli parantez bilinçli bir tokenizer kullanılır. - Yalnızca SELECT: Statement
SELECTveyaWITH ... SELECT(CTE) ile başlamalıdır. - Kara liste (kelime sınırı duyarlı, büyük/küçük harf duyarsız):
INSERT,UPDATE,DELETE,MERGE,DROP,CREATE,ALTER,TRUNCATE,GRANT,REVOKE,DENY,EXEC,EXECUTE,sp_*,xp_*,OPENROWSET,OPENQUERY,OPENDATASOURCE,BULK,BACKUP,RESTORE,SHUTDOWN,KILL,RECONFIGURE,WAITFOR,INTO(SELECT ... INTOtablo yaratır — reddedilir). - Tablo beyaz listesi (opsiyonel):
ALLOWED_TABLEStanımlıysaFROM/JOINsonrası geçen her tablo listede olmalıdır (şema önekli adlar desteklenir; CTE adları muaftır). - Zaman aşımı ve satır limiti: Her sorguya
QUERY_TIMEOUT_MSuygulanır; sonuçlar sürücü seviyesinde stream edilipMAX_ROWS'ta kesilir vetruncated: truebildirilir (sorgunuzaTOPenjekte edilmez). - Reddedilen her sorguda hangi kuralın tetiklendiği açıkça söylenir.
Ek güvenlik varsayılanları: bağlantı havuzu tek ve paylaşımlıdır, kimlik bilgileri asla loglanmaz ve hata mesajlarından temizlenir, TLS varsayılan olarak açıktır.
Kurulum
# npx ile (önerilen) — kurulum gerektirmez, her çalıştırmada güncel sürümü kullanır
npx -y @esasiyun17/mssql-mcp
# veya kalıcı kurulum
npm install -g @esasiyun17/mssql-mcpKaynak koddan kurulum (air-gap / kapalı ağ ortamları)
İnternet erişimi olmayan ortamlarda npx çalışmaz. Repoyu klonlayıp (veya
arşiv olarak taşıyıp) yerinde derleyin:
git clone https://github.com/esasiyun17/MSSQL-MCP.git
cd MSSQL-MCP
npm install
npm run buildArdından MCP yapılandırmasında npx yerine doğrudan node + tam yol kullanın:
{
"mcpServers": {
"mssql": {
"command": "node",
"args": ["/tam/yol/MSSQL-MCP/dist/index.js"],
"env": { "MSSQL_HOST": "...", "MSSQL_USER": "...", "MSSQL_PASSWORD": "...", "MSSQL_DATABASE": "..." }
}
}
}İpucu:
npm installadımı için bağımlılıkları internet erişimli bir makinede indiripnode_modulesile birlikte taşıyabilir veyanpm packçıktısını kullanabilirsiniz.
Salt-okunur kullanıcı oluşturma
Sunucu, yazma yetkisi olan kullanıcılarla çalışmayı reddeder. Hazır script ile salt-okunur kullanıcı oluşturun:
-- scripts/create-readonly-user.sql dosyasını açın,
-- YOUR_LOGIN_NAME / YOUR_STRONG_PASSWORD / YOUR_DATABASE değerlerini değiştirip
-- sysadmin bir hesapla çalıştırın. Özet:
CREATE LOGIN [mcp_reader] WITH PASSWORD = 'YOUR_STRONG_PASSWORD';
USE [YOUR_DATABASE];
CREATE USER [mcp_reader] FOR LOGIN [mcp_reader];
ALTER ROLE [db_datareader] ADD MEMBER [mcp_reader];Claude Desktop / Claude Code yapılandırması
claude_desktop_config.json (Claude Desktop) veya .mcp.json (Claude Code):
{
"mcpServers": {
"mssql": {
"command": "npx",
"args": ["-y", "@esasiyun17/mssql-mcp"],
"env": {
"MSSQL_HOST": "192.168.1.10",
"MSSQL_PORT": "1433",
"MSSQL_USER": "mcp_reader",
"MSSQL_PASSWORD": "YOUR_PASSWORD",
"MSSQL_DATABASE": "ErpDb",
"MSSQL_ENCRYPT": "true",
"MSSQL_TRUST_CERT": "false",
"MAX_ROWS": "1000",
"ALLOWED_TABLES": "dbo.Customers,dbo.Orders,dbo.OrderLines"
}
}
}
}Claude Code CLI ile:
claude mcp add mssql -e MSSQL_HOST=192.168.1.10 -e MSSQL_USER=mcp_reader \
-e MSSQL_PASSWORD=YOUR_PASSWORD -e MSSQL_DATABASE=ErpDb -- npx -y @esasiyun17/mssql-mcpOrtam değişkenleri
| Değişken | Zorunlu | Varsayılan | Açıklama |
|---|---|---|---|
| MSSQL_HOST | ✅ | — | Sunucu IP veya hostname |
| MSSQL_PORT | | 1433 | TCP port |
| MSSQL_USER | ✅ | — | SQL auth kullanıcı adı (salt-okunur olmalı) |
| MSSQL_PASSWORD | ✅ | — | Parola (asla loglanmaz) |
| MSSQL_DATABASE | ✅ | — | Veritabanı adı |
| MSSQL_ENCRYPT | | true | TLS şifreleme |
| MSSQL_TRUST_CERT | | false | Self-signed sertifika kabulü |
| QUERY_TIMEOUT_MS | | 30000 | Sorgu zaman aşımı (ms) |
| MAX_ROWS | | 1000 | Satır limiti; aşımda sonuç kesilir ve bildirilir |
| ALLOWED_TABLES | | (boş = tümü) | Virgülle ayrılmış tablo beyaz listesi, örn. dbo.Customers,dbo.Orders |
| LOG_FILE | | (kapalı) | JSON-satırı denetim logu dosya yolu |
Araçlar
| Araç | Açıklama |
|---|---|
| verify_connection | Bağlantı durumu + salt-okunurluk doğrulama raporu (hangi kontroller geçti/kaldı) |
| list_tables | şema.tablo listesi + yaklaşık satır sayıları (sys.partitions üzerinden, COUNT(*) çalıştırılmaz) |
| describe_table(table) | Kolonlar, tipler, null'luk, PK/FK, index listesi |
| sample_rows(table, count) | İlk N satır (varsayılan 5, en fazla 50) |
| run_query(sql) | Tüm filtrelerden geçen tek bir SELECT'i çalıştırır |
Örnek kullanım (Claude'a doğal dille):
"Veritabanındaki tabloları listele" →
list_tables"Orders tablosunun yapısını göster" →describe_table("dbo.Orders")"Geçen ayın en çok satan 5 ürünü?" →run_query("SELECT TOP 5 ...")
run_query çıktısı: columns, rows, rowCount, truncated, durationMs.
Denetim logu
LOG_FILE tanımlıysa her araç çağrısı bir JSON satırı olarak yazılır: zaman damgası, araç adı, sorgu metni, süre (ms), satır sayısı, hata. Kimlik bilgileri asla loglanmaz.
Yol haritası
- Windows Authentication (v1 yalnızca SQL auth destekler — kapsam bilinçli dar tutuldu)
Katkı
PR ve issue'lara açığız! Özellikle: yeni guard senaryoları için test, farklı SQL Server sürümleriyle uyumluluk raporları, dokümantasyon iyileştirmeleri. Tek kırmızı çizgi: yazma yeteneği ekleyen hiçbir katkı kabul edilmez — salt-okunurluk bu projenin kimliğidir. Güvenlik açıkları için SECURITY.md.
🇬🇧 English
What is this?
MSSQL-MCP is an MCP server designed to connect LLMs (like Claude) to enterprise Microsoft SQL Server databases safely. The LLM translates natural-language questions into SQL; MSSQL-MCP runs that SQL only after it passes layered security filters that guarantee it is read-only.
Why? — The risks of wiring an LLM straight into your database
Giving an LLM database access is powerful but dangerous:
- The LLM can produce destructive queries (
DELETE,UPDATE,DROP) by accident — or deliberately, via prompt injection. - The user you assumed was read-only may have write access through a forgotten
GRANT. - Even an unbounded
SELECTcan pull millions of rows and choke the server. - Escape hatches like
xp_cmdshellandOPENROWSETreach far beyond the database.
Security philosophy: read-only verification + defense in depth
MSSQL-MCP never trusts a single layer:
Layer 1 — Active read-only verification at startup. When the server starts, the connecting user must actively prove it is read-only. ALL three independent checks must pass:
| Check | How | Why |
|---|---|---|
| Server roles | IS_SRVROLEMEMBER: sysadmin, serveradmin, dbcreator, securityadmin | Server-admin accounts can do anything |
| Database roles | IS_ROLEMEMBER: db_owner, db_datawriter, db_ddladmin, db_securityadmin | The standard roles that grant write/DDL |
| Effective permissions | sys.fn_my_permissions(NULL, 'DATABASE') scanned for INSERT, UPDATE, DELETE, ALTER, CREATE TABLE, EXECUTE, CONTROL | Only this catches write permissions GRANTed directly, outside any role |
If verification fails the server exposes no query tools at all; it returns an actionable error listing exactly which privileges are the problem (only verify_connection remains available).
Layer 2 — Query-level defense in depth. EVEN IF the user is read-only, every query passes these filters:
- Single statement only: multiple semicolon-separated statements are rejected. A
;inside a string literal is not a false positive — a tokenizer aware of strings, comments and bracketed identifiers is used, not a plain regex. - SELECT only: the statement must start with
SELECTorWITH ... SELECT(CTE). - Keyword blacklist (word-boundary aware, case-insensitive):
INSERT,UPDATE,DELETE,MERGE,DROP,CREATE,ALTER,TRUNCATE,GRANT,REVOKE,DENY,EXEC,EXECUTE,sp_*,xp_*,OPENROWSET,OPENQUERY,OPENDATASOURCE,BULK,BACKUP,RESTORE,SHUTDOWN,KILL,RECONFIGURE,WAITFOR,INTO(SELECT ... INTOcreates a table — rejected). - Optional table allowlist: when
ALLOWED_TABLESis set, every table appearing afterFROM/JOINmust be on the list (schema-qualified names supported; CTE names are exempt). - Timeout & row cap:
QUERY_TIMEOUT_MSapplies to every query; results are streamed at the driver level and cut off atMAX_ROWSwithtruncated: truereported (noTOPis injected into your SQL). - Every rejected query states exactly which rule fired.
Additional safe defaults: one shared connection pool, credentials are never logged and are scrubbed from error messages, TLS is on by default.
Installation
# via npx (recommended) — no install step, always runs the latest version
npx -y @esasiyun17/mssql-mcp
# or install globally
npm install -g @esasiyun17/mssql-mcpInstalling from source (air-gapped / offline environments)
npx won't work without internet access. Clone the repo (or carry it over as
an archive) and build in place:
git clone https://github.com/esasiyun17/MSSQL-MCP.git
cd MSSQL-MCP
npm install
npm run buildThen point your MCP configuration at node + the absolute path instead of npx:
{
"mcpServers": {
"mssql": {
"command": "node",
"args": ["/absolute/path/MSSQL-MCP/dist/index.js"],
"env": { "MSSQL_HOST": "...", "MSSQL_USER": "...", "MSSQL_PASSWORD": "...", "MSSQL_DATABASE": "..." }
}
}
}Tip: for the
npm installstep you can download dependencies on a machine with internet access and carry thenode_modulesfolder over, or use the output ofnpm pack.
Creating a read-only user
The server refuses to run with users that hold write privileges. Use the bundled script to create a read-only user:
-- Open scripts/create-readonly-user.sql, replace
-- YOUR_LOGIN_NAME / YOUR_STRONG_PASSWORD / YOUR_DATABASE and run as sysadmin. Summary:
CREATE LOGIN [mcp_reader] WITH PASSWORD = 'YOUR_STRONG_PASSWORD';
USE [YOUR_DATABASE];
CREATE USER [mcp_reader] FOR LOGIN [mcp_reader];
ALTER ROLE [db_datareader] ADD MEMBER [mcp_reader];Claude Desktop / Claude Code configuration
claude_desktop_config.json (Claude Desktop) or .mcp.json (Claude Code):
{
"mcpServers": {
"mssql": {
"command": "npx",
"args": ["-y", "@esasiyun17/mssql-mcp"],
"env": {
"MSSQL_HOST": "192.168.1.10",
"MSSQL_PORT": "1433",
"MSSQL_USER": "mcp_reader",
"MSSQL_PASSWORD": "YOUR_PASSWORD",
"MSSQL_DATABASE": "ErpDb",
"MSSQL_ENCRYPT": "true",
"MSSQL_TRUST_CERT": "false",
"MAX_ROWS": "1000",
"ALLOWED_TABLES": "dbo.Customers,dbo.Orders,dbo.OrderLines"
}
}
}
}With the Claude Code CLI:
claude mcp add mssql -e MSSQL_HOST=192.168.1.10 -e MSSQL_USER=mcp_reader \
-e MSSQL_PASSWORD=YOUR_PASSWORD -e MSSQL_DATABASE=ErpDb -- npx -y @esasiyun17/mssql-mcpEnvironment variables
| Variable | Required | Default | Description |
|---|---|---|---|
| MSSQL_HOST | ✅ | — | Server IP or hostname |
| MSSQL_PORT | | 1433 | TCP port |
| MSSQL_USER | ✅ | — | SQL auth user name (must be read-only) |
| MSSQL_PASSWORD | ✅ | — | Password (never logged) |
| MSSQL_DATABASE | ✅ | — | Database name |
| MSSQL_ENCRYPT | | true | TLS encryption |
| MSSQL_TRUST_CERT | | false | Accept self-signed certificates |
| QUERY_TIMEOUT_MS | | 30000 | Per-query timeout (ms) |
| MAX_ROWS | | 1000 | Row cap; results are truncated and flagged |
| ALLOWED_TABLES | | (empty = all) | Comma-separated table allowlist, e.g. dbo.Customers,dbo.Orders |
| LOG_FILE | | (off) | Path for the JSON-lines audit log |
Tools
| Tool | Description |
|---|---|
| verify_connection | Connection status + read-only verification report (which checks passed/failed) |
| list_tables | schema.table list + approximate row counts (via sys.partitions, no COUNT(*)) |
| describe_table(table) | Columns, types, nullability, PK/FK, index list |
| sample_rows(table, count) | First N rows (default 5, max 50) |
| run_query(sql) | Runs a single SELECT after all defense filters |
Example usage (natural language, via Claude):
"List the tables in the database" →
list_tables"Show me the structure of Orders" →describe_table("dbo.Orders")"Top 5 products by revenue last month?" →run_query("SELECT TOP 5 ...")
run_query output: columns, rows, rowCount, truncated, durationMs.
Audit log
When LOG_FILE is set, every tool call is appended as one JSON line: timestamp, tool name, query text, duration (ms), row count, error. Credentials are never logged.
Roadmap
- Windows Authentication (v1 supports SQL auth only — scope kept deliberately narrow)
Contributing
PRs and issues welcome! Especially: tests for new guard scenarios, compatibility reports for different SQL Server versions, documentation improvements. One hard line: no contribution that adds write capability will be accepted — read-only is this project's identity. For vulnerabilities see SECURITY.md.
License / Lisans
MIT © esasiyun17
