کدینگ‌عامل شما در پیدا کردن موارد در یک مخزن بسیار خوب عمل می‌کند، تا زمانی که آن‌ها متن باشند. اگر از Claude Code یا Cursor بپرسید دیتاشیت حسگر درباره دمای عملیاتی چه می‌گوید، آن‌ها جستجو می‌کنند، چیزی پیدا نمی‌کنند و یا حدس می‌زنند یا دست می‌کشند، چون دیتاشیت یک PDF است و رکورد تصمیم‌گیری یک فایل Word است. GroupDocs.Search.Mcp به صورت محلی در Docker اجرا می‌شود و به عامل یک ایندکس متن‑کامل بر روی آن اسناد می‌دهد، با همان حلقهٔ جستجو‑سپس‑خواندن که برای کد استفاده می‌کند:

ایندکس پوشهٔ docs را بسازید، سپس به من بگویید دیتاشیت حسگر دربارهٔ دمای عملیاتی چه می‌گوید و کدام ADR ذخیره‌سازی تلمتری را تصمیم‌گیری کرده است.

نسخهٔ گام‑به‑گام همراه با پیکربندی و عیب‌یابی در مستندات موجود است: چگونه به Claude Code یا Cursor اجازه دهید PDFها و اسناد Word را در یک مخزن جستجو کنند.

چرا grep خالی برمی‌گرداند؟

چون PDF و DOCX کلمات خود را به صورت متن ساده ذخیره نمی‌کنند. یک DOCX یک آرشیو zip است؛ یک PDF جریان‌های متنی خود را فشرده می‌کند. اگر هر دو را بایت به بایت جستجو کنید، کلمات وجود ندارند. ما این را با یک مخزن کوچک آزمایش کردیم: یک دیتاشیت PDF، یک رکورد تصمیم‌گیری معماری و یک سند نیازمندی‌ها در DOCX، و یک فایل منبع.

$ grep -ri "TimescaleDB\|operating temperature\|I2C" docs/
$ grep -rn "datasheet" src/
src/sensor.py:1:MAX_TEMP_C = 85  # see docs/datasheet

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

چه تغییری با یک ایندکس ایجاد می‌شود؟

عامل یک ابزار بازیابی برای اسناد دریافت می‌کند. سرور را از ریشهٔ مخزن ثبت کنید تا مخزن به عنوان پوشهٔ ذخیره‌سازی سوار شود:

claude mcp add groupdocs-search -- docker run --rm -i \
  -v "$(pwd)":/data ghcr.io/groupdocs-search/search-net-mcp:latest

سپس همان سوالات پاسخ می‌گیرند. این خروجی سرور در مخزن آزمایشی ما بود (مسیرها نسبت به ریشهٔ مخزن نشان داده شده‌اند):

-> add_to_index {"documentsPath":"docs","indexName":"gateway"}
<- Indexed 'docs' into index 'gateway': 3 document(s) added,
   3 in the index.

-> search {"query":"TimescaleDB","indexName":"gateway"}
<- documentsFound 1: docs/adr-007-telemetry-storage.docx

-> get_text_fragments {"query":"I2C","indexName":"gateway"}
<- === docs/requirements-v2.docx (1 occurrence(s)) ===
     …REQ-15: the I2C bus runs at 400 kHz.…
   === docs/tmp117-sensor-datasheet.pdf (1 occurrence(s)) ===
     …I2C address selection: ADD0 pin to GND gives 0x48…

یک پرس‌وجو هم‌زمان نیازمندی و خط دیتاشیت را یافت، که همان نوع ارجاع متقابلی است که به‌صورت دستی انجامش دشوار و با grep غیرممکن است. در ایندکس کوچک ما، جستجوها پس از اولین فراخوانی در ۸۰ تا ۲۴۰ میلی‌ثانیه بازگشتند.

حلقه‌ای که عامل از قبل می‌داند

user              agent                         Search MCP server
 |  "What does the datasheet say about I2C addresses?"         |
 |---------------->|                                           |
 |                 |-- search {"query":"I2C"} --------------->|
 |                 |<- requirements-v2.docx,                   |
 |                 |   tmp117-sensor-datasheet.pdf ------------|
 |                 |-- get_text_fragments {"query":"I2C"} --->|
 |                 |<- "...ADD0 pin to GND gives 0x48..." -----|
 |<- "0x48 with ADD0 to GND, 0x49 to V+ (datasheet, p.1);      |
 |    REQ-15 runs the bus at 400 kHz."                         |

