mcp-sqlserv
Enables AI agents to safely read SQL Server databases via MCP with structured queries, default-deny table permissions, OAuth authentication, and full audit logging.
README
<div align="center">
mcp-sqlserv
MCP Server untuk akses read-only database SQL Server — anti SQL-injection by construction, dikelola lewat Web Admin UI.
Zero raw SQL · Default deny · Bind parameter 100% · Audit penuh
</div>
Tentang
mcp-sqlserv memungkinkan AI agent (Claude, Cursor, Claude Code, client MCP apa pun) membaca database SQL Server secara aman dan terkontrol:
- Semua query dibangun terstruktur oleh server — AI tidak pernah menulis SQL mentah.
- Identifier (tabel/kolom) divalidasi terhadap metadata asli database (
sys.tables,sys.columns). - Nilai selalu bind parameter → SQL injection mustahil by construction.
- Izin per-tabel bersifat default deny: tanpa izin eksplisit, tabel tidak bisa disentuh.
- Setiap request tercatat di audit log, lengkap dengan key, tool, filter, jumlah baris, dan durasi.
Fitur
| Fitur | Keterangan |
|---|---|
| MCP Streamable HTTP | Endpoint /mcp, kompatibel dengan semua MCP client via HTTP |
| Multi-project | URL per project /mcp/<projectId>, storage & izin terpisah |
| API Key | Buat / revoke key per konsumen AI |
| OAuth 2.1 | Authorization Code + PKCE, DCR (RFC 7591), refresh rotation, revoke |
| Koneksi SQL Server | Host/port/user/pass (terenkripsi AES-256-GCM), TLS opsional |
| Izin granular | Per tabel: baca data dan/atau lihat metadata. Default = DENY |
| Audit log | Semua request AI tercatat: key, tool, tabel, filter, baris, durasi, status |
| Rate limit | 60 req/menit per API key (dapat dikonfigurasi) |
| Read-only total | Tool hanya menghasilkan SELECT; tidak ada jalur tulis sama sekali |
| Agent Test | Chat langsung dengan model Gemini dari Web UI untuk uji end-to-end |
Arsitektur
┌──────────────┐ HTTPS ┌─────────────┐ ┌──────────────────────────────┐
│ AI Agent ├───────────►│ nginx ├─────────►│ mcp-sqlserv (Docker) │
│ (MCP client)│ Bearer │ reverse │ app-net │ Express + MCP + OAuth │
└──────────────┘ token │ proxy+SSL │ work │ │ │ │
└─────────────┘ │ ▼ ▼ │
┌──────────────┐ HTTPS │ SQLite mssql pool │
│ Web Admin UI ├─────────────────────────────────────►│ (data/, keys, │ │
│ (browser) │ REST /api/* │ audit, izin) ▼ │
└──────────────┘ │ ┌──────────┐ │
│ │ SQL Srvr │ │
└──────────────┴──────────┴────┘
Quick Start
# 1. Clone & siapkan environment
git clone https://github.com/<username>/mcp-sqlserv.git
cd mcp-sqlserv
cp .env.example .env # isi ADMIN_USER / ADMIN_PASSWORD (min 8 karakter)
# 2. Build & jalankan
docker compose up -d --build
# 3. Verifikasi
curl http://localhost:4000/healthz
Server jalan di http://localhost:4000 — Web UI admin di /, MCP endpoint di /mcp.
Environment Variables
| Variable | Default | Keterangan |
|---|---|---|
PORT |
4000 |
Port server |
DATA_DIR |
./data |
Folder SQLite (di-mount ke volume di compose) |
ADMIN_USER |
admin |
User web UI admin |
ADMIN_PASSWORD |
wajib | Password web UI admin (min 8 karakter) |
SESSION_SECRET |
auto | Secret JWT/enkripsi (auto-generate & persist jika kosong) |
QUERY_TIMEOUT_MS |
30000 |
Timeout query SQL |
RATE_LIMIT_PER_MIN |
60 |
Rate limit per API key |
OAUTH_ENABLED |
1 |
Nonaktifkan OAuth dengan 0 |
OAUTH_CODE_TTL_S |
600 |
Umur authorization code (detik) |
OAUTH_ACCESS_TTL_S |
3600 |
Umur access token (detik) |
OAUTH_REFRESH_TTL_S |
2592000 |
Umur refresh token (detik, 30 hari) |
Alur Pakai
- Login Web UI → menu Koneksi DB → isi host/port/user/pass/database + Test Connection.
Untuk container Docker, SQL Server di host bisa dipakai via
host.docker.internal. - Menu API Keys → buat key (tampil sekali, simpan!).
- Menu Izin Tabel → centang tabel yang boleh dibaca AI → Simpan Izin. Default deny.
- Hubungkan AI agent ke
https://<domain>/mcp+ headerAuthorization: Bearer <api-key>.
Menghubungkan MCP Client Generik
{
"mcpServers": {
"sql-server": {
"url": "https://<domain>/mcp",
"headers": { "Authorization": "Bearer sk-xxxx" }
}
}
}
Test cepat dengan curl:
curl -X POST https://<domain>/mcp \
-H "Authorization: Bearer sk-xxxx" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'
Claude Custom Connector (claude.ai / Desktop)
- Buka Customize → Connectors → Add custom connector.
- Remote MCP server URL:
https://<domain>/mcp. - Advanced settings → isi OAuth Client ID + Secret dari menu OAuth Clients
(redirect URI:
https://claude.ai/api/mcp/auth_callback).Boleh dikosongkan — Claude otomatis mendaftar via Dynamic Client Registration (RFC 7591).
- Klik Add → Connect → browser membuka halaman login operator → Izinkan Akses.
- Claude menyimpan refresh token dan memanggil tool MCP dengan bearer token.
Claude Code (CLI):
claude mcp add mcp-sqlserv https://<domain>/mcp --transport http \
... # bila client pre-registered: --client-id <id> --client-secret --callback-port
Endpoint OAuth
| Endpoint | Standard |
|---|---|
GET /.well-known/oauth-protected-resource |
RFC 9728 |
GET /.well-known/oauth-authorization-server |
RFC 8414 |
POST /oauth/register |
RFC 7591 (DCR, public + confidential) |
GET /oauth/authorize (login operator + consent) |
RFC 6749 + PKCE S256 |
POST /oauth/token (code exchange + refresh rotation) |
RFC 6749 / 7636 |
POST /oauth/revoke |
RFC 7009 |
Identitas OAuth = sesi operator. Access token memetakan ke API key internal oauth:<client_id> — seluruh izin tabel, rate limit, dan audit berlaku juga untuk koneksi Claude. Revoke client langsung mematikan semua token client tersebut.
Tools MCP
| Tool | Fungsi |
|---|---|
list_tables |
Daftar tabel yang diizinkan + perkiraan jumlah baris |
get_table_schema |
Kolom, tipe, nullable, identity, primary key, indeks |
read_records |
Baca baris dengan filter terstruktur, order, pagination |
count_records |
Hitung baris dengan filter opsional |
get_record_by_pk |
Ambil 1 baris via primary key |
server_info |
Info server / database |
Nama tabel wajib tanpa prefix schema (users, bukan dbo.users). Kolom divalidasi terhadap sys.columns; nilai 100% bind parameter.
Filter terstruktur yang didukung: eq, neq, lt, lte, gt, gte, like, startsWith, endsWith, in, between, isNull, isNotNull.
Keamanan
- Zero raw SQL dari AI — hanya builder query terstruktur
- Identifier allowlist — regex + verifikasi metadata DB asli
- Default deny — tabel tanpa izin tidak bisa diakses
- Limit keras — maks 1000 baris/query, 20 filter, 50 nilai IN, timeout 30s
- API key + rate limit per key + audit log semua request
- Read-only — saran: user SQL Server cukup dengan
GRANT SELECT - Password DB tersimpan terenkripsi AES-256-GCM di SQLite
Deployment
Deploy dengan Docker Compose di jaringan app-network bersama nginx sebagai reverse proxy (SSL wildcard, SSE non-buffered, CORS untuk MCP client web).
Migrasi antar VPS
Kode dan Docker akan jalan otomatis di VPS mana pun, tetapi dua hal berikut tidak ikut ke Git (ada di .gitignore) dan harus dimigrasikan manual:
| Yang dipindahkan | Isinya | Cara |
|---|---|---|
.env |
Kredensial admin & secret | Salin file dari VPS lama, atau buat baru dari .env.example |
data/ |
SQLite (API keys, izin, audit, koneksi DB) | rsync / salin folder dari VPS lama |
# Di VPS baru
git clone https://github.com/<username>/mcp-sqlserv.git && cd mcp-sqlserv
# Migrasi state dari VPS lama (opsional)
rsync -av vps-lama:/path/mcp-sqlserv/.env .env
rsync -av vps-lama:/path/mcp-sqlserv/data ./data
# Network eksternal harus ada dulu (dipakai docker-compose.yaml)
docker network create app-network # abaikan jika sudah ada
docker compose up -d --build
Tanpa migrasi
data/, server tetap jalan — Anda hanya perlu setup ulang koneksi DB, API key, dan izin tabel dari Web UI.
Struktur Proyek
mcp-sqlserv/
├── src/
│ ├── index.ts # Bootstrap Express + routing
│ ├── config.ts # Env config
│ ├── db/storage.ts # SQLite: api_keys, db_config, permissions, audit_log
│ ├── sqlserver/ # Connection pool, metadata (sys.tables), query builder
│ ├── mcp/ # MCP server (per-session) + tools
│ ├── oauth/ # OAuth 2.1: router, PKCE, discovery
│ ├── api/ # REST admin (auth, config, keys, permissions, audit)
│ └── ui/ # SPA vanilla JS (public/)
├── public/ # Web UI admin (tanpa build step)
├── test/ # Test suite keamanan + OAuth + smoke
├── Dockerfile # Multi-stage build (node:20-alpine)
├── docker-compose.yaml # Attach ke app-network, host.docker.internal
└── LICENSE # MIT
API REST Admin
| Method | Path | Keterangan |
|---|---|---|
| POST | /api/auth/login |
Login admin (cookie httpOnly) |
| GET | /api/status |
Status DB, key, permission |
| GET/PUT | /api/config |
Baca / simpan konfigurasi DB |
| POST | /api/config/test |
Test koneksi |
| GET/POST | /api/keys |
List / buat API key |
| PUT/DELETE | /api/keys/:id |
Rename / revoke |
| GET/PUT | /api/permissions |
List / simpan izin tabel |
| GET | /api/audit |
Audit log |
| GET | /api/connect |
Info URL MCP + contoh config |
| GET | /healthz |
Health check (tanpa auth) |
Testing
npm run test:smoke # smoke test dasar
npm run test:security # 29 test: injection, permission, limit, pagination, auth
npm run test:oauth # 46 test: discovery, DCR, PKCE, consent, token, refresh, revoke
test/oauth.mjs me-spawn server sendiri di port 4100 (data dir oauth-test-data/) — tidak butuh konfigurasi tambahan.
Kontribusi
Kontribusi dipersilakan! Silakan buka issue atau pull request. Untuk perubahan besar, diskusikan dulu melalui issue agar sesuai dengan prinsip produk: security is the product — setiap permukaan (MCP, UI, Agent Test) harus mempertahankan standar yang sama: read-only, default-deny, parameterized.
Lisensi
Proyek ini dilisensikan di bawah MIT License.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.