Skip to main content
Glama
ilyassakhanov

MCP SQLite Server (Read-Only)

MCP SQLite Server (읽기 전용)

프로덕션 준비가 완료된 Model Context Protocol 서버로, AI 에이전트에게 SQLite 데이터베이스(shop.db)에 대한 안전한 읽기 전용 액세스를 제공합니다. 공식 mcp Python SDK와 stdio 전송을 사용하여 구축되었습니다.

기능

  • 3가지 MCP 도구: list_tables, describe_table, query_database

  • 다층 방어(Defense-in-depth) 읽기 전용 안전성: SQLite URI 읽기 전용 모드 + PRAGMA query_only + SQL 검증기 + EXPLAIN opcode 검사

  • 쿼리 검증: INSERT/UPDATE/DELETE/DROP/ALTER/CREATE/REPLACE/TRUNCATE/ATTACH/DETACH, 다중 문 쿼리(;), SQL 주석(--, /* */) 및 수정형 PRAGMA를 거부합니다 — 문자열 리터럴에 대한 오탐(false positive) 없이

  • 페이지네이션: 기본 행 제한(100), limit/offset 매개변수, 잘림 출력 플래그

  • stderr 전용 로깅: 모든 로그/트레이스백은 sys.stderr로 전송됩니다. stdout은 JSON-RPC 전용으로 예약됩니다.

  • 전체 타입 힌트: mypy --strict 클린

  • TDD: 보안, DB 계층, MCP 도구, 8가지 벤치마크 쿼리, stderr 가드를 포함한 105개 테스트

Related MCP server: sqlite-mcp-server

빠른 시작

사전 요구 사항

  • Python 3.10+

  • SQLite 데이터베이스 파일(기본값: ./shop.db)

로컬 설정

python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

구성

.env.example을 복사하고 데이터베이스 경로를 설정합니다:

cp .env.example .env
# Edit DATABASE_PATH to point to your SQLite file

또는 환경 변수를 직접 설정합니다:

export DATABASE_PATH=/abs/path/to/shop.db

서버 실행

python -m mcp_server.server

서버는 MCP stdio 전송을 사용하여 stdin/stdout을 통해 통신합니다. 직접 상호작용할 필요는 없습니다 — MCP 클라이언트(예: Claude Desktop, AI 에이전트)가 연결합니다.

MCP 클라이언트 구성

표준 Python

MCP 클라이언트 구성(예: Claude Desktop의 claude_desktop_config.json)에 다음을 추가합니다:

{
  "mcpServers": {
    "sqlite-shop": {
      "command": "python",
      "args": ["-m", "mcp_server.server"],
      "env": {
        "DATABASE_PATH": "/abs/path/to/shop.db"
      }
    }
  }
}

Docker

먼저 이미지를 빌드합니다:

docker build -t mcp-shop:latest .

그런 다음 MCP 클라이언트를 구성합니다:

{
  "mcpServers": {
    "sqlite-shop": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-v", "/abs/path/to/shop.db:/app/shop.db",
        "-e", "DATABASE_PATH=/app/shop.db",
        "mcp-shop:latest"
      ]
    }
  }
}

Docker Compose

docker compose up -d

도구

list_tables

데이터베이스의 모든 사용자 테이블과 뷰를 나열합니다(내부 sqlite_* 테이블 제외).

매개변수: 없음

반환값:

{
  "tables": ["customers", "orders", "order_items", "products"],
  "count": 4
}

describe_table

테이블의 스키마를 설명합니다: 열, 외래 키, 행 수 및 CREATE 문.

매개변수:

  • table (문자열, 필수): 설명할 테이블의 이름.

반환값:

{
  "table": "customers",
  "columns": [
    {"cid": 0, "name": "id", "type": "INTEGER", "notnull": 0, "default": null, "pk": 1},
    {"cid": 1, "name": "first_name", "type": "TEXT", "notnull": 1, "default": null, "pk": 0}
  ],
  "foreign_keys": [],
  "row_count": 150,
  "sql": "CREATE TABLE customers (...)"
}

query_database

페이지네이션을 지원하는 읽기 전용 SQL 쿼리를 실행합니다.

매개변수:

  • sql (문자열, 필수): 단일 읽기 전용 SQL 문(SELECT, WITH, EXPLAIN 또는 읽기 전용 PRAGMA).

  • limit (정수, 선택): 반환할 최대 행 수. 기본값: 100. 최대: 1000.

  • offset (정수, 선택): 건너뛸 행 수. 기본값: 0.

반환값:

{
  "columns": ["id", "first_name"],
  "rows": [{"id": 1, "first_name": "Alice"}, {"id": 2, "first_name": "Bob"}],
  "row_count": 2,
  "truncated": false,
  "limit": 100,
  "offset": 0
}

truncatedtrue이면 더 많은 행이 존재합니다 — offset을 늘려 다음 페이지를 가져옵니다.

보안

서버는 읽기 전용 액세스를 보장하기 위해 다층 방어를 구현합니다:

계층 1: SQLite 연결(URI 읽기 전용 모드)

데이터베이스는 file:<path>?mode=ro로 열리며, SQLite 엔진 수준에서 쓰기를 방지합니다. 또한 모든 연결에 PRAGMA query_only = ON이 설정됩니다.

계층 2: SQL 쿼리 검증기(security.py)

