ನನ್ನ MCP ಸರ್ವರ್ ಸುಮ್ಮನೆ ಕೆಲಸ ಮಾಡುವುದನ್ನು ನಿಲ್ಲಿಸುತ್ತಿತ್ತು. ಯಾವುದೇ ಕ್ರ್ಯಾಶ್ ಡಂಪ್ (crash dump) ಇರುತ್ತಿರಲಿಲ್ಲ. ಲಾಗ್‌ಗಳಲ್ಲಿ ಯಾವುದೇ ಸ್ಟ್ಯಾಕ್ ಟ್ರೇಸ್ (stack trace) ಇರುತ್ತಿರಲಿಲ್ಲ. ಕ್ಲೈಂಟ್‌ಗಳು ಯಾವುದೇ ದೂರು ನೀಡದೆ ಸಂಪರ್ಕಿಸುತ್ತಿದ್ದರು, ಆದರೆ ಕೆಲವು ಗಂಟೆಗಳ ನಂತರ ಎಲ್ಲವೂ ಮೌನ trởಿಯುತ್ತಿತ್ತು. ವಿನಂತಿಗಳು (Requests) ಮಾಯವಾಗುತ್ತಿದ್ದವು ಮತ್ತು ಇನ್ನೊಂದು ಬದಿಯ AI ಏಜೆಂಟ್‌ಗೆ ಕೇವಲ ಶೂನ್ಯ ಸಂದೇಶಗಳು ಮಾತ್ರ ಸಿಗುತ್ತಿದ್ದವು.

ಇದು Model Context Protocol (MCP) ಪರಿಸರ ವ್ಯವಸ್ಥೆಯಲ್ಲಿ (ecosystem) ಕಂಡುಬರುವ ಅತ್ಯಂತ ಸಾಮಾನ್ಯ ಮತ್ತು ನಿರಾಶಾದಾಯಕ ಕಥೆ. AI ಏಜೆಂಟ್‌ಗಳು ಬಾಹ್ಯ ಪರಿಕರಗಳನ್ನು (external tools) ಹೇಗೆ ಪತ್ತೆಹಚ್ಚುತ್ತವೆ ಮತ್ತು ಅವುಗಳನ್ನು ಹೇಗೆ ಕರೆಯುತ್ತವೆ ಎಂಬುದನ್ನು ಈ ಪ್ರೊಟೊಕಾಲ್ ವ್ಯಾಖ್ಯಾನಿಸುತ್ತದೆ, ಆದರೆ ತಪ್ಪುಗಳನ್ನು (errors) ನೀವೇ ನಿರ್ವಹಿಸಬೇಕೆಂದು ಅದರ ಸ್ಪೆಸಿಫಿಕೇಶನ್ (specification) ಭಾವಿಸುತ್ತದೆ. ಹೆಚ್ಚಿನ ಟ್ಯುಟೋರಿಯಲ್‌ಗಳು ಮತ್ತು ಆರಂಭಿಕ ಅನುಷ್ಠಾನಗಳು (starter implementations) ಆ ಭಾಗವನ್ನು ಬಿಟ್ಟುಬಿಡುತ್ತವೆ. ಅವು ಕೇವಲ ಸುಗಮ ಹಾದಿಯ ಮೇಲೆ (happy path) ಗಮನ ಕೇಂದ್ರೀಕರಿಸುತ್ತವೆ: ಒಂದು ಫಂಕ್ಷನ್ ಅನ್ನು ಅ𝗻ೋಟೇಟ್ (annotate) ಮಾಡಿ, ಅದನ್ನು ಸರ್ವರ್ ಮೂಲಕ ಪ್ರದರ್ಶಿಸಿ ಮತ್ತು ಸ್ಪಷ್ಟವಾದ ಫಲಿತಾಂಶವನ್ನು ಹಿಂತಿರುಗಿಸಿ. ನಿಮ್ಮ ಬಾಹ್ಯ API ಗೆ ನೆಟ್‌ವರ್ಕ್ ಸಮಸ್ಯೆ ಎದುರಾದಾಗ ಅಥವಾ ಮಾಡೆಲ್ ಒಂದು ಪ್ಯಾರಾಮೀಟರ್ ಹೆಸರನ್ನು ತಪ್ಪಾಗಿ ಕಲ್ಪಿಸಿಕೊಂಡು (hallucinates) ಕಸದಂತಹ ಇನ್‌ಪುಟ್ ಅನ್ನು ಕಳುಹಿಸಿದಾಗ ಏನಾಗುತ್ತದೆ ಎಂಬುದನ್ನು ಅವು ಅಪರೂಪಕ್ಕೆ ತೋರಿಸುತ್ತವೆ. ಇದರ ಪರಿಣಾಮವಾಗಿ, ಸರ್ವರ್ ಆರೋಗ್ಯಕರವಾಗಿ ಕಾಣಿಸಿದರೂ, ವಾಸ್ತವವಾಗಿ ಗಂಟೆಗಟ್ಟಲೆ ಸ್ಥಗಿತಗೊಂಡಿರುವ ಅಸ್ಥಿರ ಸರ್ವರ್ ಸಿದ್ಧವಾಗುತ್ತದೆ.

