# रिपॉजिटरी में बदलावों के लिए MCP कॉन्फिग सुरक्षा

रिपॉजिटरी MCP कॉन्फिगरेशन एक छोटी JSON फाइल का रूप धारण किए executable deployment material है। यह binary चुन सकता है, पैकेज ला सकता है, उस प्रोसेस के शुरू होने की जगह तय कर सकता है, उसे डेटा दे सकता है और checkout का एक हिस्सा दिखा सकता है। इसलिए MCP कॉन्फिग सुरक्षा पहले pull request समीक्षा का विषय है, उसके बाद agent safety का।

मैंने टीमों को एक घंटे तक इस बात पर बहस करते देखा है कि एजेंट को किसी टूल को कॉल करने की अनुमति होनी चाहिए या नहीं, और फिर ऐसे launcher को merge कर दिया जाता है जो उस दोपहर किसी public package name से मिलने वाली चीज इंस्टॉल कर सकता है। टूल लिस्ट दिखाई देने वाला हिस्सा है। टूल लिस्ट बनाने वाला प्रोसेस पहले ही एक boundary पार कर चुका होता है।

## कॉन्फिगरेशन प्रोसेस शुरू करने का निर्देश है

`.mcp.json` में बदलाव पर build script में बदलाव जितना ही ध्यान दें, क्योंकि क्लाइंट को इसके fields को स्थानीय प्रोसेस में बदलना पड़ता है। सटीक schema host के अनुसार अलग हो सकता है, लेकिन आम ढांचा परिचित है: एक command, arguments की array, वैकल्पिक environment entries और कभी-कभी working directory या transport setting।

यह प्रोसेस उस developer या agent host की permissions से शुरू होता है जो इसे लॉन्च करता है। यह वे फाइलें पढ़ सकता है जिन्हें वह user पढ़ सकता है, जहां वह user लिख सकता है वहां फाइलें बना सकता है, चुने हुए environment values ले सकता है और network requests कर सकता है, जब तक operating system या कोई दूसरा control उसे रोक न दे। बाद में इसकी भूमिका चाहे «MCP server» हो, इससे इसकी सामान्य process permissions कम नहीं हो जातीं।

समीक्षक अक्सर पैकेज के नाम या बताए गए टूल की सीमित क्षमता से सुरक्षा का अनुमान लगाते हैं। दोनों अनुमान भरोसेमंद नहीं हैं। `issue-reader` नाम वाला server startup के बाद केवल read operations दे सकता है, लेकिन उसका launcher shell wrapper चलाकर home directory से token पढ़ सकता है। किसी व्यापक नाम वाला server repository में मौजूद binary हो सकता है जो वही करता हो जो रिपॉजिटरी में लिखा है। नामों से नहीं, सबूत से शुरुआत करें।

खतरनाक लाइन अक्सर देखने में बिल्कुल साधारण होती है:

```json
{
  "mcpServers": {
    "docs": {
      "command": "npx",
      "args": ["-y", "@example/docs-mcp"]
    }
  }
}
```

इसका अर्थ यह नहीं कि `npx` या registry package अपने आप अस्वीकार्य है। इसका अर्थ है कि pull request ने executable supply chain का एक हिस्सा हर मशीन पर, हर बार server लॉन्च होने के समय के लिए टाल दिया है। समीक्षक को पता होना चाहिए कि कौन सा package version चलेगा, वह कहां से आएगा, क्या इंस्टॉल करेगा और पहली बार शुरू होने पर क्या करेगा।

रिपॉजिटरी में दर्ज configuration सामाजिक दबाव भी बनाती है। फाइल के repository में आते ही नया contributor किसी server को project setup का हिस्सा समझता है और मान लेता है कि उसकी पहले ही जांच हो चुकी है। यही धारणा इस file class के लिए owner और review habit जरूरी बनाती है।

## MCP messages और repository launchers अलग layers हैं

Model Context Protocol specification MCP client और server के बीच बातचीत का वर्णन करती है, जिसमें initialization, tool discovery, tool calls और transport behavior शामिल हैं। यह कोई universal `.mcp.json` format नहीं बनाती और न ही client configuration को harmless बनाती है। हर client यह तय करता है कि configuration कहां से पढ़नी है और स्थानीय stdio server को कैसे लॉन्च करना है।

