MCP للمؤسسات: تسجيل الدخول الموحّد وسجلات التدقيق وأنماط البوابات

تجاوز بروتوكول سياق النموذج (MCP) 110 مليون تنزيل شهري في بداية 2026. ما بدأ كمعيار مفتوح من Anthropic لربط وكلاء الذكاء الاصطناعي بالأدوات الخارجية أصبح النسيج الضام لمنظومة الأتمتة الوكيلية، بمساهمات من OpenAI وGoogle ومئات الشركات.
لكن التبني على نطاق واسع كشف فجوة. معظم دروس MCP تعلّمك كيف تبني خادمًا وتربط عميلًا. تفترض مطورًا واحدًا ومفتاح API واحدًا وبيئة موثوقة. واقع المؤسسات مختلف: مئات خوادم MCP عبر الفرق، وبيانات اعتماد مشتركة، وغياب حوكمة مركزية، ولا سجل تدقيق لما تفعله الوكلاء بالأدوات.
خارطة طريق MCP 2026 تعالج هذا مباشرة، بأولوية جاهزية المؤسسات إلى جانب تطور النقل واتصال الوكلاء ونضج الحوكمة. هذا الدليل يرشدك عبر الركائز الثلاث لـ MCP المؤسسي: المصادقة المتكاملة مع SSO، وسجلات التدقيق المنظّمة، وأنماط بوابات الوكيل.
المتطلبات الأساسية
قبل البدء، تأكد من امتلاكك:
- معرفة عملية بـ MCP (أساسيات الخادم والعميل — راجع دليل بناء خادم MCP بـ TypeScript)
- Node.js 20+ وTypeScript
- مزوّد هوية OAuth 2.0 / OIDC (مثل Keycloak أو Entra ID أو Auth0)
- فهم أساسي للوكلاء العكسيين (Nginx أو Caddy أو بوابات API السحابية)
- Docker لتشغيل البنية التحتية المحلية
ما ستبنيه
نشر MCP جاهز للإنتاج يتضمن:
- مصادقة متكاملة مع SSO — الوكلاء والمستخدمون يصادقون عبر مزوّد الهوية الحالي
- تسجيل تدقيق منظّم — كل استدعاء أداة يُسجّل مع من ولماذا ومتى والنتيجة
- بوابة وكيل — مستوى تحكم مركزي لتحديد المعدل وتطبيق السياسات ونشر التفويض
الجزء 1: تكامل SSO لخوادم MCP
مشكلة مفاتيح API
معظم أمثلة خوادم MCP تستخدم مفاتيح API ثابتة أو رموز حامل. في الإنتاج، هذا يخلق ثلاث مشاكل:
- غياب سياق الهوية: الخادم يعرف أن مفتاحًا صالحًا استُخدم، لكن ليس من استخدمه أو ما يُسمح له بفعله
- انتشار المفاتيح: كل فريق يدير مفاتيحه الخاصة، بدون سياسة تدوير أو إلغاء مركزي
- غياب تكامل SSO: المستخدمون يصادقون بشكل منفصل لأدوات MCP رغم أن لديهم بالفعل بيانات اعتماد مؤسسية
OAuth 2.1 في MCP
أضافت مواصفات MCP دعم OAuth 2.1 في يونيو 2025. بدلاً من إدارة كل عميل MCP لبيانات اعتماده الخاصة، يتم توسيط الوصول عبر طبقة الهوية الحالية لمؤسستك: تسجيل دخول موحّد، رموز محدودة النطاق، وتبقى تكنولوجيا المعلومات على اطلاع.
الخطوة 1: تكوين مزوّد الهوية
أنشئ تطبيق OAuth في مزوّد الهوية. هذا المثال يستخدم Keycloak، لكن النمط ينطبق على Entra ID أو Auth0 أو Okta.
// تكوين عميل Keycloak
// realm: "enterprise"
// client_id: "mcp-gateway"
// client_secret: مخزن في الخزنة
// عناوين إعادة التوجيه: https://mcp-gateway.internal/callback
// النطاقات: openid, profile, mcp:tools:read, mcp:tools:executeحدّد نطاقات مخصصة تُعيّن لصلاحيات MCP:
mcp:tools:read — عرض ووصف الأدوات المتاحة
mcp:tools:execute — استدعاء الأدوات
mcp:resources:read — قراءة موارد MCP
mcp:admin — إدارة تكوين الخادم
الخطوة 2: تنفيذ وسيط المصادقة
أنشئ وسيط مصادقة يتحقق من رموز OAuth قبل أن يصل أي طلب MCP إلى خادمك:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import jwt from "jsonwebtoken";
import jwksClient from "jwks-rsa";
const client = jwksClient({
jwksUri: "https://keycloak.internal/realms/enterprise/protocol/openid-connect/certs",
cache: true,
rateLimit: true,
});
function getSigningKey(kid: string): Promise<string> {
return new Promise((resolve, reject) => {
client.getSigningKey(kid, (err, key) => {
if (err) reject(err);
else resolve(key!.getPublicKey());
});
});
}
interface McpTokenPayload {
sub: string;
email: string;
realm_access: { roles: string[] };
scope: string;
iat: number;
exp: number;
}
async function validateToken(token: string): Promise<McpTokenPayload> {
const decoded = jwt.decode(token, { complete: true });
if (!decoded?.header.kid) throw new Error("رأس رمز غير صالح");
const signingKey = await getSigningKey(decoded.header.kid);
return jwt.verify(token, signingKey, {
audience: "mcp-gateway",
issuer: "https://keycloak.internal/realms/enterprise",
}) as McpTokenPayload;
}الخطوة 3: تفويض الأدوات بناءً على النطاق
غلّف معالجات أدوات MCP بفحوصات التفويض:
const server = new McpServer({
name: "enterprise-tools",
version: "1.0.0",
});
server.tool(
"query_database",
"تشغيل استعلام SQL للقراءة فقط على قاعدة بيانات التحليلات",
{ query: { type: "string", description: "استعلام SQL SELECT" } },
async (args, extra) => {
const token = extra.meta?.authToken as string;
const payload = await validateToken(token);
if (!hasScope(payload, "mcp:tools:execute")) {
return {
content: [{ type: "text", text: "محظور: نطاق mcp:tools:execute مفقود" }],
isError: true,
};
}
await auditLog({
user: payload.email,
tool: "query_database",
args,
timestamp: new Date().toISOString(),
});
const result = await executeReadOnlyQuery(args.query);
return { content: [{ type: "text", text: JSON.stringify(result) }] };
}
);الجزء 2: سجلات التدقيق المنظّمة
لماذا يهم تسجيل التدقيق الآن
يتطلب قانون الذكاء الاصطناعي الأوروبي التسجيل التلقائي والتتبع لأنظمة الذكاء الاصطناعي عالية المخاطر، مع دخول الالتزامات الرئيسية حيز التنفيذ في 2 أغسطس 2026. حتى بدون ضغط تنظيمي، معرفة ما فعلته وكلاء الذكاء الاصطناعي وبأي أدوات وماذا حدث هو حد أدنى من النظافة التشغيلية.
ما يجب تسجيله
كل إدخال تدقيق يجب أن يلتقط:
| الحقل | الوصف | مثال |
|---|---|---|
timestamp | ISO 8601 مع المنطقة الزمنية | 2026-04-23T08:15:32.441Z |
request_id | معرّف تتبع فريد | req_a7b3c9d2 |
user_id | الهوية المصادق عليها | jane@company.com |
agent_id | أي وكيل ذكاء اصطناعي أجرى الاستدعاء | support-bot-v2 |
tool_name | أداة MCP المستدعاة | query_database |
tool_args | المعلمات (مُعقّمة) | تنقية الأسرار |
outcome | نجاح / خطأ / مرفوض | success |
duration_ms | وقت التنفيذ | 234 |
الخطوة 4: تنفيذ مسجّل التدقيق
import { createLogger, format, transports } from "winston";
interface AuditEntry {
timestamp: string;
requestId: string;
userId: string;
agentId?: string;
toolName: string;
toolArgs: Record<string, unknown>;
outcome: "success" | "error" | "denied";
responseSummary?: string;
durationMs?: number;
}
const auditLogger = createLogger({
level: "info",
format: format.combine(format.timestamp(), format.json()),
defaultMeta: { service: "mcp-audit" },
transports: [
new transports.File({
filename: "/var/log/mcp/audit.jsonl",
maxsize: 100 * 1024 * 1024,
maxFiles: 365,
}),
],
});
function sanitizeArgs(args: Record<string, unknown>): Record<string, unknown> {
const sensitive = ["password", "secret", "token", "key", "credential"];
const sanitized = { ...args };
for (const key of Object.keys(sanitized)) {
if (sensitive.some((s) => key.toLowerCase().includes(s))) {
sanitized[key] = "[محجوب]";
}
}
return sanitized;
}الخطوة 5: تغليف جميع معالجات الأدوات
أنشئ دالة عالية المستوى تغلّف كل أداة تلقائيًا بتسجيل التدقيق:
import { randomUUID } from "crypto";
function withAudit(toolName: string, handler: ToolHandler): ToolHandler {
return async (args, extra) => {
const requestId = `req_${randomUUID().slice(0, 8)}`;
const startTime = Date.now();
const token = extra.meta?.authToken as string;
let payload: McpTokenPayload | null = null;
try {
payload = await validateToken(token);
} catch {
await auditLog({
timestamp: new Date().toISOString(),
requestId,
userId: "unknown",
toolName,
toolArgs: args,
outcome: "denied",
responseSummary: "فشل المصادقة",
});
return {
content: [{ type: "text", text: "المصادقة مطلوبة" }],
isError: true,
};
}
try {
const result = await handler(args, extra);
await auditLog({
timestamp: new Date().toISOString(),
requestId,
userId: payload.email,
toolName,
toolArgs: args,
outcome: result.isError ? "error" : "success",
durationMs: Date.now() - startTime,
});
return result;
} catch (err) {
await auditLog({
timestamp: new Date().toISOString(),
requestId,
userId: payload.email,
toolName,
toolArgs: args,
outcome: "error",
responseSummary: String(err),
durationMs: Date.now() - startTime,
});
throw err;
}
};
}الجزء 3: نمط بوابة الوكيل
لماذا البوابة
في الإنتاج، معظم نشر MCP المؤسسي لا ينبغي أن يكون اتصالات مباشرة بين العميل والخادم. وسيط البوابة يوفر:
- نشر التفويض: الخوادم الخلفية تعرف ما كان العميل الأصلي مُفوّضًا لفعله
- تحديد المعدل: منع الوكلاء الجامحين من إرهاق الخدمات الخلفية
- تطبيق السياسات: قواعد مركزية لما هي الأدوات المتاحة لأي أدوار
- اكتشاف الخدمات: العملاء يتصلون بنقطة نهاية واحدة؛ البوابة توجّه للخادم الصحيح
الخطوة 6: بناء البوابة
import express from "express";
import httpProxy from "http-proxy-middleware";
import rateLimit from "express-rate-limit";
const app = express();
const limiter = rateLimit({
windowMs: 60 * 1000,
max: 100,
keyGenerator: (req) => req.headers["x-user-id"] as string || req.ip,
});
app.use(limiter);
app.use(async (req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader?.startsWith("Bearer ")) {
return res.status(401).json({ error: "تفويض مفقود" });
}
try {
const payload = await validateToken(authHeader.slice(7));
req.headers["x-user-id"] = payload.email;
req.headers["x-user-roles"] = payload.realm_access.roles.join(",");
req.headers["x-user-scopes"] = payload.scope;
next();
} catch {
return res.status(401).json({ error: "رمز غير صالح" });
}
});الخطوة 7: سجل الخوادم والتوجيه
interface McpServerEntry {
name: string;
url: string;
healthCheck: string;
allowedRoles: string[];
rateLimit: number;
description: string;
}
const serverRegistry: McpServerEntry[] = [
{
name: "database",
url: "http://mcp-db.internal:3001",
healthCheck: "/health",
allowedRoles: ["db-admin", "data-analyst"],
rateLimit: 50,
description: "أدوات استعلام قاعدة البيانات للقراءة فقط",
},
{
name: "files",
url: "http://mcp-files.internal:3002",
healthCheck: "/health",
allowedRoles: ["developer", "admin"],
rateLimit: 100,
description: "أدوات نظام الملفات والمستندات",
},
{
name: "deploy",
url: "http://mcp-deploy.internal:3003",
healthCheck: "/health",
allowedRoles: ["admin", "devops"],
rateLimit: 10,
description: "أدوات النشر والبنية التحتية",
},
];الخطوة 8: الحوكمة ككود
حدّد سياسات MCP كتكوين تصريحي يعيش في التحكم بالإصدارات:
# mcp-policies.yaml
version: "1.0"
policies:
- name: "database-access"
servers: ["database"]
roles: ["db-admin", "data-analyst"]
scopes: ["mcp:tools:execute"]
rate_limit:
requests_per_minute: 50
tools:
allowed: ["query_database", "list_tables", "describe_table"]
denied: ["drop_table", "truncate"]
- name: "deployment-access"
servers: ["deploy"]
roles: ["admin", "devops"]
scopes: ["mcp:tools:execute", "mcp:admin"]
rate_limit:
requests_per_minute: 10
tools:
allowed: ["deploy_staging", "rollback"]
denied: ["deploy_production"]
approval_required:
- tool: "deploy_production"
approvers: ["platform-lead"]قائمة فحص النشر
قبل الذهاب للإنتاج:
- TLS في كل مكان — من البوابة للعميل ومن البوابة لخوادم MCP
- تدوير الرموز — تكوين رموز وصول قصيرة العمر (15 دقيقة) مع رموز تحديث
- احتفاظ السجلات — تحديد سياسات احتفاظ متوافقة مع متطلبات الامتثال
- فحوصات الصحة — مراقبة صحة خوادم MCP من البوابة
- إدارة الأسرار — تخزين أسرار عميل OAuth في خزنة، وليس في ملفات التكوين
استكشاف الأخطاء وإصلاحها
فشل التحقق من الرمز مع "kid not found": ذاكرة JWKS المؤقتة قد تكون قديمة. أعد تشغيل البوابة بعد تدوير مفاتيح مزوّد الهوية.
البوابة تعيد 502 للوكلاء: خادم MCP الخلفي غير قابل للوصول. تحقق من نقاط نهاية الصحة وسياسات الشبكة.
سجلات التدقيق تفقد إدخالات: تأكد أن مسجّل التدقيق يُفرغ بشكل متزامن قبل إرسال الاستجابة.
الخطوات التالية
- استكشف بروتوكول Google A2A لأنماط اتصال الوكلاء
- راجع دليل بناء خادم MCP بـ TypeScript للأساسيات
- ابنِ عميل MCP بـ TypeScript للاختبار مع بوابتك
الخلاصة
MCP المؤسسي ليس عن إضافة المزيد من الأدوات لوكلاء الذكاء الاصطناعي. إنه عن حوكمة الأدوات الموجودة لديهم بالفعل. تكامل SSO يمنحك سياق الهوية. سجلات التدقيق تمنحك الرؤية. أنماط البوابات تمنحك التحكم. معًا، يحوّلون مجموعة من خوادم MCP غير المدارة إلى بنية تحتية محكومة ومتوافقة وجاهزة للإنتاج.
إذا كانت مؤسستك تتوسع في تبني MCP وتحتاج مساعدة في تنفيذ هذه الأنماط، خدمة تكامل MCP تغطي تصميم البنية ونشر البوابة وتكوين السياسات.
ناقش مشروعك معنا
نحن هنا للمساعدة في احتياجات تطوير الويب الخاصة بك. حدد موعدًا لمناقشة مشروعك وكيف يمكننا مساعدتك.
دعنا نجد أفضل الحلول لاحتياجاتك.
مقالات ذات صلة

بناء حزمة مهارات وكيل متعددة الأدوات لفريقك الهندسي
تعلم كيفية تصميم وبناء وإدارة دليل .agents/skills/ مشترك لمؤسستك الهندسية. يغطي هذا الدليل هندسة المهارات واتفاقيات التسمية والإصدارات وسير عمل الفريق وحوكمة المهارات المؤسسية لحزم مهارات وكلاء البرمجة بالذكاء الاصطناعي.

التحكم الصوتي لـ Cline: VS Code + ElevenLabs MCP
مكّن التفاعل بدون استخدام اليدين مع وكيل Cline AI في VS Code. يرشدك هذا الدرس عبر إنشاء إضافة مساعد صوتي باستخدام ElevenLabs لتحويل الكلام إلى نص عبر بروتوكول سياق النموذج (MCP).

بناء خط أنابيب CI/CD متكامل باستخدام GitHub Actions لتطبيقات Next.js
تعلّم كيف تبني خط أنابيب CI/CD احترافي باستخدام GitHub Actions لتطبيق Next.js — مع فحص الكود تلقائياً واختبارات الوحدات واختبارات E2E والنشر على Vercel.