Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
mcpsnoop — Wireshark لـ MCP. بروكسي شفاف يعرض كل استدعاء أداة حقيقي بين عميل الذكاء الاصطناعي الخاص بك وخوادم MCP الخاصة بك، مباشرة في الطرفية الخاصة بك. | Kitploit
أدوات/GitHubGitHub/kerlenton/mcpsnoop
أدوات عامةالتحليل الديناميكي (عزل)تخطيط الشبكةبروكسيات الويب والاعتراضالبرمجة النصية والأتمتةاختبار أمان APIمصممي الأخطاءتحليل السجلات
GitHubkerlenton/mcpsnoop

mcpsnoop

Wireshark لـ MCP. بروكسي شفاف يعرض كل استدعاء أداة حقيقي بين عميل الذكاء الاصطناعي الخاص بك وخوادم MCP الخاصة بك، مباشرة في الطرفية الخاصة بك.

عرض المستودع
3343220منذ 13 أيامتمت المراجعة من قبل Kitploit

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

mcpsnoop

Wireshark لـ MCP. وكيل شفاف يُظهر كل استدعاء أداة حقيقي بين عميل الذكاء الاصطناعي الخاص بك وخوادم MCP الخاصة بك، مباشرة في طرفيتك.

CI Go Reference MIT Marketplace

mcpsnoop demo

المشكلة

يتصل MCP Inspector الرسمي كعميل خاص به، لذا لا يرى أبدًا ما يرسله عميلك (Cursor، Claude Code، Codex) فعليًا إلى خادمك. وأي شيء ينتظر وصول طلب لا يمكنه إظهار الاستدعاء الذي لم يقم به النموذج أبدًا، أو قام به بوسائط خاطئة. عندما لا يتم استدعاء أداة بصمت، أو لا تتوافق القدرات، أو يتعطل استدعاء ما، تظل عالقًا في البحث في السجلات والتخمين.

بدلاً من ذلك، يجلس mcpsnoop في مسار البيانات الحقيقي. لفّ أمر الخادم الخاص بك به وشاهد كل إطار JSON-RPC مباشرة، بينما يتحدث عميلك وخادمك الحقيقيان.

في CI

هذه الصفحة هي أيضًا قائمة إجراء GitHub الخاص بـ mcpsnoop، إليك كل ما يتعلق به. يتحقق من جلسة مُلتقطة، ويسجل كل نتيجة كتنبيه فحص كود، ويفشل المهمة بناءً على ما قمت بتقييده عليه.```yaml permissions: security-events: write contents: read

steps:

  • uses: kerlenton/[email protected] with: session: artifacts/session.jsonl
root@kitploit:~
حدد الإصدار الذي تريده. الأحدث موجود في
[صفحة الإصدارات](https://github.com/kerlenton/mcpsnoop/releases). كل مدخل،
وماذا تعني رموز الخروج، وكيفية توصيله بدون الإجراء موجودة في
[إجراء GitHub](#the-github-action) في الأسفل.

## بدء سريع

شاهده فورًا، دون الحاجة إلى إعداد أي شيء.```bash
mcpsnoop demo

لاستخدامه فعليًا، قم بلف خادمك في إعداد MCP الخاص بالعميل.```json { "mcpServers": { "my-server": { "command": "mcpsnoop", "args": ["--", "node", "build/index.js"] } } }

root@kitploit:~
كل ما بعد `--` هو الأمر الذي يشغّل خادمك عادةً. استبدله بما تستخدمه بالفعل، مثل `python server.py` أو `npx -y @scope/server` أو ملف ثنائي مُجمَّع.

في Claude Desktop لا يتعين عليك إجراء هذا التعديل يدويًا.```bash
mcpsnoop wrap my-server     # route my-server through mcpsnoop
mcpsnoop unwrap my-server   # put it back

wrap يعثر على claude_desktop_config.json، وينسخه إلى claude_desktop_config.json.mcpsnoop.bak في المرة الأولى، ويعيد كتابة إدخال ذلك الخادم الواحد فقط، بحيث يبقى تنسيقك وجميع الخوادم الأخرى كما هي دون تغيير. داخل الإدخال المُعاد كتابته، تعود المفاتيح بترتيب أبجدي. unwrap يستعيد الملف، ويزيل النسخة الاحتياطية بمجرد عدم وجود أي خادم ملفوف بعد الآن. أعد تشغيل Claude Desktop بعد أيٍّ من العمليتين، لأن خوادم MCP تُطلق مرة واحدة فقط عند بدء التشغيل.

ثم استخدم عميلك كالمعتاد وافتح الواجهة.```bash mcpsnoop

root@kitploit:~
لا أعلام، لا مسارات مآخذ، لا ترتيب تشغيل يجب تذكّره. تجد الطبقة الوسيطة (shim) وواجهة المستخدم بعضهما البعض تلقائيًا، وتقوم واجهة المستخدم بملء الجلسات السابقة من القرص.

بالنسبة لخادم HTTP قابل للبث، شغّل mcpsnoop كوكيل عكسي.```bash
mcpsnoop http --target http://localhost:3000/mcp --listen :7000

حالة HTTP لكل استجابة تظهر في التدفق، لذا فإن الاستجابة التي لا تحمل أي رسالة JSON-RPC خاصة بها لا تزال إطارًا مرئيًا بدلاً من لا شيء: تحدي 401، و403 عند رفض Origin، و202 التي تؤكد إشعارًا، و502 عندما يتعذر الوصول إلى الهدف على الإطلاق. يتم الاحتفاظ بترويسة WWW-Authenticate الخاصة بـ 401 كما هي وعرضها في المفتش، لأنها تسمي مخطط المصادقة وبيانات المورد الوصفية للانتقال إليها بعد ذلك. قم بالتصفية حسب الحالة باستخدام status:401 في TUI، أو حسب أي فشل باستخدام status:err. أي 4xx أو 5xx يُحتسب كخطأ، لذا فإن تشغيل mcpsnoop check الافتراضي يفشل عليه.

لا تملك خادمًا خاصًا بك؟ جرّبه فعليًا ضد خادم اختبار منشور، مدفوعًا بعميلك الخاص. لفحص جلسة بعد حدوثها، راجع مراجعة الجلسات السابقة من السجلات.

ملف الإعداد

إذا كنت تعيد استخدام نفس علامات shim عبر مشروع، فضعها في ملف .mcpsnoop.toml في دليل العمل الحالي.```toml label = "filesystem" trace-file = "trace.jsonl" redact-secrets = true redact-key = "token,authorization" redact-value = "sk-[A-Za-z0-9]+" redact-path = "$.params.arguments.password" no-trace = false

root@kitploit:~
كرر `redact-key` و `redact-value` و `redact-path` في أسطر منفصلة لإضافة
أكثر من واحد من كل منها.

هذه هي جميع المفاتيح التي يدعمها.

يتم البحث عن الملف فقط في دليل العمل الحالي، وليس في الدلائل
الأصلية.

تتجاوز خيارات سطر الأوامر الصريحة القيم الواردة من ملف الإعدادات.

## الأوامر

| الأمر | ما يفعله |
|---|---|
| `mcpsnoop -- <server>` | يغلّف خادم stdio كطبقة وسيطة شفافة |
| `mcpsnoop` | يفتح واجهة TUI المباشرة |
| `mcpsnoop http --target <url>` | يمرّر عبر خادم HTTP قابل للبث |
| `mcpsnoop export` | يعرض جلسة بصيغة json أو html أو text أو har أو otlp |
| `mcpsnoop check` | يفشل CI عند وجود أخطاء أو إطارات غير صالحة أو تحذيرات أو عدم تطابق في التوجيه أو استدعاءات معلّقة أو نتائج متأخرة أو تجاوز ميزانية زمن الاستجابة |
| `mcpsnoop baseline` | يعاين أو يقبل أو يعيد تعيين تعريفات الأدوات الموثوقة |
| `mcpsnoop diff` | يقارن الأدوات والاستدعاءات عبر جلستين ملتقطتين |
| `mcpsnoop open` | يفتح جلسة محفوظة في واجهة TUI |
| `mcpsnoop inventory` | يسرد كل خادم تم تشغيله عبر mcpsnoop على هذا الجهاز |
| `mcpsnoop stats` | يدمج كل لقطة مخزنة في صف واحد لكل خادم وأداة |
| `mcpsnoop prune` | يحذف سجلات الجلسات المحفوظة الأقدم من حد زمني |
| `mcpsnoop wrap <server>` | يوجّه أحد خوادم Claude Desktop عبر mcpsnoop |
| `mcpsnoop unwrap <server>` | يعيد إدخال ذلك الخادم إلى حالته الأصلية |
| `mcpsnoop remote <user@host>` | يطبع أمر نفق SSH |
| `mcpsnoop demo` | يشغّل جلسة مكتوبة مسبقًا |

شغّل `mcpsnoop help` للحصول على القائمة الكاملة، أو `mcpsnoop help <command>` لمعرفة خيارات أمر معيّن.

## كيف يقارن

| | MCP Inspector | mcpsnoop |
|---|:---:|:---:|
| يرى حركة مرور عميلك وخادمك الفعلية | لا | نعم |
| يعلّم على الاستدعاءات المعلّقة وأخطاء البث | لا | نعم |
| يعلّم على المخرجات الشاردة التي تفسد البث | لا | نعم |
| يعلّم على إطارات JSON-RPC غير الصالحة | لا | نعم |
| يكتشف انحراف تعريف الأداة بعد الموافقة | لا | نعم |
| واجهة طرفية تفاعلية | لا | نعم |
| بدون إعداد، بدون خيارات أو ترتيب | لا | نعم |
| فاحص القدرات | جزئي | نعم |
| إعادة تشغيل استدعاء ملتقط | لا | نعم، عبر stdio وعبر HTTP |
| تصدير الجلسة (json / html / text / otlp) | لا | نعم |
| ملف ثنائي واحد، بدون تبعيات وقت تشغيل | لا | نعم |

## التثبيت

### npm

لا حاجة إلى سلسلة أدوات Go. معظم خوادم MCP مكتوبة بلغة Node أو Python، لذا
هذه هي الطريقة الأقصر للبدء.```bash
npx mcpsnoop -- node build/index.js

حزمة npm لا تحتوي على أي كود خاص بها. كل حزمة من الحزم الست الخاصة بالمنصات تحمل نسخة واحدة، ويقوم npm بتثبيت النسخة الوحيدة التي تتوافق مع جهازك، لذلك لا يوجد شيء لتنزيله وقت التثبيت ولا شيء لإلغاء حظره في وكيل. للاحتفاظ بها بدلاً من جلبها في كل تشغيل، استخدم npm i -g mcpsnoop.

Go```bash

go install github.com/kerlenton/mcpsnoop/cmd/mcpsnoop@latest

root@kitploit:~
### هوم برو```bash
brew install mcpsnoop

الملفات الثنائية الجاهزة لكل منصة متوفرة في صفحة الإصدارات.

إكمالات الصدفة

يأتي mcpsnoop مع إكمالات لـ bash وzsh وfish وPowerShell. شغّل mcpsnoop completion <shell> --help لمعرفة خطوات الإعداد، والتي تغطي تفعيل الإكمال ومسار التثبيت لنظام تشغيلك.

كيف يعمل

يجلس mcpsnoop في الأنبوب بين عميل الذكاء الاصطناعي الخاص بك وخوادم MCP الخاصة بك، وينسخ كل إطار JSON-RPC إلى واجهة طرفية حية

