خادم MCP لنظام إدارة المحتوى: دع وكلاء الذكاء الاصطناعي تقرأ وتكتب المحتوى
قضيت آخر ثلاثة أشهر في بناء خوادم MCP لمشاريع العملاء، وأنا مقتنع الآن بأن هذه هي الطريقة التي سيتم الوصول بها إلى كل نظام إدارة محتوى خلال عامين. ليس من خلال لوحات التحكم. ليس من خلال واجهات برمجية REST التي يستدعيها البشر يدويًا. بل من خلال وكلاء ذكي يفهمون نموذج المحتوى الخاص بك ويمكنهم قراءة وإنشاء وتحديث المحتوى نيابة عنك.
بروتوكول سياق النموذج (MCP) هو معيار مفتوح أطلقت عليه Anthropic في أواخر عام 2024. يوفر للنماذج الذكية طريقة منظمة للتفاعل مع الأدوات والمصادر الخارجية. فكر فيه كمحول عام بين نموذج لغة وأي شيء آخر. قاعدة البيانات الخاصة بك. نظام الملفات الخاص بك. نظام إدارة المحتوى الخاص بك.
تتناول هذه المقالة بناء خوادم MCP لثلاثة واجهات خلفية لأنظمة إدارة محتوى شهيرة: Payload CMS و Supabase (المستخدمة كنظام إدارة محتوى بدون رأس) و WordPress. سنغطي العمارة والكود الفعلي والمشاكل التي واجهتها في الطريق.
جدول المحتويات
- ما هو MCP ولماذا يجب أن تهتم به
- معمارية MCP لتكامل نظام إدارة المحتوى
- بناء خادم MCP لنظام Payload CMS
- بناء خادم MCP للنظام Supabase
- بناء خادم MCP لنظام WordPress
- مقارنة الأساليب الثلاثة
- اعتبارات الأمان
- حالات الاستخدام الواقعية
- الأسئلة الشائعة
ما هو MCP ولماذا يجب أن تهتم به
بروتوكول سياق النموذج هو في الأساس بروتوكول يعتمد على JSON-RPC 2.0 يحدد كيفية تواصل النماذج الذكية مع الأنظمة الخارجية. قبل MCP، إذا كنت تريد من Claude أو GPT التفاعل مع نظام إدارة المحتوى الخاص بك، فستبني تكاملاً مخصصًا لاستدعاء الدوال لكل نموذج. مخططات مختلفة، تدفقات مصادقة مختلفة، كل شيء مختلف.
يوحد MCP هذا. تبني خادم واحد، وأي عميل متوافق مع MCP (Claude Desktop أو Cursor أو Cline أو وكلاء مخصصون) يمكنه الاتصال به.
إليك ما يجعل هذا مثيرًا للاهتمام لعمل نظام إدارة المحتوى بشكل خاص:
- فرق المحتوى يمكنها أن تطلب من الذكاء الاصطناعي "البحث عن جميع منشورات المدونة المنشورة الشهر الماضي التي تذكر React" والحصول على نتائج حقيقية من نظام إدارة محتواهم الفعلي
- المطورون يمكنهم أن يكون لديهم مساعد الترميز الخاص بهم إنشاء وتحديث إدخالات المحتوى دون مغادرة المحرر الخاص بهم
- سير العمل التحريري يمكن أتمتته -- وكيل ذكي يصيغ محتوى ويتحقق منه مقابل دليل الأسلوب الخاص بك وينشره من خلال سير العمل الحالي الخاص بك
يحدد البروتوكول ثلاثة عناصر أساسية:
- الأدوات -- الدوال التي يمكن للذكاء الاصطناعي استدعاؤها (مثل
create_postوupdate_entryوsearch_content) - الموارد -- البيانات التي يمكن للذكاء الاصطناعي قراءتها (مثل مخطط المحتوى الخاص بك والمنشورات الحديثة ومكتبة الوسائط)
- الموجهات -- قوالب موجهات قابلة لإعادة الاستخدام للعمليات الشائعة
لتكامل نظام إدارة المحتوى، ستعمل بشكل أساسي مع الأدوات والموارد.
معمارية MCP لتكامل نظام إدارة المحتوى
قبل أن نكتب الكود، دعنا نفهم العمارة. يجلس خادم MCP بين عميل ذكي ونظام إدارة المحتوى الخاص بك:
[AI Client] <--MCP Protocol--> [MCP Server] <--REST/GraphQL/SDK--> [Your CMS]
(Claude) (stdio/SSE) (Node.js) (HTTP/DB) (Payload/WP/Supabase)
يكشف خادم MCP عن أدوات وموارد تُعين إلى عمليات نظام إدارة المحتوى الخاص بك. يمكن لطبقة النقل أن تكون:
- stdio -- للتطوير المحلي، ينتج عميل الذكاء الاصطناعي خادم MCP كعملية فرعية
- SSE (Server-Sent Events) -- للخوادم البعيدة، يستخدم HTTP مع SSE للبث
- Streamable HTTP -- خيار النقل الأحدث في مراجعة المواصفات لعام 2025
لخوادم نظام إدارة المحتوى، أوصي بالبدء باستخدام stdio للتطوير والانتقال إلى SSE أو Streamable HTTP لنشرات الإنتاج حيث يعمل خادم MCP على البنية الأساسية الخاصة بك جنبًا إلى جنب مع نظام إدارة المحتوى.
هيكل الخادم الأساسي
يتبع كل خادم MCP نفس النمط. إليك الهيكل الأساسي في TypeScript باستخدام حزمة @modelcontextprotocol/sdk الرسمية:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({
name: "my-cms-mcp",
version: "1.0.0",
});
// تحديد أداة
server.tool(
"search_content",
"البحث عن إدخالات المحتوى حسب الاستعلام",
{
query: z.string().describe("استعلام البحث"),
collection: z.string().describe("المجموعة/نوع المنشور للبحث فيه"),
limit: z.number().optional().default(10),
},
async ({ query, collection, limit }) => {
// منطق خاص بنظام إدارة المحتوى هنا
const results = await searchCMS(query, collection, limit);
return {
content: [
{
type: "text",
text: JSON.stringify(results, null, 2),
},
],
};
}
);
// تحديد مورد
server.resource(
"schema",
"cms://schema",
async (uri) => ({
contents: [
{
uri: uri.href,
mimeType: "application/json",
text: JSON.stringify(await getCMSSchema()),
},
],
})
);
const transport = new StdioServerTransport();
await server.connect(transport);
هذا هو الأساس. الآن دعنا نبني تطبيقات حقيقية.
بناء خادم MCP لنظام Payload CMS
Payload هو المفضل لدي لمشاريع headless (ونستخدمه بكثرة في عمل تطوير نظام إدارة المحتوى بدون رأس الخاص بنا). إنه أصلي TypeScript، لديه واجهة برمجية رائعة، وتُعين معمارية المجموعة الخاصة به بشكل جميل إلى أدوات MCP.
إعداد خادم Payload MCP
أولاً، قم بتثبيت المتعلقات:
mkdir payload-mcp-server && cd payload-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node tsx
إليك التطبيق الكامل. واجهة برمجية Payload REST نظيفة بما يكفي حتى أن هذا مباشر بشكل مفاجئ:
// src/index.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const PAYLOAD_URL = process.env.PAYLOAD_URL || "http://localhost:3000";
const PAYLOAD_API_KEY = process.env.PAYLOAD_API_KEY || "";
const headers = {
"Content-Type": "application/json",
Authorization: `users API-Key ${PAYLOAD_API_KEY}`,
};
async function payloadFetch(path: string, options: RequestInit = {}) {
const res = await fetch(`${PAYLOAD_URL}/api${path}`, {
...options,
headers: { ...headers, ...options.headers },
});
if (!res.ok) {
throw new Error(`Payload API error: ${res.status} ${await res.text()}`);
}
return res.json();
}
const server = new McpServer({
name: "payload-cms-mcp",
version: "1.0.0",
});
// قائمة بجميع المجموعات
server.tool(
"list_collections",
"قائمة بجميع مجموعات Payload CMS المتاحة",
{},
async () => {
// لا يمتلك Payload نقطة نهاية meta لهذا بشكل افتراضي،
// لذا نضرب الإعدادات أو نرمز جاهزة المجموعات المعروفة
const collections = ["posts", "pages", "media", "categories"];
return {
content: [{ type: "text", text: JSON.stringify(collections) }],
};
}
);
// البحث/قائمة المستندات في مجموعة
server.tool(
"find_documents",
"البحث عن المستندات في مجموعة Payload مع التصفية الاختيارية",
{
collection: z.string().describe("رمز المجموعة (على سبيل المثال، 'posts' أو 'pages')"),
where: z.string().optional().describe("استعلام Payload where كسلسلة JSON"),
limit: z.number().optional().default(10),
page: z.number().optional().default(1),
sort: z.string().optional().describe("الحقل للفرز حسبه، البادئة بـ - للترتيب التنازلي"),
},
async ({ collection, where, limit, page, sort }) => {
const params = new URLSearchParams();
params.set("limit", String(limit));
params.set("page", String(page));
if (sort) params.set("sort", sort);
if (where) {
try {
const whereObj = JSON.parse(where);
// تحويل إلى تنسيق سلسلة استعلام Payload
for (const [key, val] of Object.entries(whereObj)) {
if (typeof val === "object" && val !== null) {
for (const [op, v] of Object.entries(val as Record<string, unknown>)) {
params.set(`where[${key}][${op}]`, String(v));
}
} else {
params.set(`where[${key}][equals]`, String(val));
}
}
} catch {
return { content: [{ type: "text", text: "JSON where غير صالح" }] };
}
}
const data = await payloadFetch(`/${collection}?${params}`);
return {
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
};
}
);
// الحصول على مستند واحد
server.tool(
"get_document",
"الحصول على مستند واحد من خلال المعرف من مجموعة Payload",
{
collection: z.string(),
id: z.string().describe("معرف المستند"),
},
async ({ collection, id }) => {
const data = await payloadFetch(`/${collection}/${id}`);
return {
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
};
}
);
// إنشاء مستند
server.tool(
"create_document",
"إنشاء مستند جديد في مجموعة Payload",
{
collection: z.string(),
data: z.string().describe("بيانات المستند كسلسلة JSON"),
},
async ({ collection, data }) => {
const result = await payloadFetch(`/${collection}`, {
method: "POST",
body: data,
});
return {
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
};
}
);
// تحديث مستند
server.tool(
"update_document",
"تحديث مستند موجود في مجموعة Payload",
{
collection: z.string(),
id: z.string(),
data: z.string().describe("بيانات المستند الجزئية كسلسلة JSON"),
},
async ({ collection, id, data }) => {
const result = await payloadFetch(`/${collection}/${id}`, {
method: "PATCH",
body: data,
});
return {
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
};
}
);
const transport = new StdioServerTransport();
await server.connect(transport);
الاتصال بـ Claude Desktop
أضف هذا إلى إعدادات Claude Desktop الخاصة بك (~/Library/Application Support/Claude/claude_desktop_config.json على Mac):
{
"mcpServers": {
"payload-cms": {
"command": "npx",
"args": ["tsx", "/path/to/payload-mcp-server/src/index.ts"],
"env": {
"PAYLOAD_URL": "http://localhost:3000",
"PAYLOAD_API_KEY": "your-api-key-here"
}
}
}
}
أعد تشغيل Claude Desktop، وآنذاك يمكنك طلب أشياء مثل "ابحث عن جميع مسودات المنشورات في نظام إدارة المحتوى الخاص بي" أو "إنشاء منشور مدونة جديد حول خوادم MCP."
بناء خادم MCP للنظام Supabase
Supabase مثير للاهتمام لأنه ليس نظام إدارة محتوى من حيث الصندوق -- إنها قاعدة بيانات Postgres مع واجهة برمجية REST. لكن الكثير من الفرق تستخدمه كواحد، خاصة مع لوحات التحكم المخصصة المدمجة في Next.js (شيء نفعله بانتظام في ممارسة تطوير Next.js الخاصة بنا).
خادم Supabase MCP هو في الواقع الأقوى من الثلاثة لأن لديك وصول SQL مباشر.
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { createClient } from "@supabase/supabase-js";
import { z } from "zod";
const supabase = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY! // استخدم مفتاح خدمة لجانب الخادم
);
const server = new McpServer({
name: "supabase-cms-mcp",
version: "1.0.0",
});
// قائمة بجميع الجداول (أنواع المحتوى)
server.tool(
"list_tables",
"قائمة بجميع الجداول في المخطط العام",
{},
async () => {
const { data, error } = await supabase.rpc("get_tables");
// ستحتاج إلى دالة Postgres لهذا، أو استخدم:
const { data: tables } = await supabase
.from("information_schema.tables" as any)
.select("table_name")
.eq("table_schema", "public");
return {
content: [{ type: "text", text: JSON.stringify(tables, null, 2) }],
};
}
);
// استعلام المحتوى مع المرشحات
server.tool(
"query_content",
"استعلام الصفوف من جدول مع المرشحات الاختيارية",
{
table: z.string().describe("اسم الجدول"),
select: z.string().optional().default("*").describe("الأعمدة المراد اختيارها"),
filters: z.array(z.object({
column: z.string(),
operator: z.enum(["eq", "neq", "gt", "lt", "gte", "lte", "like", "ilike", "is"]),
value: z.string(),
})).optional().describe("مصفوفة من شروط التصفية"),
limit: z.number().optional().default(20),
orderBy: z.string().optional(),
ascending: z.boolean().optional().default(false),
},
async ({ table, select, filters, limit, orderBy, ascending }) => {
let query = supabase.from(table).select(select).limit(limit);
if (filters) {
for (const f of filters) {
query = query.filter(f.column, f.operator, f.value);
}
}
if (orderBy) {
query = query.order(orderBy, { ascending });
}
const { data, error } = await query;
if (error) {
return { content: [{ type: "text", text: `خطأ: ${error.message}` }] };
}
return {
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
};
}
);
// إدراج المحتوى
server.tool(
"insert_row",
"إدراج صف جديد في جدول",
{
table: z.string(),
data: z.string().describe("بيانات الصف كسلسلة JSON"),
},
async ({ table, data: rowData }) => {
const parsed = JSON.parse(rowData);
const { data, error } = await supabase.from(table).insert(parsed).select();
if (error) {
return { content: [{ type: "text", text: `خطأ: ${error.message}` }] };
}
return {
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
};
}
);
// البحث النصي الكامل (ميزة Supabase الحاسمة لاستخدام نظام إدارة المحتوى)
server.tool(
"full_text_search",
"إجراء بحث نصي كامل على عمود جدول",
{
table: z.string(),
column: z.string().describe("العمود مع فهرس tsvector"),
query: z.string().describe("استعلام البحث"),
limit: z.number().optional().default(10),
},
async ({ table, column, query, limit }) => {
const { data, error } = await supabase
.from(table)
.select()
.textSearch(column, query)
.limit(limit);
if (error) {
return { content: [{ type: "text", text: `خطأ: ${error.message}` }] };
}
return {
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
};
}
);
const transport = new StdioServerTransport();
await server.connect(transport);
شيء واحد أحبه في نهج Supabase: نظرًا لأن Supabase يكشف عن مخطط Postgres الخاص بك، يمكنك إنشاء مورد يعطي الذكاء الاصطناعي تعريف المخطط الكامل الخاص بك. يعرف الذكاء الاصطناعي بعد ذلك بالضبط ما هي الحقول الموجودة وما هي أنواعها وكيفية ارتباط الجداول ببعضها البعض. هذا يجعل استعلاماته أكثر دقة بكثير.
بناء خادم MCP لنظام WordPress
WordPress. لا يزال يشغل 43٪ من الويب في عام 2025. أحبه أم لا، ستصادفه.
واجهة برمجية WordPress REST سليمة فعلاً للتكامل مع MCP. الجزء الصعب هو المصادقة -- يمتلك WordPress مثل خمس طرق مصادقة مختلفة وليس أي منها رائع.
لخوادم MCP، أوصي بكلمات مرور التطبيق (المدمجة في WordPress منذ 5.6):
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const WP_URL = process.env.WP_URL!;
const WP_USER = process.env.WP_USER!;
const WP_APP_PASSWORD = process.env.WP_APP_PASSWORD!;
const authHeader = `Basic ${Buffer.from(`${WP_USER}:${WP_APP_PASSWORD}`).toString("base64")}`;
async function wpFetch(endpoint: string, options: RequestInit = {}) {
const res = await fetch(`${WP_URL}/wp-json/wp/v2${endpoint}`, {
...options,
headers: {
"Content-Type": "application/json",
Authorization: authHeader,
...options.headers,
},
});
if (!res.ok) {
throw new Error(`WP API error: ${res.status} ${await res.text()}`);
}
return res.json();
}
const server = new McpServer({
name: "wordpress-mcp",
version: "1.0.0",
});
server.tool(
"search_posts",
"البحث عن منشورات WordPress",
{
search: z.string().optional().describe("استعلام البحث"),
status: z.enum(["publish", "draft", "pending", "private", "any"]).optional().default("any"),
per_page: z.number().optional().default(10),
categories: z.array(z.number()).optional(),
tags: z.array(z.number()).optional(),
after: z.string().optional().describe("تاريخ ISO 8601 -- فقط المنشورات بعد هذا التاريخ"),
before: z.string().optional().describe("تاريخ ISO 8601 -- فقط المنشورات قبل هذا التاريخ"),
},
async (params) => {
const searchParams = new URLSearchParams();
if (params.search) searchParams.set("search", params.search);
if (params.status) searchParams.set("status", params.status);
searchParams.set("per_page", String(params.per_page));
if (params.categories) searchParams.set("categories", params.categories.join(","));
if (params.tags) searchParams.set("tags", params.tags.join(","));
if (params.after) searchParams.set("after", params.after);
if (params.before) searchParams.set("before", params.before);
const posts = await wpFetch(`/posts?${searchParams}`);
// حذف HTML من المحتوى للحصول على استهلاك أنظف للذكاء الاصطناعي
const cleaned = posts.map((p: any) => ({
id: p.id,
title: p.title.rendered,
slug: p.slug,
status: p.status,
date: p.date,
excerpt: p.excerpt.rendered.replace(/<[^>]*>/g, ""),
content: p.content.rendered.replace(/<[^>]*>/g, ""),
categories: p.categories,
tags: p.tags,
}));
return {
content: [{ type: "text", text: JSON.stringify(cleaned, null, 2) }],
};
}
);
server.tool(
"create_post",
"إنشاء منشور WordPress جديد",
{
title: z.string(),
content: z.string().describe("محتوى المنشور بصيغة HTML"),
status: z.enum(["publish", "draft", "pending"]).optional().default("draft"),
categories: z.array(z.number()).optional(),
tags: z.array(z.number()).optional(),
excerpt: z.string().optional(),
},
async (params) => {
const result = await wpFetch("/posts", {
method: "POST",
body: JSON.stringify(params),
});
return {
content: [{
type: "text",
text: `تم إنشاء المنشور "${result.title.rendered}" (المعرف: ${result.id}، الحالة: ${result.status})`,
}],
};
}
);
server.tool(
"update_post",
"تحديث منشور WordPress موجود",
{
id: z.number().describe("معرف المنشور"),
title: z.string().optional(),
content: z.string().optional(),
status: z.enum(["publish", "draft", "pending", "trash"]).optional(),
excerpt: z.string().optional(),
},
async ({ id, ...updates }) => {
const result = await wpFetch(`/posts/${id}`, {
method: "POST",
body: JSON.stringify(updates),
});
return {
content: [{
type: "text",
text: `تم تحديث المنشور "${result.title.rendered}" (المعرف: ${result.id})`,
}],
};
}
);
const transport = new StdioServerTransport();
await server.connect(transport);
أكبر عائق في WordPress MCP: يعود المحتوى كـ HTML معروض. ستريد حذف العلامات للسياق الخاص بالذكاء الاصطناعي أو ستحرق الرموز على علامات <p>. تعلمت هذا بطريقة صعبة بعد مراقبة Claude تحرق 50 ألف رمز عند قراءة خمس منشورات مدونة.
مقارنة الأساليب الثلاثة
| الميزة | Payload CMS | Supabase | WordPress |
|---|---|---|---|
| تعقيد المصادقة | بسيط (مفاتيح API) | بسيط (مفتاح دور الخدمة) | متوسط (كلمات مرور التطبيق) |
| الوعي بالمخطط | جيد (مجموعات مكتوبة) | ممتاز (مخطط Postgres كامل) | ضعيف (لا توجد نقطة نهاية المخطط) |
| تنسيق المحتوى | JSON نظيف | JSON نظيف | يحتوي على HTML، يحتاج إلى تنقية |
| دعم الكتابة | ممتاز | ممتاز | جيد (بعض الغرابة مع الكتل) |
| معالجة الوسائط | التحميل عبر API | واجهة برمجية التخزين | نقطة نهاية وسائط REST |
| مرونة الاستعلام | جيد (استعلامات Payload) | ممتاز (تصفية مستوى SQL) | محدود (معاملات WP_Query) |
| خيار ذاتي الاستضافة | نعم | نعم (أو سحابة) | نعم |
| وقت الإعداد النموذجي | 1-2 ساعة | 1-2 ساعة | 2-3 ساعات |
| الأفضل لـ | مشاريع headless حديثة | هياكل محتوى مخصصة | مواقع WP الموجودة |
اعتبارات الأمان
هذا هو القسم الذي كادت أن أنسى كتابته، وهو يعتبر الأكثر أهمية.
عندما تعطي وكيل ذكي حق الوصول للكتابة إلى نظام إدارة المحتوى الخاص بك، فأنت تثق به بعدم حذف كل شيء. إليك كيفية عدم الاحتراق:
مبدأ أقل صلاحيات
أنشئ مستخدم API/مفتاح مخصص لخادم MCP مع الحد الأدنى من الأذونات. في Payload، أنشئ دورًا يمكنه فقط الوصول إلى مجموعات محددة. في Supabase، استخدم سياسات Row Level Security. في WordPress، أنشئ مستخدمًا بدور المؤلف وليس المسؤول.
أضف تأكيدًا للعمليات التدميرية
أضيف دائمًا معاملة dryRun إلى أدوات الإنشاء/التحديث/الحذف. عندما يتم تعيينها على true، تُرجع الأداة ما سيحدث دون القيام به فعليًا. يمكن للذكاء الاصطناعي بعد ذلك التأكيد مع المستخدم قبل المتابعة.
server.tool(
"delete_document",
"حذف مستند (استخدم dryRun أولاً!)",
{
collection: z.string(),
id: z.string(),
dryRun: z.boolean().default(true).describe("إذا كانت true، معاينة فقط الحذف"),
},
async ({ collection, id, dryRun }) => {
const doc = await payloadFetch(`/${collection}/${id}`);
if (dryRun) {
return {
content: [{
type: "text",
text: `تشغيل جاف: سيحذف "${doc.title}" (${id}) من ${collection}`,
}],
};
}
await payloadFetch(`/${collection}/${id}`, { method: "DELETE" });
return {
content: [{ type: "text", text: `تم حذف "${doc.title}" (${id})` }],
};
}
);
تحديد السعة وتسجيل التدقيق
قم بتسجيل كل استدعاء أداة. بجدية. ستريد معرفة ما فعله وكيل الذكاء الاصطناعي في الساعة 2 صباحًا عندما يسأل محرر المحتوى لماذا يوجد 47 منشور مسودة جديد حول البطاريق.
لا تفضح بيانات اعتماد قاعدة البيانات مباشرة
خادم MCP هو الحد. الذكاء الاصطناعي لا يرى أبدًا كلمة مرور قاعدة البيانات أو مفتاح API الخاص بك -- إنه يرى فقط الأدوات التي تكشفها.
حالات الاستخدام الواقعية
إليك الأنماط التي رأيتها تعمل بشكل جيد في الإنتاج:
ترحيل المحتوى: وكيل ذكي يقرأ المحتوى من موقع WordPress القديم، ويحوله ليطابق مخطط Payload الجديد، وينشئ إدخالات في نظام إدارة المحتوى الجديد. قمنا بهذا لعميل ينقل ~3000 منشور. ما كان سيستغرق أسابيع من العمل اليدوي استغرق يوم ونصف مع مراجعة بشرية.
تدقيق SEO: وكيل يقرأ جميع المحتوى المنشور، ويتحقق من وصف meta المفقود والمحتوى الرقيق والروابط الداخلية المكسورة. يكتب نتائجه مرة أخرى كتقرير منظم في نظام إدارة المحتوى.
تحديثات المحتوى بالجملة: "تغيير جميع المراجع من 'اسم العلامة التجارية القديمة' إلى 'اسم العلامة التجارية الجديدة' عبر جميع الصفحات المنشورة." يقرأ الوكيل ويجد ويقترح التغييرات ويحدّث مع موافقة بشرية.
إدارة تقويم المحتوى: وكيل يعرف جدول النشر الخاص بك ويتحقق مما هو في مسودة ويصدر تنبيهات للفريق حول المواعيد النهائية القادمة -- كل شيء بقراءة بيانات نظام إدارة المحتوى.
إذا كنت تبني شيئًا من هذا القبيل وتريد مساعدة، فلدينا خبرة عميقة بجميع الأنظمة الثلاثة في ممارسة نظام إدارة المحتوى بدون رأس الخاصة بنا. يمكنك أيضًا التحقق من صفحة التسعير لديك للحصول على فكرة عما يكلف مشروع من هذا القبيل.
الأسئلة الشائعة
ما هو بروتوكول سياق النموذج (MCP)؟ MCP هو بروتوكول مفتوح أنشأته Anthropic والذي يوحد كيفية تفاعل النماذج الذكية مع مصادر البيانات والأدوات الخارجية. يستخدم JSON-RPC 2.0 ويحدد معمارية عميل-خادم حيث تتصل تطبيقات الذكاء الاصطناعي (العملاء) بخوادم تكشف عن الأدوات والموارد والموجهات. فكر فيه كمنفذ USB-C للذكاء الاصطناعي -- واجهة معيار واحدة تتصل بأنظمة مختلفة كثيرة.
هل يمكنني استخدام MCP مع ChatGPT أم فقط Claude؟ تم إنشاء MCP بواسطة Anthropic، لذا فإن Claude لديها أفضل دعم أصلي عبر Claude Desktop والـ API. ومع ذلك، البروتوكول مفتوح، وتوجد عملاء MCP لمنصات أخرى. أعلنت OpenAI عن دعم MCP في مارس 2025. Cursor و Cline و Windsurf وعدة أدوات مطور أخرى تدعم أيضًا MCP. يعمل الخادم الخاص بك مع أي عميل متوافق.
هل من الآمن إعطاء وكلاء ذكي حق الوصول للكتابة إلى نظام إدارة المحتوى الخاص بي؟ يمكن أن تكون، مع الحواجز المناسبة. استخدم بيانات اعتماد API مخصصة مع الحد الأدنى من الأذونات، نفذ أوضاع جاهزة للعمليات التدميرية، أضف تسجيل التدقيق، وفكر في طلب موافقة بشرية لإجراءات النشر. لا تعطي خادم MCP وصول مستوى المسؤول. تعامل معها كما تتعامل مع أي تكامل تابع -- مع حدود الثقة المناسبة.
هل أحتاج إلى استضافة خادم MCP بشكل منفصل عن نظام إدارة المحتوى الخاص بي؟ لنقل stdio (التطوير المحلي)، يعمل خادم MCP كعملية فرعية على جهازك المحلي. لاستخدام الإنتاج مع الوصول البعيد، ستحتاج إلى استضافته في مكان ما -- يمكن أن يكون على نفس الخادم مثل نظام إدارة المحتوى الخاص بك، في حاوية Docker بجانبه، أو كخدمة منفصلة. الكمون بين خادم MCP ونظام إدارة المحتوى الخاص بك مهم، لذا فإن تحديد موقعهما معًا أمر مثالي.
كيف يقارن MCP باستخدام واجهة برمجية CMS REST مباشرة مع استدعاء الدوال؟ يضيف MCP طبقة واجهة معيارية. مع استدعاء الدوال الخام، تحدد مخططات مخصصة لكل مزود ذكاء اصطناعي، تتعامل مع المصادقة بشكل مختلف لكل منها، وتعيد بناء عندما يغير المزودون API الخاص بهم. يعطيك MCP خادم واحد يعمل مع أي عميل متوافق. كما يتعامل مع النقل وتنسيق الخطأ واكتشاف الموارد بطريقة موحدة. لتكامل واحد، قد لا يكون الحمل الزائد يستحق الأمر. لأي شيء ستعيد استخدامه، فهو بالتأكيد يستحق.
أي نظام إدارة محتوى يعمل بشكل أفضل مع MCP؟ Supabase يعطيك أكثر المرونة لأن لديك وصول مستوى قاعدة البيانات المباشر والاستفسار الكامل للمخطط. نظام Payload CMS ممتاز لأن نهجه الأول في TypeScript واجهة برمجية نظيفة خريطة بشكل طبيعي إلى أدوات MCP. يعمل WordPress بشكل جيد لكن يتطلب المزيد من تنظيف محتوى HTML وله واجهة برمجية استعلام أقل مرونة. يعتمد الخيار "الأفضل" على المكدس الحالي الخاص بك.
هل يمكنني استخدام MCP لإدارة تحميلات الوسائط في نظام إدارة المحتوى الخاص بي؟
نعم، على الرغم من أنه يتطلب مزيدًا من العمل. لـ Payload و WordPress، يمكنك إنشاء أدوات تقبل بيانات الملفات المرمزة بـ base64 أو عناوين URL واستخدام واجهات برمجية التحميل ذات الصلة. بالنسبة إلى Supabase، ستستخدم واجهة برمجية التخزين. أوصي بإنشاء أدوات upload_media و attach_media منفصلة بدلاً من محاولة التعامل مع تحميلات الملفات داخل أدوات إنشاء المحتوى.
كم تكلفة تشغيل خادم MCP؟ خادم MCP نفسه خفيف الوزن -- عملية Node.js بسيطة تستخدم موارد قليلة. التكلفة الحقيقية موجودة في رموز الذكاء الاصطناعي المستهلكة عندما يقرأ وكيلك ويكتب محتوى. قد تستخدم عملية محتوى نموذجية 2000-10000 رمز اعتمادًا على كمية المحتوى الجاري معالجته. بأسعار 2025 الحالية (Claude Sonnet عند $3/$15 لكل مليون رمز إدخال/إخراج)، هذا أجزاء من السنت لكل عملية. تكلفة البنية الأساسية لاستضافة خادم MCP ضئيلة -- خادم VPS صغير أو حاوية أكثر من كافية.