8 मिनट पढ़ें

MCP server startup failures एक जैसे क्यों दिखते हैं?

MCP server startup failures को समझना आसान हो जाता है जब launch, handshake, tool discovery और external action के evidence को अलग-अलग देखा जाए।

MCP server startup failures एक जैसे क्यों दिखते हैं?

MCP client यह बता सकता है कि server «failed to start», भले ही operating system process शुरू कर चुका हो, process input पढ़ चुका हो और server machine के बाहर किसी system से संपर्क भी कर चुका हो। यह message diagnosis नहीं है। यह ऐसा bucket है जिसमें launch failures, protocol failures, discovery failures और कभी-कभी tool failures भी एक साथ डाल दिए जाते हैं।

Startup को ऐसे evidence-bearing boundaries की श्रृंखला मानें। अगर आप यह नहीं बता सकते कि server ने कौन-सी boundary पार की, तो operator को यह नहीं बता पाएंगे कि retry सुरक्षित है या नहीं, credential का उपयोग हुआ हो सकता है या नहीं, या client ने केवल एक healthy server को दिखाने में गलती की है। समाधान बड़ा timeout नहीं है। समाधान states को अलग करना और हर state को observable बनाना है।

एक लाल status चार अलग failures छिपा सकता है

Operator को क्रम से चार सवालों के जवाब चाहिए: क्या client ने configured command शुरू की, क्या दोनों पक्षों ने MCP initialization पूरा किया, क्या client को उपयोगी tool list मिली, और क्या किसी code ने external channel तक पहुंच बनाई? हर जवाब अलग बात साबित करता है।

Process सामान्य अर्थ में मौजूद होने से पहले ही विफल हो सकता है। Executable missing हो सकता है, working directory मौजूद न हो, package runner आपके code को चलाने से पहले fail हो सकता है, या required environment variable न मिलने पर child तुरंत exit कर सकता है। इसे launch failure कहें। कोई MCP session बना ही नहीं और आपका application code शायद चला भी न हो।

Process मौजूद हो सकता है और फिर भी protocol exchange विफल हो सकता है। stdio में child process का stdin और stdout client से जुड़े होते हैं। Server को stdin से JSON-RPC पढ़ना और stdout पर केवल JSON-RPC messages लिखना होता है। इसके बाद उसे client की initialize request का जवाब compatible protocol version और घोषित capabilities के साथ देना होता है। Client फिर notifications/initialized भेजता है। यह sequence पूरा न हो तो इसे handshake failure कहें।

सफल handshake से यह साबित नहीं होता कि client ने tools के बारे में जान लिया। Server tool support घोषित कर सकता है, लेकिन tools register करते समय exception आ सकती है, invalid input schema बन सकता है, malformed tools/list result लौट सकता है या अपनी configuration के कारण empty list मिल सकती है। इसे tool discovery failure कहें। Client और server messages exchange करने के लिए पर्याप्त रूप से healthy हो सकते हैं, फिर भी agent के पास call करने के लिए कुछ नहीं होगा।

अंत में server discovery पार करके केवल tool चलाते समय विफल हो सकता है। यह tool execution failure है और इसे अलग incident record में रखें। अगर इसे startup में मिला देंगे, तो कोई न कोई ऐसे server को retry करेगा जिसने पहले ही HTTP request भेज दी हो या SSH connection खोल दिया हो।

Model Context Protocol documentation इस separation को स्पष्ट करती है, भले ही कई client interfaces ऐसा न दिखाएं। इसकी debugging guidance process और configuration problems को protocol logging से अलग करती है और चेतावनी देती है कि local stdio servers को stdout को सामान्य logs से खाली रखना चाहिए। Protocol का initialization lifecycle और tools/list request अलग exchanges हैं। Client के generic label को स्वीकार करने के बजाय अपने telemetry में यह distinction बनाए रखें।

MCP बनने से पहले launch failure समाप्त हो जाता है

Launch failure का मतलब है कि client को readable protocol stream वाला usable child process नहीं मिला। इसका मतलब यह नहीं कि terminal में command «सही दिख रही थी»।

Interactive shells बहुत कुछ छिपा देती हैं। आपके shell में PATH, current directory, language version managers, credentials और dotfiles हो सकते हैं, जो desktop application या agent subprocess को न मिलें। macOS पर client / को working directory बनाकर launch कर सकता है। Restricted environment इस्तेमाल हो सकता है। Command को shell के जरिए नहीं, बल्कि executable और argument array के रूप में भेजा जा सकता है, इसलिए shell aliases और redirection काम नहीं करेंगे।

