FastPostgresMCP πβ‘οΈ (λͺ¨λ κΈ°λ₯μ κ°μΆ λ€μ€ DB MCP μλ²)
μ΄ νλ‘μ νΈλ AI μμ΄μ νΈ(μ: Cursor, Claude Desktop)κ° μ¬λ¬ PostgreSQL λ°μ΄ν°λ² μ΄μ€μ μνΈ μμ©νκ³ ν μ΄λΈ λμ΄ λ° μ€ν€λ§ κ²μ¬λ₯Ό μνν μ μλλ‘ μ€κ³λ λ§€μ° λΉ λ₯΄κ³ μ νμ΄ μμ νλ©° λͺ¨λ κΈ°λ₯μ κ°μΆ Model Context Protocol(MCP) μλ²λ₯Ό ꡬνν©λλ€.
Bun, TypeScript, postgres λ‘ κ΅¬μΆλμμΌλ©°, κ²¬κ³ ν MCP μλ²λ₯Ό ꡬμΆνκΈ° μν fastmcp νλ μμν¬μ κ³ κΈ κΈ°λ₯μ νμ©ν©λλ€.
π λΌμ΄μΌμ€: MIT
π fastmcpλ‘ κ΅¬λλ¨
π BunμΌλ‘ μ μ
π postgresλ₯Ό μ¬μ©ν©λλ€
π νμ
μ€ν¬λ¦½νΈ
π GitHub μ μ₯μ
π NPM ν¨ν€μ§
λͺ©μ : AI μμ΄μ νΈλ₯Ό μν MCP μλ²
μ΄ λΌμ΄λΈλ¬λ¦¬λ μ½λμ μν¬νΈν μ μμ΅λλ€ . λ
립ν μλ² μ ν리μΌμ΄μ
μ
λλ€. νλ‘μΈμ€λ‘ μ€ννλ©΄ MCP ν΄λΌμ΄μΈνΈ(AI μμ΄μ νΈ λ±)λ JSON κΈ°λ° λͺ¨λΈ 컨ν
μ€νΈ νλ‘ν μ½(v2.0)μ μ¬μ©νμ¬ ν΅μ ν©λλ€. μΌλ°μ μΌλ‘ ν΄λΌμ΄μΈνΈ μ ν리μΌμ΄μ
(μ: Cursor)μμ κ΄λ¦¬νλ stdio μ°κ²°μ ν΅ν΄ ν΅μ ν©λλ€.
Related MCP server: Postgres MCP Pro
λ¬Έμ ν΄κ²° λ° κ°λ°
ν μ€νΈλ₯Ό μν CLI μ¬μ©
ν¨ν€μ§μλ MCP μλ²λ₯Ό μ§μ ν μ€νΈνκΈ° μν λ΄μ₯ CLI λͺ λ Ήμ΄ ν¬ν¨λμ΄ μμ΅λλ€.
μ§μμ€νΌ1
λ΄μ₯λ MCP κ²μ¬κΈ°λ‘ ν μ€νΈ
MCP Inspectorλ₯Ό μ¬μ©νμ¬ μκ°μ μΌλ‘ ν μ€νΈνκ³ λλ²κΉ ν μλ μμ΅λλ€.
# From the project repository:
bun run inspectμΌλ°μ μΈ λ¬Έμ
bunx postgres-mcp μ€νν λ λ€μ μ€λ₯κ° νμλλ©΄:
FastPostgresMCP started
[warning] FastMCP could not infer client capabilitiesping λ©μμ§κ° λ€λ°λ₯΄λ κ²½μ° λ€μμ μλ―Έν©λλ€.
MCP μλ²κ° μ±κ³΅μ μΌλ‘ μμλμμ΅λλ€.
ν΄λΌμ΄μΈνΈκ° μ±κ³΅μ μΌλ‘ μ°κ²°λμμ΅λλ€
νμ§λ§ ν΄λΌμ΄μΈνΈλ ping μμ²λ§ 보λ΄κ³ κΈ°λ₯μ μ λλ‘ νμνμ§ μμ΅λλ€.
μ΄λ μΌλ°μ μΌλ‘ μ μ ν MCP ν΄λΌμ΄μΈνΈλ₯Ό μ¬μ©ν΄μΌ ν¨μ λνλ λλ€. λ€μμ μλν΄ λ³΄μΈμ.
bun run cliμ¬μ©νμ¬ MCP CLIλ‘ ν μ€νΈμ€μΉ μΉμ μ μ€λͺ λ λλ‘ Cursor λλ Claude Desktopμμ MCP μλ² κ΅¬μ±
μ¬μ©μ μ μ MCP ν΄λΌμ΄μΈνΈλ₯Ό κ°λ°νλ κ²½μ° κΈ°λ₯ νμμ ν¬ν¨νμ¬ MCP νλ‘ν μ½μ μ¬λ°λ₯΄κ² ꡬννλμ§ νμΈνμΈμ.
β¨ ν΅μ¬ κΈ°λ₯
π λ§€μ° λΉ λ¦: Bunκ³Ό
fastmcpκΈ°λ°μΌλ‘ ꡬμΆλ¨.π Type-Safe: Zod μ€ν€λ§ κ²μ¦μ ν΅ν μ’ λ¨ κ° TypeScript.
π λ€μ€ λ°μ΄ν°λ² μ΄μ€ μ§μ:
.envμ μ μλ μ¬λ¬ PostgreSQL μΈμ€ν΄μ€μ μ°κ²°νκ³ μνΈμμ©μ κ΄λ¦¬ν©λλ€.π‘οΈ λ³΄μμ κ³ λ €ν μ€κ³:
postgresν΅ν λ§€κ°λ³μνλ 쿼리λ SQL μ£Όμ μ λ°©μ§ν©λλ€.π μ νμ μΈμ¦: API ν€ κ²μ¦(
fastmcpμauthenticateνν¬)μ μ¬μ©νμ¬ λ€νΈμν¬ κΈ°λ° μ°κ²°(SSE/HTTP)μ 보νΈν©λλ€.π MCP 리μμ€λ₯Ό ν΅ν λ°μ΄ν°λ² μ΄μ€ μ€ν€λ§:
ν μ΄λΈ λͺ©λ‘:
db://{dbAlias}/schema/tablesν΅ν΄ λ°μ΄ν°λ² μ΄μ€μ ν μ΄λΈ λͺ©λ‘μ κ°μ Έμ΅λλ€.ν μ΄λΈ μ€ν€λ§ κ²μ¬:
db://{dbAlias}/schema/{tableName}ν΅ν΄ νΉμ ν μ΄λΈμ λν μμΈν μ΄ μ 보λ₯Ό κ°μ Έμ΅λλ€.
π¬ ν₯μλ λꡬ μνΈμμ©:
λꡬ λ΄ λ‘κΉ : λꡬλ μμΈν λ‘κ·Έλ₯Ό ν΄λΌμ΄μΈνΈλ‘ λ€μ 보λ λλ€(
log컨ν μ€νΈ).μ§ν μν© λ³΄κ³ : μ₯κΈ° μ€ν μμ μ μ§ν μν©μ λ³΄κ³ ν©λλ€(
reportProgress컨ν μ€νΈ).
π§ μΈμ μΈμ: λꡬ μ€ν 컨ν μ€νΈ(
session컨ν μ€νΈ) λ΄μμ μΈμ μ 보μ μ‘μΈμ€ν©λλ€.π‘ μ΄λ²€νΈ κΈ°λ°: μ°κ²°/μΈμ μ΄λ²€νΈ μ²λ¦¬λ₯Ό μν΄
server.onλ°session.onμ¬μ©ν©λλ€.π§ μ΅μ κ°λ°μ κ²½ν(DX): λͺ νν ꡬμ±, μ§κ΄μ μΈ API,
fastmcpλꡬλ₯Ό μ¬μ©ν κ°νΈν ν μ€νΈ.
ν¬ν¨ μ¬ν(fastmcp κΈ°λ₯ νμ©)
FastMCPμλ² μ½μ΄server.addTool(query_tool,execute_tool,schema_toolλ°transaction_toolμ©)server.addResourceTemplate(ν μ΄λΈ λμ΄ λ° ν μ΄λΈ μ€ν€λ§ κ²μ¬μ©)server.start(stdioν¬μ»€μ€ ν¬ν¨,sse/httpμ λ§κ² μ‘°μ κ°λ₯)μ ν μ¬ν:
authenticateνν¬(API ν€ κ²μ¦μ©)λꡬ μ€ν
context(log,reportProgress,session)λ§€κ°λ³μ μ€ν€λ§ κ²μ¦μ μν Zod
server.on(μ°κ²° λ‘κΉ μ©)(μ μ¬μ μΌλ‘) μΈμ λ³ λ Όλ¦¬λ₯Ό μν
session.on
π νμ 쑰건
Bun (v1.0 μ΄μ κΆμ₯): μ€μΉλμμΌλ©° PATHμ μμ΅λλ€.
PostgreSQL λ°μ΄ν°λ² μ΄μ€: μ‘μΈμ€ μ격 μ¦λͺ λ° μ°κ²°. μ¬μ©μμκ²
information_schema쿼리 κΆνμ΄ νμν©λλ€.
βοΈ μ€μΉ
μ΅μ 1: NPM ν¨ν€μ§
# Install globally
npm install -g postgres-mcp
# Or install locally in your project
npm install postgres-mcpnpm ν¨ν€μ§λ https://www.npmjs.com/package/postgres-mcp μμ μ¬μ©ν μ μμ΅λλ€.
μ΅μ 2: μ μ₯μ 볡μ
μ μ₯μλ₯Ό 볡μ ν©λλ€.
# Replace with your actual repository URL git clone https://github.com/llm-graph/postgres-mcp.git cd postgres-mcpμ’ μμ± μ€μΉ:
bun install
π ꡬμ±(λ€μ€ λ°μ΄ν°λ² μ΄μ€ λ° μ νμ μΈμ¦)
μ μ ν .env νμΌμμ λ‘λλ νκ²½ λ³μλ₯Ό ν΅ν΄ ꡬμ±ν©λλ€.
νκ²½ νμΌμ λ§λλλ€.
νλ‘λμ μ κ²½μ°:
cp .env.example .envκ°λ°μ©:
cp .env.development.example .env.development
νκ²½ νμΌ λ‘λ© μμ: μλ²λ λ€μ μ°μ μμ μμμ λ°λΌ νμΌμμ νκ²½ λ³μλ₯Ό λ‘λν©λλ€.
.env.<NODE_ENV>(μ:.env.development,.env.production,.env.staging).env.local(λ²μ μ μ΄λμ§ μλ λ‘컬 μ¬μ μμ©).env(κΈ°λ³Έ λ체) μ΄λ₯Ό ν΅ν΄ λ€μν νκ²½μ λ§κ² λ€μν ꡬμ±μ΄ κ°λ₯ν©λλ€.
λ°μ΄ν°λ² μ΄μ€ μ°κ²°κ³Ό μΈμ¦μ μ μνλ €λ©΄ νκ²½ νμΌμ νΈμ§νμΈμ .
DB_ALIASES- κ³ μ ν DB λ³μΉμ μΌνλ‘ κ΅¬λΆλ λͺ©λ‘DEFAULT_DB_ALIAS- λꡬ νΈμΆμμ 'dbAlias'κ° μλ΅λ κ²½μ° κΈ°λ³Έ λ³μΉκ° λ³μΉμ λν λ°μ΄ν°λ² μ΄μ€ μ°κ²° μΈλΆ μ 보(μ:
DB_MAIN_HOST,DB_REPORTING_HOST)μ νμ API ν€ μΈμ¦(
ENABLE_AUTH,MCP_API_KEY)
# Example .env file - Key Variables
# REQUIRED: Comma-separated list of unique DB aliases
DB_ALIASES=main,reporting
# REQUIRED: Default alias if 'dbAlias' is omitted in tool calls
DEFAULT_DB_ALIAS=main
# OPTIONAL: Enable API Key auth (primarily for network transports)
ENABLE_AUTH=false
MCP_API_KEY=your_super_secret_api_key_here # CHANGE THIS
# Define DB connection details for each alias (DB_MAIN_*, DB_REPORTING_*, etc.)
DB_MAIN_HOST=localhost
DB_MAIN_PORT=5432
DB_MAIN_NAME=app_prod_db
DB_MAIN_USER=app_user
DB_MAIN_PASSWORD=app_secret_password
DB_MAIN_SSL=disable
# Alternative: Use connection URLs
# DB_MAIN_URL=postgres://user:password@localhost:5432/database?sslmode=require
# --- Optional: Server Logging Level ---
# LOG_LEVEL=info # debug, info, warn, error (defaults to info)π μλ² μ€ν(νλ‘μΈμ€λ‘)
Bunμ μ¬μ©νμ¬ μ΄ μλ²λ₯Ό μ§μ μ€ννμΈμ. AI ν΄λΌμ΄μΈνΈ(Cursorμ μ μ¬)κ° μΌλ°μ μΌλ‘ μ΄ λͺ λ Ήμ μ€ννκ³ κ΄λ¦¬ν΄ μ€λλ€.
μ΅μ 1: κΈλ‘λ²νκ² μ€μΉλ ν¨ν€μ§ μ¬μ©
μλμΌλ‘ μ€ννλ €λ©΄:
postgres-mcp
μ΅μ 2: νλ‘μ νΈμμ ν¨ν€μ§ μ¬μ©
νλ‘μ νΈμμ μ€ννλ €λ©΄:
npx postgres-mcpλλ νλ‘κ·Έλλ° λ°©μμΌλ‘ κ°μ Έμ€κΈ°:
// server.js import { startServer } from 'postgres-mcp'; // Start the MCP server startServer();
μ΅μ 3: 볡μ λ μ μ₯μμμ
μλμΌλ‘ μ€ννλ €λ©΄(ν μ€νΈμ©):
bun run src/index.tsμλ κ°λ° λͺ¨λ:
bun run --watch src/index.ts
fastmcp CLI λκ΅¬λ‘ ν
μ€νΈ
λνν ν°λ―Έλ:
bunx fastmcp dev src/index.tsμΉ UI κ²μ¬κΈ°:
bunx fastmcp inspect src/index.ts
π» νλ‘κ·Έλλ° API μ¬μ©(λΌμ΄λΈλ¬λ¦¬λ‘)
postgres-mcpλ λ 립ν MCP μλ²λ‘ μ€ννλ κ² μΈμλ Node.js/TypeScript μ ν리μΌμ΄μ μμ λΌμ΄λΈλ¬λ¦¬λ‘ νλ‘κ·Έλλ° λ°©μμΌλ‘ μ¬μ©ν μλ μμ΅λλ€.
κΈ°λ³Έ μ¬μ©λ²
import { createPostgresMcp } from 'postgres-mcp';
// Create the PostgresMcp instance
const postgresMcp = createPostgresMcp();
// Start the server
postgresMcp.start();
// Direct database operations
const results = await postgresMcp.executeQuery(
'SELECT * FROM users WHERE role = $1',
['admin'],
'main' // optional database alias
);
// When done, stop the server and close connections
await postgresMcp.stop();μ§μ ν¨μ κ°μ Έμ€κΈ°
λ κ°λ¨ν μ¬μ© μ¬λ‘μμλ νΉμ ν¨μλ₯Ό μ§μ κ°μ Έμ¬ μ μμ΅λλ€.
import {
initConnections,
closeConnections,
executeQuery,
executeCommand,
executeTransaction,
getTableSchema,
getAllTableSchemas
} from 'postgres-mcp';
// Configure database connections
const dbConfigs = {
main: {
host: 'localhost',
port: 5432,
database: 'my_db',
user: 'db_user',
password: 'db_password'
}
};
// Initialize connections
initConnections(dbConfigs);
// Execute a query
const results = await executeQuery(
'SELECT * FROM users WHERE role = $1',
['admin'],
'main'
);
// Get schema for a single table
const schema = await getTableSchema('users', 'main');
// Get schema for all tables in the database
const allSchemas = await getAllTableSchemas('main');
// Close connections when done
await closeConnections();κ΅¬μ± μ΅μ
const postgresMcp = createPostgresMcp({
// Custom database configurations (override .env)
databaseConfigs: {
main: {
host: 'localhost',
port: 5432,
database: 'app_db',
user: 'app_user',
password: 'password',
ssl: 'disable'
}
},
// Server configuration
serverConfig: {
name: 'Custom PostgresMCP',
defaultDbAlias: 'main'
},
// Transport options: 'stdio', 'sse', or 'http'
transport: 'http',
port: 3456
});νλ‘κ·Έλλ° APIμ λν μ 체 μ€λͺ μλ docs/programmatic-api.mdλ₯Ό μ°Έμ‘°νμΈμ.
π AI ν΄λΌμ΄μΈνΈ(Cursor, Claude Desktop)μ μ°κ²°
AI μμ΄μ νΈ(MCP ν΄λΌμ΄μΈνΈ)λ₯Ό ꡬμ±νμ¬ λͺ λ Ή/μΈμ λ©μ»€λμ¦μ ν΅ν΄ μ΄ μλ² μ€ν¬λ¦½νΈλ₯Ό μ€ννμΈμ .
컀μ AI - μμΈν μ
컀μ μ€μ /νκ²½ μ€μ μ μ½λλ€(Cmd+, λλ Ctrl+,).
"νμ₯ νλ‘κ·Έλ¨" -> "MCP"λ‘ μ΄λν©λλ€.
"MCP μλ² μΆκ°"λ₯Ό ν΄λ¦νκ±°λ
settings.jsonνΈμ§ν©λλ€.λ€μ JSON ꡬμ±μ μΆκ°ν©λλ€.
// In Cursor's settings.json or MCP configuration UI { "mcpServers": { "postgres-mcp": { // Unique name for Cursor "description": "MCP Server for PostgreSQL DBs (Main, Reporting)", "command": "bunx", // Use 'bun' or provide absolute path: "/Users/your_username/.bun/bin/bun" "args": [ "postgres-mcp" // or // *** ABSOLUTE PATH to your server's entry point *** // "/Users/your_username/projects/postgres-mcp/src/index.ts" / ], "env": { // .env file in project dir is loaded automatically by Bun. // Add overrides or Cursor-specific vars here if needed. }, "enabled": true } } }컀μλ₯Ό μ μ₯ νκ³ λ€μ μμνκ±°λ "MCP μλ² λ€μ λ‘λ"λ₯Ό ν΄λ¦ν©λλ€.
컀μμ MCP μν/λ‘κ·Έμμ μ°κ²°μ νμΈνμΈμ .
ν΄λ‘λ λ°μ€ν¬ν
config.jsonμ°Ύμ νΈμ§ν©λλ€(κ²½λ‘λ μ΄μ README μ°Έμ‘°).argsμ μ λ κ²½λ‘λ₯Ό μ¬μ©νμ¬mcpServersμλμ λΉμ·ν νλͺ©μ μΆκ°ν©λλ€.Claude Desktopμ λ€μ μμν©λλ€.
π οΈ MCP κΈ°λ₯ 곡κ°
μΈμ¦(μ ν μ¬ν)
ENABLE_AUTH=trueκ²½μ°MCP_API_KEYμ μΌμΉνλX-API-Keyν€λλ₯Ό ν΅ν΄ λ€νΈμν¬ μ μ‘(HTTP/SSE)μ 보νΈν©λλ€.stdioμ°κ²°(Cursor/Claudeμ κΈ°λ³Έκ°)μ μΌλ°μ μΌλ‘ μ΄ κ²μ¬λ₯Ό μ°νν©λλ€.
μμ
1. λ°μ΄ν°λ² μ΄μ€ ν μ΄λΈ λμ΄
URI ν νλ¦Ώ:
db://{dbAlias}/schema/tablesμ€λͺ : μ§μ λ λ°μ΄ν°λ² μ΄μ€ λ³μΉ(μΌλ°μ μΌλ‘ 'public' μ€ν€λ§μμ) λ΄μ μ¬μ©μ ν μ΄λΈ μ΄λ¦ λͺ©λ‘μ κ²μν©λλ€.
리μμ€ μ μ(
addResourceTemplate):uriTemplate:"db://{dbAlias}/schema/tables"arguments:dbAlias: (λ¬Έμμ΄, νμ) - λ°μ΄ν°λ² μ΄μ€μ λ³μΉ(.envμμ).
load({ dbAlias }): λ°μ΄ν°λ² μ΄μ€μ μ°κ²°νκ³information_schema.tables(κ³΅κ° μ€ν€λ§μ κΈ°λ³Έ ν μ΄λΈμ λν΄ νν°λ§, ꡬν μ μ¬μ©μ μ μ κ°λ₯)λ₯Ό 쿼리νκ³ κ²°κ³Όλ₯Ό JSON λ¬Έμμ΄ λ°°μ΄["table1", "table2", ...]λ‘ ν¬λ§·νκ³{ text: "..." }λ°νν©λλ€.
μ¬μ© μ(AI ν둬ννΈ): "κΈ°λ³Έ λ°μ΄ν°λ² μ΄μ€μ ν
μ΄λΈμ λμ΄νλ €λ©΄ 리μμ€ db://main/schema/tables κ°μ Έμ΅λλ€."
2. ν μ΄λΈ μ€ν€λ§ κ²μ¬
URI ν νλ¦Ώ:
db://{dbAlias}/schema/{tableName}μ€λͺ : νΉμ ν μ΄λΈμ λν μμΈν μ€ν€λ§ μ 보(μ΄, μ ν, NULL νμ© μ¬λΆ, κΈ°λ³Έκ°)λ₯Ό μ 곡ν©λλ€.
리μμ€ μ μ(
addResourceTemplate):uriTemplate:"db://{dbAlias}/schema/{tableName}"arguments:dbAlias: (λ¬Έμμ΄, νμ) - λ°μ΄ν°λ² μ΄μ€ λ³μΉ.tableName: (λ¬Έμμ΄, νμ) - ν μ΄λΈμ μ΄λ¦μ λλ€.
load({ dbAlias, tableName }): μ°κ²°νκ³ , νΉμ ν μ΄λΈμ λνinformation_schema.columns쿼리νκ³ , μ΄ κ°μ²΄μ JSON λ¬Έμμ΄ λ°°μ΄λ‘ ν¬λ§·νκ³ ,{ text: "..." }λ°νν©λλ€.
μ¬μ© μμ(AI ν둬ννΈ): " db://reporting/schema/daily_sales 리μμ€λ₯Ό μ€λͺ
νμΈμ."
μλ΅ λ΄μ© μ(JSON λ¬Έμμ΄):
"[{\"column_name\":\"session_id\",\"data_type\":\"uuid\",\"is_nullable\":\"NO\",\"column_default\":\"gen_random_uuid()\"},{\"column_name\":\"user_id\",\"data_type\":\"integer\",\"is_nullable\":\"NO\",\"column_default\":null},{\"column_name\":\"created_at\",\"data_type\":\"timestamp with time zone\",\"is_nullable\":\"YES\",\"column_default\":\"now()\"},{\"column_name\":\"expires_at\",\"data_type\":\"timestamp with time zone\",\"is_nullable\":\"YES\",\"column_default\":null}]"λꡬ
λꡬλ context κ°μ²΄( log , reportProgress , session )λ₯Ό μμ ν©λλ€.
1. query_tool
μ½κΈ° μ μ© SQL 쿼리λ₯Ό μ€νν©λλ€.
μ€λͺ : μ€ν λ‘κΉ /μ§ν μν©μ κΈ°λ‘νμ¬ μ½κΈ° μ μ© SQLμ μμ νκ² μ€ννκ³ κ²°κ³Όλ₯Ό μ»μ΅λλ€.
λ§€κ°λ³μ:
statement(λ¬Έμμ΄),params(λ°°μ΄, opt),dbAlias(λ¬Έμμ΄, opt).컨ν μ€νΈ μ¬μ©:
log.info/debug, μ νμ reportProgress, μ‘μΈμ€session.λ°ν: ν λ°°μ΄μ JSON λ¬Έμμ΄.
μμ² μμ:
{
"tool_name": "query_tool",
"arguments": {
"statement": "SELECT product_id, name, price FROM products WHERE category = $1 AND price < $2 ORDER BY name LIMIT 10",
"params": ["electronics", 500],
"dbAlias": "main"
}
}μλ΅ λ΄μ© μ(JSON λ¬Έμμ΄):
"[{\"product_id\":123,\"name\":\"Example Gadget\",\"price\":499.99},{\"product_id\":456,\"name\":\"Another Device\",\"price\":350.00}]"2. execute_tool
λ°μ΄ν°λ₯Ό μμ νλ SQL λ¬Έμ μ€νν©λλ€.
μ€λͺ : μ€ν λ‘κΉ μ ν΅ν΄ λ°μ΄ν°λ₯Ό μμ νλ SQLμ μμ νκ² μ€νν©λλ€.
λ§€κ°λ³μ:
statement(λ¬Έμμ΄),params(λ°°μ΄, opt),dbAlias(λ¬Έμμ΄, opt).컨ν μ€νΈ μ¬μ©:
log.info/debug,sessionμ μ κ·Όν©λλ€.λ°νκ°: μν₯μ λ°λ νμ λνλ΄λ λ¬Έμμ΄μ λλ€.
μμ² μμ:
{
"tool_name": "execute_tool",
"arguments": {
"statement": "UPDATE users SET last_login = NOW() WHERE user_id = $1",
"params": [54321]
// dbAlias omitted, uses DEFAULT_DB_ALIAS
}
}μλ΅ λ΄μ© μμ(λ¬Έμμ΄):
"Rows affected: 1"3. schema_tool
νΉμ ν μ΄λΈμ λν μμΈν μ€ν€λ§ μ 보λ₯Ό κ²μν©λλ€.
μ€λͺ : λ°μ΄ν°λ² μ΄μ€ ν μ΄λΈμ λν μ΄ μ μμ μΈλΆ μ 보λ₯Ό κ°μ Έμ΅λλ€.
λ§€κ°λ³μ:
tableName(λ¬Έμμ΄),dbAlias(λ¬Έμμ΄, opt).컨ν μ€νΈ μ¬μ©:
log.info, μ‘μΈμ€session.λ°ν: μ΄ μ 보 κ°μ²΄μ JSON λ¬Έμμ΄ λ°°μ΄μ λλ€.
μμ² μμ:
{
"tool_name": "schema_tool",
"arguments": {
"tableName": "user_sessions",
"dbAlias": "main"
}
}μλ΅ λ΄μ© μ(JSON λ¬Έμμ΄):
"[{\"column_name\":\"session_id\",\"data_type\":\"uuid\",\"is_nullable\":\"NO\",\"column_default\":\"gen_random_uuid()\"},{\"column_name\":\"user_id\",\"data_type\":\"integer\",\"is_nullable\":\"NO\",\"column_default\":null},{\"column_name\":\"created_at\",\"data_type\":\"timestamp with time zone\",\"is_nullable\":\"YES\",\"column_default\":\"now()\"},{\"column_name\":\"expires_at\",\"data_type\":\"timestamp with time zone\",\"is_nullable\":\"YES\",\"column_default\":null}]"4. transaction_tool
μ¬λ¬ SQL λ¬Έμ μμμ μΌλ‘ μ€νν©λλ€.
μ€λͺ : λ¨κ³λ³ λ‘κΉ /μ§ν μν©μ κΈ°λ‘νμ¬ νΈλμμ μμ SQL μνμ€λ₯Ό μ€νν©λλ€.
λ§€κ°λ³μ:
operations({statement, params}μ λ°°μ΄),dbAlias(λ¬Έμμ΄, opt).컨ν μ€νΈ μ¬μ©:
log.info/debug/error,reportProgress, accesssession.λ°ν: μ±κ³΅/μ€ν¨λ₯Ό μμ½ν JSON λ¬Έμμ΄:
{"success": true, "results": [...]}λλ{"success": false, "error": ..., "failedOperationIndex": ...}.
μμ² μμ:
{
"tool_name": "transaction_tool",
"arguments": {
"operations": [
{
"statement": "INSERT INTO orders (customer_id, order_date, status) VALUES ($1, NOW(), 'pending') RETURNING order_id",
"params": [101]
},
{
"statement": "INSERT INTO order_items (order_id, product_sku, quantity, price) VALUES ($1, $2, $3, $4)",
"params": [9999, "GADGET-X", 2, 49.99]
},
{
"statement": "UPDATE inventory SET stock_count = stock_count - $1 WHERE product_sku = $2 AND stock_count >= $1",
"params": [2, "GADGET-X"]
}
],
"dbAlias": "main"
}
}μ±κ³΅ μλ΅ μ½ν μΈ μμ(JSON λ¬Έμμ΄):
"{\"success\":true,\"results\":[{\"operation\":0,\"rowsAffected\":1},{\"operation\":1,\"rowsAffected\":1},{\"operation\":2,\"rowsAffected\":1}]}"μ€λ₯ μλ΅ λ΄μ© μ(JSON λ¬Έμμ΄):
"{\"success\":false,\"error\":\"Error executing operation 2: new row for relation \\\"inventory\\\" violates check constraint \\\"stock_count_non_negative\\\"\",\"failedOperationIndex\":2}"μλ² λ° μΈμ μ΄λ²€νΈ
ν΄λΌμ΄μΈνΈ μ°κ²°μ λ‘κΉ νλ €λ©΄
server.on('connect'/'disconnect')μ¬μ©ν©λλ€.νμν κ²½μ° λ³΄λ€ μΈλΆμ μΈ μΈμ μ΄λ²€νΈ μ²λ¦¬λ₯Ό μν΄
session.on(...)μ¬μ©ν μ μμ΅λλ€.
π 보μ κ³ λ € μ¬ν
SQL μ£Όμ : λ§€κ°λ³μνλ 쿼리λ₯Ό ν΅ν΄ μνλ©λλ€. μ§μ μ μΈ μ λ ₯ μ°κ²°μ μμ΅λλ€.
λ°μ΄ν°λ² μ΄μ€ κΆν: μ€μ. κ°
DB_<ALIAS>_USERμ μ΅μνμ κΆνμ ν λΉνμΈμ. μ¬κΈ°μλ μ€ν€λ§/ν μ΄λΈ λͺ©λ‘ 리μμ€μ λνinformation_schemaμ½κΈ° κΆνμ΄ ν¬ν¨λ©λλ€.SSL/TLS: νλ‘λμ μ νμ (
DB_<ALIAS>_SSL=requireλλ stricter).λΉλ° κ΄λ¦¬:
.envνμΌμ 보νΈνμΈμ(.gitignoreνμΌμ μΆκ°). μ΄μ νκ²½(Vault, Doppler, ν΄λΌμ°λ λΉλ°)μ μμ ν λΉλ° κ΄λ¦¬λ₯Ό μ¬μ©νμΈμ.μΈμ¦ λ²μ:
authenticateνν¬λ μ£Όλ‘ λ€νΈμν¬ μ μ‘μ 보νΈν©λλ€.stdio보μμ μ€ν νκ²½μ λ°λΌ λ¬λΌμ§λλ€.λ°μ΄ν° λ―Όκ°μ±: μ°κ²°/λꡬλ₯Ό ν΅ν΄ μ κ·Ό κ°λ₯ν λ°μ΄ν°λ₯Ό νμ νμΈμ.
리μμ€ μΏΌλ¦¬: ν μ΄λΈ(
information_schema.tables) λ° μ€ν€λ§(information_schema.columns)λ₯Ό λμ΄νλ λ° μ¬μ©λλ 쿼리λ μΌλ°μ μΌλ‘ μμ νμ§λ§ λ°μ΄ν°λ² μ΄μ€ κΆνμ μμ‘΄ν©λλ€. ꡬμ±λ μ¬μ©μμκ² μ μ ν μ½κΈ° κΆνμ΄ μλμ§ νμΈνμμμ€. 보μ λλ λͺ νμ±μ μν΄ νμν κ²½μ° ν μ΄λΈ λμ΄ μΏΌλ¦¬(μ: μ€ν€λ§ νν°λ§)λ₯Ό μ¬μ©μ μ μνμμμ€.
π λΌμ΄μΌμ€
μ΄ νλ‘μ νΈλ MIT λΌμ΄μ μ€ μ λ°λΌ λΌμ΄μ μ€κ° λΆμ¬λ©λλ€. μμΈν λ΄μ©μ λΌμ΄μ μ€ νμΌμ μ°Έμ‘°νμΈμ.
π λ³κ²½ μ¬ν
1.0.0
μ΅μ΄ μΆμ
PostgreSQLμ μν λͺ¨λ κΈ°λ₯μ κ°μΆ MCP μλ²
λ€μ€ λ°μ΄ν°λ² μ΄μ€ μ°κ²° μ§μ
쿼리, μ€ν, μ€ν€λ§ κ²μ¬ λ° νΈλμμ μ μν λꡬ
μ€ν€λ§ λ΄μ±μ μν 리μμ€
ν¬κ΄μ μΈ λ¬Έμ λ° μμ
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Appeared in Searches
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/llm-graph/postgres-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
