Skip to main content
Glama
Khushboo-Mishra

SQL-MCP-101

SQL-MCP-101

MCP가 처음이신가요? 대화형 튜토리얼부터 시작하세요. 도구, 리소스, 프롬프트를 클릭하며 살펴보고, 어떤 기능이 어느 것에 해당하는지 결정하는 방법을 배울 수 있습니다.

약 1,100줄의 Python으로 구현된 세 가지 Model Context Protocol 프리미티브(도구, 리소스, 프롬프트)를 모두 보여주는, 주석이 매우 상세한 소규모 MySQL용 MCP 서버이며, 탐색할 수 있는 브라우저 UI도 포함합니다.

이 저장소는 단지 실행되는 것이 아니라 읽히기 위해 존재합니다. MCP에 대해 들어보았고 서버를 구축하는 것이 실제로 무엇을 수반하는지 이해하고 싶다면, 이 저장소는 한 번에 읽을 수 있을 만큼 작은 완전하고 동작하는 예제입니다. 파일마다 하나의 프리미티브, 무엇이 아니라 이유를 설명하는 주석, 그리고 예제가 장난감이 아닌 실제 문제를 찾도록 일부러 결함을 넣어 둔 데모 데이터베이스가 있습니다.

mcp_server/
├── database.py    read-only introspection; the only file not about MCP
├── execution.py   running queries and writes, plus every safety control
├── tools.py       6 TOOLS      inspect structure, cannot read or change a row
├── data_tools.py  6 TOOLS      read rows, and insert / update / delete / alter
├── resources.py   4 RESOURCES  content the APPLICATION attaches (+2 templates)
├── prompts.py     6 PROMPTS    workflows the USER invokes
└── server.py      wires them together, about 10 meaningful lines

이 서버는 읽기-쓰기가 가능합니다. 실제 쿼리를 실행해 데이터에 대한 질문에 답하고, 데이터와 스키마를 변경할 수도 있습니다. 서버는 단일 임시 데모 데이터베이스에 고정되어 있으며, 안전하게 만드는 제어 장치는 execution.py에 있고 아래에서 설명합니다. 그 설계 자체가 교훈의 일부입니다.


기억해 둘 한 가지 아이디어

대부분의 MCP 튜토리얼은 도구만 다루기 때문에 사람들이 MCP가 도구라고 생각하게 됩니다. 하지만 MCP는 세 가지 프리미티브이며, 이들은 누가 통제하는지에 따라 다릅니다.

프리미티브

결정 주체

발생 시점

비유

도구

모델

대화 중, 자율적으로

모델이 호출할 수 있는 함수

리소스

애플리케이션

사전에, 인간이 선택

첨부하는 파일

프롬프트

사용자

명시적으로, 메뉴에서

저장된 전문가 질문

같은 데이터가 둘 이상의 형태로 나타날 수 있습니다. 이 저장소에서 get_table_ddl은 도구이고 동시에 schema://table/{name}/ddl은 리소스입니다. 같은 바이트에 두 가지 다른 방식으로 접근하는 것입니다. "모델이 필요하다고 판단했을 때 가져오는 것"과 "인간이 시작 전에 첨부하는 것"은 정말로 다른 필요이기 때문입니다.


Related MCP server: mysql-mcp-server

빠른 시작

git clone https://github.com/Khushboo-Mishra/SQL-MCP-101.git
cd SQL-MCP-101
bash scripts/setup.sh

setup.sh는 사전 요구 사항을 확인하고, virtualenv를 만들고, 두 개의 의존성을 설치하고, 데모 데이터베이스를 생성한 다음, 서버를 끝까지 검증합니다. 첫 번째로 빠진 항목이 있으면 특정 메시지와 함께 중단됩니다.

그런 다음 세 가지 프리미티브를 한 번에 모두 확인하세요:

bash scripts/run_explorer.sh

요구 사항

  • Python 3.10+

  • 로컬에서 실행 중인 MySQL 8.x (brew services start mysql)

  • Node.js: 선택 사항, MCP Inspector에서만 필요

  • Ollama: 선택 사항, UI의 Chat 패널에서만 필요

기본값은 비밀번호 없이 127.0.0.1:3306root이며, 이는 Homebrew 기본값이므로 대부분의 사람은 아무것도 변경하지 않아도 됩니다. 그 외에는 MYSQL_USER, MYSQL_PASSWORD, MYSQL_HOST, MYSQL_PORT를 내보내세요(export).


무엇이 만들어지나

**6개 테이블로 구성된 데모 데이터베이스 위에 도구 12개, 리소스 4개 + URI 템플릿 2개, 프롬프트 6개가 만들어집니다.

