देर-सबेर कोई न कोई असिस्टेंट वाली चैट में पासपोर्ट की फ़ोटो डालकर कहेगा, "बस फ़ॉर्म भर दो"। सामान्य काम का विज़न मॉडल कोशिश तो करेगा। हो सकता है नाम भी सही पढ़ ले। पर वह यह नहीं बताएगा कि मशीन-रीडेबल ज़ोन (MRZ) के चेक डिजिट पास हुए या नहीं, हर बार तारीखें एक ही फ़ॉर्मैट में नहीं लौटाएगा, और अंदाज़ा लगाने के बजाय "मैं इसे पढ़ नहीं पाया" नहीं कहेगा।

यह कमी किसी टूल से अच्छी तरह भरती है। Model Context Protocol एजेंट को टूल कॉल करने देता है, और यह पोस्ट बताती है कि Claude Desktop, Claude Code, Cursor और दूसरे क्लाइंट को डॉक्यूमेंट-रिकग्निशन टूल कैसे दें, एजेंट को जवाब में क्या मिलता है, ख़र्च को सीमा में कैसे रखें, और किसी एजेंट को पहचान दस्तावेज़ों पर लगाने से पहले किन बातों पर सोचना चाहिए।

यह doc.cheap का ब्लॉग है, यानी उस API का जिस पर यहाँ इस्तेमाल हुआ MCP सर्वर चलता है। सर्वर MIT लाइसेंस के तहत है, और सेटअप से जुड़े सवाल इस तरह के किसी भी टूल पर लागू होते हैं।

एजेंट को क्या मिलता है

सर्वर npm पर @doc-cheap/mcp है (MIT, Node 20 या नया), और यह तीन टूल देता है:

टूल क्या करता है क्रेडिट ख़र्च होता है?
scan_document फ़ोटो या स्कैन से पासपोर्ट, राष्ट्रीय ID कार्ड या ड्राइविंग लाइसेंस पहचानता है और स्ट्रक्चर्ड नतीजा लौटाता है हाँ, सिर्फ़ तब जब दस्तावेज़ पहचाना जाए
check_balance बचे हुए क्रेडिट और इस महीने के काउंटर पढ़ता है नहीं (सिर्फ़ पढ़ता है)
search_docs सर्वर के साथ आई API डॉक्यूमेंटेशन में ऑफ़लाइन खोजता है नहीं (सिर्फ़ पढ़ता है)

हर टूल के साथ एक टाइटल, एक विवरण (अकाउंट से जुड़े दोनों टूल के विवरण में कीमत लिखी है), और MCP के वे व्यवहार-संकेत (behaviour hints) होते हैं जिन्हें क्लाइंट यह तय करने से पहले पढ़ता है कि आपसे पहले पूछे या नहीं: scan_document "सिर्फ़ पढ़ने वाला नहीं" के रूप में चिह्नित है, बाकी दो "सिर्फ़ पढ़ने वाले" के रूप में। सर्वर ऐसे निर्देश भी भेजता है जिन्हें मॉडल किसी भी कॉल से पहले पढ़ता है, कि यह क्या पहचानता है और एक कॉल की कीमत क्या है। टूल के अलावा चार प्रॉम्प्ट हैं (scan_document_to_json, check_document_expiry, batch_scan, explain_error), और डॉक्स का हर पेज सिर्फ़ पढ़ने लायक रिसोर्स के रूप में उपलब्ध है, जैसे doccheap://docs/reference/fields

scan_document पूरा नतीजा स्ट्रक्चर्ड JSON के रूप में और साथ में एक लाइन का सार लौटाता है, जैसे:

Scan 01a0af18-cd8d-7a61-9f2d-4c7b8e105da3: recognized · passport (GRC) · PARADEIGMA ELENI SOFIA · billed · 684 ms

(डॉक्स का एक काल्पनिक नमूना धारक।) इसके पीछे के JSON में धारक, दस्तावेज़ नंबर और ISO 8601 में तारीखें, हर फ़ील्ड अपने confidence बैंड के साथ, passed / failed / absent फ़ैसले के साथ MRZ लाइनें, और billed फ़्लैग होता है। पूरी बात इसी स्ट्रक्चर की है: एजेंट को पिक्सल का मतलब नहीं निकालना पड़ता, वह फ़ील्ड पढ़ता है।