ಶೂನ್ಯ ಪ್ರತಿಕ್ರಿಯೆಗಳು (Blank Responses) ಕ್ರ್ಯಾಶ್‌ಗಳಿಗಿಂತ ಏಕೆ ಹೆಚ್ಚು ಅಪಾಯಕಾರಿ

MCP ಟೂಲ್ ಹ್ಯಾಂಡ್ಲರ್‌ನಲ್ಲಿ ಅನ್‌ಹ್ಯಾಂಡಲ್ಡ್ ಎಕ್ಸೆಪ್ಶನ್ (unhandled exception) ಸಂಭವಿಸಿದಾಗ, ಟ್ರಾನ್ಸ್‌ಪೋರ್ಟ್ ಲೇಯರ್ (transport layer) ಅದನ್ನು ನುಂಗಿಬಿಡುತ್ತದೆ. ಸರ್ವರ್ ಪ್ರಕ್ರಿಯೆಯು ಜೀವಂತವಾಗಿರುತ್ತದೆ, ಸಾಕೆಟ್ (socket) ತೆರೆದೆಯೇ ಇರುತ್ತದೆ, ಆದರೆ ಕ್ಲೈಂಟ್‌ಗೆ ಕೇವಲ ಖಾಲಿ ಪ್ರತಿಕ್ರಿಯೆ ಸಿಗುತ್ತದೆ. ಇದು ದೊಡ್ಡ ಮಟ್ಟದ ಕ್ರ್ಯಾಶ್‌ಗಿಂತ ಹೆಚ್ಚು ಅಪಾಯಕಾರಿ, ಏಕೆಂದರೆ ನಿಮ್ಮ ಮಾನಿಟರಿಂಗ್ (monitoring) ಇದನ್ನು ಗಮನಿಸದಿರಬಹುದು. ಪ್ರಕ್ರಿಯೆಯು ಇನ್ನೂ ನಡೆಯುತ್ತಿರುತ್ತದೆ. ಪೋರ್ಟ್ ಇನ್ನೂ ಲಿಸ್ಲಿನ್ ಆಗಿರುತ್ತದೆ. ಆದರೂ ಪ್ರತಿ ಟೂಲ್ ಕಾಲ್ ಯಾವುದೇ ಫಲಿತಾಂಶವನ್ನು ನೀಡುವುದಿಲ್ಲ.

