mcp-sqlserv
mcp-sqlserv
SQL Server 데이터베이스에 대한 읽기 전용 액세스용 MCP 서버 — 설계 자체로 SQL 인젝션을 원천 차단하며, Web Admin UI로 관리됩니다.
원시 SQL 제로 · 기본 거부(Default Deny) · 바인드 파라미터 100% · 전체 감사
소개
mcp-sqlserv를 사용하면 AI 에이전트(Claude, Cursor, Claude Code, 모든 MCP 클라이언트)가 SQL Server 데이터베이스를 안전하고 통제된 방식으로 읽을 수 있습니다:
모든 쿼리는 서버가 구조적으로 생성하며, AI가 원시 SQL을 작성하지 않습니다.
식별자(테이블/컬럼)는 실제 데이터베이스 메타데이터(
sys.tables,sys.columns)와 대조하여 검증됩니다.값은 항상 바인드 파라미터로 전달됩니다 → 설계 자체로 SQL 인젝션 불가능.
테이블별 권한은 기본 거부(Default Deny): 명시적 권한이 없으면 테이블에 접근할 수 없습니다.
모든 요청은 감사 로그에 기록되며, 키, 도구, 필터, 행 수, 소요 시간까지 남습니다.
Related MCP server: SQL Server MCP
기능
기능 | 설명 |
MCP Streamable HTTP |
|
다중 프로젝트 | 프로젝트별 URL |
API 키 | AI 소비자별 키 생성 / 폐기 |
OAuth 2.1 | Authorization Code + PKCE, DCR (RFC 7591), 토큰 순환, 폐기 |
SQL Server 연결 | 호스트/포트/사용자/비밀번호(AES-256-GCM 암호화), 선택적 TLS |
세분화된 권한 | 테이블별: 데이터 읽기 및/또는 메타데이터 보기. 기본값 = DENY |
감사 로그 | 모든 AI 요청 기록: 키, 도구, 테이블, 필터, 행, 실행 시간, 상태 |
요청률 제한 | API 키당 분당 60회(구성 가능) |
전체 읽기 전용 | 도구는 |
에이전트 테스트 | Web UI에서 Gemini 모델과 직접 대화하여 end-to-end 테스트 |
아키텍처
┌──────────────┐ 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 │ │
└──────────────┴──────────┴────┘빠른 시작
# 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서버는 http://localhost:4000에서 실행됩니다 — Web UI admin은 /, MCP 엔드포인트는 /mcp입니다.
환경 변수
변수 | 기본값 | 설명 |
|
| 서버 포트 |
|
| SQLite 폴더(compose에서 볼륨에 마운트) |
|
| Web UI 관리자 아이디 |
| 필수 | Web UI 관리자 비밀번호(최소 8자) |
| 자동 | JWT/암호화 시크릿(비어 있으면 자동 생성 및 유지) |
|
| SQL 쿼리 타임아웃 |
|
| API 키별 요청률 제한 |
|
|
|
|
| 인가 코드 유효 기간(초) |
|
| 액세스 토큰 유효 기간(초) |
|
| 리프레시 토큰 유효 기간(초, 30일) |
사용 절차
Web UI에 로그인 → DB 연결 메뉴 → 호스트/포트/사용자/비밀번호/데이터베이스 입력 → 연결 테스트.
Docker 컨테이너의 경우 호스트의 SQL Server를
host.docker.internal로 접속할 수 있습니다.API Keys 메뉴 → 키 생성(한 번만 표시되므로 반드시 저장).
테이블 권한 메뉴 → AI가 읽을 수 있는 테이블을 체크 → 권한 저장. 기본값은 거부입니다.
AI 에이전트를
https://<도메인>/mcp에 연결하고 헤더Authorization: Bearer <api-key>를 추가합니다.
일반 MCP 클라이언트 연결
{
"mcpServers": {
"sql-server": {
"url": "https://<domain>/mcp",
"headers": { "Authorization": "Bearer sk-xxxx" }
}
}
}다음으로 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)
Customize → Connectors → Add custom connector를 엽니다.
For Remote MCP server URL:
https://<도메인>/mcp.Advanced settings → OAuth Clients 메뉴에서 OAuth Client ID + Secret을 입력합니다(리디렉션 URI:
https://claude.ai/api/mcp/auth_callback).공백으로 둘 수 있습니다. Claude가 Dynamic Client Registration(RFC 7591)을 통해 자동 등록합니다.
Add → Connect 클릭 → 브라우저에서 운영자 로그인 페이지가 열리고 → 액세스 승인.
Claude가 리프레시 토큰을 저장하고 베어러 토큰으로 MCP 도구를 호출합니다.
Claude Code(CLI):
claude mcp add mcp-sqlserv https://<domain>/mcp --transport http \
... # bila client pre-registered: --client-id <id> --client-secret --callback-portOAuth 엔드포인트
엔드포인트 | 표준 |
| RFC 9728 |
| RFC 8414 |
| RFC 7591(DCR, public + confidential) |
| RFC 6749 + PKCE S256 |
| RFC 6749 / 7636 |
| RFC 7009 |
OAuth identity = 운영자 세션입니다. 액세스 토큰은 내부 API 키 oauth:<client_id>에 대응되며, 테이블 권한, 요청 제한, 감사 로그가 있는 듯. Claude의 연결에도 동일하게 적용됩니다. 클라이언트를 폐기하면 해당 클라이언트의 모든 토큰이 즉시 무효화됩니다.
MCP 도구
도구 | 기능 |
| 허용된 테이블 목록 + 예상 행 수 |
| 플롬, 타입, nullable, identity, 기본 키, 인덱스 |
| 구조화된 필터, 정렬, 페이지네이션으로 행 읽기 |
| 선택 필터로 행 수 계산 |
| 기본 키로 한 행 조회 |
| 서버/데이터베이스 정보 |
테이블 이름은 스키마 접두사를 반드시 생략해야 합니다(users이지 dbo.users가 아님). 컬럼은 sys.columns로 검증되고, 값은 100% bind parameter입니다.
지원 필터: eq, neq, lt, lte, gt, gte, like, startsWith, endsWith, in, between, isNull, isNotNull.
보안
원시 SQL 제로 — AI 구조화된 쿼리 빌더만 사용
식별자 허용 목록 — 정규식 + 실제 DB 메타데이터 검증
기본 거부(Default Deny) — 권한 없는 테이블은 접근 불가능
하드 제한 — 쿼리당 1000행, 필터 20개, IN 50개, 타임아웃 30초
API 키 + 요청 제한 — 키별 제한과 모든 요청 감사 로그 기록
읽기 전용 — SQL 서버 계정에
GRANT SELECT만 부여 권장DB 비밀번호는 AES-256-GCM 암호화를 통해 SQLite에 저장됩니다
배포
app-network 네트워크에서 app-network와 함께 Docker Compose로 배포합니다. 그리고 CORS를 사용합니다.
VPS 간 마이그레이션
코드와 Docker는 어떤 VPS에서도 그대로 실행되지만, 다음 두 가지는 Git에 포함되지 않습니다(.gitignore에 등록) 귀와 꼭 반드시 수동으로 마이그레이션:
이전할 대상 | 내용 | 방법 |
| 관리자부터 secret까지 인증 정보 | 이전 VPS에서 para 파일을 복사하거나 |
| SQLite(API 키, 권한, 감사 로그, DB 연결 정보) | 이전 VPS에서 |
# 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
data/를 마이그레이션하지 않아도 서버는 그대로 실행됩니다. Web UI에서 DB 연결, API 키, 테이블 권한만 다시 설정하면 됩니다.
프로젝트 구조
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관리자 REST API
Method | Path | 설명 |
POST |
| 관리자 로그인(httpOnly 쿠키) |
GET |
| DB, 키, 권한 등의 상태 |
GET/PUT |
| DB 설정 읽기 / 저장 |
POST |
| 연결 테스트 |
GET/POST |
| API 키 목록 / 생성 |
PUT/DELETE |
| 이름 변경 / 폐기 |
GET/PUT |
| 테이블 권한 목록 / 저장 |
GET |
| 감사 로그 |
GET |
| MCP URL 정보 + 설정 예시 |
GET |
| Health check(인증 불필요) |
테스트
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, revoketest/oauth.mjs는 포트 4100에서 별도의 서버를 실행합니다(데이터 디렉터리 oauth-test-data/) — 추가 설정이 필요 없습니다.
기여
기여를 언제나 환영합니다! 이슈나 pull request를 열어 주세요. 큰 변경의 경우 먼저 이슈에서 논의하여 제품의 원칙 security is the product에 부합하는지 확인해 주세요. MCP, UI, Agent Test 등 모든 표면이 동일한 기준으로 읽기 전용, 기본 거부, 파라미터화를 유지해야 합니다.
라이선스
이 프로젝트는 MIT License를 따릅니다.
Related MCP Connectors
Guard AI agents' PostgreSQL/MySQL access via MCP: SQL audit, auth, masking, write approval
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
Query your org's data in natural language — read-only MCP access to SQL, NoSQL, files & warehouses.
Query your warehouse or a CSV with Claude/ChatGPT over MCP, governed by table-level ACL + audit.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI agents to securely connect to and query Microsoft SQL Server databases with read-only access, schema discovery, and relationship mapping. Features advanced security protections, health monitoring, and bulk operations for production environments.963 npmMIT
- AlicenseBqualityDmaintenanceAn MCP server that connects AI assistants to Microsoft SQL Server databases, enabling schema exploration and read-only queries safely.4912 npm4MIT
- AlicenseNot gradedqualityCmaintenanceProvides read-only Microsoft SQL Server database access to AI agents with row-level security, enabling SELECT queries, table metadata, and schema introspection through MCP.15 npmMIT
- AlicenseNot gradedqualityCmaintenanceA read-only MCP server for Microsoft SQL Server that enables AI agents to safely explore and query SQL Server databases.804 npmMIT