도구: 모델이 호출하는 것

하위 시스템이 아니라 영향 범위(blast radius)별로 두 파일에 나뉘어 있습니다. 이는 따라 할 만한 의도적인 설계 선택입니다. 위험한 표면을 작게 유지하고 서버를 검토하거나 데이터베이스 GRANT 권한을 작성하는 누구에게나 명확하게 보이도록 합니다.

tools.py: 구조를 검사합니다. 행을 읽을 수 없고 아무것도 변경할 수 없습니다.

도구

용도

list_tables

행 추정치를 포함한 모든 테이블과 뷰

describe_table(table)

열, 유형, 키, 인덱스, 외래 키

get_table_ddl(table)

정확한 CREATE TABLE

list_relationships

선언된 모든 외래 키

find_sensitive_columns

이름이 PII 또는 비밀을 암시하는 열

search_columns(keyword)

열이 어떤 테이블에 있는지 잊었을 때 열 찾기

data_tools.py: 행을 읽고 데이터를 변경합니다. 이쪽이 결과를 수반하는 반쪽입니다.

도구

용도

run_query(sql, limit)

SELECT를 실행하고 결과 행을 반환합니다. 데이터 질문에 답하는 것이 바로 이것입니다.

execute_statement(sql)

INSERT / UPDATE / DELETE / CREATE / ALTER / DROP / TRUNCATE

insert_row(table, values)

구조화된 삽입, 값은 바인딩 매개변수로 전송됨

update_rows(table, changes, where)

구조화된 업데이트, where 필수

delete_rows(table, where)

구조화된 삭제, where 필수

show_audit_log(limit)

서버가 실행한 모든 문장

일반 execute_statement와 구조화된 래퍼를 모두 두는 이유는 무엇일까요? 구조화된 도구는 더 안전합니다. 인자가 타입이 지정되고 값이 바인딩되므로 모델이 SQL 텍스트를 작성하지 않으며 잘못된 형식을 만들어 낼 수 없습니다. 하지만 예상한 대로만 동작합니다. 일반 SQL 통로는 긴 꼬리(long tail)를 처리합니다. 예를 들어 윈도우 함수, 예측하지 못한 ALTER 등입니다. 대부분의 실제 서버는 바로 그 이유로 두 가지를 모두 제공하게 됩니다.

리소스: 애플리케이션이 첨부하는 것

URI

유형

내용

schema://tables

JSON

테이블 목록

schema://ddl

SQL

전체 스키마의 DDL

schema://relationships

JSON

모든 외래 키

schema://overview

Markdown

사람이 읽을 수 있는 요약

schema://table/{name}

JSON

하나의 테이블 (템플릿)

schema://table/{name}/ddl

SQL

하나의 테이블 DDL (템플릿)

정적 리소스는 고정된 URI를 가지며 resources/list에 나타나므로 클라이언트가 선택기(picker)에 표시할 수 있습니다. 템플릿 리소스는 {placeholders}를 가지며 대신 resources/templates/list에 나타납니다. 표시할 고정 목록이 없으므로 클라이언트가 빈칸을 채웁니다.

프롬프트: 사용자가 호출하는 것

프롬프트

인자

하는 일

audit_schema

없음

5단계 상태 점검: 키, 관계, PII, 명명 규칙

explain_table

table

하나의 테이블을 쉬운 언어로 설명

ask_data

question

쿼리를 작성하고, 실행한 뒤, 쉬운 언어로 답합니다.

modify_data

request

변경 사항에 대해 미리 보기 → 확인 → 적용 → 검증

document_schema

없음

참조 문서 생성

onboarding_tour

role

역할에 맞게 조정된 안내형 첫인상


결정하기: 도구, 리소스, 프롬프트?

사람들이 가장 막히는 질문입니다. 다음 순서로 생각해 보세요.

1. 동작을 수행하거나 모델이 선택하는 무언가를 가져오는가?도구. 모델이 스스로 결정하고 수행할 수 있어야 하는 모든 것.

2. 인간이 시작하기 전에 합리적으로 첨부할 문서인가?리소스. 참조 자료, 전체 스키마 컨텍스트, 안정적인 모든 것.

**3. 누군가 반복하는 작업이며, 질문하는 방식이 전문성인가?** → 프롬프트. 재발견을 기대하는 대신 좋은 질문을 함께 제공하세요.

남은 대부분의 의문을 해결해 주는 두 가지 휴리스틱:

누가 시작하는가? 모델 → 도구. 애플리케이션 → 리소스. 사용자 → 프롬프트.

