Skip to main content
Glama
lampmaster

shop-sql-mcp

by lampmaster

shop-sql-mcp

AI 에이전트가 shop.db SQLite 데이터베이스에 대해 읽기 전용 분석 접근을 stdio를 통해 얻을 수 있게 해주는 작은 MCP 서버입니다.

이 서버는 다음 세 가지 일만 수행하며 그 외에는 아무것도 하지 않습니다: 테이블 나열, 스키마 설명, 그리고 호출당 읽기 전용 SQL 문 하나를 서버가 강제하는 페이지네이션으로 실행합니다. 어떤 조인을 할지, 어떻게 집계할지, 언제 스키마를 볼지에 대한 모든 추론은 에이전트의 몫입니다.

AI Agent
    |
    |  MCP over stdio
    v
shop-sql-mcp
    |
    +-- list_tables
    +-- describe_table
    +-- query_database
    |
    v
read-only SQLite connection
    |
    v
shop.db

요구 사항

  • Node.js 22.5 이상(24+ 권장). 이 서버는 내장 node:sqlite 모듈을 사용하므로 컴파일할 네이티브 SQLite 의존성이 없습니다.

  • 다른 런타임 전제 조건은 없습니다.

Related MCP server: mcpserve-py

설치

npm install

구성

구성은 선택사항입니다. 기본적으로 서버는 프로젝트 루트에 있는 shop.db를 엽니다.

변수

기본값

의미

DATABASE_PATH

<project>/shop.db

SQLite 파일의 경로입니다. 상대 경로는 프로젝트 루트를 기준으로 해석되므로, 서버가 실행되는 작업 디렉터리에 의존하지 않습니다.

로컬 재정의를 유지하려면 .env.example.env로 복사하세요. 서버 자체는 일반 환경 변수를 읽습니다. .env.exampleANTHROPIC_API_KEY, EVAL_MODEL, EVAL_MAX_STEPSnpm run eval에서만 사용됩니다.

빌드

npm run build

src/dist/로 컴파일합니다.

실행

npm start              # runs the built server (dist/index.js)
npm run dev            # runs src/index.ts directly, no build step

서버는 stdin/stdout에서 MCP를 사용하며 stderr에는 진단 메시지만 출력합니다. 따라서 터미널에서 실행하면 멈춘 것처럼 보이는데, 그것이 정상입니다. MCP 호스트가 서버를 시작하도록 설계되었습니다.

MCP 에이전트 연결

프로젝트의 절대 경로를 사용해 MCP 호스트 구성(Claude Desktop의 claude_desktop_config.json, Claude Code의 .mcp.json, 또는 호스트에 해당하는 파일)에 다음을 추가하세요:

{
  "mcpServers": {
    "shop-sql": {
      "command": "node",
      "args": ["/absolute/path/to/shop-sql-mcp/dist/index.js"]
    }
  }
}

빌드 없이 소스에서 실행하려면 TypeScript 진입점을 대신 지정하세요 — Node가 직접 실행합니다:

{
  "mcpServers": {
    "shop-sql": {
      "command": "node",
      "args": ["/absolute/path/to/shop-sql-mcp/src/index.ts"]
    }
  }
}

다른 위치의 데이터베이스를 읽으려면:

{
  "mcpServers": {
    "shop-sql": {
      "command": "node",
      "args": ["/absolute/path/to/shop-sql-mcp/dist/index.js"],
      "env": { "DATABASE_PATH": "/absolute/path/to/other.db" }
    }
  }
}

Claude Code에서는 명령줄로도 등록할 수 있습니다:

claude mcp add shop-sql -- node /absolute/path/to/shop-sql-mcp/dist/index.js

도구

list_tables

인자가 없습니다. 사용자 테이블을 반환하며, 내부 sqlite_* 테이블은 숨겨집니다.

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

describe_table

{ table: string }

스키마를 SQLite에서 직접 읽고 — 하드코딩된 것은 없으며 — 열, 타입, null 허용 여부, 기본 키, 외래 키를 보고합니다:

{
  "table": "order_items",
  "columns": [
    { "name": "id", "type": "INTEGER", "nullable": false, "primaryKey": true },
    { "name": "order_id", "type": "INTEGER", "nullable": false, "primaryKey": false }
  ],
  "foreignKeys": [
    { "column": "order_id", "referencesTable": "orders", "referencesColumn": "id" },
    { "column": "product_id", "referencesTable": "products", "referencesColumn": "id" }
  ]
}

