This skill should be used when the user asks about "error messages", "did you mean", "similar tools", "parameter suggestions", "schema hints", "MCP error handling", "guide the client", "helpful errors", "fuzzy matching", or discusses how MCP servers should guide clients with progressive error enhancement and corrective feedback.
From mcp-architectnpx claudepluginhub standardbeagle/standardbeagle-tools --plugin mcp-architectThis skill uses the workspace's default tool permissions.
Design MCP error responses that guide clients toward success through progressive enhancement: suggesting similar tools, recommending correct parameters, providing schema subsets, and offering corrective feedback rather than just rejecting requests.
Traditional errors reject and stop. Progressive enhancement errors reject but guide:
Traditional:
→ "Unknown tool: serach"
→ Client is stuck
Progressive Enhancement:
→ "Unknown tool: serach"
→ "Did you mean: search, search_code, search_files?"
→ "Available tool categories: search (3), get (5), list (4)"
→ Client can self-correct
When a client calls an invalid tool, suggest similar ones:
// Pseudocode
function handleToolCall(toolName: string, params: any) {
const tool = tools.get(toolName)
if (!tool) {
const similar = findSimilarTools(toolName, tools.keys())
const categories = groupToolsByCategory(tools.keys())
return {
error: {
code: "UNKNOWN_TOOL",
message: `Tool '${toolName}' not found`,
suggestions: {
similar_tools: similar.slice(0, 5),
did_you_mean: similar[0],
available_categories: Object.keys(categories),
hint: similar.length > 0
? `Try: ${similar[0]}`
: "Use info() to list all available tools"
}
}
}
}
return tool.execute(params)
}
function findSimilarTools(input: string, available: string[]): string[] {
// Levenshtein distance + prefix matching + substring matching
return available
.map(name => ({
name,
score: calculateSimilarity(input, name)
}))
.filter(t => t.score > 0.3)
.sort((a, b) => b.score - a.score)
.map(t => t.name)
}
Request: serach(pattern: "User")
{
"error": {
"code": "UNKNOWN_TOOL",
"message": "Tool 'serach' not found",
"suggestions": {
"did_you_mean": "search",
"similar_tools": ["search", "search_code", "search_files"],
"available_categories": ["search", "get", "list", "info"],
"hint": "Try: search(pattern: \"User\")"
}
}
}
Combine multiple signals for best matches:
function calculateSimilarity(input: string, candidate: string): number {
const scores = [
levenshteinSimilarity(input, candidate) * 0.4, // Typo tolerance
prefixMatch(input, candidate) * 0.3, // Starts with
substringMatch(input, candidate) * 0.2, // Contains
wordOverlap(input, candidate) * 0.1 // Semantic similarity
]
return scores.reduce((a, b) => a + b, 0)
}
Priority order for suggestions:
sea → search)serach → search)auth → authenticate)user_search → search_users)When parameters are invalid, suggest corrections:
function validateParams(params: any, schema: Schema) {
const known = Object.keys(schema.properties)
const provided = Object.keys(params)
const unknown = provided.filter(p => !known.includes(p))
const warnings = []
const suggestions = {}
for (const param of unknown) {
const similar = findSimilarParams(param, known)
if (similar.length > 0) {
suggestions[param] = {
did_you_mean: similar[0],
alternatives: similar.slice(0, 3)
}
warnings.push(`Unknown param '${param}', did you mean '${similar[0]}'?`)
} else {
warnings.push(`Unknown param '${param}' ignored`)
}
}
return { warnings, suggestions, valid: true }
}
Request: search(patern: "User", filtr: "*.ts")
{
"results": [...],
"warnings": [
"Unknown param 'patern', did you mean 'pattern'?",
"Unknown param 'filtr', did you mean 'filter'?"
],
"suggestions": {
"patern": {
"did_you_mean": "pattern",
"alternatives": ["pattern"]
},
"filtr": {
"did_you_mean": "filter",
"alternatives": ["filter", "file_filter"]
}
},
"hint": "Corrected call: search(pattern: \"User\", filter: \"*.ts\")"
}
For high-confidence matches, optionally auto-correct:
function handleParams(params: any, schema: Schema) {
const corrected = {}
const corrections = []
for (const [key, value] of Object.entries(params)) {
if (schema.properties[key]) {
corrected[key] = value
} else {
const match = findBestMatch(key, Object.keys(schema.properties))
if (match && match.confidence > 0.9) {
// Auto-correct with notification
corrected[match.name] = value
corrections.push({
from: key,
to: match.name,
confidence: match.confidence,
auto_corrected: true
})
}
}
}
return { corrected, corrections }
}
Response with auto-correction:
{
"results": [...],
"corrections": [
{
"from": "patern",
"to": "pattern",
"confidence": 0.95,
"auto_corrected": true
}
],
"note": "Parameter 'patern' was auto-corrected to 'pattern'"
}
Include relevant schema information in error responses:
{
"error": {
"code": "MISSING_REQUIRED",
"message": "Required parameter 'pattern' is missing",
"schema_hint": {
"required": ["pattern"],
"optional": ["filter", "max", "offset"],
"example": {
"pattern": "authenticate",
"filter": "*.ts",
"max": 50
}
},
"documentation_url": "https://docs.example.com/tools/search"
}
}
{
"error": {
"code": "INVALID_TYPE",
"message": "Parameter 'max' must be integer, got string",
"details": {
"parameter": "max",
"expected_type": "integer",
"received_type": "string",
"received_value": "fifty"
},
"schema_hint": {
"max": {
"type": "integer",
"minimum": 1,
"maximum": 1000,
"default": 50,
"description": "Maximum number of results to return"
}
},
"hint": "Use a number: max: 50"
}
}
{
"error": {
"code": "OUT_OF_RANGE",
"message": "Parameter 'max' value 5000 exceeds maximum 1000",
"details": {
"parameter": "max",
"value": 5000,
"minimum": 1,
"maximum": 1000
},
"hint": "Use max: 1000 for maximum results, or paginate with offset"
}
}
Provide schema at different detail levels based on context:
{
"error": {
"code": "INVALID_INPUT",
"schema_hint": {
"required": ["pattern"],
"optional": ["filter", "max"]
}
}
}
{
"schema": {
"pattern": {"type": "string", "required": true},
"filter": {"type": "string", "required": false},
"max": {"type": "integer", "required": false, "default": 50}
}
}
{
"schema": {
"pattern": {
"type": "string",
"required": true,
"description": "Search pattern (regex supported)",
"examples": ["authenticate", "User.*", "^function"]
},
"filter": {
"type": "string",
"required": false,
"description": "File filter glob pattern",
"examples": ["*.ts", "src/**/*.js"]
},
"max": {
"type": "integer",
"required": false,
"default": 50,
"minimum": 1,
"maximum": 1000,
"description": "Maximum results to return"
}
}
}
function getSchemaHint(schema: Schema, level: 'minimal' | 'typed' | 'full') {
switch (level) {
case 'minimal':
return {
required: schema.required,
optional: Object.keys(schema.properties).filter(k => !schema.required.includes(k))
}
case 'typed':
return Object.fromEntries(
Object.entries(schema.properties).map(([k, v]) => [k, {
type: v.type,
required: schema.required.includes(k),
default: v.default
}])
)
case 'full':
return schema.properties
}
}
Always provide actionable next steps:
{
"results": [...],
"has_more": true,
"total": 127,
"next_steps": {
"get_more": "search(pattern: \"User\", offset: 10)",
"get_details": "get_definition(id: \"r1\")",
"refine_search": "search(pattern: \"User\", filter: \"*.ts\")"
}
}
{
"error": {
"code": "NOT_FOUND",
"message": "No results found for pattern 'xyzabc123'",
"next_steps": {
"broaden_search": "Try a simpler pattern or remove filters",
"check_scope": "Use info() to see indexed paths",
"alternatives": [
"search(pattern: \"xyz\")",
"search(pattern: \"abc\")",
"list_files()"
]
}
}
}
{
"results": [...],
"warnings": ["Some paths were not accessible"],
"partial": true,
"next_steps": {
"retry_failed": "search(pattern: \"User\", include_errors: true)",
"check_permissions": "info(detail: \"permissions\")",
"proceed_anyway": "Results shown are valid, continue with get_definition(id)"
}
}
Include helpful hints even in successful responses:
{
"results": [
{"id": "r1", "name": "User.authenticate", "confidence": 0.95},
{"id": "r2", "name": "Auth.validate", "confidence": 0.72}
],
"has_more": true,
"total": 47,
"tips": {
"high_results": "Use filter: \"*.ts\" to narrow to TypeScript files",
"get_details": "Use get_definition(id) for full code and documentation",
"pagination": "Use offset: 10 to see more results"
}
}
{
"results": [...],
"returned": 100,
"total": 100,
"limit_reached": true,
"guidance": {
"at_limit": "Showing maximum 100 results",
"recommendations": [
"Add filter to narrow results: filter: \"src/**\"",
"Use more specific pattern",
"Results are sorted by relevance, best matches shown first"
]
}
}
| Severity | Action | Include Schema | Suggest Similar |
|---|---|---|---|
| Critical | Reject | Full schema | Yes |
| High | Reject | Typed schema | Yes |
| Medium | Warn + Continue | Minimal | Yes |
| Low | Warn only | No | Optional |
function determineErrorSeverity(error: ValidationError): Severity {
// Critical: Security risks, data corruption potential
if (error.type === 'injection_attempt') return 'critical'
if (error.type === 'path_traversal') return 'critical'
// High: Required field missing, type mismatch
if (error.type === 'missing_required') return 'high'
if (error.type === 'type_mismatch') return 'high'
// Medium: Unknown params, out of range (correctable)
if (error.type === 'unknown_param') return 'medium'
if (error.type === 'out_of_range') return 'medium'
// Low: Deprecation warnings, style issues
if (error.type === 'deprecated_param') return 'low'
return 'medium'
}
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error message",
"severity": "high|medium|low",
"details": {
"field": "affected_field",
"value": "provided_value",
"expected": "what was expected"
},
"suggestions": {
"did_you_mean": "closest_match",
"alternatives": ["option1", "option2"],
"auto_correctable": true
},
"schema_hint": {
"required": ["field1"],
"optional": ["field2"],
"types": {"field1": "string", "field2": "integer"}
},
"next_steps": {
"fix": "Corrected call example",
"help": "info(tool: \"tool_name\")",
"docs": "https://docs.example.com/tool"
}
}
}
For every MCP tool:
Use the mcp-fuzzer agent to validate:
## Test: Unknown Tool Handling
**Input:** Call non-existent tool "serach"
**Expected:**
- Error code: UNKNOWN_TOOL
- did_you_mean present
- similar_tools array with "search"
- hint for correction
## Test: Unknown Parameter Handling
**Input:** search(patern: "User")
**Expected:**
- Warnings array present
- Suggestion for "pattern"
- Results still returned (graceful handling)
## Test: Schema Hints on Missing Required
**Input:** search() with no parameters
**Expected:**
- Error code: MISSING_REQUIRED
- schema_hint.required includes "pattern"
- Example usage provided
Client guidance principles:
Error response must include:
code - Machine-readable error codemessage - Human-readable explanationsuggestions - Did you mean / alternativesnext_steps - How to proceedSimilarity thresholds:
Guides agentic engineering workflows: eval-first loops, 15-min task decomposition, model routing (Haiku/Sonnet/Opus), AI code reviews, and cost tracking.