이것이 메뉴에 있으면 좋겠는가? 그렇다면 프롬프트입니다. 메뉴는 사람을 위한 것이며, 오직 프롬프트만 사람에게 명령으로 노출됩니다.

이 저장소의 실제 예시

기능

선택

이유

하나의 테이블 구조 가져오기

도구

모델이 추론 중에 예측할 수 없이 필요로 함

전체 스키마 DDL

둘 다

모델에게는 도구; 인간이 사전에 첨부하기에는 리소스

스키마 감사

프롬프트

무엇을 물어볼지 아는 것이 가치인 반복 작업

열 검색

도구

호출 시점에 모델이 선택하는 인자를 받음

Markdown 개요

리소스

수동적인 참조, 결정 불필요

사람들이 자주 틀리는 부분

  • 모든 것을 도구로 만드는 것. 동작은 하지만, 모델이 인간이 한 번에 첨부할 수 있었던 컨텍스트를 가져오기 위해 호출을 낭비하고, 사용자는 발견 가능한 진입점을 얻지 못합니다.

  • 모델이 선택하는 인자가 필요한 것을 리소스로 만드는 것. 모델이 매개변수를 결정한다면 그것은 도구입니다.

  • 일을 수행하는 프롬프트. 프롬프트는 텍스트를 반환합니다. 프롬프트 안에서 데이터베이스를 질의하게 된다면, 원래 도구가 필요했던 것입니다.


데모 데이터베이스

mcp_demo는 6개의 테이블로 구성되며, 예제가 실제 문제를 찾도록 일부러 불완전하게 만들어졌습니다:

테이블

의도적인 결함

CUSTOMERS

EMAIL, PHONE, 민감 열 스캔이 트리거됨

PRODUCTS

SKUUNIQUE이지만 PK가 아님, 논의할 가치가 있는 자연 키

ORDERS

(깨끗함, 참조 예제)

ORDER_ITEMS

PRODUCT_ID는 외래 키처럼 보이지만 제약 조건이 없음

AUDIT_LOG

기본 키가 전혀 없음

legacy_notes

다른 모든 것이 UPPER_CASE인 반면 snake_case

audit_schema를 실행하면 위의 모든 문제가 드러나야 합니다. 이것이 데모입니다. 도구가 장난감이 아닌 실제 문제를 찾아냅니다.


실행하기

탐색기: 모든 프리미티브를 한 번에

bash scripts/run_explorer.sh

initialize 핸드셰이크를 출력한 다음 도구, 리소스(정적 템플릿), 프롬프트를 나열하고 실행합니다. 먼저 이 명령을 실행하면 설정이 제대로 작동하는지 확인할 수 있고 전체 프로토콜 표면을 한 화면에 보여줍니다.

웹 UI: 브라우저에서 세 가지 프리미티브 모두

bash scripts/run_ui.sh          # http://127.0.0.1:8000
PORT=9000 bash scripts/run_ui.sh

보여줄 가치가 있는 것마다 하나씩, 총 네 개의 패널:

패널

보여주는 것

Chat

쉬운 영어로 질문할 수 있습니다. 모델이 선택한 모든 도구가 답변 위에 인라인으로 나열됩니다.

Tools

전체 12개를 영향 범위별로 그룹화, 각각은 폼에서 호출 가능

Resources

정적 및 템플릿 리소스를 제자리에서 읽을 수 있음

Prompts

하나를 펼치면 텍스트를 보거나 채팅으로 바로 보낼 수 있음

하단의 실시간 Activity 스트립은 그 뒤에서 일어나는 실제 JSON-RPC(tools/call, resources/read, prompts/get)를 보여 주므로 프로토콜이 항상 눈에 보입니다.

이 페이지는 그 자체가 MCP 클라이언트입니다. 자체적으로 MySQL에 접근할 수 없습니다. 화면의 모든 것은 Claude Desktop이 사용하는 것과 동일한 프로토콜을 통해 도착했습니다.

Chat은 Ollama를 통한 로컬 LLM이 필요합니다. 무료이고 API 키가 필요 없으며 아무것도 머신 밖으로 나가지 않습니다:

brew install ollama && ollama serve
ollama pull qwen2.5:7b

대신 ANTHROPIC_API_KEY를 설정하면 자동으로 Claude API로 전환됩니다. Tools, Resources, Prompts 패널은 LLM 없이도 완전히 작동합니다.

MCP Inspector: Anthropic의 공식 클라이언트

bash scripts/run_inspector.sh

인쇄된 http://localhost:6274?... URL을 여세요. 토큰이 필요합니다. 여기에는 별도의 Tools, Resources, Prompts 탭이 있으며, 이 세 가지를 모두 보여주는 가장 설득력 있는 방법입니다. 이 중 어느 것도 우리 코드가 아니므로, Inspector가 서버를 구동한다면 서버는 진정으로 스펙을 준수하는 것입니다.