mcpsnoop هو دورين في ملف ثنائي واحد. mcpsnoop -- <server> هو الواجهة الشفافة التي يشغّلها عميلك، حيث يمرر البايتات حرفيًا بينما يرسل نسخة من كل إطار إلى المركز. mcpsnoop بدون وسائط هو ذلك المركز وواجهة TUI الحية الخاصة به. يتواصلان عبر مقبس معروف وسجلات على القرص، لذا لا يحتاج أي منهما إلى البدء أولًا.

يقوم المركز بتحميل أحدث 100 جلسة محفوظة افتراضيًا، مما يبقي عمل بدء التشغيل محدودًا دون حذف السجلات الأقدم. استخدم mcpsnoop --history-limit N لاختيار حد آخر، أو mcpsnoop --history-limit 0 لتحميل السجل الكامل. تبقى الجلسات الأقدم متاحة عبر mcpsnoop open <session-id> و mcpsnoop export <session-id>.

حد السجل يقيّد عدد الجلسات التي يتم تحميلها. داخل الجلسة، تكون واجهة TUI الحية مقيّدة مرتين، لأن مركزًا يُترك لمراقبة خادم ثرثار سينمو خلاف ذلك حتى يُقتل. يحتفظ بما يصل إلى 64 ميجابايت من أجسام الإطارات، محررًا الأقدم أولًا، وبحد أقصى 200,000 إطار، ويسقط الأقدم تمامًا بعد ذلك. الحد الأول هو ما يصطدم به التقاط الحمولات الكبيرة، والثاني هو ما يفعله تدفق طويل من الإشعارات الصغيرة.

لا يغيّر أي من الحدين الإجابة. الإطار الذي تم تحرير جسمه يحتفظ بصفه، وحكمه وموقعه في الخط الزمني، ويقول مفتشه أن الجسم قد اختفى بدلاً من إظهار إطار فارغ. الإطار الذي تم إسقاطه تمامًا يأخذ إحصائيات استدعاء أداته معه إلى الإجماليات الجارية أولًا، لذا فإن ملخص الأداة وما يكلفك به الخادم في السياق يصف كل استدعاء قامت به الجلسة، وليس فقط الاستدعاءات الأخيرة. يقول تذييل البث عدد الإطارات الأقدم الموجودة على القرص فقط، ويرفض r إطارًا لم يعد يحتفظ بمعاملاته بدلاً من إعادة تشغيل شيء آخر.

mcpsnoop open <session-id> يقرأ السجل ويحتفظ بكل شيء، والتصدير من واجهة TUI يقرأ السجل أيضًا، لذا لا يكون أي منهما محدودًا. check وexport و diff يبنون مخزنًا غير محدود عن قصد، لأن بوابة تقلل من التقرير على التقاط كبير أسوأ من تلك التي تستخدم الذاكرة.

حد السجل يقيّد ما يتم تحميله. mcpsnoop prune يقيّد ما يتم الاحتفاظ به. يحذف سجلات الجلسات المحفوظة الأقدم من حد زمني، ولا يعمل أبدًا من تلقاء نفسه.```bash mcpsnoop prune --older-than 30d --dry-run # list what would go, remove nothing mcpsnoop prune --older-than 30d # delete after confirming mcpsnoop prune --older-than 72h --yes # skip the prompt in a script

root@kitploit:~
`--older-than` مطلوب (لا يوجد افتراضي قد يحذف أي شيء) ويقبل عدد أيام مثل `30d` أو مدة بصيغة Go مثل `72h`. تُترك خطوط الأساس للأدوات دون تغيير، لأن خط الأساس مرتبط بتسمية الخادم وليس بالجلسة.

نظرًا لأنه يقع داخل خط الأنابيب الفعلي، وليس جانبًا مثل Inspector، فإنه يرى بالضبط ما يقوله عميلك وخادمك الحقيقيان لبعضهما البعض، مهما كانت اللغة التي كُتب بها الخادم.

## اختصارات لوحة المفاتيح

| المفتاح | الإجراء | | المفتاح | الإجراء |
|---|---|---|---|---|
| `enter` | فحص / التعمق | | `/` | تصفية |
| `esc` | رجوع | | `:` | أمر |
| `j` / `k` | تحريك | | `r` / `R` | إعادة تشغيل / تعديل وإعادة تشغيل |
| `g` / `G` | أعلى / أسفل | | `c` | القدرات |
| `ctrl-f` / `ctrl-b` | صفحة | | `s` | ملخص الأداة |
| `p` | إيقاف مؤقت | | `y` | نسخ |
| `shift`+`<key>` | فرز حسب العمود | | `e` | تصدير |
| `ctrl-d` | حذف الجلسة | | `f` | متابعة |
| `?` | مساعدة | | | |

اضغط `?` داخل التطبيق للحصول على القائمة الكاملة.

## تصفية التدفق

اضغط `/` في جلسة واجمع الرموز المميزة المفصولة بمسافات، مع منطق AND. النص العادي يطابق الطريقة والأداة والمعرف والحمولة.

| الرمز | التصفية حسب | مثال |
|---|---|---|
| `tool:` | اسم الأداة | `tool:search` |
| `method:` | طريقة JSON-RPC | `method:tools/call` |
| `id:` | معرف الطلب، وأي إعادة محاولة تكمله | `id:7` |
| `task:` | معرف المهمة | `task:01J...` |
| `dir:` | الاتجاه (`c2s`, `s2c`) | `dir:s2c` |
| `kind:` | نوع الإطار (`req`, `resp`, `notify`, `stderr`, `invalid`) | `kind:invalid` |
| `status:` | نتيجة الاستدعاء (`ok`, `error`, `cancel`, `late`, `cancelled`, `pending`, `bad`, `warn`, `mismatch`, أو حالة HTTP مثل `401`) | `status:error` |

كدّس الرموز للحصول على نتائج محددة.```text
tool:search status:pending        # in-flight calls to one search tool
status:cancel                     # calls the client gave up on (status:cancelled is a cancelled task)
status:late                       # results that arrived after the cancellation
method:tools/call status:error    # tool calls that failed
dir:s2c kind:req                  # server-initiated requests (servers before 2026-07-28)

النسخة الأخيرة لا تجد شيئًا سوى على خادم يتحدث بإصدار 2025-11-25 أو أقدم. مراجعة 2026-07-28 أزالت الطلبات التي يبدأها الخادم، والخادم الذي يحتاج إلى شيء من العميل يرد الآن على طلب العميل نفسه طالبًا إياه، ثم يعيد العميل المحاولة. يربط mcpsnoop تلك المحاولات المعاد إرسالها بالطلب الذي تستكمله، بحيث تُقرأ الجلسة كاستدعاء واحد بدلاً من عدة استدعاءات.

تصدير الجلسات

حوّل أي جلسة تم التقاطها إلى ملف قابل للنقل.```bash mcpsnoop export -T json|html|text|har|otlp [-o file|-] [session-id|log.jsonl|-]

root@kitploit:~
| الصيغة | ما الذي ستحصل عليه |
|---|---|
| `json` | استدعاءات مترابطة، عدد مرات الاستخدام لكل أداة، زمن الاستجابة p50/p95/p99، أبطأ الاستدعاءات، القدرات، والإطارات الخام |
| `html` | ملف متصفح مستقل بذاته مع بحث وJSON قابل للطي |
| `text` | تفريغ نصي بسيط وأنيق |
| `har` | إدخال واحد لكل استدعاء مترابط، قابل للفتح في أدوات مطوري المتصفح وأي شيء آخر يقرأ HAR |
| `otlp` | JSON بصيغة OTLP مع فترة زمنية (span) لكل استدعاء مترابط، مع سياق تتبع W3C الذي يربط تتبعات المُستدعي حيثما كان موجودًا، وتتبع واحد لكل جلسة بخلاف ذلك |

MCP ليس HTTP، لذا فإن عنوان URL لإدخال HAR ورمز الحالة والتوقيتات هي تعيين
متعمّد لكل استدعاء وليست نسخة حرفية من الأسلاك.

بالنسبة لـ OTLP، يوفر `_meta.traceparent` الخاص بالطلب تتبع ذلك الاستدعاء ومعرّفات
الفترة الزمنية الأصلية، بينما ينتقل `_meta.tracestate` مع الفترة الزمنية. عندما يكون
traceparent غائبًا أو غير صالح، يحتفظ mcpsnoop بالتتبع المشتق من الجلسة ولا يحمل أي حالة.
يراقب mcpsnoop ولا يشارك، لذا فهو لا يضيف أي إدخال خاص بالبائع
ويمرر حالة المُستدعي دون تغيير.```bash
mcpsnoop export -T html -o out.html                    # an HTML file to open in a browser
mcpsnoop export -T text server.py-48213-7f3a1c9e2b04   # a specific session, as text
mcpsnoop export -T json | jq                           # the newest session, piped to jq
mcpsnoop export -T har -o session.har                  # a HAR file to open in browser devtools
mcpsnoop export -T otlp -o trace.json                  # import into an OTLP-compatible tracing backend

احذف -o للكتابة إلى stdout، واحذف الجلسة لأخذ الأحدث، أو مرر - لقراءة JSONL من stdin. في واجهة TUI، اضغط e لتصدير الجلسة المحددة بصيغة HTML، أو شغّل :export json|html|text|har|otlp [path] من وضع الأوامر.

التنقيح

لتنظيف تسجيل موجود قبل فحصه أو مشاركته، مرر نفس أعلام التنقيح المستخدمة أثناء التسجيل إلى export أو open:```bash mcpsnoop export session.jsonl --redact-secrets --redact-key project_token -o shared.json mcpsnoop open session.jsonl --redact-path '$.params.arguments.password'

root@kitploit:~
هذه العلامات تعيد كتابة الملف المُصدَّر أو عرض TUI في الذاكرة، ولا تلمس أبدًا
ملف JSONL المصدر. يرفض `export` مخرجًا يسمّي نفس الملف الذي هو مدخله،
ويكتب عبر ملف مؤقت يُعاد تسميته إلى مكانه، لذا فإن أي تشغيل يفشل يترك الملف
السابق سليمًا.

يُترك `inputSchema` و`outputSchema` الخاصان بالأداة، كما هو مُعلَن في نتيجة
`tools/list`، دون مساس من قِبل `--redact-key` و`--redact-secrets`، لثلاثة أسباب.

- الاسم داخل المخطط هو إعلان نوع وليس قيمة.
- الاسم نفسه يبقى في السجل في كلتا الحالتين.
- تنظيف المخطط الفرعي تحت خاصية تُدعى `token` سيأخذ فحوصات الأداة نفسها معه.

الاستثناء هو ذلك الموضع فقط، لذا فإن أي وسيط يصادف أن يُدعى
`inputSchema` يُنظَّف مثل أي وسيط آخر، ويتوقف عند `default` و`const`
و`examples` و`enum`، التي تحمل بيانات وليست بنية. استخدم
`--redact-path` لتسمية شيء داخل مخطط، أو `--redact-value`، الذي
يطابق النص أينما وُجد باستثناء الكلمتين المفتاحيتين اللتين يحللهما mcpsnoop، وهما
`type` و`x-mcp-header`.

ما يصل إليه كل علم يختلف، لذا تحقق من النتيجة بدلًا من الافتراض. جميع
الأعلام الأربعة تنظف حمولات JSON-RPC، و`--redact-key` و`--redact-path`
و`--redact-secrets` تصل فقط إلى تلك. فقط `--redact-value` ينظف أيضًا stderr،
والنصوص الأخرى غير JSON، وداخل السلسلة النصية. يُنظَّف ترويسة `Mcp-Param-*`
جنبًا إلى جنب مع قيمة الجسم التي تعكسها. بيانات الغلاف الوصفية الأخرى،
تسميات الخادم، و`Mcp-Name` و`Mcp-Method` وحالة HTTP، تُترك كما
التُقطت. التنظيف هو جهد بأفضل ما يمكن، لذا استخدم مسار مخرج منفصل واقرأ
النتيجة قبل مشاركتها.

### بث الاستدعاءات المكتملة إلى مجمّع OTLP

أرسل spans أثناء تشغيل الوكيل بتوجيهه إلى نقطة نهاية OTLP/HTTP JSON
لتتبعات traces. كرر `--otlp-header` لمصادقة المجمّع أو ترويسات
المستأجر.```bash
mcpsnoop \
  --otlp-endpoint http://localhost:4318/v1/traces \
  --otlp-header "Authorization=Bearer $OTLP_TOKEN" \
  -- node build/index.js

