ساخت MCP Server برای دیتابیس

قسمت ۸ ۲۰ دقیقه

قبلاً چی گفتیم؟

تا اینجای سری، MCP رو شناختیم، سرور ساختیم، به Claude وصل کردیم، امنیت رو بررسی کردیم و بردنش به پروداکشن رو یاد گرفتیم. ولی یه سوال بزرگ مونده: چطور MCP رو به دیتابیس وصل کنیم؟

فکرش رو بکن. یه مدل هوش مصنوعی که بتونه مستقیم از دیتابیست query بزنه. نه اینکه تو دستی نتایج رو کپی-پیست کنی، بلکه خودش بره بخونه و تحلیل کنه. خیلی وسوسه‌انگیزه، ولی یه عالمه خطر هم داره.

این قسمت دقیقاً درباره همینه: ساختن یه MCP Server که دیتابیس رو به AI وصل می‌کنه — ولی امن و کنترل‌شده.

پیش‌نیاز
برای این قسمت، آشنایی پایه با SQL و مفاهیم دیتابیس لازمه. اگه قبلاً با PostgreSQL یا MySQL کار کردی، عالیه. اگه نه، نگران نباش — مفاهیم رو ساده توضیح می‌دم.

چرا MCP + دیتابیس؟

بذار چند سناریوی واقعی بگم که نشون بده چرا این ترکیب قدرتمنده:

سناریوی ۱: تحلیل فروش. مدیر فروش می‌خواد بدونه «فروش ماه گذشته نسبت به سال قبل چطور بوده؟» به جای اینکه یه نفر SQL بنویسه، مدیر مستقیم از Claude می‌پرسه. Claude از MCP Server query می‌زنه و جواب رو تحلیل می‌کنه.

سناریوی ۲: عیب‌یابی. توسعه‌دهنده می‌خواد بفهمه چرا یه کاربر خاص مشکل داره. به جای اینکه دستی چند تا query بزنه، از AI می‌خواد «وضعیت حساب کاربر شماره ۴۵۲۱ رو بررسی کن.» AI چند query مختلف می‌زنه و یه گزارش جامع می‌ده.

سناریوی ۳: گزارش‌گیری. هر هفته باید گزارش عملکرد تهیه بشه. AI خودش queryها رو اجرا می‌کنه، نتایج رو تحلیل می‌کنه و گزارش رو آماده می‌کنه.

تشبیه
MCP Server دیتابیس مثل یه کتابدار حرفه‌ای هست. تو نمی‌ری خودت بین قفسه‌ها بگردی (خطرناکه، ممکنه کتاب‌ها رو بریزی!). به کتابدار می‌گی چی می‌خوای و اون بهت می‌ده. کتابدار می‌دونه کجا بگرده، چی بده و چی نده.

معماری امن

قبل از هر چیز، بذار یه اصل مهم رو مشخص کنم: MCP Server دیتابیس باید read-only باشه. مگه اینکه واقعاً بدونی چیکار می‌کنی و لایه‌های امنیتی کافی داشته باشی.

چرا؟ چون یه مدل AI ممکنه اشتباه کنه. اگه دسترسی write داشته باشه و یه DELETE یا UPDATE اشتباهی بزنه، فاجعه‌ست. پس قانون اول:

قانون طلایی
هرگز به MCP Server دسترسی write به دیتابیس پروداکشن نده. یه کاربر read-only بساز و فقط به جدول‌هایی که لازمه دسترسی بده. بقیه جدول‌ها اصلاً قابل مشاهده نباشن.

لایه‌های امنیتی

یه MCP Server دیتابیس خوب چند لایه محافظت داره:

لایه ۱ — کاربر محدود: یه کاربر دیتابیس بساز که فقط SELECT روی جدول‌های مشخص داشته باشه. نه INSERT، نه UPDATE، نه DELETE.

لایه ۲ — فیلتر queryها: قبل از اجرای هر query، بررسی کن که فقط SELECT باشه. هر query دیگه‌ای رو رد کن.