추천 투어: ToolsORDERSdescribe_table; Resourcesschema://overview; Promptsaudit_schema.

Claude Desktop / Claude Code

bash scripts/add_to_claude_desktop.sh    # Claude Desktop, run from Terminal.app
bash scripts/install_claude.sh           # Claude Code, safe to run anywhere

add_to_claude_desktop.sh는 설정을 백업하고, 이미 등록된 서버를 보존하며, JSON을 검증하고, 정확한 실행 명령을 스모크 테스트한 다음 앱을 다시 실행합니다. 완료되면 제안된 데모 스크립트를 출력합니다.

그런 다음 *"이 데이터베이스를 감사해줘"*라고 묻거나, 메뉴에서 audit_schema 프롬프트를 사용하세요. 프롬프트가 마침내 표시되는 곳입니다.

--desktop은 Claude Desktop 내부가 아닌 Terminal.app에서 실행해야 합니다. Claude Desktop은 설정을 메모리에 보관하고 해당 복사본에서 파일을 다시 작성하므로, 실행 중에 편집한 내용은 조용히 폐기됩니다. 스크립트는 앱을 종료하고, 편집하고, 다시 실행하므로, 스크립트를 실행한 세션이 종료됩니다.


코드 읽기

대략 1시간 정도 소요됩니다. 이 순서는 앞선 참조 없이 차근차근 구성됩니다:

1. mcp_server/server.py: 여기서 시작하세요. 의미 있는 10줄이며, 전체 아키텍처가 한 화면에 들어갑니다: 서버 생성, 세 가지 프리미티브 등록, 실행. 나머지는 모두 세부 사항입니다.

2. mcp_server/database.py: MCP가 전혀 없는 일반적인 MySQL 코드입니다. MCP 계층이 실제로 얼마나 얇은지 보여주기 때문에 일찍 읽을 가치가 있습니다: 이미 데이터 접근 계층이 있다면, 대부분 완료된 것입니다.

safe_identifier를 자세히 살펴보세요. MySQL은 테이블 이름을 파라미터로 바인딩할 수 없습니다(SHOW CREATE TABLE %s는 유효한 SQL이 아닙니다). 따라서 식별자는 문자열에 보간되어야 합니다. 이는 진정한 인젝션 위험이며, 이 작은 함수 하나가 안전을 보장합니다.

3. mcp_server/tools.py: @mcp.tool() 데코레이터와 프로젝트 전체에서 가장 많은 작업을 수행하는 아이디어: docstring이 프롬프트입니다. 모델이 도구 호출 여부를 결정할 때 읽는 유일한 것이므로, 소스를 읽는 사람이 아닌 모델을 위해 작성되었습니다.

4. mcp_server/resources.py: 정적 URI 대 템플릿 URI, 그리고 get_table_ddl이 도구 이면서 리소스로 존재하는 이유. 그 중복은 의도적이며, 누가 무엇을 제어하는지에 대한 가장 명확한 예시입니다.

5. mcp_server/prompts.py: 프롬프트는 데이터가 아닌 텍스트를 반환합니다. 텍스트는 일반적으로 모델에게 어떤 도구를 사용할지 알려주는 지시사항입니다. 짧은 파일이며, 대부분의 사람이 본 적 없는 파일입니다.

6. mcp_server/execution.py: 쓰기 접근을 어떻게 안전하게 만들 수 있는지 알고 싶을 때 읽으세요. 각각 무엇을 방지하는지 설명하는 주석이 있는 5가지 제어 장치가 있습니다.

7. examples/explore_server.py: 프로토콜의 반대편입니다. 모든 것을 나열하고 호출하는 최소 클라이언트로, 실제로 네트워크를 통해 무엇이 오가는지 확인할 수 있습니다.


더 나아가기

이 서버는 예제를 짧게 유지하기 위해 하나의 데이터베이스로 범위가 제한되어 있습니다. 더 확장하려면:

  • 다중 스키마: MYSQL_DEMO_SCHEMA를 읽는 대신 schema를 도구 인자로 받으세요. 에이전트가 프로덕션에 접근할 수 없도록 허용 목록을 추가하세요.

  • 쿼리 실행: run_query 도구. 가능하지만 보안 구조가 완전히 바뀝니다: 서버는 테이블을 읽을 수 있는 자격 증명이 필요하고, 결과가 모델의 컨텍스트에 들어갑니다. SELECT 전용을 강제하고, LIMIT을 주입하고, 읽기 전용 데이터베이스 사용자를 사용하세요.

  • 원격 전송: mcp.run(transport="streamable-http"). 동일한 도구, 동일한 코드, 다른 파이프. 노출 전에 인증을 추가하세요.

  • 캐싱: describe_table는 호출할 때마다 데이터베이스에 접근합니다. 모델이 루프에서 호출하기 시작하면 짧은 TTL 캐시가 가치가 있습니다.