यह अंतर तब महत्वपूर्ण होता है जब समीक्षा में गलती हो जाती है। Protocol connection बनने के बाद server को घोषित methods के एक सेट तक सीमित कर सकता है। Host configuration तय करती है कि सबसे पहले उन methods की घोषणा करने का अवसर किस program को मिलेगा। अगर आप केवल protocol-facing behavior देखते हैं, तो आपकी समीक्षा उस समय से शुरू होती है जब launcher पहले ही काम कर चुका होता है।

इन दो सवालों को अलग रखें:

- Connected server अपने tools के जरिए कौन सी कार्रवाइयां मांग या कर सकता है?
- Client के server connection बनने से पहले local launcher क्या करता है?

पहला सवाल agent permissions, approval flow और tool design से जुड़ा है। दूसरा repository trust, process execution, dependency provenance और filesystem scope से जुड़ा है। अच्छी समीक्षा दोनों का जवाब देती है, लेकिन एक के जवाब को दूसरे के जवाब का विकल्प नहीं बनने देती।

Protocol documentation clients और servers को capabilities negotiate करने के लिए प्रोत्साहित करती है। यह compatibility के लिए उपयोगी है, repository command पर trust स्थापित करने के लिए नहीं। Capability negotiation client को बता सकती है कि server tools support करता है। इससे यह साबित नहीं होता कि command path, package content या startup hook developer की access के लायक है।

इसी वजह से किसी नए configuration में परिचित server फिर भी जोखिम भरा हो सकता है। Server code वही रह सकता है, लेकिन बदला हुआ argument उसे किसी दूसरे endpoint, credential source या project directory की ओर भेज सकता है। Launch context भी behavior का हिस्सा है।

## Advertised tools से पहले launched command पढ़ें

Command resolution को chain की तरह देखें, JSON में दिए पहले string की तरह नहीं। पूछें कि current environment से command resolve होने के बाद host वास्तव में कौन सा program चलाएगा। `python`, `node`, `uvx`, `npx`, `bunx`, `sh` और relative path का अर्थ है कि कोई दूसरा resolver final executable तय करेगा।

सीधा absolute path जांचना आसान होता है, हालांकि उसके लिए भी provenance स्पष्ट होनी चाहिए। Repository relative path स्वीकार्य हो सकता है, जब repository में वह file मौजूद हो और सामान्य code review उस पर लागू हो। Bare command name के लिए developer के PATH behavior की जांच करनी पड़ती है। Shell command पर सबसे अधिक संदेह करें, क्योंकि quoting, expansion, pipes, redirects और command substitution साधारण argument array से कहीं अधिक execution छिपा सकते हैं।

Arguments की अलग समीक्षा करें। समीक्षक अक्सर पहले दो arguments पढ़ते हैं, package name पहचानते हैं और आगे बढ़ जाते हैं। हर element पढ़ें। कोई argument checkout के बाहर configuration file चुन सकता है, output directory तय कर सकता है, plugin loader चालू कर सकता है, alternate registry की ओर भेज सकता है या harmless command को script evaluator में बदल सकता है।

इन दो entries का अंतर देखें:

```json
{
  "command": "node",
  "args": ["tools/mcp-server.js", "--root", "."]
}
```

```json
{
  "command": "node",
  "args": ["tools/mcp-server.js", "--config", "../../shared/runtime.json"]
}
```

दूसरी entry जायज हो सकती है। फिर भी यह checkout boundary के बाहर मौजूद file पर निर्भरता बनाती है, जिसे pull request में शायद दिखाया न गया हो। अगर server उस file से instructions या credentials पढ़ता है, तो reviewers केवल diff देखकर बदलाव का आकलन नहीं कर सकते। लेखक से कहें कि referenced configuration को review में शामिल करे, उसे स्पष्ट repository path से बदले या समझाए कि external file क्यों जरूरी है।

«पैकेज इसे संभाल लेता है» जैसे अस्पष्ट जवाब को स्वीकार न करें। Package आज इसे सही तरीके से संभाल सकता है, लेकिन बदलाव फिर भी उसे authority देता है। उपयोगी जवाब में program, उसका version, उसके inputs और expected files का नाम होना चाहिए। अगर लेखक ने fresh checkout से exact command नहीं चलाया है, तो वह behavior नहीं, केवल intent बता रहा है।