AI ಮಾಡೆಲ್ ಈ ಮೌನವನ್ನು ವೈಫಲ್ಯ ಎಂದು ಪರಿಗಣಿಸುವುದಿಲ್ಲ. ಬದಲಾಗಿ, ಯಾವುದೇ ಡೇಟಾವನ್ನು ಉತ್ಪಾದಿಸದ ಯಶಸ್ವಿ ಕಾಲ್ ಎಂದು ಅದು ಭಾವಿಸುತ್ತದೆ. ಆ ಶೂನ್ಯ ಪ್ರತಿಕ್ರಿಯೆಯು ಮಾಡೆಲ್ ಅನ್ನು ಅನಿರೀಕ್ಷಿತವಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸಲು (improvise) ತರಬೇತಿಗೊಳಿಸುತ್ತದೆ. ಅದು ಆ ಕೊರತೆಯನ್ನು ತುಂಬಲು ತಪ್ಪು ಮಾಹಿತಿಗಳನ್ನು ಕಲ್ಪಿಸಿಕೊಳ್ಳಲು (hallucinating facts) ಪ್ರಾರಂಭಿಸುತ್ತದೆ ಅಥವಾ ಅದೇ ದೋಷಪೂರಿತ ಕಾಲ್ ಅನ್ನು ಪದೇ ಪದೇ ಪ್ರಯತ್ನಿಸುವ ಲೂಪ್‌ಗೆ ಸಿಲುಕಿಕೊಳ್ಳುತ್ತದೆ. ತಾತ್ಕಾಲಿಕ ನೆಟ್‌ವರ್ಕ್ ಟೈಮೌಟ್ ಅಥವಾ ಅಮಾನ್ಯವಾದ ಟೂಲ್ ಆರ್ಗ್ಯುಮೆಂಟ್‌ನಂತಹ ಸಣ್ಣ ಸಮಸ್ಯೆಗಳು ಇಂತಹ ವರ್ತನೆಗೆ ಕಾರಣವಾಗಲು ಎಂದಿಗೂ ಬಿಡಬಾರದು.

ದ ವ್ರ್ಯಾಪ್ಪರ್ ಪ್ಯಾಟರ್ನ್ (The Wrapper Pattern): ರಕ್ಷಣೆಯ ಮೂರು ಹಂತಗಳು

ನಾನು ಪ್ರತಿಯೊಂದು ಟೂಲ್ ಹ್ಯಾಂಡ್ಲರ್ ಅನ್ನು ಒಂದು ತೆಳುವಾದ ಎರರ್-ರಿಕವರಿ ಲೇಯರ್ (error-recovery layer) ಮೂಲಕ ವ್ರ್ಯಾಪ್ (wrap) ಮಾಡುವ ಮೂಲಕ ಇದನ್ನು ಸರಿಪಡಿಸಿದೆ. ಈ ವ್ರ್ಯಾಪ್ಪರ್ ಪ್ರತಿಯೊಂದು ಸಂಭವನೀಯ ವೈಫಲ್ಯವನ್ನು ಊಹಿಸಲು ಪ್ರಯತ್ನಿಸುವುದಿಲ್ಲ. ಬದಲಾಗಿ, ಅದು ಅವುಗಳನ್ನು ವರ್ಗೀಕರಿಸುತ್ತದೆ ಮತ್ತು ಅದಕ್ಕೆ ಅನುಗುಣವಾಗಿ ಪ್ರತಿಕ್ರಿಯಿಸುತ್ತದೆ.