보안 참고 사항

이 서버는 데이터를 변경할 수 있습니다. 이는 의도적입니다: "에이전트가 내 데이터베이스에 쓸 수 있는가?"는 모든 팀이 묻는 질문이며, 안전하게 수행하는 방법에 대한 작동 예제는 주제를 회피하는 것보다 더 유용합니다. 그러나 제어 장치가 중요하다는 것을 의미합니다.

5가지 제어 장치, 모두 execution.py에 있음

제어 장치

방지하는 것

스키마 잠금

모든 문은 데모 데이터베이스에 고정된 연결에서 실행됩니다; 다른 데이터베이스에 대한 참조는 거부됩니다

호출당 단일 문

두 번째 문이 합법적인 문에 편승할 수 없습니다

읽기/쓰기 분리

run_query는 쓰기를 거부하고 execute_statement는 읽기를 거부하므로, 어느 쪽도 상대방의 역할을 하도록 유도될 수 없습니다

행 상한

광범위한 SELECT가 모델의 컨텍스트를 넘치게 할 수 없습니다

감사 로그

모든 문이 기록되고 show_audit_log를 통해 읽을 수 있습니다

차단 목록은 또한 스키마 잠금을 우회하거나, 파일 시스템에 도달하거나, 서버 전체 상태를 변경하는 문, 권한 변경, 사용자 관리, 파일 가져오기/내보내기, 데이터베이스 수준 작업을 거부합니다.

한 가지 미묘한 점, 반복하기 쉬운 실수이기 때문입니다: 스키마 잠금은 패턴만으로는 작동할 수 없습니다. SQL에서 a.b는 일반적으로 schema.table이 아닌 alias.column(SELECT c.NAME FROM CUSTOMERS c)이므로, 모든 점으로 구분된 이름을 거부하면 일반적인 조인이 깨집니다. 이것이 바로 이 기능의 첫 번째 버전에 있던 버그입니다. 이제 각 한정자를 서버의 실제 데이터베이스 목록과 비교합니다: 실제 데이터베이스 이름은 거부되고, 테이블 별칭은 그대로 통과합니다.

제한된 사용자로 연결하세요

위의 제어 장치는 심층 방어이지, 방어 자체가 아닙니다. 데모를 넘어서는 모든 것에서, 노출하려는 스키마만 포함하는 권한을 가진 MySQL 사용자로 연결하세요. 자격 증명이 프로덕션에 도달할 수 없다면, 프롬프트 인젝션이나 모델 실수도 도달할 수 없습니다.

명확히 언급할 가치가 있는 두 가지 더:

  • 테이블 이름은 바인딩 파라미터가 될 수 없습니다. SHOW CREATE TABLE %s는 유효한 SQL이 아니므로 식별자는 보간되어야 하며, 이는 진정한 인젝션 지점입니다. database.safe_identifier가 이를 안전하게 만드는 것이며, 프로젝트에서 가장 중요한 단일 함수입니다.

  • 연결하는 MySQL 사용자가 실제 경계입니다. 노출하려는 스키마로 범위가 제한된 읽기 전용 GRANT를 부여하세요. 코드의 읽기 전용성은 심층 방어이지, 방어 자체가 아닙니다.


라이선스

MIT, LICENSE 참조.

A
license - permissive license
Not graded
quality - not tested
B
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

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables interaction with MySQL databases through MCP, supporting query execution, table operations (insert, update, delete), and schema inspection for natural language database management.
    121
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables MySQL database operations through MCP, including executing SQL queries, listing databases and tables, and describing table structures.
    454
    5
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables natural language interaction with MySQL databases through MCP, supporting SQL execution, schema exploration, and database management via tools, resources, and prompts.
    5
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables natural language interaction with MySQL databases through MCP tools for querying, executing DDL/DML, listing databases/tables, and describing table schemas, with parameterized queries and read-only mode.
    454
    MIT

View all related MCP servers

Related MCP Connectors

  • GibsonAI MCP server: manage your databases with natural language

  • Connect to PlanetScale databases, branches, schema, query insights, and execute SQL

  • MCP server for managing Prisma Postgres.

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/Khushboo-Mishra/SQL-MCP-101'

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