Shell wrappers के लिए सीधा default रखें: उन्हें अस्वीकार करें, जब तक repository की कोई ठोस जरूरत न हो जिसे argument array पूरा नहीं कर सकती। Wrapper सुविधाजनक लग सकता है क्योंकि वह environment value सेट करके दो helpers शुरू करता है। साथ ही, समीक्षा shell parsing rules और wrapper तक पहुंचने वाले हर command पर निर्भर हो जाती है। अगर वह जरूरी है, तो setup को स्पष्ट filename वाले reviewed script में रखें और उस script की समीक्षा application code की तरह करें।

## Package runners startup को supply chain event बना देते हैं

Package runner पहली बार server लॉन्च होने पर code डाउनलोड और चला सकता है, इसलिए केवल package name पूरी dependency review नहीं है। यही वजह है कि `npx -y package`, `uvx package` और ऐसे दूसरे forms को checked in file चलाने वाले command से अधिक जांच की जरूरत होती है।

Unpinned runner के पक्ष में आम तर्क सुविधा है। Contributors को कुछ manually इंस्टॉल नहीं करना पड़ता और project हमेशा updated दिखाई देता है। इसकी कीमत यह है कि repository अब वह exact code नहीं बताती जिसे हर contributor से चलाने को कहा गया है। नया published package version, बदली हुई dependency या registry routing में बदलाव बिना नई pull request के behavior बदल सकता है।

कम से कम version स्पष्ट करें और source को समझने योग्य बनाएं:

```json
{
  "mcpServers": {
    "schema-checker": {
      "command": "npx",
      "args": ["-y", "@acme/schema-mcp@1.4.2"],
      "cwd": "${workspaceFolder}"
    }
  }
}
```

Version pinning package को प्रमाणित नहीं करती। यह review target को स्थिर बनाती है। Reviewer उस release की जांच कर सकता है, उसे पिछले release से compare कर सकता है और update के लिए जानबूझकर pull request मांग सकता है। जहां आसपास का toolchain support करे, वहां package manager की lockfile, integrity data या repository में मौजूद artifact इस्तेमाल करें। Downloaded content verify करने का कोई तरीका नहीं होने पर version string एक gap छोड़ती है, फिर भी यह unbounded name से बेहतर है।

Package manager cache को review न समझें। Cache केवल यह बदलती है कि एक मशीन पर bytes कहां से आए। इससे reviewer को यह नहीं पता चलता कि दूसरे contributors को कौन से bytes मिलेंगे, install hooks चलेंगे या नहीं, या clean machine पर behavior वही रहेगा या नहीं।

एक असहज सवाल पूछें, जो कई कमजोर बदलाव पकड़ लेता है: package missing होने पर क्या होगा? अगर जवाब है «यह खुद install हो जाता है», तो configuration में network और code execution path है। अगर जवाब है «launch documented dependency इंस्टॉल करने के निर्देश के साथ fail होता है», तो टीम ने धीमा लेकिन अधिक स्पष्ट setup चुना है। इनमें से कोई जवाब अपने आप सही नहीं है। अंतर को छिपाना गलत है।

## Working directories और environment entries असली scope तय करते हैं

`cwd` field बताती है कि relative files खोजते समय process कहां से शुरू होगा, और यह चुनाव अक्सर अपेक्षा से अधिक चीजें नियंत्रित करता है। कई tools working directory से ऊपर की ओर चलते हुए project configuration, language runtimes, ignore files, credentials और plugins खोजते हैं। Repository root से शुरू होने वाला server dedicated fixture directory से शुरू होने वाले server से अलग दुनिया देख सकता है।

Working directory सोच-समझकर तय करें। अगर server को केवल `tools/specs` के अंदर मौजूद generated API specifications चाहिए, तो उसे ऐसे parent directory से शुरू न करें जिसमें deployment material और private development notes हों। अगर उसे पूरा checkout देखना जरूरी है, तो pull request में यह साफ लिखें। लक्ष्य हर path को छोटा करना नहीं है। लक्ष्य यह है कि reviewer जिस access को मंजूर करता है, वह server को मिलने वाले access से मेल खाए।

