Skip to main content
Glama
dkautomation23

mcp-data-server

mcp-data-server

프로덕션 웹 스크래핑/자동화 패턴을 보여주는 샘플 프로젝트입니다.

Claude(또는 모든 MCP 클라이언트)에 비즈니스 데이터베이스에 대한 읽기 전용 액세스를 제공하는 MCP 서버 — LLM을 실제 회사 데이터에 연결할 때 허용 가능한 수준의 보호 장치를 갖추고 있습니다: 읽기 전용 연결, 테이블 허용 목록, PII 마스킹, 행 제한, 쿼리 시간 제한 및 전체 감사 로그.

Claude Desktop에서 *"어느 국가에서 주문이 가장 많으며, 지난 분기 환불 비용은 얼마였나요?"*라고 물어보면 실제 데이터베이스에서 답변을 얻을 수 있습니다. 모델이 쓰기, 삭제, 첨부 또는 허용되지 않은 테이블을 읽을 수 있는 방법은 없습니다.


존재 이유

대부분의 "AI를 데이터에 연결" 프로젝트에서 막히는 부분은 배선이 아니라 데이터베이스 소유자의 첫 번째 질문입니다: 모델이 읽거나 부수면 안 되는 것을 읽거나 망가뜨리는 것을 어떻게 막을 수 있습니까? 이 서버는 코드로 그 질문에 답합니다.

Related MCP server: Vela MCP Server

네 가지 독립적인 장벽

#

장벽

막는 대상

1

연결이 mode=ro로 열림

위의 모든 검사를 우회하더라도 모든 쓰기 작업

2

문장 구문 분석

여러 문장, SELECT / WITH가 아닌 모든 것

3

키워드 블록리스트

ATTACH, PRAGMA, DDL, VACUUM, GRANT …

4

허용 목록 + 마스킹 + 제한

허용되지 않은 테이블, PII 열, 과도한 결과, 통제 불능 쿼리

실행된 모든 문장은 행 수와 기간과 함께 감사 로그에 추가되므로 데이터 소유자는 모델이 요청한 내용을 정확히 확인할 수 있습니다.

2026-08-18T11:22:41  6 rows in 1ms       SELECT country, COUNT(*) FROM customers GROUP BY 1 LIMIT 201
2026-08-18T11:22:44  error: rejected     DELETE FROM customers

노출된 도구

도구

목적

list_tables()

읽을 수 있는 테이블 + 행 수

describe_table(table)

열, 유형, 마스킹된 항목, 샘플 행 3개

run_sql(sql)

하나의 읽기 전용 SELECT, 제한 및 감사 처리됨

search(table, column, term, limit)

SQL을 작성하지 않고 부분 문자열 검색

summarize_column(table, column)

null, 고유 개수, 최소/최대, 상위 5개 값

추가로 schema://tables 리소스가 있어 클라이언트가 도구 호출 없이 전체 스키마를 로드할 수 있습니다.

빠른 시작

git clone https://github.com/dkautomation23/mcp-data-server.git
cd mcp-data-server
python -m venv .venv && . .venv/bin/activate      # Windows: .venv\Scripts\activate
pip install -r requirements.txt

python -m mcp_data_server.seed                    # creates demo.db
cp .env.example .env                              # then point DATABASE_PATH at your file
python -m mcp_data_server                         # serves over stdio

Python 3.10+. 데모 데이터베이스에는 customers, orders, order_items 및 아래에서 허용 목록이 액세스를 차단하는 모습을 보여주기 위해 사용된 의도적으로 민감한 internal_notes 테이블이 있습니다.

Claude Desktop에 연결

claude_desktop_config.json에 추가합니다 (전체 예제는 examples/claude_desktop_config.json에 있음):

{
  "mcpServers": {
    "business-data": {
      "command": "python",
      "args": ["-m", "mcp_data_server"],
      "cwd": "C:/path/to/mcp-data-server",
      "env": {
        "DATABASE_PATH": "C:/path/to/your.db",
        "ALLOWED_TABLES": "customers,orders,order_items",
        "MASKED_COLUMNS": "customers.email,customers.phone"
      }
    }
  }
}

