મારો MCP સર્વર અચાનક કામ કરવાનું બંધ કરી દેતો હતો. કોઈ ક્રેશ ડમ્પ નહીં. લોગ્સમાં કોઈ સ્ટેક ટ્રેસ નહીં. ક્લાયન્ટ્સ કોઈ ફરિયાદ વગર જોડાયેલા રહેતા, અને પછી થોડા કલાકો પછી બધું જ શાંત થઈ જતું. વિનંતીઓ (Requests) ગાયબ થઈ જતી અને સામેના છેડે રહેલા AI એજન્ટને ખાલી શૂન્ય સિવાય કંઈ મળતું નહીં.
Model Context Protocol (MCP) ઇકોસિસ્ટમમાં આ એક અત્યંત નિરાશાજનક અને સામાન્ય વાત છે. આ પ્રોટોકોલ વ્યાખ્યાયિત કરે છે કે AI એજન્ટો કેવી રીતે બાહ્ય ટૂલ્સ શોધી શકે અને તેને કોલ કરી શકે, પરંતુ તેની સ્પષ્ટીકરણ (specification) એવું માની લે છે કે તમે ભૂલો (errors) જાતે સંભાળશો. મોટાભાગના ટ્યુટોરિયલ્સ અને સ્ટાર્ટર ઇમ્પ્લીમેન્ટેશન આ ભાગને છોડી દે છે. તેઓ માત્ર 'happy path' પર ધ્યાન કેન્દ્રિત કરે છે: એક ફંક્શનને એનોટેટ કરો, તેને સર્વર દ્વારા એક્સપોઝ કરો, અને ચોખ્ખું પરિણામ પરત કરો. જ્યારે તમારા એક્સટર્નલ API માં નેટવર્કની સમસ્યા આવે, અથવા જ્યારે મોડેલ પેરામીટરનું નામ ખોટું (hallucinate) બતાવે અને ગેરમાર્ગે દોરનારો ઇનપુટ મોકલે, ત્યારે શું થાય છે તે તેઓ ભાગ્યે જ બતાવે છે. પરિણામે એક નાજુક સર્વર બને છે જે દેખાવમાં તો હેલ્ધી લાગે છે પરંતુ વાસ્તવમાં કલાકોથી બંધ હોય છે.
ખાલી પ્રતિસાદ (Blank Responses) ક્રેશ કરતાં પણ વધુ ખરાબ કેમ છે
જ્યારે MCP ટૂલ હેન્ડલરમાં કોઈ અનહેન્ડલ્ડ એક્સેપ્શન (unhandled exception) આવે છે, ત્યારે ટ્રાન્સપોર્ટ લેયર ઘણીવાર તેને ગળી જાય છે. સર્વર પ્રોસેસ ચાલુ રહે છે, સોકેટ ખુલ્લું રહે છે, પરંતુ ક્લાયન્ટને ખાલી પ્રતિસાદ મળે છે. આ એક મોટા ક્રેશ કરતાં પણ વધુ જોખમી છે કારણ કે તમારું મોનિટરિંગ કદાચ તેને નોટિસ પણ નહીં કરે. પ્રોસેસ હજુ પણ ચાલી રહી છે. પોર્ટ હજુ પણ લિસનિંગ મોડમાં છે. છતાં દરેક ટૂલ કોલ કંઈ જ પરત કરતું નથી.
AI મોડેલ મૌનને નિષ્ફળતા તરીકે નથી જોતું. તે મૌનને એક સફળ કોલ તરીકે જુએ છે જેણે કોઈ ડેટા ઉત્પન્ન કર્યો નથી. તે ખાલી પ્રતિસાદ મોડેલને પોતાની રીતે અનુમાન લગાવવા (improvise) માટે તાલીમ આપે છે. તે ખાલી જગ્યા ભરવા માટે તથ્યોની ખોટી કલ્પના (hallucinate) કરવા લાગે છે, અથવા તે એ જ ખામીયુક્ત કોલને વારંવાર કરવાના લૂપમાં ફસાઈ જાય છે. ટ્રાન્ઝિએન્ટ નેટવર્ક ટાઈમઆઉટ અથવા અમાન્ય ટૂલ આર્ગ્યુમેન્ટ જેવી નાની સમસ્યાઓને આ પ્રકારનું વર્તન કરવા દેવી જોઈએ નહીં.
વ્રેપર પેટર્ન (The Wrapper Pattern): સુરક્ષાની ત્રણ લાઇન
મેં દરેક ટૂલ હેન્ડલરને એક પાતળા એરર-રિકવરી લેયર (error-recovery layer) માં વ્રેપ કરીને આ સમસ્યા સુધારી છે. વ્રેપર દરેક સંભવિત નિષ્ફળતાની આગાહી કરવાનો પ્રયાસ કરતું નથી. તે તેમને વર્ગીકૃત કરે છે અને તે મુજબ પ્રતિસાદ આપે છે.
ConnectionError અને TimeoutError
જ્યારે તમારું સર્વર એક્સટર્નલ API સાથે વાત કરે છે અને નેટવર્કમાં અસ્થિરતા આવે ત્યારે આ સમસ્યાઓ ઉભી થાય છે. આનો સહજ ઉપાય આખા MCP સર્વર પ્રોસેસને રિસ્ટાર્ટ કરવાનો છે. આવું કરશો નહીં. રીબૂટ કરવાથી સક્રિય ક્લાયન્ટ કનેક્શન કપાઈ જાય છે, ઇન-મેમરી સ્ટેટ ક્લિયર થઈ જાય છે અને સંપૂર્ણ રી-ઇનિશિયલાઇઝેશન કરવું પડે છે. તેના બદલે, કનેક્શન નિષ્ફળતાને કેચ (catch) કરો અને ફક્ત તમારા ટૂલ દ્વારા ઉપયોગમાં લેવાતા ટ્રાન્સપોર્ટ લેયર અથવા HTTP ક્લાયન્ટને જ ફરીથી કનેક્ટ કરો. સર્વર તરત જ આગલી વિનંતી માટે તૈયાર રહેશે.
ValueError
જ્યારે AI ક્લાયન્ટ ખોટા (malformed) આર્ગ્યુમેન્ટ્સ મોકલે છે ત્યારે તમને આ જોવા મળે છે. કદાચ મોડેલે કોઈ નવો પેરામીટર બનાવ્યો હોય, જ્યાં ઇન્ટિજર (integer) ની જરૂર હતી ત્યાં સ્ટ્રિંગ (string) મોકલી હોય, અથવા કોઈ જરૂરી ફિલ્ડ ભૂલી ગયું હોય. જો તમે આને અનહેન્ડલ્ડ રહેવા દેશો, તો ક્લાયન્ટને કાં તો ક્રેશ મળશે અથવા ખાલી જવાબ મળશે. તેને વ્રેપરની અંદર કેચ કરો, અને પછી એક સ્પષ્ટ, ચોક્કસ સંદેશ બનાવો જે મોડેલને બરાબર જણાવે કે શું ખોટું થયું છે. કયો પેરામીટર નિષ્ફળ ગયો અને શું અપેક્ષિત હતું તે સમજાવો. મોટાભાગના આધુનિક AI મોડેલ્સ તે સંદેશ વાંચશે અને તરત જ સુધારો કરી લેશે. અસ્પષ્ટ ભૂલ રિઝનિંગ સાયકલનો બગાડ કરે છે. ચોક્કસ ભૂલ સમસ્યાને તરત જ સુધારી દે છે.
General Exceptions
એક સેફ્ટી નેટ રાખો. જો ભૂલ ઉપરની શ્રેણીઓ બહારની હોય, તો તમારા માટે વિગતો લોગ કરો અને ક્લાયન્ટને એક ચોખ્ખો, સામાન્ય નિષ્ફળતાનો પ્રતિસાદ પરત કરો. આ એક વિચિત્ર એજ કેસ (edge case) ને કારણે બધા માટે સેશન બંધ થતું અટકાવે છે. સર્વર ટકી રહે છે, ક્લાયન્ટને સંકેત મળે છે કે કંઈક નિષ્ફળ ગયું છે, અને તમે પછીથી ડિબગ કરવા માટે તમારા લોગ્સમાં પૂરતો સંદર્ભ (context) રાખી શકો છો.
isError ફ્લેગ અનિવાર્ય છે
અહીં એ વિગત છે જે ખરેખર નક્કી કરે છે કે તમારો સુધારો કામ કરશે કે નહીં. MCP પ્રતિસાદોમાં isError બુલિયન (boolean) ફિલ્ડ હોય છે. જો કોઈ એક્સેપ્શન આવે અને તમે isError ને true સેટ કર્યા વિના ભૂલનો સંદેશ પરત કરો છો, તો ક્લાયન્ટ તે ભૂલના લખાણને સફળ ટૂલ પરિણામ તરીકે ગણે છે.
કલ્પના કરો કે તમારું એક્સટર્નલ API રેટ લિમિટ (rate limit) પર પહોંચી જાય છે. તમે એક્સેપ્શનને કેચ કરો છો અને "API rate limit exceeded" સ્ટ્રિંગ પરત કરો છો પરંતુ isError ને false રાખ છો. ક્લાયન્ટ તે સ્ટ્રિંગને મોડેલના કોન્ટેક્સ્ટ વિન્ડોમાં એવી રીતે પસાર કરે છે જાણે કે તે સાચું ટૂલ આઉટપુટ હોય. મોડેલ પછી તે લખાણ પર ડેટા તરીકે વિચારવાનો પ્રયાસ કરે છે. તે સારાંશમાં ભૂલનો ઉલ્લેખ કરી શકે છે, અથવા તેનાથી પણ ખરાબ, તે એ ભૂલના લખાણ અને અન્ય તથ્યો વચ્ચે ખોટા સંબંધોની કલ્પના કરી શકે છે. તમે ઇન્ફ્રાસ્ટ્રક્ચરની કામચલાઉ સમસ્યાને ખોટી માહિતીના સ્ત્રોતમાં ફેરવી દીધી છે.
જ્યારે તમે એરર પેલોડ (error payload) રિટર્ન કરી રહ્યા હોવ ત્યારે હંમેશા isError ને true પર સેટ કરો. આ ક્લાયન્ટને સ્પષ્ટ સંકેત આપે છે કે ટૂલ કોલ નિષ્ફળ ગયો છે, જે મોડેલને ફરીથી પ્રયાસ કરવો (retry), સ્પષ્ટતા માંગવી અથવા સંપૂર્ણપણે અલગ ટૂલ અજમાવવું તે નક્કી કરવા દે છે.
શું પકડવું (catch) અને શું બંધ કરવું (kill) તે જાણો
તમારા આખા સર્વરને એવા અંધ try-catch માં ન લપેટો જે બધું જ ગળી જાય. કેટલાક એરરનો અર્થ એ છે કે સર્વર તરત જ બંધ થઈ જવું જોઈએ. જો સ્ટાર્ટઅપ વખતે કોઈ જરૂરી એન્વાયરમેન્ટ વેરિએબલ (environment variable) ખૂટતું હોય, અથવા તમારી કોન્ફિગરેશન ફાઇલ કરપ્ટ હોય, તો રિક્વેસ્ટ-લેવલનું કેચિંગ (request-level catching) કોઈ કામ નહીં લાગે. આવા ગંભીર (fatal) એરર માટે એક ચોક્કસ એક્સેપ્શન ક્લાસ (exception class) બનાવો અને તેમને પ્રોસેસ ક્રેશ કરવા દો.
નિયમ સરળ છે. જો એરર કામચલાઉ હોય અથવા માત્ર એક જ રિક્વેસ્ટ પૂરતી મર્યાદિત હોય, તો તેને પકડો અને રિકવર કરો. જો એરરનો અર્થ એ હોય કે પછીની દરેક રિક્વેસ્ટ નિષ્ફળ જવાની ખાતરી છે, તો સર્વરને સ્પષ્ટ રીતે બંધ થવા દો. સ્ટાર્ટઅપ વખતે ઝડપી નિષ્ફળતા એ સર્વર કરતાં અનંતગણ્ય સારી છે જે દિવસો સુધી ખામીયુક્ત અવસ્થામાં લથડતું રહે.
જરૂર પડે તે પહેલાં Observability ઉમેરો
એકવાર તમે વ્રેપર (wrapper) સેટ કરી લો, પછી તેને સ્ટ્રક્ચર્ડ લોગિંગ (structured logging) સાથે જોડો. દરેક ટૂલ કોલ અને તેના પરિણામને JSON ફોર્મેટમાં લોગ કરો. તેમાં ટૂલનું નામ, રો (raw) આર્ગ્યુમેન્ટ્સ, લેટન્સી (latency), અને તે સફળ થયું, નિષ્ફળ ગયું કે ફરીથી પ્રયાસ (retry) કરવામાં આવ્યો તે શામેલ કરો.
આ શિસ્તનું પરિણામ ઝડપથી મળે છે. જ્યારે તમે એરરમાં વધારો જુઓ, ત્યારે તમે ટૂલ દ્વારા ફિલ્ટર કરી શકો છો અને મિનિટોમાં પેટર્ન શોધી શકો છો. કદાચ કોઈ ચોક્કસ એક્સટર્નલ API દરરોજ એક જ સમયે ટાઈમઆઉટ (timeout) આપવાનું શરૂ કરે છે, જે તમને ખબર ન હોય તેવા શેડ્યૂલ મેન્ટેનન્સ વિન્ડો તરફ નિર્દેશ કરે છે. કદાચ કોઈ એક ટૂલને સતત ખોટા (malformed) આર્ગ્યુમેન્ટ્સ મળે છે, જે અપસ્ટ્રીમમાં પ્રોમ્પ્ટ એન્જિનિયરિંગની ખામી દર્શાવે છે. સ્ટેક ટ્રેસમાં દબાયેલા પ્લેન ટેક્સ્ટ લોગ્સ આ ડિટેક્ટિવ કામને પીડાદાયક બનાવે છે. સ્ટ્રક્ચર્ડ JSON તેને અત્યંત સરળ બનાવે છે.
પ્રોડક્શનનું પરિણામ
મેં છેલ્લા ત્રણ અઠવાડિયાથી બે પ્રોડક્શન MCP સર્વર્સ પર આ વ્રેપર પેટર્ન ચલાવી છે. તે સમયગાળા દરમિયાન, મેં શૂન્ય સાયલન્ટ ફેઈલ્યોર (silent failures) જોયા છે. વ્રેપર ઉમેરતા પહેલા, દરરોજ સરેરાશ એક અસ્પષ્ટ નિષ્ફળતા જોવા મળતી હતી. આ પેટર્ન જટિલ નથી, પરંતુ તેની અસર ખૂબ મોટી છે કારણ કે તે ટકી શકાય તેવા ઘોંઘાટ (noise) ને વાસ્તવિક સમસ્યાઓથી અલગ કરે છે.
સાયલન્ટ ફેઈલ્યોર (Silent failures) ક્રેશ કરતાં વધુ મોંઘા પડે છે. ક્રેશ તમારી એલર્ટિંગ સિસ્ટમને સક્રિય કરે છે. મૌન માત્ર વિશ્વાસ ઘટાડે છે. એક દિવસ તમારો AI એજન્ટ ઉપયોગી ટૂલ ડેટા આપે છે, અને બીજા દિવસે તે વાતો બનાવવાનું શરૂ કરે છે કારણ કે સર્વર કલાકો પહેલા જવાબ આપવાનું બંધ કરી દીધું હતું. વ્રેપર પેટર્ન તે અંતરને પૂરેપૂરું કરે છે. તે તમારા સર્વરને નાની અસ્થિરતામાં પણ ચાલુ રાખે છે, મોડેલને તેની પોતાની ભૂલો સુધારવા માટે પૂરતો સંદર્ભ (context) આપે છે, અને એ સુનિશ્ચિત કરે છે કે જ્યારે ખરેખર કંઈક ગંભીર ખોટું થાય, ત્યારે તમને તરત જ ખબર પડે.
જો તમે આજે MCP ટૂલ્સ બનાવી રહ્યા હોવ, તો વ્રેપર અને isError ફ્લેગથી શરૂઆત કરો. બાકી બધું માત્ર સફાઈ (cleanup) છે.