इंस्टॉल: लोकल सर्वर

नीचे का हर क्लाइंट सर्वर को npx से चलाता है। कोई key सेट न हो, तो यह पब्लिक sandbox key इस्तेमाल करता है, जो हर IP एड्रेस पर कुल 10 पहचाने गए दस्तावेज़ मुफ़्त देती है और एक घंटे में ज़्यादा से ज़्यादा 10 रिक्वेस्ट। आज़माने के लिए इतना काफ़ी है। रजिस्टर करने पर 20 मुफ़्त क्रेडिट मिलते हैं; उसके बाद एक पहचाने गए दस्तावेज़ की कीमत $0.01 है।

Claude Desktop, Cursor और Windsurf एक ही ब्लॉक पढ़ते हैं, क्रमशः claude_desktop_config.json, ~/.cursor/mcp.json और ~/.codeium/windsurf/mcp_config.json में:

{
  "mcpServers": {
    "doc-cheap": {
      "command": "npx",
      "args": ["-y", "@doc-cheap/mcp"],
      "env": { "DOC_CHEAP_API_KEY": "sk_live_your_key" }
    }
  }
}

sandbox key पर चलाने के लिए env वाली लाइन हटा दें।

Claude Code:

claude mcp add-json doc-cheap '{"command":"npx","args":["-y","@doc-cheap/mcp"],"env":{"DOC_CHEAP_API_KEY":"sk_live_your_key"}}'

VS Code:

code --add-mcp '{"name":"doc-cheap","command":"npx","args":["-y","@doc-cheap/mcp"]}'

Gemini CLI और Kiro अपनी सेटिंग फ़ाइलों में यही mcpServers ब्लॉक इस्तेमाल करते हैं; हर फ़ाइल का पाथ MCP गाइड में है। बदलाव के बाद क्लाइंट रीस्टार्ट करें: सर्वर बदला हुआ एनवायरनमेंट सिर्फ़ नए सिरे से शुरू होने पर ही पढ़ता है।

इंस्टॉल: होस्टेड सर्वर

अगर आपका क्लाइंट कमांड चलाने के बजाय किसी URL से जुड़ता है, तो वही तीन टूल https://mcp.doc.cheap/mcp पर Streamable HTTP के ज़रिए होस्ट किए गए हैं, बिना लॉगिन के। key हेडर में जाती है, X-Doc-Cheap-Api-Key या Authorization: Bearer (दोनों भेजे जाएँ तो नाम वाला हेडर माना जाता है); key न हो तो sandbox key इस्तेमाल होती है।

Claude Code:

claude mcp add --transport http doc-cheap https://mcp.doc.cheap/mcp --header "Authorization: Bearer sk_live_your_key"

Cursor:

{
  "mcpServers": {
    "doc-cheap": {
      "url": "https://mcp.doc.cheap/mcp",
      "headers": { "Authorization": "Bearer sk_live_your_key" }
    }
  }
}

Claude Desktop और claude.ai में इसे Settings → Connectors में उसी URL के साथ कस्टम कनेक्टर के रूप में जोड़ें।

होस्टेड सर्वर आपकी मशीन की फ़ाइलें नहीं देख सकता, इसलिए वहाँ scan_document इमेज को image_base64 के रूप में या पब्लिक image_url के रूप में लेता है।

लोकल फ़ाइलों और URL पर जानबूझकर बाड़ लगाई गई है

टूल का आर्ग्युमेंट मॉडल चुनता है, और मॉडल को बातों में लाकर कुछ भी करवाया जा सकता है। इसलिए लोकल सर्वर मनचाहे पाथ नहीं पढ़ता:

  • image_path तब तक बंद रहता है जब तक आप DOC_CHEAP_IMAGE_ROOT को किसी एक डायरेक्टरी पर सेट न करें। पाथ पहले symlink के ज़रिए resolve किए जाते हैं, और .. या डायरेक्टरी से बाहर जाने वाला लिंक अस्वीकार किया जाता है। ग़ायब फ़ाइल और सीमा से बाहर की फ़ाइल, दोनों पर एक ही संदेश मिलता है, ताकि टूल से यह टटोला न जा सके कि कोई फ़ाइल मौजूद है या नहीं।
  • image_url का https: होना ज़रूरी है, वह सिर्फ़ पब्लिक एड्रेस पर resolve होना चाहिए (loopback, प्राइवेट, link-local और ऐसी ही दूसरी रेंज अस्वीकार की जाती हैं), ज़्यादा से ज़्यादा तीन रीडायरेक्ट फ़ॉलो करता है और हर कदम दोबारा जाँचता है, और उसकी सीमा 25 MB है।

