البرمجياتالدليل 3 من 4
ما هو MCP
آخر تحقّق من المصادر في .
كتبت أداة لتطبيقك — دالّة تبحث عن طلبيّة مثلاً — والنموذج يستدعيها. ثمّ أردت الأداة نفسها داخل تطبيق ذكاء اصطناعيّ ثانٍ، وثالث، وكلّ واحد يطلبها بصيغته هو وبطريقة ربطه هو. فتجد نفسك تكتب الأداة نفسها مرّات، مرّة لكلّ تطبيق، وتلاحق النسخ كلّها كي تبقى متطابقة. وMCP وُجد كي تكتبها مرّة واحدة.
MCP (بروتوكول سياق النموذج) معيار مفتوح المصدر لوصل تطبيقات الذكاء الاصطناعيّ بالأنظمة الخارجيّة. ووثائقه نفسها تشبّهه بمنفذ USB-C لتطبيقات الذكاء الاصطناعيّ : شكل واحد للقابس، فالأداة المبنيّة على المعيار تركب في أيّ تطبيق يتكلّمه. وعمليّاً يعني ذلك برنامجاً صغيراً —خادم MCP — يقدّم أداتك، ومجموعة ثابتة من الرسائل يستطيع أيّ تطبيق أن يرسلها إليه ليعرف ما الأداة وليستدعيها.
وهذا الدليل يبني ذلك بالضبط، بلا شيء غير Node. ستكتب خادماً يقدّم أداة واحدة — أداة البحث عن الطلبيّة نفسها التي في دليل هذا الموقع ما هو استخدام الأدوات — وتكلّمه بيدك، ثمّ تكتب جهة العميل التي يحتويها تطبيق الذكاء الاصطناعيّ، وتستدعي الأداة من خلالها. كلّ صيغة رسالة في هذه الصفحة مقتبسة من مواصفة MCP، وكلّ مخرج هو ما طبعته الملفّات حين شُغّلت.
وتنبيه قبل أن تبدأ، لأنّه يوفّر عليك بعد ظهر كامل. إصدار بروتوكول MCP الحاليّ هو 2026-07-28 ، وقد غيّر الطريقة التي تبدأ بها المحادثة مع الخادم. فمراجعات البروتوكول السابقة كانت تنشئ جلسة مرتبطة بالاتّصال عبر مصافحة initialize ؛ أمّا هذه المراجعة فلا مصافحة فيها أصلاً. وكثير ممّا ستجده مكتوباً عن MCP يصف الطريقة القديمة. هذا الدليل يتبع الحاليّة، وقسم الأخطاء الشائعة يريك ما يحدث حين تلتقي الاثنتان.
بنهاية هذا الدليل ستقدر
- تكتب خادم MCP يقدّم أداة واحدة، وترسل إليه رسالة بيدك لترى بالضبط بماذا يجيب.
- تكتب جهة العميل التي تطلق الخادم، وتسأله عمّا يقدّم، وتقرأ تعريف أداته.
- تستدعي الأداة عبر MCP، وتفرّق بين نوعَي الخطأ اللذين يعرّفهما MCP — الذي يستطيع النموذج إصلاحه والذي لا يستطيع.
- تقول أين ينتهي MCP ويبدأ النموذج: أيّ جزء يقرّر استدعاء الأداة، وأيّ جزء يرسل الاستدعاء، وأيّ جزء ينفّذه.
قبل أن تبدأ
تحتاج شيئين، ولا يكلّفك أيّ منهما شيئاً.
- Node.js إصدار 22 أو أحدث. شغّل
node --version. يطبع إصداراً مثلv24.14.1، وهو الإصدار الذي جاءت منه المخرجات في هذه الصفحة. إن طبع رسالة خطأ، نزّل Node.js من موقعه الرسميّ. - طرفيّة في مجلّد فارغ. شغّل
mkdir mcp-order-deskثمّcd mcp-order-desk. ستنشئ فيه ملفّين:server.mjsوclient.mjs.
ولا مفتاح في هذا الدليل، لا على ويندوز ولا على Mac، لأنّ لا شيء هنا يستدعي نموذجاً أو يخرج من جهازك: الخادم والعميل يتكلّمان عبر دخل الطرفيّة وخرجها. ولا شيء يُثبَّت أيضاً — لا مكتبة MCP ولا حزمة — لأنّ المقصود أن ترى الرسائل نفسها.
الخطوة 1 — اكتب خادماً وكلّمه بيدك
أنشئ ملفّاً اسمه server.mjs وضع فيه هذا:
serverimport { createInterface } from 'node:readline';
// The protocol revision this server speaks: MCP's current one.
const VERSION = '2026-07-28';
// The shop's order system, and the one tool that reads it — the same as in "What Tool Use Is".
const ORDERS = {
'1042': { status: 'shipped', carrier: 'DHL', expected_delivery: '2026-09-14' },
'1043': { status: 'packed', carrier: null, expected_delivery: '2026-09-16' },
};
const getOrderStatus = {
name: 'get_order_status',
description:
'Look up one order in the shop\'s order system by its order number. Returns the order\'s current ' +
'status (packed, shipped or delivered), the carrier once it has shipped, and the expected delivery ' +
'date. Returns an error for an order number that does not exist.',
inputSchema: {
type: 'object',
properties: {
order_id: { type: 'string', description: 'The order number as the customer sees it, digits only, for example "1042".' },
},
required: ['order_id'],
},
};
// One request in, one reply out. Every request names its protocol version in _meta.
function reply(request) {
const result = (fields) => ({ jsonrpc: '2.0', id: request.id, result: { resultType: 'complete', ...fields } });
const error = (code, message, data) => ({ jsonrpc: '2.0', id: request.id, error: { code, message, ...(data && { data }) } });
const requested = request.params?._meta?.['io.modelcontextprotocol/protocolVersion'];
if (requested !== VERSION) {
return error(-32022, 'Unsupported protocol version', { supported: [VERSION], requested: requested ?? null });
}
if (request.method === 'server/discover') {
return result({
supportedVersions: [VERSION],
capabilities: { tools: {} },
_meta: { 'io.modelcontextprotocol/serverInfo': { name: 'order-status', version: '1.0.0' } },
});
}
if (request.method === 'tools/list') return result({ tools: [getOrderStatus] });
if (request.method === 'tools/call') {
if (request.params.name !== getOrderStatus.name) return error(-32602, `Unknown tool: ${request.params.name}`);
const order = ORDERS[request.params.arguments?.order_id];
const text = JSON.stringify(order ?? { error: `no order numbered ${request.params.arguments?.order_id}` });
return result({ content: [{ type: 'text', text }], isError: order === undefined });
}
return error(-32601, `Method not found: ${request.method}`);
}
// The stdio transport: read one JSON-RPC message per line on stdin, write one per line on stdout,
// and write nothing else there. When the client closes stdin, the conversation is over.
const lines = createInterface({ input: process.stdin });
lines.on('line', (line) => process.stdout.write(JSON.stringify(reply(JSON.parse(line))) + '\n'));
lines.on('close', () => process.exit(0));
المخرجات
{"jsonrpc":"2.0","id":1,"result":{"resultType":"complete","supportedVersions":["2026-07-28"],"capabilities":{"tools":{}},"_meta":{"io.modelcontextprotocol/serverInfo":{"name":"order-status","version":"1.0.0"}}}}
اقرأه من الأسفل إلى الأعلى، لأنّ الأسفل هو ما يجعله خادم MCP. فلـMCP ناقلان قياسيّان لرسائله. الأوّل stdio: رسائل تفصل بينها أسطر جديدة عبر المجاري القياسيّة لعمليّة فرعيّة يطلقها العميل. والثاني Streamable HTTP، وفيه كلّ رسالة طلب HTTP POST إلى نقطة MCP واحدة. وهذا الخادم يستعمل stdio. ففي ناقل stdio يطلق العميل خادم MCP عمليّةً فرعيّة ، والأسطر الثلاثة الأخيرة هي كلّ ما على الخادم في ذلك: اقرأ سطراً، وأجب بسطر.
والرسائل من نوع JSON-RPC، وهو معيار صغير للطلبات والردود يكتبها كائنات JSON. فالبروتوكول الأساسيّ يستعمل صيغة رسائل JSON-RPC، وطلبات مستقلّة قائمة بذاتها، والتفاوض على القدرات مع كلّ طلب. و«قائمة بذاتها» هي ما تغيّر عن المراجعات القديمة، وتراه فيreply: أوّل ما تفعله أنّها تقرأ إصدار البروتوكول من الطلب نفسه، من _meta، لأنّ كلّ طلب يحمل إصدار البروتوكول وقدرات العميل في حقول _meta.io.modelcontextprotocol/*. فلا رسالة سابقة يمكن أن يكون الخادم تذكّره منها.
والآن شغّله بالأمر node server.mjs. لا يطبع شيئاً وينتظر: إنّه يصغي إلى دخله. الصق هذا السطر الواحد واضغط Enter:
{"id":1,"jsonrpc":"2.0","method":"server/discover","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientCapabilities":{}}}}
فيجيب الخادم بسطر واحد. هذا ما طبعه:
{"jsonrpc":"2.0","id":1,"result":{"resultType":"complete","supportedVersions":["2026-07-28"],"capabilities":{"tools":{}},"_meta":{"io.modelcontextprotocol/serverInfo":{"name":"order-status","version":"1.0.0"}}}}
اقرأه حقلاً حقلاً:
"jsonrpc":"2.0"و"id":1— ردّ JSON-RPC، وidفيه يطابق"id":1الذي أرسلته، وبهذا يربط العميل كلّ ردّ بطلبه حين تكون عدّة طلبات في الطريق."resultType":"complete"— انتهى الطلب في هذا الردّ الواحد."supportedVersions":["2026-07-28"]— إصدارات البروتوكول التي يتكلّمها هذا الخادم. وهي واحد."capabilities":{"tools":{}}— ما يقدّمه: أدوات، ولا شيء غيرها."_meta":{"io.modelcontextprotocol/serverInfo":{"name":"order-status","version":"1.0.0"}}— اسمه وإصداره، كما يصف هو نفسه.
والرسالة التي أرسلتها هي server/discover. وهي تتيح للعميل أن يسأل الخادم عن إصدارات البروتوكول التي يدعمها وقدراته وهويّته قبل أيّ طلب آخر، وعلى كلّ خادم أن يطبّقها. إنّها طريقة لسؤال «من أنت وماذا تستطيع» في جولة واحدة، مع أنّ استدعاءها اختياريّ للعميل : فالعميل الذي يعرف الخادم مسبقاً يستطيع أن يذهب إلى أدواته مباشرةً.
ولتوقف الخادم، اضغط Ctrl+C. أمّا في الخطوة 2 فيفعل العميل شيئاً ألطف: يغلق دخل الخادم حين لا يبقى عنده ما يسأله. والسطر الأخير في الخادم يستجيب لذلك، والمواصفة تطلبه — على الخادم أن يخرج فوراً حين يُغلق دخله القياسيّ.
وهناك قاعدتان يتبعهما الخادم يسهل أن تفوتاك لأنّهما عمّا لايفعله. تفصل بين الرسائل أسطر جديدة، ولا يجوز أن تحتوي الرسالة سطراً جديداً داخلها ، ولهذا يكتب الخادمJSON.stringify(...) بلا مسافات بادئة، ثمّ \nواحداً بعده. ولا يجوز للخادم أن يكتب على stdout أيّ شيء ليس رسالة MCP صالحة — لا تحيّة، ولا سطر تنقيح. وقسم الأخطاء الشائعة يعود إلى هذه القاعدة.
الخطوة 2 — اكتب العميل الذي يطلق الخادم
تطبيق الذكاء الاصطناعيّ لا يلصق أسطراً في طرفيّة. إنّه يشغّل الخادم بنفسه ويكلّمه من الشيفرة، وتلك الشيفرة هي عميل MCP. أنشئ ملفّاً اسمه client.mjs بجانب server.mjs وضع فيه هذا:
clientimport { spawn } from 'node:child_process';
import { createInterface } from 'node:readline';
import { setImmediate } from 'node:timers';
// Launch the server as a child process — MCP's stdio transport. Requests go in on its stdin and
// replies come back on its stdout, one JSON object per line.
const server = spawn(process.execPath, ['server.mjs'], { stdio: ['pipe', 'pipe', 'inherit'] });
const waiting = new Map();
createInterface({ input: server.stdout }).on('line', (line) => {
const message = JSON.parse(line);
waiting.get(message.id)(message);
waiting.delete(message.id);
// Nothing left to ask: close the server's input, which is how a client says it is done.
setImmediate(() => {
if (waiting.size === 0 && !server.stdin.writableEnded) server.stdin.end();
});
});
// Every request carries the protocol version, the client's capabilities and its name in _meta.
let nextId = 1;
function request(method, params = {}) {
const id = nextId++;
const _meta = {
'io.modelcontextprotocol/protocolVersion': '2026-07-28',
'io.modelcontextprotocol/clientInfo': { name: 'order-desk', version: '1.0.0' },
'io.modelcontextprotocol/clientCapabilities': {},
};
server.stdin.write(JSON.stringify({ jsonrpc: '2.0', id, method, params: { ...params, _meta } }) + '\n');
return new Promise((resolve) => waiting.set(id, resolve));
}
console.log('→ server/discover');
const discovered = (await request('server/discover')).result;
const info = discovered._meta['io.modelcontextprotocol/serverInfo'];
console.log(`server: ${info.name} ${info.version}, speaks ${discovered.supportedVersions.join(', ')}`);
console.log(`offers: ${Object.keys(discovered.capabilities).join(', ')}`);
console.log('→ tools/list');
for (const tool of (await request('tools/list')).result.tools) {
console.log(`tool: ${tool.name}`);
console.log(` needs: ${JSON.stringify(tool.inputSchema.properties)} (required: ${tool.inputSchema.required.join(', ')})`);
}
المخرجات
→ server/discover
server: order-status 1.0.0, speaks 2026-07-28
offers: tools
→ tools/list
tool: get_order_status
needs: {"order_id":{"type":"string","description":"The order number as the customer sees it, digits only, for example \"1042\"."}} (required: order_id)
شغّله بالأمر node client.mjs. يطلق العميل الخادم، ويسأله أمرين، ثمّ يغلقه ويخرج. هذا ما طبعه:
→ server/discover— يرسل العميل الرسالة نفسها التي كتبتها بيدك في الخطوة 1، وقد بنتها الآن الدالّةrequest.server: order-status 1.0.0, speaks 2026-07-28— الاسم والإصدار وإصدار البروتوكول الوحيد من الردّ، مقروءة من الحقول نفسها التي رأيتها خاماً.offers: tools— مفاتيحcapabilities.→ tools/list— الطلب الثاني. فليعرف العميل الأدوات المتاحة، يرسل طلب tools/list.tool: get_order_status— الأداة الوحيدة التي يقدّمها الخادم، باسمها.needs: {"order_id":{"type":"string","description":"The order number as the customer sees it, digits only, for example \"1042\"."}} (required: order_id)— ما تأخذه الأداة: نصّ واحد،order_id، لا تستغني عنه.
انظر إلى request. إنّها تبني كتلة _metaلكلّ رسالة — إصدار البروتوكول، وقدرات العميل، واسمه — وهذا التكرار تصميم المراجعة الحاليّة لا سهو: كلّ طلب قائم بذاته. وباقي العميل تمديدات:spawn تطلق node server.mjs بأنابيب على دخله وخرجه، ومعالج line يقرأ ردود الخادم سطراً سطراً ويسلّم كلّ ردّ إلى الطلب الذي ينتظر id الخاصّ به. وحين لا يبقى شيء ينتظر، يستدعي server.stdin.end()، فيرى الخادم دخله يُغلق فيخرج، ويخرج العميل بعده.
والآن قارن الأداة التي قرأها العميل للتوّ بالأداة في ما هو استخدام الأدوات. هناك كُتبت داخل التطبيق أداةَ دالّة لها name وdescription وparameters. وهنا يرسل الخادم name وdescription وinputSchema — الأشياء الثلاثة نفسها، ومخطّط JSON نفسه يصف order_id. وهذه غاية البروتوكول كلّه: التطبيق الذي يتكلّم MCP لا يحتاج أن تُكتب الأداة داخله. إنّه يسأل الخادم بـtools/list، ويسلّم ما يرجع إلى نموذجه قائمةَ أدوات.
الخطوة 3 — استدعِ الأداة، وتعرّف إلى نوعَي الخطأ
أضف هذا في آخر client.mjs:
call-toolasync function call(name, args) {
console.log(`→ tools/call ${name} ${JSON.stringify(args)}`);
const answer = await request('tools/call', { name, arguments: args });
if (answer.error) console.log(`protocol error ${answer.error.code}: ${answer.error.message}`);
else console.log(`${answer.result.isError ? 'tool error' : 'result'}: ${answer.result.content[0].text}`);
}
await call('get_order_status', { order_id: '1042' });
await call('get_order_status', { order_id: '9999' });
await call('cancel_order', { order_id: '1042' });
المخرجات
→ tools/call get_order_status {"order_id":"1042"}
result: {"status":"shipped","carrier":"DHL","expected_delivery":"2026-09-14"}
→ tools/call get_order_status {"order_id":"9999"}
tool error: {"error":"no order numbered 9999"}
→ tools/call cancel_order {"order_id":"1042"}
protocol error -32602: Unknown tool: cancel_order
شغّل node client.mjs مرّة أخرى. تُطبع أسطر الخطوة 2 أوّلاً، ثمّ ستّة أسطر أخرى. هذا ما قالته:
→ tools/call get_order_status {"order_id":"1042"}— ليستدعي العميل أداة، يرسل طلب tools/call ، باسم الأداة ومُعامِلاتها.result: {"status":"shipped","carrier":"DHL","expected_delivery":"2026-09-14"}— نُفّذت الأداة على الخادم ورجع جوابها محتوى نصّيّاً. وهذا هو النصّ الذي يسلّمه التطبيق إلى نموذجه.→ tools/call get_order_status {"order_id":"9999"}— الأداة الصحيحة، مع طلبيّة غير موجودة.tool error: {"error":"no order numbered 9999"}— نجح الاستدعاء بوصفه رسالة، وأبلغت الأداة عن فشل داخل نتيجتها.→ tools/call cancel_order {"order_id":"1042"}— أداة ليست عند الخادم.protocol error -32602: Unknown tool: cancel_order— رُفض الطلب نفسه.
وهذان الأخيران مختلفان عن قصد. فللأدوات طريقتان للإبلاغ عن الأخطاء. خطأ تنفيذ الأداة — الطلبيّة 9999 — يُبلَّغ داخل نتيجة الأداة معisError: true، ويحمل ملاحظات قابلة للعمل يستطيع النموذج اللغويّ أن يصحّح بها نفسه ويعيد المحاولة بمُعامِلات معدّلة : فالنموذج الذي يُقال له «no order numbered 9999» يستطيع أن يطلب من المستخدم التأكّد من الرقم. أمّا خطأ البروتوكول —cancel_order— فيدلّ على مشكلة في بنية الطلب نفسه يقلّ أن يستطيع النموذج إصلاحها، ومنها الأداة غير المعروفة. ويرجع خطأ JSON-RPC بدل النتيجة، ومثال المواصفة نفسها على الأداة غير المعروفة يستعمل الرمز نفسه الذي استعمله هذا الخادم، -32602. وما يفعله التطبيق بكلّ منهما يتبع من ذلك: يجوز للعميل أن يمرّر أخطاء البروتوكول إلى النموذج، مع أنّها يقلّ أن تقود إلى تعافٍ، وعليه أن يمرّر أخطاء تنفيذ الأداة إليه ليصحّح نفسه.
القاعدة الوحيدة
MCP يحمل الأدوات؛ لا يستدعيها. النموذج ما زال هو من يقرّر متى يحتاج أداة، تماماً كما في ما هو استخدام الأدوات؛ وMCP هو الطريق الذي وصلت به الأداة إلى التطبيق، والطريق الذي يصل به استدعاء التطبيق إلى الأداة.
والمواصفة تسمّي ثلاثة أدوار. المضيف تطبيق نماذج لغويّة يبدأ الاتّصالات؛ والعميل موصِّل داخل التطبيق المضيف؛ والخادم خدمة تقدّم السياق والقدرات. والأدوات يتحكّم بها النموذج: دوالّ معروضة على النموذج اللغويّ ليتّخذ بها أفعالاً. وإذا جمعت ذلك، فاستدعاء أداة واحد يعبر الثلاثة:
| من | ماذا يفعل | في هذا الدليل |
|---|---|---|
| النموذج | يقرّر أنّ أداة مطلوبة ويطلبها باسمها ومُعامِلاتها | ليس هنا — الخطوة 1 في دليل استخدام الأدوات |
| المضيف، عبر عميله | يسرد أدوات الخادم، ويعطيها للنموذج، ويرسل tools/call حين يطلب النموذج |
client.mjs |
| الخادم | ينفّذ الأداة ويعيد نتيجتها أو خطأها | server.mjs |
والأدوات واحد من ثلاثة أشياء يستطيع الخادم أن يقدّمها. فيستطيع أن يقدّم أيضاً موارد، أي سياقاً وبيانات، وقوالب رسائل، أي رسائل ومسارات عمل جاهزة للمستخدم؛ والأدوات هي الدوالّ التي ينفّذها نموذج الذكاء الاصطناعيّ. وخادم هذا الدليل لا يقدّم إلّا أدوات، ولهذا لم تحملcapabilities عنده إلّا tools.
ويستطيع نموذج مستضاف أن يؤدّي دور المضيف عنك. ففي واجهة Responses لدى OpenAI تستعمل نوع الأداة mcp، مع server_url لخادم MCP بعيد، أو tunnel_idلخادم محلّيّ عبر Secure MCP Tunnel. وخادم MCP البعيد يمكن أن يكون أيّ خادم على الإنترنت العامّ يطبّق خادم MCP بعيداً — ولهذا لا يمكن تسليم خادم هذا الدليل إليها بعنوان، فهو عمليّة محلّيّة تتكلّم stdio.
متى تستخدمه ومتى لا
| الحالة | القرار | السبب |
|---|---|---|
| أداة واحدة يستعملها تطبيقك وحده ولا شيء غيره | لا — استعمل استدعاء الدوالّ | طريقة دليل استخدام الأدوات أبسط، وMCP يضيف عمليّة وبروتوكولاً بلا فائدة |
| الأداة نفسها يجب أن تعمل في عدّة تطبيقات ذكاء اصطناعيّ | اكتب خادم MCP | خادم واحد، يسرده ويستدعيه بالطريقة نفسها كلّ مضيف يتكلّم MCP |
| خدمة تستعملها تنشر خادم MCP جاهزاً | صِلها | تصل أدواتها بـtools/list؛ ولا تكتب أيّاً منها |
| خادم من مصدر لا تضمنه، وأدواته تفعل أشياء | لا، أو بموافقة على كلّ استدعاء فقط | أوصافه غير موثوقة، وما يصل إلى النموذج قد يتسرّب عبره |
| نموذجك يعمل على واجهة Responses لدى OpenAI والخادم عامّ | استعمل نوع الأداة mcp مع server_url |
الواجهة تؤدّي دور المضيف وتستدعي الخادم عن النموذج |
| الخادم برنامج محلّيّ، مثل خادم هذا الدليل | أطلقه من عميلك أنت عبر stdio، أو صِله عبر Secure MCP Tunnel | الواجهة المستضافة لا تصل إلى عمليّة على جهازك بعنوان |
مصطلحات مرّت معنا
- MCP (بروتوكول سياق النموذج) — معيار مفتوح لوصل تطبيقات الذكاء الاصطناعيّ بالأنظمة الخارجيّة: الأدوات والبيانات وقوالب الرسائل.
- الخادم — البرنامج الذي يقدّم الأدوات (وربّما الموارد وقوالب الرسائل)؛ وهنا هو
server.mjs. - العميل — الشيفرة داخل تطبيق الذكاء الاصطناعيّ التي تكلّم خادماً واحداً؛ وهنا هو
client.mjs. - المضيف — تطبيق الذكاء الاصطناعيّ نفسه، الذي يشغّل العملاء ويعطي النموذج ما يجدونه.
- الأداة — دالّة يقدّمها الخادم ليستدعيها النموذج، يصفها اسم ووصف ومخطّط مدخلات.
- المورد وقالب الرسالة — الشيئان الآخران اللذان يستطيع الخادم تقديمهما: سياق وبيانات، ورسائل جاهزة للمستخدم.
- صيغة JSON-RPC — صيغة الرسائل التي يستعملها MCP: طلبات لها
idوmethod، وردود بالـidنفسه ومعهاresultأوerror. - ناقل stdio — حمل تلك الرسائل عبر الدخل والخرج القياسيّين لعمليّة فرعيّة، رسالة في كلّ سطر.
- ناقل Streamable HTTP — الناقل القياسيّ الآخر، وفيه كلّ رسالة طلب HTTP POST إلى نقطة واحدة.
_meta— الجزء من كلّ طلب الذي يحمل إصدار البروتوكول وقدرات العميل في المراجعة الحاليّة.- إصدار البروتوكول — تاريخ بالصيغة YYYY-MM-DD؛ والحاليّ هو 2026-07-28.
server/discoverوtools/listوtools/call— الطلبات الثلاثة في هذا الدليل: من أنت، وما أدواتك، ونفّذ هذه.- خطأ تنفيذ الأداة — فشل داخل نتيجة الأداة، معلَّم بـ
isError: true، وكثيراً ما يستطيع النموذج إصلاحه. - خطأ البروتوكول — خطأ JSON-RPC لطلب لم يمكن التعامل معه أصلاً، مثل أداة غير معروفة.
الخلاصة
MCP طريقة واحدة معياريّة يجد بها تطبيق الذكاء الاصطناعيّ أداةً ويستدعيها: يسرد الخادم ما يقدّمه، ويطلبه العميل بـtools/list وينفّذه بـtools/call. وفي المراجعة الحاليّة، 2026-07-28، يحمل كلّ طلب إصدار بروتوكوله بنفسه، ولا مصافحة. والنموذج ما زال هو من يقرّر متى يستدعي الأداة؛ وMCP لا يفعل إلّا أن يجعل الأداة نفسها في متناول كلّ تطبيق يتكلّمه.
ما تغيّر مؤخراً
لم يتغيّر أيّ مصدر من مصادر هذا الدليل منذ آخر فحص.