Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Map application errors to MCP error codes with proper messages, error types, and recovery suggestions.
.claude/skills/a5c-ai-mcp-error-code-mapper/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 36% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 11% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 17% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 84% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 50% | 0% |
Map application errors to MCP error codes with proper handling.
Invoke this skill when you need to:
| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | language | string | Yes | Target language | | errors | array | Yes | Error definitions | | includeRecovery | boolean | No | Include recovery hints |
json{ "errors": [ { "name": "FileNotFound", "mcpCode": -32002, "message": "File not found: {path}", "recovery": "Check if the file exists and the path is correct" }, { "name": "InvalidInput", "mcpCode": -32602, "message": "Invalid input: {reason}", "recovery": "Review the input parameters and try again" } ] }
typescriptimport { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js'; // Standard MCP Error Codes export const MCP_ERROR_CODES = { PARSE_ERROR: -32700, INVALID_REQUEST: -32600, METHOD_NOT_FOUND: -32601, INVALID_PARAMS: -32602, INTERNAL_ERROR: -32603, // Custom codes (-32000 to -32099) FILE_NOT_FOUND: -32001, PERMISSION_DENIED: -32002, RESOURCE_NOT_FOUND: -32003, VALIDATION_ERROR: -32004, } as const; // Error with recovery hint interface McpErrorWithRecovery extends McpError { data?: { recovery?: string; details?: unknown; }; } // Error factory functions export function fileNotFoundError(path: string): McpErrorWithRecovery { return { code: MCP_ERROR_CODES.FILE_NOT_FOUND, message: `File not found: ${path}`, data: { recovery: 'Check if the file exists and the path is correct', details: { path }, }, }; } export function invalidParamsError(reason: string): McpErrorWithRecovery { return { code: MCP_ERROR_CODES.INVALID_PARAMS, message: `Invalid parameters: ${reason}`, data: { recovery: 'Review the input parameters and try again', }, }; } // Error handler wrapper export function handleToolError(error: unknown): McpErrorWithRecovery { if (error instanceof Error) { // Map known error types if (error.message.includes('ENOENT')) { return fileNotFoundError(error.message); } if (error.message.includes('EACCES')) { return { code: MCP_ERROR_CODES.PERMISSION_DENIED, message: `Permission denied: ${error.message}`, data: { recovery: 'Check file permissions' }, }; } // Fallback to internal error return { code: MCP_ERROR_CODES.INTERNAL_ERROR, message: error.message, }; } return { code: MCP_ERROR_CODES.INTERNAL_ERROR, message: 'An unexpected error occurred', }; }
pythonfrom enum import IntEnum from typing import Any, Optional from dataclasses import dataclass class McpErrorCode(IntEnum): PARSE_ERROR = -32700 INVALID_REQUEST = -32600 METHOD_NOT_FOUND = -32601 INVALID_PARAMS = -32602 INTERNAL_ERROR = -32603 # Custom codes FILE_NOT_FOUND = -32001 PERMISSION_DENIED = -32002 RESOURCE_NOT_FOUND = -32003 @dataclass class McpError(Exception): code: int message: str recovery: Optional[str] = None details: Optional[Any] = None def to_dict(self) -> dict: result = {'code': self.code, 'message': self.message} if self.recovery or self.details: result['data'] = {} if self.recovery: result['data']['recovery'] = self.recovery if self.details: result['data']['details'] = self.details return result def file_not_found_error(path: str) -> McpError: return McpError( code=McpErrorCode.FILE_NOT_FOUND, message=f'File not found: {path}', recovery='Check if the file exists and the path is correct', details={'path': path} ) def handle_tool_error(error: Exception) -> McpError: error_msg = str(error) if 'FileNotFoundError' in type(error).__name__: return file_not_found_error(error_msg) if 'PermissionError' in type(error).__name__: return McpError( code=McpErrorCode.PERMISSION_DENIED, message=f'Permission denied: {error_msg}', recovery='Check file permissions' ) return McpError( code=McpErrorCode.INTERNAL_ERROR, message=error_msg )
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 15,344 | 14,605 | -5% | 1 | 1 | 0% | 3,562 | 4,841 | +36% | 0 | 0 | — |
case-02 | fail→pass | 18,084 | 12,766 | -29% | 1 | 1 | 0% | 4,254 | 4,705 | +11% | 0 | 0 | — |
case-03 | fail→pass | 17,001 | 12,061 | -29% | 1 | 1 | 0% | 3,633 | 4,244 | +17% | 0 | 0 | — |
case-04 | fail→fail | 5,270 | 4,998 | -5% | 1 | 1 | 0% | 1,082 | 2,549 | +136% | 0 | 0 | — |
case-05 | fail→pass | 15,107 | 14,410 | -5% | 1 | 1 | 0% | 2,561 | 4,710 | +84% | 0 | 0 | — |
case-06 | fail→pass | 13,322 | 12,152 | -9% | 1 | 1 | 0% | 2,671 | 4,001 | +50% | 0 | 0 | — |
case-07 | fail→pass | 12,554 | 8,247 | -34% | 1 | 1 | 0% | 2,409 | 3,225 | +34% | 0 | 0 | — |
case-08 | fail→pass | 15,391 | 8,490 | -45% | 1 | 1 | 0% | 2,680 | 3,179 | +19% | 0 | 0 | — |
case-09 | fail→fail | 12,056 | 9,137 | -24% | 1 | 1 | 0% | 2,534 | 3,648 | +44% | 0 | 0 | — |
case-10 | fail→pass | 9,656 | 4,679 | -52% | 1 | 1 | 0% | 1,913 | 2,547 | +33% | 0 | 0 | — |
case-11 | fail→fail | 14,278 | 12,084 | -15% | 1 | 1 | 0% | 2,475 | 3,949 | +60% | 0 | 0 | — |
case-12 | fail→pass | 13,708 | 4,470 | -67% | 1 | 1 | 0% | 2,231 | 2,406 | +8% | 0 | 0 | — |
case-13 | fail→fail | 11,813 | 9,598 | -19% | 1 | 1 | 0% | 2,365 | 3,537 | +50% | 0 | 0 | — |
case-14 | fail→pass | 12,758 | 12,855 | +1% | 1 | 1 | 0% | 2,693 | 3,828 | +42% | 0 | 0 | — |
case-15 | fail→pass | 12,695 | 2,675 | -79% | 1 | 1 | 0% | 2,023 | 1,862 | -8% | 0 | 0 | — |
case-16 | fail→pass | 15,084 | 10,126 | -33% | 1 | 1 | 0% | 2,459 | 3,803 | +55% | 0 | 0 | — |
case-17 | fail→fail | 3,865 | 2,594 | -33% | 1 | 1 | 0% | 715 | 2,009 | +181% | 0 | 0 | — |
case-18 | fail→pass | 10,138 | 1,920 | -81% | 1 | 1 | 0% | 1,831 | 1,791 | -2% | 0 | 0 | — |
case-19 | fail→pass | 10,719 | 4,714 | -56% | 1 | 1 | 0% | 2,167 | 2,454 | +13% | 0 | 0 | — |
case-20 | fail→fail | 10,759 | 15,955 | +48% | 1 | 1 | 0% | 2,621 | 5,304 | +102% | 0 | 0 | — |
case-21 | fail→fail | 19,497 | 13,083 | -33% | 1 | 1 | 0% | 3,811 | 4,501 | +18% | 0 | 0 | — |
case-22 | fail→fail | 6,850 | 8,055 | +18% | 1 | 1 | 0% | 1,508 | 2,824 | +87% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +64 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.