अगर आपने पहले कभी किसी एजेंट के लिए फ़ाइल पढ़ने वाला टूल जोड़ा है, तो उसकी तुलना इस सूची से करें। "मॉडल तो सिर्फ़ समझदारी वाले पाथ ही देगा" कोई सुरक्षा सीमा नहीं है।

ख़र्च को सीमा में रखना

दो खूबियाँ एजेंट के इस्तेमाल को अनुमान लगाने लायक बनाती हैं:

  1. सिर्फ़ पहचाने गए दस्तावेज़ों का बिल बनता है। कॉल पर चार्ज तब लगता है जब दस्तावेज़ का प्रकार तय हो गया और सच में डेटा निकाला गया: ऐसा MRZ जिसके चेक डिजिट पास हों, कम से कम पाँच प्रिंटेड फ़ील्ड, या सही तरह डिकोड हुआ बारकोड। कोई दस्तावेज़ न मिलना, न पढ़ी जा सकने वाली इमेज, असमर्थित प्रकार, इंटरनल एरर या टाइमआउट, इनमें कुछ ख़र्च नहीं होता। नतीजे का billed फ़्लैग हर बार बताता है कि क्या हुआ। sandbox key पर कुछ भी चार्ज नहीं होता, और तब फ़्लैग बताता है कि यही स्कैन लाइव key पर बिल होता या नहीं।
  2. रीट्राई मुफ़्त बनाए जा सकते हैं। scan_document एक idempotency_key लेता है; लाइव key पर उसी key के साथ दोहराई गई कॉल दोबारा चार्ज करने के बजाय पहला सेव किया गया नतीजा लौटाती है। बिना key का रीट्राई दूसरा स्कैन है। दोहराई गई कॉल सेव किया गया नतीजा लौटाती है, इसलिए retain_hours: 0 और दोहराए जा सकने वाले रीट्राई में से एक ही चुना जा सकता है।

व्यवहार में:

  • बैच से पहले एजेंट से check_balance कॉल करवाएँ। सर्वर के अपने निर्देश मॉडल को यही करने को कहते हैं, और batch_scan प्रॉम्प्ट सबसे पहले यही करता है। sandbox key पर बैलेंस null होता है, और टूल शून्य दिखाने के बजाय साफ़ कहता है कि कोई बैलेंस नहीं है।
  • सिर्फ़ पढ़ने वाले टूल को ही अपने-आप मंज़ूरी दें। उदाहरण के लिए, Kiro का कॉन्फ़िग "autoApprove": ["check_balance", "search_docs"] सपोर्ट करता है। scan_document को कन्फ़र्मेशन के पीछे रहने दें, क्योंकि पैसा यही ख़र्च करता है।
  • एजेंट को ख़ुद जानकारी खोजने दें। search_docs साथ आई डॉक्स पर ऑफ़लाइन काम करता है, इसलिए "unsupported_document का क्या मतलब है" पूछने में कुछ ख़र्च नहीं होता और यह मॉडल की याददाश्त पर निर्भर नहीं रहता।

प्राइवेसी: शुरू करने से पहले पूछने लायक सवाल

पहचान दस्तावेज़ सबसे संवेदनशील डेटा में गिने जाते हैं, और एजेंट इस प्रवाह में और पक्ष जोड़ देता है। यहाँ बताया गया है कि API की तरफ़ क्या सच है, और क्या आपके सेटअप पर निर्भर करता है।