Environment entries भी उतनी ही महत्वपूर्ण हैं। कुछ केवल locale या port जैसी operational settings होती हैं। दूसरी package registry चुनती हैं, module search path बढ़ाती हैं, request bodies लिखने वाला debug mode चालू करती हैं या credentials रखती हैं। `${TOKEN}` इस्तेमाल करने वाला configuration token value को file से छिपाता है, लेकिन वह secret फिर भी child process तक पहुंचता है।

जब server अलग action boundary के जरिए काम कर सकता हो, तो repository MCP configuration में credentials रखने से बचें। अगर server को सचमुच secret चाहिए, तो उसका source, purpose और यह बात लिखें कि process उसे children तक भेज सकता है या नहीं। Comment या copied shell transcript में sample production token न रखें। Developers उसी example को copy करेंगे जिसे काम करना सबसे आसान लगेगा।

Inherited environment values पर भी ध्यान दें। Process JSON में सूचीबद्ध values से कहीं अधिक inherit कर सकता है। Host तय करता है कि वह क्या पास करेगा, लेकिन repository author ऐसा command चुन सकता है जो standard runtime locations पढ़ता हो। यह direct और छोटे launchers को general shells और package runners पर प्राथमिकता देने की एक और वजह है।

## Pull request diff execution graph दिखा सकता है

आप अधिकांश configuration changes की समीक्षा untrusted code चलाए बिना कर सकते हैं, अगर diff को उससे बनने वाले processes और inputs में खोलकर देखें। Rendered file view के बजाय focused diff से शुरुआत करें, ताकि हटाए गए arguments और बदले हुए paths दिखाई देते रहें:

```sh
git diff --check
git diff -- .mcp.json
```

पहली command whitespace errors मिलने पर उनकी रिपोर्ट करती है। दूसरी को configuration path में जोड़ी, हटाई और बदली गई हर line दिखानी चाहिए। अगर repository file को कहीं और रखती है या generate करती है, तो path बदलें और generator change भी मांगें। Source के बिना generated configuration की समीक्षा अधूरी है।

यह छोटा बदलाव देखें:

```diff
 "mcpServers": {
   "release-notes": {
-    "command": "node",
-    "args": ["tools/release-notes-server.js"],
-    "cwd": "${workspaceFolder}"
+    "command": "npx",
+    "args": ["-y", "release-notes-mcp"],
+    "cwd": ".."
   }
 }
```

ऊपरी कहानी कहती है कि टीम ने local helper को published server से बदला है। Execution graph इससे अधिक बताता है। Client developer के PATH से `npx` resolve करता है। `npx` `release-notes-mcp` और उसकी dependencies ला सकता है। `cwd` अब parent directory की ओर इशारा कर रहा है, इसलिए package repository root के बाहर शुरू होता है। Server वहां configuration खोज सकता है, cache files लिख सकता है या sibling projects पढ़ सकता है। Merge से पहले हर arrow का जवाब चाहिए।

अनुशासित समीक्षा इस क्रम में सबूत मांगती है:

1. Final executable और उसे उपलब्ध कराने वाले exact package या repository file की पहचान करें।
2. हर file path, URL, registry और environment value की सूची बनाएं जो startup behavior बदल सकती है।
3. Process की working directory और वे directories बताएं जिन्हें server सामान्य उपयोग में पढ़ता या लिखता है।
4. Package cache मौजूद न होने वाली clean machine पर क्या होगा, इसकी पुष्टि करें।
5. बताए गए tool purpose की तुलना launcher को वास्तव में चाहिए permissions से करें।

यह क्रम कोई औपचारिकता नहीं, बल्कि concrete artifact है। इससे वह सामान्य गलती रुकती है जिसमें reviewer tool description को मंजूर कर देता है, जबकि installer, runtime selector या parent directory one-line change में चुपचाप निकल जाते हैं।

अगर configuration को validate करने के लिए उसे चलाना जरूरी हो, तो disposable account या isolated environment में करें, जहां production credentials न हों और package cache खाली हो। Resolved executable, package version, outbound hosts और लिखी गई files दर्ज करें। Tool discovery सफल होने का screenshot कमजोर evidence है, क्योंकि उसमें वह हिस्सा नहीं दिखता जिसने सबसे अधिक जोखिम पैदा किया।

## Tool descriptions broad launcher की भरपाई नहीं कर सकते