لایه ۳ — محدودیت نتایج: حداکثر تعداد ردیف‌های خروجی رو محدود کن (مثلاً ۱۰۰۰ ردیف). اگه کسی بخواد کل دیتابیس رو dump کنه، نتونه.

لایه ۴ — محدودیت زمانی: اگه query بیشتر از مثلاً ۳۰ ثانیه طول بکشه، لغوش کن. queryهای سنگین نباید سرور رو زمین بزنن.

لایه ۵ — لاگ کامل: هر query که اجرا می‌شه رو لاگ کن. کی زده، چی زده، نتیجه چی بوده.

ساختن MCP Server دیتابیس

حالا بذار عملی بریم سراغش. یه MCP Server می‌سازیم که به PostgreSQL وصل می‌شه و سه تا ابزار داره:

  1. query: اجرای SELECT queryهای امن
  2. list_tables: لیست جدول‌های قابل دسترسی
  3. describe_table: ساختار یه جدول خاص

چرا این سه تا؟ چون AI اول باید بفهمه چه جدول‌هایی هست و ساختارشون چیه، بعد query بزنه. بدون اطلاعات schema، AI کورکورانه query می‌زنه و نتیجه بد می‌گیره.

نکته مهم
یه اشتباه رایج اینه که فقط ابزار query رو می‌سازن. ولی AI بدون دونستن ساختار دیتابیس نمی‌تونه query خوب بزنه. حتماً ابزار schema discovery رو هم اضافه کن.

ابزار list_tables

ساده‌ترین ابزار. لیست جدول‌هایی که AI بهشون دسترسی داره رو برمی‌گردونه. نکته مهم اینه که همه جدول‌ها رو نشون نمی‌ده — فقط اونایی که توی whitelist هستن.

// Allowed tables - only these are visible to AI
const ALLOWED_TABLES = [
  'orders', 'products', 'customers', 'categories'
];

// Tool: list_tables
{
  name: "list_tables",
  description: "List all accessible database tables",
  handler: async () => {
    return ALLOWED_TABLES.map(t => ({ name: t }));
  }
}

ابزار describe_table

ساختار یه جدول رو برمی‌گردونه — اسم ستون‌ها، نوع‌شون و اینکه کدوم primary key هست. این اطلاعات به AI کمک می‌کنه query درست بسازه.

// Tool: describe_table
{
  name: "describe_table",
  inputSchema: {
    type: "object",
    properties: {
      table_name: { type: "string" }
    },
    required: ["table_name"]
  },
  handler: async ({ table_name }) => {
    if (!ALLOWED_TABLES.includes(table_name)) {
      throw new Error("Access denied");
    }
    const result = await db.query(`
      SELECT column_name, data_type, is_nullable
      FROM information_schema.columns
      WHERE table_name = $1
      ORDER BY ordinal_position
    `, [table_name]);
    return result.rows;
  }
}

ابزار query

مهم‌ترین و حساس‌ترین ابزار. چند لایه بررسی داره:

// Tool: query
{
  name: "query",
  inputSchema: {
    type: "object",
    properties: {
      sql: { type: "string", description: "SELECT query to run" }
    },
    required: ["sql"]
  },
  handler: async ({ sql }) => {
    // Layer 1: Only SELECT allowed
    const normalized = sql.trim().toLowerCase();
    if (!normalized.startsWith('select')) {
      throw new Error("Only SELECT queries are allowed");
    }

    // Layer 2: Block dangerous keywords
    const blocked = ['insert','update','delete','drop','alter','create'];
    if (blocked.some(kw => normalized.includes(kw))) {
      throw new Error("Query contains blocked keywords");
    }

    // Layer 3: Add LIMIT if missing
    if (!normalized.includes('limit')) {
      sql = sql + ' LIMIT 1000';
    }

    // Layer 4: Execute with timeout
    const result = await db.query(sql, [], { timeout: 30000 });
    return result.rows;
  }
}
هشدار
فیلتر کردن SQL با بررسی متنی ۱۰۰٪ مطمئن نیست (مثلاً ممکنه کسی از subquery استفاده کنه). برای امنیت بیشتر، حتماً کاربر دیتابیس هم read-only باشه. فیلتر متنی + کاربر محدود = دو لایه امنیت.