API की तरफ़ (जैसा डॉक्यूमेंटेशन में लिखा है):

  • अपलोड की गई इमेज रिक्वेस्ट के दौरान मेमोरी में रहती है और कभी स्थायी स्टोरेज में नहीं लिखी जाती।
  • रिकग्निशन का नतीजा रखा जाता है ताकि उसे बाद में दोबारा पढ़ा जा सके, अकाउंट पर तय अवधि तक (24 घंटे, 7 दिन, 30 दिन या एक साल)। नए अकाउंट के लिए डिफ़ॉल्ट एक साल है। हर कॉल पर retain_hours: 0 कोई पंक्ति लिखता ही नहीं, और scan_document भी retain_hours लेता है। अगर एजेंट को जवाब सिर्फ़ एक बार चाहिए, तो इसे सेट करें।
  • प्रोसेसिंग यूरोपीय संघ में होती है। डेटा का इस्तेमाल मॉडल ट्रेन करने के लिए नहीं होता।
  • return_portrait: false images.main_photo को छोड़ देता है, यानी धारक की फ़ोटो का क्रॉप। पूरे पेज का क्रॉप फिर भी लौटता है, और चेहरे की वह हल्की दूसरी कॉपी भी, जो कुछ दस्तावेज़ पेज में छापते हैं।

आपकी तरफ़:

  • नतीजा मॉडल के कॉन्टेक्स्ट में जाता है। scan_document जो कुछ लौटाता है (नाम, नंबर, तारीखें), वह अब बातचीत में है, और उसे वह LLM प्रोवाइडर प्रोसेस करता है जो आपका क्लाइंट चलाता है, उसी प्रोवाइडर की शर्तों के तहत। यह हर MCP टूल की स्वाभाविक बात है, सिर्फ़ इसी की नहीं।
  • इमेज कैसे पहुँचती है, यह मायने रखता है। लोकल सर्वर पर image_path के साथ सर्वर फ़ाइल पढ़कर सीधे API को भेजता है। image_base64 के साथ इमेज के बाइट मॉडल के टूल-कॉल आर्ग्युमेंट में होते हैं। अगर आप चाहते हैं कि पिक्सल मॉडल के कॉन्टेक्स्ट से बाहर रहें, तो बाड़ लगी लोकल डायरेक्टरी इस्तेमाल करें।
  • यह रिकग्निशन है, वेरिफ़िकेशन नहीं। नतीजे का authenticity ग्रुप not_checked दिखाता है। पास हुए MRZ का मतलब है कि ज़ोन पढ़ा गया और अंदर से सुसंगत है, यह नहीं कि दस्तावेज़ असली है। कोई liveness या face-match चरण नहीं है। अगर आपका यूज़ केस KYC है, तो यह फ़ैसला नहीं, सिर्फ़ एक इनपुट है।
  • बनाते समय सिंथेटिक दस्तावेज़ इस्तेमाल करें। सब कुछ जोड़ने के लिए नमूने और जनरेट किए गए MRZ काफ़ी हैं।

एक छोटा सेशन

सर्वर इंस्टॉल होने के बाद, सिंथेटिक नमूना संलग्न करके "इस पासपोर्ट स्कैन को पढ़ो और बताओ कि क्या यह अगले छह महीनों में एक्सपायर हो रहा है" जैसा प्रॉम्प्ट काफ़ी है। ठीक से काम करने वाला एजेंट scan_document कॉल करता है, नतीजे से document.expiry_date और document.days_remaining पढ़ता है, और इमेज के अपने अंदाज़े से नहीं बल्कि इन फ़ील्ड से जवाब देता है। अगर स्कैन unreadable लौटे, तो उसे यह बताना चाहिए और बेहतर फ़ोटो माँगनी चाहिए, और उसके लिए आपसे कोई चार्ज नहीं लिया गया।

यहाँ टूल इस्तेमाल करने की असली वजह यही आख़िरी व्यवहार है: एजेंट को ख़ाली जगह भरने के लालच के बजाय साफ़ "पढ़ा नहीं जा सका" मिलता है।

लिंक

अगर आप इससे कुछ बनाते हैं, या आपको कोई ऐसा क्लाइंट मिलता है जिसमें ऊपर का कॉन्फ़िग काम नहीं करता, तो admin@doc.cheap पर लिखें।

doc.cheap और उसके MCP सर्वर के बारे में हर बात उनके कोड से जाँची गई।