mcpsnoop http \
  --target http://localhost:3000/mcp \
  --otlp-endpoint http://localhost:4318/v1/traces

التسليم بأفضل جهد ولا يحجب أبدًا حركة مرور MCP المُمرَّرة عبر الوكيل. إذا كان المُجمِّع غير متاح، يقوم mcpsnoop بإعادة المحاولة في الخلفية ويتجاهل إطارات التتبع الجديدة عندما تكون قائمة الانتظار المحدودة ممتلئة. يبقى سجل الجلسة العادي بصيغة JSONL هو السجل الدائم.

مقارنة الجلسات

قارن بين جلستين محفوظتين حسب المعرّف أو مسار ملف JSONL.```bash mcpsnoop diff before-session after-session mcpsnoop diff old.jsonl new.jsonl

root@kitploit:~
التقرير يعرض الأدوات التي تمت إضافتها أو إزالتها، ووصفها وتغييرات `inputSchema`، واستدعاءات الأدوات المتطابقة التي تغيّرت حالتها، وتحولات المدة الملحوظة. تتم مطابقة الاستدعاءات حسب اسم الأداة والوسائط، لذا فإن الاستدعاءات المعاد ترتيبها لا تزال تُقارن بشكل صحيح. افتراضيًا، يجب أن يختلف تغيّر المدة بمقدار 100 مللي ثانية على الأقل وبمعامل 2x. استخدم `--duration-threshold` و`--duration-ratio` لضبط هذه الحدود.

مرّر `--exit-code` لتفعيل البوابة في CI عند حدوث تراجعات. يخرج برمز غير صفري عندما تكون الجلسة "بعد":

- تُسقط أداة
- تغيّر وصف أداة أو عنوانها أو مخطط الإدخال أو مخطط الإخراج أو التعليقات التوضيحية
- تحتوي على استدعاء تدهورت حالته
- تتباطأ

تغيير الأيقونة لا يُحتسب، لأنه يعدّل مظهر الأداة دون تغيير وظيفتها. التحسينات، أي الأدوات المضافة والاستدعاءات المُصححة وتسريع الأداء، لا تزال تخرج برمز صفري.

## فحص الجلسات في CI

قم بتقييد جلسة وكيل مسجّلة بناءً على الأخطاء، أو تلف التدفق، أو تحذيرات البروتوكول، أو عدم تطابق ترويسات التوجيه، أو الاستدعاءات التي لم تتلقَ استجابة أبدًا، أو الإطارات المسقطة التي تترك الالتقاط غير مكتمل، أو انحراف تعريف الأداة، أو استخدام ميزات بروتوكول قديمة.```bash
mcpsnoop check [--format text|junit|sarif] [--fail-on error,invalid,warn,mismatch,pending,late-result,drift,deprecated,incomplete,schema] [session-id|log.jsonl|-]

error وinvalid وwarn تفشل الفحص بمفردها. أما البقية فهي اختيارية. مرّر مجموعة فرعية مفصولة بفواصل للتحقق فقط مما يهم المهمة، أو احذف الجلسة للتحقق من أحدث التقاط، أو استخدم - لقراءة JSONL من الإدخال القياسي.

الإشارةتفشل عند
errorمكالمة يُرد عليها بخطأ JSON-RPC، أو نتيجة موسومة بـ isError، أو مهمة انتهت بفشل
invalidإطار على قناة البروتوكول ليس JSON-RPC صالحًا، عادةً ما يكون خادمًا يسجّل إلى stdout
warnإطار يخالف توقعًا تحدده مواصفات MCP أو JSON-RPC
mismatchترويسة توجيه تتعارض مع الجسم، أو تركب دفعة، أو تغيب حيث يتطلبها الإصدار
pendingطلب ما زال مفتوحًا عند انتهاء الالتقاط، فتُرك المتصل في انتظار
late-resultاستجابة وصلت بعد إلغاء طلبها
driftتعريف أداة معلن يتغير بعد اعتماد خط الأساس
deprecatedميزة أوقفتها المواصفات
incompleteإطارات أُسقطت من المصب، مما يجعل كل عدد آخر حدًا أدنى وليس إجمالًا
schemaمخطط معلن يستخدم بنية أو لهجة تنتقل بشكل سيئ عبر العملاء

تُحسب كل إشارة سواء كانت مُفعّلة للفحص أم لا، لذا تُظهر الجولة ما وجدته قبل أن تقرر ما الذي يجب أن يفشل عندها.``` session build-agent: errors=1 invalid=0 warnings=0 mismatches=0 pending=0 late_results=0 deprecated=0 missing_frames=0 schema_findings=1 schema findings: oneOf: search check failed: error

root@kitploit:~
عدد الإطارات المفقودة ينتقل مع القطع الأثرية أيضًا، لذا فإن أي عملية التقاط تقلل من حجمها توضح ذلك أينما تم فتحها:

- `missing_frames` في تصدير JSON
- `log.comment` في HAR
- سمة المورد `mcpsnoop.session.missing_frames` في OTLP```bash
mcpsnoop check build-agent
mcpsnoop check --fail-on error,invalid artifacts/session.jsonl
mcpsnoop check --fail-on mismatch gateway-run.jsonl

رمز الخروج يخبرك بأي من الأمرين حدث، وطبقة التكامل مع CI تحتاج إلى الفرق بينهما. الرقم 1 يعني أن الفحص تم تشغيله وفشل شيء ما في معيار القبول، لذا فإن النتائج حقيقية وتستحق النشر. الرقم 2 يعني أن الفحص لم يحدث أبدًا: مسار غير موجود، ملف ليس سجل جلسة، دليل حالة لا يحتوي على شيء، علامة لا يمكن تحليلها. لا يُكتب أي شيء إلى stdout عند الرقم 2، لذا لا يقوم خط الأنابيب أبدًا برفع تقرير فارغ كما لو كان حكمًا.

تأكيد ما يجب وما لا يجب أن يحدث

بالإضافة إلى عدّادات الإشارات، أكّد شكل التشغيل. هذه تتوافق مع بعضها البعض ومع --fail-on، وأي فشل يخرج بالرقم 1، وهو الرمز الذي يعني أن الفحص تم تشغيله ووجد شيئًا.

العلامةتفشل عندما
--max-duration <dur>تجاوز استدعاء أداة واحد أو أكثر من الاستدعاءات المكتملة الميزانية، مع الإبلاغ عن عددها وأسوأ استدعاء
--expect-tool <name>لم يتم استدعاء الأداة المسماة أبدًا (قابلة للتكرار)
--forbid-tool <name>تم استدعاء الأداة المسماة (قابلة للتكرار)

a contract for the run: search must run, delete must not, nothing over 2s

mcpsnoop check --expect-tool search --forbid-tool delete --max-duration 2s run.jsonl

root@kitploit:~
### أبلغ عنها حيث تبحث CI بالفعل

يكتب `--format junit` عنصر `<testcase>` واحدًا لكل إشارة وجلسة، وتتبع حالات الفشل الخاصة به نفس تحديد `--fail-on` المتبع في إخراج النص.```yaml
- name: Check captured MCP session
  run: |
    mkdir -p test-results
    mcpsnoop check --format junit artifacts/session.jsonl > test-results/mcpsnoop.xml
- name: Upload mcpsnoop JUnit report
  if: always()
  uses: actions/upload-artifact@v4
  with:
    name: mcpsnoop-junit
    path: test-results/mcpsnoop.xml

--format sarif يكتب سجل SARIF 2.1.0 بدلاً من ذلك. حيث يُبلغ junit عن تجميع واحد لكل إشارة، يُبلغ SARIF عن نتيجة واحدة لكل اكتشاف، حاملاً الجلسة، وSeq الخاص بالإطار، ونص التحذير أو الانجراف الخاص بالإطار نفسه، ومشيراً إلى سطر السجل الذي فُكّ منه الإطار. الإشارة المذكورة في --fail-on تُبلغ بمستوى error، وما خارجها بمستوى note، بحيث لا يختلف التقرير عن البوابة أبداً.

تشير النتيجة إلى السجل الذي جاء منه الاكتشاف، وتعتمد كيفية ذلك على مكان قراءة السجل.

  • المسار داخل دليل العمل يصبح نسبياً، وهو ما يحلّه فحص الكود مقابل جذر المستودع.
  • المسار في مكان آخر على القرص، أو معرف جلسة تم حله من دليل الحالة، يصبح URI مطلقاً بصيغة file://.
  • القراءة من stdin تعطي نتيجة بدون أي موقع، إذ لا يوجد ملف للإشارة إليه.

يُعرض التنبيه مع سطوره المحيطة فقط عندما يكون ذلك المسار ملفاً في الالتزام المُحلَّل، لذا فإن التقاطاً يولّده سير العمل في artifacts/ يفتح تنبيهاً يحمل الرسالة والقاعدة ورقم السطر لكن دون عرض المصدر. الالتزام بالتقاط تريد عرضه بالكامل هو الطريقة الوحيدة للحصول على ذلك.

يرفض فحص الكود ملفاً يحتوي تشغيله على أكثر من 25,000 نتيجة، ويعرض فقط أعلى 5,000 مما يقبله، لذا يُحدّ التقرير عند 5,000: الاكتشافات التي فشلت البوابة عليها أولاً، ثم نتيجة mcpsnoop/report-truncated توضح كم تم استبعاده. تبقى صيغتا النص وjunit كاملتين.

إجراء GitHub

كل ما يلي هو ما يفعله الإجراء نيابة عنك. يثبّت mcpsnoop، ويفحص الالتقاط، ويودع الاكتشافات في تبويب الأمان، ويُفشل المهمة على ما قيّدته عليه.```yaml permissions: security-events: write contents: read

steps:

  • uses: kerlenton/[email protected] with: session: artifacts/session.jsonl