MCP पर विचार करने से पहले exact launch record capture करें:

run_id=run_01JX...
phase=launch
command=/usr/local/bin/node
argv=["/Users/dev/work/acme-mcp/dist/index.js"]
cwd=/
pid=84217
started_at=2026-07-22T14:03:12.417Z

इसके बाद process exit होने या handshake deadline समाप्त होने पर एक अंतिम terminal event capture करें:

run_id=run_01JX...
phase=launch
exit_code=1
signal=null
stderr=Error: ENOENT: no such file or directory, open './config.json'

यह record एक आम बहस को जल्दी समाप्त कर देता है। Server को «MCP problem» नहीं हुई। उसने मान लिया था कि relative path project directory में resolve होगा, जबकि client ने उसे / से launch किया।

Executable, entry point, configuration files और startup में पढ़ी जाने वाली सभी files के लिए absolute paths इस्तेमाल करें। MCP debugging guide client-launched servers के undefined working directories को स्पष्ट रूप से बताती है और absolute paths की सलाह देती है। यह केवल style की सावधानी नहीं है। इससे वे failures हटते हैं जो किसी दूसरी machine पर वही configuration install करने के बाद सामने आते हैं।

केवल PID मिलने से launch सफल घोषित न करें। PID बताता है कि kernel ने process बनाया। इससे यह पता नहीं चलता कि program load हुआ या नहीं, stdout pipe सही है या नहीं, या process पहले ही zombie बन चुका है और reap होने का इंतजार कर रहा है।

एक उपयोगी launch state machine छोटी होनी चाहिए:

not_requested
  -> spawn_requested
  -> spawned
  -> executable_ready
  -> handshake_pending

spawned का मतलब है कि parent को child PID मिल गया। executable_ready का मतलब है कि child ने configuration load करने और fatal-error handler install करने के बाद stderr पर जानबूझकर एक non-protocol readiness event लिखा। यह event stdout पर न भेजें। stdio server में stdout कोई पास में मौजूद logging channel नहीं है। वही wire है।

Readiness event को यह दावा नहीं करना चाहिए कि server किसी API, database या remote host से connected है। उसे केवल उतना ही बताना चाहिए जितना वह साबित करता है: process MCP transport setup तक पहुंच गया। ready=true जैसी line तब नुकसानदेह बन जाती है जब teams चुपचाप उसका अर्थ «अब tools call करना सुरक्षित है» समझने लगती हैं। इसके बजाय phase का नाम दें।

Handshake की परिभाषा सीमित है

MCP handshake failure usable process बनने के बाद शुरू होती है और initialization lifecycle पूरा होने से पहले समाप्त होती है। Messages जांचे बिना इसे connection failure न कहें।

stdio transport में stdout के शुरुआती bytes महत्वपूर्ण होते हैं। साधारण startup banner server को request मिलने से पहले stream को खराब कर सकता है। Dependency का update notice, console.log, Python print, framework exception formatter या stdout पर status text लिखने वाली wrapper script भी यही कर सकती है। Official MCP build और debugging guidance इसे साफ तौर पर कहती है: stdio servers में logs stderr पर लिखें, क्योंकि stdout protocol messages के लिए है।

Healthy initialization का सबसे छोटा उपयोगी trace इस तरह दिखता है:

{"direction":"in","id":1,"method":"initialize"}
{"direction":"out","id":1,"result":{"protocolVersion":"2025-06-18","capabilities":{"tools":{}},"serverInfo":{"name":"acme","version":"1.4.0"}}}
{"direction":"in","method":"notifications/initialized"}

Exact protocol version client और server द्वारा supported versions पर निर्भर करती है। महत्वपूर्ण बात यह है कि server ने client द्वारा स्वीकार की जाने वाली version चुनी, valid result लौटाया और completion notification प्राप्त की। हर message के लिए parsed event store करें, लेकिन credential वाले raw payloads नहीं।

अगर trace इसके बजाय इस तरह शुरू हो, तो diagnosis बदल जाता है:

stdout: Starting Acme MCP server
{"jsonrpc":"2.0","id":1,"method":"initialize",...}