search می‌گوید کدام فایل‌ها، get_text_fragments خطوط منطبق را همراه با چند کلمهٔ زمینه برمی‌گرداند و عامل هر دو را استناد می‌کند. این همان شکل grep است که به ۸۲ فرمت گسترش یافته: PDF، DOCX، XLSX، PPTX، HTML، Markdown، حتی رشته‌های ایمیلی که کسی به مخزن صادر کرده است.

به عامل بگویید چه زمانی از آن استفاده کند

عاملان دستورالعمل‌های پروژه را دربارهٔ زمان استفاده از ابزار دنبال می‌کنند. سه خط در CLAUDE.md یا AGENTS.md تفاوت بین عاملی که grep را امتحان می‌کند، شکست می‌خورد و دست می‌کشد، و عاملی که ابتدا ایندکس را جستجو می‌کند، ایجاد می‌کند:

PDF, DOCX and XLSX files under docs/ are indexed in the groupdocs-search MCP index
'docs'. grep cannot read them: use search (quote phrases) and get_text_fragments
for anything in specs, datasheets or ADRs, and cite the file.
Run update_index (indexName: docs) after pulling changes.

دو نکتهٔ نگهداری. ایندکس در .groupdocs-search-index/ در ریشهٔ پوشهٔ سوار شده نوشته می‌شود، پس آن را به .gitignore اضافه کنید. و پس از یک pull، update_index فقط موارد تغییر یافته را دوباره می‌خواند، بنابراین به‌روز نگه داشتن ایندکس تنها یک فراخوانی هزینه دارد.

Cursor و VS Code

همین کانتینر در هر کلاینت MCP کار می‌کند. در VS Code، یک workspace در .vscode/mcp.json می‌تواند هر پوشهٔ باز را سوار کند، بنابراین ایندکس پروژه را دنبال می‌کند:

{
  "servers": {
    "groupdocs-search": {
      "type": "stdio",
      "command": "docker",
      "args": [ "run", "--rm", "-i",
                "-v", "${workspaceFolder}:/data",
                "ghcr.io/groupdocs-search/search-net-mcp:latest" ]
    }
  }
}

Cursor از همان command و args تحت mcpServers در .cursor/mcp.json استفاده می‌کند. فایل پیکربندی را commit کنید و هر توسعه‌دهندهٔ پروژه ابزار را دریافت می‌کند؛ ایندکس را خارج از گیت نگه دارید.

چرا ابتدا همه چیز را به متن تبدیل نکنیم؟

می‌توانید: عامل هر PDF را وقتی نیاز دارد تبدیل کند، یا نسخه‌های Markdown را در مخزن بررسی کنید. هر دو برای تعداد کمی فایل کار می‌کنند. ایندکس یک بار تبدیل را انجام می‌دهد، با یک فراخوانی به‌روز می‌شود و می‌گوید کدام فایل مهم است پیش از این که عامل آن را بخواند، که این گامی است که زمینهٔ یک جلسهٔ طولانی را کوچک نگه می‌دارد. موتور پشت آن GroupDocs.Search است که اسناد Office و PDF را مستقیماً می‌خواند، نه از طریق یک مبدل که باید نگهداری شود.

محدودیت‌های صادقانه

  • در حالت ارزیابی یک ایندکس حداکثر ۱۰۰ سند را نگه می‌دارد و یک جستجو حداکثر ۱۰ نتیجه برمی‌گرداند؛ ابتدا get_license_status را فراخوانی کنید.
  • متن‑کامل، نه معنایی: عامل باید از کلماتی که اسناد استفاده می‌کنند، استفاده کند یا انواع مختلف را امتحان کند.
  • بدون OCR: یک دیتاشیت اسکن‌شده بدون لایهٔ متن فقط بر اساس ویژگی‌های فایل ایندکس می‌شود.
  • فقط Docker. در لینوکس، --user "$(id -u):$(id -g)" را اضافه کنید تا کانتینر بتواند ایندکس را در مخزنی که مالک آن هستید بنویسد.

پرسش‌های متداول

آیا Claude Code می‌تواند فایل‌های PDF را در مخزن من بخواند؟
نه با grep. با سرور GroupDocs.Search MCP می‌تواند آن‌ها را به‌صورت محلی جستجو و نقل قول کند، بدون اینکه ابتدا تبدیل شوند.

آیا این در Cursor و VS Code هم کار می‌کند؟
بله. همان آرگومان‌های docker run را در .cursor/mcp.json یا .vscode/mcp.json استفاده کنید؛ VS Code می‌تواند ${workspaceFolder} را سوار کند.

آیا ایندکس در کامیت‌های من قرار می‌گیرد؟
فقط اگر اجازه دهید. .groupdocs-search-index/ را به .gitignore اضافه کنید.

عمیق‌تر بروید