root@kitploit:~
ثبّت إصدارًا محددًا، أي إصدار تريده. الأحدث موجود في
[صفحة الإصدارات](https://github.com/kerlenton/mcpsnoop/releases). لا يوجد
إصدار عائم `v1`، وهذا مقصود. الإصدار المثبّت هو أيضًا الثنائي الذي يثبّته الإجراء،
لذلك لا يمكن أن يختلف الاثنان أبدًا ولا يوجد إصدار افتراضي يصبح قديمًا.

| الإدخال | |
|---|---|
| `session` | ملف الالتقاط `.jsonl` للفحص، نسبةً إلى جذر المستودع. مطلوب |
| `fail-on` | كما في `--fail-on`، مع افتراض ما يفعله سطر الأوامر افتراضيًا |
| `args` | أي علامات `check` أخرى، مكتوبة بين علامتي اقتباس كما في سطر الأوامر. يُرفض `--format`، لأن الإجراء يقرأ التقرير |
| `upload-sarif` | إرسال التقرير إلى فحص الكود. `true` |
| `category` | مساحة اسم فحص الكود. `mcpsnoop`. غيّرها لكل مسار من مسارات المصفوفة، وإلا فستستبدل المسارات بعضها البعض |
| `fail-on-findings` | إفشال المهمة عند وجود نتيجة. `true`. اضبطها على `false` لتسجيل التنبيهات والسماح لفحص الكود الإلزامي باتخاذ القرار |
| `version` | أي إصدار من mcpsnoop سيتم تثبيته. الافتراضي هو الإصدار الذي ثبّته |
| `install` | `false` عندما يكون mcpsnoop موجودًا بالفعل في PATH، وهو الطريقة على منصة لا يوجد لها إصدار مُصدر |

المخرجات هي `outcome` و`sarif` و`exit-code`. `outcome` تكون `passed` أو
`findings` أو `error`، والثالث يستحق معالجة منفصلة. يعني أن شيئًا لم يتم فحصه،
وهو ليس نفس معنى عدم العثور على شيء. **التشغيل الذي لا يمكنه الفحص يُفشل المهمة
بغض النظر عن `fail-on-findings`**، لأن خط أنابيب يتحول إلى أخضر بعد التحقق من لا شيء
أسوأ من خط يفشل.

تحتاج المهمة إلى `security-events: write`، وإلا سيرجع الرفع برمز 403. اضبط
`upload-sarif: false` في مستودع بدون فحص كود.

### أو اربطها بنفسك

الإجراء هو أربع خطوات وبدون أي سحر. القيام بذلك يدويًا يتطلب نفس العناية التي يتطلبها.
يجب أن يعمل الرفع على التشغيلات التي لديها تقرير، وهي تلك التي خرجت برمز 0 أو 1
وليس تلك التي خرجت برمز 2، والخطوة التي تُفشل المهمة يجب أن تأتي بعده،
وإلا فلن تصل النتائج أبدًا إلى التبويب الذي وُجدت من أجله.```yaml
permissions:
  # required for all workflows
  security-events: write
  # only required for workflows in private repositories
  actions: read
  contents: read

steps:
- name: Check captured MCP session
  id: check
  run: |
    code=0
    mcpsnoop check --format sarif artifacts/session.jsonl > mcpsnoop.sarif || code=$?
    echo "exit-code=$code" >> "$GITHUB_OUTPUT"
    # 2 means the check never happened, so there is no report to publish and
    # nothing was verified. Stop here rather than uploading an empty file.
    [ "$code" -le 1 ] || exit 1
- name: Upload mcpsnoop SARIF report
  if: ${{ !cancelled() }}
  uses: github/codeql-action/upload-sarif@v4
  with:
    sarif_file: mcpsnoop.sarif
    category: mcpsnoop
- name: Fail on findings
  # Separate, and after the upload, so the findings reach the Security tab on
  # exactly the runs that have some.
  if: ${{ !cancelled() && steps.check.outputs.exit-code == '1' }}
  run: exit 1

التقاط ترويسة توجيه تتعارض مع الجسم

في ناقل HTTP القابل للبث، يقوم البوابة بالتوجيه بناءً على Mcp-Method وMcp-Name بينما يقرأ الخادم الجسم، لذا فإن ترويسة تتعارض مع الجسم تعني أن الاثنين ينظران إلى طلبين مختلفين. تغطي إشارة mismatch ذلك، وترويسة تحملها دفعة لا يمكنها معالجتها، وترويسة مطلوبة مفقودة بالكامل.

في 2026-07-28، تُعد الترويسة المفقودة للتوجيه فشل تحقق، والخادم المتوافق يرفض الطلب برمز 400 و-32020. يرفع mcpsnoop هذه الإشارة فقط بمجرد معرفة أن الجلسة تتحدث بهذا الإصدار أو أحدث، نظرًا لأن الإصدارات السابقة لا تعرّف هذه الترويسات إطلاقًا وحذفها هناك صحيح. رفض الخادم الخاص برمز -32020 يُحتسب كإشارة مماثلة.

اسم أو URI مورد لن يتسع لقيمة حقل HTTP يُنقل بتنسيق Base64 في حارس =?base64?…?=، والذي يُفك ترميزه قبل المقارنة، لذا فإن العميل الذي يرمّز بشكل صحيح لا يتم الإبلاغ عنه أبدًا.

في طلبات HTTP من نوع tools/call، يعرض mcpsnoop أيضًا كل ترويسة Mcp-Param-{Name} وعندما يكون تعريف الأداة المُعلن المطابق معروفًا، يقارنها بمسار الوسيطة المُعلَّق. يتم التعامل مع الخصائص المتداخلة، وحارس Base64، والقيم المنطقية، والأعداد الصحيحة الآمنة المكافئة رقميًا دون نتائج إيجابية خاطئة من مقارنة السلاسل. تبقى ترويسات المعاملات غير المعروفة والجلسات دون تعريف أداة مطابق في نطاق الملاحظة فقط. يُطبَّق التنقيح القائم على المفاتيح والقيم على قيم ترويسات المعاملات الملتقطة قبل وصولها إلى وجهة، والقيمة التي نقّحها mcpsnoop بنفسه لا تُبلَّغ أبدًا كخلاف.

التحقق من ترويسات النقل التي تفرضها المواصفة

كانت ترويسات التوجيه أعلاه هي الوحيدة التي حملها إطار، لذا فإن بقية ترويسات ناقل HTTP القابل للبث الإلزامية لم تصل إلى أي شيء يمكنه التحقق منها. كانت Content-Type الحالة الأكثر حدة. كان جانب الاستجابة يقرأها بالفعل للتمييز بين تدفق SSE وجسم JSON، ثم يتجاهلها.

يحمل إطار HTTP الآن الترويسات التي تذكر المواصفة قواعد بشأنها، واثنتان من تلك القواعد قابلة للتحقق.

القاعدةتُبلَّغ كـ
يجب على العميل إرسال Accept يسرد كلاً من application/json وtext/event-streamwarn على الطلب
يجب على الخادم الذي يرد على طلب JSON-RPC إرجاع Content-Type: application/json أو text/event-streamwarn على الاستجابة

تقرأ الجملتان نفس القراءة في 2025-11-25 و2026-07-28، لذا على عكس فحوصات الانجراف والامتداد، لا تحتاج هذه إلى بوابة إصدار. يتم تسجيل Origin أيضًا، نظرًا لأن الخوادم يجب أن تتحقق منه ويجب أن ترد بـ403 عندما يكون غير صالح، لكن mcpsnoop لا يمكنه معرفة أصولك المسموح بها لذا يعرض القيمة بدلاً من الحكم عليها.

البدائل تُحتسب. العميل الذي يرسل */* قد عرض كلا النوعين ولا يتم الإبلاغ عنه أبدًا، ومعامل charset على Content-Type يُتجاهل. سجل مُلتقط قبل أن يسجل mcpsnoop هذه الترويسات يبقى صامتًا بدلاً من الإبلاغ عن كل إطار فيه لترويسة لم يدونها أحد، وstdio لا يملكها إطلاقًا.

Authorization لا يتم التقاطها عمدًا. تحويل تحدي إلى حقائق رمزية هي مشكلة بحد ذاتها ووضع رمز حامل على القرص ليس هو الحل لها. Mcp-Session-Id وLast-Event-ID لا يتم التقاطهما أيضًا. أزال إصدار 2026-07-28 كلاهما ويخبر الخادم بتجاهلهما، لذا لا توجد قاعدة متبقية للتحقق منها.

اكتشاف انجراف تعريف الأداة

أول tools/list كامل يُلاحظ لملصق خادم يصبح خط الأساس الموثوق به. تقارن الجلسات اللاحقة ذلك الخط الأساسي حقلاً بحقل:

  • الوصف
  • العنوان
  • مخططات الإدخال والإخراج
  • التعليقات التوضيحية والأيقونات

الأدوات التي أُضيفت أو أُزيلت تُقارن أيضًا، وهي مقارنة مجموعات وليست مقارنة حقول.

التعليقات التوضيحية هي الأهم، نظرًا لأن أداة معتمدة مع readOnlyHint تعلن لاحقًا عن نفسها كأداة تخريبية هي السحب المفاجئ الذي وُجد هذا الفحص من أجله، وتخبر المواصفة العملاء بمعاملة التعليقات التوضيحية كغير موثوقة. يُتتبع العنوان والأيقونات لأنهما ما يراه المستخدم، وتصنف المواصفة title للأداة فوق annotations.title واسمها. يعلّم جدول الجلسات وملخص الأدوات عن الانجراف دون حظر أو تغيير حركة مرور MCP.

تُقارن التعليقات التوضيحية من خلال افتراضاتها الافتراضية في المواصفة، لذا فإن الخادم الذي يبدأ في توضيح تلميح كان يعتمد عليه بالفعل لا يتم الإبلاغ عنه. خط أساس مُسجل قبل أن يتتبع mcpsnoop حقلاً يستمر في العمل للحقول التي يسجلها ويذكر أيها لا يمكنه الإجابة عنها. أعد التسجيل باستخدام mcpsnoop baseline --accept بمجرد أن تثق في التعريفات الحالية.

تغيير ما تسجله عملية التنقيح يغير ما تقارنه عملية كشف الانجراف. خط أساس مأخوذ دون --redact-value ثم يُفحص مقابل التقاط مأخوذ مع أحدها يبلغ عن الحقول المنقحة كمتغيرة، وهو صحيح، نظرًا لأن التعريف المسجل تغير فعلًا. أعد التسجيل باستخدام --accept بعد تغيير إعدادات التنقيح.

استخدم --label مستقرًا وفريدًا لكل خادم قد يتعارض اسم أمره أو مضيفه المستهدف بخلاف ذلك. تُخزن خطوط الأساس تحت دليل حالة mcpsnoop العادي، لذا تنطبق MCPSNOOP_HOME وXDG_STATE_HOME.```bash mcpsnoop check --fail-on drift session.jsonl mcpsnoop baseline session.jsonl mcpsnoop baseline --accept session.jsonl # trust a legitimate definition change mcpsnoop baseline --reset session.jsonl # trust the next complete tools/list

root@kitploit:~
في CI المؤقت يبدأ دليل الحالة فارغًا، لذا لا يوجد لدى التشغيل ما يقارن به فيسجّل خط الأساس بدلاً من التحقق منه. **التشغيل الذي طُلب منه الفشل عند الانحراف ثم لم يتحقق من أي شيء لا ينجح**، ويشير إلى الدليل الذي يجب الاحتفاظ به. هذه هي الحالة الوحيدة التي يُعد فيها تسجيل خط الأساس فشلًا. بدون `drift` في `--fail-on`، يُعد تسجيله أمرًا اعتياديًا ولا يغيّر رمز الخروج.

لذا يجب أن يبقى خط الأساس بين عمليات التشغيل حتى يكون لبوابة الانحراف أي معنى. وجّه `--baseline` إلى دليل مُضمّن في المستودع أو مخزّن مؤقتًا، أو عيّن `MCPSNOOP_HOME` إلى مسار محفوظ.```
recorded first-seen tool baseline (trusted, not verified)
check failed: drift

بعد اكتمال التثبيت، يمكنك تشغيل الأداة باستخدام الأمر التالي:

root@kitploit:~
toolname --help

لمزيد من المعلومات حول خيارات سطر الأوامر، راجع قسم الاستخدام في الوثائق.

المتطلبات الأساسية

  • Python 3.8 أو أحدث
  • pip (مدير حزم Python)
  • الوصول إلى الإنترنت لتنزيل التبعيات

التثبيت من المصدر

إذا كنت تفضل التثبيت من الكود المصدري، فاتبع الخطوات التالية:

  1. استنسخ المستودع:
root@kitploit:~
git clone https://github.com/example/toolname.git
  1. انتقل إلى دليل المشروع:
root@kitploit:~
cd toolname
  1. ثبّت الحزمة في الوضع القابل للتحرير:
root@kitploit:~
pip install -e .

التحقق من التثبيت

لتأكيد أن التثبيت تم بنجاح، شغّل:

root@kitploit:~
toolname --version

يجب أن يعرض هذا رقم الإصدار الحالي للأداة.```bash mcpsnoop check --fail-on drift --baseline .mcpsnoop/baselines session.jsonl

root@kitploit:~
`drift` اختياري لـ `check`. البوابة الافتراضية `error,invalid,warn` لم تتغير.

### اكتشاف ميزة لم يتفاوض عليها أي من الطرفين

نقل SEP-2133 الميزات الاختيارية خارج البروتوكول الأساسي إلى الامتدادات،
المُعلن عنها في خريطة `extensions` لقدرات كل طرف. Tasks واحدة منها،
لذا في 2026-07-28، فإن `tasks/get` أو `notifications/tasks` أو `tools/call`
التي تُجاب بمقبض مهمة لا تعني شيئًا إلا إذا قال الطرف الآخر إنه يتحدث Tasks.

عندما لا يحدث ذلك، يكون المواصف صريحًا: يجب على الطرف الداعم إما
التراجع إلى السلوك الأساسي أو رفض الطلب. القيام بذلك على أي حال هو السبب في أن ميزة
تبدو وكأنها موصولة ثم لا تفعل شيئًا بهدوء، وما يحصل عليه القارئ
بدلاً من ذلك هو `-32601` أو `-32021` بعد عدة إطارات، أو مهمة لا
تتقدم أبدًا. يحذر mcpsnoop على الإطار الذي وصل إلى الامتداد ويسمي
الطرف الذي لم يعلن عنه أبدًا.```
tool "slow" answered with a task handle uses the io.modelcontextprotocol/tasks
extension, which the client never advertised

إنه تحذير warn، لذا فإن فحص check الافتراضي يفشل بسبب وجوده. ويبقى صامتًا كلما تعذّر على الالتقاط إظهار ما تم التفاوض عليه، وهو التقاط يبدأ بعد المصافحة أو التقاط قامت أدوات التنقيح الخاصة بك بمسح قدراته، وعلى المراجعات قبل 2026-07-28، حيث تكون tasks/* بروتوكولًا أساسيًا واستخدامها صحيح.

وضع علامة على ميزات البروتوكول المهجورة

مراجعة 2026-07-28 تهجر Roots وSampling وLogging. فهي تستمر في العمل لمدة عام على الأقل، لذا يقوم mcpsnoop بوضع علامات عليها بدلًا من معاملتها كأخطاء. ويقوم كل من الدفق ومفتش القدرات والتصدير بوضع علامات عليها، ويذكر كل مؤشر البديل.

اثنان من الثلاثة أصبحا الآن قابلين للوصول فقط من خلال طلب متعدد الجولات، حيث يقع اسم الطريقة داخل خريطة inputRequests الخاصة بالخادم بدلًا من أن يكون على الإطار نفسه. ويتم وضع علامات على تلك أيضًا، لذا فإن الخادم الذي انتقل إلى النمط الجديد لا يتوقف عن الإبلاغ بصمت.```bash mcpsnoop check --fail-on deprecated session.jsonl

root@kitploit:~
مثل `drift`، فإن `deprecated` اختياري. التشغيل الافتراضي يُبلغ عن العدد ويبقى أخضر، لذا فإن جلسة تستخدم ميزة مهملة لا تزال قانونية لا تجعل CI يتحول إلى الأحمر من تلقاء نفسه.

### بنى المخطط التي تتعامل معها العملاء بشكل سيئ

يمكن أن يكون الخادم صالحًا تمامًا ومع ذلك يكون صعبًا على الوكيل استخدامه. تختلف العملاء في مقدار دعمهم الفعلي لـ JSON Schema، والأداة التي يستمر النموذج في استدعائها بشكل خاطئ غالبًا ما تكون أداة طلب مخططها أكثر مما يقدمه العميل.

ملخص الأدوات، الذي يُفتح بـ `s`، يحتوي على عمود SCHEMA يسمي أبرز ما في مخطط كل أداة معلنة، مع `+` في النهاية عندما يكون هناك أكثر من نوع واحد.

| المعروض | المعنى |
|---|---|
| `no root` | `inputSchema` غائب، أو ليس كائن JSON، أو له نوع جذر غير `"object"` |
| `dialect` | `$schema` تسمي لهجة غير 2020-12 التي تفترضها المراجعة افتراضيًا |
| `ext ref` | `$ref` يشير خارج المستند، وهي الحالة التي تحذر المواصفات المنفذين من اتباعها بشكل أعمى |
| `oneOf`, `anyOf`, `allOf`, `not` | كلمة تركيب، تُعالج بشكل غير متسق عبر العملاء |
| `ref` | `$ref` يشير داخل نفس المستند |
| `untyped` | خاصية لا تعلن عن نوع ولا عن أي طريقة أخرى لقول ما تقبله |

كل ما عدا الأول هو ملاحظات وليس أحكامًا. مخطط يستخدم `oneOf` ليس خاطئًا، فقط من المرجح أن يُقرأ بشكل مختلف من قبل عملاء مختلفين، والمخطط قد يعلن أي لهجة يريدها. `no root` هو الاستثناء: تعريف `Tool` يتطلب `inputSchema` ويثبت نوع جذره على `"object"`، لذا فإن العميل الذي يتحقق من صحة القائمة يرفض تلك الأداة تمامًا ولا تصبح قابلة للاستدعاء أبدًا، دون أي شيء على الشبكة يوضح السبب. `no root` يتصدر العمود لهذا السبب، والمخطط الذي نقّحه mcpsnoop الخاص به لا يُبلغ عنه أبدًا، لأن المخطط غير القابل للقراءة ليس مخططًا خاطئًا.

هذا التقسيم يحدد ما يفعله `check` بها. `no root` هو تحذير على إطار `tools/list`، لذا يفشل بوابة `error,invalid,warn` الافتراضية دون أي علم على الإطلاق، وهذا هو الهدف: الخادم الذي يرسل أداة غير قابلة للاستخدام يجيب على كل مصافحة بشكل طبيعي ولا يتلقى ببساطة `tools/call` أبدًا. الملاحظات تُحسب كـ `schema_findings` وتُبلغ تحت `schema findings:`، ولا تفشل التشغيل إلا عندما تضيف `schema` إلى `--fail-on`. كلاهما يصل إلى `--format junit` و`--format sarif`، و`export` يحمل قائمة كل أداة تحت `summary.definitions.per_tool[].findings`.```bash
mcpsnoop check session.jsonl                     # a non-object root already fails this
mcpsnoop check --fail-on schema session.jsonl    # and now so do the observations

العمود يحمل لون التحذير ولا يحمل أبدًا اللون الأحمر لعمود ERR، و ما زال mcpsnoop لا يغيّر شيئًا في حركة المرور التي يعيد توجيهها.

لا يتم حل أي شيء أو جلبه. يتم التعرف على $ref خارجي من خلال شكله وحده، ولا تتم قراءة المخطط الذي يشير إليه أبدًا.

إعادة تشغيل استدعاء تم التقاطه عبر HTTP

r يعيد إصدار استدعاء تم التقاطه ضد خادم مباشر. بالنسبة لالتقاط stdio، يكون الأمر في السجل، لذا يطلق mcpsnoop نسخة معزولة ويرسل الطلب إليها. لا يحتوي التقاط HTTP على أمر لإطلاقه، ونقطة النهاية التي يسجلها تُجرّد من معلومات المستخدم الخاصة بها ومن كل قيمة استعلام، لذا فهي تسمّي الخادم دون أن تكون عنوانًا للاتصال به.

لذا فأنت تحدد أين يذهب إعادة التشغيل، ولا يقوم mcpsnoop أبدًا بالاتصال بنقطة إنتاج لأن شخصًا ما ضغط على مفتاح.```bash mcpsnoop open --replay-target https://api.example.com/mcp session.jsonl mcpsnoop open --replay-target https://api.example.com/mcp
--replay-header 'Authorization: Bearer sk-…' session.jsonl

root@kitploit:~
بدون `--replay-target`، تُشير جلسة HTTP إلى ذلك بدلاً من تقديم مفتاح لا يمكن أن يعمل. ومع وجوده، لا يزال `r` يطلب التأكيد قبل الإرسال الأول للجلسة، بنفس الطريقة التي يُطلب بها تأكيد أمر مُسجَّل قبل تنفيذه.

تصل بيانات الاعتماد إلى الخادم عبر `--replay-header` ولا شيء غير ذلك. لا يسجّل mcpsnoop أي ترويسة `Authorization` ولا يعيد تشغيل أيًا منها، لذا لا يوجد شيء مُلتقَط يمكن أن يُسرّبه إعادة التشغيل.

يحمل طلب POST المُعاد تشغيله ما يفرضه النقل كأمر إلزامي، وهو ما لا يفعله طلب POST للجسم المُلتقَط المجرّد: `MCP-Protocol-Version`، وترويسة `Accept` تُدرج كلاً من `application/json` و`text/event-stream`، و`Mcp-Method`، و`Mcp-Name` حيث تتطلبه المواصفات، وكل `Mcp-Param-*` مُلتقَط. تُعاد إرسال تلك الترويسات حرفيًا من الالتقاط، بما في ذلك الحارس المشفَّر base64، لذا لا يمكن أن تتعارض مع الجسم بالطريقة التي قد يحدث بها إعادة اشتقاق. الترويسة الوحيدة التي لا تُنسخ هي إصدار البروتوكول، لأن الجسم المُعاد تشغيله يُعلن عن المراجعة التي يتحدث بها mcpsnoop ويجب أن تطابق الترويسة الجسم.

يُشتق `Mcp-Name` من الجسم المُرسَل بدلاً من نسخه، لأن المواصفات تستمدّه من `params.name` أو `params.uri` وتتطلب من الخادم رفض ترويسة تتعارض مع الجسم، لذا فإن التعديل الذي يعيد تسمية الأداة كان سيرسل الاسم القديم بخلاف ذلك. تعكس ترويسات `Mcp-Param-*` الوسائط المُلتقَطة، لذا فإن إعادة تشغيل مُعدَّلة لا ترسل أيًا منها بدلاً من تأكيد شيء عن جسم أعاد شخص ما كتابته. لا يمكن للالتقاط تعيين ترويسات إلا في تلك العائلة الواحدة. السجل هو ملف يتداوله الأشخاص، والسماح له بتسمية أي ترويسة كان سيسمح له بالكتابة فوق الترويسات الإلزامية أو إضافة بيانات اعتماد لم يمررها أحد.

توقف `Mcp-Param-*` التي نظّفتها قاعدة تنقيح إعادة التشغيل مع ذكر سبب. إرسال العنصر النائب كان سيضع بايتات mcpsnoop الخاصة على خادم حي كما لو كان مستخدم قد كتبها.

يُرفض إعادة التوجيه بدلاً من اتباعها. العنوان هو الذي سمّيته وأجبت عنه، واتباع 307 كان سيسلّم ذلك الاختيار إلى الطرف البعيد، مع إعادة إرسال الجسم، وعلى قفزة تغيّر المنفذ فقط، بيانات الاعتماد أيضًا. يُبلغ mcpsnoop عن المكان الذي أراد الخادم إرساله إليه ويترك لك قرار تسمية ذلك المكان بدلاً منه.

يُقرأ كل من الإجابة التي تصل ككائن JSON واحد وتلك التي تصل كتدفق أحداث، ويُسمّى الفشل بدلاً من ترقيمه:

- يُبلغ رمز 401 عن المخطط الذي طلبه الخادم
- يُبلغ `-32020` عن الشيء الذي اعترض عليه
- يُشير رمز 400 أو 404 غير الخاص بـ JSON-RPC إلى أن العنوان ليس نقطة نهاية HTTP قابلة للبث من هذه المراجعة

### تمييز زمن استجابة الخادم عن زمن المستخدم

في طلبات متعددة الجولات، تكون استدعاء الأداة الواحدة عدة طلبات، وتقع الثواني التي قضاها شخص في الإجابة على استفسار داخل تلك الفترة. هذا مقصود، لأن تلك الفترة عادةً هي التي تريد رؤيتها أكثر من غيرها، لكنه يعني أن رقمًا واحدًا لا يمكنه الإجابة على السؤالين معًا.

في سلسلة `book_flight` حيث عمل الخادم 1.2 ثانية بينما استغرق المستخدم 37، يُلقي `check --max-duration 5s` اللوم على الأداة لمدة 38.2 ثانية. وما زال يفعل ذلك، لأن تغيير معنى ذلك العلم كان سيُرخي كل خط أنابيب يضبطه بالفعل. بدلاً من ذلك، يسمّي شقيقان ما يقيسانه.```bash
mcpsnoop check --max-server-duration 1s session.jsonl   # the server's share alone
mcpsnoop check --max-round-trips 2 session.jsonl        # how chatty a tool is

بعد اكتمال التثبيت، يمكنك التحقق من أن الأداة تعمل بشكل صحيح عن طريق تشغيل الأمر التالي:

root@kitploit:~
toolname --version

يجب أن ترى رقم الإصدار المطابق للإصدار الذي قمت بتثبيته. إذا واجهت أي أخطاء، فتأكد من أن جميع التبعيات مثبتة بشكل صحيح وأن متغيرات البيئة الخاصة بك مضبوطة بشكل صحيح.

الاستخدام

لبدء استخدام الأداة، يمكنك تشغيلها مع الخيارات المتاحة. فيما يلي بعض الأمثلة الشائعة:

root@kitploit:~
toolname scan --target example.com
toolname report --format json

لمزيد من المعلومات حول جميع الخيارات المتاحة، يمكنك استخدام:

root@kitploit:~
toolname --help

أمثلة متقدمة

يمكنك دمج خيارات متعددة لتحقيق نتائج أكثر تحديدًا. على سبيل المثال، لفحص نطاق معين مع إخراج مفصل:

root@kitploit:~
toolname scan --target example.com --verbose --output results.txt

التكوين

يمكن تخصيص الأداة من خلال ملف تكوين يقع في ~/.config/toolname/config.yaml. يمكنك تحديد خيارات مثل:

  • مستوى السجل الافتراضي
  • مهلة الطلبات
  • عدد المحاولات القصوى

استكشاف الأخطاء وإصلاحها

إذا واجهت مشاكل، فراجع قسم الأسئلة الشائعة أو افتح مشكلة في مستودع GitHub. تأكد من تضمين:

  • إصدار الأداة
  • نظام التشغيل الخاص بك
  • الخطوات اللازمة لإعادة إنتاج المشكلة
  • أي رسائل خطأ ذات صلة

الترخيص

هذه الأداة مرخصة بموجب رخصة MIT. راجع ملف LICENSE لمزيد من التفاصيل.``` assertion failed: 1 tool call exceeded the 1s server budget (worst: tool "book_flight" held for 1.2s) assertion failed: 1 tool call exceeded the 2 round trip budget (worst: tool "book_flight" took 3)

root@kitploit:~
كلاهما معطّل افتراضيًا، لذا فإن تشغيل `check` الافتراضي لا يتأثر، وكلاهما
يُقرأ من طوابع الإطارات ومن رابطٍ كان mcpsnoop قد استنتجه بالفعل، لذا لا يخمّن أيٌّ منهما النية.

اضغط `i` في واجهة TUI للحصول على التفصيل، أو اقرأ `interactions` في تصديرات
json والنص وhtml. كل إدخال هو عملية منطقية واحدة مع عدد جولاتها ذهابًا وإيابًا،
وإجماليها، وحصة الخادم من الاحتفاظ بها، وحصة انتظارها على العميل، بالإضافة إلى
سطر لكل قفزة يسمّي ما طلبته كل إجابة. يكتسب ملخص كل أداة عمود `TRIPS` بحيث
تظهر الأداة كثيرة الكلام دون فتح أي شيء.

يضع `export --format har` حصة الخادم في `wait` والباقي في
`blocked`، وهذا هو الغرض من ذلك الحقل، بحيث يتوقف العارض عن رسم انتظار خادم
دام 38 ثانية ولم يحدث أبدًا.

تُجمَّع الأعداد والحصتان مع وصول الإطارات بدلًا من اشتقاقها عند الطلب، لأن
المخزن المباشر يحرر الإطارات القديمة ليبقى ضمن ميزانيته، وكانت الإجابة المشتقة
ستكون نافذة بصمت بدلًا من سلسلة. يُقرأ تفصيل كل قفزة من الإطارات التي ما زالت
محفوظة، ويُذكر ذلك عندما يكون جزءًا من قفزة واحدة فقط. `ServerTime + ClientTurnaround`
يساوي الإجمالي بالبناء لا بحسابٍ على أحد أن يثق به.

يحكم `--max-round-trips` على سلسلة ما زالت قيد التشغيل، لأن كل طلب قدّمته
بالفعل قابل للعدّ، والخادم الذي يطلب مرارًا وتكرارًا ينتج بالضبط العملية التي
لا يُنهيها أحد أبدًا. ينتظر `--max-server-duration` نهايةً، وهي القاعدة التي
يطبّقها `--max-duration` بالفعل، لأن العملية التي ما زالت مفتوحة لا تملك زمن
استجابة ليُحكَم عليه.

العملية التي لم يستطع mcpsnoop ربطها تبقى إدخالها الخاص بقفزة واحدة. يرفض
`matchRetry` رابطًا غامضًا عن قصد، ولا يسدّ هذا العرض تلك الفجوة.

العملية التي استغرقت طلبًا واحدًا لا تحمل تفصيل قفزات، لأن القفزة الواحدة
تعيد صياغة الإجماليات أعلاه كلمةً بكلمة. تبلغ السلسلة عن قفزة واحدة لكل طلب،
وتذكر ذلك عندما لا يعود المخزن يحمل كل إطار أو عندما تستقر العملية خارج زوج
الطلب والإجابة الذي تتكوّن منه القفزة، وهو ما يفعله مقبض المهمة.

### انظر ما طلبه خادم من مستخدمك

الاستجواب هو المسار الوحيد في MCP حيث يكتب شخص بيانات إلى خادم، وتحت
MRTR لم يعودا السؤال والجواب نصفين لتبادلٍ واحد. السؤال مدفون في
`InputRequiredResult`، ويعود الجواب داخل `inputResponses` عند إعادة محاولة
بمعرّف مختلف، والشيء الوحيد الذي يربطهما هو الرابط الذي يستنتجه mcpsnoop
بالفعل.

بدون ذلك الاقتران، يظهر طلب كلمة مرور مرفوض كخطأ أداة عادي.```
tools/call login_legacy [form] creds: decline after 3s
  password string

اضغط l في واجهة TUI، أو اقرأ elicitations في ملفات التصدير json والنص وhtml. كل صف يسمّي العملية التي قاطعها السؤال، والوضع، والرسالة، وما طُلب، وما فعله المستخدم والمدة التي استغرقها. السؤال الذي لم يُجب عنه أي إعادة محاولة يظهر كـ"قيد الانتظار"، وهو ما يجعل MRTR نتيجة عادية وليست خطأ، لأن المواصفات تخبر الخوادم ألا تفترض أن العميل سيعيد المحاولة إطلاقاً.

صفوف النماذج تسرد أسماء خصائص requestedSchema وأنواعها المعلنة. خاصية استُبدل مخططها الفرعي بقاعدة تنقيح تظهر بنوع غير معروف بدلاً من العنصر النائب، لأن العنصر النائب ليس شيئاً أعلنه الخادم. صفوف URL تحمل العنوان كاملاً، وهو ما تجعله المواصفات ظاهراً للعميل قبل الموافقة، وتسمّي المضيف منفرداً، وهو ما تقول بإبرازه ضد انتحال النطاقات الفرعية.

لا يحمل السجل أبداً قيمة مُرسلة. ما كتبه المستخدم يبقى في الالتقاط لمن يحتاجه، وتركه خارج سطح ملخص صُمم ليُصدَّر ويُنسخ حولياً هو ما يُبقي هذا خارج قصة التنقيح تماماً. الأمر الأهم في وضع url، حيث تضع المواصفات بيانات الاعتماد عمداً.

إعادة المحاولة تجيب عن الجولة التي صدرت منها ولا غيرها. يخبر MRTR الخادم بأنه عندما يحذف العميل بعض ما طُلب، يجب أن يطلب مرة أخرى في جولة جديدة، لذا فإن جولة سابقة تحمل مفتاحاً بلا إجابة بجانب مفتاح مُجاب هي حركة مرور عادية، ويبقى النصف بلا إجابة قيد الانتظار بدلاً من استعارة إجابة الجولة اللاحقة.

سؤال واحد مُسجَّل محدود. الرسالة وعنوان url وقائمة الحقول محفوظة طوال عمر الجلسة، خارج ميزانية الإطار التي تُطلق الأجسام، لذا لا يمكن للخادم جعل أحدها مكلفاً بشكل تعسفي. الحدود أعلى بكثير من أي سؤال حقيقي، والرسالة المقتطعة تقول إنها اقتُطعت.

لا شيء هنا يحذّر ولا شيء هنا يغيّر رمز خروج check. السجل يسجّل ما حدث. لا يحكم عليه.

ابحث عن الأداة التي تفشل مرة واحدة من كل أربع

يقرأ check جلسة واحدة ويقرأ diff جلستين بالضبط، لذا فإن الأداة التي تفشل أحياناً تبقى غير مرئية حتى يفتح أحدهم الالتقاطات يدوياً. عبر ستة عشر التقاطاً لخادم يجيب run_query فيه بـisError حوالي ربع الوقت، يبلّغ check عن الأحدث منها، بصدق، على أنه نظيف.```bash mcpsnoop stats mcpsnoop stats --since 7d --label prod mcpsnoop stats --limit 20 --format json

root@kitploit:~
Since you did not provide the actual content to translate, I cannot produce a translation. Please provide the chunk text you want translated.```
read 16 logs of 16 in ~/.local/state/mcpsnoop/sessions

SERVER       TOOL          CALLS   ERR  PROTO    FAIL%       SESS       p50      p95      p99      DEF
flaky-demo   run_query        13     3      0    23.1%       3/13     434ms    519ms    519ms     195B
docs-mirror  run_query         3     1      0    33.3%        1/3     357ms    434ms    434ms     195B
docs-mirror  search_docs      12     0      0     0.0%        0/3     377ms    386ms    386ms     200B
flaky-demo   search_docs      52     0      0     0.0%       0/13      42ms     58ms      59ms    200B

ERR وPROTO عمودان منفصلان لأن المواصفات تجعلهما شيئين منفصلين. الأداة التي تجيب بـisError تُبلغ عن شيء يمكن لنموذج أن يتصرف بناءً عليه ويعيد المحاولة. خطأ JSON-RPC يعني أن الطلب أو الخادم خاطئ. SESS هو عدد الجلسات التي شهدت فشلًا مقسومًا على الجلسات التي استدعت الأداة، وهو سؤال "تشغيل واحد من كل عشرة" الذي لا يمكن لمعدل عبر الاستدعاءات الإجابة عنه.

ترتبط الصفوف بالخادم والتسمية معًا. الخادم هو الأمر المسجل ودليل العمل لـstdio ونقطة النهاية لـHTTP، وهو نفس الهوية التي يستخدمها inventory. أي نصف بمفرده يجمع ما لا ينبغي: التسمية وحدها تدمج خادمين يشتقان اسمًا واحدًا، وهو ما يحدث كلما شغّل نسختان من مشروع نفس نقطة الدخول، والهوية وحدها تدمج أمرًا واحدًا شُغّل عمدًا كـprod ومرة أخرى كـstaging. كلا الخطأين يلطخان توزيعين نظيفين في توزيع واحد لا يصف أيًا منهما.

عندما يتشارك صفان في تسمية، تحمل خلية SERVER دليل العمل أو نقطة النهاية التي تميّزهما، ويحمل JSON command وcwd وendpoint في كل صف. الاسم الذي لم يكن غامضًا أبدًا يُترك كما هو، لذا يبقى الجدول العادي دون تغيير.

تُطوى كل جلسة في سجل، وليس الأولى فقط، لذا فإن ملفًا صُنع بدمج عمليات تسلسل يحسبها جميعًا.

تُجمّع النسب المئوية عبر المدد الخام. متوسط المتوسطات هو متوسط لا شيء. عملية واحدة متعددة الرحلات هي استدعاء واحد بمدّة واحدة مهما استغرق من طلبات، والاستدعاء الذي ما زال مفتوحًا يُحتسب ضمن CALLS دون أن يساهم في زمن الاستجابة.

يُحمَّل التقاط واحد في كل مرة. يُحمَّل سجل، ويُطوى في العدادات الجارية، ثم يُسقَط قبل فتح التالي، لذا فإن دليلًا يضم مئات الملفات يكلف أكبر التقاط واحد بدلًا من مجموعها.

يبلغ --limit افتراضيًا عن مئة من أحدث السجلات ويذكر الترويسة كم من كم قُرئ، لذا فإن إجابة محدودة لا تمر أبدًا كإجابة كاملة. stats يُبلغ ولا يقيّد: لا يكتب شيئًا، ولا يلمس خط الأساس، ولا يفتح مقبسًا، ويخرج بـ0 كلما نجح المسح.

معرفة أي الخوادم شُغّلت فعلًا هنا

النتيجة التي يكررها الناس باستمرار حول Shadow MCP هي أن المؤسسات تكتشف خوادم MCP تعمل بعدة أضعاف ما وافق عليه أي شخص، لأن الخادم غالبًا مجرد تبعية أضافها شخص ما إلى إضافة IDE. يحدث الشيء نفسه بشكل مصغّر على جهاز كمبيوتر محمول واحد، وكان mcpsnoop يسجّل الإجابة طوال الوقت دون أن يعرضها أبدًا.```bash mcpsnoop inventory mcpsnoop inventory --tools # also count what each server last advertised mcpsnoop inventory --format json # for something else to read

root@kitploit:~
صف واحد لكل خادم وليس لكل جلسة. مفتاح الصف هو الأمر المسجَّل
ودليل العمل، وليس التسمية أبدًا، لأن التسمية تأتي من
آخر عنصر مسار في الأمر و`node ~/one/build/index.js` و
`node ~/two/build/index.js` كلاهما يشتقان `index.js`. جلسة HTTP تُفتح بمفتاح على
نقطة النهاية التي وكّلها بدلًا من ذلك، لأن mcpsnoop لم يُطلق شيئًا هناك.

القراءة هي مغلّف واحد لكل سجل، وهو الإطار الوصفي الذي يكتبه الوكيل أولًا، لذا
يبقى هذا رخيصًا عبر دليل من التقاطات كبيرة. `--tools` هو الاستثناء ويقرأ
سجلًا واحدًا لكل خادم، وهو أحدث تشغيل لكلٍّ منها، ولهذا هو علامة وليس
عمودًا. وحتى عندها تكون القراءة محدودة، لأن جرد الأدوات هو
حالة جلسة يطويها المخزن أثناء تقدمه، لذا فإن التقاطًا بمئة ميغابايت
يُقرأ عبر نافذة ثابتة بدلًا من الاحتفاظ به كاملًا لإنتاج عدد صحيح واحد.

عندما لا يوجد عدد، يذكر الصف أيٌّ من ثلاثة أشياء حدث، لأن
السجل الذي تعذّرت قراءته ليس خادمًا لم يُعلن عن شيء، وجملة
واحدة لكليهما ستجعل mcpsnoop يذكر أمرًا خاطئًا.

أمر أعادت كتابته قاعدة `--redact` يُطبع كما سُجِّل ويُعلَّم، بدلًا من
تمريره كالأمر الذي نُفِّذ. تشغيلان لخادم واحد، أحدهما مُنقَّح
والآخر ليس كذلك، هما صفّان. لا يمكن لـ mcpsnoop معرفة ما استبدله العنصر النائب،
ودمجهما سيعني تخمين أن النصفين المخفيين متطابقان. خادم واحد يعمل تحت
قيمتين لـ `--label` هو صف واحد يحمل الاسمين، لأن المفتاح هو
الأمر وليس الاسم.

لا شيء في الصف يكتبه mcpsnoop. الأمر يأتي من whoever ثبّت
الخادم، ودليل العمل يأتي من نظام الملفات، والتسمية المشتقة
تأتي من الأمر. قيمة تحمل حرف تحكم تُقتبس بدلًا من
طبعها خامًا، لذا لا يمكن لدليل يحتوي اسمه على سطر جديد أن يُغلق
الحقل الذي يُطبع فيه ويجعل الأسطر التالية تُقرأ كخوادم لم
تعمل أبدًا. وسيطة تحتوي على مسافة تُقتبس أيضًا، لأن
`node "~/My Project/build/index.js"` لا يمكن تمييزها بخلاف ذلك عن وسيطتين.

أي شيء لم يستطع المسح طيّه يُذكر في الترويسة بدلًا من إسقاطه.
السجلات الفارغة تُحسب منفصلة عن التالفة، لأن السجل صفر البايت هو
بقايا عادية لتشغيل فشل فيه exec أو لوكيل HTTP لم يستدعه أحد.

المخرجات تُرتَّب بالاسم وليس بالأحدثية بحيث ينتج تشغيلان على دليل واحد
نفس البايتات، وهو ما يجعلها قابلة للاستخدام كخط أساس للمقارنة
لاحقًا.

ثغرتان موجودتان بالتصميم وليس بالإغفال. تشغيل مع
`--trace-file` كتب خارج دليل الجلسات ولن يظهر، و
`prune` يحذف السجلات، لذا فإن أول ظهور لا يكون أقدم أبدًا مما هو
ما زال على القرص. يبلّغ mcpsnoop عما عمل على هذا الجهاز عبره. لا يفحص شبكة،
ولا يقرأ إعداد عميل لم يُوجَّه إليه، ولا يحكم على شيء.

### التمييز بين خادم معطوب وأداة تقول لا

أداة تجيب بـ `result.isError` تعمل. لقد نظرت ولم تجد شيئًا، أو
رفضت المدخلات. خادم يجيب بخطأ JSON-RPC معطوب. كلاهما كان
رقمًا واحدًا في ملخص الأدوات، مما جعل أداة حسنة السلوك تبلّغ عن إخفاقات
المجال تبدو تمامًا كخادم معطوب، وتُرتب فوقه.

عمود `ERR` يفصل بينهما. الأحمر هو جانب الخادم، وهو خطأ JSON-RPC
أو مهمة انتهت بالفشل دون ذكر السبب. اللون التحذيري هو `isError` الخاص
بالأداة نفسها. أداة تحمل كليهما تُظهر العدّين موصولين، الأحمر أولًا، وسطر
تحت الجدول يسمّي الإجماليين كلما وُجد رقم تحذيري
لشرحه. يحمل التصدير نفس التقسيم كـ `protocol_errors` و
`tool_errors` بجانب إجمالي `errors` الذي يصلان إليه دائمًا.

`check --fail-on error` لم يتغيّر وما زال يعمل على أيٍّ منهما، لأن
بوابة تتجاهل أحدهما ستكون بوابة يمكن لخادم إيقافها بإرجاع
الآخر.```bash
mcpsnoop export -T json | jq '.summary.tools[] | {name, errors, protocol_errors, tool_errors}'

تعرّف على ما يكلّفك الخادم في السياق

تدخل تعريفات الأدوات في سياق النموذج في كل محادثة، وتدخل نتائج الأدوات في كل استدعاء. يقيس ملخص الأدوات (s) كليهما من الجلسة التي التقطتها فعليًا.

سطر definitions هو التكلفة الثابتة: ما يزنه tools/list لهذا الخادم قبل إجراء أي استدعاء واحد. يكسر عمود DEF ذلك لكل أداة، وRESULT هو ما كلّفته إجابات كل أداة حتى الآن. يبقى الجدول مرتبًا حسب الأخطاء وزمن الاستجابة، لذا امسح DEF للعثور على التعريفات المكلفة. يسرد التصدير الأثقل أولًا. سطر أسفل الجدول يسمّي النتيجة الأثقل على الإطلاق، وهو ما يخفيه الإجمالي.

أرقام التعريفات هي JSON مع إزالة المسافات البيضاء غير المهمة، لذا فإن الخادم الذي ينسّق tools/list بشكل جميل لا يُحتسب أكثر تكلفة من الذي لا يفعل ذلك، ويقيس نفس الخادم نفسه بشكل متساوٍ عبر عمليات الالتقاط. RESULT هو البايتات كما وصلت: النتيجة هي حمولة لمرة واحدة وليست عقدًا يستحق التطبيع.```bash mcpsnoop export -T json | jq '.summary.definitions'

root@kitploit:~
التصدير يحمل نفس الأرقام، لكل أداة ومقسّمة إلى وصف و
بايتات المخطط، لذا فإن الوصف الضخم والمخطط الضخم يبقيان قابلين للفصل ويمكن
تتبّع أيٍّ منهما عبر اللقطات. يخبرك `mcpsnoop diff` ما إذا كان الوصف أو
المخطط قد تغيّر بين جلستين. التصدير هو المكان الذي يعيش فيه حجم ذلك التغيير.

**هذه بايتات، وليست رموزًا.** يعتمد عدد الرموز على النموذج، لذا
فقياسها يعني تضمين محلل رموز واختيار أي نموذج. البايتات دقيقة
ويمكنك تطبيق النسبة الخاصة بك عليها. يُبلّغ `tools/list` غير المكتمل بما رآه
كحد أدنى ويوضح ذلك، بدلًا من تمرير مجموع جزئي على أنه الإجمالي.

### كشف عميل يعبث بحالة الخادم

في نمط الرحلات المتعددة ذهابًا وإيابًا، يسلّم الخادم للعميل قيمة
`requestState` غير شفافة ويجب على العميل إعادتها كما هي دون تغيير عند إعادة المحاولة. يُطلب من الخادم
معاملتها كمدخل يتحكم فيه المهاجم، لأن العميل الذي
يعبث بها قد يحاول تغيير سلوك الخادم أو تجاوز فحص التفويض.

وبكونه في منتصف الاتصال، يرى mcpsnoop القيمة تغادر وتعود، لذا يمكنه القول
متى انتهك العقد. هناك ثلاث طرق يمكن أن ينتهك بها، كل واحدة تُبلَّغ كتحذير بروتوكول عند إعادة المحاولة.

| المُبلَّغ | المعنى |
|---|---|
| `MRTR retry changed requestState` | أرسل العميل شيئًا مختلفًا عمّا أصدره الخادم |
| `MRTR retry is missing requestState` | أصدر الخادم قيمة وحذفها إعادة المحاولة |
| `MRTR retry invented requestState` | حملت إعادة المحاولة قيمة لم يصدرها الخادم أبدًا |

هذه انتهاكات بروتوكول من جانب العميل وليست ملاحظات من جانبنا، لذا
فهي تسلك مسار إشارة التحذير العادي و**يفشل تشغيل `check` الافتراضي عند حدوث واحدة**.
هذا مقصود. العميل الذي يعبث بحالة الخادم يستحق إيقاف البناء من أجله.

لا يتم عرض القيمة نفسها أو تسجيلها أبدًا، ولا شيء يفك ترميزها أو يحللها.
قد تكون كتلة مشفرة تحمل هوية ورموزًا، ومقارنة البايتات غير الشفافة
هي الفحص بأكمله.

هناك حالة واحدة خارج النطاق. عندما يجيب الخادم بقيمة `requestState` دون
`inputRequests`، فإن إعادة المحاولة العابثة لا تطابق شيئًا ولا تجيب عن أي مفاتيح، لذا
لا يبقى ما يربطها بالطلب الأصلي وتُقرأ كاستدعاء غير مرتبط
بدلًا من انتهاك.

التبادل المهجور لا يزعج التالي، ولا يُحتفظ به إلى الأبد
أيضًا. أربعة وستون تبادلًا مفتوحًا أكثر بكثير مما يملكه أي عميل في وقت واحد، لذا
فالجلسة التي تحمل أكثر من ذلك تحمل تبادلات لن يُنهيها أحد، ويُتقاعد الأقدم
لأن المواصفات تطلب من الخوادم منح تلك الحالة صلاحية قصيرة و
رفضها بعد ذلك. التقاعد يُحسب بدلًا من أن يكون صامتًا. يُظهر تذييل الدفق
`N unlinked` ويحمل التصدير `session.retired_exchanges`، لأن
إعادة المحاولة التي تصل لعملية متقاعدة تُقرأ كاستدعاء خاص بها، والقارئ
الذي يقارن الأعداد يستحق أن يُخبَر.

تقاعد واحدة يسمح أيضًا للمخزن الحي بتحريرها. تبقى العملية المتوقفة
قيد الانتظار عن قصد، لذا يمتد مداها عبر التبادل بأكمله، ويرفض المخزن
نسيان استدعاء معلق لأن الاستجابة قد لا تزال قادمة. بمجرد أن
يتقاعد الحد الأقصى عمليةً، لا يمكن لأي شيء الإجابة عنها، لذا فإن الاحتفاظ بها يُبقي استدعاءً حيًا
لا يمكن لأي قارئ الوصول إليه. ما تُبلغ عنه الجلسة لا يتغير. لا يزال
يُحسب كاستدعاء معلق وما زال يُحسب في `N unlinked`، لأن مقدار
الذاكرة التي يشغلها السجل وما يقوله السجل سؤالان مختلفان.

التبادل المهجور لا يزعج التالي. يخبر MRTR الخوادم بأنه
يجب ألا تفترض أن العميل سيعيد المحاولة أبدًا، لذا فإن المستخدم الذي يرفض استدراجًا
يترك عمليةً لن تسوّيها أي إطارات لاحقة أبدًا. يبحث mcpsnoop أولًا
بين العمليات التي يتوافق وجود `requestState` فيها مع إعادة المحاولة،
وهو ما تجعله المواصفات قاعدة في الاتجاهين، لذا فإن إعادة المحاولة المطابقة لا تزال
تجد العملية الوحيدة التي تواصلها حتى عندما يجلس تبادل مهجور على نفس
الأداة بجانبها. الفحص الذي يُبلّغ عن الانتهاكات الثلاثة أعلاه
يعمل فقط عندما لا يتوافق شيء، لذا فإن إعادة المحاولة غير المطابقة حقًا لا تزال
تُسمّى.

## المراقبة من جهاز آخر

أبقِ الالتقاط محليًا على الجهاز الذي يحدث فيه حركة المرور واستخدم SSH للقفزة
عبر الشبكة، لذا لا يحتاج mcpsnoop أبدًا إلى نقل عن بُعد خاص به.

### العرض المباشر

شغّل واجهة TUI على محطة عملك ومرّر مقبس mcpsnoop الخاص بالجهاز البعيد
إليها. يستخدم النفق المباشر توجيه مقبس SSH عبر Unix، لذا يجب أن يعمل كلا الطرفين
على Linux أو macOS. على Windows، استخدم نسخة السجل بعد الوفاة أدناه.```bash
# on your workstation, start the TUI
mcpsnoop

# create the remote socket directory once
ssh remote-user@remote-host 'mkdir -p ~/.local/state/mcpsnoop'

# print the tunnel command, then run the printed ssh -R line
mcpsnoop remote remote-user@remote-host

# on the remote host, wrap your server as usual
mcpsnoop -- node build/index.js

المقبس موجود تحت دليل الحالة الخاص بالجهاز البعيد، ويتم حله كـ MCPSNOOP_HOME، وإلا XDG_STATE_HOME/mcpsnoop، وإلا ~/.local/state/mcpsnoop. افتراضيًا، يفترض mcpsnoop الدليل الرئيسي لنظام Linux /home/<user> من user@host الخاص بك ويطبع تذكيرًا إلى stderr كلما تراجع إلى هذا التخمين. إذا تم حل الجهاز البعيد في مكان آخر، قم بتسمية الجزء الوحيد غير الافتراضي.```bash

a non-Linux or custom home, macOS is /Users/ and root is /root

mcpsnoop remote --remote-home /Users/remote-user remote-user@remote-host

an explicit MCPSNOOP_HOME on the remote

mcpsnoop remote --remote-mcpsnoop-home /srv/mcpsnoop remote-user@remote-host

an explicit XDG_STATE_HOME on the remote

mcpsnoop remote --remote-xdg-state-home /var/lib/state remote-user@remote-host

root@kitploit:~
### تحليل ما بعد الحادثة (Post-mortem)

قم ببث جلسة عن بُعد مباشرةً إلى واجهة TUI عبر SSH، دون الحاجة إلى نسخة محلية.```bash
ssh remote-user@remote-host 'cat ~/.local/state/mcpsnoop/sessions/session.jsonl' | mcpsnoop open -

للاحتفاظ بنسخة محلية بدلاً من ذلك، انسخ السجلات عبر scp إلى دليل الجلسات الخاص بك ثم شغّل واجهة TUI كالمعتاد.```bash

copy the remote logs into your local sessions directory

mkdir -p /.local/state/mcpsnoop/sessions scp remote-user@remote-host:'/.local/state/mcpsnoop/sessions/*.jsonl'
~/.local/state/mcpsnoop/sessions/

open the TUI, it backfills the copied sessions

mcpsnoop

root@kitploit:~
## الأمان

يشغّل mcpsnoop أمر الخادم الذي تغلّفه، لذا لا تغلّف إلا الخوادم التي تثق بها، وشغّل غير الموثوقة داخل حاوية. لا ينفّذ أبدًا أي شيء لم تضعه في إعدادات عميلك.

بالنسبة لسير العمل عن بُعد، استخدم نفق SSH أو نقل ملفات SSH بحيث تبقى مصادقة النقل والتشفير والتحقق من المضيف وتدوير المفاتيح وسياسة التدقيق ضمن إعداد SSH الحالي لديك.

### تنقيح ما تلتقطه

يمكن أن تتضمن الإطارات الملتقطة المطالبات ووسائط الأدوات وبيانات الاعتماد ونتائج الأدوات. إذا كانت الحمولات قد تحمل أسرارًا، فاختر الاشتراك في التنقيح لتنظيف نسخ التتبّع المرصودة بينما تظل البايتات المُمرَّرة عبر الوكيل تمر دون تغيير.

يستبدل التنقيح المستند إلى المفاتيح القيم الكاملة تحت مفاتيح JSON المطابقة، وتُطبَّق نفس مجموعة المفاتيح بأفضل جهد على وسائط سطر الأوامر للخادم المغلَّف، لذا يتم تنظيف `--api-key=sk-x` و`--token sk-x` تحت `--redact-secrets`. لا يمكن اكتشاف وسيطة تحمل سرًا دون اسم علم مميّز.

لا تعد نقطة نهاية HTTP جزءًا من أيٍّ من ذلك، لأنها ليست حمولة اخترت إرسالها. `--target` علم يجب تمريره لتشغيل الوكيل أصلًا، لذا سيصل عنوانه إلى سجل الجلسة مهما كانت إعدادات التنقيح لديك. يكتبه mcpsnoop مع إزالة معلومات المستخدم وكل قيمة استعلام والجزء المقتطع دائمًا، بالبناء لا بالنمط. تبقى مفاتيح الاستعلام، لأنها ما يميّز نقطتي نهاية لمضيف واحد، ويُسقَط الجزء المقتطع لأنه لم يصل إلى الخادم أصلًا. ما يُسجَّل يحدد الخادم وليس عنوانًا للاتصال به.

يستبدل التنقيح المستند إلى المسار فقط القيم المحددة بتعبير JSONPath، وهو مفيد عندما يكون اسم مفتاح شائع حساسًا في موضع واحد وآمنًا في آخر. كرّر `--redact-path` لتنظيف أكثر من موضع واحد.

يطبّق التنقيح المستند إلى القيمة تعبيرات منتظمة على قيم السلاسل المرصودة ونص stderr وإطارات النص غير JSON.

كلها بأفضل جهد. قد تفوت التعبيرات المنتظمة أسرارًا، أو تطابق نصًا غير ضار بشكل مفرط، أو تفشل في رؤية القيم المحوَّلة أو المشفَّرة.

لا يتحول التنقيح أبدًا إلى اتهام. كل فحص يقارن شيئًا مرصودًا بآخر، أو ترويسة توجيه بالجسم، أو قيمة `Mcp-Param` بالوسيطة التي تعكسها، أو مخطط أداة بما يتطلبه التنقيح منها، يعرف متى كان mcpsnoop هو الجانب الذي أعاد كتابة البايتات ويبقى صامتًا بدلًا من الإبلاغ عن خادم بسبب إعداد الخصوصية الخاص بالمستخدم. انحراف تعريف الأداة هو الاستثناء، وعمدًا، لأن تشغيل التنقيح يغيّر ما يُسجَّل وبالتالي ما يحمله خط الأساس. انظر [اكتشاف انحراف تعريف الأداة](#detect-tool-definition-drift).```bash
# built-in preset of common secret keys
mcpsnoop --redact-secrets -- node build/index.js

# or name your own keys
mcpsnoop --redact-key token,api_key,password -- node build/index.js

# scrub one location without redacting every field named password
mcpsnoop --redact-path '$.params.arguments.password' -- node build/index.js

# wildcards scrub every matching array element
mcpsnoop --redact-path '$.params.arguments.accounts[*].password' -- node build/index.js

# scrub obvious token-shaped values outside known keys
mcpsnoop --redact-value 'sk-[A-Za-z0-9]+' -- node build/index.js

# combine the layers in http mode
mcpsnoop http --target http://localhost:3000/mcp --redact-secrets --redact-value 'Bearer\s+\S+'

المساهمة

نرحب بالمسائل (Issues) وطلبات السحب (Pull Requests). راجع CONTRIBUTING.md للحصول على التفاصيل.

الترخيص

MIT

تنزيل الأداة