مثال عملی: تحلیل فروش

بذار ببینیم عملاً چطور کار می‌کنه. فرض کن این رو از Claude می‌پرسی:

«فروش سه ماهه اول امسال رو با سال قبل مقایسه کن. کدوم دسته‌بندی محصول بیشترین رشد رو داشته؟»

Claude اول list_tables رو صدا می‌زنه تا ببینه چه جدول‌هایی هست. بعد describe_table رو برای orders، products و categories صدا می‌زنه تا ساختارشون رو بفهمه. بعد یه query مناسب می‌سازه:

SELECT c.name as category,
       SUM(CASE WHEN o.created_at >= '2026-01-01' 
            THEN o.total ELSE 0 END) as sales_2026,
       SUM(CASE WHEN o.created_at >= '2025-01-01' 
            AND o.created_at < '2025-04-01' 
            THEN o.total ELSE 0 END) as sales_2025
FROM orders o
JOIN products p ON o.product_id = p.id
JOIN categories c ON p.category_id = c.id
WHERE o.created_at >= '2025-01-01'
GROUP BY c.name
ORDER BY (sales_2026 - sales_2025) DESC

نتیجه رو می‌گیره و یه تحلیل کامل ارائه می‌ده — بدون اینکه تو یه خط SQL بنویسی.

دیتابیس‌های مختلف

تا اینجا از PostgreSQL مثال زدم، ولی MCP Server دیتابیس می‌تونه به هر دیتابیسی وصل بشه:

PostgreSQL: بهترین انتخاب برای شروع. پشتیبانی عالی از JSON، full-text search و queryهای پیچیده.

MySQL/MariaDB: اگه پروژه‌ت از قبل MySQL استفاده می‌کنه، عالیه. فرقی نمی‌کنه — فقط کانکشن و syntax بعضی queryها فرق می‌کنه.

SQLite: برای پروژه‌های کوچک و لوکال. فایل‌بیسه و نصب نمی‌خواد. ولی برای چند کاربر همزمان مناسب نیست.

MongoDB: اگه دیتات NoSQL هست، می‌تونی MCP Server رو طوری بسازی که از aggregation pipeline استفاده کنه. ولی فیلتر امنیتی پیچیده‌تر می‌شه.

توصیه
اگه تازه شروع کردی، با PostgreSQL برو. بیشترین منابع آموزشی و بهترین ابزارهای MCP رو داره. بعداً می‌تونی برای دیتابیس‌های دیگه هم بسازی.

سرورهای آماده

خبر خوب اینه که لازم نیست حتماً از صفر بسازی. چند MCP Server آماده برای دیتابیس هست:

  • @modelcontextprotocol/server-postgres: سرور رسمی Anthropic برای PostgreSQL
  • @modelcontextprotocol/server-sqlite: سرور رسمی برای SQLite
  • سرورهای community: برای MySQL، MongoDB، Redis و خیلی دیتابیس‌های دیگه

اینها نقطه شروع خوبی هستن. می‌تونی مستقیم استفاده کنی یا fork کنی و سفارشی‌سازی کنی.

تنظیم سرور رسمی PostgreSQL

ساده‌ترین راه شروع، استفاده از سرور رسمیه. فقط کافیه توی تنظیمات Claude Desktop اضافه‌ش کنی:

{
  "mcpServers": {
    "postgres": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-postgres",
        "postgresql://readonly_user:password@localhost/mydb"
      ]
    }
  }
}

حتماً از کاربر readonly استفاده کن و رمز رو توی environment variable بذار، نه مستقیم توی config.

بهینه‌سازی عملکرد

وقتی AI شروع به query زدن می‌کنه، بهینه‌سازی مهم می‌شه:

Schema Caching: اطلاعات ساختار جدول‌ها رو cache کن. هر بار از دیتابیس نخون. ساختار جدول‌ها معمولاً تغییر نمی‌کنه.

Query Analysis: قبل از اجرای query، با EXPLAIN بررسی کن چقدر سنگینه. اگه full table scan روی جدول میلیونی داره، هشدار بده.