알 수 없는 이름은 크래시가 아니라 복구 가능한 오류입니다:

{ "error": { "code": "TABLE_NOT_FOUND", "message": "TABLE_NOT_FOUND: Table \"foo\" does not exist." } }

참고: INTEGER PRIMARY KEY 열은 nullable: false로 보고됩니다. SQLite의 table_info는 그렇지 않다고 말하지만, 이런 열은 rowid 별칭이므로 NULL을 가질 수 없습니다.

query_database

{ sql: string; limit?: number; offset?: number }

JOIN, WHERE, GROUP BY, HAVING, ORDER BY, 서브쿼리, 집계, 날짜 필터링을 모두 지원하면서, 읽기 전용 문(SELECT ... 또는 WITH ... SELECT ...) 하나를 실행합니다.

{
  "columns": ["category", "revenue"],
  "rows": [["Electronics", 1234567.89]],
  "returnedRows": 1,
  "limit": 100,
  "offset": 0,
  "hasMore": false
}

행은 columns 순서의 값 배열입니다. 이렇게 하면 결과 페이로드가 압축적으로 유지되고, 쿼리가 같은 이름을 가진 두 열을 생성할 때 모호함이 없습니다.

실패는 isError가 설정된 일반 도구 결과와 짧고 실행 가능한 페이로드로 반환되므로 에이전트는 SQL을 고치고 다시 시도할 수 있습니다:

{ "error": { "code": "SQL_ERROR", "message": "no such column: total" } }

오류 코드: SQL_ERROR, READ_ONLY_VIOLATION, MULTIPLE_STATEMENTS, TABLE_NOT_FOUND, INVALID_ARGUMENT, DATABASE_UNAVAILABLE. 스택 트레이스는 절대 반환되지 않습니다.

페이지네이션

페이지네이션은 모델의 SQL이 아니라 서버 값이 강제합니다.

  • limit의 기본값은 100, 최대값은 500이며, offset의 기본값은 0입니다.

  • 에이전트의 쿼리는 SELECT * FROM (<your sql>) LIMIT ? OFFSET ?로 감싸지므로 자체 LIMIT 100000을 가진 쿼리도 limit보다 많은 행을 반환할 수 없습니다.

  • 서버는 두 번째 카운팅 쿼리 없이 hasMore를 결정하기 위해 내부적으로 limit + 1 행을 가져오고, 최대 limit 행을 반환합니다.

  • 따라서 단일 호출은 500행 이상을 반환하지 않으며, 이 때문에 넓은 SELECT *가 모델의 컨텍스트를 넘치게 하지 않습니다.

결과를 페이지로 나누려면 SQL을 동일하게(결정적 ORDER BY와 함께) 유지하면서 hasMoretrue인 동안 offsetlimit만큼 진행하세요.

읽기 전용 안전장치

각각 독립적인 두 계층이 있어, 어느 하나에만 의존하지 않습니다.

1. SQL 유효성 검사(src/sqlSafety.ts). 작은 렉서가 주석, 문자열 리터럴, 인용 식별자를 건너뛰고 다음을 요구합니다:

  • 구문이 SELECT 또는 WITH로 시작해야 합니다 — 단순한 startsWith("SELECT")는 유효한 읽기 전용 CTE를 거부합니다.

  • 문장이 정확히 하나 존재해야 합니다(첫 번째 ; 이후의 내용은 거부되며, 리터럴이나 주석 안의 ;는 구분자가 아닙니다).

  • CTE 내부에 중첩된 것을 포함하여 어디에도 금지 키워드가 나타나면 안 됩니다: INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, REPLACE, ATTACH, DETACH, VACUUM, REINDEX, PRAGMA, ANALYZE, BEGIN, COMMIT, ROLLBACK, SAVEPOINT, load_extension, writable_schema.

금지된 SQL은 항상 명시적 오류로 거부됩니다 — 절대 조용히 무시되거나, 절대 부분 실행되지 않습니다. REPLACE(a, b, c)는 스칼라 함수로 여전히 허용됩니다. 실제 쓰기인 REPLACE INTO 문만 금지되기 때문입니다.

2. SQLite connection itself. shop.dbnew DatabaseSync(path, { readOnly: true })로 열립니다. 쓰기가 유효성 검사를 통과해도 SQLite는 *"attempt to write a readonly database"*로 거부합니다. 테스트 스위트는 유효성 검사기를 우회한 상태로 연결에 쓰기를 실행하여 이 사실을 직접 확인합니다.