모든 쿼리가 SQLite에 도달하기 전에 다단계 검증기를 통과합니다:

  1. 문자열 리터럴 제거: 문자열 리터럴('...', "...")은 플레이스홀더로 대체되어 데이터 내부의 키워드(예: "Deleted Item"이라는 제품)가 오탐을 유발하지 않도록 합니다.

  2. 주석 감지: SQL 주석(--, /* */)은 주석 기반 우회를 방지하기 위해 거부됩니다.

  3. 다중 문 거부: 세미콜론(;)은 스택 쿼리를 방지하기 위해 거부됩니다.

  4. 키워드 분석: 첫 번째 실제 문 키워드는 SELECT, WITH, EXPLAIN 또는 PRAGMA여야 합니다. 파괴적 키워드(INSERT, UPDATE, DELETE, DROP, ALTER, CREATE, REPLACE, TRUNCATE, ATTACH, DETACH, VACUUM 등)는 차단됩니다.

  5. PRAGMA 검증: 읽기 전용 PRAGMA(table_info, database_list 등)는 허용됩니다. 할당(=)이 있거나 변경형 PRAGMA 블록리스트(journal_mode, synchronous, foreign_keys 등)에 포함된 PRAGMA는 거부됩니다.

계층 3: EXPLAIN Opcode 검사

최종 방어선으로, 쿼리는 EXPLAIN <query>를 통해 SQLite 자체 파서로 실행됩니다. 결과 opcode 스트림에서 쓰기 opcode(OpenWrite, Insert, Delete, Create, Drop 등)와 쓰기 트랜잭션 플래그를 검사합니다. 발견되면 쿼리가 거부됩니다.

계층 4: 정화된 오류 메시지

클라이언트에 반환되는 모든 오류는 정화됩니다 — 파일 시스템 경로와 내부 세부 정보는 정보 유출을 방지하기 위해 제거됩니다.

테스트

테스트는 임시/인메모리 데이터베이스만 사용합니다 — 프로덕션 shop.db는 절대 사용하지 않습니다.

# Run all tests
python -m pytest

# Run with verbose output
python -m pytest -v

# Run a specific test file
python -m pytest tests/test_security.py

테스트 커버리지

테스트 파일

커버리지

tests/test_security.py

76개 테스트: 유효한 쿼리, 파괴적 문 거부, PRAGMA 검증, 다중 문 거부, 주석 우회 방지, 문자열 리터럴 처리

tests/test_db.py

20개 테스트: 읽기 전용 강제, 테이블 나열, 스키마 설명, 페이지네이션, 잘림, 8가지 벤치마크 쿼리 전체

tests/test_server.py

9개 테스트: MCP 도구 검색, SDK 클라이언트를 통한 도구 호출, 파괴적 쿼리 거부, 페이지네이션, 도구를 통한 7가지 벤치마크 쿼리, stderr/stdout 오염 방지 가드

정적 분석

# Type checking
python -m mypy

# Linting
python -m ruff check src/ tests/

프로젝트 구조

.
├── .env.example          # Environment variable template
├── Dockerfile            # Docker containerization
├── docker-compose.yml    # Docker Compose config
├── pyproject.toml        # Package config, deps, tool settings
├── README.md             # This file
├── shop.db               # The SQLite database (not included in tests)
├── src/mcp_server/
│   ├── __init__.py
│   ├── config.py         # Configuration (DATABASE_PATH, limits, URI builder)
│   ├── db.py             # Read-only Database class with introspection + query
│   ├── security.py       # SQL validator (multi-layer defense-in-depth)
│   ├── server.py         # MCP server entrypoint (stdio transport)
│   ├── tools.py          # MCP tool definitions and handlers
│   └── py.typed          # PEP 561 marker
└── tests/
    ├── __init__.py
    ├── test_db.py        # Database layer + benchmark tests
    ├── test_security.py  # Query validator tests
    └── test_server.py    # MCP server/tool tests

벤치마크 작업

서버의 도구를 통해 AI 에이전트는 다음 분석 작업을 수행할 수 있습니다(통제된 픽스처 데이터베이스에 대한 테스트로 검증됨):

  1. 테이블 검색: list_tables + describe_table — 모든 테이블을 나열하고 스키마를 설명합니다.

  2. 필터링된 개수: SELECT COUNT(*) FROM customers WHERE country = 'Germany'를 사용한 query_database.

  3. 국가 집계: SELECT country, COUNT(*) ... GROUP BY country ORDER BY ... DESC LIMIT 1.

  4. 고객 LTV: customers + orders 조인, SUM(total_amount), 합계 기준 정렬.

  5. 제품 성과: order_items + products 조인, 수량과 매출로 집계, LIMIT 5.

  6. 카테고리 집계: order_itemsproductscategory 탐색, 매출 집계, LIMIT 3.

  7. 날짜 필터링: SUM(total_amount) WHERE substr(order_date,1,4) = '2025'.

  8. 주문 집계: customers + orders 조인, COUNT(o.id), 개수 기준 정렬.

구성

환경 변수

기본값

설명

DATABASE_PATH

./shop.db

SQLite 데이터베이스 파일 경로

ROW_LIMIT

100

쿼리 결과의 기본 행 제한(최대 1000)

라이선스

이 프로젝트는 데모 목적으로 있는 그대로 제공됩니다.

Install Server
F
license - not found
A
quality
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Exposes a SQLite database to AI assistants with structured, read-safe access. Includes five tools for schema exploration, querying, and sampling data.
  • A
    license
    Not graded
    quality
    C
    maintenance
    A read-only MCP server that enables LLMs to safely explore and query any SQLite database via natural language. It exposes tools for listing tables, describing schemas, and executing SELECT/WITH queries with built-in safety guards like write prevention and row limits.
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Exposes any SQLite database as read-only MCP tools for AI assistants, enabling listing tables, describing schemas, and running SELECT queries with filtering, ordering, and pagination.
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to query a SQLite database using natural language through the Model Context Protocol (MCP). Includes security guardrails that block destructive SQL operations.

View all related MCP servers

Related MCP Connectors

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ilyassakhanov/my-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server