ConnectionError ಮತ್ತು TimeoutError
ನಿಮ್ಮ ಸರ್ವರ್ ಬಾಹ್ಯ API ಜೊತೆಗೆ ಸಂವಹನ ನಡೆಸುವಾಗ ನೆಟ್‌ವರ್ಕ್ ಏರುಪೇರಾದಾಗ ಇವು ಉಂಟಾಗುತ್ತವೆ. ಇಡೀ MCP ಸರ್ವರ್ ಪ್ರಕ್ರಿಯೆಯನ್ನು ಮರುಪ್ರಾರಂಭಿಸುವುದು ಸಹಜವಾದ ಪರಿಹಾರವಾಗಿ ಕಾಣಿಸಬಹುದು. ಆದರೆ ಹಾಗೆ ಮಾಡಬೇಡಿ. ರೀಬೂಟ್ ಮಾಡುವುದರಿಂದ ಸಕ್ರಿಯ ಕ್ಲೈಂಟ್ ಸಂಪರ್ಕಗಳು ಕಡಿತಗೊಳ್ಳುತ್ತವೆ, ಇನ್‌-ಮೆಮೊರಿ ಸ್ಟೇಟ್ (in-memory state) ಅಳಿಸಿಹೋಗುತ್ತದೆ ಮತ್ತು ಸಂಪೂರ್ಣ ಮರು-ಆರಂಭಕ್ಕೆ (re-initialization) ಒತ್ತಾಯಿಸುತ್ತದೆ. ಬದಲಾಗಿ, ಕನೆಕ್ಷನ್ ವೈಫಲ್ಯವನ್ನು ಪತ್ತೆಹಚ್ಚಿ ಮತ್ತು ನಿಮ್ಮ ಟೂಲ್ ಬಳಸುವ ಟ್ರಾನ್ಸ್‌ಪೋರ್ಟ್ ಲೇಯರ್ ಅಥವಾ HTTP ಕ್ಲೈಂಟ್ ಅನ್ನು ಮಾತ್ರ ಮರುಸಂಪರ್ಕಿಸಿ. ಇದರಿಂದ ಸರ್ವರ್ ತಕ್ಷಣವೇ ಮುಂದಿನ ವಿನಂತಿಗೆ ಸಿದ್ಧವಾಗಿರುತ್ತದೆ.

ValueError
AI ಕ್ಲೈಂಟ್ ತಪ್ಪಾದ ಆರ್ಗ್ಯುಮೆಂಟ್‌ಗಳನ್ನು (malformed arguments) ಕಳುಹಿಸಿದಾಗ ಇದು ಕಂಡುಬರುತ್ತದೆ. ಬಹುಶಃ ಮಾಡೆಲ್ ಒಂದು ಪ್ಯಾರಾಮೀಟರ್ ಅನ್ನು ತಾನೇ ಸೃಷ್ಟಿಸಿರಬಹುದು, ಇಂಟೆಜರ್ (integer) ಬೇಕಾದಲ್ಲಿ ಸ್ಟ್ರಿಂಗ್ (string) ಅನ್ನು ಕಳುಹಿಸಿರಬಹುದು ಅಥವಾ ಅಗತ್ಯವಿರುವ ಫೀಲ್ಡ್ ಅನ್ನು ಮರೆತಿರಬಹುದು. ನೀವು ಇದನ್ನು ಅನ್‌ಹ್ಯಾಂಡಲ್ಡ್ ಆಗಿ ಬಿಟ್ಟರೆ, ಕ್ಲೈಂಟ್‌ಗೆ ಕ್ರ್ಯಾಶ್ ಅಥವಾ ಶೂನ್ಯ ಪ್ರತಿಕ್ರಿಯೆ ಸಿಗುತ್ತದೆ. ಇದನ್ನು ವ್ರ್ಯಾಪ್ಪರ್ ಒಳಗಡೆಯೇ ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಿ (catch), ನಂತರ ಮಾಡೆಲ್‌ಗೆ ಏನು ತಪ್ಪಾಗಿದೆ ಎಂದು ನಿಖರವಾಗಿ ತಿಳಿಸುವ ಸ್ಪಷ್ಟವಾದ ಸಂದೇಶವನ್ನು ಸಿದ್ಧಪಡಿಸಿ. ಯಾವ ಪ್ಯಾರಾಮೀಟರ್ ವಿಫಲವಾಯಿತು ಮತ್ತು ಏನನ್ನು ನಿರೀಕ್ಷಿಸಲಾಗಿತ್ತು ಎಂಬುದನ್ನು ವಿವರಿಸಿ. ಹೆಚ್ಚಿನ ಆಧುನಿಕ AI ಮಾಡೆಲ್‌ಗಳು ಆ ಸಂದೇಶವನ್ನು ಓದಿ ಮುಂದಿನ ಹಂತದಲ್ಲೇ ತಾವಾಗಿಯೇ ಸರಿಪಡಿಸಿಕೊಳ್ಳುತ್ತವೆ. ಅಸ್ಪಷ್ಟವಾದ ದೋಷವು ರೀಸನಿಂಗ್ ಸೈಕಲ್ ಅನ್ನು ವ್ಯರ್ಥ ಮಾಡುತ್ತದೆ. ನಿಖರವಾದ ದೋಷವು ಸಮಸ್ಯೆಯನ್ನು ತಕ್ಷಣವೇ ಸರಿಪಡಿಸುತ್ತದೆ.