Claude Code에 연결

claude mcp add business-data -- python -m mcp_data_server

세션 예시

실행 중인 서버의 실제 출력 (전체 대화 기록은 examples/demo_session.md 참조):

// run_sql("SELECT status, COUNT(*) n, ROUND(SUM(total_eur)) revenue FROM orders GROUP BY 1 ORDER BY 3 DESC")
{
  "sql": "SELECT status, COUNT(*) n, ROUND(SUM(total_eur)) revenue FROM orders GROUP BY 1 ORDER BY 3 DESC LIMIT 201",
  "columns": ["status", "n", "revenue"],
  "rows": [["paid", 92, 149914.0], ["pending", 39, 64596.0], ["refunded", 31, 45911.0]],
  "row_count": 3, "truncated": false, "elapsed_ms": 0
}

// run_sql("DELETE FROM customers")
{ "error": "only SELECT (or WITH ... SELECT) statements are allowed" }

// run_sql("SELECT * FROM internal_notes")
{ "error": "table 'internal_notes' is not in the allowlist (allowed: customers, orders, order_items)" }

// run_sql("SELECT id, name, email FROM customers LIMIT 2")
{ "rows": [[1, "Customer 001", "***"], [2, "Customer 002", "***"]] }

구성

변수

기본값

목적

DATABASE_PATH

demo.db

노출할 SQLite 파일 (항상 읽기 전용으로 열림)

ALLOWED_TABLES

모두

쉼표로 구분된 허용 목록; 이 외의 것은 모두 보이지 않음

MASKED_COLUMNS

–

table.column 목록, 모든 결과에서 ***로 대체됨

MAX_ROWS

200

호출당 하드 제한; 초과 시 truncated로 표시됨

QUERY_TIMEOUT_SECONDS

10

더 긴 쿼리는 취소됨

AUDIT_LOG_PATH

audit.log

모든 문장의 추가 전용 로그; 비어 있으면 비활성화

테스트

pytest -q
...............................                                          [100%]
31 passed in 1.77s

세 가지 레이어: SQL 보호 장치 (주입, 두 번째 문장, 주석 밀반입, 금지된 테이블), 실제 시드 파일에 대한 데이터베이스 레이어 (SQLite 자체가 거부하는 쓰기 시도 포함), 그리고 실제 MCP 프로토콜을 통해 서버를 구동하는 7개의 테스트 — 데스크탑 클라이언트가 수행하는 것과 동일한 핸드셰이크, list_tools 및 call_tool 흐름.

클라이언트 스택에 맞게 조정

  • Postgres / MySQL: db.py의 연결을 풀 드라이버와 SET TRANSACTION READ ONLY 세션으로 교체; 유효성 검사 레이어는 변경되지 않습니다.

  • 비즈니스별 도구: server.py에 @mcp.tool()과 함께 함수 추가 — 잘 명명된 top_customers(period)가 모델이 SQL을 작성하도록 하는 것보다 낫습니다.

  • HTTP 전송 (stdio 대신): mcp.run(transport="streamable-http"), 그런 다음 자체 인증 뒤에 배치하십시오.

라이선스

MIT — LICENSE 참조.

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    Enables read-only exploration and querying of PostgreSQL or MySQL databases via MCP, with schema discovery, safe SQL validation, natural language to SQL conversion, and CSV export.
    11
    1
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables governed, agent-agnostic data exploration by allowing users to ask natural language questions through MCP-compatible agents, executing safe, permission-scoped queries against data sources and returning interactive charts.
    3 npm
    Apache 2.0
  • A
    license
    Not graded
    quality
    A
    maintenance
    Provides a secure, policy-driven read-only gateway that exposes multiple databases to AI tools via MCP, with governed select, search, and aggregate operations and no free-form SQL.
    Apache 2.0
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables natural-language querying of Postgres and MongoDB databases in read-only mode, with PII masking and row/timeout guardrails, from any MCP client.
    -