Narrow tool schema MCP handshake से पहले हुई गतिविधि को मिटा नहीं सकती। टीमें अक्सर server के `tools/list` output को permissions inventory मानती हैं, फिर `search_docs` और `read_status` उपलब्ध होने पर उसे सुरक्षित समझ लेती हैं। यह inventory initialization के बाद का interface बताती है। इससे package installation, configuration discovery, telemetry, child processes या startup पर पढ़ी गई files के बारे में बहुत कम पता चलता है।

यह अंतर दोनों दिशाओं में लागू होता है। Write capable tool वाला server स्वीकार्य हो सकता है, अगर launcher pinned, local, documented और intended project तक सीमित हो। Read only server अस्वीकार्य हो सकता है, अगर repository config चुपचाप network से mutable package चलाकर developer के बड़े workspace तक access दे।

लेखक से lifecycle साधारण भाषा में लिखने को कहें: क्या शुरू होता है, connect होने से पहले क्या पढ़ता है, कुछ download करता है या नहीं और connect होने के बाद server किन चीजों तक पहुंच सकता है। इसका जवाब pull request description में आ जाना चाहिए। अगर जवाब देने के लिए लंबी जांच चाहिए, तो configuration नियमित समीक्षा के लिए बहुत indirect है।

«हम इस vendor पर भरोसा करते हैं» कहकर चर्चा बंद न होने दें। Trust महत्वपूर्ण है, लेकिन इससे version pin नहीं होता, working directory सीमित नहीं होती और यह पता नहीं चलता कि command alternate registry इस्तेमाल करती है या नहीं। ये अलग controls हैं और इनके failure modes भी अलग हैं।

## Repository ownership को runtime backstop चाहिए

Repository review unsafe launch instructions को सामान्य project setup बनने से रोकती है। Runtime controls फिर भी जरूरी हैं, क्योंकि मंजूर configuration का इस्तेमाल compromised dependency, malicious prompt या agent से जरूरत से अधिक काम करवाने वाला user कर सकता है।

Boundary स्पष्ट रखें। Repository यह नियंत्रित करती है कि वह क्या launch करने का प्रस्ताव देती है। मशीन चलाने वाला human तय करता है कि किसी खास agent session को क्या करने की अनुमति है। संवेदनशील कार्रवाइयों के लिए ऐसे records चाहिए जिनसे operator यह समझ सके कि agent ने क्या किया और run गलत होने पर session रद्द कर सके।

Sallyport API और SSH credentials को agent process से बाहर रखता है, जबकि उसका session authorization और activity record operator को कार्रवाइयों को मंजूर करने और जांचने की अलग जगह देते हैं। इससे risky repository command harmless नहीं बनती, इसलिए configuration review फिर भी पहले आती है।

जो टीमें कोई दूसरी boundary इस्तेमाल करती हैं, वे यही test लागू करें। क्या developer देख सकता है कि किस agent process ने access मांगा? क्या वह unrelated work बंद किए बिना उस process को रोक सकता है? क्या वह attempted action और successful action में अंतर कर सकता है? अगर जवाब नहीं है, तो merge के बाद खराब configuration के पास परेशानी पैदा करने के लिए अधिक समय होगा।

## इन files को owned execution code मानें

Repository को MCP configuration, उसके wrapper scripts और उन package manifests के लिए code owners या equivalent review rule तय करना चाहिए जो launcher के install करने का तरीका निर्धारित करते हैं। Owner का security specialist होना जरूरी नहीं है। उसे इतना context जरूर होना चाहिए कि वह पूछ सके कि यह बदलाव इस program को इस access के साथ क्यों शुरू करता है।

Configurations छोटी रखें। हर system तक पहुंचने वाले universal helper की तुलना में purpose के अनुसार एक server review करना आसान होता है। Configuration के पास ordinary prose में unusual requirements लिखें: expected command, package version policy, working directory, required network access और intended inputs। यह note tribal knowledge को ऐसी चीज में बदल देता है जिसे अगला reviewer चुनौती दे सकता है।

व्यावहारिक test सरल है। यह diff ऐसे अनुभवी developer को दें जो feature को नहीं जानता और उससे पूछें कि clean machine पर क्या execute होगा, कहां execute होगा और वह क्या देख सकता है। अगर वह pull request और referenced code से जवाब नहीं दे सकता, तो बदलाव को repository में शामिल करने से पहले और काम चाहिए।
