Supabase MCP 서버 구현 계획
이 문서에서는 GitHub Copilot과 같은 AI 어시스턴트가 Supabase 데이터베이스와 상호 작용할 수 있도록 Supabase에 연결되는 MCP(Model Context Protocol) 서버를 만드는 계획을 설명합니다.
목차
개요
Supabase MCP 서버는 AI 어시스턴트(예: GitHub Copilot)와 Supabase 데이터베이스를 연결하는 다리 역할을 합니다. 이를 통해 AI는 다음과 같은 작업을 수행할 수 있습니다.
- 데이터베이스 스키마를 이해하세요
- 테이블과 관계에 대해 알아보세요
- 쿼리 작성 지원
- 데이터 모델과 관련된 컨텍스트 인식 제안을 제공합니다.
필수 조건
- Node.js 18+ 설치됨
- npm 또는 yarn 패키지 관리자
- 관리자 API 키가 있는 Supabase 프로젝트
- Copilot/MCP 지원이 포함된 VS 코드
- 깃
구현 단계
1. 서버 패키지 생성
지엑스피1
2. 종속성 설치
npm install @supabase/supabase-js @modelcontextprotocol/server dotenv
3. 기본 서버 구조
다음 파일을 생성하세요.
src/index.js
- 주요 진입점src/supabase-client.js
- Supabase 연결 처리src/schema-provider.js
- 데이터베이스 스키마 추출src/query-handler.js
- 안전한 쿼리 실행.env.example
- 환경 변수 템플릿config.js
- 구성 관리
4. 서버 구현 세부 사항
src/index.js
이 파일은 MCP 서버를 초기화하고 구성 요소를 연결합니다.
const { MCPServer } = require('@modelcontextprotocol/server');
const { getSupabaseClient } = require('./supabase-client');
const { SchemaProvider } = require('./schema-provider');
const { QueryHandler } = require('./query-handler');
const config = require('./config');
async function main() {
try {
// Initialize Supabase client
const supabaseClient = getSupabaseClient(config.supabase.url, config.supabase.key);
// Create providers
const schemaProvider = new SchemaProvider(supabaseClient);
const queryHandler = new QueryHandler(supabaseClient, config.security.allowedQueries);
// Initialize MCP server
const server = new MCPServer({
name: 'mcp-server-supabase',
version: '1.0.0',
});
// Register handlers
server.registerHandler('getSchema', async () => {
return await schemaProvider.getFullSchema();
});
server.registerHandler('getTableInfo', async (params) => {
return await schemaProvider.getTableInfo(params.tableName);
});
server.registerHandler('executeQuery', async (params) => {
return await queryHandler.execute(params.query, params.params);
});
// Start the server
await server.start();
console.log('MCP Supabase server is running');
} catch (error) {
console.error('Failed to start MCP server:', error);
process.exit(1);
}
}
main();
src/supabase-client.js
const { createClient } = require('@supabase/supabase-js');
function getSupabaseClient(url, apiKey) {
if (!url || !apiKey) {
throw new Error('Supabase URL and API key must be provided');
}
return createClient(url, apiKey, {
auth: { persistSession: false },
});
}
module.exports = { getSupabaseClient };
src/schema-provider.js
class SchemaProvider {
constructor(supabaseClient) {
this.supabase = supabaseClient;
}
async getFullSchema() {
// Query Supabase for full database schema
const { data, error } = await this.supabase
.rpc('get_schema_information', {});
if (error) throw new Error(`Failed to get schema: ${error.message}`);
return data;
}
async getTableInfo(tableName) {
// Get detailed information about a specific table
const { data, error } = await this.supabase
.rpc('get_table_information', { table_name: tableName });
if (error) throw new Error(`Failed to get table info: ${error.message}`);
return data;
}
}
module.exports = { SchemaProvider };
src/query-handler.js
class QueryHandler {
constructor(supabaseClient, allowedQueryTypes = ['SELECT']) {
this.supabase = supabaseClient;
this.allowedQueryTypes = allowedQueryTypes;
}
validateQuery(queryString) {
// Basic SQL injection prevention and query type validation
const normalizedQuery = queryString.trim().toUpperCase();
// Check if the query starts with allowed query types
const isAllowed = this.allowedQueryTypes.some(
type => normalizedQuery.startsWith(type)
);
if (!isAllowed) {
throw new Error(`Query type not allowed. Allowed types: ${this.allowedQueryTypes.join(', ')}`);
}
return true;
}
async execute(queryString, params = {}) {
// Validate query before execution
this.validateQuery(queryString);
// Execute the query through Supabase
const { data, error } = await this.supabase
.rpc('execute_query', { query_string: queryString, query_params: params });
if (error) throw new Error(`Query execution failed: ${error.message}`);
return data;
}
}
module.exports = { QueryHandler };
config.js
require('dotenv').config();
module.exports = {
supabase: {
url: process.env.SUPABASE_URL,
key: process.env.SUPABASE_SERVICE_KEY,
},
server: {
port: process.env.PORT || 3000,
},
security: {
allowedQueries: process.env.ALLOWED_QUERY_TYPES
? process.env.ALLOWED_QUERY_TYPES.split(',')
: ['SELECT'],
}
};
.env.예제
SUPABASE_URL=https://your-project-ref.supabase.co
SUPABASE_SERVICE_KEY=your-service-key
PORT=3000
ALLOWED_QUERY_TYPES=SELECT
5. Supabase 데이터베이스 함수
Supabase에서 다음과 같은 저장 프로시저를 만들어야 합니다.
get_schema_information()
- 데이터베이스 스키마를 반환합니다.get_table_information(table_name TEXT)
- 특정 테이블에 대한 정보를 반환합니다.execute_query(query_string TEXT, query_params JSONB)
- 쿼리를 안전하게 실행합니다.
서버 아키텍처
┌─────────────────────┐ ┌───────────────────┐
│ │ │ │
│ VS Code + Copilot │◄────►│ MCP Protocol │
│ │ │ │
└─────────────────────┘ └─────────┬─────────┘
│
▼
┌─────────────────────┐
│ │
│ Supabase MCP Server │
│ │
└─────────┬───────────┘
│
▼
┌─────────────────────┐
│ │
│ Supabase Database │
│ │
└─────────────────────┘
구성
VS Code settings.json
에 Supabase MCP 서버를 추가합니다.
"mcp": {
"inputs": [],
"servers": {
// ...existing servers...
"mcp-server-supabase": {
"command": "node",
"args": [
"/path/to/mcp-server-supabase/src/index.js"
],
"env": {
"SUPABASE_URL": "https://your-project-ref.supabase.co",
"SUPABASE_SERVICE_KEY": "your-service-key",
"ALLOWED_QUERY_TYPES": "SELECT"
}
}
}
}
보안 고려 사항
- API 키 관리 :
- 최소 필수 권한이 있는 범위가 지정된 API 키를 사용하세요.
- API 키를 안전하게 저장하고 버전 제어에 절대 커밋하지 마세요.
- 키 로테이션 전략 사용을 고려하세요
- 쿼리 제한 사항 :
- 안전을 위해 SELECT 전용으로 기본 설정
- 쿼리 허용 목록 접근 방식 구현을 고려하세요
- 남용을 방지하기 위해 속도 제한을 추가하세요
- 데이터 보호 :
- PII 또는 민감한 데이터 노출을 피하세요
- Supabase에서 행 수준 보안 구현
- 민감한 필드에 데이터 마스킹을 추가하는 것을 고려하세요
설치 가이드
지역 개발
- 저장소를 복제합니다
git clone https://github.com/yourusername/mcp-server-supabase.git
cd mcp-server-supabase
- 종속성 설치
- 예제에서
.env
파일을 만듭니다. - Supabase 자격 증명으로
.env
편집하세요. - 서버를 시작합니다
VS 코드 통합
- 서버 구성으로 VS Code
settings.json
업데이트하세요. - VS 코드 재시작
- VS Code MCP 패널에서 서버가 실행 중인지 확인하세요.
사용 예
통합이 완료되면 Supabase MCP 서버를 다양한 방법으로 사용할 수 있습니다.
- 스키마 탐색:
What tables do I have in my Supabase database?
- 테이블 정보:
What columns are in the users table?
- 질의 지원:
Help me write a query to get all users who signed up in the last 7 days
문제 해결
서버가 시작되지 않습니다
- Node.js 버전을 확인하세요(18 이상이어야 함)
- Supabase 자격 증명을 확인하세요
- 터미널에서 오류 로그를 확인하세요
스키마가 로드되지 않습니다
- Supabase 서비스 키에 필요한 권한이 있는지 확인하세요.
- 데이터베이스 기능이 제대로 생성되었는지 확인하세요
VS Code에 연결할 수 없습니다
- settings.json의 서버 경로가 올바른지 확인하세요
- 구성 변경 후 VS Code를 다시 시작하세요
- 서버 프로세스가 실행 중인지 확인하세요