Result Summarization: وقتی نتیجه خیلی بزرگه، به جای برگردوندن همه ردیف‌ها، یه خلاصه بده. مثلاً «۵۴,۳۲۱ ردیف پیدا شد. ۱۰ تای اول رو نشون می‌دم.»

Connection Pooling: از connection pool استفاده کن تا برای هر query اتصال جدید نسازی. قسمت قبلی این رو بیشتر توضیح دادیم.

حریم خصوصی و حساسیت داده

این بخش خیلی مهمه و اکثر آدم‌ها نادیده‌ش می‌گیرن.

وقتی AI به دیتابیس دسترسی داره، داده‌ها به مدل AI فرستاده می‌شن. اگه از Claude API استفاده می‌کنی، Anthropic گفته که داده‌ها رو برای آموزش استفاده نمی‌کنه — ولی بازم باید حواست به این نکات باشه:

۱. فیلتر داده حساس: ستون‌هایی مثل رمز عبور، شماره کارت بانکی و اطلاعات پزشکی رو از نتایج حذف کن. حتی اگه AI بهشون نیاز نداره، بهتره اصلاً نبینه.

۲. Masking: بعضی داده‌ها مثل شماره تلفن و ایمیل رو می‌تونی mask کنی. مثلاً «0912***4567» به جای شماره کامل.

۳. Row-Level Security: PostgreSQL از Row-Level Security (RLS) پشتیبانی می‌کنه. می‌تونی تنظیم کنی که کاربر read-only فقط ردیف‌های خاصی رو ببینه.

۴. Audit Trail: هر query رو با مشخصات کاربر لاگ کن. اگه مشکلی پیش اومد، باید بتونی ردیابی کنی.

مهم
اگه با داده‌های شخصی کاربران کار می‌کنی (مخصوصاً توی اروپا که GDPR داره)، حتماً قبل از اتصال AI به دیتابیس با تیم حقوقی‌ت مشورت کن. نقض حریم خصوصی می‌تونه جریمه سنگینی داشته باشه.

خطاهای رایج

بذار چند اشتباه رایج رو بگم که خیلی‌ها مرتکب می‌شن:

اشتباه ۱: دسترسی write دادن. «ولی من فقط یه UPDATE ساده می‌خوام!» — نه. اگه واقعاً write لازمه، یه ابزار جداگانه با تایید انسانی بساز.

اشتباه ۲: نداشتن schema discovery. AI بدون دونستن ساختار جدول‌ها، queryهای بد می‌زنه و نتایج بد می‌گیره.

اشتباه ۳: بدون timeout اجرا کردن. یه query سنگین می‌تونه دیتابیست رو قفل کنه. حتماً timeout بذار.

اشتباه ۴: نادیده گرفتن حجم نتایج. اگه query ۱ میلیون ردیف برگردونه، هم حافظه پر می‌شه هم هزینه توکن AI بالا می‌ره. حتماً LIMIT بذار.

اشتباه ۵: اتصال مستقیم به پروداکشن. اول روی یه کپی از دیتابیس (replica) تست کن. مطمئن شو queryها فشار زیادی روی سرور اصلی نمیارن.

جمع‌بندی

وصل کردن MCP به دیتابیس یکی از قدرتمندترین و در عین حال حساس‌ترین کارهایی هست که می‌تونی انجام بدی. کلید موفقیت اینه:

  • Read-only باشه — write فقط با تایید انسانی
  • لایه‌های امنیتی داشته باشه — کاربر محدود + فیلتر query + محدودیت نتایج
  • Schema discovery داشته باشه — AI باید ساختار رو بشناسه
  • داده حساس فیلتر بشه — رمز، کارت بانکی، اطلاعات شخصی
  • همه‌چیز لاگ بشه — برای ردیابی و عیب‌یابی
قسمت بعدی
قسمت بعدی سری درباره ترکیب MCP با RAG (بازیابی تقویت‌شده) هست. یاد می‌گیریم چطور از MCP برای اتصال مدل‌های AI به vector database و جستجوی معنایی استفاده کنیم. منتظر باش!

نظرات

هنوز نظری ثبت نشده. اولین نفر باشید!

نظر خود را بنویسید