General Exceptions
ಒಂದು ಸೇಫ್ಟಿ ನೆಟ್ (safety net) ಇಟ್ಟುಕೊಳ್ಳಿ. ಒಂದು ವೇಳೆ ದೋಷವು ಮೇಲಿನ ವರ್ಗೀಕರಣಗಳ ಹೊರಗಿದ್ದರೆ, ವಿವರಗಳನ್ನು ಲಾಗ್ ಮಾಡಿ ಮತ್ತು ಕ್ಲೈಂಟ್‌ಗೆ ಒಂದು ಸಾಮಾನ್ಯ ವೈಫಲ್ಯದ ಪ್ರತಿಕ್ರಿಯೆಯನ್ನು ಹಿಂತಿರುಗಿಸಿ. ಇದು ಯಾವುದೋ ಒಂದು ವಿಚಿತ್ರ ಎಡ್ಜ್ ಕೇಸ್ (edge case) ಇಡೀ ಸೆಷನ್ ಅನ್ನು ಹಾಳು ಮಾಡದಂತೆ ತಡೆಯುತ್ತದೆ. ಸರ್ವರ್ ಉಳಿಯುತ್ತದೆ, ಏನೋ ವೈಫಲ್ಯವಾಗಿದೆ ಎಂಬ ಸಿಗ್ನಲ್ ಕ್ಲೈಂಟ್‌ಗೆ ಸಿಗುತ್ತದೆ ಮತ್ತು ನೀವು ನಂತರ ಡಿಬಗ್ (debug) ಮಾಡಲು ಅಗತ್ಯವಿರುವ ಮಾಹಿತಿಯನ್ನು ಲಾಗ್‌ಗಳಲ್ಲಿ ಇರಿಸಿಕೊಳ್ಳಬಹುದು.

isError ಫ್ಲಾಗ್ (Flag) ಅತ್ಯಗತ್ಯ

ನಿಮ್ಮ ಪರಿಹಾರವು ಕೆಲಸ ಮಾಡುತ್ತದೆಯೇ ಅಥವಾ ಇಲ್ಲವೇ ಎಂಬುದನ್ನು ನಿರ್ಧರಿಸುವ ಪ್ರಮುಖ ವಿವರ ಇಲ್ಲಿದೆ. MCP ಪ್ರತಿಕ್ರಿಯೆಗಳು isError ಎಂಬ ಬೂಲಿಯನ್ (boolean) ಫೀಲ್ಡ್ ಅನ್ನು ಒಳಗೊಂಡಿರುತ್ತವೆ. ಒಂದು ಎಕ್ಸೆಪ್ಶನ್ ಸಂಭವಿಸಿದಾಗ ನೀವು isError ಅನ್ನು true ಎಂದು ಸೆಟ್ ಮಾಡದೆ ಕೇವಲ ಎರರ್ ಮೆಸೇಜ್ ಅನ್ನು ಹಿಂತಿರುಗಿಸಿದರೆ, ಕ್ಲೈಂಟ್ ಆ ಎರರ್ ಪಠ್ಯವನ್ನು ಯಶಸ್ವಿ ಟೂಲ್ ಫಲಿತಾಂಶವೆಂದು ಪರಿಗಣಿಸುತ್ತದೆ.