나쁘거나 금지된 작업은 도구 오류로 반환되며 프로세스를 종료하지 않으므로, 세션은 실패한 시도가 여러 번 반복되어도 살아 있습니다.

테스트 실행

npm test

결정적 스위트만 실행합니다 — 네트워크 없음, API 키는 없음, LLM 없음. Node 공식 테스트 러너가 TypeScript 소스를 직접 실행합니다. 테스트 범위에는 list_tables, describe_table(컬럼, 유형, null 허용, 기본 키, 외래 키, 알려지지 않은 테이블), 일반 SELECT, 필터링, 집계, 조인, GROUP BY, 읽기 전용 CTE, 데이터 필터링, 페이지네이션(기본 제한, 최대 제한, 오프셋, hasMore 경계), 잘못된 SQL, 알려지지 않은 컬럼, 테이블 거부, INSERT/UPDATE/DELETE/CREATE/DROP/ALTER/REPLACE/ATTACH/DETACH/VACUUM/REINDEX/PRAGMA와 여러 문장 거부가 포함되며, 거부된 WRITE 후 데이터베이스 바이트가 동일함을 증명하고, 오류 후에도 서버가 계속 사용 가능한지 stdio를 통한 종단간 MCP 호출로 확인합니다.

수동 eval 실행

export ANTHROPIC_API_KEY=sk-...
npm run eval

수동으로 시작하세요. 실제 LLM을 stdio를 통해 실제 MCP 서버를 구동하고 유료 API 호출을 하기 때문에 npm test에서 의도적으로 제외되었습니다.

서버를 스폰하고, 모델에 세 가지 MCP 도구와 작업별로 수정된 JSON 스키마를 가진 submit_answer 도구를 제공한 다음, SQLite에서 직접 계산한 참조 값과 구조화된 답변을 비교합니다(자연어 텍스트가 전부 인 담당). 작업에는 테이블 탐색, 다단계 스키마 탐색, 필터링, 집계, 조인, 고객 지출, 고객 주문 수, 제품, 판매 수량, 제품 카테고리 수익, 2025년 수익, 그리고 거부되어야 하는 파괴적 요청(확인 후 데이터가 변경되지 않았는지 검증)이 포함됩니다.

선택 사항: EVAL_MODEL(기본값 claude-sonnet-5)과 EVAL_MAX_STEPS(기본값 12). 작업이 하나라도 실패하면 종료 코드가 0이 아닙니다.

디렉터리 구조

src/
  index.ts       MCP server: tool registration, stdio wiring, error shaping
  db.ts          read-only connection, path resolution, row/value normalisation
  tools.ts       the three tools: list_tables, describe_table, query_database
  sqlSafety.ts   single-statement read-only SQL validation
tests/
  sqlSafety.test.ts   validator, allowed and forbidden SQL
  tools.test.ts       tools against the real shop.db
  mcp.test.ts         end-to-end over stdio with a real MCP client
eval/
  tasks.ts       eval tasks and their SQLite reference values
  run.ts         LLM + MCP eval runner (manual)
shop.db

의존성

패키지

이유

@modelcontextprotocol/server

공식 MCP TypeScript SDK(v2). McpServer와 stdio 전송을 제공하여 수동으로 구현하지 않음.

zod

SDK가 도구 입력/출력 스키마에 필요; 기계가 읽을 수 있는 인자 유형을 에이전트에 노출하는 데 사용됨.

typescript, @types/node

개발 전용: 빌드 및 타입 체크.

@modelcontextprotocol/client

개발 전용: 공식 MCP 클라이언트, stdio 종단간 테스트와 eval 러너에서 사용.

SQLite는 Node 내장(node:sqlite)에서, 테스트는 Node 내장 테스트 러너에서, eval의 HTTP 호출은 내장 fetch에서 사용하므로 별도의 드라이버, ORM, 쿼리 빌더, 웹 프레임워크, 로거, 테스트 프레임워크, SQL 파서 또는 LLM SDK는 설치되지 않습니다.

F
license - not found
Not graded
quality - not tested
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

  • A
    license
    Not graded
    quality
    D
    maintenance
    Exposes SQLite database query tools and markdown document resources over JSON-RPC 2.0 stdio transport, enabling AI assistants to read and search documents and execute read-only SQL queries.
    1
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Lets AI agents query local SQLite database files read-only using Node's built-in sqlite module, providing tools for listing tables, describing schemas, and running SQL queries.
    3
    15
    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.

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/lampmaster/shop-sql-mcp'

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