Server जवाब देने में पूरी तरह सक्षम हो सकता है, लेकिन client का JSON parser पहले ही invalid input पढ़ चुका है। इसके बाद आने वाला timeout यह नहीं बताता कि server धीमा था। यह बताता है कि transport corrupt था।

एक और परिचित failure कुछ बेहतर दिखता है:

phase=handshake
initialize_received=true
initialize_response_sent=false
fatal_error=Cannot read properties of undefined (reading 'tools')

Child launch हुआ। उसे request मिली। Response तैयार करते समय वह fail हो गया। यह server bug या unhandled configuration assumption है, खराब client configuration नहीं।

Logs में boundaries स्पष्ट करें:

phase=handshake event=initialize_received run_id=run_01JX request_id=1
phase=handshake event=initialize_responded run_id=run_01JX request_id=1 protocol_version=2025-06-18
phase=handshake event=initialized_received run_id=run_01JX

अगर आप केवल connected=true लिखते हैं, तो वह जानकारी मिट जाती है जो response भेजे जाने और initialization lifecycle पूरा होने के बीच अंतर करती है। Response मिलने के बाद लेकिन notification भेजने से पहले clients close या restart हो सकते हैं। यह initialization parser error से अलग operational स्थिति है।

Handshake के लिए अपनी deadline रखें। इसे process spawn होने पर शुरू करें, या transport ready होने का क्षण दिख सके तो वहां से। notifications/initialized आने पर रोकें। Deadline समाप्त होने पर आखिरी confirmed event बताएं, जैसे spawned_no_initialize, initialize_received_no_response या response_sent_no_initialized। इन नामों से operator सही जगह पहले जांच सकता है।

Server reachable होने के बाद tool discovery विफल होती है

Tool discovery failure का मतलब है कि client और server MCP में बात कर सकते हैं, लेकिन client को tools/list का usable answer नहीं मिला। कई clients initialization के तुरंत बाद tools discover करते हैं, इसलिए इसे अक्सर startup failure बताया जाता है।

Blank tool panel को tools/list के empty result का प्रमाण न मानें। Schema validation विफल होने पर कुछ clients tools छिपा देते हैं। कुछ discovery results cache करते हैं। कुछ केवल तब tools request करते हैं जब agent task शुरू करता है। कुछ MCP server से resources या prompts के लिए connect होते हैं और tools मांगते ही नहीं। आपके evidence में request और response दोनों होने चाहिए।

Healthy discovery trace का रूप ऐसा है:

{"direction":"in","id":2,"method":"tools/list"}
{"direction":"out","id":2,"result":{"tools":[{"name":"issue_lookup","description":"Fetch one issue by identifier","inputSchema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]}}]}}

Discovery record में tools की संख्या और normalized schemas का digest शामिल होना चाहिए। Digest से आप देख सकते हैं कि दो runs में advertised interface एक जैसा था या नहीं, बिना sensitive descriptions या configuration store किए। इससे ऐसे accidental changes भी पकड़े जाते हैं जिनमें tool मौजूद रहता है, लेकिन उसके required parameters गायब हो जाते हैं।

tools/list के दौरान external service से संपर्क करके tool definitions न बनाएं। इससे discovery side effect बन जाती है, client refresh execution जैसा दिखता है और सबसे खराब incident question पैदा होता है: «क्या tools list करने से कुछ बदल गया?» जहां संभव हो, tool registration local और deterministic रखें।

किसी tool को advertise करना है या नहीं, यह तय करने के लिए server को configuration की जरूरत हो सकती है। वह configuration startup पर पढ़ें और result दर्ज करें, लेकिन tool discovery को token refresh या SSH probe का इंतजार न कराएं। Tool को credential चाहिए तो उसके local reference की मौजूदगी जांचें, उसका उपयोग न करें। असली remote action client के tool call करने तक टालें।

Agent control के लिए यह distinction महत्वपूर्ण है। अगर कोई agent sp mcp के जरिए Sallyport तक पहुंचता है, तो successful MCP discovery record केवल यह दिखाता है कि shim ने callable operations expose कीं। यह नहीं दिखाता कि Sallyport ने HTTP या SSH action किया।

Empty list लौटाने का एक वैध कारण है: current configuration में server के पास कोई enabled tool नहीं है। इसे structured response या client-facing log में बताएं। Registration के दौरान crash करके client को यह अनुमान लगाने के लिए न छोड़ें कि tool set जानबूझकर empty है।

phase=discovery event=tools_list_responded run_id=run_01JX tool_count=0 reason=no_enabled_tools

यह record operator को ठीक करने के लिए configuration problem देता है। Generic startup error केवल दोहराने के लिए एक अंधविश्वास देता है।

External reachability के लिए अपना प्रमाण चाहिए

Audit trail को offline verify करें
एक encrypted, hash-chained audit log दोनों journals को सुरक्षित रखता है और sp audit verify से offline verify होता है।

«क्या process external channel तक पहुंचा?» इस सवाल का जवाब PID, successful handshake या populated tool list से नहीं मिल सकता। आपको उस boundary पर event चाहिए जहां आपका code external action शुरू करने की कोशिश करता है।

इस उद्देश्य के लिए external channel की परिभाषा सीमित रखें। इसमें outbound HTTP request, SSH helper invocation, local process से बाहर database connection, cloud credential refresh, message queue publish या ऐसी कोई call शामिल है जो MCP session के बाहर effect पैदा कर सकती है या information उजागर कर सकती है। Local configuration file पढ़ना इसमें शामिल नहीं है। Local protected store से credential load करना भी अपने-आप में external action नहीं है। उसे request में भेजना है।

Call शुरू होने से पहले attempt record करें, फिर उसका outcome दर्ज करें। Opaque action ID इस्तेमाल करें जिसे MCP request ID और server run ID से जोड़ा जा सके।

run_id=run_01JX phase=execution event=external_attempt action_id=act_8Qf tool=issue_lookup channel=https host=api.example.test
run_id=run_01JX phase=execution event=external_result action_id=act_8Qf status=200 duration_ms=184

Authorization headers, bearer tokens, signed URLs, secrets वाले command arguments या full response bodies इन records में न रखें। जिस credential की जांच करनी थी, वही leak करने वाला incident log समस्या को और गंभीर बना देता है।

external_attempt की जगह केवल सैद्धांतिक बात नहीं है। इसे बहुत पहले रखें तो आप external call होने का दावा करेंगे, जबकि code ने केवल request object बनाया था। बहुत देर से रखें तो timeout या process crash के बाद gap रह सकता है, जबकि bytes machine से बाहर जा चुके हों। इसे उस library call से तुरंत पहले emit करें जो network या SSH activity शुरू कर सकती है। अगर library lower-level connection या request hook देती है, तो वहां दूसरा event तभी record करें जब «attempt» का अर्थ भ्रमित न हो।

एक failure walkthrough दिखाता है कि यह क्यों महत्वपूर्ण है। Operator ऐसा MCP server जोड़ता है जो module initialization में issue tracker token पढ़ता है और उसे validate करने के लिए «who am I» endpoint call करता है। Child process शुरू होता है, stdout पर debug line लिखता है और पहला MCP message खराब कर देता है। Client «server failed to start» दिखाता है। Team client को दो बार restart करती है।

Phase records के बिना वे निष्कर्ष निकालते हैं कि कोई request machine से बाहर नहीं गई, क्योंकि server client UI में दिखाई ही नहीं दिया। यह निष्कर्ष गलत है। Client के initialize भेजने से पहले module initialization call चल चुकी थी और उसने issue tracker से तीन बार संपर्क किया था। UI state external reachability के बारे में कुछ नहीं बताती।

Identity check को जानबूझकर read-only tool में रखें, या उसे उस पहली action का हिस्सा बनाएं जिसे remote service की सच में जरूरत हो। फिर उसे tool execution के रूप में record करें। Server network को छुए बिना launch, initialize और tools list कर सकता है। अब operator «server available है» और «credential तथा remote service काम कर रहे हैं» के बीच अंतर कर सकता है। ये अलग facts हैं और अलग ही रहने चाहिए।

Phase ledger अस्पष्ट incidents को testable claims में बदल देता है

हर run के लिए एक ledger entry बनाएं और immutable phase events append करें। आपको complicated rules engine नहीं चाहिए। Stable names, timestamps और घटना को फिर से बनाने के लिए पर्याप्त correlation fields चाहिए।

यह shape इस्तेमाल करें:

{
  "run_id": "run_01JX",
  "server_name": "acme",
  "pid": 84217,
  "phase": "discovery",
  "event": "tools_list_responded",
  "request_id": 2,
  "tool_count": 4,
  "at": "2026-07-22T14:03:13.083Z"
}

Ledger में string में चिपकाए गए conclusions नहीं, events record होने चाहिए। phase=handshake और event=initialize_received को count, query और test किया जा सकता है। message="MCP seems stuck" को नहीं।

State model को जानबूझकर सरल रखें:

  1. spawn_requested, spawned, executable_ready और exited launch से संबंधित हैं।
  2. initialize_received, initialize_responded और initialized_received handshake से संबंधित हैं।
  3. tools_list_received और tools_list_responded discovery से संबंधित हैं।
  4. tool_call_received, external_attempt और external_result execution से संबंधित हैं।
  5. revoked, terminated और client_disconnected interruption बताते हैं, success नहीं।

Teams जिस distinction को अक्सर मिला देती हैं, वह है session establishment और authority to act। Server credential इस्तेमाल करने या remote system से connect करने की permission के बिना MCP session establish कर सकता है। अगर आप दोनों को एक ही state मानेंगे, तो approval event connectivity event जैसा दिख सकता है और denied action failed startup जैसी लग सकती है।

Authorization events को उस call के साथ रखें जिसे वे govern करते हैं। उदाहरण के लिए tool_call_received के बाद और external_attempt से पहले authorization_requested और authorization_granted record करें। तब operator evidence के साथ कह सकता है कि tool request आई, human ने उसे deny किया और कोई external attempt नहीं हुआ। यह «request complete नहीं हुई» कहने से कहीं मजबूत है।

ऐसा run ID इस्तेमाल करें जो केवल एक child process तक रहे। Server name को correlation identifier के रूप में reuse न करें। Client एक ही server की दो copies शुरू कर सकता है, timeout के बाद एक को restart कर सकता है और पुराना tool metadata रख सकता है। Reused identifiers अलग attempts को एक बनाई हुई कहानी में बदल देते हैं।

User data उजागर करने वाले values को hash या redact करें। आम तौर पर आपको tool name, endpoint host, status class, error class और timing चाहिए। Query string, request body या response की शायद ही जरूरत होती है। Operators को boundary पार होने का प्रमाण चाहिए, logs से user data दोबारा चलाना नहीं।

Full client पर भरोसा किए बिना boundaries test करें

Policy rules के बिना calls नियंत्रित करें
Fixed decision ladder आपको vault gate, session approval और हर call पर key approval देता है।

Full client integration testing के लिए उपयोगी है, लेकिन पहला witness बनाने के लिए खराब है। उसका UI errors को मिला सकता है, capabilities cache कर सकता है, children restart कर सकता है और अपना timeout लागू कर सकता है। Server या client को दोष देने से पहले हर boundary को संकरे path से test करें।

Client जिस exact command, environment और working directory का उपयोग करता है, उसी से शुरू करें। Configured command की जगह npm run dev न चलाएं। Client कहीं और से launch करता है तो उसे project folder से न चलाएं। stderr को inspection के लिए file में redirect करें, लेकिन stdout को untouched रखें अगर कोई दूसरा process उसी के जरिए MCP बोलेगा।

stdio server के लिए official MCP Inspector को पहला protocol test बनाएं। MCP documentation transports के बीच servers test करने के लिए Inspector की सलाह देती है और Inspector project stdio command को सीधे launch कर सकता है। इससे initialization exchange देखा जा सकता है और tools/list invoke किया जा सकता है, बिना यह अनुमान लगाए कि desktop client ने result के साथ क्या किया।

फिर test को तीन checks तक सीमित करें:

1. Does the configured command remain alive long enough to receive initialize?
2. Does it return a valid initialize response and receive initialized?
3. Does tools/list return the expected tool names and schemas?

इनके सफल होने के बाद ही external system तक पहुंचने वाला tool call करें। Harmless target के साथ read-only action चुनें। Confirm करें कि execution ledger में एक external_attempt और एक terminal result है। अगर call data बदल सकती है, तो disposable environment में test करें या ऐसी dedicated dry-run operation दें जो production endpoint से संपर्क न करे।

Official MCP Inspector repository यहां उपयोगी है क्योंकि यह transport boundary को visible बनाती है। यह आपके server traffic के लिए network interception proxy नहीं है। यह चुने गए server के लिए MCP client की तरह काम करती है और test के लिए browser interface देती है। Transport corruption की जांच में यह अंतर महत्वपूर्ण है: Inspector client side के protocol को reproduce कर सकता है, लेकिन यह साबित नहीं कर सकता कि किसी अलग production client ने pipe पर क्या लिखा।

HTTP transports के लिए HTTP evidence जोड़ें, लेकिन इसे MCP state न समझें। Request method, endpoint path, status, मौजूद होने पर session identifier और response में JSON था या event stream शुरू हुई, यह record करें। TCP connection या HTTP 200 अपने-आप MCP initialization पूरा होने का प्रमाण नहीं है। HTTP request server तक पहुंचने के बाद वही lifecycle records लागू करें।

Test suite में एक fixture server रखें जो हर boundary पर जानबूझकर fail हो। एक fixture input पढ़ने से पहले exit हो। दूसरा जवाब देने से पहले stdout पर hello लिखे। तीसरा initialize का जवाब दे और फिर invalid tool schema लौटाए। चौथा एक tool list करे जिसका handler external attempt record करके controlled error लौटाए। अगर आपका client integration इन चारों को एक ही alert में मिला देता है, तो असली server से अंधेरे में debugging करने से पहले integration ठीक करें।

Timeouts और retries की ownership phase के अनुसार होनी चाहिए

स्टार्टअप को कार्रवाइयों से अलग रखें
sp mcp एजेंट के HTTP और SSH कार्यों को Sallyport के जरिए चलाता है, इसलिए एजेंट को क्रेडेंशियल नहीं मिलते।

एक ही startup timeout गलत repair को बढ़ावा देता है। Slow package download, initialization parser error, schema exception और remote API stall एक जैसे दिखने लगते हैं। अलग deadlines रखें, क्योंकि हर deadline की जिम्मेदारी अलग owner की है।

Launcher spawn_requested से spawned तक की अवधि का owner है। Server और transport spawn से initialized_received तक की अवधि के owner हैं। Server का registration path discovery का owner है। Tool handler और उसकी remote dependency execution के owner हैं। Timeout का नाम उसके owner के अनुसार रखें और आखिरी confirmed phase event emit करें।

error=handshake_timeout last_event=initialize_received run_id=run_01JX

यह actionable है। यह server maintainer को response construction और stderr की जांच करने को कहता है, remote API की नहीं।

Automatic retry तभी सुरक्षित है जब failed phase का कोई external effect न हो। Executable अस्थायी रूप से unavailable होने पर failed spawn को retry करना स्वीकार्य हो सकता है। अगर discovery local और pure है तो discovery request retry करना आम तौर पर ठीक है। external_attempt के बाद tool call retry करना खतरनाक है, जब तक remote operation में documented idempotency mechanism न हो और आप idempotency value attach न करें।

Retry को server restart के पीछे न छिपाएं। Startup code token refresh करता है, tunnel बनाता है, telemetry event भेजता है या remote identity validate करता है, तो restart पहले ही external action है। Startup local रखने और remote work को explicit tools में ले जाने का यह भी एक कारण है।

जब client deadline के बाद child को kill करे, तो यदि संभव हो termination से पहले interruption event emit करें। Server इसे flush न कर पाए। Parent को kill request को अपना अलग event record करना चाहिए और साथ में आखिरी child event भी लिखना चाहिए जिसे उसने देखा। इससे honest record बचता है: process जवाब देने वाला हो सकता था, लेकिन आप यह दावा नहीं करते कि उसने जवाब दिया।

Startup को fast बनाने से पहले उसे boring बनाएं

एक अच्छा MCP server बिना network, बिना credential use, बिना mutable side effect और अपनी protocol state को लेकर बिना ambiguity के शुरू हो सकता है। वह local configuration load करता है, transport install करता है, initialization का जवाब देता है और deterministic interface advertise करता है। ऐसा व्यवहार operate करना आसान और retry करना सुरक्षित बनाता है।

सबसे लोकप्रिय खराब सलाह है «startup पर सब कुछ verify करें»। यह जिम्मेदार लगती है क्योंकि errors जल्दी दिखते हैं। व्यवहार में यह local configuration, identity, remote availability और authorization को एक opaque ritual में मिला देती है। इससे clients startup error label के तहत external actions retry भी कर सकते हैं।

जो कुछ locally validate कर सकते हैं, करें। Remote reachability को explicit tool या उस पहली operation के जरिए report करें जिसे उसकी जरूरत है। Ledger phase names stable रखें। stdio के लिए stdout को केवल protocol के लिए रखें। जिस boundary को observe करने का दावा करते हैं, हर boundary पर जानबूझकर broken server test करें।

अगली बार client कहे कि MCP server start नहीं हुआ, तो एक run record से चार सवालों के जवाब मिलने चाहिए: process launch हुआ या नहीं, initialization पूरा हुआ या नहीं, tools discoverable थे या नहीं और क्या कुछ बाहरी दुनिया तक पहुंचा। अगर इन चारों का जवाब नहीं दे सकते, तो status अभी भी ambiguous है।

सामान्य प्रश्न

मेरा MCP client कई अलग-अलग startup समस्याओं के लिए एक ही error क्यों दिखाता है?

Process launch, protocol initialization, capability discovery और पहली external action को अलग-अलग states मानें। Client एक generic failure दिखा सकता है, भले ही इनमें से केवल एक state विफल हुई हो। आपके logs में हर state पर पार की गई boundary दर्ज होनी चाहिए।

क्या running MCP process का मतलब है कि server सफलतापूर्वक connect हो गया?

नहीं। Running process केवल यह साबित करता है कि operating system ने उसे बनाया है और वह बंद नहीं हुआ है। वह configuration लोड करते समय अटका हो सकता है, किसी dependency का इंतजार कर सकता है, stdout में गलत data लिख सकता है या client की initialize request को अनदेखा कर सकता है।

क्या stdout logging MCP stdio server को खराब कर सकती है?

stdio server में stdout protocol wire होता है। Banner, stack trace, package manager notice या सामान्य print statement, server के initialize का जवाब देने से पहले JSON-RPC stream को खराब कर सकता है। Diagnostic output stderr पर भेजें।

MCP initialization handshake क्या है?

Client initialize request भेजता है, server compatible protocol version और capabilities लौटाता है, फिर client notifications/initialized notification भेजता है। Server शुरू हो जाए लेकिन यह exchange पूरा न करे, तो यह handshake failure है, tool problem नहीं।

MCP tool discovery विफल होने का क्या मतलब है?

इसका मतलब है कि client initialization तक पहुंच गया, लेकिन tools/list से उपयोगी परिणाम नहीं मिला। वजह missing handler, schema बनाते समय exception, unsupported capability declaration या यह भी हो सकती है कि client tools मांगता ही न हो।

क्या MCP server को startup के दौरान external API से संपर्क करना चाहिए?

Server startup में network request, SSH login, token refresh या secret lookup न रखें, जब तक server इनके बिना काम ही न कर सके। पहले protocol endpoint शुरू करें, फिर external call को tool handler के भीतर करें और उसे अलग action के रूप में दर्ज करें।

मैं अपने client के बाहर MCP startup failure को कैसे दोहरा सकता हूं?

Client जिस user, working directory और environment का उपयोग करता है, उसी के साथ वही launch command चलाएं। फिर MCP Inspector या नियंत्रित JSON-RPC exchange से test करें। Interactive shell वाला terminal test असली failure को छिपा सकता है।

MCP server startup troubleshooting के लिए मुझे क्या log करना चाहिए?

Launch पर एक unique run ID बनाएं और उसे stderr events, protocol events, tool discovery और हर outbound request से जोड़ें। Process ID, executable path, exit status और external action ID दर्ज करें। Credentials या request bodies को default रूप से दर्ज न करें।

MCP startup timeout कितना लंबा होना चाहिए?

Time limit उचित है, लेकिन उसे उस phase का नाम बताना चाहिए जिसकी वह रक्षा करती है। अलग launch deadline, initialization deadline और tools/list के लिए अलग deadline रखें। एक ही timeout message diagnosis की जरूरी जानकारी मिटा देता है।

क्या failed MCP server startup को अपने-आप retry करना सुरक्षित है?

नहीं। Startup code files बनाता है, tokens refresh करता है या services से संपर्क करता है, तो failed launch को दोहराने से side effects दोहर सकते हैं। केवल उसी phase को retry करें जिसके बारे में आप जानते हों कि उसका कोई external effect नहीं है, और हर retry को अलग run ID दें।

Sallyport

Sallyport आपके AI एजेंट के लिए API कॉल और SSH कमांड चलाता है। कुंजियाँ आपके Mac पर एक लोकल वॉल्ट में रहती हैं; आप हर रन को स्वीकृत करते हैं और हर क्रिया एक सीलबंद जर्नल में दर्ज होती है।

© 2026 Sallyport · Apache-2.0 के तहत ओपन सोर्स · Oleg Sotnikov