ನಿಮ್ಮ ಬಾಹ್ಯ API ರೇಟ್ ಲಿಮಿಟ್ (rate limit) ತಲುಪಿದೆ ಎಂದು ಭಾವಿಸಿ. ನೀವು ಎಕ್ಸೆಪ್ಶನ್ ಅನ್ನು ಹಿಡಿದಿಟ್ಟುಕೊಂಡು "API rate limit exceeded" ಎಂಬ ಸ್ಟ್ರಿಂಗ್ ಅನ್ನು ಹಿಂತಿರುಗಿಸುತ್ತೀರಿ ಆದರೆ isError ಅನ್ನು false ಎಂದು ಇಡುತ್ತೀರಿ. ಕ್ಲೈಂಟ್ ಆ ಸ್ಟ್ರಿಂಗ್ ಅನ್ನು ನಿಜವಾದ ಟೂಲ್ ಔಟ್‌ಪುಟ್‌ನಂತೆ ಮಾಡೆಲ್‌ನ ಕಾಂಟೆಕ್ಸ್ಟ್ ವಿಂಡೋಗೆ (context window) ಕಳುಹಿಸುತ್ತದೆ. ಆಗ ಮಾಡೆಲ್ ಆ ಪಠ್ಯವನ್ನು ಡೇಟಾವಿನಂತೆ ಪರಿಗಣಿಸಿ ವಿಶ್ಲೇಷಿಸಲು ಪ್ರಯತ್ನಿಸುತ್ತದೆ. ಅದು ಸಾರಾಂಶದಲ್ಲಿ ಆ ದೋಷವನ್ನು ಉಲ್ಲೇಖಿಸಬಹುದು ಅಥವಾ ಅದಕ್ಕಿಂತ ಕೆಟ್ಟದಾಗಿ, ಆ ದೋಷದ ಪಠ್ಯ ಮತ್ತು ಇತರ ಸತ್ಯಗಳ ನಡುವೆ ತಪ್ಪು ಸಂಬಂಧಗಳನ್ನು ಕಲ್ಪಿಸಿಕೊಳ್ಳಬಹುದು (hallucinate). ನೀವು ಒಂದು ತಾತ್ಕಾಲಿಕ ಮೂಲಸೌಕರ್ಯದ ಸಮಸ್ಯೆಯನ್ನು ತಪ್ಪು ಮಾಹಿತಿಯ ಮೂಲವನ್ನಾಗಿ ಪರಿವರ್ತಿಸಿದ್ದೀರಿ ಎಂದರ್ಥ.

Always set isError to true when you are returning an error payload. This gives the client a clear signal that the tool call failed, which lets the model decide whether to retry, ask for clarification, or try a different tool entirely.

Know What to Catch and What to Kill

Do not wrap your entire server in a blind try-catch that swallows everything. Some errors mean the server should stop immediately. If a required environment variable is missing on startup, or your configuration file is corrupt, no amount of request-level catching will help. Create a specific exception class for fatal errors like these and let them crash the process.

The rule is simple. If the error is temporary or isolated to a single request, catch it and recover. If the error means every subsequent request is guaranteed to fail, let the server die loudly. A fast failure on startup is infinitely better than a server that limps along for days in a broken state.

Add Observability Before You Need It

Once you have the wrapper in place, pair it with structured logging. Log every tool call and its outcome in JSON format. Include the tool name, the raw arguments, the latency, and whether it succeeded, failed, or retried.

This discipline pays off quickly. When you notice a spike in errors, you can filter by tool and spot patterns in minutes. Maybe a specific external API starts throwing timeouts at the same time every day, pointing to a scheduled maintenance window you did not know about. Maybe one tool receives consistently malformed arguments, revealing a prompt engineering flaw upstream. Plain text logs buried in stack traces make this detective work painful. Structured JSON makes it trivial.

The Production Result

I have run this wrapper pattern on two production MCP servers for the past three weeks. In that window, I have seen zero silent failures. Before adding the wrapper, I averaged roughly one unexplained failure every day. The pattern is not complex, but its impact is outsized because it separates survivable noise from real problems.

Silent failures cost more than crashes. A crash triggers your alerting system. Silence just erodes trust. One day your AI agent returns useful tool data, and the next day it starts making things up because the server stopped answering hours ago. The wrapper pattern closes that gap. It keeps your server running through minor turbulence, gives the model enough context to fix its own mistakes, and ensures that when something truly fatal goes wrong, you hear about it immediately.

If you are building MCP tools today, start with the wrapper and the isError flag. Everything else is just cleanup.