எனது MCP சர்வர் சும்மா வேலை செய்வதை நிறுத்திவிடும். எந்த கிராஷ் டம்பும் (crash dump) இல்லை. லாக்ஸில் (logs) எந்த ஸ்டேக் ட்ரேஸும் (stack trace) இல்லை. கிளையன்ட்கள் எந்தப் புகாரும் இன்றி இணைக்கப்பட்டனர், ஆனால் சில மணிநேரங்களுக்குப் பிறகு அனைத்தும் மௌனமாகிவிட்டன. கோரிக்கைகள் (Requests) மறைந்துவிட்டன, மறுமுனையில் இருந்த AI ஏஜென்ட் வெறும் வெற்றுத் தகவலைத் தவிர வேறொன்றையும் பெறவில்லை.
Model Context Protocol (MCP) சூழலில் இது மிகவும் எரிச்சலூட்டும் ஒரு பொதுவான கதையாகும். AI ஏஜென்ட்கள் எவ்வாறு வெளிப்புறக் கருவிகளைக் (external tools) கண்டறிந்து அழைக்கின்றன என்பதை இந்த புரோட்டோகால் வரையறுக்கிறது, ஆனால் பிழைகளை (errors) நீங்களே கையாளுவீர்கள் என்று அதன் விவரக்குறிப்பு (specification) கருதுகிறது. பெரும்பாலான பயிற்சிகளும் (tutorials) ஆரம்பக்கட்டச் செயல்பாடுகளும் அந்தப் பகுதியைத் தவிர்த்துவிடுகின்றன. அவை 'ஹேப்பி பாத்' (happy path) எனப்படும் வெற்றிகரமான பாதையில் மட்டுமே கவனம் செலுத்துகின்றன: ஒரு செயல்பாட்டை (function) குறிப்பீடு (annotate) செய்தல், அதை சர்வர் மூலம் வெளிப்படுத்துதல் மற்றும் ஒரு தெளிவான முடிவைத் திருப்புதல். உங்கள் வெளிப்புற API-இல் ஒரு நெட்வொர்க் கோளாறு ஏற்படும்போது அல்லது மாடல் ஒரு அளவுருப் பெயரைத் (parameter name) தவறாகக் கற்பனை செய்து குப்பை உள்ளீட்டை (garbage input) அனுப்பும்போது என்ன நடக்கும் என்பதை அவை அரிதாகவே காட்டுகின்றன. இதன் விளைவாக, பார்ப்பதற்கு ஆரோக்கியமாகத் தோன்றும் ஆனால் உண்மையில் பல மணிநேரமாகச் செயலிழந்திருக்கும் ஒரு பலவீனமான சர்வர் உருவாகிறது.
ஏன் வெற்றுப் பதில்கள் கிராஷ்களை விட மோசமானவை
ஒரு MCP டூல் ஹேண்ட்லரில் (tool handler) கையாளப்படாத ஒரு விதிவிலக்கு (unhandled exception) ஏற்படும்போது, டிரான்ஸ்போர்ட் லேயர் (transport layer) பெரும்பாலும் அதை விழுங்கிவிடுகிறது. சர்வர் செயல்முறை (process) உயிர்ப்புடன் இருக்கும், சாக்கெட் (socket) திறந்தே இருக்கும், ஆனால் கிளையன்ட் ஒரு வெற்றுப் பதிலைப் பெறும். இது ஒரு பெரிய கிராஷ் (crash) ஏற்படுவதை விட ஆபத்தானது, ஏனெனில் உங்கள் கண்காணிப்பு (monitoring) அதைத் கவனிக்காமல் போகலாம். செயல்முறை இன்னும் இயங்கிக் கொண்டிருக்கிறது. போர்ட் (port) இன்னும் இணைப்பைக் கேட்டுக்கொண்டிருக்கிறது. இருப்பினும் ஒவ்வொரு டூல் அழைப்பும் எதையும் திருப்பித் தரவில்லை.
AI மாடல் மௌனத்தை ஒரு தோல்வியாகக் கருதுவதில்லை. மாறாக, தரவுகளைத் தரவில்லை என்றாலும், அது ஒரு வெற்றிகரமான அழைப்பாகவே கருதுகிறது. அந்த வெற்றுப் பதில், மாடலைத் தானாகவே கற்பனை செய்து செயல்படத் தூண்டுகிறது. அந்த இடைவெளியை நிரப்ப அது உண்மைகளைக் கற்பனை செய்யத் தொடங்குகிறது அல்லது அதே தோல்வியடைந்த அழைப்பைத் திரும்பத் திரும்பச் செய்யும் சுழற்சிக்குள் (loop) நுழைகிறது. தற்காலிக நெட்வொர்க் டைம்அவுட் (network timeout) அல்லது தவறான டூல் ஆர்குமெண்ட் (tool argument) போன்ற சிறிய சிக்கல்கள் இத்தகைய நடத்தையைத் தூண்ட அனுமதிக்கக் கூடாது.
Wrapper Pattern: மூன்று பாதுகாப்பு அரண்கள்
ஒவ்வொரு டூல் ஹேண்ட்லரையும் ஒரு மெல்லிய பிழை-மீட்பு அடுக்கில் (error-recovery layer) போர்த்தியதன் மூலம் (wrapping) நான் இதைச் சரிசெய்தேன். இந்த Wrapper அனைத்து சாத்தியமான தோல்விகளையும் கணிக்க முயல்வதில்லை. மாறாக, அது அவற்றை வகைப்படுத்தி அதற்கேற்ப பதிலளிக்கிறது.
ConnectionError மற்றும் TimeoutError
உங்கள் சர்வர் ஒரு வெளிப்புற API-உடன் பேசும்போது நெட்வொர்க் தத்தளித்தால் இவை ஏற்படுகின்றன. முழு MCP சர்வர் செயல்முறையையும் மீண்டும் தொடங்குவதே (restart) இயல்பான தீர்வாகத் தோன்றும். அதைச் செய்யாதீர்கள். ரீபூட் (Reboot) செய்வது செயல்பாட்டில் உள்ள கிளையன்ட் இணைப்புகளைத் துண்டிக்கும், மெமரியில் உள்ள நிலையை (in-memory state) அழிக்கும் மற்றும் முழுமையான மறுதொடக்கத்திற்கு (re-initialization) நிர்ப்பந்திக்கவும் செய்யும். அதற்குப் பதிலாக, இணைப்புத் தோல்வியைக் கண்டறிந்து (catch), உங்கள் டூல் பயன்படுத்தும் டிரான்ஸ்போர்ட் லேயர் அல்லது HTTP கிளையன்ட்டை மட்டும் மீண்டும் இணைக்கவும். இதனால் சர்வர் அடுத்த கோரிக்கைக்கு உடனடியாகத் தயாராக இருக்கும்.
ValueError
AI கிளையன்ட் தவறான ஆர்குமென்ட்களை (malformed arguments) அனுப்பும்போது இதை நீங்கள் காண்பீர்கள். ஒருவேளை மாடல் ஒரு அளவுருவை (parameter) கற்பனை செய்திருக்கலாம், ஒரு முழு எண்ணுக்குப் (integer) பதிலாக ஒரு சரத்தை (string) அனுப்பியிருக்கலாம் அல்லது ஒரு தேவையான புலத்தை (field) மறந்துவிட்டிருக்கலாம். இதை நீங்கள் கையாளாமல் விட்டுவிட்டால், கிளையன்ட் ஒரு கிராஷ் அல்லது வெற்றுப் பதிலைப் பெறும். இதை Wrapper-க்குள் பிடித்து (catch), என்ன தவறு நடந்தது என்பதை மாடலுக்குத் துல்லியமாகத் தெரிவிக்கும் தெளிவான செய்தியை உருவாக்கவும். எந்த அளவுரு தோல்வியடைந்தது மற்றும் என்ன எதிர்பார்க்கப்பட்டது என்பதை விளக்கவும். பெரும்பாலான நவீன AI மாடல்கள் அந்தச் செய்தியைப் படித்து அடுத்த முறையிலேயே தானாகவே திருத்திக் கொள்ளும். தெளிவற்ற பிழை ஒரு சிந்தனைச் சுழற்சியைத் (reasoning cycle) வீணடிக்கும். துல்லியமான பிழை சிக்கலை உடனடியாகச் சரிசெய்யும்.
General Exceptions
ஒரு பாதுகாப்பு வலையை (safety net) வைத்திருங்கள். ஒரு பிழை மேலே உள்ள வகைகளுக்கு வெளியே இருந்தால், அதன் விவரங்களை உங்களுக்காக லாக் (log) செய்துவிட்டு, கிளையன்ட்டிற்கு ஒரு தெளிவான, பொதுவான தோல்விப் பதிலைத் திருப்பி அனுப்பவும். இது ஒரு விசித்திரமான விளிம்பு நிலைச் சிக்கல் (edge case) காரணமாக அனைவரின் செஷனும் (session) முறிவதைத் தடுக்கும். சர்வர் தொடர்ந்து இயங்கும், ஏதோ ஒன்று தோல்வியடைந்தது என்பதற்கான சமிக்ஞையை கிளையன்ட் பெறும், மேலும் நீங்கள் பிழைத்திருத்தம் (debug) செய்யத் தேவையான விவரங்களை உங்கள் லாக்ஸில் வைத்திருக்க முடியும்.
isError Flag என்பது தவிர்க்க முடியாதது
உங்கள் தீர்வு வேலை செய்கிறதா இல்லையா என்பதைத் தீர்மானிக்கும் முக்கிய விவரம் இதுதான். MCP பதில்களில் an isError boolean புலம் (field) இருக்கும். ஒரு விதிவிலக்கு ஏற்படும்போது, நீங்கள் isError-ஐ true என்று அமைக்காமல் ஒரு பிழைச் செய்தியைத் திருப்பி அனுப்பினால், கிளையன்ட் அந்தப் பிழை உரையை ஒரு வெற்றிகரமான டூல் முடிவாகவே கருதும்.
உங்கள் வெளிப்புற API ஒரு 'ரேட் லிமிட்' (rate limit) நிலையை எட்டுகிறது என்று கற்பனை செய்து கொள்ளுங்கள். நீங்கள் அந்த விதிவிலக்கைப் பிடித்து "API rate limit exceeded" என்ற சரத்தைத் (string) திருப்பி அனுப்புகிறீர்கள், ஆனால் isError-ஐ false என்று அப்படியே விட்டுவிடுகிறீர்கள். கிளையன்ட் அந்தச் சரத்தை ஒரு உண்மையான டூல் வெளியீடாகக் கருதி மாடலின் கான்டெக்ஸ்ட் விண்டோவிற்குள் (context window) அனுப்பும். மாடல் அந்த உரையைத் தரவாகக் கருதி அதன் அடிப்படையில் சிந்திக்கும். அது ஒரு சுருக்கத்தில் (summary) அந்தப் பிழையைக் குறிப்பிடலாம், அல்லது அதைவிட மோசமாக, அந்தப் பிழைத் text-க்கும் மற்ற உண்மைகளுக்கும் இடையே தொடர்புகளைக் கற்பனை செய்து கூறலாம். ஒரு தற்காலிக உள்கட்டமைப்புத் தடையை (infrastructure hiccup) நீங்கள் தவறான தகவல்களின் ஆதாரமாக மாற்றிவிட்டீர்கள்.
நீங்கள் ஒரு பிழைத் தரவை (error payload) திருப்பி அனுப்பும்போது, எப்போதும் isError-ஐ true என அமைக்கவும். இது கருவி அழைப்பு (tool call) தோல்வியடைந்துவிட்டது என்பதற்கான தெளிவான சமிக்ஞையை கிளையண்டிற்கு (client) வழங்குகிறது, இதன் மூலம் மாடல் மீண்டும் முயற்சிக்க வேண்டுமா, விளக்கத்தைக் கேட்க வேண்டுமா அல்லது முற்றிலும் வேறு ஒரு கருவியைப் பயன்படுத்த வேண்டுமா என்பதைத் தீர்மானிக்க முடியும்.
எதைக் கையாள வேண்டும் மற்றும் எதைக் கொல்ல வேண்டும் என்பதைத் தெரிந்து கொள்ளுங்கள்
அனைத்தையும் விழுங்கிவிடும் ஒரு குருட்டு try-catch அமைப்பால் உங்கள் முழு சர்வரையும் மூடிவிடாதீர்கள். சில பிழைகள் சர்வர் உடனடியாக நிறுத்தப்பட வேண்டும் என்பதைக் குறிக்கின்றன. தொடக்கத்தின் போது (startup) ஒரு தேவையான சூழல் மாறி (environment variable) விடுபட்டிருந்தாலோ அல்லது உங்கள் உள்ளமைவு கோப்பு (configuration file) சிதைந்திருந்தாலோ, கோரிக்கை மட்டத்தில் (request-level) செய்யப்படும் எந்த பிழைத் தடுத்தலும் உதவாது. இத்தகைய கடுமையான பிழைகளுக்காக (fatal errors) ஒரு குறிப்பிட்ட விதிவிலக்கு வகுப்பை (exception class) உருவாக்கி, அவற்றைச் செயல்முறையை (process) முறிக்க அனுமதிக்கவும்.
விதி எளிமையானது. பிழை தற்காலிகமானது அல்லது ஒரு தனிப்பட்ட கோரிக்கையுடன் மட்டும் தொடர்புடையது என்றால், அதைத் தடுத்து மீட்டெடுக்கவும். பிழை என்பது அடுத்தடுத்த அனைத்து கோரிக்கைகளும் தோல்வியடையும் என்று உறுதியாக இருந்தால், சர்வர் வெளிப்படையாக முறிந்துவிடட்டும். ஒரு சர்வர் பழுதடைந்த நிலையில் பல நாட்களாகத் தத்தளித்துக் கொண்டிருப்பதை விட, தொடக்கத்திலேயே விரைவாகத் தோல்வியடைவது பல மடங்கு சிறந்தது.
தேவைப்படுவதற்கு முன்பே கண்காணிப்புத் திறனை (Observability) சேர்க்கவும்
நீங்கள் wrapper-ஐ அமைத்தவுடன், அதை கட்டமைக்கப்பட்ட லாகிங்குடன் (structured logging) இணைக்கவும். ஒவ்வொரு கருவி அழைப்பையும் (tool call) அதன் முடிவையும் JSON வடிவத்தில் பதிவு செய்யவும். கருவியின் பெயர், மூல வாதங்கள் (raw arguments), தாமதம் (latency), மற்றும் அது வெற்றியடைந்ததா, தோல்வியடைந்ததா அல்லது மீண்டும் முயற்சிக்கப்பட்டதா என்பதையும் சேர்க்கவும்.
இந்த ஒழுக்கம் விரைவாகப் பலன் தரும். பிழைகள் அதிகரிப்பதைக் கவனிக்கும்போது, கருவியின் அடிப்படையில் வடிகட்டி (filter) சில நிமிடங்களில் முறைகளைக் கண்டறியலாம். ஒரு குறிப்பிட்ட வெளிப்புற API ஒவ்வொரு நாளும் ஒரே நேரத்தில் timeout-களைத் தரத் தொடங்கலாம், இது உங்களுக்குத் தெரியாத ஒரு திட்டமிடப்பட்ட பராமரிப்பு நேரத்தைக் (maintenance window) குறிக்கலாம். ஒரு கருவி தொடர்ந்து தவறான வாதங்களைப் (malformed arguments) பெறுவது இருக்கலாம், இது முந்தைய நிலையில் உள்ள ஒரு prompt engineering குறைபாட்டை வெளிப்படுத்தும். stack traces-க்குள் புதைந்துள்ள சாதாரண உரை லாக்கள் (plain text logs) இந்தத் துப்பறியும் வேலையைத் கடினமாக்கும். கட்டமைக்கப்பட்ட JSON இதை மிக எளிதாக்குகிறது.
உற்பத்தித் தளம் (Production) முடிவு
கடந்த மூன்று வாரங்களாக இரண்டு production MCP சர்வர்களில் இந்த wrapper முறையைப் பயன்படுத்தி வருகிறேன். அந்த காலத்தில், ஒரு கூட அமைதியான தோல்விகளை (silent failures) நான் பார்க்கவில்லை. இந்த wrapper-ஐச் சேர்ப்பதற்கு முன்பு, சராசரியாக ஒவ்வொரு நாளும் ஒரு விளக்க முடியாத தோல்வியைக் கண்டேன். இந்த முறை சிக்கலானது அல்ல, ஆனால் இது சமாளிக்கக்கூடிய இரைச்சலையும் (noise) உண்மையான சிக்கல்களையும் பிரித்து விடுவதால் இதன் தாக்கம் மிகப்பெரியது.
அமைதியான தோல்விகள் (Silent failures), சர்வர் முறிவதை விட அதிக இழப்பை ஏற்படுத்தும். ஒரு சர்வர் முறிவு (crash) உங்கள் எச்சரிக்கை அமைப்பை (alerting system) இயக்கும். ஆனால் அமைதி என்பது நம்பிக்கையைச் சிதைக்கும். ஒரு நாள் உங்கள் AI ஏஜென்ட் பயனுள்ள கருவித் தரவைத் தரும், ஆனால் அடுத்த நாள் சர்வர் பல மணிநேரங்களுக்கு முன்பே பதிலளிக்கத் தவறிவிட்டதால், அது கற்பனையான தகவல்களைத் தரத் தொடங்கும். இந்த wrapper முறை அந்த இடைவெளியை நிரப்புகிறது. இது சிறிய இடையூறுகளின் போதும் உங்கள் சர்வரை இயங்க வைக்கிறது, மாடல் தனது சொந்தத் தவறுகளைத் திருத்த போதுமான சூழலை (context) வழங்குகிறது, மேலும் உண்மையிலேயே ஒரு கடுமையான தவறு நடக்கும்போது, நீங்கள் அதை உடனடியாகத் தெரிந்துகொள்வதை உறுதி செய்கிறது.
நீங்கள் இன்று MCP கருவிகளை உருவாக்கிக் கொண்டிருந்தால், wrapper மற்றும் isError flag உடன் தொடங்குங்கள். மற்ற அனைத்தும் வெறும் சுத்திகரிப்பு மட்டுமே.
